@markus-global/cli 0.9.7-rc.0 → 0.9.7-rc.1

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.
Files changed (63) hide show
  1. package/dist/markus.mjs +223 -14
  2. package/dist/web-ui/assets/{CommentInput-Dvlq2svZ.js → CommentInput-CIxUL6dU.js} +1 -1
  3. package/dist/web-ui/assets/{ContentRenderer-BfnvpFM7.js → ContentRenderer-Bb_drUpO.js} +2 -2
  4. package/dist/web-ui/assets/{DeliverableShareModal-DkGpQmZ8.js → DeliverableShareModal-BEeIlXig.js} +1 -1
  5. package/dist/web-ui/assets/{Deliverables-CtPvquKO.js → Deliverables-CJFzxbLw.js} +1 -1
  6. package/dist/web-ui/assets/{Notifications-C_e9_V74.js → Notifications-Cz2LKhGE.js} +1 -1
  7. package/dist/web-ui/assets/{Search-DZBGpN3c.js → Search-dq45wHQN.js} +1 -1
  8. package/dist/web-ui/assets/Settings-WAXEtxMR.js +8 -0
  9. package/dist/web-ui/assets/{Store-dbJSFCFw.js → Store-DOGCOxTK.js} +1 -1
  10. package/dist/web-ui/assets/{Team-vmqHkmh8.js → Team-NM2SsmjN.js} +4 -4
  11. package/dist/web-ui/assets/{Work-Ds7q6pZg.js → Work-ornw-1Zh.js} +1 -1
  12. package/dist/web-ui/assets/{arc-BLoofCdL.js → arc-D4xcu8MX.js} +1 -1
  13. package/dist/web-ui/assets/{architectureDiagram-3BPJPVTR-BGO4nFRN.js → architectureDiagram-3BPJPVTR-DP3EZPSb.js} +1 -1
  14. package/dist/web-ui/assets/{blockDiagram-GPEHLZMM-Cn1E0037.js → blockDiagram-GPEHLZMM-BnSHtwXa.js} +1 -1
  15. package/dist/web-ui/assets/{c4Diagram-AAUBKEIU-DXFAnq3E.js → c4Diagram-AAUBKEIU-DpPSihlY.js} +1 -1
  16. package/dist/web-ui/assets/channel-DSB2MBEK.js +1 -0
  17. package/dist/web-ui/assets/{chunk-2J33WTMH-BXCSmrWD.js → chunk-2J33WTMH-DD5lZIGF.js} +1 -1
  18. package/dist/web-ui/assets/{chunk-4BX2VUAB-CIWJeena.js → chunk-4BX2VUAB-D9wu9GG0.js} +1 -1
  19. package/dist/web-ui/assets/{chunk-55IACEB6-BuQ5-tdz.js → chunk-55IACEB6-p_n2ARjh.js} +1 -1
  20. package/dist/web-ui/assets/{chunk-727SXJPM-q9Yx_12l.js → chunk-727SXJPM-BiTqi43c.js} +1 -1
  21. package/dist/web-ui/assets/{chunk-AQP2D5EJ-DqaehwKB.js → chunk-AQP2D5EJ-DVPMedje.js} +1 -1
  22. package/dist/web-ui/assets/{chunk-FMBD7UC4-BFs2IYjK.js → chunk-FMBD7UC4-B53AqN8D.js} +1 -1
  23. package/dist/web-ui/assets/{chunk-ND2GUHAM-DyYGWpbj.js → chunk-ND2GUHAM-sACe_lkd.js} +1 -1
  24. package/dist/web-ui/assets/{chunk-QZHKN3VN-DmbA4AU_.js → chunk-QZHKN3VN-B0qDAQUW.js} +1 -1
  25. package/dist/web-ui/assets/classDiagram-4FO5ZUOK-D5cDjaiz.js +1 -0
  26. package/dist/web-ui/assets/classDiagram-v2-Q7XG4LA2-D5cDjaiz.js +1 -0
  27. package/dist/web-ui/assets/{cose-bilkent-S5V4N54A-BLWm27gv.js → cose-bilkent-S5V4N54A-BzZayQQf.js} +1 -1
  28. package/dist/web-ui/assets/{dagre-BM42HDAG-Cb2YgHjF.js → dagre-BM42HDAG-DjcfWzm_.js} +1 -1
  29. package/dist/web-ui/assets/{diagram-2AECGRRQ-hMyyF4SK.js → diagram-2AECGRRQ-CEK9T3rW.js} +1 -1
  30. package/dist/web-ui/assets/{diagram-5GNKFQAL-DQvYRI_z.js → diagram-5GNKFQAL-BJsJPwEI.js} +1 -1
  31. package/dist/web-ui/assets/{diagram-KO2AKTUF-CPOv2Kga.js → diagram-KO2AKTUF-BZlki2qo.js} +1 -1
  32. package/dist/web-ui/assets/{diagram-LMA3HP47-DvgOU39M.js → diagram-LMA3HP47-Bkmh3WcY.js} +1 -1
  33. package/dist/web-ui/assets/{diagram-OG6HWLK6-DhLJ9Bog.js → diagram-OG6HWLK6-4THSXHiA.js} +1 -1
  34. package/dist/web-ui/assets/{erDiagram-TEJ5UH35-C4MKvJYc.js → erDiagram-TEJ5UH35-CPj2HGe-.js} +1 -1
  35. package/dist/web-ui/assets/{flowDiagram-I6XJVG4X-C4KiUPBX.js → flowDiagram-I6XJVG4X-Bu8HgFqR.js} +1 -1
  36. package/dist/web-ui/assets/{ganttDiagram-6RSMTGT7-CFiAe8nx.js → ganttDiagram-6RSMTGT7-C5gs9b9P.js} +1 -1
  37. package/dist/web-ui/assets/{gitGraphDiagram-PVQCEYII-y6rZo1sT.js → gitGraphDiagram-PVQCEYII-DxnBgR_T.js} +1 -1
  38. package/dist/web-ui/assets/{index-CcppNtga.js → index-CiAGgfZx.js} +6 -6
  39. package/dist/web-ui/assets/{infoDiagram-5YYISTIA-LLlnmiVb.js → infoDiagram-5YYISTIA-D4M-cR8I.js} +1 -1
  40. package/dist/web-ui/assets/{ishikawaDiagram-YF4QCWOH-Brs-NT84.js → ishikawaDiagram-YF4QCWOH-Oiq6jknk.js} +1 -1
  41. package/dist/web-ui/assets/{journeyDiagram-JHISSGLW-um06-20P.js → journeyDiagram-JHISSGLW-D2gmyCKv.js} +1 -1
  42. package/dist/web-ui/assets/{kanban-definition-UN3LZRKU-yws0Rgw8.js → kanban-definition-UN3LZRKU-DqjzkO8l.js} +1 -1
  43. package/dist/web-ui/assets/{mermaid.core-C0Q8mcc_.js → mermaid.core-N5tL3hIv.js} +5 -5
  44. package/dist/web-ui/assets/{mindmap-definition-RKZ34NQL-xCtHajk4.js → mindmap-definition-RKZ34NQL-ATHsVy0v.js} +1 -1
  45. package/dist/web-ui/assets/{pieDiagram-4H26LBE5-BhKiwY7r.js → pieDiagram-4H26LBE5-CprLr2Gv.js} +1 -1
  46. package/dist/web-ui/assets/{quadrantDiagram-W4KKPZXB-CGmxw13s.js → quadrantDiagram-W4KKPZXB-0uN86dlU.js} +1 -1
  47. package/dist/web-ui/assets/{requirementDiagram-4Y6WPE33-CYJRHrZE.js → requirementDiagram-4Y6WPE33-CQmWbZXW.js} +1 -1
  48. package/dist/web-ui/assets/{sankeyDiagram-5OEKKPKP-CgkdSCTc.js → sankeyDiagram-5OEKKPKP-D6kdJsQI.js} +1 -1
  49. package/dist/web-ui/assets/{sequenceDiagram-3UESZ5HK-BD2dXCDe.js → sequenceDiagram-3UESZ5HK-1Y79snKt.js} +1 -1
  50. package/dist/web-ui/assets/{stateDiagram-AJRCARHV-DdEvCrm2.js → stateDiagram-AJRCARHV-BqmCPSIN.js} +1 -1
  51. package/dist/web-ui/assets/stateDiagram-v2-BHNVJYJU-DRaoGsBn.js +1 -0
  52. package/dist/web-ui/assets/{timeline-definition-PNZ67QCA-CWfdKPN1.js → timeline-definition-PNZ67QCA-OG71KAzb.js} +1 -1
  53. package/dist/web-ui/assets/{vennDiagram-CIIHVFJN-BTiDdRt6.js → vennDiagram-CIIHVFJN-V9c-71bn.js} +1 -1
  54. package/dist/web-ui/assets/{wardley-L42UT6IY-eDkltTBC.js → wardley-L42UT6IY-C3A6_LpL.js} +1 -1
  55. package/dist/web-ui/assets/{wardleyDiagram-YWT4CUSO-DLOZOKTX.js → wardleyDiagram-YWT4CUSO-B54ZiT7U.js} +1 -1
  56. package/dist/web-ui/assets/{xychartDiagram-2RQKCTM6-RU8GlPu6.js → xychartDiagram-2RQKCTM6-DpWlpUfV.js} +1 -1
  57. package/dist/web-ui/index.html +1 -1
  58. package/package.json +1 -1
  59. package/dist/web-ui/assets/Settings-6xm2sHhm.js +0 -8
  60. package/dist/web-ui/assets/channel-Cw25sYRm.js +0 -1
  61. package/dist/web-ui/assets/classDiagram-4FO5ZUOK-CDWjvgnK.js +0 -1
  62. package/dist/web-ui/assets/classDiagram-v2-Q7XG4LA2-CDWjvgnK.js +0 -1
  63. 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,133 @@ 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 contextWindow = await this.probeOllamaContext(base, m.name);
