@markus-global/cli 0.9.7-rc.0 → 0.9.7-rc.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/markus.mjs +292 -17
- package/dist/web-ui/assets/{CommentInput-Dvlq2svZ.js → CommentInput-H50XI7sG.js} +1 -1
- package/dist/web-ui/assets/{ContentRenderer-BfnvpFM7.js → ContentRenderer-CbJWw6ni.js} +2 -2
- package/dist/web-ui/assets/{DeliverableShareModal-DkGpQmZ8.js → DeliverableShareModal-CHdOyC9c.js} +1 -1
- package/dist/web-ui/assets/{Deliverables-CtPvquKO.js → Deliverables-B48EGVOS.js} +1 -1
- package/dist/web-ui/assets/{Notifications-C_e9_V74.js → Notifications-Q29_jC_0.js} +1 -1
- package/dist/web-ui/assets/{Search-DZBGpN3c.js → Search-BYZ8QKgz.js} +1 -1
- package/dist/web-ui/assets/Settings-Kck8VNiS.js +8 -0
- package/dist/web-ui/assets/{Store-dbJSFCFw.js → Store-afxOnzIy.js} +1 -1
- package/dist/web-ui/assets/{Team-vmqHkmh8.js → Team-B7UAO190.js} +4 -4
- package/dist/web-ui/assets/{Work-Ds7q6pZg.js → Work-DhJSUJ8s.js} +1 -1
- package/dist/web-ui/assets/{arc-BLoofCdL.js → arc-oi2C2tM_.js} +1 -1
- package/dist/web-ui/assets/{architectureDiagram-3BPJPVTR-BGO4nFRN.js → architectureDiagram-3BPJPVTR-CK_H0la_.js} +1 -1
- package/dist/web-ui/assets/{blockDiagram-GPEHLZMM-Cn1E0037.js → blockDiagram-GPEHLZMM-B6SjWtm1.js} +1 -1
- package/dist/web-ui/assets/{c4Diagram-AAUBKEIU-DXFAnq3E.js → c4Diagram-AAUBKEIU-DVBOL2Mr.js} +1 -1
- package/dist/web-ui/assets/channel-B2Rur3o9.js +1 -0
- package/dist/web-ui/assets/{chunk-2J33WTMH-BXCSmrWD.js → chunk-2J33WTMH-p074NkEK.js} +1 -1
- package/dist/web-ui/assets/{chunk-4BX2VUAB-CIWJeena.js → chunk-4BX2VUAB-Dgt_oQ5Z.js} +1 -1
- package/dist/web-ui/assets/{chunk-55IACEB6-BuQ5-tdz.js → chunk-55IACEB6-Db-juaJ9.js} +1 -1
- package/dist/web-ui/assets/{chunk-727SXJPM-q9Yx_12l.js → chunk-727SXJPM-D8nAWxeV.js} +1 -1
- package/dist/web-ui/assets/{chunk-AQP2D5EJ-DqaehwKB.js → chunk-AQP2D5EJ-CxZV02WA.js} +1 -1
- package/dist/web-ui/assets/{chunk-FMBD7UC4-BFs2IYjK.js → chunk-FMBD7UC4-B5-ZRwUd.js} +1 -1
- package/dist/web-ui/assets/{chunk-ND2GUHAM-DyYGWpbj.js → chunk-ND2GUHAM-Dhk2IHCQ.js} +1 -1
- package/dist/web-ui/assets/{chunk-QZHKN3VN-DmbA4AU_.js → chunk-QZHKN3VN-EcAQZTUP.js} +1 -1
- package/dist/web-ui/assets/classDiagram-4FO5ZUOK-DxHkl_eV.js +1 -0
- package/dist/web-ui/assets/classDiagram-v2-Q7XG4LA2-DxHkl_eV.js +1 -0
- package/dist/web-ui/assets/{cose-bilkent-S5V4N54A-BLWm27gv.js → cose-bilkent-S5V4N54A-DLL4WcR1.js} +1 -1
- package/dist/web-ui/assets/{dagre-BM42HDAG-Cb2YgHjF.js → dagre-BM42HDAG-DrKXWZlt.js} +1 -1
- package/dist/web-ui/assets/{diagram-2AECGRRQ-hMyyF4SK.js → diagram-2AECGRRQ-DLOwNUpQ.js} +1 -1
- package/dist/web-ui/assets/{diagram-5GNKFQAL-DQvYRI_z.js → diagram-5GNKFQAL-BWcPBTuv.js} +1 -1
- package/dist/web-ui/assets/{diagram-KO2AKTUF-CPOv2Kga.js → diagram-KO2AKTUF-CdHvIQGV.js} +1 -1
- package/dist/web-ui/assets/{diagram-LMA3HP47-DvgOU39M.js → diagram-LMA3HP47-Dm80PSxk.js} +1 -1
- package/dist/web-ui/assets/{diagram-OG6HWLK6-DhLJ9Bog.js → diagram-OG6HWLK6-CV3Ynpw5.js} +1 -1
- package/dist/web-ui/assets/{erDiagram-TEJ5UH35-C4MKvJYc.js → erDiagram-TEJ5UH35-BiOoSELr.js} +1 -1
- package/dist/web-ui/assets/{flowDiagram-I6XJVG4X-C4KiUPBX.js → flowDiagram-I6XJVG4X-BuBzkN5x.js} +1 -1
- package/dist/web-ui/assets/{ganttDiagram-6RSMTGT7-CFiAe8nx.js → ganttDiagram-6RSMTGT7-CvPvDHVe.js} +1 -1
- package/dist/web-ui/assets/{gitGraphDiagram-PVQCEYII-y6rZo1sT.js → gitGraphDiagram-PVQCEYII-CmqSg9ZW.js} +1 -1
- package/dist/web-ui/assets/{index-CcppNtga.js → index-B-xjev59.js} +6 -6
- package/dist/web-ui/assets/{infoDiagram-5YYISTIA-LLlnmiVb.js → infoDiagram-5YYISTIA-C_griWOm.js} +1 -1
- package/dist/web-ui/assets/{ishikawaDiagram-YF4QCWOH-Brs-NT84.js → ishikawaDiagram-YF4QCWOH-wLNhIFRK.js} +1 -1
- package/dist/web-ui/assets/{journeyDiagram-JHISSGLW-um06-20P.js → journeyDiagram-JHISSGLW-BJUPzH74.js} +1 -1
- package/dist/web-ui/assets/{kanban-definition-UN3LZRKU-yws0Rgw8.js → kanban-definition-UN3LZRKU-C-exBcTE.js} +1 -1
- package/dist/web-ui/assets/{mermaid.core-C0Q8mcc_.js → mermaid.core-BcQakp0U.js} +5 -5
- package/dist/web-ui/assets/{mindmap-definition-RKZ34NQL-xCtHajk4.js → mindmap-definition-RKZ34NQL-B7jG8seW.js} +1 -1
- package/dist/web-ui/assets/{pieDiagram-4H26LBE5-BhKiwY7r.js → pieDiagram-4H26LBE5-CN4AAPgP.js} +1 -1
- package/dist/web-ui/assets/{quadrantDiagram-W4KKPZXB-CGmxw13s.js → quadrantDiagram-W4KKPZXB-rK-x9Rbd.js} +1 -1
- package/dist/web-ui/assets/{requirementDiagram-4Y6WPE33-CYJRHrZE.js → requirementDiagram-4Y6WPE33-XAjhwp64.js} +1 -1
- package/dist/web-ui/assets/{sankeyDiagram-5OEKKPKP-CgkdSCTc.js → sankeyDiagram-5OEKKPKP-jxToLEBs.js} +1 -1
- package/dist/web-ui/assets/{sequenceDiagram-3UESZ5HK-BD2dXCDe.js → sequenceDiagram-3UESZ5HK-BqiwRyol.js} +1 -1
- package/dist/web-ui/assets/{stateDiagram-AJRCARHV-DdEvCrm2.js → stateDiagram-AJRCARHV-CiFFWJwO.js} +1 -1
- package/dist/web-ui/assets/stateDiagram-v2-BHNVJYJU-C9aZNCon.js +1 -0
- package/dist/web-ui/assets/{timeline-definition-PNZ67QCA-CWfdKPN1.js → timeline-definition-PNZ67QCA-CWbiUHvH.js} +1 -1
- package/dist/web-ui/assets/{vennDiagram-CIIHVFJN-BTiDdRt6.js → vennDiagram-CIIHVFJN-CwOu2L0b.js} +1 -1
- package/dist/web-ui/assets/{wardley-L42UT6IY-eDkltTBC.js → wardley-L42UT6IY-EdI9vfy5.js} +1 -1
- package/dist/web-ui/assets/{wardleyDiagram-YWT4CUSO-DLOZOKTX.js → wardleyDiagram-YWT4CUSO-DZzukmtq.js} +1 -1
- package/dist/web-ui/assets/{xychartDiagram-2RQKCTM6-RU8GlPu6.js → xychartDiagram-2RQKCTM6-BN5doc0x.js} +1 -1
- package/dist/web-ui/index.html +1 -1
- package/package.json +8 -1
- package/dist/web-ui/assets/Settings-6xm2sHhm.js +0 -8
- package/dist/web-ui/assets/channel-Cw25sYRm.js +0 -1
- package/dist/web-ui/assets/classDiagram-4FO5ZUOK-CDWjvgnK.js +0 -1
- package/dist/web-ui/assets/classDiagram-v2-Q7XG4LA2-CDWjvgnK.js +0 -1
- package/dist/web-ui/assets/stateDiagram-v2-BHNVJYJU-DKPteYMC.js +0 -1
package/dist/markus.mjs
CHANGED
|
@@ -72159,7 +72159,7 @@ var init_ollama = __esm({
|
|
|
72159
72159
|
async chat(request) {
|
|
72160
72160
|
const messages2 = this.convertMessages(request.messages);
|
|
72161
72161
|
const body = {
|
|
72162
|
-
model: this.model,
|
|
72162
|
+
model: request.model ?? this.model,
|
|
72163
72163
|
messages: messages2,
|
|
72164
72164
|
stream: false,
|
|
72165
72165
|
options: {
|
|
@@ -72194,7 +72194,7 @@ var init_ollama = __esm({
|
|
|
72194
72194
|
async chatStream(request, onEvent, signal) {
|
|
72195
72195
|
const messages2 = this.convertMessages(request.messages);
|
|
72196
72196
|
const body = {
|
|
72197
|
-
model: this.model,
|
|
72197
|
+
model: request.model ?? this.model,
|
|
72198
72198
|
messages: messages2,
|
|
72199
72199
|
stream: true,
|
|
72200
72200
|
options: {
|
|
@@ -75095,12 +75095,13 @@ function costTierFromPrice(inputPer1M) {
|
|
|
75095
75095
|
return "$$$";
|
|
75096
75096
|
return "$$$$";
|
|
75097
75097
|
}
|
|
75098
|
-
var log57, CAPABILITY_KEY_MAP, MINIMAX_NAMES, DASHSCOPE_NAMES, FIREWORKS_NAMES, REGIONAL_PROVIDER_ALIASES, ALL_COMPLEXITY, LLMRouter, PROVIDER_DISPLAY_NAMES, BUILTIN_MODEL_CATALOG;
|
|
75098
|
+
var log57, OLLAMA_DEFAULT_CONTEXT_WINDOW, OLLAMA_DEFAULT_MAX_OUTPUT, DEFAULT_CONTEXT_WINDOW_FALLBACK, DEFAULT_MAX_OUTPUT_FALLBACK, CAPABILITY_KEY_MAP, MINIMAX_NAMES, DASHSCOPE_NAMES, FIREWORKS_NAMES, REGIONAL_PROVIDER_ALIASES, ALL_COMPLEXITY, LLMRouter, PROVIDER_DISPLAY_NAMES, BUILTIN_MODEL_CATALOG;
|
|
75099
75099
|
var init_router2 = __esm({
|
|
75100
75100
|
"../core/dist/llm/router.js"() {
|
|
75101
75101
|
"use strict";
|
|
75102
75102
|
init_dist();
|
|
75103
75103
|
init_tracing();
|
|
75104
|
+
init_provider();
|
|
75104
75105
|
init_anthropic();
|
|
75105
75106
|
init_openai();
|
|
75106
75107
|
init_minimax();
|
|
@@ -75115,6 +75116,10 @@ var init_router2 = __esm({
|
|
|
75115
75116
|
init_auth_profiles();
|
|
75116
75117
|
init_oauth_manager();
|
|
75117
75118
|
log57 = createLogger("llm-router");
|
|
75119
|
+
OLLAMA_DEFAULT_CONTEXT_WINDOW = 8192;
|
|
75120
|
+
OLLAMA_DEFAULT_MAX_OUTPUT = 4096;
|
|
75121
|
+
DEFAULT_CONTEXT_WINDOW_FALLBACK = 128e3;
|
|
75122
|
+
DEFAULT_MAX_OUTPUT_FALLBACK = DEFAULT_REQUEST_MAX_TOKENS;
|
|
75118
75123
|
CAPABILITY_KEY_MAP = {
|
|
75119
75124
|
image_generation: "imageGeneration",
|
|
75120
75125
|
image_recognition: "vision",
|
|
@@ -75419,6 +75424,12 @@ var init_router2 = __esm({
|
|
|
75419
75424
|
return hubModels.map((m) => this.enrichModelFromCatalog(m));
|
|
75420
75425
|
}
|
|
75421
75426
|
}
|
|
75427
|
+
if (providerName === "ollama") {
|
|
75428
|
+
const localModels = this.customModelCatalog.get("ollama");
|
|
75429
|
+
if (localModels && localModels.length > 0) {
|
|
75430
|
+
return localModels.map((m) => this.enrichModelFromCatalog(m));
|
|
75431
|
+
}
|
|
75432
|
+
}
|
|
75422
75433
|
let builtinModels = BUILTIN_MODEL_CATALOG.filter((m) => m.provider === providerName);
|
|
75423
75434
|
if (builtinModels.length === 0 && REGIONAL_PROVIDER_ALIASES[providerName]) {
|
|
75424
75435
|
const parent = REGIONAL_PROVIDER_ALIASES[providerName];
|
|
@@ -75477,6 +75488,154 @@ var init_router2 = __esm({
|
|
|
75477
75488
|
}
|
|
75478
75489
|
return defs.length;
|
|
75479
75490
|
}
|
|
75491
|
+
/**
|
|
75492
|
+
* Probe a local Ollama server (/api/tags) and record the actually-pulled
|
|
75493
|
+
* models into the provider's custom catalog. This makes local models appear
|
|
75494
|
+
* in both the Settings panel and the chat model picker (which both read
|
|
75495
|
+
* getEnhancedSettings / getProviderModels). On success the local list
|
|
75496
|
+
* REPLACES the static catalog for Ollama (only real models are usable).
|
|
75497
|
+
* On failure we keep any previously-cached local models (last-good), so a
|
|
75498
|
+
* transient Ollama stop does not wipe the picker.
|
|
75499
|
+
*/
|
|
75500
|
+
async refreshOllamaLocalModels(baseUrl) {
|
|
75501
|
+
const provider = this.providers.get("ollama");
|
|
75502
|
+
const effectiveBase = baseUrl ?? provider?.baseUrl ?? process.env["OLLAMA_BASE_URL"] ?? "http://localhost:11434";
|
|
75503
|
+
const base = String(effectiveBase).replace(/\/+$/, "");
|
|
75504
|
+
try {
|
|
75505
|
+
const ctrl = new AbortController();
|
|
75506
|
+
const tmr = setTimeout(() => ctrl.abort(), 5e3);
|
|
75507
|
+
const res = await fetch(`${base}/api/tags`, {
|
|
75508
|
+
signal: ctrl.signal
|
|
75509
|
+
});
|
|
75510
|
+
clearTimeout(tmr);
|
|
75511
|
+
if (!res.ok) {
|
|
75512
|
+
log57.warn("Ollama /api/tags HTTP error", { baseUrl: base, status: res.status });
|
|
75513
|
+
return this.customModelCatalog.get("ollama")?.length ?? 0;
|
|
75514
|
+
}
|
|
75515
|
+
const data = await res.json();
|
|
75516
|
+
const models = await Promise.all((data.models ?? []).map(async (m) => {
|
|
75517
|
+
const d = m.details;
|
|
75518
|
+
const tag = d?.parameter_size || d?.quantization_level;
|
|
75519
|
+
const info2 = await this.probeOllamaModel(base, m.name);
|
|
75520
|
+
const caps = info2.capabilities;
|
|
75521
|
+
const hasVision = caps.includes("vision");
|
|
75522
|
+
const hasReasoning = caps.includes("thinking");
|
|
75523
|
+
return {
|
|
75524
|
+
id: m.name,
|
|
75525
|
+
name: m.name,
|
|
75526
|
+
provider: "ollama",
|
|
75527
|
+
contextWindow: info2.contextWindow,
|
|
75528
|
+
maxOutputTokens: OLLAMA_DEFAULT_MAX_OUTPUT,
|
|
75529
|
+
cost: { input: 0, output: 0 },
|
|
75530
|
+
reasoning: hasReasoning || void 0,
|
|
75531
|
+
inputTypes: hasVision ? ["text", "image"] : ["text"],
|
|
75532
|
+
capabilities: caps.length > 0 ? caps : void 0,
|
|
75533
|
+
description: tag ? tag : void 0
|
|
75534
|
+
};
|
|
75535
|
+
}));
|
|
75536
|
+
this.customModelCatalog.set("ollama", models);
|
|
75537
|
+
log57.info(`Synced ${models.length} local Ollama models`, { baseUrl: base });
|
|
75538
|
+
return models.length;
|
|
75539
|
+
} catch (err) {
|
|
75540
|
+
log57.warn("Ollama local model sync failed", { error: String(err), baseUrl: base });
|
|
75541
|
+
return this.customModelCatalog.get("ollama")?.length ?? 0;
|
|
75542
|
+
}
|
|
75543
|
+
}
|
|
75544
|
+
/**
|
|
75545
|
+
* Probe a local Ollama model's real context length and capabilities via `/api/show`.
|
|
75546
|
+
* Reads `model_info["*.context_length"]` (key name varies by model family,
|
|
75547
|
+
* e.g. `llama.context_length`, `qwen3_5.context_length`) for the context window,
|
|
75548
|
+
* plus the top-level `capabilities` array (e.g. `['completion','vision','tools','thinking']`)
|
|
75549
|
+
* for multimodal / function-calling / reasoning support. Falls back to a sane
|
|
75550
|
+
* default so a probe failure never blocks agent budget planning.
|
|
75551
|
+
*/
|
|
75552
|
+
async probeOllamaModel(base, modelId) {
|
|
75553
|
+
try {
|
|
75554
|
+
const ctrl = new AbortController();
|
|
75555
|
+
const tmr = setTimeout(() => ctrl.abort(), 4e3);
|
|
75556
|
+
const res = await fetch(`${base}/api/show`, {
|
|
75557
|
+
method: "POST",
|
|
75558
|
+
headers: { "Content-Type": "application/json" },
|
|
75559
|
+
body: JSON.stringify({ model: modelId }),
|
|
75560
|
+
signal: ctrl.signal
|
|
75561
|
+
});
|
|
75562
|
+
clearTimeout(tmr);
|
|
75563
|
+
if (!res.ok)
|
|
75564
|
+
return { contextWindow: OLLAMA_DEFAULT_CONTEXT_WINDOW, capabilities: [] };
|
|
75565
|
+
const data = await res.json();
|
|
75566
|
+
const vals = Object.entries(data.model_info ?? {}).filter(([k]) => k.toLowerCase().includes("context_length")).map(([, v]) => Number(v)).filter((n2) => Number.isFinite(n2) && n2 > 0);
|
|
75567
|
+
const ctx = vals.length ? Math.max(...vals) : 0;
|
|
75568
|
+
const capabilities = Array.isArray(data.capabilities) ? data.capabilities : [];
|
|
75569
|
+
if (ctx > 0)
|
|
75570
|
+
log57.info(`Ollama local model ${modelId}: context_window=${ctx}, capabilities=${capabilities.join(",")}`);
|
|
75571
|
+
return {
|
|
75572
|
+
contextWindow: ctx > 0 ? ctx : OLLAMA_DEFAULT_CONTEXT_WINDOW,
|
|
75573
|
+
capabilities
|
|
75574
|
+
};
|
|
75575
|
+
} catch {
|
|
75576
|
+
return { contextWindow: OLLAMA_DEFAULT_CONTEXT_WINDOW, capabilities: [] };
|
|
75577
|
+
}
|
|
75578
|
+
}
|
|
75579
|
+
/**
|
|
75580
|
+
* Pull a live /v1/models list for an OpenAI-compatible provider into its
|
|
75581
|
+
* custom catalog. Used for newly-added providers that have no builtin entry
|
|
75582
|
+
* (and therefore would otherwise show zero models in pickers). If the
|
|
75583
|
+
* provider already has a usable catalog (builtin/custom) we skip the call.
|
|
75584
|
+
*/
|
|
75585
|
+
async refreshProviderLiveModels(providerName, baseUrl, apiKey) {
|
|
75586
|
+
if (this.getProviderModels(providerName).length > 0)
|
|
75587
|
+
return 0;
|
|
75588
|
+
const provider = this.providers.get(providerName);
|
|
75589
|
+
const effectiveBase = baseUrl ?? provider?.baseUrl;
|
|
75590
|
+
if (!effectiveBase)
|
|
75591
|
+
return 0;
|
|
75592
|
+
const effectiveKey = apiKey ?? provider?.apiKey;
|
|
75593
|
+
try {
|
|
75594
|
+
const headers = {};
|
|
75595
|
+
if (effectiveKey)
|
|
75596
|
+
headers["Authorization"] = `Bearer ${effectiveKey}`;
|
|
75597
|
+
const ctrl = new AbortController();
|
|
75598
|
+
const tmr = setTimeout(() => ctrl.abort(), 8e3);
|
|
75599
|
+
const res = await fetch(`${String(effectiveBase).replace(/\/+$/, "")}/v1/models`, {
|
|
75600
|
+
headers,
|
|
75601
|
+
signal: ctrl.signal
|
|
75602
|
+
});
|
|
75603
|
+
clearTimeout(tmr);
|
|
75604
|
+
if (!res.ok)
|
|
75605
|
+
return 0;
|
|
75606
|
+
const data = await res.json();
|
|
75607
|
+
const ids = (data.data ?? []).map((m) => m.id).filter((x) => !!x);
|
|
75608
|
+
if (ids.length === 0)
|
|
75609
|
+
return 0;
|
|
75610
|
+
const defs = (data.data ?? []).map((m) => {
|
|
75611
|
+
const id = m.id ?? "";
|
|
75612
|
+
const raw = m;
|
|
75613
|
+
const capsArr = Array.isArray(raw.capabilities) ? raw.capabilities : [];
|
|
75614
|
+
const capsObj = raw.capabilities ?? {};
|
|
75615
|
+
const arch4 = raw.architecture ?? {};
|
|
75616
|
+
const modalities = arch4.input_modalities ?? raw.input_modalities ?? [];
|
|
75617
|
+
const flagTrue = (key2) => capsObj[key2] === true || capsArr.includes(key2) || raw[key2] === true;
|
|
75618
|
+
const hasVision = modalities.includes("image") || flagTrue("vision");
|
|
75619
|
+
const hasReasoning = flagTrue("reasoning") || flagTrue("thinking");
|
|
75620
|
+
return {
|
|
75621
|
+
id,
|
|
75622
|
+
name: id,
|
|
75623
|
+
provider: providerName,
|
|
75624
|
+
contextWindow: 0,
|
|
75625
|
+
maxOutputTokens: 0,
|
|
75626
|
+
cost: { input: 0, output: 0 },
|
|
75627
|
+
reasoning: hasReasoning || void 0,
|
|
75628
|
+
inputTypes: hasVision ? ["text", "image"] : ["text"]
|
|
75629
|
+
};
|
|
75630
|
+
}).filter((m) => m.id.length > 0);
|
|
75631
|
+
this.customModelCatalog.set(providerName, defs);
|
|
75632
|
+
log57.info(`Synced ${defs.length} live models for provider ${providerName}`, { baseUrl: effectiveBase });
|
|
75633
|
+
return defs.length;
|
|
75634
|
+
} catch (err) {
|
|
75635
|
+
log57.warn(`Live model sync failed for provider ${providerName}`, { error: String(err), baseUrl: effectiveBase });
|
|
75636
|
+
return 0;
|
|
75637
|
+
}
|
|
75638
|
+
}
|
|
75480
75639
|
/**
|
|
75481
75640
|
* Drop sticky Markus defaults that are no longer in the Hub catalog
|
|
75482
75641
|
* (e.g. CN geo-filter removes anthropic/claude-opus-5 while chip still shows it).
|
|
@@ -76161,7 +76320,7 @@ var init_router2 = __esm({
|
|
|
76161
76320
|
* Used by the test endpoint to verify a single provider's connectivity.
|
|
76162
76321
|
* Also returns the baseUrl used for diagnostics.
|
|
76163
76322
|
*/
|
|
76164
|
-
async chatDirect(request, providerName) {
|
|
76323
|
+
async chatDirect(request, providerName, altModel) {
|
|
76165
76324
|
const provider = this.providers.get(providerName);
|
|
76166
76325
|
if (!provider) {
|
|
76167
76326
|
throw new Error(`Provider "${providerName}" not registered`);
|
|
@@ -76170,9 +76329,24 @@ var init_router2 = __esm({
|
|
|
76170
76329
|
throw new Error(`Provider "${providerName}" is disabled`);
|
|
76171
76330
|
}
|
|
76172
76331
|
request = this.resolveMaxTokens(request, providerName);
|
|
76173
|
-
const
|
|
76174
|
-
const
|
|
76175
|
-
|
|
76332
|
+
const originalModel = provider.model;
|
|
76333
|
+
const useRequestModelOnly = providerName === "markus" || provider instanceof MarkusProvider;
|
|
76334
|
+
const activeModel = altModel ?? originalModel;
|
|
76335
|
+
let switched = false;
|
|
76336
|
+
if (!useRequestModelOnly && altModel && altModel !== originalModel) {
|
|
76337
|
+
provider.configure({ provider: providerName, model: altModel });
|
|
76338
|
+
switched = true;
|
|
76339
|
+
}
|
|
76340
|
+
const directRequest = useRequestModelOnly && altModel ? { ...request, model: altModel } : request;
|
|
76341
|
+
try {
|
|
76342
|
+
const response = await provider.chat(directRequest);
|
|
76343
|
+
const baseUrl = provider.baseUrl ?? provider.config?.baseUrl;
|
|
76344
|
+
return Object.assign(response, { _providerBaseUrl: baseUrl, _model: activeModel });
|
|
76345
|
+
} finally {
|
|
76346
|
+
if (switched) {
|
|
76347
|
+
provider.configure({ provider: providerName, model: originalModel });
|
|
76348
|
+
}
|
|
76349
|
+
}
|
|
76176
76350
|
}
|
|
76177
76351
|
/**
|
|
76178
76352
|
* Try a streaming chat on a specific provider, optionally with an alternate model.
|
|
@@ -76522,7 +76696,8 @@ var init_router2 = __esm({
|
|
|
76522
76696
|
});
|
|
76523
76697
|
const ctx = catalogEntry?.contextWindow;
|
|
76524
76698
|
if (!ctx || ctx <= 0) {
|
|
76525
|
-
|
|
76699
|
+
log57.warn(`No context_window for provider "${name}" model "${provider.model || "(unset)"}" \u2014 using fallback ${DEFAULT_CONTEXT_WINDOW_FALLBACK}. Configure the model for accurate budgeting.`);
|
|
76700
|
+
return DEFAULT_CONTEXT_WINDOW_FALLBACK;
|
|
76526
76701
|
}
|
|
76527
76702
|
return ctx;
|
|
76528
76703
|
}
|
|
@@ -76544,7 +76719,8 @@ var init_router2 = __esm({
|
|
|
76544
76719
|
});
|
|
76545
76720
|
const out = catalogEntry?.maxOutputTokens;
|
|
76546
76721
|
if (!out || out <= 0) {
|
|
76547
|
-
|
|
76722
|
+
log57.warn(`No max_output_tokens for provider "${name}" model "${provider.model || "(unset)"}" \u2014 using fallback ${DEFAULT_MAX_OUTPUT_FALLBACK}.`);
|
|
76723
|
+
return DEFAULT_MAX_OUTPUT_FALLBACK;
|
|
76548
76724
|
}
|
|
76549
76725
|
return out;
|
|
76550
76726
|
}
|
|
@@ -215631,6 +215807,53 @@ EXPLANATION_END`;
|
|
|
215631
215807
|
}
|
|
215632
215808
|
return;
|
|
215633
215809
|
}
|
|
215810
|
+
if (providerName === "ollama") {
|
|
215811
|
+
const ollamaUrl = process.env["OLLAMA_BASE_URL"] || "http://localhost:11434";
|
|
215812
|
+
const providerInstance = this.llmRouter?.getProvider("ollama");
|
|
215813
|
+
const configuredBaseUrl = providerInstance?.baseUrl;
|
|
215814
|
+
const baseUrl = configuredBaseUrl ?? ollamaUrl;
|
|
215815
|
+
try {
|
|
215816
|
+
const ctrl = new AbortController();
|
|
215817
|
+
const tmr = setTimeout(() => ctrl.abort(), 5e3);
|
|
215818
|
+
const ollamaRes = await fetch(`${String(baseUrl).replace(/\/+$/, "")}/api/tags`, { signal: ctrl.signal });
|
|
215819
|
+
clearTimeout(tmr);
|
|
215820
|
+
if (!ollamaRes.ok) {
|
|
215821
|
+
this.json(res, 200, { provider: "ollama", models: [], source: "error", error: `Ollama returned HTTP ${ollamaRes.status}` });
|
|
215822
|
+
return;
|
|
215823
|
+
}
|
|
215824
|
+
const data = await ollamaRes.json();
|
|
215825
|
+
const models = await Promise.all((data.models ?? []).map(async (m) => {
|
|
215826
|
+
const caps = await this.probeOllamaCapabilities(String(baseUrl).replace(/\/+$/, ""), m.name);
|
|
215827
|
+
return {
|
|
215828
|
+
id: m.name,
|
|
215829
|
+
provider: "ollama",
|
|
215830
|
+
mode: "chat",
|
|
215831
|
+
maxInputTokens: 0,
|
|
215832
|
+
maxOutputTokens: 0,
|
|
215833
|
+
inputCostPer1MTokens: 0,
|
|
215834
|
+
outputCostPer1MTokens: 0,
|
|
215835
|
+
capabilities: {
|
|
215836
|
+
vision: caps.includes("vision"),
|
|
215837
|
+
functionCalling: caps.includes("tools"),
|
|
215838
|
+
reasoning: caps.includes("thinking"),
|
|
215839
|
+
promptCaching: false,
|
|
215840
|
+
webSearch: false,
|
|
215841
|
+
audioInput: false,
|
|
215842
|
+
audioOutput: false
|
|
215843
|
+
},
|
|
215844
|
+
size: m.size,
|
|
215845
|
+
modifiedAt: m.modified_at,
|
|
215846
|
+
parameterSize: m.details?.parameter_size,
|
|
215847
|
+
family: m.details?.family,
|
|
215848
|
+
quantization: m.details?.quantization_level
|
|
215849
|
+
};
|
|
215850
|
+
}));
|
|
215851
|
+
this.json(res, 200, { provider: "ollama", models, source: "live", count: models.length });
|
|
215852
|
+
} catch (err) {
|
|
215853
|
+
this.json(res, 200, { provider: "ollama", models: [], source: "error", error: err instanceof Error ? err.message : String(err) });
|
|
215854
|
+
}
|
|
215855
|
+
return;
|
|
215856
|
+
}
|
|
215634
215857
|
try {
|
|
215635
215858
|
const providerInstance = this.llmRouter?.getProvider(providerName);
|
|
215636
215859
|
const apiKey = providerInstance?.apiKey ?? "";
|
|
@@ -215677,6 +215900,10 @@ EXPLANATION_END`;
|
|
|
215677
215900
|
}
|
|
215678
215901
|
} catch {
|
|
215679
215902
|
}
|
|
215903
|
+
try {
|
|
215904
|
+
await this.llmRouter.refreshOllamaLocalModels?.();
|
|
215905
|
+
} catch {
|
|
215906
|
+
}
|
|
215680
215907
|
this.json(res, 200, this.llmRouter.getEnhancedSettings());
|
|
215681
215908
|
return;
|
|
215682
215909
|
}
|
|
@@ -216883,6 +217110,11 @@ data: ${JSON.stringify({ error: msg })}
|
|
|
216883
217110
|
apiKey,
|
|
216884
217111
|
baseUrl
|
|
216885
217112
|
});
|
|
217113
|
+
if (name === "ollama") {
|
|
217114
|
+
await this.llmRouter.refreshOllamaLocalModels?.(baseUrl);
|
|
217115
|
+
} else {
|
|
217116
|
+
await this.llmRouter.refreshProviderLiveModels?.(name, baseUrl, apiKey);
|
|
217117
|
+
}
|
|
216886
217118
|
if (enabled === false) {
|
|
216887
217119
|
this.llmRouter.setProviderEnabled(name, false);
|
|
216888
217120
|
}
|
|
@@ -216965,6 +217197,11 @@ data: ${JSON.stringify({ error: msg })}
|
|
|
216965
217197
|
if (typeof enabled === "boolean") {
|
|
216966
217198
|
this.llmRouter.setProviderEnabled(providerName, enabled);
|
|
216967
217199
|
}
|
|
217200
|
+
if (providerName === "ollama") {
|
|
217201
|
+
await this.llmRouter.refreshOllamaLocalModels?.(baseUrl ?? void 0);
|
|
217202
|
+
} else {
|
|
217203
|
+
await this.llmRouter.refreshProviderLiveModels?.(providerName, baseUrl ?? void 0, apiKey);
|
|
217204
|
+
}
|
|
216968
217205
|
if (contextWindow || maxOutputTokens || cost) {
|
|
216969
217206
|
this.llmRouter.updateProviderModelConfig(providerName, {
|
|
216970
217207
|
...contextWindow ? { contextWindow } : {},
|
|
@@ -217245,26 +217482,30 @@ data: ${JSON.stringify({ error: msg })}
|
|
|
217245
217482
|
this.json(res, 404, { ok: false, error: `Provider "${providerName}" not found or not configured` });
|
|
217246
217483
|
return;
|
|
217247
217484
|
}
|
|
217485
|
+
const body = await this.readBody(req);
|
|
217486
|
+
const requestedModel = typeof body?.model === "string" && body.model.trim() ? body.model.trim() : void 0;
|
|
217248
217487
|
const requestBody = {
|
|
217249
217488
|
messages: [{ role: "user", content: "Reply with exactly one word: hello" }],
|
|
217250
217489
|
// No maxTokens cap: a reasoning model spends the whole budget on hidden
|
|
217251
217490
|
// reasoning under a tight cap, returning empty content and producing a
|
|
217252
217491
|
// false "empty response / misconfigured" result. Let the router fill in
|
|
217253
217492
|
// the model's real limit; the model stops after the one-word reply.
|
|
217254
|
-
temperature: 0
|
|
217493
|
+
temperature: 0,
|
|
217494
|
+
...requestedModel ? { model: requestedModel } : {}
|
|
217255
217495
|
};
|
|
217256
217496
|
const baseUrl = provider.baseUrl ?? provider.config?.baseUrl ?? "";
|
|
217257
217497
|
try {
|
|
217258
217498
|
const startMs = Date.now();
|
|
217259
|
-
const response = await this.llmRouter.chatDirect(requestBody, providerName);
|
|
217499
|
+
const response = await this.llmRouter.chatDirect(requestBody, providerName, requestedModel);
|
|
217260
217500
|
const durationMs = Date.now() - startMs;
|
|
217261
217501
|
const reply = (response.content ?? "").trim();
|
|
217262
217502
|
const requestUrl = response._providerBaseUrl ?? baseUrl;
|
|
217503
|
+
const resultModel = response._model ?? requestedModel ?? provider.model;
|
|
217263
217504
|
if (!reply) {
|
|
217264
217505
|
this.json(res, 200, {
|
|
217265
217506
|
ok: false,
|
|
217266
217507
|
error: "Model returned empty response \u2014 API key or model may be misconfigured",
|
|
217267
|
-
model:
|
|
217508
|
+
model: resultModel,
|
|
217268
217509
|
durationMs,
|
|
217269
217510
|
requestUrl,
|
|
217270
217511
|
requestBody
|
|
@@ -217273,7 +217514,7 @@ data: ${JSON.stringify({ error: msg })}
|
|
|
217273
217514
|
this.json(res, 200, {
|
|
217274
217515
|
ok: true,
|
|
217275
217516
|
durationMs,
|
|
217276
|
-
model:
|
|
217517
|
+
model: resultModel,
|
|
217277
217518
|
reply: reply.slice(0, 100),
|
|
217278
217519
|
usage: response.usage,
|
|
217279
217520
|
requestUrl,
|
|
@@ -217300,7 +217541,7 @@ data: ${JSON.stringify({ error: msg })}
|
|
|
217300
217541
|
ok: false,
|
|
217301
217542
|
error: errorMsg.slice(0, 500),
|
|
217302
217543
|
errorCode,
|
|
217303
|
-
model: provider.model,
|
|
217544
|
+
model: requestedModel ?? provider.model,
|
|
217304
217545
|
requestUrl: baseUrl,
|
|
217305
217546
|
requestBody
|
|
217306
217547
|
});
|
|
@@ -220742,6 +220983,30 @@ You can now:
|
|
|
220742
220983
|
failures
|
|
220743
220984
|
};
|
|
220744
220985
|
}
|
|
220986
|
+
/**
|
|
220987
|
+
* Probe a local Ollama model's capabilities (`vision` / `tools` / `thinking`)
|
|
220988
|
+
* via `/api/show`. Returns an empty array on any failure so callers can keep
|
|
220989
|
+
* a conservative default without breaking model listing.
|
|
220990
|
+
*/
|
|
220991
|
+
async probeOllamaCapabilities(baseUrl, modelId) {
|
|
220992
|
+
try {
|
|
220993
|
+
const ctrl = new AbortController();
|
|
220994
|
+
const tmr = setTimeout(() => ctrl.abort(), 4e3);
|
|
220995
|
+
const res = await fetch(`${String(baseUrl).replace(/\/+$/, "")}/api/show`, {
|
|
220996
|
+
method: "POST",
|
|
220997
|
+
headers: { "Content-Type": "application/json" },
|
|
220998
|
+
body: JSON.stringify({ model: modelId }),
|
|
220999
|
+
signal: ctrl.signal
|
|
221000
|
+
});
|
|
221001
|
+
clearTimeout(tmr);
|
|
221002
|
+
if (!res.ok)
|
|
221003
|
+
return [];
|
|
221004
|
+
const data = await res.json();
|
|
221005
|
+
return Array.isArray(data.capabilities) ? data.capabilities : [];
|
|
221006
|
+
} catch {
|
|
221007
|
+
return [];
|
|
221008
|
+
}
|
|
221009
|
+
}
|
|
220745
221010
|
async validateProviderKey(provider, apiKey, baseUrl) {
|
|
220746
221011
|
const PROVIDER_BASE_URLS = {
|
|
220747
221012
|
anthropic: "https://api.anthropic.com",
|
|
@@ -220833,7 +221098,9 @@ You can now:
|
|
|
220833
221098
|
maxOutputTokens: gm.outputTokenLimit || 8192,
|
|
220834
221099
|
inputCostPer1MTokens: 0,
|
|
220835
221100
|
outputCostPer1MTokens: 0,
|
|
220836
|
-
|
|
221101
|
+
// Gemini `generateContent` models are multimodal (image-in capable)
|
|
221102
|
+
// unless they are embedding-only, which are filtered out above.
|
|
221103
|
+
capabilities: { vision: true, functionCalling: true, reasoning: false, promptCaching: false, webSearch: false, audioInput: false, audioOutput: false }
|
|
220837
221104
|
});
|
|
220838
221105
|
}
|
|
220839
221106
|
}
|
|
@@ -220972,7 +221239,15 @@ You can now:
|
|
|
220972
221239
|
inputCostPer1M = parseFloat(pricing.prompt || "0") * 1e6;
|
|
220973
221240
|
outputCostPer1M = parseFloat(pricing.completion || "0") * 1e6;
|
|
220974
221241
|
}
|
|
220975
|
-
|
|
221242
|
+
const arch4 = remoteModel.architecture ?? {};
|
|
221243
|
+
const capsArr = Array.isArray(remoteModel.capabilities) ? remoteModel.capabilities : [];
|
|
221244
|
+
const capsObj = remoteModel.capabilities ?? {};
|
|
221245
|
+
const modalities = arch4.input_modalities ?? remoteModel.input_modalities ?? [];
|
|
221246
|
+
const flagTrue = (key2) => capsObj[key2] === true || capsArr.includes(key2) || remoteModel[key2] === true;
|
|
221247
|
+
const vision = modalities.includes("image") || flagTrue("vision");
|
|
221248
|
+
const reasoning = flagTrue("reasoning") || flagTrue("thinking");
|
|
221249
|
+
const functionCalling = flagTrue("function_calling") || flagTrue("functionCalling") || flagTrue("tools");
|
|
221250
|
+
return { contextLength, maxOutput, inputCostPer1M, outputCostPer1M, vision, reasoning, functionCalling };
|
|
220976
221251
|
};
|
|
220977
221252
|
let providerFallbackContext = 128e3;
|
|
220978
221253
|
if (catalogModels.length > 0) {
|
|
@@ -221010,7 +221285,7 @@ You can now:
|
|
|
221010
221285
|
maxOutputTokens: apiMeta.maxOutput || 8192,
|
|
221011
221286
|
inputCostPer1MTokens: apiMeta.inputCostPer1M,
|
|
221012
221287
|
outputCostPer1MTokens: apiMeta.outputCostPer1M,
|
|
221013
|
-
capabilities: { vision:
|
|
221288
|
+
capabilities: { vision: apiMeta.vision, functionCalling: apiMeta.functionCalling, reasoning: apiMeta.reasoning, promptCaching: false, webSearch: false, audioInput: false, audioOutput: false }
|
|
221014
221289
|
});
|
|
221015
221290
|
}
|
|
221016
221291
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as t,u as T,r as a,k as ee}from"./index-CcppNtga.js";const te=1920,ne=10*1024*1024,W=5,re=.8;function se(l,u,i){return new Promise((g,f)=>{const y=new Image;y.onload=()=>{let{width:s,height:r}=y;if(s<=u&&r<=u){g(l);return}s>r?(r=Math.round(r*(u/s)),s=u):(s=Math.round(s*(u/r)),r=u);const x=document.createElement("canvas");x.width=s,x.height=r;const b=x.getContext("2d");if(!b){f(new Error("Failed to get canvas context"));return}b.drawImage(y,0,0,s,r),g(x.toDataURL("image/jpeg",i))},y.onerror=()=>f(new Error("Failed to load image")),y.src=l})}function ae({candidates:l,filter:u,anchorRef:i,onSelect:g,selectedIndex:f,onIndexChange:y}){const{t:s}=T("common"),[r,x]=a.useState(null),b=a.useRef(null),w=l.filter(d=>d.name.toLowerCase().includes(u));return a.useEffect(()=>{const d=i.current;if(!d)return;const h=d.getBoundingClientRect();x({top:h.top+window.scrollY-4,left:h.left+window.scrollX+8})},[i,u]),a.useEffect(()=>{if(!b.current||!r)return;if(b.current.getBoundingClientRect().top<8){const h=i.current;if(!h)return;const c=h.getBoundingClientRect();x({top:c.bottom+window.scrollY+4,left:r.left})}},[r,i]),a.useEffect(()=>{f>=w.length&&y(Math.max(0,w.length-1))},[w.length,f,y]),a.useEffect(()=>{if(!b.current)return;b.current.querySelector('[data-selected="true"]')?.scrollIntoView({block:"nearest"})},[f]),!r||w.length===0?null:ee.createPortal(t.jsxs("div",{ref:b,style:{position:"absolute",top:r.top,left:r.left,transform:"translateY(-100%)"},className:"w-60 bg-surface-overlay border border-border-default rounded-lg shadow-xl z-[9999] max-h-48 overflow-y-auto",children:[t.jsx("div",{className:"px-2.5 py-1.5 text-[10px] text-fg-tertiary font-medium uppercase tracking-wider border-b border-border-default",children:s("commentInput.mentionHeading")}),w.map((d,h)=>t.jsxs("button",{"data-selected":h===f,onMouseDown:c=>{c.preventDefault(),g(d)},onMouseEnter:()=>y(h),className:`w-full text-left px-3 py-2 text-xs flex items-center gap-2 transition-colors ${h===f?"bg-brand-500/15 text-brand-500":"hover:bg-surface-elevated"}`,children:[t.jsx("span",{className:`w-6 h-6 rounded-full flex items-center justify-center text-[10px] font-bold shrink-0 ${d.type==="human"?"bg-green-500/20 text-green-500":"bg-brand-500/20 text-brand-500"}`,children:d.name.slice(0,2).toUpperCase()}),t.jsxs("div",{className:"flex-1 min-w-0",children:[t.jsx("span",{className:"text-fg-primary font-medium",children:d.name}),t.jsx("span",{className:"text-fg-tertiary text-[10px] ml-1.5",children:d.subtitle??d.type})]}),d.type==="agent"&&t.jsx("span",{className:`w-1.5 h-1.5 rounded-full shrink-0 ${d.online?"bg-green-400":"bg-gray-500"}`})]},d.id))]}),document.body)}function oe(l){return/^\w+$/.test(l)?`@${l}`:`@[${l}]`}const K=/@\[([^\]]+)\]|@([\w\p{L}\p{N}]+)/gu;function ie(l){const u=[];let i;for(K.lastIndex=0;(i=K.exec(l))!==null;)u.push(i[1]??i[2]);return u}function ce(l,u,i){const g=[];let f=0;const y=u.map(r=>r.name).sort((r,x)=>x.length-r.length);let s=0;for(;s<l.length;){const r=l.indexOf("@",s);if(r<0){g.push(t.jsx("span",{children:l.slice(s)},f++));break}if(r>s&&g.push(t.jsx("span",{children:l.slice(s,r)},f++)),l[r+1]==="["){const c=l.indexOf("]",r+2);if(c>r+2){const m=l.slice(r+2,c),j=u.find(k=>k.name.toLowerCase()===m.toLowerCase());g.push(t.jsxs("span",{className:`text-brand-500 font-medium ${i&&j?"cursor-pointer hover:underline":""}`,onClick:i&&j?k=>i(j,k):void 0,title:j?`${j.name} (${j.role})`:void 0,children:["@",m]},f++)),s=c+1;continue}}const x=l.slice(r+1),b=x.toLowerCase(),w=y.find(c=>b.startsWith(c.toLowerCase()));if(w){const c=u.find(m=>m.name.toLowerCase()===w.toLowerCase());g.push(t.jsxs("span",{className:`text-brand-500 font-medium ${i&&c?"cursor-pointer hover:underline":""}`,onClick:i&&c?m=>i(c,m):void 0,title:c?`${c.name} (${c.role})`:void 0,children:["@",w]},f++)),s=r+1+w.length;continue}const d=/^([\w\p{L}\p{N}]+)/u,h=x.match(d);if(h){const c=h[1],m=u.find(j=>j.name.toLowerCase()===c.toLowerCase());g.push(t.jsxs("span",{className:`text-brand-500 font-medium ${i&&m?"cursor-pointer hover:underline":""}`,onClick:i&&m?j=>i(m,j):void 0,title:m?`${m.name} (${m.role})`:void 0,children:["@",c]},f++)),s=r+1+c.length;continue}g.push(t.jsx("span",{children:"@"},f++)),s=r+1}return g.length>0?g:[t.jsx("span",{children:l},0)]}function de({agents:l,humans:u,onSubmit:i,placeholder:g,replyTo:f,onCancelReply:y}){const{t:s}=T("common"),[r,x]=a.useState(""),[b,w]=a.useState(!1),[d,h]=a.useState(null),[c,m]=a.useState(!1),[j,k]=a.useState(""),[C,S]=a.useState([]),[B,I]=a.useState(0),[N,M]=a.useState([]),[z,A]=a.useState(!1),F=a.useRef(null),U=a.useRef(null),L=a.useRef(null),$=a.useMemo(()=>{const e=(u??[]).map(n=>({id:n.id,name:n.name,type:"human",subtitle:n.role}));for(const n of l)e.push({id:n.id,name:n.name,type:"agent",subtitle:n.role,online:n.status==="idle"||n.status==="working"});return e},[l,u]),D=$.filter(e=>e.name.toLowerCase().includes(j)),E=a.useCallback(e=>{const n=Array.from(e).filter(o=>o.type.startsWith("image/"));if(n.length!==0)for(const o of n){if(o.size>ne)continue;const p=new FileReader;p.onload=()=>{const R=p.result;se(R,te,re).then(v=>{M(_=>_.length>=W?_:[..._,{id:`img_${Date.now()}_${Math.random().toString(36).slice(2,6)}`,dataUrl:v,name:o.name}])})},p.readAsDataURL(o)}},[]),X=a.useCallback(e=>{M(n=>n.filter(o=>o.id!==e))},[]),Y=a.useCallback(e=>{const n=e.clipboardData?.files;if(n&&n.length>0){const o=Array.from(n).filter(p=>p.type.startsWith("image/"));o.length>0&&(e.preventDefault(),E(o))}},[E]),q=a.useCallback(e=>{e.preventDefault(),A(!1);const n=e.dataTransfer?.files;n&&n.length>0&&E(Array.from(n).filter(o=>o.type.startsWith("image/")))},[E]),G=a.useCallback(e=>{e.preventDefault(),A(!0)},[]),H=a.useCallback(()=>{A(!1)},[]),O=async()=>{if(!(!r.trim()&&N.length===0)){w(!0),h(null),L.current={content:r,mentions:[...C],images:[...N]};try{await i(r,C,[...N],f?.id),x(""),S([]),M([]),L.current=null,y?.()}catch(e){h(String(e instanceof Error?e.message:e)||s("commentInput.sendFailed"))}w(!1)}},Q=async()=>{if(!L.current)return;const{content:e,mentions:n,images:o}=L.current;w(!0),h(null);try{await i(e,n,o),x(""),S([]),M([]),L.current=null}catch(p){h(String(p instanceof Error?p.message:p)||s("commentInput.sendFailed"))}w(!1)},P=a.useCallback(e=>{x(n=>{const o=n.lastIndexOf("@"),p=oe(e.name);return o>=0?n.slice(0,o)+p+" ":n+p+" "}),C.includes(e.id)||S(n=>[...n,e.id]),m(!1),k(""),I(0),F.current?.focus()},[C]),V=e=>{x(e),h(null);const n=e.lastIndexOf("@");if(n>=0&&(n===0||e[n-1]===" ")){const p=e.slice(n+1).toLowerCase();if($.some(v=>v.name.toLowerCase().includes(p))){k(p),m(!0),I(0);return}}m(!1)},Z=e=>{if(c&&D.length>0){const n=e.key==="ArrowUp"||e.ctrlKey&&e.key==="p",o=e.key==="ArrowDown"||e.ctrlKey&&e.key==="n",p=e.key==="Enter"||e.key==="Tab",R=e.key==="Escape";if(n){e.preventDefault(),I(v=>(v-1+D.length)%D.length);return}if(o){e.preventDefault(),I(v=>(v+1)%D.length);return}if(p){e.preventDefault();const v=D[B];v&&P(v);return}if(R){e.preventDefault(),m(!1);return}}e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),O())},J=a.useCallback(()=>{setTimeout(()=>m(!1),200)},[]);return t.jsxs("div",{className:"relative",onDragOver:G,onDragLeave:H,onDrop:q,children:[z&&t.jsx("div",{className:"absolute inset-0 z-50 flex items-center justify-center bg-brand-500/10 rounded-lg border-2 border-dashed border-brand-500",children:t.jsx("span",{className:"text-sm text-brand-500 font-medium",children:s("commentInput.dragDropHint")})}),c&&t.jsx(ae,{candidates:$,filter:j,anchorRef:F,onSelect:P,selectedIndex:B,onIndexChange:I}),t.jsxs("div",{className:"border border-border-default rounded-lg bg-surface-elevated",children:[f&&t.jsxs("div",{className:"flex items-center gap-2 px-2.5 pt-2 pb-1 border-b border-border-default/50",children:[t.jsxs("div",{className:"flex-1 min-w-0 pl-2 border-l-2 border-brand-500/50",children:[t.jsx("span",{className:"text-[10px] font-medium text-brand-500",children:f.authorName}),t.jsx("p",{className:"text-[10px] text-fg-tertiary truncate",children:f.content})]}),t.jsx("button",{onClick:y,className:"text-fg-tertiary hover:text-fg-secondary shrink-0 p-0.5",children:t.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[t.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),t.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]}),C.length>0&&t.jsx("div",{className:"flex gap-1 px-2.5 pt-2 flex-wrap",children:C.map(e=>{const n=$.find(o=>o.id===e);return t.jsxs("span",{className:`inline-flex items-center gap-1 px-1.5 py-0.5 text-[10px] rounded-full ${n?.type==="human"?"bg-green-500/15 text-green-500":"bg-brand-500/15 text-brand-500"}`,children:["@",n?.name??e,t.jsx("button",{onClick:()=>S(o=>o.filter(p=>p!==e)),className:"hover:text-red-400",children:"×"})]},e)})}),t.jsx("textarea",{ref:F,value:r,onChange:e=>V(e.target.value),onKeyDown:Z,onBlur:J,onPaste:Y,placeholder:g??s("commentInput.placeholder"),rows:2,className:"w-full px-2.5 py-2 text-xs bg-transparent text-fg-primary placeholder-fg-tertiary outline-none resize-none"}),N.length>0&&t.jsx("div",{className:"flex items-center gap-1.5 px-2.5 pb-1.5 overflow-x-auto",children:N.map(e=>t.jsxs("div",{className:"relative group/img shrink-0",children:[t.jsx("img",{src:e.dataUrl,alt:e.name,className:"w-12 h-12 rounded-lg object-cover border border-border-default"}),t.jsx("button",{onClick:()=>X(e.id),className:"absolute -top-1.5 -right-1.5 w-4 h-4 bg-surface-secondary border border-gray-600 rounded-full flex items-center justify-center text-fg-secondary hover:text-red-500 hover:border-red-500 text-[10px] opacity-0 group-hover/img:opacity-100 transition-opacity",title:s("commentInput.removeImage"),children:"×"})]},e.id))}),d&&t.jsxs("div",{className:"flex items-center gap-2 px-2.5 pb-1.5",children:[t.jsx("span",{className:"text-[11px] text-red-400 flex-1 truncate",children:d}),t.jsxs("button",{onClick:Q,disabled:b,className:"text-[11px] text-amber-500 hover:text-amber-400 font-medium transition-colors flex items-center gap-1",children:[t.jsxs("svg",{className:"w-3 h-3",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[t.jsx("polyline",{points:"23 4 23 10 17 10"}),t.jsx("path",{d:"M20.49 15a9 9 0 11-2.12-9.36L23 10"})]}),s("commentInput.retry")]})]}),t.jsxs("div",{className:"flex items-center justify-between px-2.5 pb-2",children:[t.jsx("button",{type:"button",onClick:()=>U.current?.click(),disabled:b||N.length>=W,className:"p-1 text-fg-tertiary hover:text-brand-500 disabled:opacity-30 disabled:cursor-not-allowed transition-colors",title:s("commentInput.attachImage"),children:t.jsxs("svg",{className:"w-4 h-4",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[t.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),t.jsx("circle",{cx:"8.5",cy:"8.5",r:"1.5"}),t.jsx("polyline",{points:"21 15 16 10 5 21"})]})}),t.jsx("input",{ref:U,type:"file",accept:"image/*",multiple:!0,className:"hidden",onChange:e=>{e.target.files&&E(e.target.files),e.target.value=""}}),t.jsx("button",{onClick:O,disabled:!r.trim()&&N.length===0||b,className:"px-3 py-1 text-[11px] font-medium bg-brand-500 text-white rounded-md hover:bg-brand-600 disabled:opacity-40 disabled:cursor-not-allowed transition-colors",children:s(b?"commentInput.sending":"commentInput.submit")})]})]}),t.jsx("p",{className:"mt-1 text-center text-[10px] text-fg-tertiary/80 select-none",children:s("aiDisclaimer")})]})}export{de as C,ie as p,ce as r};
|
|
1
|
+
import{j as t,u as T,r as a,k as ee}from"./index-B-xjev59.js";const te=1920,ne=10*1024*1024,W=5,re=.8;function se(l,u,i){return new Promise((g,f)=>{const y=new Image;y.onload=()=>{let{width:s,height:r}=y;if(s<=u&&r<=u){g(l);return}s>r?(r=Math.round(r*(u/s)),s=u):(s=Math.round(s*(u/r)),r=u);const x=document.createElement("canvas");x.width=s,x.height=r;const b=x.getContext("2d");if(!b){f(new Error("Failed to get canvas context"));return}b.drawImage(y,0,0,s,r),g(x.toDataURL("image/jpeg",i))},y.onerror=()=>f(new Error("Failed to load image")),y.src=l})}function ae({candidates:l,filter:u,anchorRef:i,onSelect:g,selectedIndex:f,onIndexChange:y}){const{t:s}=T("common"),[r,x]=a.useState(null),b=a.useRef(null),w=l.filter(d=>d.name.toLowerCase().includes(u));return a.useEffect(()=>{const d=i.current;if(!d)return;const h=d.getBoundingClientRect();x({top:h.top+window.scrollY-4,left:h.left+window.scrollX+8})},[i,u]),a.useEffect(()=>{if(!b.current||!r)return;if(b.current.getBoundingClientRect().top<8){const h=i.current;if(!h)return;const c=h.getBoundingClientRect();x({top:c.bottom+window.scrollY+4,left:r.left})}},[r,i]),a.useEffect(()=>{f>=w.length&&y(Math.max(0,w.length-1))},[w.length,f,y]),a.useEffect(()=>{if(!b.current)return;b.current.querySelector('[data-selected="true"]')?.scrollIntoView({block:"nearest"})},[f]),!r||w.length===0?null:ee.createPortal(t.jsxs("div",{ref:b,style:{position:"absolute",top:r.top,left:r.left,transform:"translateY(-100%)"},className:"w-60 bg-surface-overlay border border-border-default rounded-lg shadow-xl z-[9999] max-h-48 overflow-y-auto",children:[t.jsx("div",{className:"px-2.5 py-1.5 text-[10px] text-fg-tertiary font-medium uppercase tracking-wider border-b border-border-default",children:s("commentInput.mentionHeading")}),w.map((d,h)=>t.jsxs("button",{"data-selected":h===f,onMouseDown:c=>{c.preventDefault(),g(d)},onMouseEnter:()=>y(h),className:`w-full text-left px-3 py-2 text-xs flex items-center gap-2 transition-colors ${h===f?"bg-brand-500/15 text-brand-500":"hover:bg-surface-elevated"}`,children:[t.jsx("span",{className:`w-6 h-6 rounded-full flex items-center justify-center text-[10px] font-bold shrink-0 ${d.type==="human"?"bg-green-500/20 text-green-500":"bg-brand-500/20 text-brand-500"}`,children:d.name.slice(0,2).toUpperCase()}),t.jsxs("div",{className:"flex-1 min-w-0",children:[t.jsx("span",{className:"text-fg-primary font-medium",children:d.name}),t.jsx("span",{className:"text-fg-tertiary text-[10px] ml-1.5",children:d.subtitle??d.type})]}),d.type==="agent"&&t.jsx("span",{className:`w-1.5 h-1.5 rounded-full shrink-0 ${d.online?"bg-green-400":"bg-gray-500"}`})]},d.id))]}),document.body)}function oe(l){return/^\w+$/.test(l)?`@${l}`:`@[${l}]`}const K=/@\[([^\]]+)\]|@([\w\p{L}\p{N}]+)/gu;function ie(l){const u=[];let i;for(K.lastIndex=0;(i=K.exec(l))!==null;)u.push(i[1]??i[2]);return u}function ce(l,u,i){const g=[];let f=0;const y=u.map(r=>r.name).sort((r,x)=>x.length-r.length);let s=0;for(;s<l.length;){const r=l.indexOf("@",s);if(r<0){g.push(t.jsx("span",{children:l.slice(s)},f++));break}if(r>s&&g.push(t.jsx("span",{children:l.slice(s,r)},f++)),l[r+1]==="["){const c=l.indexOf("]",r+2);if(c>r+2){const m=l.slice(r+2,c),j=u.find(k=>k.name.toLowerCase()===m.toLowerCase());g.push(t.jsxs("span",{className:`text-brand-500 font-medium ${i&&j?"cursor-pointer hover:underline":""}`,onClick:i&&j?k=>i(j,k):void 0,title:j?`${j.name} (${j.role})`:void 0,children:["@",m]},f++)),s=c+1;continue}}const x=l.slice(r+1),b=x.toLowerCase(),w=y.find(c=>b.startsWith(c.toLowerCase()));if(w){const c=u.find(m=>m.name.toLowerCase()===w.toLowerCase());g.push(t.jsxs("span",{className:`text-brand-500 font-medium ${i&&c?"cursor-pointer hover:underline":""}`,onClick:i&&c?m=>i(c,m):void 0,title:c?`${c.name} (${c.role})`:void 0,children:["@",w]},f++)),s=r+1+w.length;continue}const d=/^([\w\p{L}\p{N}]+)/u,h=x.match(d);if(h){const c=h[1],m=u.find(j=>j.name.toLowerCase()===c.toLowerCase());g.push(t.jsxs("span",{className:`text-brand-500 font-medium ${i&&m?"cursor-pointer hover:underline":""}`,onClick:i&&m?j=>i(m,j):void 0,title:m?`${m.name} (${m.role})`:void 0,children:["@",c]},f++)),s=r+1+c.length;continue}g.push(t.jsx("span",{children:"@"},f++)),s=r+1}return g.length>0?g:[t.jsx("span",{children:l},0)]}function de({agents:l,humans:u,onSubmit:i,placeholder:g,replyTo:f,onCancelReply:y}){const{t:s}=T("common"),[r,x]=a.useState(""),[b,w]=a.useState(!1),[d,h]=a.useState(null),[c,m]=a.useState(!1),[j,k]=a.useState(""),[C,S]=a.useState([]),[B,I]=a.useState(0),[N,M]=a.useState([]),[z,A]=a.useState(!1),F=a.useRef(null),U=a.useRef(null),L=a.useRef(null),$=a.useMemo(()=>{const e=(u??[]).map(n=>({id:n.id,name:n.name,type:"human",subtitle:n.role}));for(const n of l)e.push({id:n.id,name:n.name,type:"agent",subtitle:n.role,online:n.status==="idle"||n.status==="working"});return e},[l,u]),D=$.filter(e=>e.name.toLowerCase().includes(j)),E=a.useCallback(e=>{const n=Array.from(e).filter(o=>o.type.startsWith("image/"));if(n.length!==0)for(const o of n){if(o.size>ne)continue;const p=new FileReader;p.onload=()=>{const R=p.result;se(R,te,re).then(v=>{M(_=>_.length>=W?_:[..._,{id:`img_${Date.now()}_${Math.random().toString(36).slice(2,6)}`,dataUrl:v,name:o.name}])})},p.readAsDataURL(o)}},[]),X=a.useCallback(e=>{M(n=>n.filter(o=>o.id!==e))},[]),Y=a.useCallback(e=>{const n=e.clipboardData?.files;if(n&&n.length>0){const o=Array.from(n).filter(p=>p.type.startsWith("image/"));o.length>0&&(e.preventDefault(),E(o))}},[E]),q=a.useCallback(e=>{e.preventDefault(),A(!1);const n=e.dataTransfer?.files;n&&n.length>0&&E(Array.from(n).filter(o=>o.type.startsWith("image/")))},[E]),G=a.useCallback(e=>{e.preventDefault(),A(!0)},[]),H=a.useCallback(()=>{A(!1)},[]),O=async()=>{if(!(!r.trim()&&N.length===0)){w(!0),h(null),L.current={content:r,mentions:[...C],images:[...N]};try{await i(r,C,[...N],f?.id),x(""),S([]),M([]),L.current=null,y?.()}catch(e){h(String(e instanceof Error?e.message:e)||s("commentInput.sendFailed"))}w(!1)}},Q=async()=>{if(!L.current)return;const{content:e,mentions:n,images:o}=L.current;w(!0),h(null);try{await i(e,n,o),x(""),S([]),M([]),L.current=null}catch(p){h(String(p instanceof Error?p.message:p)||s("commentInput.sendFailed"))}w(!1)},P=a.useCallback(e=>{x(n=>{const o=n.lastIndexOf("@"),p=oe(e.name);return o>=0?n.slice(0,o)+p+" ":n+p+" "}),C.includes(e.id)||S(n=>[...n,e.id]),m(!1),k(""),I(0),F.current?.focus()},[C]),V=e=>{x(e),h(null);const n=e.lastIndexOf("@");if(n>=0&&(n===0||e[n-1]===" ")){const p=e.slice(n+1).toLowerCase();if($.some(v=>v.name.toLowerCase().includes(p))){k(p),m(!0),I(0);return}}m(!1)},Z=e=>{if(c&&D.length>0){const n=e.key==="ArrowUp"||e.ctrlKey&&e.key==="p",o=e.key==="ArrowDown"||e.ctrlKey&&e.key==="n",p=e.key==="Enter"||e.key==="Tab",R=e.key==="Escape";if(n){e.preventDefault(),I(v=>(v-1+D.length)%D.length);return}if(o){e.preventDefault(),I(v=>(v+1)%D.length);return}if(p){e.preventDefault();const v=D[B];v&&P(v);return}if(R){e.preventDefault(),m(!1);return}}e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),O())},J=a.useCallback(()=>{setTimeout(()=>m(!1),200)},[]);return t.jsxs("div",{className:"relative",onDragOver:G,onDragLeave:H,onDrop:q,children:[z&&t.jsx("div",{className:"absolute inset-0 z-50 flex items-center justify-center bg-brand-500/10 rounded-lg border-2 border-dashed border-brand-500",children:t.jsx("span",{className:"text-sm text-brand-500 font-medium",children:s("commentInput.dragDropHint")})}),c&&t.jsx(ae,{candidates:$,filter:j,anchorRef:F,onSelect:P,selectedIndex:B,onIndexChange:I}),t.jsxs("div",{className:"border border-border-default rounded-lg bg-surface-elevated",children:[f&&t.jsxs("div",{className:"flex items-center gap-2 px-2.5 pt-2 pb-1 border-b border-border-default/50",children:[t.jsxs("div",{className:"flex-1 min-w-0 pl-2 border-l-2 border-brand-500/50",children:[t.jsx("span",{className:"text-[10px] font-medium text-brand-500",children:f.authorName}),t.jsx("p",{className:"text-[10px] text-fg-tertiary truncate",children:f.content})]}),t.jsx("button",{onClick:y,className:"text-fg-tertiary hover:text-fg-secondary shrink-0 p-0.5",children:t.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[t.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),t.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]}),C.length>0&&t.jsx("div",{className:"flex gap-1 px-2.5 pt-2 flex-wrap",children:C.map(e=>{const n=$.find(o=>o.id===e);return t.jsxs("span",{className:`inline-flex items-center gap-1 px-1.5 py-0.5 text-[10px] rounded-full ${n?.type==="human"?"bg-green-500/15 text-green-500":"bg-brand-500/15 text-brand-500"}`,children:["@",n?.name??e,t.jsx("button",{onClick:()=>S(o=>o.filter(p=>p!==e)),className:"hover:text-red-400",children:"×"})]},e)})}),t.jsx("textarea",{ref:F,value:r,onChange:e=>V(e.target.value),onKeyDown:Z,onBlur:J,onPaste:Y,placeholder:g??s("commentInput.placeholder"),rows:2,className:"w-full px-2.5 py-2 text-xs bg-transparent text-fg-primary placeholder-fg-tertiary outline-none resize-none"}),N.length>0&&t.jsx("div",{className:"flex items-center gap-1.5 px-2.5 pb-1.5 overflow-x-auto",children:N.map(e=>t.jsxs("div",{className:"relative group/img shrink-0",children:[t.jsx("img",{src:e.dataUrl,alt:e.name,className:"w-12 h-12 rounded-lg object-cover border border-border-default"}),t.jsx("button",{onClick:()=>X(e.id),className:"absolute -top-1.5 -right-1.5 w-4 h-4 bg-surface-secondary border border-gray-600 rounded-full flex items-center justify-center text-fg-secondary hover:text-red-500 hover:border-red-500 text-[10px] opacity-0 group-hover/img:opacity-100 transition-opacity",title:s("commentInput.removeImage"),children:"×"})]},e.id))}),d&&t.jsxs("div",{className:"flex items-center gap-2 px-2.5 pb-1.5",children:[t.jsx("span",{className:"text-[11px] text-red-400 flex-1 truncate",children:d}),t.jsxs("button",{onClick:Q,disabled:b,className:"text-[11px] text-amber-500 hover:text-amber-400 font-medium transition-colors flex items-center gap-1",children:[t.jsxs("svg",{className:"w-3 h-3",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[t.jsx("polyline",{points:"23 4 23 10 17 10"}),t.jsx("path",{d:"M20.49 15a9 9 0 11-2.12-9.36L23 10"})]}),s("commentInput.retry")]})]}),t.jsxs("div",{className:"flex items-center justify-between px-2.5 pb-2",children:[t.jsx("button",{type:"button",onClick:()=>U.current?.click(),disabled:b||N.length>=W,className:"p-1 text-fg-tertiary hover:text-brand-500 disabled:opacity-30 disabled:cursor-not-allowed transition-colors",title:s("commentInput.attachImage"),children:t.jsxs("svg",{className:"w-4 h-4",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[t.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),t.jsx("circle",{cx:"8.5",cy:"8.5",r:"1.5"}),t.jsx("polyline",{points:"21 15 16 10 5 21"})]})}),t.jsx("input",{ref:U,type:"file",accept:"image/*",multiple:!0,className:"hidden",onChange:e=>{e.target.files&&E(e.target.files),e.target.value=""}}),t.jsx("button",{onClick:O,disabled:!r.trim()&&N.length===0||b,className:"px-3 py-1 text-[11px] font-medium bg-brand-500 text-white rounded-md hover:bg-brand-600 disabled:opacity-40 disabled:cursor-not-allowed transition-colors",children:s(b?"commentInput.sending":"commentInput.submit")})]})]}),t.jsx("p",{className:"mt-1 text-center text-[10px] text-fg-tertiary/80 select-none",children:s("aiDisclaimer")})]})}export{de as C,ie as p,ce as r};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-
|
|
2
|
-
import{j as a,r as i,_ as f}from"./index-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-B-xjev59.js","assets/index-BbQpGkiM.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{j as a,r as i,_ as f}from"./index-B-xjev59.js";const x=i.lazy(()=>f(()=>import("./index-B-xjev59.js").then(e=>e.aE),__vite__mapDeps([0,1])).then(e=>({default:e.MarkdownMessage}))),b=new Set(["ts","tsx","js","jsx","mjs","cjs","py","go","rs","java","kt","kts","c","cc","cpp","cxx","h","hpp","hxx","cs","rb","php","swift","scala","sh","bash","zsh","fish","ps1","sql","yaml","yml","toml","xml","css","scss","less","vue","svelte","graphql","gql","proto","dockerfile","makefile","cmake","rsx","r","lua","pl","pm","ex","exs","erl","hs","clj","zig","nim","dart","gradle","tf","hcl"]);function v(e){const t=e.split(/[/\\]/).pop()?.toLowerCase()||"";if(t==="dockerfile"||t==="makefile")return"code";const r=t.includes(".")?t.split(".").pop():"";switch(r){case"md":case"markdown":return"markdown";case"html":case"htm":return"html";case"json":case"jsonc":return"json";case"csv":case"tsv":return"csv";default:return r&&b.has(r)?"code":r?"text":void 0}}function w(e){const t=e.trimStart();if(/^<!doctype\s+html/i.test(t)||/^<html[\s>]/i.test(t))return"html";if(t.startsWith("{")||t.startsWith("["))try{return JSON.parse(e),"json"}catch{}}function S(e){if(e.format)return e.format;if(e.reference){const t=v(e.reference);if(t)return t}if(e.content){const t=w(e.content);if(t)return t}return e.reference?"text":"markdown"}function y({content:e,className:t,onSelection:r}){const c=i.useRef(null),[l,p]=i.useState(null);i.useEffect(()=>{const o=d=>{d.data?.type==="__htmlpreview_height"&&typeof d.data.height=="number"&&p(d.data.height),d.data?.type==="__htmlpreview_selection"&&r&&r(d.data)};return window.addEventListener("message",o),()=>window.removeEventListener("message",o)},[r]);const h=`<script>
|
|
3
3
|
(function(){
|
|
4
4
|
function getXPath(el){
|
|
5
5
|
if(!el||el.nodeType!==1)return'';
|