75520
+ return {
75521
+ id: m.name,
75522
+ name: m.name,
75523
+ provider: "ollama",
75524
+ contextWindow,
75525
+ maxOutputTokens: OLLAMA_DEFAULT_MAX_OUTPUT,
75526
+ cost: { input: 0, output: 0 },
75527
+ inputTypes: ["text"],
75528
+ description: tag ? tag : void 0
75529
+ };
75530
+ }));
75531
+ this.customModelCatalog.set("ollama", models);
75532
+ log57.info(`Synced ${models.length} local Ollama models`, { baseUrl: base });
75533
+ return models.length;
75534
+ } catch (err) {
75535
+ log57.warn("Ollama local model sync failed", { error: String(err), baseUrl: base });
75536
+ return this.customModelCatalog.get("ollama")?.length ?? 0;
75537
+ }
75538
+ }
75539
+ /**
75540
+ * Probe a local Ollama model's real context length via `/api/show`.
75541
+ * Reads `model_info["*.context_length"]` (key name varies by model family,
75542
+ * e.g. `llama.context_length`, `qwen3_5.context_length`) and returns the
75543
+ * largest positive value found. Falls back to a sane default so a probe
75544
+ * failure never blocks agent budget planning.
75545
+ */
75546
+ async probeOllamaContext(base, modelId) {
75547
+ try {
75548
+ const ctrl = new AbortController();
75549
+ const tmr = setTimeout(() => ctrl.abort(), 4e3);
75550
+ const res = await fetch(`${base}/api/show`, {
75551
+ method: "POST",
75552
+ headers: { "Content-Type": "application/json" },
75553
+ body: JSON.stringify({ model: modelId }),
75554
+ signal: ctrl.signal
75555
+ });
75556
+ clearTimeout(tmr);
75557
+ if (!res.ok)
75558
+ return OLLAMA_DEFAULT_CONTEXT_WINDOW;
75559
+ const data = await res.json();
75560
+ 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);
75561
+ const ctx = vals.length ? Math.max(...vals) : 0;
75562
+ if (ctx <= 0)
75563
+ return OLLAMA_DEFAULT_CONTEXT_WINDOW;
75564
+ log57.info(`Ollama local model ${modelId}: context_window=${ctx}`);
75565
+ return ctx;
75566
+ } catch {
75567
+ return OLLAMA_DEFAULT_CONTEXT_WINDOW;
75568
+ }
75569
+ }
75570
+ /**
75571
+ * Pull a live /v1/models list for an OpenAI-compatible provider into its
75572
+ * custom catalog. Used for newly-added providers that have no builtin entry
75573
+ * (and therefore would otherwise show zero models in pickers). If the
75574
+ * provider already has a usable catalog (builtin/custom) we skip the call.
75575
+ */
75576
+ async refreshProviderLiveModels(providerName, baseUrl, apiKey) {
75577
+ if (this.getProviderModels(providerName).length > 0)
75578
+ return 0;
75579
+ const provider = this.providers.get(providerName);
75580
+ const effectiveBase = baseUrl ?? provider?.baseUrl;
75581
+ if (!effectiveBase)
75582
+ return 0;
75583
+ const effectiveKey = apiKey ?? provider?.apiKey;
75584
+ try {
75585
+ const headers = {};
75586
+ if (effectiveKey)
75587
+ headers["Authorization"] = `Bearer ${effectiveKey}`;
75588
+ const ctrl = new AbortController();
75589
+ const tmr = setTimeout(() => ctrl.abort(), 8e3);
75590
+ const res = await fetch(`${String(effectiveBase).replace(/\/+$/, "")}/v1/models`, {
75591
+ headers,
75592
+ signal: ctrl.signal
75593
+ });
75594
+ clearTimeout(tmr);
75595
+ if (!res.ok)
75596
+ return 0;
75597
+ const data = await res.json();
75598
+ const ids = (data.data ?? []).map((m) => m.id).filter((x) => !!x);
75599
+ if (ids.length === 0)
75600
+ return 0;
75601
+ const defs = ids.map((id) => ({
75602
+ id,
75603
+ name: id,
75604
+ provider: providerName,
75605
+ contextWindow: 0,
75606
+ maxOutputTokens: 0,
75607
+ cost: { input: 0, output: 0 },
75608
+ inputTypes: ["text"]
75609
+ }));
75610
+ this.customModelCatalog.set(providerName, defs);
75611
+ log57.info(`Synced ${defs.length} live models for provider ${providerName}`, { baseUrl: effectiveBase });
75612
+ return defs.length;
75613
+ } catch (err) {
75614
+ log57.warn(`Live model sync failed for provider ${providerName}`, { error: String(err), baseUrl: effectiveBase });
75615
+ return 0;
75616
+ }
75617
+ }
75480
75618
  /**
75481
75619
  * Drop sticky Markus defaults that are no longer in the Hub catalog
75482
75620
  * (e.g. CN geo-filter removes anthropic/claude-opus-5 while chip still shows it).
@@ -76161,7 +76299,7 @@ var init_router2 = __esm({
76161
76299
  * Used by the test endpoint to verify a single provider's connectivity.
76162
76300
  * Also returns the baseUrl used for diagnostics.
76163
76301
  */
76164
- async chatDirect(request, providerName) {
76302
+ async chatDirect(request, providerName, altModel) {
76165
76303
  const provider = this.providers.get(providerName);
76166
76304
  if (!provider) {
76167
76305
  throw new Error(`Provider "${providerName}" not registered`);
@@ -76170,9 +76308,24 @@ var init_router2 = __esm({
76170
76308
  throw new Error(`Provider "${providerName}" is disabled`);
76171
76309
  }
76172
76310
  request = this.resolveMaxTokens(request, providerName);
76173
- const response = await provider.chat(request);
76174
- const baseUrl = provider.baseUrl ?? provider.config?.baseUrl;
76175
- return Object.assign(response, { _providerBaseUrl: baseUrl });
76311
+ const originalModel = provider.model;
76312
+ const useRequestModelOnly = providerName === "markus" || provider instanceof MarkusProvider;
76313
+ const activeModel = altModel ?? originalModel;
76314
+ let switched = false;
76315
+ if (!useRequestModelOnly && altModel && altModel !== originalModel) {
76316
+ provider.configure({ provider: providerName, model: altModel });
76317
+ switched = true;
76318
+ }
76319
+ const directRequest = useRequestModelOnly && altModel ? { ...request, model: altModel } : request;
76320
+ try {
76321
+ const response = await provider.chat(directRequest);
76322
+ const baseUrl = provider.baseUrl ?? provider.config?.baseUrl;
76323
+ return Object.assign(response, { _providerBaseUrl: baseUrl, _model: activeModel });
76324
+ } finally {
76325
+ if (switched) {
76326
+ provider.configure({ provider: providerName, model: originalModel });
76327
+ }
76328
+ }
76176
76329
  }
76177
76330
  /**
76178
76331
  * Try a streaming chat on a specific provider, optionally with an alternate model.
@@ -76522,7 +76675,8 @@ var init_router2 = __esm({
76522
76675
  });
76523
76676
  const ctx = catalogEntry?.contextWindow;
76524
76677
  if (!ctx || ctx <= 0) {
76525
- throw new Error(name === "markus" ? `Cannot resolve context_window for markus model "${provider.model || "(unset)"}": it is not in the loaded Hub catalog (catalog may be empty). Please check the Hub connection and refresh the model list, or reconfigure the model. No default is substituted.` : `Cannot resolve context_window for provider "${name}" (model "${provider.model || "(unset)"}"): the model is unknown to the built-in catalog. Please configure the model or fix the model id. No default is substituted.`);
76678
+ 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.`);
76679
+ return DEFAULT_CONTEXT_WINDOW_FALLBACK;
76526
76680
  }
76527
76681
  return ctx;
76528
76682
  }
@@ -76544,7 +76698,8 @@ var init_router2 = __esm({
76544
76698
  });
76545
76699
  const out = catalogEntry?.maxOutputTokens;
76546
76700
  if (!out || out <= 0) {
76547
- throw new Error(`Cannot resolve max_output_tokens for provider "${name}" (model "${provider.model || "(unset)"}"). The model catalog must supply a real value \u2014 refresh the Hub catalog / reconfigure the model. No default is substituted.`);
76701
+ log57.warn(`No max_output_tokens for provider "${name}" model "${provider.model || "(unset)"}" \u2014 using fallback ${DEFAULT_MAX_OUTPUT_FALLBACK}.`);
76702
+ return DEFAULT_MAX_OUTPUT_FALLBACK;
76548
76703
  }
76549
76704
  return out;
76550
76705
  }
@@ -215631,6 +215786,42 @@ EXPLANATION_END`;
215631
215786
  }
215632
215787
  return;
215633
215788
  }
215789
+ if (providerName === "ollama") {
215790
+ const ollamaUrl = process.env["OLLAMA_BASE_URL"] || "http://localhost:11434";
215791
+ const providerInstance = this.llmRouter?.getProvider("ollama");
215792
+ const configuredBaseUrl = providerInstance?.baseUrl;
215793
+ const baseUrl = configuredBaseUrl ?? ollamaUrl;
215794
+ try {
215795
+ const ctrl = new AbortController();
215796
+ const tmr = setTimeout(() => ctrl.abort(), 5e3);
215797
+ const ollamaRes = await fetch(`${String(baseUrl).replace(/\/+$/, "")}/api/tags`, { signal: ctrl.signal });
215798
+ clearTimeout(tmr);
215799
+ if (!ollamaRes.ok) {
215800
+ this.json(res, 200, { provider: "ollama", models: [], source: "error", error: `Ollama returned HTTP ${ollamaRes.status}` });
215801
+ return;
215802
+ }
215803
+ const data = await ollamaRes.json();
215804
+ const models = (data.models ?? []).map((m) => ({
215805
+ id: m.name,
215806
+ provider: "ollama",
215807
+ mode: "chat",
215808
+ maxInputTokens: 0,
215809
+ maxOutputTokens: 0,
215810
+ inputCostPer1MTokens: 0,
215811
+ outputCostPer1MTokens: 0,
215812
+ capabilities: { vision: false, functionCalling: false, reasoning: false, promptCaching: false, webSearch: false, audioInput: false, audioOutput: false },
215813
+ size: m.size,
215814
+ modifiedAt: m.modified_at,
215815
+ parameterSize: m.details?.parameter_size,
215816
+ family: m.details?.family,
215817
+ quantization: m.details?.quantization_level
215818
+ }));
215819
+ this.json(res, 200, { provider: "ollama", models, source: "live", count: models.length });
215820
+ } catch (err) {
215821
+ this.json(res, 200, { provider: "ollama", models: [], source: "error", error: err instanceof Error ? err.message : String(err) });
215822
+ }
215823
+ return;
215824
+ }
215634
215825
  try {
215635
215826
  const providerInstance = this.llmRouter?.getProvider(providerName);
215636
215827
  const apiKey = providerInstance?.apiKey ?? "";
@@ -215677,6 +215868,10 @@ EXPLANATION_END`;
215677
215868
  }
215678
215869
  } catch {
215679
215870
  }
215871
+ try {
215872
+ await this.llmRouter.refreshOllamaLocalModels?.();
215873
+ } catch {
215874
+ }
215680
215875
  this.json(res, 200, this.llmRouter.getEnhancedSettings());
215681
215876
  return;
215682
215877
  }
@@ -216883,6 +217078,11 @@ data: ${JSON.stringify({ error: msg })}
216883
217078
  apiKey,
216884
217079
  baseUrl
216885
217080
  });
217081
+ if (name === "ollama") {
217082
+ await this.llmRouter.refreshOllamaLocalModels?.(baseUrl);
217083
+ } else {
217084
+ await this.llmRouter.refreshProviderLiveModels?.(name, baseUrl, apiKey);
217085
+ }
216886
217086
  if (enabled === false) {
216887
217087
  this.llmRouter.setProviderEnabled(name, false);
216888
217088
  }
@@ -216965,6 +217165,11 @@ data: ${JSON.stringify({ error: msg })}
216965
217165
  if (typeof enabled === "boolean") {
216966
217166
  this.llmRouter.setProviderEnabled(providerName, enabled);
216967
217167
  }
217168
+ if (providerName === "ollama") {
217169
+ await this.llmRouter.refreshOllamaLocalModels?.(baseUrl ?? void 0);
217170
+ } else {
217171
+ await this.llmRouter.refreshProviderLiveModels?.(providerName, baseUrl ?? void 0, apiKey);
217172
+ }
216968
217173
  if (contextWindow || maxOutputTokens || cost) {
216969
217174
  this.llmRouter.updateProviderModelConfig(providerName, {
216970
217175
  ...contextWindow ? { contextWindow } : {},
@@ -217245,26 +217450,30 @@ data: ${JSON.stringify({ error: msg })}
217245
217450
  this.json(res, 404, { ok: false, error: `Provider "${providerName}" not found or not configured` });
217246
217451
  return;
217247
217452
  }
217453
+ const body = await this.readBody(req);
217454
+ const requestedModel = typeof body?.model === "string" && body.model.trim() ? body.model.trim() : void 0;
217248
217455
  const requestBody = {
217249
217456
  messages: [{ role: "user", content: "Reply with exactly one word: hello" }],
217250
217457
  // No maxTokens cap: a reasoning model spends the whole budget on hidden
217251
217458
  // reasoning under a tight cap, returning empty content and producing a
217252
217459
  // false "empty response / misconfigured" result. Let the router fill in
217253
217460
  // the model's real limit; the model stops after the one-word reply.
217254
- temperature: 0
217461
+ temperature: 0,
217462
+ ...requestedModel ? { model: requestedModel } : {}
217255
217463
  };
217256
217464
  const baseUrl = provider.baseUrl ?? provider.config?.baseUrl ?? "";
217257
217465
  try {
217258
217466
  const startMs = Date.now();
217259
- const response = await this.llmRouter.chatDirect(requestBody, providerName);
217467
+ const response = await this.llmRouter.chatDirect(requestBody, providerName, requestedModel);
217260
217468
  const durationMs = Date.now() - startMs;
217261
217469
  const reply = (response.content ?? "").trim();
217262
217470
  const requestUrl = response._providerBaseUrl ?? baseUrl;
217471
+ const resultModel = response._model ?? requestedModel ?? provider.model;
217263
217472
  if (!reply) {
217264
217473
  this.json(res, 200, {
217265
217474
  ok: false,
217266
217475
  error: "Model returned empty response \u2014 API key or model may be misconfigured",
217267
- model: provider.model,
217476
+ model: resultModel,
217268
217477
  durationMs,
217269
217478
  requestUrl,
217270
217479
  requestBody
@@ -217273,7 +217482,7 @@ data: ${JSON.stringify({ error: msg })}
217273
217482
  this.json(res, 200, {
217274
217483
  ok: true,
217275
217484
  durationMs,
217276
- model: provider.model,
217485
+ model: resultModel,
217277
217486
  reply: reply.slice(0, 100),
217278
217487
  usage: response.usage,
217279
217488
  requestUrl,
@@ -217300,7 +217509,7 @@ data: ${JSON.stringify({ error: msg })}
217300
217509
  ok: false,
217301
217510
  error: errorMsg.slice(0, 500),
217302
217511
  errorCode,
217303
- model: provider.model,
217512
+ model: requestedModel ?? provider.model,
217304
217513
  requestUrl: baseUrl,
217305
217514
  requestBody
217306
217515
  });
@@ -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-CiAGgfZx.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-CcppNtga.js","assets/index-BbQpGkiM.css"])))=>i.map(i=>d[i]);
2
- import{j as a,r as i,_ as f}from"./index-CcppNtga.js";const x=i.lazy(()=>f(()=>import("./index-CcppNtga.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>
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-CiAGgfZx.js","assets/index-BbQpGkiM.css"])))=>i.map(i=>d[i]);
2
+ import{j as a,r as i,_ as f}from"./index-CiAGgfZx.js";const x=i.lazy(()=>f(()=>import("./index-CiAGgfZx.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'';
@@ -1 +1 @@
1
- import{u as ce,r as u,h as A,o as de,t as ue,l as N,j as r}from"./index-CcppNtga.js";const O=50*1024*1024;class H extends Error{constructor(e){super(e),this.name="DeliverableShareError"}}class Z extends H{constructor(){super("需要登录 Markus Hub 账号后才能分享产出物。"),this.name="NotLoggedIntoHubError"}}class fe extends H{bytes;limit;constructor(e,a){super(`产出物文件大小 ${e} 字节超过上限 ${a} 字节(50MB),请压缩或拒绝分享。`),this.name="DeliverableTooLargeError",this.bytes=e,this.limit=a}}class he extends H{status;constructor(e,a){super(`Hub 请求失败 (HTTP ${e}): ${a}`),this.name="HubApiError",this.status=e}}function be(t){const e=t.replace(/\s+/g,"");if(!e)return 0;let a=0;return e.endsWith("==")?a=2:e.endsWith("=")&&(a=1),Math.floor(e.length*3/4)-a}function V(t,e){const a=t&&typeof t=="object"?t:{},l=a.share??a.deliverable??{},s=m=>a[m]??l[m],i=s("id")??s("shareId")??"",c=s("slug"),o=c!=null?String(c):void 0,d=s("url")??s("shareUrl");let h=null;d!=null?h=String(d):o&&e&&(h=`${e.replace(/\/+$/,"")}/deliverable/${encodeURIComponent(o)}`);const f=s("reason")??s("rejectNote"),p=s("localDeliverableId")??s("localId");return{id:String(i),slug:o,visibility:s("visibility")??"public",status:s("status")??"pending_review",url:h,reason:f!=null?String(f):null,localId:p!=null?String(p):null}}class pe{basePath;fetchImpl;hubOrigin;constructor(e){this.getHubToken=e.getHubToken,this.hubOrigin=e.hubUrl,this.basePath=(e.proxyBasePath??"/api/hub").replace(/\/+$/,""),this.fetchImpl=e.fetch??(globalThis.fetch?globalThis.fetch.bind(globalThis):(()=>{throw new Error("fetch unavailable")}))}getHubToken;isHubLoggedIn(){return!!this.getHubToken()}assertHubLoggedIn(){if(!this.getHubToken())throw new Z}async doFetch(e,a){const l=this.getHubToken(),s={"Content-Type":"application/json",...a.headers};l&&(s.Authorization=`Bearer ${l}`);const i=await this.fetchImpl(`${this.basePath}${e}`,{...a,headers:s,credentials:"include"});let c=null;try{c=await i.json()}catch{c=null}if(!i.ok){const o=c&&typeof c=="object"&&"error"in c?String(c.error):i.statusText||`HTTP ${i.status}`;throw new he(i.status,o)}return{status:i.status,data:c}}async publish(e){this.assertHubLoggedIn();const a=e.fileSizeBytes??(e.fileBase64?be(e.fileBase64):0);if(a>O)throw new fe(a,O);const l={localDeliverableId:e.localId,visibility:e.visibility,title:e.title,summary:e.summary,tags:e.tags,filename:e.filename,format:e.format,producerAgent:{id:e.producerAgent.id,name:e.producerAgent.name,source:e.producerAgent.source}};e.content&&(l.content=e.content),e.fileBase64&&(l.fileBase64=e.fileBase64);const{data:s}=await this.doFetch("/deliverables/publish",{method:"POST",body:JSON.stringify(l)});return V(s,this.hubOrigin)}async pollStatus(e){this.assertHubLoggedIn();const{data:a}=await this.doFetch(`/deliverables/status?localId=${encodeURIComponent(e)}`,{method:"GET"});return V(a,this.hubOrigin)}async listMine(){this.assertHubLoggedIn();const{data:e}=await this.doFetch("/deliverables/mine",{method:"GET"}),a=e&&typeof e=="object"?e:{};return(Array.isArray(a.shares)?a.shares:[]).map(s=>V(s,this.hubOrigin))}async revoke(e){this.assertHubLoggedIn();const{data:a}=await this.doFetch("/deliverables/revoke",{method:"POST",body:JSON.stringify({localId:e})});return{...V(a,this.hubOrigin),status:"revoked",url:null}}}function me(t,e){return new pe({getHubToken:t,hubUrl:e,proxyBasePath:"/api/hub"})}const ge=/\.(png|jpe?g|gif|webp|svg|bmp|avif|ico)$/i,xe=/\.(mp4|webm|mp3|wav|ogg|m4a|mov|avi|mkv|flac)$/i;function K(t){return ge.test(t)?"image":xe.test(t)?"media":"other"}function ye(t){return t.replace(/^file:\/\//i,"").replace(/^file:/i,"")}function G(t){const e=t.match(/!?\[[^\]]*\]\(([^)]+)\)/);if(e)return e[1].trim().split(/\s+(?="|')/)[0].trim()||null;const a=t.match(/(?:src|href|poster)\s*=\s*["']([^"']+)["']/i);return a?a[1]:null}function X(t){return!t||/^(https?:|data:|mailto:|tel:|#)/i.test(t)||t.startsWith("//")?!1:(t.startsWith("/api/files/"),!0)}function J(t,e){if(!t)return null;const a=t.trim(),l=a.match(/^\/api\/files\/(?:image|stream|preview)\?path=([^&]+)/i);if(l)try{return decodeURIComponent(l[1])||null}catch{return l[1]||null}return/^file:\/\//i.test(a)?ye(a).replace(/\\/g,"/"):/^[a-zA-Z]:[\\/]/.test(a)?a.replace(/\\/g,"/"):a.startsWith("/")?a:e&&(a.startsWith("./")||a.startsWith("../")||!a.includes("://"))?`${e.replace(/\\/g,"/").replace(/\/+$/,"")}/${a.replace(/^\.\//,"").replace(/\\/g,"/")}`:null}function ve(t,e){const a=[],l=new Set,s=/!?\[[^\]]*\]\(([^)\s]+(?:\s+["'][^"']*["'])?)\)/g;for(const c of t.matchAll(s)){const o=c[0],d=G(o);if(!d||!X(d))continue;const h=J(d,e);!h||l.has(o)||(l.add(o),a.push({raw:o,localPath:h,kind:K(h.split("?")[0])}))}const i=/<[a-zA-Z][^>]*(?:src|href|poster)\s*=\s*["'][^"']+["'][^>]*>/gi;for(const c of t.matchAll(i)){const o=c[0],d=G(o);if(!d||!X(d))continue;const h=J(d,e);!h||l.has(o)||(l.add(o),a.push({raw:o,localPath:h,kind:K(h.split("?")[0])}))}return{refs:a,baseDir:e??""}}function ke(t,e){let a=t;for(const[l,s]of e){const i=we(l,s);a=a.split(l).join(i)}return a}function we(t,e){const a=t.match(/^(!?\[[^\]]*\])\([^)]*\)$/);if(a)return`${a[1]}(${e})`;const l=t.match(/(src|href|poster)(\s*=\s*)(["'])[^"']*\3/i);return l?t.replace(/(src|href|poster)(\s*=\s*)(["'])[^"']*\3/i,`${l[1]}${l[2]}${l[3]}${e}${l[3]}`):e}function je(t,e){return/^https?:\/\//i.test(t)?t:`${e.replace(/\/+$/,"")}${t.startsWith("/")?"":"/"}${t}`}function Ne(t,e,a){const l=new Map,s=new Map(t.map(i=>[i.localPath,i]));for(const i of e){if(!i.key)continue;const c=s.get(i.key);!c||!i.url||l.set(c.raw,je(i.url,a))}return l}async function He(t){try{const e=N.files.streamUrl(t),a=await fetch(e).then(d=>d.ok?d.blob():null);if(!a)return null;const l=await a.arrayBuffer(),s=new Uint8Array(l);let i="";const c=32768;for(let d=0;d<s.length;d+=c)i+=String.fromCharCode.apply(null,Array.from(s.subarray(d,d+c)));const o=t.split("/").pop()||"media";return{base64:btoa(i),filename:o}}catch{return null}}async function Ie(t,e){const a=new Map;if(t.length===0)return a;const l=[];for(const c of t){const o=await He(c.localPath);o&&l.push({key:c.localPath,filename:o.filename,base64:o.base64})}if(l.length===0)return a;const{files:s,errors:i}=await A.uploadMediaBatch(l);return i.length>0&&console.warn("[deliverable-share] media upload errors:",i),Ne(t,s,e)}async function Se(t,e,a){if(!t||e==="directory"||t.startsWith("http://")||t.startsWith("https://"))return{};try{const l=await N.files.preview(t);if((l.type==="text"||l.type==="markdown"||l.type==="html"||l.type==="json"||l.type==="csv")&&typeof l.content=="string"){if(!(l.type==="markdown"||l.type==="html"))return{content:l.content};const i=t.replace(/[/\\]/g,"/").split("/").slice(0,-1).join("/"),{refs:c}=ve(l.content,i);if(c.length===0)return{content:l.content};const o=await Ie(c,a);return o.size===0?{content:l.content}:{content:ke(l.content,o),uploadedMedia:o.size}}if(l.type==="image"||l.type==="audio"||l.type==="video"||l.type==="binary"){const s=l.streamUrl||(l.path?N.files.streamUrl(l.path):N.files.streamUrl(t)),c=await(await fetch(s).then(f=>f.blob())).arrayBuffer(),o=new Uint8Array(c);let d="";const h=32768;for(let f=0;f<o.length;f+=h)d+=String.fromCharCode.apply(null,Array.from(o.subarray(f,f+h)));return{fileBase64:btoa(d)}}return{}}catch{return{}}}function Ve({item:t,onClose:e,onShared:a,service:l}){const{t:s}=ce(["deliverables","common"]),i=u.useMemo(()=>l??me(de,A.getUrl()),[l]),[c,o]=u.useState(()=>i?i.isHubLoggedIn():null),[d,h]=u.useState(!1),[f,p]=u.useState(()=>{const n=t.shareStatus;return n==="published"?"published":n==="pending_review"?"pending_review":n==="rejected"?"rejected":"form"}),[m,B]=u.useState("public"),[I,Y]=u.useState(t.title||""),[C,q]=u.useState(t.summary||""),[g,$]=u.useState(Array.isArray(t.tags)?[...t.tags]:[]),[k,M]=u.useState(""),[L,Q]=u.useState(null),[R,P]=u.useState(!1),[S,x]=u.useState(null),U=u.useRef(a);U.current=a;const y=u.useCallback(n=>{Q(n);const b=n.status;p(b==="published"?"published":b==="rejected"?"rejected":b==="revoked"?"revoked":b==="pending_review"?"pending_review":"form"),U.current?.(n)},[]);u.useEffect(()=>{o(i.isHubLoggedIn())},[i]);const ee=u.useCallback(async()=>{h(!0),x(null);try{await ue({force:!0}),o(i.isHubLoggedIn())}catch{o(i.isHubLoggedIn())}finally{h(!1)}},[i]),E=u.useCallback(()=>{const n=k.trim().replace(/^#/,"");n&&!g.includes(n)&&$(b=>[...b,n]),M("")},[k,g]),te=u.useCallback(n=>{$(b=>b.filter(v=>v!==n))},[]),re=u.useCallback(n=>{n.key==="Enter"||n.key===","?(n.preventDefault(),E()):n.key==="Backspace"&&!k&&g.length&&$(b=>b.slice(0,-1))},[E,k,g.length]),se=u.useCallback(()=>{const n=L?.url??t.shareUrl;n&&navigator.clipboard?.writeText(n).then(()=>{P(!0),setTimeout(()=>P(!1),1500)}).catch(()=>{})},[L,t.shareUrl]),ae=u.useCallback(async()=>{x(null),p("busy");try{const n=t.reference.replace(/[/\\]/g,"/").split("/").pop()||"deliverable",b=A.getUrl(),{content:v,fileBase64:ne,uploadedMedia:W}=await Se(t.reference,t.type,b);W&&console.info(`[deliverable-share] uploaded ${W} local media reference(s) to Hub`);const w=t.agentId??"";let _=w;if(w)try{const{agents:ie}=await N.agents.list(),z=ie.find(oe=>oe.id===w);z&&(_=z.name||w)}catch{}const j=await i.publish({localId:t.id,title:I.trim()||t.title,summary:C.trim(),tags:g,visibility:m,filename:n,format:t.format||"markdown",content:v,fileBase64:ne,producerAgent:{id:w,name:_,source:"local"}});y(j),j.status==="rejected"?x(typeof j.reason=="string"&&j.reason?j.reason:"分享被拒绝"):e()}catch(n){if(p("form"),n instanceof Z){o(!1);return}x(n instanceof H||n instanceof Error?n.message:String(n))}},[i,t,I,C,g,m,y]),le=u.useCallback(async()=>{x(null);try{const n=await i.revoke(t.id);y({...n,status:"revoked",url:null})}catch(n){x(n instanceof H?n.message:String(n))}},[i,t.id,y]),D=u.useCallback(()=>{p("form"),x(null)},[]);u.useEffect(()=>{if(f!=="pending_review")return;let n=!1;const b=setInterval(async()=>{try{const v=await i.pollStatus(t.id);if(n)return;v.status!=="pending_review"&&y(v)}catch{}},8e3);return()=>{n=!0,clearInterval(b)}},[f,i,t.id,y]),u.useEffect(()=>{const n=b=>{b.key==="Escape"&&e()};return window.addEventListener("keydown",n),()=>window.removeEventListener("keydown",n)},[e]);const T=m==="link",F=L?.url??t.shareUrl;return r.jsxs("div",{className:"fixed inset-0 z-50 flex items-center justify-center p-4",onClick:e,children:[r.jsx("div",{className:"absolute inset-0 bg-black/50 backdrop-blur-sm"}),r.jsxs("div",{className:"relative bg-surface-primary rounded-2xl shadow-2xl border border-border-default w-full max-w-md max-h-[85vh] overflow-y-auto",onClick:n=>n.stopPropagation(),children:[r.jsxs("div",{className:"sticky top-0 bg-surface-primary/95 backdrop-blur-sm border-b border-border-default px-5 py-4 flex items-center justify-between rounded-t-2xl z-10",children:[r.jsx("h3",{className:"text-base font-semibold text-fg-primary",children:s("deliverables:share.title",{defaultValue:"分享到 Markus Hub"})}),r.jsx("button",{onClick:e,className:"p-1.5 rounded-lg hover:bg-surface-overlay transition-colors text-fg-tertiary hover:text-fg-primary",children:r.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[r.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),r.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]}),r.jsx("div",{className:"px-5 py-4 space-y-4",children:c===!1?r.jsxs("div",{className:"space-y-4 py-2",children:[r.jsxs("div",{className:"flex items-start gap-3 rounded-xl bg-amber-500/10 border border-amber-500/25 p-3",children:[r.jsx("span",{className:"text-lg",children:"🔑"}),r.jsx("p",{className:"text-sm text-fg-secondary",children:s("deliverables:share.needHubLogin",{defaultValue:"需登录 Markus Hub 账号后才能分享产出物。"})})]}),r.jsx("button",{onClick:()=>{ee()},disabled:d,className:"w-full px-3 py-2 text-sm font-medium rounded-lg bg-brand-600 text-white hover:bg-brand-500 transition-colors disabled:opacity-60",children:d?s("deliverables:share.loggingIn",{defaultValue:"正在打开登录…"}):s("deliverables:share.loginHub",{defaultValue:"登录 Markus Hub 账号"})}),r.jsx("p",{className:"text-[11px] text-fg-tertiary",children:s("deliverables:share.loginHint",{defaultValue:"解锁后将支持一键公开/链接分享产出物。"})})]}):r.jsx(r.Fragment,{children:f==="published"?r.jsxs("div",{className:"space-y-3",children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("span",{className:"px-2 py-0.5 text-[11px] rounded-full bg-green-500/15 text-green-500 font-medium",children:s("deliverables:share.published",{defaultValue:"已发布"})}),r.jsx("span",{className:"text-[11px] text-fg-tertiary",children:m==="link"?s("deliverables:share.linkVisibility",{defaultValue:"有链接可见"}):s("deliverables:share.publicVisibility",{defaultValue:"公开"})})]}),F?r.jsxs("div",{className:"flex items-center gap-2 bg-surface-elevated rounded-lg px-3 py-2",children:[r.jsx("span",{className:"text-xs text-fg-secondary font-mono break-all flex-1 select-all",children:F}),r.jsx("button",{onClick:se,className:`px-2 py-1 text-[10px] rounded transition-colors shrink-0 ${R?"bg-green-500/20 text-green-500":"bg-brand-600/20 text-brand-500 hover:bg-brand-600/30"}`,children:R?s("common:copied",{defaultValue:"已复制"}):s("common:copy",{defaultValue:"复制链接"})})]}):r.jsx("p",{className:"text-xs text-fg-tertiary",children:s("deliverables:share.urlPending",{defaultValue:"链接生成中,稍后刷新查看…"})}),r.jsx("button",{onClick:()=>{le()},className:"w-full px-3 py-2 text-xs font-medium rounded-lg text-red-500 border border-red-500/30 hover:bg-red-500/10 transition-colors",children:s("deliverables:share.revoke",{defaultValue:"取消分享"})})]}):f==="pending_review"?r.jsxs("div",{className:"space-y-3",children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("span",{className:"w-2.5 h-2.5 rounded-full bg-amber-500 animate-pulse"}),r.jsx("span",{className:"px-2 py-0.5 text-[11px] rounded-full bg-amber-500/15 text-amber-500 font-medium",children:s("deliverables:share.pendingReview",{defaultValue:"审核中"})})]}),r.jsx("p",{className:"text-sm text-fg-secondary",children:s("deliverables:share.pendingHint",{defaultValue:"你的产出物已提交审核,通过后将生成可分享链接。"})})]}):f==="rejected"?r.jsxs("div",{className:"space-y-3",children:[r.jsx("div",{className:"flex items-center gap-2",children:r.jsx("span",{className:"px-2 py-0.5 text-[11px] rounded-full bg-red-500/15 text-red-500 font-medium",children:s("deliverables:share.rejected",{defaultValue:"已拒绝"})})}),S&&r.jsx("div",{className:"rounded-lg bg-red-500/10 border border-red-500/25 px-3 py-2 text-xs text-red-500",children:S}),r.jsx("button",{onClick:D,className:"w-full px-3 py-2 text-sm font-medium rounded-lg bg-brand-600 text-white hover:bg-brand-500 transition-colors",children:s("deliverables:share.resubmit",{defaultValue:"重新提交"})})]}):f==="revoked"?r.jsxs("div",{className:"space-y-3",children:[r.jsx("p",{className:"text-sm text-fg-secondary",children:s("deliverables:share.revoked",{defaultValue:"已取消分享,该产出物不再公开可访问。"})}),r.jsx("button",{onClick:D,className:"w-full px-3 py-2 text-sm font-medium rounded-lg bg-brand-600 text-white hover:bg-brand-500 transition-colors",children:s("deliverables:share.shareAgain",{defaultValue:"重新分享"})})]}):r.jsxs(r.Fragment,{children:[r.jsxs("div",{className:"space-y-2",children:[r.jsx("div",{className:"text-[10px] text-fg-tertiary uppercase tracking-wider font-medium",children:s("deliverables:share.visibility",{defaultValue:"可见性"})}),r.jsxs("label",{className:`flex items-start gap-3 rounded-xl border p-3 cursor-pointer transition-colors ${T?"border-border-default hover:bg-surface-elevated":"border-brand-500/50 bg-brand-500/5"}`,children:[r.jsx("input",{type:"radio",name:"visibility",checked:!T,onChange:()=>B("public"),className:"mt-0.5 accent-brand-500"}),r.jsxs("span",{className:"space-y-0.5",children:[r.jsx("span",{className:"block text-sm font-medium text-fg-primary",children:s("deliverables:share.public",{defaultValue:"公开(所有人可见 + 搜索引擎)"})}),r.jsx("span",{className:"block text-[11px] text-fg-tertiary",children:s("deliverables:share.publicHint",{defaultValue:"公开产出物需经 Hub 审核后发布,发布后所有人可见并参与搜索"})})]})]}),r.jsxs("label",{className:`flex items-start gap-3 rounded-xl border p-3 cursor-pointer transition-colors ${T?"border-brand-500/50 bg-brand-500/5":"border-border-default hover:bg-surface-elevated"}`,children:[r.jsx("input",{type:"radio",name:"visibility",checked:T,onChange:()=>B("link"),className:"mt-0.5 accent-brand-500"}),r.jsxs("span",{className:"space-y-0.5",children:[r.jsx("span",{className:"block text-sm font-medium text-fg-primary",children:s("deliverables:share.link",{defaultValue:"有链接可见"})}),r.jsx("span",{className:"block text-[11px] text-fg-tertiary",children:s("deliverables:share.linkHint",{defaultValue:"仅获得链接的人可查看,不参与搜索引擎;同样需经 Hub 审核"})})]})]})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("div",{className:"text-[10px] text-fg-tertiary uppercase tracking-wider font-medium",children:s("deliverables:share.titleField",{defaultValue:"标题"})}),r.jsx("input",{value:I,onChange:n=>Y(n.target.value),placeholder:s("deliverables:share.titlePlaceholder",{defaultValue:"清晰、可检索的标题"}),className:"w-full px-3 py-2 text-sm rounded-lg bg-surface-elevated border border-border-default focus:border-brand-500/60 outline-none"})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("div",{className:"text-[10px] text-fg-tertiary uppercase tracking-wider font-medium",children:s("deliverables:share.summary",{defaultValue:"摘要"})}),r.jsx("textarea",{value:C,onChange:n=>q(n.target.value),rows:3,placeholder:s("deliverables:share.summaryPlaceholder",{defaultValue:"简要描述该产出物…"}),className:"w-full px-3 py-2 text-sm rounded-lg bg-surface-elevated border border-border-default focus:border-brand-500/60 outline-none resize-y"})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("div",{className:"text-[10px] text-fg-tertiary uppercase tracking-wider font-medium",children:s("deliverables:share.tags",{defaultValue:"标签"})}),r.jsx("div",{className:"flex flex-wrap gap-1.5 mb-1.5",children:g.map(n=>r.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 text-[11px] bg-surface-elevated rounded-md text-fg-secondary",children:[n,r.jsx("button",{onClick:()=>te(n),className:"text-fg-tertiary hover:text-red-500","aria-label":"remove",children:r.jsxs("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",children:[r.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),r.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]},n))}),r.jsx("input",{value:k,onChange:n=>M(n.target.value),onKeyDown:re,onBlur:E,placeholder:s("deliverables:share.tagsPlaceholder",{defaultValue:"输入标签后回车添加"}),className:"w-full px-3 py-2 text-sm rounded-lg bg-surface-elevated border border-border-default focus:border-brand-500/60 outline-none"})]}),S&&r.jsx("div",{className:"rounded-lg bg-red-500/10 border border-red-500/25 px-3 py-2 text-xs text-red-500",children:S}),r.jsxs("button",{type:"button",onClick:()=>{ae()},disabled:f==="busy"||!I.trim(),className:"w-full px-3 py-2.5 text-sm font-medium rounded-lg bg-brand-600 text-white hover:bg-brand-500 transition-colors disabled:opacity-60 flex items-center justify-center gap-2",children:[f==="busy"&&r.jsxs("svg",{className:"animate-spin",width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",children:[r.jsx("circle",{cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"3",opacity:"0.25"}),r.jsx("path",{d:"M22 12a10 10 0 0 0-10-10",stroke:"currentColor",strokeWidth:"3",strokeLinecap:"round"})]}),f==="busy"?s("deliverables:share.sharing",{defaultValue:"分享中…"}):s("deliverables:share.shareToHub",{defaultValue:"分享到 Hub"})]})]})})})]})]})}export{Ve as D,me as c};
1
+ import{u as ce,r as u,h as A,o as de,t as ue,l as N,j as r}from"./index-CiAGgfZx.js";const O=50*1024*1024;class H extends Error{constructor(e){super(e),this.name="DeliverableShareError"}}class Z extends H{constructor(){super("需要登录 Markus Hub 账号后才能分享产出物。"),this.name="NotLoggedIntoHubError"}}class fe extends H{bytes;limit;constructor(e,a){super(`产出物文件大小 ${e} 字节超过上限 ${a} 字节(50MB),请压缩或拒绝分享。`),this.name="DeliverableTooLargeError",this.bytes=e,this.limit=a}}class he extends H{status;constructor(e,a){super(`Hub 请求失败 (HTTP ${e}): ${a}`),this.name="HubApiError",this.status=e}}function be(t){const e=t.replace(/\s+/g,"");if(!e)return 0;let a=0;return e.endsWith("==")?a=2:e.endsWith("=")&&(a=1),Math.floor(e.length*3/4)-a}function V(t,e){const a=t&&typeof t=="object"?t:{},l=a.share??a.deliverable??{},s=m=>a[m]??l[m],i=s("id")??s("shareId")??"",c=s("slug"),o=c!=null?String(c):void 0,d=s("url")??s("shareUrl");let h=null;d!=null?h=String(d):o&&e&&(h=`${e.replace(/\/+$/,"")}/deliverable/${encodeURIComponent(o)}`);const f=s("reason")??s("rejectNote"),p=s("localDeliverableId")??s("localId");return{id:String(i),slug:o,visibility:s("visibility")??"public",status:s("status")??"pending_review",url:h,reason:f!=null?String(f):null,localId:p!=null?String(p):null}}class pe{basePath;fetchImpl;hubOrigin;constructor(e){this.getHubToken=e.getHubToken,this.hubOrigin=e.hubUrl,this.basePath=(e.proxyBasePath??"/api/hub").replace(/\/+$/,""),this.fetchImpl=e.fetch??(globalThis.fetch?globalThis.fetch.bind(globalThis):(()=>{throw new Error("fetch unavailable")}))}getHubToken;isHubLoggedIn(){return!!this.getHubToken()}assertHubLoggedIn(){if(!this.getHubToken())throw new Z}async doFetch(e,a){const l=this.getHubToken(),s={"Content-Type":"application/json",...a.headers};l&&(s.Authorization=`Bearer ${l}`);const i=await this.fetchImpl(`${this.basePath}${e}`,{...a,headers:s,credentials:"include"});let c=null;try{c=await i.json()}catch{c=null}if(!i.ok){const o=c&&typeof c=="object"&&"error"in c?String(c.error):i.statusText||`HTTP ${i.status}`;throw new he(i.status,o)}return{status:i.status,data:c}}async publish(e){this.assertHubLoggedIn();const a=e.fileSizeBytes??(e.fileBase64?be(e.fileBase64):0);if(a>O)throw new fe(a,O);const l={localDeliverableId:e.localId,visibility:e.visibility,title:e.title,summary:e.summary,tags:e.tags,filename:e.filename,format:e.format,producerAgent:{id:e.producerAgent.id,name:e.producerAgent.name,source:e.producerAgent.source}};e.content&&(l.content=e.content),e.fileBase64&&(l.fileBase64=e.fileBase64);const{data:s}=await this.doFetch("/deliverables/publish",{method:"POST",body:JSON.stringify(l)});return V(s,this.hubOrigin)}async pollStatus(e){this.assertHubLoggedIn();const{data:a}=await this.doFetch(`/deliverables/status?localId=${encodeURIComponent(e)}`,{method:"GET"});return V(a,this.hubOrigin)}async listMine(){this.assertHubLoggedIn();const{data:e}=await this.doFetch("/deliverables/mine",{method:"GET"}),a=e&&typeof e=="object"?e:{};return(Array.isArray(a.shares)?a.shares:[]).map(s=>V(s,this.hubOrigin))}async revoke(e){this.assertHubLoggedIn();const{data:a}=await this.doFetch("/deliverables/revoke",{method:"POST",body:JSON.stringify({localId:e})});return{...V(a,this.hubOrigin),status:"revoked",url:null}}}function me(t,e){return new pe({getHubToken:t,hubUrl:e,proxyBasePath:"/api/hub"})}const ge=/\.(png|jpe?g|gif|webp|svg|bmp|avif|ico)$/i,xe=/\.(mp4|webm|mp3|wav|ogg|m4a|mov|avi|mkv|flac)$/i;function K(t){return ge.test(t)?"image":xe.test(t)?"media":"other"}function ye(t){return t.replace(/^file:\/\//i,"").replace(/^file:/i,"")}function G(t){const e=t.match(/!?\[[^\]]*\]\(([^)]+)\)/);if(e)return e[1].trim().split(/\s+(?="|')/)[0].trim()||null;const a=t.match(/(?:src|href|poster)\s*=\s*["']([^"']+)["']/i);return a?a[1]:null}function X(t){return!t||/^(https?:|data:|mailto:|tel:|#)/i.test(t)||t.startsWith("//")?!1:(t.startsWith("/api/files/"),!0)}function J(t,e){if(!t)return null;const a=t.trim(),l=a.match(/^\/api\/files\/(?:image|stream|preview)\?path=([^&]+)/i);if(l)try{return decodeURIComponent(l[1])||null}catch{return l[1]||null}return/^file:\/\//i.test(a)?ye(a).replace(/\\/g,"/"):/^[a-zA-Z]:[\\/]/.test(a)?a.replace(/\\/g,"/"):a.startsWith("/")?a:e&&(a.startsWith("./")||a.startsWith("../")||!a.includes("://"))?`${e.replace(/\\/g,"/").replace(/\/+$/,"")}/${a.replace(/^\.\//,"").replace(/\\/g,"/")}`:null}function ve(t,e){const a=[],l=new Set,s=/!?\[[^\]]*\]\(([^)\s]+(?:\s+["'][^"']*["'])?)\)/g;for(const c of t.matchAll(s)){const o=c[0],d=G(o);if(!d||!X(d))continue;const h=J(d,e);!h||l.has(o)||(l.add(o),a.push({raw:o,localPath:h,kind:K(h.split("?")[0])}))}const i=/<[a-zA-Z][^>]*(?:src|href|poster)\s*=\s*["'][^"']+["'][^>]*>/gi;for(const c of t.matchAll(i)){const o=c[0],d=G(o);if(!d||!X(d))continue;const h=J(d,e);!h||l.has(o)||(l.add(o),a.push({raw:o,localPath:h,kind:K(h.split("?")[0])}))}return{refs:a,baseDir:e??""}}function ke(t,e){let a=t;for(const[l,s]of e){const i=we(l,s);a=a.split(l).join(i)}return a}function we(t,e){const a=t.match(/^(!?\[[^\]]*\])\([^)]*\)$/);if(a)return`${a[1]}(${e})`;const l=t.match(/(src|href|poster)(\s*=\s*)(["'])[^"']*\3/i);return l?t.replace(/(src|href|poster)(\s*=\s*)(["'])[^"']*\3/i,`${l[1]}${l[2]}${l[3]}${e}${l[3]}`):e}function je(t,e){return/^https?:\/\//i.test(t)?t:`${e.replace(/\/+$/,"")}${t.startsWith("/")?"":"/"}${t}`}function Ne(t,e,a){const l=new Map,s=new Map(t.map(i=>[i.localPath,i]));for(const i of e){if(!i.key)continue;const c=s.get(i.key);!c||!i.url||l.set(c.raw,je(i.url,a))}return l}async function He(t){try{const e=N.files.streamUrl(t),a=await fetch(e).then(d=>d.ok?d.blob():null);if(!a)return null;const l=await a.arrayBuffer(),s=new Uint8Array(l);let i="";const c=32768;for(let d=0;d<s.length;d+=c)i+=String.fromCharCode.apply(null,Array.from(s.subarray(d,d+c)));const o=t.split("/").pop()||"media";return{base64:btoa(i),filename:o}}catch{return null}}async function Ie(t,e){const a=new Map;if(t.length===0)return a;const l=[];for(const c of t){const o=await He(c.localPath);o&&l.push({key:c.localPath,filename:o.filename,base64:o.base64})}if(l.length===0)return a;const{files:s,errors:i}=await A.uploadMediaBatch(l);return i.length>0&&console.warn("[deliverable-share] media upload errors:",i),Ne(t,s,e)}async function Se(t,e,a){if(!t||e==="directory"||t.startsWith("http://")||t.startsWith("https://"))return{};try{const l=await N.files.preview(t);if((l.type==="text"||l.type==="markdown"||l.type==="html"||l.type==="json"||l.type==="csv")&&typeof l.content=="string"){if(!(l.type==="markdown"||l.type==="html"))return{content:l.content};const i=t.replace(/[/\\]/g,"/").split("/").slice(0,-1).join("/"),{refs:c}=ve(l.content,i);if(c.length===0)return{content:l.content};const o=await Ie(c,a);return o.size===0?{content:l.content}:{content:ke(l.content,o),uploadedMedia:o.size}}if(l.type==="image"||l.type==="audio"||l.type==="video"||l.type==="binary"){const s=l.streamUrl||(l.path?N.files.streamUrl(l.path):N.files.streamUrl(t)),c=await(await fetch(s).then(f=>f.blob())).arrayBuffer(),o=new Uint8Array(c);let d="";const h=32768;for(let f=0;f<o.length;f+=h)d+=String.fromCharCode.apply(null,Array.from(o.subarray(f,f+h)));return{fileBase64:btoa(d)}}return{}}catch{return{}}}function Ve({item:t,onClose:e,onShared:a,service:l}){const{t:s}=ce(["deliverables","common"]),i=u.useMemo(()=>l??me(de,A.getUrl()),[l]),[c,o]=u.useState(()=>i?i.isHubLoggedIn():null),[d,h]=u.useState(!1),[f,p]=u.useState(()=>{const n=t.shareStatus;return n==="published"?"published":n==="pending_review"?"pending_review":n==="rejected"?"rejected":"form"}),[m,B]=u.useState("public"),[I,Y]=u.useState(t.title||""),[C,q]=u.useState(t.summary||""),[g,$]=u.useState(Array.isArray(t.tags)?[...t.tags]:[]),[k,M]=u.useState(""),[L,Q]=u.useState(null),[R,P]=u.useState(!1),[S,x]=u.useState(null),U=u.useRef(a);U.current=a;const y=u.useCallback(n=>{Q(n);const b=n.status;p(b==="published"?"published":b==="rejected"?"rejected":b==="revoked"?"revoked":b==="pending_review"?"pending_review":"form"),U.current?.(n)},[]);u.useEffect(()=>{o(i.isHubLoggedIn())},[i]);const ee=u.useCallback(async()=>{h(!0),x(null);try{await ue({force:!0}),o(i.isHubLoggedIn())}catch{o(i.isHubLoggedIn())}finally{h(!1)}},[i]),E=u.useCallback(()=>{const n=k.trim().replace(/^#/,"");n&&!g.includes(n)&&$(b=>[...b,n]),M("")},[k,g]),te=u.useCallback(n=>{$(b=>b.filter(v=>v!==n))},[]),re=u.useCallback(n=>{n.key==="Enter"||n.key===","?(n.preventDefault(),E()):n.key==="Backspace"&&!k&&g.length&&$(b=>b.slice(0,-1))},[E,k,g.length]),se=u.useCallback(()=>{const n=L?.url??t.shareUrl;n&&navigator.clipboard?.writeText(n).then(()=>{P(!0),setTimeout(()=>P(!1),1500)}).catch(()=>{})},[L,t.shareUrl]),ae=u.useCallback(async()=>{x(null),p("busy");try{const n=t.reference.replace(/[/\\]/g,"/").split("/").pop()||"deliverable",b=A.getUrl(),{content:v,fileBase64:ne,uploadedMedia:W}=await Se(t.reference,t.type,b);W&&console.info(`[deliverable-share] uploaded ${W} local media reference(s) to Hub`);const w=t.agentId??"";let _=w;if(w)try{const{agents:ie}=await N.agents.list(),z=ie.find(oe=>oe.id===w);z&&(_=z.name||w)}catch{}const j=await i.publish({localId:t.id,title:I.trim()||t.title,summary:C.trim(),tags:g,visibility:m,filename:n,format:t.format||"markdown",content:v,fileBase64:ne,producerAgent:{id:w,name:_,source:"local"}});y(j),j.status==="rejected"?x(typeof j.reason=="string"&&j.reason?j.reason:"分享被拒绝"):e()}catch(n){if(p("form"),n instanceof Z){o(!1);return}x(n instanceof H||n instanceof Error?n.message:String(n))}},[i,t,I,C,g,m,y]),le=u.useCallback(async()=>{x(null);try{const n=await i.revoke(t.id);y({...n,status:"revoked",url:null})}catch(n){x(n instanceof H?n.message:String(n))}},[i,t.id,y]),D=u.useCallback(()=>{p("form"),x(null)},[]);u.useEffect(()=>{if(f!=="pending_review")return;let n=!1;const b=setInterval(async()=>{try{const v=await i.pollStatus(t.id);if(n)return;v.status!=="pending_review"&&y(v)}catch{}},8e3);return()=>{n=!0,clearInterval(b)}},[f,i,t.id,y]),u.useEffect(()=>{const n=b=>{b.key==="Escape"&&e()};return window.addEventListener("keydown",n),()=>window.removeEventListener("keydown",n)},[e]);const T=m==="link",F=L?.url??t.shareUrl;return r.jsxs("div",{className:"fixed inset-0 z-50 flex items-center justify-center p-4",onClick:e,children:[r.jsx("div",{className:"absolute inset-0 bg-black/50 backdrop-blur-sm"}),r.jsxs("div",{className:"relative bg-surface-primary rounded-2xl shadow-2xl border border-border-default w-full max-w-md max-h-[85vh] overflow-y-auto",onClick:n=>n.stopPropagation(),children:[r.jsxs("div",{className:"sticky top-0 bg-surface-primary/95 backdrop-blur-sm border-b border-border-default px-5 py-4 flex items-center justify-between rounded-t-2xl z-10",children:[r.jsx("h3",{className:"text-base font-semibold text-fg-primary",children:s("deliverables:share.title",{defaultValue:"分享到 Markus Hub"})}),r.jsx("button",{onClick:e,className:"p-1.5 rounded-lg hover:bg-surface-overlay transition-colors text-fg-tertiary hover:text-fg-primary",children:r.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[r.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),r.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]}),r.jsx("div",{className:"px-5 py-4 space-y-4",children:c===!1?r.jsxs("div",{className:"space-y-4 py-2",children:[r.jsxs("div",{className:"flex items-start gap-3 rounded-xl bg-amber-500/10 border border-amber-500/25 p-3",children:[r.jsx("span",{className:"text-lg",children:"🔑"}),r.jsx("p",{className:"text-sm text-fg-secondary",children:s("deliverables:share.needHubLogin",{defaultValue:"需登录 Markus Hub 账号后才能分享产出物。"})})]}),r.jsx("button",{onClick:()=>{ee()},disabled:d,className:"w-full px-3 py-2 text-sm font-medium rounded-lg bg-brand-600 text-white hover:bg-brand-500 transition-colors disabled:opacity-60",children:d?s("deliverables:share.loggingIn",{defaultValue:"正在打开登录…"}):s("deliverables:share.loginHub",{defaultValue:"登录 Markus Hub 账号"})}),r.jsx("p",{className:"text-[11px] text-fg-tertiary",children:s("deliverables:share.loginHint",{defaultValue:"解锁后将支持一键公开/链接分享产出物。"})})]}):r.jsx(r.Fragment,{children:f==="published"?r.jsxs("div",{className:"space-y-3",children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("span",{className:"px-2 py-0.5 text-[11px] rounded-full bg-green-500/15 text-green-500 font-medium",children:s("deliverables:share.published",{defaultValue:"已发布"})}),r.jsx("span",{className:"text-[11px] text-fg-tertiary",children:m==="link"?s("deliverables:share.linkVisibility",{defaultValue:"有链接可见"}):s("deliverables:share.publicVisibility",{defaultValue:"公开"})})]}),F?r.jsxs("div",{className:"flex items-center gap-2 bg-surface-elevated rounded-lg px-3 py-2",children:[r.jsx("span",{className:"text-xs text-fg-secondary font-mono break-all flex-1 select-all",children:F}),r.jsx("button",{onClick:se,className:`px-2 py-1 text-[10px] rounded transition-colors shrink-0 ${R?"bg-green-500/20 text-green-500":"bg-brand-600/20 text-brand-500 hover:bg-brand-600/30"}`,children:R?s("common:copied",{defaultValue:"已复制"}):s("common:copy",{defaultValue:"复制链接"})})]}):r.jsx("p",{className:"text-xs text-fg-tertiary",children:s("deliverables:share.urlPending",{defaultValue:"链接生成中,稍后刷新查看…"})}),r.jsx("button",{onClick:()=>{le()},className:"w-full px-3 py-2 text-xs font-medium rounded-lg text-red-500 border border-red-500/30 hover:bg-red-500/10 transition-colors",children:s("deliverables:share.revoke",{defaultValue:"取消分享"})})]}):f==="pending_review"?r.jsxs("div",{className:"space-y-3",children:[r.jsxs("div",{className:"flex items-center gap-2",children:[r.jsx("span",{className:"w-2.5 h-2.5 rounded-full bg-amber-500 animate-pulse"}),r.jsx("span",{className:"px-2 py-0.5 text-[11px] rounded-full bg-amber-500/15 text-amber-500 font-medium",children:s("deliverables:share.pendingReview",{defaultValue:"审核中"})})]}),r.jsx("p",{className:"text-sm text-fg-secondary",children:s("deliverables:share.pendingHint",{defaultValue:"你的产出物已提交审核,通过后将生成可分享链接。"})})]}):f==="rejected"?r.jsxs("div",{className:"space-y-3",children:[r.jsx("div",{className:"flex items-center gap-2",children:r.jsx("span",{className:"px-2 py-0.5 text-[11px] rounded-full bg-red-500/15 text-red-500 font-medium",children:s("deliverables:share.rejected",{defaultValue:"已拒绝"})})}),S&&r.jsx("div",{className:"rounded-lg bg-red-500/10 border border-red-500/25 px-3 py-2 text-xs text-red-500",children:S}),r.jsx("button",{onClick:D,className:"w-full px-3 py-2 text-sm font-medium rounded-lg bg-brand-600 text-white hover:bg-brand-500 transition-colors",children:s("deliverables:share.resubmit",{defaultValue:"重新提交"})})]}):f==="revoked"?r.jsxs("div",{className:"space-y-3",children:[r.jsx("p",{className:"text-sm text-fg-secondary",children:s("deliverables:share.revoked",{defaultValue:"已取消分享,该产出物不再公开可访问。"})}),r.jsx("button",{onClick:D,className:"w-full px-3 py-2 text-sm font-medium rounded-lg bg-brand-600 text-white hover:bg-brand-500 transition-colors",children:s("deliverables:share.shareAgain",{defaultValue:"重新分享"})})]}):r.jsxs(r.Fragment,{children:[r.jsxs("div",{className:"space-y-2",children:[r.jsx("div",{className:"text-[10px] text-fg-tertiary uppercase tracking-wider font-medium",children:s("deliverables:share.visibility",{defaultValue:"可见性"})}),r.jsxs("label",{className:`flex items-start gap-3 rounded-xl border p-3 cursor-pointer transition-colors ${T?"border-border-default hover:bg-surface-elevated":"border-brand-500/50 bg-brand-500/5"}`,children:[r.jsx("input",{type:"radio",name:"visibility",checked:!T,onChange:()=>B("public"),className:"mt-0.5 accent-brand-500"}),r.jsxs("span",{className:"space-y-0.5",children:[r.jsx("span",{className:"block text-sm font-medium text-fg-primary",children:s("deliverables:share.public",{defaultValue:"公开(所有人可见 + 搜索引擎)"})}),r.jsx("span",{className:"block text-[11px] text-fg-tertiary",children:s("deliverables:share.publicHint",{defaultValue:"公开产出物需经 Hub 审核后发布,发布后所有人可见并参与搜索"})})]})]}),r.jsxs("label",{className:`flex items-start gap-3 rounded-xl border p-3 cursor-pointer transition-colors ${T?"border-brand-500/50 bg-brand-500/5":"border-border-default hover:bg-surface-elevated"}`,children:[r.jsx("input",{type:"radio",name:"visibility",checked:T,onChange:()=>B("link"),className:"mt-0.5 accent-brand-500"}),r.jsxs("span",{className:"space-y-0.5",children:[r.jsx("span",{className:"block text-sm font-medium text-fg-primary",children:s("deliverables:share.link",{defaultValue:"有链接可见"})}),r.jsx("span",{className:"block text-[11px] text-fg-tertiary",children:s("deliverables:share.linkHint",{defaultValue:"仅获得链接的人可查看,不参与搜索引擎;同样需经 Hub 审核"})})]})]})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("div",{className:"text-[10px] text-fg-tertiary uppercase tracking-wider font-medium",children:s("deliverables:share.titleField",{defaultValue:"标题"})}),r.jsx("input",{value:I,onChange:n=>Y(n.target.value),placeholder:s("deliverables:share.titlePlaceholder",{defaultValue:"清晰、可检索的标题"}),className:"w-full px-3 py-2 text-sm rounded-lg bg-surface-elevated border border-border-default focus:border-brand-500/60 outline-none"})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("div",{className:"text-[10px] text-fg-tertiary uppercase tracking-wider font-medium",children:s("deliverables:share.summary",{defaultValue:"摘要"})}),r.jsx("textarea",{value:C,onChange:n=>q(n.target.value),rows:3,placeholder:s("deliverables:share.summaryPlaceholder",{defaultValue:"简要描述该产出物…"}),className:"w-full px-3 py-2 text-sm rounded-lg bg-surface-elevated border border-border-default focus:border-brand-500/60 outline-none resize-y"})]}),r.jsxs("div",{className:"space-y-1.5",children:[r.jsx("div",{className:"text-[10px] text-fg-tertiary uppercase tracking-wider font-medium",children:s("deliverables:share.tags",{defaultValue:"标签"})}),r.jsx("div",{className:"flex flex-wrap gap-1.5 mb-1.5",children:g.map(n=>r.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 text-[11px] bg-surface-elevated rounded-md text-fg-secondary",children:[n,r.jsx("button",{onClick:()=>te(n),className:"text-fg-tertiary hover:text-red-500","aria-label":"remove",children:r.jsxs("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",children:[r.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),r.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]},n))}),r.jsx("input",{value:k,onChange:n=>M(n.target.value),onKeyDown:re,onBlur:E,placeholder:s("deliverables:share.tagsPlaceholder",{defaultValue:"输入标签后回车添加"}),className:"w-full px-3 py-2 text-sm rounded-lg bg-surface-elevated border border-border-default focus:border-brand-500/60 outline-none"})]}),S&&r.jsx("div",{className:"rounded-lg bg-red-500/10 border border-red-500/25 px-3 py-2 text-xs text-red-500",children:S}),r.jsxs("button",{type:"button",onClick:()=>{ae()},disabled:f==="busy"||!I.trim(),className:"w-full px-3 py-2.5 text-sm font-medium rounded-lg bg-brand-600 text-white hover:bg-brand-500 transition-colors disabled:opacity-60 flex items-center justify-center gap-2",children:[f==="busy"&&r.jsxs("svg",{className:"animate-spin",width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",children:[r.jsx("circle",{cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"3",opacity:"0.25"}),r.jsx("path",{d:"M22 12a10 10 0 0 0-10-10",stroke:"currentColor",strokeWidth:"3",strokeLinecap:"round"})]}),f==="busy"?s("deliverables:share.sharing",{defaultValue:"分享中…"}):s("deliverables:share.shareToHub",{defaultValue:"分享到 Hub"})]})]})})})]})]})}export{Ve as D,me as c};