dsh-mnemon-source-memory-spaces 0.5.21 → 0.5.22
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/README.md +8 -2
- package/lib/client.js +1571 -91
- package/lib/contracts.d.ts +78 -2
- package/lib/contracts.js +91 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.js +58 -85
- package/lib/{plugin-DlsNeZbQ.js → plugin-m1PeU1IE.js} +3 -2
- package/lib/space-identity.d.ts +20 -0
- package/lib/space-identity.js +365 -0
- package/lib/testing.js +1 -1
- package/lib/types/client/entities-page.d.ts +10 -0
- package/lib/types/client/explore-page.d.ts +16 -0
- package/lib/types/client/list-page.d.ts +11 -0
- package/lib/types/client/memory-graph.d.ts +13 -0
- package/lib/types/client/overview-page.d.ts +20 -0
- package/lib/types/client/pages.d.ts +7 -76
- package/lib/types/client/persistence-strategy-dialog.d.ts +17 -0
- package/lib/types/client/presentation.d.ts +29 -1
- package/lib/types/client/provider-field.d.ts +24 -0
- package/lib/types/client/provider-settings.d.ts +26 -0
- package/lib/types/client/remember-page.d.ts +15 -0
- package/lib/types/client/settings-client.d.ts +20 -0
- package/lib/types/client/settings.d.ts +26 -0
- package/lib/types/client/ui.d.ts +2 -2
- package/lib/types/client/widgets.d.ts +44 -0
- package/lib/types/client.d.ts +3 -0
- package/lib/types/contracts.d.ts +77 -1
- package/package.json +10 -6
- package/presentation/locales.json +246 -2
package/lib/client.js
CHANGED
|
@@ -4,8 +4,31 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
//#region \0rolldown/runtime.js
|
|
8
|
+
var __create = Object.create;
|
|
9
|
+
var __defProp = Object.defineProperty;
|
|
10
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
11
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
12
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
16
|
+
key = keys[i];
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
18
|
+
get: ((k) => from[k]).bind(null, key),
|
|
19
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
25
|
+
value: mod,
|
|
26
|
+
enumerable: true
|
|
27
|
+
}) : target, mod));
|
|
28
|
+
//#endregion
|
|
7
29
|
let react = require("react");
|
|
8
30
|
let dsh_mnemon_client = require("dsh-mnemon/client");
|
|
31
|
+
dsh_mnemon_client = __toESM(dsh_mnemon_client, 1);
|
|
9
32
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
10
33
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
11
34
|
//#region presentation/locales.json
|
|
@@ -375,7 +398,129 @@ window.__ModuleLoader__.load({
|
|
|
375
398
|
"overview.rediscoveryFailed": "{provider} 无法完成发现:{error}",
|
|
376
399
|
"overview.rediscoveryTimedOut": "{provider} 没有按时响应,稍后可以再次发现。",
|
|
377
400
|
"overview.rediscoveryDismiss": "知道了",
|
|
378
|
-
"overview.newSpace": "新发现"
|
|
401
|
+
"overview.newSpace": "新发现",
|
|
402
|
+
"common.copyId": "复制 ID",
|
|
403
|
+
"common.readOnly": "只读模式",
|
|
404
|
+
"common.activationOnly": "仅可切换激活状态",
|
|
405
|
+
"common.active": "已激活",
|
|
406
|
+
"common.category": "分类",
|
|
407
|
+
"common.importanceLabel": "重要性",
|
|
408
|
+
"common.importance": "重要性 {value}",
|
|
409
|
+
"common.hops": "{count} 跳",
|
|
410
|
+
"common.allCategories": "全部分类",
|
|
411
|
+
"common.memories": "{count} 条记忆",
|
|
412
|
+
"common.edges": "{count} 条连接",
|
|
413
|
+
"card.confirmText": "软删除这条记忆?",
|
|
414
|
+
"card.processing": "处理中…",
|
|
415
|
+
"card.confirmForget": "确认忘记",
|
|
416
|
+
"card.related": "查看关联",
|
|
417
|
+
"card.clone": "基于此新建",
|
|
418
|
+
"card.forget": "忘记",
|
|
419
|
+
"readSources.all": "全部 Provider",
|
|
420
|
+
"readSources.mode.search": "原生检索",
|
|
421
|
+
"readSources.mode.graph": "真实关系图",
|
|
422
|
+
"readSources.mode.projection": "内容投影",
|
|
423
|
+
"readSources.mode.enumerable": "可枚举内容",
|
|
424
|
+
"readSources.mode.query-only": "仅查询",
|
|
425
|
+
"readSources.mode.entities": "实体索引",
|
|
426
|
+
"readSources.mode.unsupported": "不支持",
|
|
427
|
+
"readSources.status.ready": "{count} 条可观察",
|
|
428
|
+
"readSources.status.empty": "已连接 · 暂无内容",
|
|
429
|
+
"readSources.status.query-required": "输入查询后读取",
|
|
430
|
+
"readSources.status.unsupported": "当前表面不可用",
|
|
431
|
+
"readSources.status.unavailable": "连接不可用",
|
|
432
|
+
"readSources.edges": "{count} 条真实关系",
|
|
433
|
+
"readSources.model.mnemon-native": "事实、实体与类型关系",
|
|
434
|
+
"readSources.model.openviking": "目录与分层内容",
|
|
435
|
+
"readSources.model.honcho": "Peer 结论与画像",
|
|
436
|
+
"readSources.model.mem0": "提炼后的语义记忆",
|
|
437
|
+
"readSources.model.hindsight": "记忆单元与知识图",
|
|
438
|
+
"readSources.model.holographic": "可信事实与实体",
|
|
439
|
+
"readSources.model.retaindb": "画像与类型化事实",
|
|
440
|
+
"readSources.model.byterover": "知识树查询",
|
|
441
|
+
"readSources.model.supermemory": "记忆与摄取文档",
|
|
442
|
+
"common.inactive": "未激活",
|
|
443
|
+
"config.providerSecretShow": "显示凭证",
|
|
444
|
+
"config.providerSecretHide": "隐藏凭证",
|
|
445
|
+
"config.providerSecretStoredValue": "已保存凭证",
|
|
446
|
+
"config.providersSpacesOffTitle": "“记忆空间”已关闭",
|
|
447
|
+
"config.providersSpacesOffDetail": "已保存的连接会保留",
|
|
448
|
+
"config.providersSpacesOn": "开启“记忆空间”",
|
|
449
|
+
"config.providersReadOnlyTitle": "dsh-mnemon 当前为只读",
|
|
450
|
+
"config.providersReadOnlyDetail": "writeEnabled 为 false 时,不能启用或停用 Provider。",
|
|
451
|
+
"spaces.offNote": "开启后可配置 Provider 与嵌入",
|
|
452
|
+
"config.providersTitle": "记忆 Provider",
|
|
453
|
+
"config.providersDescription": "Provider 为记忆空间提供存储。启用或保存会同步其中已有的记忆空间;关闭只移除本地映射,不会删除第三方数据。",
|
|
454
|
+
"config.nativeSummary": "官方原生长期记忆与完整关系图",
|
|
455
|
+
"config.officialNative": "官方原生",
|
|
456
|
+
"config.nativeCliMissing": "未安装 CLI(可选)",
|
|
457
|
+
"config.embeddingTitle": "本地向量嵌入",
|
|
458
|
+
"config.embeddingDescription": "让 DSH Host 为每次 Mnemon CLI 调用注入嵌入 Endpoint 与模型;Endpoint 以 /v1 结尾时 Mnemon 自动使用 OpenAI 兼容协议(/v1/embeddings + Bearer 认证),否则使用 Ollama 协议;不以 /v1 结尾的兼容端点可在“协议”下拉中显式指定。",
|
|
459
|
+
"config.embeddingManaged": "由 DSH 管理嵌入配置",
|
|
460
|
+
"config.embeddingManagedHint": "开启后以这里保存的值覆盖 Mnemon 子进程环境;关闭后继续沿用 Host 环境与 Mnemon 默认值。",
|
|
461
|
+
"config.embeddingEndpoint": "嵌入 Endpoint",
|
|
462
|
+
"config.embeddingModel": "嵌入模型",
|
|
463
|
+
"config.embeddingApiKey": "API Key(可选,OpenAI 兼容服务)",
|
|
464
|
+
"config.embeddingApiKeyInvalid": "API Key 不能包含控制字符,且长度不超过 2048。",
|
|
465
|
+
"config.embeddingProtocol": "协议",
|
|
466
|
+
"config.embeddingProtocolAuto": "自动(按 /v1 探测)",
|
|
467
|
+
"config.embeddingProtocolOllama": "Ollama",
|
|
468
|
+
"config.embeddingProtocolOpenai": "OpenAI 兼容",
|
|
469
|
+
"config.embeddingProtocolInvalid": "协议必须是 自动 / Ollama / OpenAI 兼容 之一。",
|
|
470
|
+
"config.embeddingEndpointInvalid": "嵌入 Endpoint 必须是不含凭据、查询参数或片段的 HTTP(S) 绝对 URL。",
|
|
471
|
+
"config.embeddingModelInvalid": "嵌入模型必须包含 1–200 个字符,且不能包含控制字符。",
|
|
472
|
+
"config.embeddingSecurity": "Mnemon 会把记忆与查询正文发送到该 Endpoint;API Key 与其他设置一样保存在 DSH 设置文件中。远程 HTTP 会明文传输,请仅使用受信任的本地地址,或为远程服务配置 HTTPS。",
|
|
473
|
+
"config.embeddingTest": "测试状态",
|
|
474
|
+
"config.embeddingNotTested": "尚未检查嵌入服务的连接与各 Mnemon Native 空间的覆盖率。",
|
|
475
|
+
"config.embeddingTesting": "正在通过 Mnemon 检查嵌入服务与覆盖率…",
|
|
476
|
+
"config.embeddingSaveBeforeTest": "请先保存嵌入配置,再测试实际运行值。",
|
|
477
|
+
"config.embeddingTestUnavailable": "当前 DSH Host 不提供嵌入状态检查。",
|
|
478
|
+
"config.embeddingCliMissing": "测试需要 Mnemon CLI;向量设置只作用于 Mnemon Native。",
|
|
479
|
+
"config.embeddingStatusAvailable": "嵌入服务可用 · {model} · 已嵌入 {embedded}/{total}({coverage})",
|
|
480
|
+
"config.embeddingStatusAvailableWithProtocol": "嵌入服务可用 · {model} · 协议 {protocol} · 已嵌入 {embedded}/{total}({coverage})",
|
|
481
|
+
"config.embeddingStatusUnavailable": "嵌入服务不可达 · {model} · 已嵌入 {embedded}/{total}({coverage})",
|
|
482
|
+
"config.embeddingStatusUnavailableWithProtocol": "嵌入服务不可达 · {model} · 协议 {protocol} · 已嵌入 {embedded}/{total}({coverage})",
|
|
483
|
+
"config.embeddingStatusFailed": "嵌入状态检查失败:{error}",
|
|
484
|
+
"config.embeddingSpaces": "各 Mnemon Native 空间",
|
|
485
|
+
"config.embeddingSpaceCounts": "已嵌入 {embedded}/{total}({coverage})",
|
|
486
|
+
"config.embeddingSpaceFailed": "无法读取:{error}",
|
|
487
|
+
"config.embeddingMissing": "没有向量的记忆不参与语义匹配。",
|
|
488
|
+
"config.embeddingMissingFill": "没有向量的记忆不参与语义匹配;点空间旁的「补齐」即可生成缺少的向量。",
|
|
489
|
+
"config.embeddingMissingOffline": "没有向量的记忆不参与语义匹配;嵌入服务可用后,可以在这里补齐。",
|
|
490
|
+
"config.embeddingSpacesUnread": "无法读取的空间没有计入合计。",
|
|
491
|
+
"config.embeddingFill": "补齐",
|
|
492
|
+
"config.embeddingFilling": "补齐中…",
|
|
493
|
+
"config.embeddingFillLabel": "补齐「{name}」的向量",
|
|
494
|
+
"config.embeddingFillingLabel": "正在补齐「{name}」的向量",
|
|
495
|
+
"config.embeddingFillDone": "已为「{name}」补齐 {filled} 条向量。",
|
|
496
|
+
"config.embeddingFillMore": "已为「{name}」补齐 {filled} 条向量,还缺 {remaining} 条,再点「补齐」继续。",
|
|
497
|
+
"config.embeddingFillPartly": "已为「{name}」补齐 {filled} 条向量;其余 {remaining} 条嵌入服务没有返回向量,可以稍后再点「补齐」。",
|
|
498
|
+
"config.embeddingFillRefused": "嵌入服务没有为「{name}」返回向量,请确认它在运行并提供模型 {model}。",
|
|
499
|
+
"config.embeddingFillFailed": "「{name}」的向量没有补齐:{error}",
|
|
500
|
+
"config.providerGlobalLocation": "全局数据位置",
|
|
501
|
+
"config.providerGlobalLocationHint": "{provider} 默认使用全局范围目录,也可以指定一个自定义位置。",
|
|
502
|
+
"config.providerGlobalLocationWorkspaceHint": "当前使用工作区默认位置;切换到全局范围后可指定自定义位置。",
|
|
503
|
+
"config.providerDefaultLocation": "默认(跟随范围)",
|
|
504
|
+
"config.providerSaveFailed": "配置保存失败:{error}",
|
|
505
|
+
"config.providerServiceTitle": "服务配置",
|
|
506
|
+
"config.providerServiceHint": "供该 Provider 的所有记忆空间复用;启用或保存时会刷新记忆空间目录中的映射与元信息。",
|
|
507
|
+
"config.providerEnableHint": "填写服务配置并保存后,Provider 会启用并同步所有可见记忆空间。",
|
|
508
|
+
"config.providerEnabled": "已启用",
|
|
509
|
+
"config.providerDisabled": "未启用",
|
|
510
|
+
"config.providerDisabledConfigured": "已关闭 · 配置已保留",
|
|
511
|
+
"config.providerNeedsConfiguration": "需要完成配置",
|
|
512
|
+
"config.providerToggleAria": "启用 {provider}",
|
|
513
|
+
"config.providerToggleFailed": "切换失败:{error}",
|
|
514
|
+
"config.enableProvider": "保存并启用",
|
|
515
|
+
"config.providerServiceSaved": "服务配置已保存,记忆空间目录已同步",
|
|
516
|
+
"config.saveProviderService": "保存服务配置",
|
|
517
|
+
"config.providerUnavailable": "当前 DSH 主机不支持 Provider 服务配置。",
|
|
518
|
+
"config.saveScopeBeforeProviders": "存储范围有未保存修改。请先保存范围,再配置对应目录中的 Provider。",
|
|
519
|
+
"config.providerTargetWorkspace": "当前工作区:{workspace};标记“工作区”的 Provider 配置与记忆空间使用此范围。",
|
|
520
|
+
"config.loadingProviders": "正在读取 Provider 配置…",
|
|
521
|
+
"config.providerLoadFailed": "读取 Provider 配置失败:{error}",
|
|
522
|
+
"config.retryProviders": "重试",
|
|
523
|
+
"config.saving": "保存中…"
|
|
379
524
|
};
|
|
380
525
|
var en = {
|
|
381
526
|
"term.space": "Memory Space",
|
|
@@ -743,7 +888,129 @@ window.__ModuleLoader__.load({
|
|
|
743
888
|
"overview.rediscoveryFailed": "{provider} could not finish discovery: {error}",
|
|
744
889
|
"overview.rediscoveryTimedOut": "{provider} did not answer in time; try Rediscover later.",
|
|
745
890
|
"overview.rediscoveryDismiss": "Dismiss",
|
|
746
|
-
"overview.newSpace": "New"
|
|
891
|
+
"overview.newSpace": "New",
|
|
892
|
+
"common.copyId": "Copy ID",
|
|
893
|
+
"common.readOnly": "Read only",
|
|
894
|
+
"common.activationOnly": "Activation control only",
|
|
895
|
+
"common.active": "Active",
|
|
896
|
+
"common.category": "Category",
|
|
897
|
+
"common.importanceLabel": "Importance",
|
|
898
|
+
"common.importance": "Importance {value}",
|
|
899
|
+
"common.hops": "{count} hops",
|
|
900
|
+
"common.allCategories": "All categories",
|
|
901
|
+
"common.memories": "{count} memories",
|
|
902
|
+
"common.edges": "{count} edges",
|
|
903
|
+
"card.confirmText": "Soft-delete this memory?",
|
|
904
|
+
"card.processing": "Processing…",
|
|
905
|
+
"card.confirmForget": "Confirm forget",
|
|
906
|
+
"card.related": "View related",
|
|
907
|
+
"card.clone": "Create from this",
|
|
908
|
+
"card.forget": "Forget",
|
|
909
|
+
"readSources.all": "All providers",
|
|
910
|
+
"readSources.mode.search": "Native search",
|
|
911
|
+
"readSources.mode.graph": "True relation graph",
|
|
912
|
+
"readSources.mode.projection": "Content projection",
|
|
913
|
+
"readSources.mode.enumerable": "Enumerable content",
|
|
914
|
+
"readSources.mode.query-only": "Query only",
|
|
915
|
+
"readSources.mode.entities": "Entity index",
|
|
916
|
+
"readSources.mode.unsupported": "Unsupported",
|
|
917
|
+
"readSources.status.ready": "{count} observable",
|
|
918
|
+
"readSources.status.empty": "Connected · no content",
|
|
919
|
+
"readSources.status.query-required": "Read after a query",
|
|
920
|
+
"readSources.status.unsupported": "Unavailable on this surface",
|
|
921
|
+
"readSources.status.unavailable": "Connection unavailable",
|
|
922
|
+
"readSources.edges": "{count} true relations",
|
|
923
|
+
"readSources.model.mnemon-native": "Facts, entities, and typed relations",
|
|
924
|
+
"readSources.model.openviking": "Hierarchy and tiered content",
|
|
925
|
+
"readSources.model.honcho": "Peer conclusions and profiles",
|
|
926
|
+
"readSources.model.mem0": "Extracted semantic memories",
|
|
927
|
+
"readSources.model.hindsight": "Memory units and knowledge graph",
|
|
928
|
+
"readSources.model.holographic": "Trusted facts and entities",
|
|
929
|
+
"readSources.model.retaindb": "Profiles and typed facts",
|
|
930
|
+
"readSources.model.byterover": "Knowledge-tree queries",
|
|
931
|
+
"readSources.model.supermemory": "Memories and ingested documents",
|
|
932
|
+
"common.inactive": "Inactive",
|
|
933
|
+
"config.providerSecretShow": "Show credential",
|
|
934
|
+
"config.providerSecretHide": "Hide credential",
|
|
935
|
+
"config.providerSecretStoredValue": "Saved credential",
|
|
936
|
+
"config.providersSpacesOffTitle": "Memory Spaces is off",
|
|
937
|
+
"config.providersSpacesOffDetail": "Saved connections are kept",
|
|
938
|
+
"config.providersSpacesOn": "Turn on “Memory Spaces”",
|
|
939
|
+
"config.providersReadOnlyTitle": "dsh-mnemon is read-only",
|
|
940
|
+
"config.providersReadOnlyDetail": "With writeEnabled false, Providers cannot be switched on or off.",
|
|
941
|
+
"spaces.offNote": "Turn it on to configure Providers and embedding",
|
|
942
|
+
"config.providersTitle": "Memory providers",
|
|
943
|
+
"config.providersDescription": "Providers store memory spaces. Enabling or saving one synchronizes its existing spaces; turning it off removes only the local mapping, never third-party data.",
|
|
944
|
+
"config.nativeSummary": "Official native long-term memory with a complete relation graph",
|
|
945
|
+
"config.officialNative": "Official native",
|
|
946
|
+
"config.nativeCliMissing": "CLI not installed (optional)",
|
|
947
|
+
"config.embeddingTitle": "Local vector embeddings",
|
|
948
|
+
"config.embeddingDescription": "Have the DSH Host inject the embedding endpoint and model into every Mnemon CLI call; an endpoint ending in /v1 automatically uses the OpenAI-compatible protocol (/v1/embeddings with Bearer auth), otherwise the Ollama protocol. Compatible endpoints that do not end in /v1 can set the protocol explicitly.",
|
|
949
|
+
"config.embeddingManaged": "Manage embedding settings in DSH",
|
|
950
|
+
"config.embeddingManagedHint": "When enabled, saved values override the Mnemon child-process environment. When off, Mnemon keeps the Host environment and its built-in defaults.",
|
|
951
|
+
"config.embeddingEndpoint": "Embedding endpoint",
|
|
952
|
+
"config.embeddingModel": "Embedding model",
|
|
953
|
+
"config.embeddingApiKey": "API key (optional, OpenAI-compatible servers)",
|
|
954
|
+
"config.embeddingApiKeyInvalid": "The API key must contain no control characters and at most 2048 characters.",
|
|
955
|
+
"config.embeddingProtocol": "Protocol",
|
|
956
|
+
"config.embeddingProtocolAuto": "Auto (detect via /v1)",
|
|
957
|
+
"config.embeddingProtocolOllama": "Ollama",
|
|
958
|
+
"config.embeddingProtocolOpenai": "OpenAI-compatible",
|
|
959
|
+
"config.embeddingProtocolInvalid": "The protocol must be one of Auto / Ollama / OpenAI-compatible.",
|
|
960
|
+
"config.embeddingEndpointInvalid": "The embedding endpoint must be an absolute HTTP(S) URL without credentials, a query, or a fragment.",
|
|
961
|
+
"config.embeddingModelInvalid": "The embedding model must contain 1–200 characters and no control characters.",
|
|
962
|
+
"config.embeddingSecurity": "Mnemon sends memory and query text to this endpoint; the API key is stored in the DSH settings file like other settings. Remote HTTP is unencrypted; use a trusted local address or HTTPS for a remote service.",
|
|
963
|
+
"config.embeddingTest": "Test status",
|
|
964
|
+
"config.embeddingNotTested": "The embedding connection and the coverage of each Mnemon Native space have not been checked.",
|
|
965
|
+
"config.embeddingTesting": "Checking the embedding server and coverage through Mnemon…",
|
|
966
|
+
"config.embeddingSaveBeforeTest": "Save the embedding settings before testing their effective runtime values.",
|
|
967
|
+
"config.embeddingTestUnavailable": "This DSH Host does not provide embedding status checks.",
|
|
968
|
+
"config.embeddingCliMissing": "Testing needs the Mnemon CLI; these embedding settings only apply to Mnemon Native.",
|
|
969
|
+
"config.embeddingStatusAvailable": "Embedding server available · {model} · {embedded}/{total} embedded ({coverage})",
|
|
970
|
+
"config.embeddingStatusAvailableWithProtocol": "Embedding server available · {model} · protocol {protocol} · {embedded}/{total} embedded ({coverage})",
|
|
971
|
+
"config.embeddingStatusUnavailable": "Embedding server unreachable · {model} · {embedded}/{total} embedded ({coverage})",
|
|
972
|
+
"config.embeddingStatusUnavailableWithProtocol": "Embedding server unreachable · {model} · protocol {protocol} · {embedded}/{total} embedded ({coverage})",
|
|
973
|
+
"config.embeddingStatusFailed": "Embedding status check failed: {error}",
|
|
974
|
+
"config.embeddingSpaces": "Each Mnemon Native space",
|
|
975
|
+
"config.embeddingSpaceCounts": "{embedded}/{total} embedded ({coverage})",
|
|
976
|
+
"config.embeddingSpaceFailed": "Could not read: {error}",
|
|
977
|
+
"config.embeddingMissing": "Memories without a vector are left out of semantic matching.",
|
|
978
|
+
"config.embeddingMissingFill": "Memories without a vector are left out of semantic matching; Fill in beside a space creates its missing vectors.",
|
|
979
|
+
"config.embeddingMissingOffline": "Memories without a vector are left out of semantic matching; once the embedding service answers, their vectors can be filled in here.",
|
|
980
|
+
"config.embeddingSpacesUnread": "Spaces that could not be read are left out of the total.",
|
|
981
|
+
"config.embeddingFill": "Fill in",
|
|
982
|
+
"config.embeddingFilling": "Filling in…",
|
|
983
|
+
"config.embeddingFillLabel": "Fill in the vectors of {name}",
|
|
984
|
+
"config.embeddingFillingLabel": "Filling in the vectors of {name}",
|
|
985
|
+
"config.embeddingFillDone": "Filled in {filled} vectors for {name}.",
|
|
986
|
+
"config.embeddingFillMore": "Filled in {filled} vectors for {name}; {remaining} are still missing. Press Fill in to go on.",
|
|
987
|
+
"config.embeddingFillPartly": "Filled in {filled} vectors for {name}; the embedding service returned none for the other {remaining}. Press Fill in later to try again.",
|
|
988
|
+
"config.embeddingFillRefused": "The embedding service returned no vectors for {name}. Check that it is running and serves the model {model}.",
|
|
989
|
+
"config.embeddingFillFailed": "The vectors of {name} were not filled in: {error}",
|
|
990
|
+
"config.providerGlobalLocation": "Global data location",
|
|
991
|
+
"config.providerGlobalLocationHint": "{provider} uses the global scope directory by default, or you can choose a custom location.",
|
|
992
|
+
"config.providerGlobalLocationWorkspaceHint": "The workspace default is active. Switch to Global to choose a custom location.",
|
|
993
|
+
"config.providerDefaultLocation": "Default (follows scope)",
|
|
994
|
+
"config.providerSaveFailed": "Could not save configuration: {error}",
|
|
995
|
+
"config.providerServiceTitle": "Service configuration",
|
|
996
|
+
"config.providerServiceHint": "Shared by this provider’s Memory Spaces; enabling or saving refreshes their directory mappings and metadata.",
|
|
997
|
+
"config.providerEnableHint": "Complete and save the service configuration to enable the provider and synchronize every visible namespace.",
|
|
998
|
+
"config.providerEnabled": "Enabled",
|
|
999
|
+
"config.providerDisabled": "Not enabled",
|
|
1000
|
+
"config.providerDisabledConfigured": "Off · configuration kept",
|
|
1001
|
+
"config.providerNeedsConfiguration": "Configuration required",
|
|
1002
|
+
"config.providerToggleAria": "Enable {provider}",
|
|
1003
|
+
"config.providerToggleFailed": "Could not change provider state: {error}",
|
|
1004
|
+
"config.enableProvider": "Save and enable",
|
|
1005
|
+
"config.providerServiceSaved": "Service configuration saved and Memory Spaces synchronized",
|
|
1006
|
+
"config.saveProviderService": "Save service configuration",
|
|
1007
|
+
"config.providerUnavailable": "This DSH host does not support provider service configuration.",
|
|
1008
|
+
"config.saveScopeBeforeProviders": "The storage scope has unsaved changes. Save the scope before configuring providers in that directory.",
|
|
1009
|
+
"config.providerTargetWorkspace": "Current workspace: {workspace}. Providers tagged Workspace use this scope for configuration and Memory Spaces.",
|
|
1010
|
+
"config.loadingProviders": "Loading provider configurations…",
|
|
1011
|
+
"config.providerLoadFailed": "Could not load provider configurations: {error}",
|
|
1012
|
+
"config.retryProviders": "Retry",
|
|
1013
|
+
"config.saving": "Saving…"
|
|
747
1014
|
};
|
|
748
1015
|
//#endregion
|
|
749
1016
|
//#region \0source-css:/home/runner/work/dsh-mnemon/dsh-mnemon/plugins/dsh-mnemon-source-memory-spaces/presentation/page.module.css.mjs
|
|
@@ -942,18 +1209,61 @@ window.__ModuleLoader__.load({
|
|
|
942
1209
|
...dsh_mnemon_client.memorySidebarStyles,
|
|
943
1210
|
...sidebar_module_css_default
|
|
944
1211
|
};
|
|
1212
|
+
const TranslationOverride = (0, react.createContext)(void 0);
|
|
1213
|
+
const SourceTranslation = TranslationOverride.Provider;
|
|
1214
|
+
function interpolate(text, params) {
|
|
1215
|
+
return params === void 0 ? text : text.replace(/\{(\w+)\}/g, (match, name) => name in params ? String(params[name]) : match);
|
|
1216
|
+
}
|
|
945
1217
|
function useT() {
|
|
1218
|
+
const override = (0, react.useContext)(TranslationOverride);
|
|
946
1219
|
const fallback = (0, dsh_mnemon_client.useT)();
|
|
947
1220
|
const locale = (0, dsh_mnemon_client.useLocale)();
|
|
948
|
-
return (0, react.useMemo)(() => (key, params) => {
|
|
1221
|
+
return (0, react.useMemo)(() => override ?? ((key, params) => {
|
|
949
1222
|
const dictionary = locale.startsWith("en") ? en : zh;
|
|
950
1223
|
if (!Object.hasOwn(dictionary, key)) return fallback(key, params);
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
1224
|
+
return interpolate(dictionary[key], params);
|
|
1225
|
+
}), [
|
|
1226
|
+
override,
|
|
1227
|
+
locale,
|
|
1228
|
+
fallback
|
|
1229
|
+
]);
|
|
1230
|
+
}
|
|
1231
|
+
/** The languages DSH asks for a key: the active one, then each one's fallback. */
|
|
1232
|
+
function languageChain(snapshot) {
|
|
1233
|
+
const fallbacks = new Map(snapshot.locales.map((locale) => [locale.id, locale.fallback]));
|
|
1234
|
+
const chain = [];
|
|
1235
|
+
for (let id = snapshot.active; id !== void 0 && !chain.includes(id); id = fallbacks.get(id)) chain.push(id);
|
|
1236
|
+
return chain;
|
|
1237
|
+
}
|
|
1238
|
+
/**
|
|
1239
|
+
* Translate as dsh-mnemon drew these settings, through DSH's language chain
|
|
1240
|
+
* and the `mnemon` namespace it registers this copy in. This copy answers in
|
|
1241
|
+
* the first of zh and en the chain reaches; a language pack ahead of that one
|
|
1242
|
+
* is asked first, through the namespace, as dsh-mnemon asked it; a key this
|
|
1243
|
+
* copy lacks goes to the namespace too. Without DSH's chain the page's
|
|
1244
|
+
* language picks the copy, as the page frame does.
|
|
1245
|
+
*/
|
|
1246
|
+
function settingsTranslate(locale, chain, language) {
|
|
1247
|
+
const bound = locale.bind("mnemon");
|
|
1248
|
+
const head = chain === void 0 ? language.startsWith("en") ? "en" : "zh" : chain.find((id) => id === "zh" || id === "en") ?? "en";
|
|
1249
|
+
const own = head === "en" ? en : zh;
|
|
1250
|
+
const packFirst = chain !== void 0 && chain.length > 0 && chain[0] !== head;
|
|
1251
|
+
return (key, params) => {
|
|
1252
|
+
if (packFirst) {
|
|
1253
|
+
const text = bound(key, params);
|
|
1254
|
+
if (text !== key) return text;
|
|
1255
|
+
}
|
|
1256
|
+
return Object.hasOwn(own, key) ? interpolate(own[key], params) : bound(key, params);
|
|
1257
|
+
};
|
|
954
1258
|
}
|
|
955
1259
|
//#endregion
|
|
956
1260
|
//#region src/contracts.ts
|
|
1261
|
+
/**
|
|
1262
|
+
* The Mnemon Native Provider's id. Its package names its descriptor and driver
|
|
1263
|
+
* with it, the Starter installs it under it, and a stored space that names no
|
|
1264
|
+
* Provider belongs to it.
|
|
1265
|
+
*/
|
|
1266
|
+
const NATIVE_PROVIDER_ID = "mnemon-native";
|
|
957
1267
|
const CATEGORIES = [
|
|
958
1268
|
"preference",
|
|
959
1269
|
"decision",
|
|
@@ -969,6 +1279,14 @@ window.__ModuleLoader__.load({
|
|
|
969
1279
|
function normalizeEntityKey(entity) {
|
|
970
1280
|
return entity.normalize("NFKC").trim().toLocaleLowerCase();
|
|
971
1281
|
}
|
|
1282
|
+
/** Wire protocols accepted by the embedding protocol override; single source for schema, resolver, and UI validation. */
|
|
1283
|
+
const MNEMON_EMBEDDING_PROTOCOLS = [
|
|
1284
|
+
"auto",
|
|
1285
|
+
"ollama",
|
|
1286
|
+
"openai"
|
|
1287
|
+
];
|
|
1288
|
+
/** The most characters a space's routing description holds. */
|
|
1289
|
+
const MEMORY_SPACE_DESCRIPTION_MAX_LENGTH = 1e3;
|
|
972
1290
|
//#endregion
|
|
973
1291
|
//#region src/client/ProviderIcon.tsx
|
|
974
1292
|
function GenericProviderMark() {
|
|
@@ -1034,7 +1352,165 @@ window.__ModuleLoader__.load({
|
|
|
1034
1352
|
return typeof localized !== "string" || localized.length === 0 || localized === option.i18nKey ? option.label : localized;
|
|
1035
1353
|
}
|
|
1036
1354
|
//#endregion
|
|
1037
|
-
//#region src/client/
|
|
1355
|
+
//#region src/client/provider-field.tsx
|
|
1356
|
+
const SAVED_SECRET_MASK = "••••••••••••";
|
|
1357
|
+
function inputType(field, secretVisible) {
|
|
1358
|
+
return field.input === "secret" ? secretVisible ? "text" : "password" : field.input === "number" ? "number" : field.input === "url" ? "url" : "text";
|
|
1359
|
+
}
|
|
1360
|
+
function SecretVisibilityIcon({ visible }) {
|
|
1361
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
1362
|
+
viewBox: "0 0 20 20",
|
|
1363
|
+
fill: "none",
|
|
1364
|
+
"aria-hidden": "true",
|
|
1365
|
+
children: [
|
|
1366
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1367
|
+
d: "M2.3 10s2.8-4.5 7.7-4.5 7.7 4.5 7.7 4.5-2.8 4.5-7.7 4.5S2.3 10 2.3 10Z",
|
|
1368
|
+
stroke: "currentColor",
|
|
1369
|
+
strokeWidth: "1.4",
|
|
1370
|
+
strokeLinecap: "round",
|
|
1371
|
+
strokeLinejoin: "round"
|
|
1372
|
+
}),
|
|
1373
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
1374
|
+
cx: "10",
|
|
1375
|
+
cy: "10",
|
|
1376
|
+
r: "2.1",
|
|
1377
|
+
stroke: "currentColor",
|
|
1378
|
+
strokeWidth: "1.4"
|
|
1379
|
+
}),
|
|
1380
|
+
visible && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1381
|
+
d: "m3.5 3.5 13 13",
|
|
1382
|
+
stroke: "currentColor",
|
|
1383
|
+
strokeWidth: "1.4",
|
|
1384
|
+
strokeLinecap: "round"
|
|
1385
|
+
})
|
|
1386
|
+
]
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
/** One field of a Provider descriptor, wherever it is edited. */
|
|
1390
|
+
function ProviderField(props) {
|
|
1391
|
+
return props.layout === "settings" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsField, { ...props }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DialogField, { ...props });
|
|
1392
|
+
}
|
|
1393
|
+
function SettingsField(props) {
|
|
1394
|
+
const t = useT();
|
|
1395
|
+
const settings = dsh_mnemon_client.memorySettingsStyles;
|
|
1396
|
+
const [secretVisible, setSecretVisible] = (0, react.useState)(false);
|
|
1397
|
+
const { field } = props;
|
|
1398
|
+
const label = providerFieldLabel(t, field);
|
|
1399
|
+
const disabled = props.disabled === true;
|
|
1400
|
+
const required = field.required && !props.saved;
|
|
1401
|
+
const secret = field.input === "secret";
|
|
1402
|
+
const fieldValue = String(props.value ?? "");
|
|
1403
|
+
const showingSavedMask = secret && props.saved && fieldValue === "";
|
|
1404
|
+
const displayValue = showingSavedMask ? secretVisible ? t("config.providerSecretStoredValue") : SAVED_SECRET_MASK : fieldValue;
|
|
1405
|
+
const input = field.input === "boolean" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
1406
|
+
className: settings.providerBoolean,
|
|
1407
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1408
|
+
"aria-label": label,
|
|
1409
|
+
type: "checkbox",
|
|
1410
|
+
checked: Boolean(props.value),
|
|
1411
|
+
disabled,
|
|
1412
|
+
onChange: (event) => props.onChange(event.target.checked)
|
|
1413
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label })]
|
|
1414
|
+
}) : field.input === "select" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.SelectField, {
|
|
1415
|
+
label,
|
|
1416
|
+
value: String(props.value ?? ""),
|
|
1417
|
+
disabled,
|
|
1418
|
+
options: (field.options ?? []).map((option) => ({
|
|
1419
|
+
value: option.value,
|
|
1420
|
+
label: providerOptionLabel(t, option)
|
|
1421
|
+
})),
|
|
1422
|
+
onChange: (next) => props.onChange(next)
|
|
1423
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [label, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1424
|
+
className: secret ? settings.providerSecretInput : void 0,
|
|
1425
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1426
|
+
"aria-label": label,
|
|
1427
|
+
type: inputType(field, secretVisible),
|
|
1428
|
+
value: displayValue,
|
|
1429
|
+
required,
|
|
1430
|
+
disabled,
|
|
1431
|
+
autoComplete: secret ? "new-password" : void 0,
|
|
1432
|
+
placeholder: field.placeholder ?? (secret ? t("overview.providerApiKeyOptional") : void 0),
|
|
1433
|
+
maxLength: field.maxLength ?? (secret ? 8e3 : 2e3),
|
|
1434
|
+
min: field.min,
|
|
1435
|
+
max: field.max,
|
|
1436
|
+
pattern: field.pattern,
|
|
1437
|
+
step: field.input === "number" ? "any" : void 0,
|
|
1438
|
+
onFocus: (event) => {
|
|
1439
|
+
if (showingSavedMask) event.currentTarget.select();
|
|
1440
|
+
},
|
|
1441
|
+
onClick: (event) => {
|
|
1442
|
+
if (showingSavedMask) event.currentTarget.select();
|
|
1443
|
+
},
|
|
1444
|
+
onChange: (event) => {
|
|
1445
|
+
const value = showingSavedMask ? event.target.value.replace(SAVED_SECRET_MASK, "").replace(t("config.providerSecretStoredValue"), "") : event.target.value;
|
|
1446
|
+
props.onChange(value);
|
|
1447
|
+
}
|
|
1448
|
+
}), secret && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1449
|
+
type: "button",
|
|
1450
|
+
className: settings.providerSecretVisibility,
|
|
1451
|
+
"aria-label": t(secretVisible ? "config.providerSecretHide" : "config.providerSecretShow"),
|
|
1452
|
+
title: t(secretVisible ? "config.providerSecretHide" : "config.providerSecretShow"),
|
|
1453
|
+
"aria-pressed": secretVisible,
|
|
1454
|
+
disabled,
|
|
1455
|
+
onClick: () => setSecretVisible((value) => !value),
|
|
1456
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SecretVisibilityIcon, { visible: secretVisible })
|
|
1457
|
+
})]
|
|
1458
|
+
})] });
|
|
1459
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1460
|
+
className: settings.providerFieldControl,
|
|
1461
|
+
"data-input": field.input,
|
|
1462
|
+
children: input
|
|
1463
|
+
});
|
|
1464
|
+
}
|
|
1465
|
+
function DialogField(props) {
|
|
1466
|
+
const t = useT();
|
|
1467
|
+
const { field } = props;
|
|
1468
|
+
const label = providerFieldLabel(t, field);
|
|
1469
|
+
const value = props.value ?? "";
|
|
1470
|
+
const clearing = props.clearing === true;
|
|
1471
|
+
const required = field.required && (!props.saved || clearing);
|
|
1472
|
+
const input = field.input === "boolean" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1473
|
+
"aria-label": label,
|
|
1474
|
+
type: "checkbox",
|
|
1475
|
+
checked: Boolean(value),
|
|
1476
|
+
onChange: (event) => props.onChange(event.target.checked)
|
|
1477
|
+
}) : field.input === "select" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.SelectField, {
|
|
1478
|
+
hideLabel: true,
|
|
1479
|
+
label,
|
|
1480
|
+
value: String(value),
|
|
1481
|
+
options: (field.options ?? []).map((option) => ({
|
|
1482
|
+
value: option.value,
|
|
1483
|
+
label: providerOptionLabel(t, option)
|
|
1484
|
+
})),
|
|
1485
|
+
onChange: (next) => props.onChange(next)
|
|
1486
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1487
|
+
"aria-label": label,
|
|
1488
|
+
type: inputType(field, false),
|
|
1489
|
+
value: String(value),
|
|
1490
|
+
required,
|
|
1491
|
+
autoComplete: field.input === "secret" ? "new-password" : void 0,
|
|
1492
|
+
placeholder: props.saved ? t("overview.providerApiKeyKeep") : field.placeholder ?? (field.input === "secret" ? t("overview.providerApiKeyOptional") : void 0),
|
|
1493
|
+
maxLength: field.maxLength ?? (field.input === "secret" ? 8e3 : 2e3),
|
|
1494
|
+
min: field.min,
|
|
1495
|
+
max: field.max,
|
|
1496
|
+
pattern: field.pattern,
|
|
1497
|
+
step: field.input === "number" ? "any" : void 0,
|
|
1498
|
+
onChange: (event) => props.onChange(event.target.value)
|
|
1499
|
+
});
|
|
1500
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1501
|
+
className: css.providerFieldControl,
|
|
1502
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [label, input] }), field.input === "secret" && props.saved && props.onClearChange !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
1503
|
+
className: css.providerSecretClear,
|
|
1504
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1505
|
+
type: "checkbox",
|
|
1506
|
+
checked: clearing,
|
|
1507
|
+
onChange: (event) => props.onClearChange(event.target.checked)
|
|
1508
|
+
}), t("overview.providerSecretClear")]
|
|
1509
|
+
})]
|
|
1510
|
+
});
|
|
1511
|
+
}
|
|
1512
|
+
//#endregion
|
|
1513
|
+
//#region src/client/widgets.tsx
|
|
1038
1514
|
function memoryProviderFields(provider) {
|
|
1039
1515
|
return provider.fields.filter((field) => field.scope !== "service");
|
|
1040
1516
|
}
|
|
@@ -1092,49 +1568,16 @@ window.__ModuleLoader__.load({
|
|
|
1092
1568
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1093
1569
|
className: css.providerAdvancedGrid,
|
|
1094
1570
|
children: memoryProviderFields(props.provider).map((field) => {
|
|
1095
|
-
const
|
|
1096
|
-
const
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
}) : field.input === "select" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.SelectField, {
|
|
1106
|
-
hideLabel: true,
|
|
1107
|
-
label,
|
|
1108
|
-
value: String(value),
|
|
1109
|
-
options: (field.options ?? []).map((option) => ({
|
|
1110
|
-
value: option.value,
|
|
1111
|
-
label: providerOptionLabel(t, option)
|
|
1112
|
-
})),
|
|
1113
|
-
onChange: (next) => props.onChange(field.key, next)
|
|
1114
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1115
|
-
"aria-label": label,
|
|
1116
|
-
type: field.input === "secret" ? "password" : field.input === "number" ? "number" : field.input === "url" ? "url" : "text",
|
|
1117
|
-
value: String(value),
|
|
1118
|
-
required,
|
|
1119
|
-
autoComplete: field.input === "secret" ? "new-password" : void 0,
|
|
1120
|
-
placeholder: savedSecret ? t("overview.providerApiKeyKeep") : field.placeholder ?? (field.input === "secret" ? t("overview.providerApiKeyOptional") : void 0),
|
|
1121
|
-
maxLength: field.maxLength ?? (field.input === "secret" ? 8e3 : 2e3),
|
|
1122
|
-
min: field.min,
|
|
1123
|
-
max: field.max,
|
|
1124
|
-
pattern: field.pattern,
|
|
1125
|
-
step: field.input === "number" ? "any" : void 0,
|
|
1126
|
-
onChange: (event) => props.onChange(field.key, event.target.value)
|
|
1127
|
-
});
|
|
1128
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1129
|
-
className: css.providerFieldControl,
|
|
1130
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [label, input] }), props.body !== void 0 && field.input === "secret" && savedSecret && props.onClearSecretsChange !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
1131
|
-
className: css.providerSecretClear,
|
|
1132
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1133
|
-
type: "checkbox",
|
|
1134
|
-
checked: clearingSecret,
|
|
1135
|
-
onChange: (event) => props.onClearSecretsChange(event.target.checked ? [.../* @__PURE__ */ new Set([...props.clearSecrets ?? [], field.key])] : (props.clearSecrets ?? []).filter((key) => key !== field.key))
|
|
1136
|
-
}), t("overview.providerSecretClear")]
|
|
1137
|
-
})]
|
|
1571
|
+
const saved = props.body?.provider.configuredSecrets.includes(field.key) === true;
|
|
1572
|
+
const clearSecrets = props.clearSecrets ?? [];
|
|
1573
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProviderField, {
|
|
1574
|
+
field,
|
|
1575
|
+
value: props.connection[field.key],
|
|
1576
|
+
layout: "dialog",
|
|
1577
|
+
saved,
|
|
1578
|
+
clearing: clearSecrets.includes(field.key),
|
|
1579
|
+
onChange: (value) => props.onChange(field.key, value),
|
|
1580
|
+
...props.body === void 0 || props.onClearSecretsChange === void 0 ? {} : { onClearChange: (clearing) => props.onClearSecretsChange(clearing ? [.../* @__PURE__ */ new Set([...clearSecrets, field.key])] : clearSecrets.filter((key) => key !== field.key)) }
|
|
1138
1581
|
}, field.key);
|
|
1139
1582
|
})
|
|
1140
1583
|
}),
|
|
@@ -1224,24 +1667,6 @@ window.__ModuleLoader__.load({
|
|
|
1224
1667
|
}, source.memoryBodyId)) })]
|
|
1225
1668
|
});
|
|
1226
1669
|
}
|
|
1227
|
-
/** Full-text popup for a selected graph node whose inspector preview is clamped. */
|
|
1228
|
-
function ContentPreview(props) {
|
|
1229
|
-
const t = useT();
|
|
1230
|
-
const meta = [
|
|
1231
|
-
props.kind,
|
|
1232
|
-
props.node.id,
|
|
1233
|
-
props.node.memoryBodyName
|
|
1234
|
-
].filter((entry) => entry !== void 0).join(" · ");
|
|
1235
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.SidebarModal, {
|
|
1236
|
-
title: t("overview.previewTitle"),
|
|
1237
|
-
description: meta,
|
|
1238
|
-
onClose: props.onClose,
|
|
1239
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1240
|
-
className: css.previewContent,
|
|
1241
|
-
children: props.node.content
|
|
1242
|
-
})
|
|
1243
|
-
});
|
|
1244
|
-
}
|
|
1245
1670
|
function InsightCard(props) {
|
|
1246
1671
|
const t = useT();
|
|
1247
1672
|
const [confirming, setConfirming] = (0, react.useState)(false);
|
|
@@ -1359,6 +1784,10 @@ window.__ModuleLoader__.load({
|
|
|
1359
1784
|
})
|
|
1360
1785
|
})] });
|
|
1361
1786
|
}
|
|
1787
|
+
/** @deprecated Use nativeSpaceProvider. */
|
|
1788
|
+
const nativeBodyProvider = nativeSpaceProvider;
|
|
1789
|
+
//#endregion
|
|
1790
|
+
//#region src/client/memory-graph.tsx
|
|
1362
1791
|
const GRAPH_WIDTH = 930;
|
|
1363
1792
|
const GRAPH_HEIGHT = 520;
|
|
1364
1793
|
const GRAPH_MARGIN_X = 58;
|
|
@@ -1967,6 +2396,26 @@ window.__ModuleLoader__.load({
|
|
|
1967
2396
|
]
|
|
1968
2397
|
})] });
|
|
1969
2398
|
}
|
|
2399
|
+
//#endregion
|
|
2400
|
+
//#region src/client/overview-page.tsx
|
|
2401
|
+
/** Full-text popup for a selected graph node whose inspector preview is clamped. */
|
|
2402
|
+
function ContentPreview(props) {
|
|
2403
|
+
const t = useT();
|
|
2404
|
+
const meta = [
|
|
2405
|
+
props.kind,
|
|
2406
|
+
props.node.id,
|
|
2407
|
+
props.node.memoryBodyName
|
|
2408
|
+
].filter((entry) => entry !== void 0).join(" · ");
|
|
2409
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.SidebarModal, {
|
|
2410
|
+
title: t("overview.previewTitle"),
|
|
2411
|
+
description: meta,
|
|
2412
|
+
onClose: props.onClose,
|
|
2413
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2414
|
+
className: css.previewContent,
|
|
2415
|
+
children: props.node.content
|
|
2416
|
+
})
|
|
2417
|
+
});
|
|
2418
|
+
}
|
|
1970
2419
|
function OverviewPage(props) {
|
|
1971
2420
|
const t = useT();
|
|
1972
2421
|
const locale = (0, dsh_mnemon_client.useLocale)();
|
|
@@ -1985,7 +2434,7 @@ window.__ModuleLoader__.load({
|
|
|
1985
2434
|
const [creatingSpaceOpen, setCreatingSpaceOpen] = (0, react.useState)(false);
|
|
1986
2435
|
const [spaceName, setSpaceName] = (0, react.useState)("");
|
|
1987
2436
|
const [spaceDescription, setSpaceDescription] = (0, react.useState)("");
|
|
1988
|
-
const [spaceProviderId, setSpaceProviderId] = (0, react.useState)(
|
|
2437
|
+
const [spaceProviderId, setSpaceProviderId] = (0, react.useState)(NATIVE_PROVIDER_ID);
|
|
1989
2438
|
const [providerDrafts, setProviderDrafts] = (0, react.useState)({});
|
|
1990
2439
|
const [catalogUnavailable, setCatalogUnavailable] = (0, react.useState)(false);
|
|
1991
2440
|
const [editingSpace, setEditingSpace] = (0, react.useState)(null);
|
|
@@ -2386,7 +2835,7 @@ window.__ModuleLoader__.load({
|
|
|
2386
2835
|
value: editDescription,
|
|
2387
2836
|
onChange: (event) => setEditDescription(event.target.value),
|
|
2388
2837
|
rows: 4,
|
|
2389
|
-
maxLength:
|
|
2838
|
+
maxLength: MEMORY_SPACE_DESCRIPTION_MAX_LENGTH
|
|
2390
2839
|
})] }),
|
|
2391
2840
|
!nativeSpaceProvider(body.provider) && (() => {
|
|
2392
2841
|
const descriptor = providers.find((provider) => provider.id === body.provider.id);
|
|
@@ -2429,7 +2878,7 @@ window.__ModuleLoader__.load({
|
|
|
2429
2878
|
onChange: (event) => setSpaceDescription(event.target.value),
|
|
2430
2879
|
placeholder: t("overview.createDescriptionPlaceholder"),
|
|
2431
2880
|
rows: 3,
|
|
2432
|
-
maxLength:
|
|
2881
|
+
maxLength: MEMORY_SPACE_DESCRIPTION_MAX_LENGTH,
|
|
2433
2882
|
required: true
|
|
2434
2883
|
})] })]
|
|
2435
2884
|
})]
|
|
@@ -3072,6 +3521,24 @@ window.__ModuleLoader__.load({
|
|
|
3072
3521
|
]
|
|
3073
3522
|
});
|
|
3074
3523
|
}
|
|
3524
|
+
/** The rediscovery a person last dismissed on this browser, so the same news is not shown twice. */
|
|
3525
|
+
const REDISCOVERY_SEEN_KEY = "dsh-mnemon.memory-spaces.rediscovery-seen";
|
|
3526
|
+
/** How often an open page looks again while the Host asks the Providers. */
|
|
3527
|
+
const REDISCOVERY_POLL_MS = 2e3;
|
|
3528
|
+
function readSeenRediscovery() {
|
|
3529
|
+
try {
|
|
3530
|
+
return globalThis.localStorage?.getItem(REDISCOVERY_SEEN_KEY) ?? null;
|
|
3531
|
+
} catch {
|
|
3532
|
+
return null;
|
|
3533
|
+
}
|
|
3534
|
+
}
|
|
3535
|
+
function writeSeenRediscovery(at) {
|
|
3536
|
+
try {
|
|
3537
|
+
globalThis.localStorage?.setItem(REDISCOVERY_SEEN_KEY, at);
|
|
3538
|
+
} catch {}
|
|
3539
|
+
}
|
|
3540
|
+
//#endregion
|
|
3541
|
+
//#region src/client/explore-page.tsx
|
|
3075
3542
|
function ExplorePage(props) {
|
|
3076
3543
|
const t = useT();
|
|
3077
3544
|
const pageSize = 6;
|
|
@@ -3384,22 +3851,8 @@ window.__ModuleLoader__.load({
|
|
|
3384
3851
|
]
|
|
3385
3852
|
});
|
|
3386
3853
|
}
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
/** How often an open page looks again while the Host asks the Providers. */
|
|
3390
|
-
const REDISCOVERY_POLL_MS = 2e3;
|
|
3391
|
-
function readSeenRediscovery() {
|
|
3392
|
-
try {
|
|
3393
|
-
return globalThis.localStorage?.getItem(REDISCOVERY_SEEN_KEY) ?? null;
|
|
3394
|
-
} catch {
|
|
3395
|
-
return null;
|
|
3396
|
-
}
|
|
3397
|
-
}
|
|
3398
|
-
function writeSeenRediscovery(at) {
|
|
3399
|
-
try {
|
|
3400
|
-
globalThis.localStorage?.setItem(REDISCOVERY_SEEN_KEY, at);
|
|
3401
|
-
} catch {}
|
|
3402
|
-
}
|
|
3854
|
+
//#endregion
|
|
3855
|
+
//#region src/client/entities-page.tsx
|
|
3403
3856
|
/** Show a loading placeholder only when a read outlasts this, so a quick read never flashes one. */
|
|
3404
3857
|
const ENTITY_PLACEHOLDER_DELAY_MS = 160;
|
|
3405
3858
|
const ENTITY_RAIL_PAGE = 10;
|
|
@@ -3895,6 +4348,8 @@ window.__ModuleLoader__.load({
|
|
|
3895
4348
|
]
|
|
3896
4349
|
});
|
|
3897
4350
|
}
|
|
4351
|
+
//#endregion
|
|
4352
|
+
//#region src/client/persistence-strategy-dialog.tsx
|
|
3898
4353
|
function PersistenceStrategyDialog(props) {
|
|
3899
4354
|
const t = useT();
|
|
3900
4355
|
const strategyFormId = (0, react.useId)();
|
|
@@ -4225,6 +4680,9 @@ window.__ModuleLoader__.load({
|
|
|
4225
4680
|
})
|
|
4226
4681
|
});
|
|
4227
4682
|
}
|
|
4683
|
+
//#endregion
|
|
4684
|
+
//#region src/client/remember-page.tsx
|
|
4685
|
+
/** `embeddingManaged`, from this Source's status, words a memory saved without a vector; left out, the receipt keeps the caution. */
|
|
4228
4686
|
function RememberPage(props) {
|
|
4229
4687
|
const t = useT();
|
|
4230
4688
|
const rememberFormId = (0, react.useId)();
|
|
@@ -4259,7 +4717,8 @@ window.__ModuleLoader__.load({
|
|
|
4259
4717
|
content: candidate,
|
|
4260
4718
|
action: response.action,
|
|
4261
4719
|
summary: response.summary,
|
|
4262
|
-
unembedded: (response.unembedded ?? []).length > 0
|
|
4720
|
+
unembedded: (response.unembedded ?? []).length > 0,
|
|
4721
|
+
embeddingManaged: props.embeddingManaged
|
|
4263
4722
|
});
|
|
4264
4723
|
props.onMutate();
|
|
4265
4724
|
} catch (reason) {
|
|
@@ -4290,7 +4749,8 @@ window.__ModuleLoader__.load({
|
|
|
4290
4749
|
content: candidate,
|
|
4291
4750
|
action: typeof response.action === "string" ? response.action : "stored",
|
|
4292
4751
|
summary: typeof response.summary === "string" ? response.summary : "",
|
|
4293
|
-
unembedded: response.embedded === false
|
|
4752
|
+
unembedded: response.embedded === false,
|
|
4753
|
+
embeddingManaged: props.embeddingManaged
|
|
4294
4754
|
});
|
|
4295
4755
|
props.onMutate();
|
|
4296
4756
|
} catch (reason) {
|
|
@@ -4333,6 +4793,7 @@ window.__ModuleLoader__.load({
|
|
|
4333
4793
|
summary: outcome.summary,
|
|
4334
4794
|
error: outcome.error,
|
|
4335
4795
|
unembedded: outcome.unembedded,
|
|
4796
|
+
embeddingManaged: outcome.embeddingManaged,
|
|
4336
4797
|
onView: props.onView
|
|
4337
4798
|
})
|
|
4338
4799
|
]
|
|
@@ -4441,6 +4902,8 @@ window.__ModuleLoader__.load({
|
|
|
4441
4902
|
})
|
|
4442
4903
|
});
|
|
4443
4904
|
}
|
|
4905
|
+
//#endregion
|
|
4906
|
+
//#region src/client/list-page.tsx
|
|
4444
4907
|
function ListPage(props) {
|
|
4445
4908
|
const t = useT();
|
|
4446
4909
|
const pageSize = 12;
|
|
@@ -4579,8 +5042,1020 @@ window.__ModuleLoader__.load({
|
|
|
4579
5042
|
]
|
|
4580
5043
|
});
|
|
4581
5044
|
}
|
|
4582
|
-
|
|
4583
|
-
|
|
5045
|
+
//#endregion
|
|
5046
|
+
//#region src/client/provider-settings.tsx
|
|
5047
|
+
const EMPTY_PROVIDER_CATALOG = {
|
|
5048
|
+
providers: [],
|
|
5049
|
+
items: [],
|
|
5050
|
+
generatedAt: ""
|
|
5051
|
+
};
|
|
5052
|
+
const RETAINED_PROVIDERS = "provider-services";
|
|
5053
|
+
const retainedCatalog = (retained) => retained.get(RETAINED_PROVIDERS);
|
|
5054
|
+
function stabilizeProviderCard(element) {
|
|
5055
|
+
const view = element.ownerDocument.defaultView;
|
|
5056
|
+
let scrollContainer;
|
|
5057
|
+
for (let ancestor = element.parentElement; ancestor !== null; ancestor = ancestor.parentElement) {
|
|
5058
|
+
const overflowY = view?.getComputedStyle(ancestor).overflowY ?? ancestor.style.overflowY;
|
|
5059
|
+
if (scrollContainer !== void 0 && overflowY === "hidden" && ancestor.scrollTop !== 0) ancestor.scrollTop = 0;
|
|
5060
|
+
if (scrollContainer === void 0 && (overflowY === "auto" || overflowY === "scroll") && ancestor.scrollHeight > ancestor.clientHeight) scrollContainer = ancestor;
|
|
5061
|
+
if (ancestor.getAttribute("role") === "dialog") break;
|
|
5062
|
+
}
|
|
5063
|
+
if (scrollContainer === void 0) return;
|
|
5064
|
+
const headerRect = (element.firstElementChild instanceof HTMLElement ? element.firstElementChild : element).getBoundingClientRect();
|
|
5065
|
+
const containerRect = scrollContainer.getBoundingClientRect();
|
|
5066
|
+
if (headerRect.top < containerRect.top) scrollContainer.scrollTop -= containerRect.top - headerRect.top;
|
|
5067
|
+
else if (headerRect.bottom > containerRect.bottom) scrollContainer.scrollTop += headerRect.bottom - containerRect.bottom;
|
|
5068
|
+
}
|
|
5069
|
+
function serviceFields(provider) {
|
|
5070
|
+
return provider.fields.filter((field) => field.scope === "service");
|
|
5071
|
+
}
|
|
5072
|
+
function globalLocationFields(provider) {
|
|
5073
|
+
return serviceFields(provider).filter((field) => field.role === "global-location");
|
|
5074
|
+
}
|
|
5075
|
+
function serviceDefaults(provider) {
|
|
5076
|
+
return Object.fromEntries(serviceFields(provider).flatMap((field) => field.defaultValue === void 0 ? [] : [[field.key, field.defaultValue]]));
|
|
5077
|
+
}
|
|
5078
|
+
function draftFor(provider, service) {
|
|
5079
|
+
return { settings: {
|
|
5080
|
+
...serviceDefaults(provider),
|
|
5081
|
+
...service.settings,
|
|
5082
|
+
...service.secretValues
|
|
5083
|
+
} };
|
|
5084
|
+
}
|
|
5085
|
+
function configurationComplete(provider, draft, service) {
|
|
5086
|
+
return serviceFields(provider).every((field) => {
|
|
5087
|
+
if (!field.required) return true;
|
|
5088
|
+
if (field.input === "secret" && service.configuredSecrets.includes(field.key)) return true;
|
|
5089
|
+
const value = draft.settings[field.key];
|
|
5090
|
+
return field.input === "boolean" ? typeof value === "boolean" : String(value ?? "").trim() !== "";
|
|
5091
|
+
});
|
|
5092
|
+
}
|
|
5093
|
+
function ProviderServiceForm(props) {
|
|
5094
|
+
const t = useT();
|
|
5095
|
+
const css = dsh_mnemon_client.memorySettingsStyles;
|
|
5096
|
+
const [draft, setDraft] = (0, react.useState)(() => draftFor(props.provider, props.service));
|
|
5097
|
+
const [customLocations, setCustomLocations] = (0, react.useState)(() => new Set(globalLocationFields(props.provider).filter((field) => String(props.service.settings[field.key] ?? "").trim() !== "").map((field) => field.key)));
|
|
5098
|
+
const [saving, setSaving] = (0, react.useState)(false);
|
|
5099
|
+
const [failed, setFailed] = (0, react.useState)(null);
|
|
5100
|
+
const [saved, setSaved] = (0, react.useState)(false);
|
|
5101
|
+
const formRef = (0, react.useRef)(null);
|
|
5102
|
+
const stabilizeAfterLocationLayout = (0, react.useRef)(false);
|
|
5103
|
+
(0, react.useEffect)(() => {
|
|
5104
|
+
setDraft(draftFor(props.provider, props.service));
|
|
5105
|
+
setCustomLocations(new Set(globalLocationFields(props.provider).filter((field) => String(props.service.settings[field.key] ?? "").trim() !== "").map((field) => field.key)));
|
|
5106
|
+
}, [props.provider, props.service]);
|
|
5107
|
+
(0, react.useLayoutEffect)(() => {
|
|
5108
|
+
if (!stabilizeAfterLocationLayout.current || formRef.current === null) return;
|
|
5109
|
+
stabilizeAfterLocationLayout.current = false;
|
|
5110
|
+
stabilizeProviderCard(formRef.current.closest("[data-provider]") ?? formRef.current);
|
|
5111
|
+
}, [customLocations]);
|
|
5112
|
+
const submit = async (event) => {
|
|
5113
|
+
event.preventDefault();
|
|
5114
|
+
const locationsComplete = props.activeScope === "workspace" || globalLocationFields(props.provider).every((field) => !customLocations.has(field.key) || String(draft.settings[field.key] ?? "").trim() !== "");
|
|
5115
|
+
if (!configurationComplete(props.provider, draft, props.service) || !locationsComplete || saving || props.disabled) return;
|
|
5116
|
+
setSaving(true);
|
|
5117
|
+
setFailed(null);
|
|
5118
|
+
setSaved(false);
|
|
5119
|
+
const settings = { ...draft.settings };
|
|
5120
|
+
for (const field of globalLocationFields(props.provider)) if (props.activeScope === "workspace" || !customLocations.has(field.key)) settings[field.key] = "";
|
|
5121
|
+
try {
|
|
5122
|
+
await props.onSave(props.provider, { settings });
|
|
5123
|
+
setSaved(true);
|
|
5124
|
+
} catch (reason) {
|
|
5125
|
+
setFailed((0, dsh_mnemon_client.message)(reason));
|
|
5126
|
+
} finally {
|
|
5127
|
+
setSaving(false);
|
|
5128
|
+
}
|
|
5129
|
+
};
|
|
5130
|
+
const update = (key, value) => {
|
|
5131
|
+
setDraft((current) => ({
|
|
5132
|
+
...current,
|
|
5133
|
+
settings: {
|
|
5134
|
+
...current.settings,
|
|
5135
|
+
[key]: value
|
|
5136
|
+
}
|
|
5137
|
+
}));
|
|
5138
|
+
setFailed(null);
|
|
5139
|
+
setSaved(false);
|
|
5140
|
+
};
|
|
5141
|
+
const useCustomLocation = (field, custom) => {
|
|
5142
|
+
stabilizeAfterLocationLayout.current = true;
|
|
5143
|
+
setCustomLocations((current) => {
|
|
5144
|
+
const next = new Set(current);
|
|
5145
|
+
if (custom) next.add(field.key);
|
|
5146
|
+
else next.delete(field.key);
|
|
5147
|
+
return next;
|
|
5148
|
+
});
|
|
5149
|
+
setFailed(null);
|
|
5150
|
+
setSaved(false);
|
|
5151
|
+
};
|
|
5152
|
+
const stabilizeLocationCard = () => {
|
|
5153
|
+
if (formRef.current === null) return;
|
|
5154
|
+
stabilizeProviderCard(formRef.current.closest("[data-provider]") ?? formRef.current);
|
|
5155
|
+
};
|
|
5156
|
+
const locations = globalLocationFields(props.provider);
|
|
5157
|
+
const regularFields = serviceFields(props.provider).filter((field) => field.role !== "global-location");
|
|
5158
|
+
const locationsComplete = props.activeScope === "workspace" || locations.every((field) => !customLocations.has(field.key) || String(draft.settings[field.key] ?? "").trim() !== "");
|
|
5159
|
+
const formComplete = configurationComplete(props.provider, draft, props.service) && locationsComplete;
|
|
5160
|
+
const field = (descriptor) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProviderField, {
|
|
5161
|
+
field: descriptor,
|
|
5162
|
+
value: draft.settings[descriptor.key],
|
|
5163
|
+
layout: "settings",
|
|
5164
|
+
saved: props.service.configuredSecrets.includes(descriptor.key),
|
|
5165
|
+
disabled: props.disabled || saving,
|
|
5166
|
+
onChange: (value) => update(descriptor.key, value)
|
|
5167
|
+
}, descriptor.key);
|
|
5168
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
|
|
5169
|
+
ref: formRef,
|
|
5170
|
+
className: css.providerServiceForm,
|
|
5171
|
+
onSubmit: (event) => void submit(event),
|
|
5172
|
+
"data-provider": props.provider.id,
|
|
5173
|
+
children: [
|
|
5174
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5175
|
+
className: css.providerServicePrompt,
|
|
5176
|
+
children: t(props.service.configured ? "config.providerServiceHint" : "config.providerEnableHint")
|
|
5177
|
+
}),
|
|
5178
|
+
locations.map((location) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.GlobalLocationSetting, {
|
|
5179
|
+
className: css.providerServiceLocation,
|
|
5180
|
+
name: `${props.provider.id}-${location.key}-location`,
|
|
5181
|
+
ariaLabel: `${props.provider.label} ${t("config.providerGlobalLocation")}`,
|
|
5182
|
+
label: t("config.providerGlobalLocation"),
|
|
5183
|
+
hint: t(props.activeScope === "workspace" ? "config.providerGlobalLocationWorkspaceHint" : "config.providerGlobalLocationHint", { provider: props.provider.label }),
|
|
5184
|
+
defaultLabel: t("config.providerDefaultLocation"),
|
|
5185
|
+
customLabel: t("config.custom"),
|
|
5186
|
+
custom: customLocations.has(location.key),
|
|
5187
|
+
workspace: props.activeScope === "workspace",
|
|
5188
|
+
disabled: props.disabled || saving,
|
|
5189
|
+
onInteract: stabilizeLocationCard,
|
|
5190
|
+
onChange: (custom) => useCustomLocation(location, custom),
|
|
5191
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5192
|
+
className: css.providerLocationField,
|
|
5193
|
+
children: field(location)
|
|
5194
|
+
})
|
|
5195
|
+
}, location.key)),
|
|
5196
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5197
|
+
className: css.providerSettingsGrid,
|
|
5198
|
+
children: regularFields.map(field)
|
|
5199
|
+
}),
|
|
5200
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5201
|
+
className: `${css.memoryConfigFooter} ${css.providerServiceFooter}`,
|
|
5202
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5203
|
+
className: css.configFeedback,
|
|
5204
|
+
"aria-live": "polite",
|
|
5205
|
+
children: [failed !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5206
|
+
className: css.error,
|
|
5207
|
+
children: t("config.providerSaveFailed", { error: failed })
|
|
5208
|
+
}), saved && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5209
|
+
className: css.packSuccess,
|
|
5210
|
+
children: t("config.providerServiceSaved")
|
|
5211
|
+
})]
|
|
5212
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5213
|
+
type: "submit",
|
|
5214
|
+
variant: "primary",
|
|
5215
|
+
size: "sm",
|
|
5216
|
+
disabled: props.disabled || saving || !formComplete,
|
|
5217
|
+
children: saving ? t("config.saving") : t(props.service.configured ? "config.saveProviderService" : "config.enableProvider")
|
|
5218
|
+
})]
|
|
5219
|
+
})
|
|
5220
|
+
]
|
|
5221
|
+
});
|
|
5222
|
+
}
|
|
5223
|
+
function ProviderPanel(props) {
|
|
5224
|
+
const t = useT();
|
|
5225
|
+
const css = dsh_mnemon_client.memorySettingsStyles;
|
|
5226
|
+
const [enabled, setEnabled] = (0, react.useState)(props.service.enabled);
|
|
5227
|
+
const [expanded, setExpanded] = (0, react.useState)(props.service.enabled && !props.service.configured);
|
|
5228
|
+
const [toggling, setToggling] = (0, react.useState)(false);
|
|
5229
|
+
const [failed, setFailed] = (0, react.useState)(null);
|
|
5230
|
+
const rowRef = (0, react.useRef)(null);
|
|
5231
|
+
const stabilizeAfterLayout = (0, react.useRef)(false);
|
|
5232
|
+
(0, react.useLayoutEffect)(() => {
|
|
5233
|
+
if (!stabilizeAfterLayout.current || rowRef.current === null) return;
|
|
5234
|
+
stabilizeAfterLayout.current = false;
|
|
5235
|
+
stabilizeProviderCard(rowRef.current);
|
|
5236
|
+
}, [enabled, expanded]);
|
|
5237
|
+
(0, react.useEffect)(() => {
|
|
5238
|
+
if (toggling) return;
|
|
5239
|
+
setEnabled(props.service.enabled);
|
|
5240
|
+
if (!props.service.enabled) setExpanded(false);
|
|
5241
|
+
}, [props.service.enabled, toggling]);
|
|
5242
|
+
const toggle = async (next) => {
|
|
5243
|
+
setFailed(null);
|
|
5244
|
+
stabilizeAfterLayout.current = true;
|
|
5245
|
+
if (next && !props.service.configured) {
|
|
5246
|
+
setEnabled(true);
|
|
5247
|
+
setExpanded(true);
|
|
5248
|
+
return;
|
|
5249
|
+
}
|
|
5250
|
+
if (!next && !props.service.enabled) {
|
|
5251
|
+
setEnabled(false);
|
|
5252
|
+
setExpanded(false);
|
|
5253
|
+
return;
|
|
5254
|
+
}
|
|
5255
|
+
const restoreEnabled = enabled;
|
|
5256
|
+
const restoreExpanded = expanded;
|
|
5257
|
+
setEnabled(next);
|
|
5258
|
+
if (!next && expanded) setExpanded(false);
|
|
5259
|
+
setToggling(true);
|
|
5260
|
+
try {
|
|
5261
|
+
const updated = await props.onToggle(props.provider, next);
|
|
5262
|
+
setEnabled(updated.enabled);
|
|
5263
|
+
if (!next) setExpanded(false);
|
|
5264
|
+
} catch (reason) {
|
|
5265
|
+
setEnabled(restoreEnabled);
|
|
5266
|
+
if (restoreExpanded) setExpanded(true);
|
|
5267
|
+
setFailed((0, dsh_mnemon_client.message)(reason));
|
|
5268
|
+
} finally {
|
|
5269
|
+
setToggling(false);
|
|
5270
|
+
}
|
|
5271
|
+
};
|
|
5272
|
+
const stateKey = enabled ? props.service.configured ? "config.providerEnabled" : "config.providerNeedsConfiguration" : props.service.configured ? "config.providerDisabledConfigured" : "config.providerDisabled";
|
|
5273
|
+
const providerScope = props.provider.workspaceBinding === "provider-global" ? "global" : props.activeScope;
|
|
5274
|
+
const controlDisabled = props.disabled || toggling;
|
|
5275
|
+
const toggleExpanded = () => {
|
|
5276
|
+
stabilizeAfterLayout.current = true;
|
|
5277
|
+
setExpanded((value) => !value);
|
|
5278
|
+
};
|
|
5279
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5280
|
+
ref: rowRef,
|
|
5281
|
+
className: css.providerRow,
|
|
5282
|
+
"data-provider": props.provider.id,
|
|
5283
|
+
"data-enabled": enabled || void 0,
|
|
5284
|
+
"data-expanded": expanded || void 0,
|
|
5285
|
+
role: "group",
|
|
5286
|
+
"aria-label": `${props.provider.label} ${t("config.providerServiceTitle")}`,
|
|
5287
|
+
children: [
|
|
5288
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5289
|
+
className: css.providerRowHeader,
|
|
5290
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
5291
|
+
type: "button",
|
|
5292
|
+
className: css.providerDisclosure,
|
|
5293
|
+
"aria-expanded": expanded,
|
|
5294
|
+
disabled: !enabled || controlDisabled,
|
|
5295
|
+
onClick: toggleExpanded,
|
|
5296
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5297
|
+
className: css.providerIdentity,
|
|
5298
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProviderIcon, {
|
|
5299
|
+
providerId: props.provider.id,
|
|
5300
|
+
icon: props.provider.icon,
|
|
5301
|
+
className: css.providerMark
|
|
5302
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: props.provider.label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: providerSummary(t, props.provider) })] })]
|
|
5303
|
+
}), enabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, {
|
|
5304
|
+
className: css.providerChevron,
|
|
5305
|
+
size: 14
|
|
5306
|
+
})]
|
|
5307
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5308
|
+
className: css.providerEnableControl,
|
|
5309
|
+
children: [
|
|
5310
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5311
|
+
className: css.providerScopeTag,
|
|
5312
|
+
"data-scope": providerScope,
|
|
5313
|
+
children: t(`config.${providerScope}`)
|
|
5314
|
+
}),
|
|
5315
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5316
|
+
className: css.providerState,
|
|
5317
|
+
"data-enabled": enabled || void 0,
|
|
5318
|
+
children: t(stateKey)
|
|
5319
|
+
}),
|
|
5320
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
|
|
5321
|
+
className: css.providerToggle,
|
|
5322
|
+
checked: enabled,
|
|
5323
|
+
label: t("config.providerToggleAria", { provider: props.provider.label }),
|
|
5324
|
+
disabled: controlDisabled,
|
|
5325
|
+
onChange: (next) => void toggle(next)
|
|
5326
|
+
})
|
|
5327
|
+
]
|
|
5328
|
+
})]
|
|
5329
|
+
}),
|
|
5330
|
+
failed !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5331
|
+
className: css.providerToggleError,
|
|
5332
|
+
role: "alert",
|
|
5333
|
+
children: t("config.providerToggleFailed", { error: failed })
|
|
5334
|
+
}),
|
|
5335
|
+
enabled && expanded && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5336
|
+
className: css.providerInlineBody,
|
|
5337
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProviderServiceForm, {
|
|
5338
|
+
provider: props.provider,
|
|
5339
|
+
service: props.service,
|
|
5340
|
+
activeScope: props.activeScope,
|
|
5341
|
+
disabled: controlDisabled,
|
|
5342
|
+
onSave: props.onSave
|
|
5343
|
+
})
|
|
5344
|
+
})
|
|
5345
|
+
]
|
|
5346
|
+
});
|
|
5347
|
+
}
|
|
5348
|
+
/** The Providers that store Memory Spaces, one card each, with what their services need. */
|
|
5349
|
+
function ProviderSettingsSection(props) {
|
|
5350
|
+
const t = useT();
|
|
5351
|
+
const css = dsh_mnemon_client.memorySettingsStyles;
|
|
5352
|
+
const { client, retained } = props;
|
|
5353
|
+
const initialCatalog = client === void 0 ? void 0 : retainedCatalog(retained);
|
|
5354
|
+
const [catalog, setCatalog] = (0, react.useState)(() => initialCatalog ?? EMPTY_PROVIDER_CATALOG);
|
|
5355
|
+
const [loading, setLoading] = (0, react.useState)(client !== void 0 && initialCatalog === void 0);
|
|
5356
|
+
const [failed, setFailed] = (0, react.useState)(null);
|
|
5357
|
+
const loadRequests = (0, dsh_mnemon_client.useRequestVersion)();
|
|
5358
|
+
const load = (0, react.useCallback)(async (quiet = false) => {
|
|
5359
|
+
if (client === void 0) return;
|
|
5360
|
+
const request = loadRequests.begin();
|
|
5361
|
+
if (!quiet) setLoading(true);
|
|
5362
|
+
setFailed(null);
|
|
5363
|
+
try {
|
|
5364
|
+
const next = await client.providerServices();
|
|
5365
|
+
if (!loadRequests.isCurrent(request)) return;
|
|
5366
|
+
retained.set(RETAINED_PROVIDERS, next);
|
|
5367
|
+
setCatalog(next);
|
|
5368
|
+
} catch (reason) {
|
|
5369
|
+
if (!loadRequests.isCurrent(request)) return;
|
|
5370
|
+
setFailed((0, dsh_mnemon_client.message)(reason));
|
|
5371
|
+
} finally {
|
|
5372
|
+
if (!quiet && loadRequests.isCurrent(request)) setLoading(false);
|
|
5373
|
+
}
|
|
5374
|
+
}, [
|
|
5375
|
+
client,
|
|
5376
|
+
loadRequests,
|
|
5377
|
+
retained
|
|
5378
|
+
]);
|
|
5379
|
+
const blocked = props.blocked !== void 0;
|
|
5380
|
+
const pending = props.pending === true;
|
|
5381
|
+
(0, react.useEffect)(() => {
|
|
5382
|
+
if (blocked || pending) {
|
|
5383
|
+
loadRequests.begin();
|
|
5384
|
+
setLoading(pending);
|
|
5385
|
+
setFailed(null);
|
|
5386
|
+
return;
|
|
5387
|
+
}
|
|
5388
|
+
const cached = client === void 0 ? void 0 : retainedCatalog(retained);
|
|
5389
|
+
setCatalog(cached ?? EMPTY_PROVIDER_CATALOG);
|
|
5390
|
+
setLoading(client !== void 0 && cached === void 0);
|
|
5391
|
+
load(cached !== void 0);
|
|
5392
|
+
}, [
|
|
5393
|
+
blocked,
|
|
5394
|
+
client,
|
|
5395
|
+
load,
|
|
5396
|
+
loadRequests,
|
|
5397
|
+
pending,
|
|
5398
|
+
props.refreshKey,
|
|
5399
|
+
retained
|
|
5400
|
+
]);
|
|
5401
|
+
const acceptService = (0, react.useCallback)((service) => {
|
|
5402
|
+
setCatalog((current) => {
|
|
5403
|
+
const items = current.items.some((item) => item.providerId === service.providerId) ? current.items.map((item) => item.providerId === service.providerId ? service : item) : [...current.items, service];
|
|
5404
|
+
const next = {
|
|
5405
|
+
...current,
|
|
5406
|
+
items,
|
|
5407
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5408
|
+
};
|
|
5409
|
+
if (client !== void 0) retained.set(RETAINED_PROVIDERS, next);
|
|
5410
|
+
return next;
|
|
5411
|
+
});
|
|
5412
|
+
}, [client, retained]);
|
|
5413
|
+
const save = async (provider, draft) => {
|
|
5414
|
+
if (client === void 0) throw new Error(t("config.providerUnavailable"));
|
|
5415
|
+
const settings = Object.fromEntries(Object.entries(draft.settings).filter(([key, value]) => serviceFields(provider).find((field) => field.key === key)?.input !== "secret" || String(value).trim() !== ""));
|
|
5416
|
+
acceptService(await client.updateProviderService({
|
|
5417
|
+
providerId: provider.id,
|
|
5418
|
+
settings,
|
|
5419
|
+
enabled: true
|
|
5420
|
+
}));
|
|
5421
|
+
props.onChanged?.();
|
|
5422
|
+
};
|
|
5423
|
+
const toggle = async (provider, enabled) => {
|
|
5424
|
+
if (client === void 0) throw new Error(t("config.providerUnavailable"));
|
|
5425
|
+
const updated = await client.updateProviderService({
|
|
5426
|
+
providerId: provider.id,
|
|
5427
|
+
settings: {},
|
|
5428
|
+
enabled
|
|
5429
|
+
});
|
|
5430
|
+
acceptService(updated);
|
|
5431
|
+
props.onChanged?.();
|
|
5432
|
+
return updated;
|
|
5433
|
+
};
|
|
5434
|
+
const disabled = props.disabled || props.scopeChanging || client === void 0 || loading || catalog.generatedAt === "";
|
|
5435
|
+
if (blocked) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.Reveal, { children: props.blocked }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5436
|
+
className: css.providerList,
|
|
5437
|
+
children: props.leading
|
|
5438
|
+
})] });
|
|
5439
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
5440
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.Reveal, { children: props.notice ?? null }),
|
|
5441
|
+
props.scopeChanging && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5442
|
+
className: css.scopeChanging,
|
|
5443
|
+
role: "status",
|
|
5444
|
+
children: t("config.saveScopeBeforeProviders")
|
|
5445
|
+
}),
|
|
5446
|
+
props.workspaceLabel !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5447
|
+
className: css.providerTarget,
|
|
5448
|
+
children: t("config.providerTargetWorkspace", { workspace: props.workspaceLabel })
|
|
5449
|
+
}),
|
|
5450
|
+
loading && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5451
|
+
className: css.visuallyHidden,
|
|
5452
|
+
role: "status",
|
|
5453
|
+
children: t("config.loadingProviders")
|
|
5454
|
+
}),
|
|
5455
|
+
failed !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5456
|
+
className: css.providerLoadError,
|
|
5457
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5458
|
+
className: css.error,
|
|
5459
|
+
children: t("config.providerLoadFailed", { error: failed })
|
|
5460
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5461
|
+
variant: "ghost",
|
|
5462
|
+
size: "sm",
|
|
5463
|
+
onClick: () => void load(),
|
|
5464
|
+
children: t("config.retryProviders")
|
|
5465
|
+
})]
|
|
5466
|
+
}),
|
|
5467
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5468
|
+
className: css.providerList,
|
|
5469
|
+
"aria-busy": loading,
|
|
5470
|
+
children: [props.leading, catalog.providers.map((provider) => {
|
|
5471
|
+
const service = catalog.items.find((item) => item.providerId === provider.id) ?? {
|
|
5472
|
+
providerId: provider.id,
|
|
5473
|
+
enabled: false,
|
|
5474
|
+
configured: false,
|
|
5475
|
+
settings: {},
|
|
5476
|
+
configuredSecrets: []
|
|
5477
|
+
};
|
|
5478
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProviderPanel, {
|
|
5479
|
+
provider,
|
|
5480
|
+
service,
|
|
5481
|
+
disabled,
|
|
5482
|
+
activeScope: props.activeScope,
|
|
5483
|
+
onSave: save,
|
|
5484
|
+
onToggle: toggle
|
|
5485
|
+
}, provider.id);
|
|
5486
|
+
})]
|
|
5487
|
+
})
|
|
5488
|
+
] });
|
|
5489
|
+
}
|
|
5490
|
+
//#endregion
|
|
5491
|
+
//#region src/client/settings-client.ts
|
|
5492
|
+
const clients = /* @__PURE__ */ new WeakMap();
|
|
5493
|
+
function memorySpacesSettingsClient(operations) {
|
|
5494
|
+
let client = clients.get(operations);
|
|
5495
|
+
if (client === void 0) {
|
|
5496
|
+
client = {
|
|
5497
|
+
statusSummary: () => operations.read("status-summary"),
|
|
5498
|
+
providerServices: () => operations.read("provider-services"),
|
|
5499
|
+
updateProviderService: (request) => operations.write("provider-service-update", JSON.parse(JSON.stringify(request))),
|
|
5500
|
+
embeddingStatus: () => operations.read("embedding-status"),
|
|
5501
|
+
fillEmbeddings: (memoryBodyId) => operations.write("embedding-fill", { memoryBodyId })
|
|
5502
|
+
};
|
|
5503
|
+
clients.set(operations, client);
|
|
5504
|
+
}
|
|
5505
|
+
return client;
|
|
5506
|
+
}
|
|
5507
|
+
//#endregion
|
|
5508
|
+
//#region src/client/settings.tsx
|
|
5509
|
+
/** The package these settings belong to, as Memory Spaces' plugin declaration names it. */
|
|
5510
|
+
const PACKAGE_NAME = "dsh-mnemon-source-memory-spaces";
|
|
5511
|
+
/**
|
|
5512
|
+
* Whether dsh-mnemon yields the settings it keeps for Memory Spaces to these.
|
|
5513
|
+
* One that exports the priority it keeps them at promises both that they do
|
|
5514
|
+
* not collide with these and that it lends these `host`. dsh-mnemon 0.5.31 and
|
|
5515
|
+
* earlier draw them itself and lend nothing, so registering them there would
|
|
5516
|
+
* show a second, unworkable copy.
|
|
5517
|
+
*/
|
|
5518
|
+
function yieldsComponentSettings(client) {
|
|
5519
|
+
return typeof client.MNEMON_COMPONENT_FALLBACK_PRIORITY === "number";
|
|
5520
|
+
}
|
|
5521
|
+
/** Memory Spaces' own settings on its page under Plugins: its Providers and the embedding Mnemon Native reads. */
|
|
5522
|
+
function installMemorySpacesSettings(ctx) {
|
|
5523
|
+
const { locale } = ctx;
|
|
5524
|
+
return (0, dsh_mnemon_client.installMemoryComponentUI)(ctx, {
|
|
5525
|
+
packageName: PACKAGE_NAME,
|
|
5526
|
+
settings: (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemorySpacesSettings, {
|
|
5527
|
+
...props,
|
|
5528
|
+
...locale === void 0 ? {} : { locale }
|
|
5529
|
+
})
|
|
5530
|
+
});
|
|
5531
|
+
}
|
|
5532
|
+
function embeddingDraft(value) {
|
|
5533
|
+
const embedding = value?.embedding;
|
|
5534
|
+
return {
|
|
5535
|
+
endpoint: embedding?.endpoint?.trim() || "http://localhost:11434",
|
|
5536
|
+
model: embedding?.model?.trim() || "nomic-embed-text",
|
|
5537
|
+
apiKey: embedding?.apiKey?.trim() ?? "",
|
|
5538
|
+
protocol: embedding?.protocol ?? "auto"
|
|
5539
|
+
};
|
|
5540
|
+
}
|
|
5541
|
+
function validEmbeddingEndpoint(value) {
|
|
5542
|
+
const endpoint = value.trim();
|
|
5543
|
+
if (endpoint === "" || endpoint.length > 2048) return false;
|
|
5544
|
+
try {
|
|
5545
|
+
const parsed = new URL(endpoint);
|
|
5546
|
+
return ["http:", "https:"].includes(parsed.protocol) && parsed.username === "" && parsed.password === "" && !endpoint.includes("?") && !endpoint.includes("#");
|
|
5547
|
+
} catch {
|
|
5548
|
+
return false;
|
|
5549
|
+
}
|
|
5550
|
+
}
|
|
5551
|
+
function validEmbeddingModel(value) {
|
|
5552
|
+
const model = value.trim();
|
|
5553
|
+
return model.length > 0 && model.length <= 200 && !/[\u0000-\u001f\u007f]/u.test(model);
|
|
5554
|
+
}
|
|
5555
|
+
function validEmbeddingApiKey(value) {
|
|
5556
|
+
const key = value.trim();
|
|
5557
|
+
return key.length <= 2048 && !/[\u0000-\u001f\u007f]/u.test(key);
|
|
5558
|
+
}
|
|
5559
|
+
const validProtocol = (protocol) => MNEMON_EMBEDDING_PROTOCOLS.includes(protocol);
|
|
5560
|
+
function embeddingProblem(draft, t) {
|
|
5561
|
+
if (!validEmbeddingEndpoint(draft.endpoint)) return t("config.embeddingEndpointInvalid");
|
|
5562
|
+
if (!validEmbeddingModel(draft.model)) return t("config.embeddingModelInvalid");
|
|
5563
|
+
if (!validEmbeddingApiKey(draft.apiKey)) return t("config.embeddingApiKeyInvalid");
|
|
5564
|
+
if (!validProtocol(draft.protocol)) return t("config.embeddingProtocolInvalid");
|
|
5565
|
+
return null;
|
|
5566
|
+
}
|
|
5567
|
+
/** The stored value: a switched-off override keeps only the fields that are valid. */
|
|
5568
|
+
function embeddingValue(enabled, draft) {
|
|
5569
|
+
const endpoint = draft.endpoint.trim().replace(/\/+$/u, "");
|
|
5570
|
+
if (enabled) return {
|
|
5571
|
+
enabled: true,
|
|
5572
|
+
endpoint,
|
|
5573
|
+
model: draft.model.trim(),
|
|
5574
|
+
protocol: draft.protocol,
|
|
5575
|
+
apiKey: draft.apiKey.trim()
|
|
5576
|
+
};
|
|
5577
|
+
return {
|
|
5578
|
+
enabled: false,
|
|
5579
|
+
...validEmbeddingEndpoint(draft.endpoint) ? { endpoint } : {},
|
|
5580
|
+
...validEmbeddingModel(draft.model) ? { model: draft.model.trim() } : {},
|
|
5581
|
+
...validProtocol(draft.protocol) ? { protocol: draft.protocol } : {},
|
|
5582
|
+
...validEmbeddingApiKey(draft.apiKey) ? { apiKey: draft.apiKey.trim() } : {}
|
|
5583
|
+
};
|
|
5584
|
+
}
|
|
5585
|
+
/**
|
|
5586
|
+
* Memory Spaces' own settings: the Providers that store its spaces, Mnemon
|
|
5587
|
+
* Native first with the embedding runtime only Native reads. They need what
|
|
5588
|
+
* dsh-mnemon lends them; without it they show nothing. With DSH's language
|
|
5589
|
+
* service they translate as dsh-mnemon drew them, through its language chain.
|
|
5590
|
+
*/
|
|
5591
|
+
function MemorySpacesSettings(props) {
|
|
5592
|
+
if (props.host === void 0) return null;
|
|
5593
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.MemorySourcePageFrame, {
|
|
5594
|
+
locale: props.language,
|
|
5595
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsTranslation, {
|
|
5596
|
+
locale: props.locale,
|
|
5597
|
+
language: props.language,
|
|
5598
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SpacesSettings, {
|
|
5599
|
+
page: props,
|
|
5600
|
+
host: props.host
|
|
5601
|
+
})
|
|
5602
|
+
})
|
|
5603
|
+
});
|
|
5604
|
+
}
|
|
5605
|
+
const noLocaleChanges = () => () => {};
|
|
5606
|
+
function SettingsTranslation(props) {
|
|
5607
|
+
const { locale, language } = props;
|
|
5608
|
+
const subscribe = (0, react.useCallback)((listener) => locale?.subscribe?.(listener) ?? noLocaleChanges(), [locale]);
|
|
5609
|
+
const getChain = (0, react.useCallback)(() => {
|
|
5610
|
+
const snapshot = locale?.getSnapshot?.();
|
|
5611
|
+
return snapshot === void 0 ? "" : languageChain(snapshot).join("\n");
|
|
5612
|
+
}, [locale]);
|
|
5613
|
+
const chain = (0, react.useSyncExternalStore)(subscribe, getChain, getChain);
|
|
5614
|
+
const translate = (0, react.useMemo)(() => locale === void 0 ? void 0 : settingsTranslate(locale, chain === "" ? void 0 : chain.split("\n"), language), [
|
|
5615
|
+
locale,
|
|
5616
|
+
chain,
|
|
5617
|
+
language
|
|
5618
|
+
]);
|
|
5619
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SourceTranslation, {
|
|
5620
|
+
value: translate,
|
|
5621
|
+
children: props.children
|
|
5622
|
+
});
|
|
5623
|
+
}
|
|
5624
|
+
const RETAINED_CLI = "status-summary";
|
|
5625
|
+
function SpacesSettings({ page, host }) {
|
|
5626
|
+
const t = useT();
|
|
5627
|
+
const css = dsh_mnemon_client.memorySettingsStyles;
|
|
5628
|
+
const { configuration, retained } = host;
|
|
5629
|
+
const snapshot = (0, react.useSyncExternalStore)(configuration.subscribe, configuration.getSnapshot, configuration.getSnapshot);
|
|
5630
|
+
const value = snapshot.value;
|
|
5631
|
+
const client = (0, react.useMemo)(() => host.operations === void 0 ? void 0 : memorySpacesSettingsClient(host.operations), [host.operations]);
|
|
5632
|
+
const saved = embeddingDraft(value);
|
|
5633
|
+
const managedSaved = value?.embedding?.enabled === true;
|
|
5634
|
+
const managed = (0, dsh_mnemon_client.useLive)(managedSaved, async (enabled) => {
|
|
5635
|
+
await configuration.set("embedding", embeddingValue(enabled, saved));
|
|
5636
|
+
});
|
|
5637
|
+
const form = (0, dsh_mnemon_client.useStaged)(saved, async (draft) => {
|
|
5638
|
+
await configuration.set("embedding", embeddingValue(managedSaved, draft));
|
|
5639
|
+
});
|
|
5640
|
+
const [nativeCliFound, setNativeCliFound] = (0, react.useState)(() => retained.get(RETAINED_CLI)?.commandFound);
|
|
5641
|
+
const [status, setStatus] = (0, react.useState)({ state: "idle" });
|
|
5642
|
+
const [fill, setFill] = (0, react.useState)(void 0);
|
|
5643
|
+
const statusRequest = (0, react.useRef)(0);
|
|
5644
|
+
const on = page.component.enabled;
|
|
5645
|
+
(0, react.useEffect)(() => {
|
|
5646
|
+
if (client === void 0 || !on) {
|
|
5647
|
+
setNativeCliFound(void 0);
|
|
5648
|
+
retained.delete(RETAINED_CLI);
|
|
5649
|
+
return;
|
|
5650
|
+
}
|
|
5651
|
+
let current = true;
|
|
5652
|
+
client.statusSummary().then((summary) => {
|
|
5653
|
+
if (!current) return;
|
|
5654
|
+
setNativeCliFound(summary.commandFound);
|
|
5655
|
+
retained.set(RETAINED_CLI, { commandFound: summary.commandFound });
|
|
5656
|
+
}, () => {
|
|
5657
|
+
if (current) {
|
|
5658
|
+
setNativeCliFound(void 0);
|
|
5659
|
+
retained.delete(RETAINED_CLI);
|
|
5660
|
+
}
|
|
5661
|
+
});
|
|
5662
|
+
return () => {
|
|
5663
|
+
current = false;
|
|
5664
|
+
};
|
|
5665
|
+
}, [
|
|
5666
|
+
client,
|
|
5667
|
+
on,
|
|
5668
|
+
retained,
|
|
5669
|
+
snapshot.revision
|
|
5670
|
+
]);
|
|
5671
|
+
(0, react.useEffect)(() => () => {
|
|
5672
|
+
retained.delete(RETAINED_CLI);
|
|
5673
|
+
}, [retained]);
|
|
5674
|
+
(0, react.useEffect)(() => {
|
|
5675
|
+
statusRequest.current += 1;
|
|
5676
|
+
setStatus({ state: "idle" });
|
|
5677
|
+
setFill(void 0);
|
|
5678
|
+
}, [client, snapshot.revision]);
|
|
5679
|
+
if (!on) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5680
|
+
className: css.panelNote,
|
|
5681
|
+
children: t("spaces.offNote")
|
|
5682
|
+
});
|
|
5683
|
+
const test = () => {
|
|
5684
|
+
if (client === void 0) return;
|
|
5685
|
+
const request = statusRequest.current + 1;
|
|
5686
|
+
statusRequest.current = request;
|
|
5687
|
+
setStatus((previous) => ({
|
|
5688
|
+
state: "loading",
|
|
5689
|
+
...previous.value === void 0 ? {} : { value: previous.value }
|
|
5690
|
+
}));
|
|
5691
|
+
client.embeddingStatus().then((value) => {
|
|
5692
|
+
if (statusRequest.current === request) setStatus({
|
|
5693
|
+
state: "ready",
|
|
5694
|
+
value
|
|
5695
|
+
});
|
|
5696
|
+
}, (reason) => {
|
|
5697
|
+
if (statusRequest.current === request) setStatus({
|
|
5698
|
+
state: "error",
|
|
5699
|
+
error: (0, dsh_mnemon_client.message)(reason)
|
|
5700
|
+
});
|
|
5701
|
+
});
|
|
5702
|
+
};
|
|
5703
|
+
const fillSpace = (space) => {
|
|
5704
|
+
if (client === void 0 || fill?.state === "running") return;
|
|
5705
|
+
const target = {
|
|
5706
|
+
memoryBodyId: space.memoryBodyId,
|
|
5707
|
+
name: space.name
|
|
5708
|
+
};
|
|
5709
|
+
setFill({
|
|
5710
|
+
...target,
|
|
5711
|
+
state: "running"
|
|
5712
|
+
});
|
|
5713
|
+
client.fillEmbeddings(space.memoryBodyId).then((result) => {
|
|
5714
|
+
setFill({
|
|
5715
|
+
...target,
|
|
5716
|
+
state: "done",
|
|
5717
|
+
result
|
|
5718
|
+
});
|
|
5719
|
+
test();
|
|
5720
|
+
}, (reason) => {
|
|
5721
|
+
setFill({
|
|
5722
|
+
...target,
|
|
5723
|
+
state: "failed",
|
|
5724
|
+
error: (0, dsh_mnemon_client.message)(reason)
|
|
5725
|
+
});
|
|
5726
|
+
test();
|
|
5727
|
+
});
|
|
5728
|
+
};
|
|
5729
|
+
const activeScope = value?.storageScope === "workspace" || value?.storageScope === "workspaces" ? "workspace" : "global";
|
|
5730
|
+
const readOnly = value?.writeEnabled === false;
|
|
5731
|
+
const disabled = !page.writable || snapshot.status === "loading" || !snapshot.writable;
|
|
5732
|
+
const cliMissing = nativeCliFound === false;
|
|
5733
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5734
|
+
className: css.panelSection,
|
|
5735
|
+
"aria-labelledby": "mnemon-spaces-providers",
|
|
5736
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5737
|
+
className: css.panelHeading,
|
|
5738
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
5739
|
+
id: "mnemon-spaces-providers",
|
|
5740
|
+
children: t("config.providersTitle")
|
|
5741
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("config.providersDescription") })]
|
|
5742
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProviderSettingsSection, {
|
|
5743
|
+
client,
|
|
5744
|
+
retained,
|
|
5745
|
+
...activeScope !== "workspace" || page.workspace?.label === void 0 ? {} : { workspaceLabel: page.workspace.label },
|
|
5746
|
+
activeScope,
|
|
5747
|
+
refreshKey: snapshot.revision ?? 0,
|
|
5748
|
+
disabled: disabled || readOnly,
|
|
5749
|
+
scopeChanging: false,
|
|
5750
|
+
onChanged: host.changed,
|
|
5751
|
+
...readOnly ? { notice: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.Callout, {
|
|
5752
|
+
tone: "warning",
|
|
5753
|
+
className: css.groupCallout,
|
|
5754
|
+
title: t("config.providersReadOnlyTitle"),
|
|
5755
|
+
children: t("config.providersReadOnlyDetail")
|
|
5756
|
+
}) } : {},
|
|
5757
|
+
leading: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NativeProviderCard, {
|
|
5758
|
+
activeScope,
|
|
5759
|
+
cliMissing,
|
|
5760
|
+
t,
|
|
5761
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmbeddingEditor, {
|
|
5762
|
+
managed: managed.value,
|
|
5763
|
+
draft: form.draft,
|
|
5764
|
+
disabled,
|
|
5765
|
+
connectionAvailable: client !== void 0,
|
|
5766
|
+
cliMissing,
|
|
5767
|
+
changing: form.dirty,
|
|
5768
|
+
status,
|
|
5769
|
+
t,
|
|
5770
|
+
onEdit: form.edit,
|
|
5771
|
+
onTest: () => {
|
|
5772
|
+
setFill(void 0);
|
|
5773
|
+
test();
|
|
5774
|
+
},
|
|
5775
|
+
canFill: !disabled && !readOnly,
|
|
5776
|
+
fill,
|
|
5777
|
+
onFill: fillSpace,
|
|
5778
|
+
onManaged: (on) => {
|
|
5779
|
+
if (!on) form.discard();
|
|
5780
|
+
managed.set(on);
|
|
5781
|
+
},
|
|
5782
|
+
actions: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.WriteFailure, {
|
|
5783
|
+
error: managed.failed,
|
|
5784
|
+
t
|
|
5785
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.PanelActions, {
|
|
5786
|
+
dirty: form.dirty,
|
|
5787
|
+
saving: form.saving,
|
|
5788
|
+
invalid: embeddingProblem(form.draft, t),
|
|
5789
|
+
failed: form.failed,
|
|
5790
|
+
applied: form.applied,
|
|
5791
|
+
disabled,
|
|
5792
|
+
t,
|
|
5793
|
+
onDiscard: form.discard,
|
|
5794
|
+
onApply: () => {
|
|
5795
|
+
form.apply();
|
|
5796
|
+
}
|
|
5797
|
+
})] })
|
|
5798
|
+
})
|
|
5799
|
+
})
|
|
5800
|
+
})]
|
|
5801
|
+
});
|
|
5802
|
+
}
|
|
5803
|
+
/** Mnemon Native, listed first among the Providers; its body holds the settings only Native reads. */
|
|
5804
|
+
function NativeProviderCard(props) {
|
|
5805
|
+
const css = dsh_mnemon_client.memorySettingsStyles;
|
|
5806
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
5807
|
+
className: css.providerRow,
|
|
5808
|
+
"data-provider": NATIVE_PROVIDER_ID,
|
|
5809
|
+
"data-native": "",
|
|
5810
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", {
|
|
5811
|
+
className: css.providerRowHeader,
|
|
5812
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5813
|
+
className: css.providerIdentity,
|
|
5814
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProviderIcon, {
|
|
5815
|
+
providerId: NATIVE_PROVIDER_ID,
|
|
5816
|
+
icon: {
|
|
5817
|
+
kind: "brand",
|
|
5818
|
+
value: "mnemon"
|
|
5819
|
+
},
|
|
5820
|
+
className: css.providerMark
|
|
5821
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: props.t("config.nativeName") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: props.t("config.nativeSummary") })] })]
|
|
5822
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5823
|
+
className: css.providerEnableControl,
|
|
5824
|
+
children: [
|
|
5825
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5826
|
+
className: css.providerScopeTag,
|
|
5827
|
+
"data-scope": props.activeScope,
|
|
5828
|
+
children: props.t(`config.${props.activeScope}`)
|
|
5829
|
+
}),
|
|
5830
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5831
|
+
className: css.providerState,
|
|
5832
|
+
"data-enabled": props.cliMissing ? void 0 : "",
|
|
5833
|
+
children: props.t(props.cliMissing ? "config.nativeCliMissing" : "config.officialNative")
|
|
5834
|
+
}),
|
|
5835
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, {
|
|
5836
|
+
className: css.providerChevron,
|
|
5837
|
+
size: 14
|
|
5838
|
+
})
|
|
5839
|
+
]
|
|
5840
|
+
})]
|
|
5841
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5842
|
+
className: css.providerInlineBody,
|
|
5843
|
+
children: props.children
|
|
5844
|
+
})]
|
|
5845
|
+
});
|
|
5846
|
+
}
|
|
5847
|
+
/** Reachability and coverage line; the protocol appears only when the Host reports one. */
|
|
5848
|
+
function embeddingStatusText(t, status) {
|
|
5849
|
+
const coverage = {
|
|
5850
|
+
embedded: status.embedded,
|
|
5851
|
+
total: status.totalInsights,
|
|
5852
|
+
coverage: status.coverage
|
|
5853
|
+
};
|
|
5854
|
+
return status.protocol === void 0 ? t(status.available ? "config.embeddingStatusAvailable" : "config.embeddingStatusUnavailable", {
|
|
5855
|
+
model: status.model,
|
|
5856
|
+
...coverage
|
|
5857
|
+
}) : t(status.available ? "config.embeddingStatusAvailableWithProtocol" : "config.embeddingStatusUnavailableWithProtocol", {
|
|
5858
|
+
model: status.model,
|
|
5859
|
+
protocol: status.protocol,
|
|
5860
|
+
...coverage
|
|
5861
|
+
});
|
|
5862
|
+
}
|
|
5863
|
+
/** The embedding runtime: the switch applies at once; the connection fields, shown while DSH manages it, wait for Apply. */
|
|
5864
|
+
function EmbeddingEditor(props) {
|
|
5865
|
+
const { draft, t, status } = props;
|
|
5866
|
+
const css = dsh_mnemon_client.memorySettingsStyles;
|
|
5867
|
+
const feedback = props.cliMissing ? t("config.embeddingCliMissing") : props.changing ? t("config.embeddingSaveBeforeTest") : status.state === "loading" ? t("config.embeddingTesting") : status.state === "error" ? t("config.embeddingStatusFailed", { error: status.error ?? "" }) : status.state === "ready" && status.value !== void 0 ? embeddingStatusText(t, status.value) : !props.connectionAvailable ? t("config.embeddingTestUnavailable") : t("config.embeddingNotTested");
|
|
5868
|
+
const text = (field, type, label, valid, placeholder) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [label, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5869
|
+
type,
|
|
5870
|
+
"aria-label": label,
|
|
5871
|
+
"aria-invalid": !valid,
|
|
5872
|
+
value: draft[field],
|
|
5873
|
+
disabled: props.disabled,
|
|
5874
|
+
autoComplete: "off",
|
|
5875
|
+
spellCheck: false,
|
|
5876
|
+
autoCapitalize: "none",
|
|
5877
|
+
autoCorrect: "off",
|
|
5878
|
+
placeholder,
|
|
5879
|
+
onChange: (event) => props.onEdit({ [field]: event.target.value })
|
|
5880
|
+
})] });
|
|
5881
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5882
|
+
className: css.editor,
|
|
5883
|
+
"aria-labelledby": "mnemon-embedding-heading",
|
|
5884
|
+
children: [
|
|
5885
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5886
|
+
className: css.editorHeading,
|
|
5887
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
5888
|
+
id: "mnemon-embedding-heading",
|
|
5889
|
+
children: t("config.embeddingTitle")
|
|
5890
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("config.embeddingDescription") })]
|
|
5891
|
+
}),
|
|
5892
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.ToggleRow, {
|
|
5893
|
+
id: "mnemon-embedding-managed",
|
|
5894
|
+
label: t("config.embeddingManaged"),
|
|
5895
|
+
hint: t("config.embeddingManagedHint"),
|
|
5896
|
+
checked: props.managed,
|
|
5897
|
+
disabled: props.disabled,
|
|
5898
|
+
onChange: props.onManaged
|
|
5899
|
+
}),
|
|
5900
|
+
props.managed && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5901
|
+
className: css.fieldGrid,
|
|
5902
|
+
children: [
|
|
5903
|
+
text("endpoint", "url", t("config.embeddingEndpoint"), validEmbeddingEndpoint(draft.endpoint), "http://localhost:11434"),
|
|
5904
|
+
text("model", "text", t("config.embeddingModel"), validEmbeddingModel(draft.model), "nomic-embed-text"),
|
|
5905
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.SelectField, {
|
|
5906
|
+
label: t("config.embeddingProtocol"),
|
|
5907
|
+
value: draft.protocol,
|
|
5908
|
+
disabled: props.disabled,
|
|
5909
|
+
options: [
|
|
5910
|
+
{
|
|
5911
|
+
value: "auto",
|
|
5912
|
+
label: t("config.embeddingProtocolAuto")
|
|
5913
|
+
},
|
|
5914
|
+
{
|
|
5915
|
+
value: "ollama",
|
|
5916
|
+
label: t("config.embeddingProtocolOllama")
|
|
5917
|
+
},
|
|
5918
|
+
{
|
|
5919
|
+
value: "openai",
|
|
5920
|
+
label: t("config.embeddingProtocolOpenai")
|
|
5921
|
+
}
|
|
5922
|
+
],
|
|
5923
|
+
onChange: (protocol) => props.onEdit({ protocol })
|
|
5924
|
+
}),
|
|
5925
|
+
text("apiKey", "password", t("config.embeddingApiKey"), validEmbeddingApiKey(draft.apiKey), "sk-…")
|
|
5926
|
+
]
|
|
5927
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5928
|
+
className: css.editorNote,
|
|
5929
|
+
children: t("config.embeddingSecurity")
|
|
5930
|
+
})] }),
|
|
5931
|
+
props.actions,
|
|
5932
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5933
|
+
className: css.embeddingTest,
|
|
5934
|
+
"aria-live": "polite",
|
|
5935
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5936
|
+
className: status.state === "error" ? css.error : void 0,
|
|
5937
|
+
role: status.state === "error" ? "alert" : void 0,
|
|
5938
|
+
children: feedback
|
|
5939
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5940
|
+
variant: "outline",
|
|
5941
|
+
size: "sm",
|
|
5942
|
+
disabled: props.disabled || !props.connectionAvailable || props.cliMissing || props.changing || status.state === "loading" || props.fill?.state === "running",
|
|
5943
|
+
onClick: props.onTest,
|
|
5944
|
+
children: t("config.embeddingTest")
|
|
5945
|
+
})]
|
|
5946
|
+
}),
|
|
5947
|
+
!props.cliMissing && !props.changing && (status.state === "ready" || status.state === "loading") && (status.value?.spaces ?? []).length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmbeddingSpaces, {
|
|
5948
|
+
spaces: status.value.spaces,
|
|
5949
|
+
available: status.value.available,
|
|
5950
|
+
canFill: props.canFill,
|
|
5951
|
+
counting: status.state === "loading",
|
|
5952
|
+
fill: props.fill,
|
|
5953
|
+
onFill: props.onFill,
|
|
5954
|
+
t
|
|
5955
|
+
}),
|
|
5956
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmbeddingFillOutcome, {
|
|
5957
|
+
fill: props.fill,
|
|
5958
|
+
t
|
|
5959
|
+
})
|
|
5960
|
+
]
|
|
5961
|
+
});
|
|
5962
|
+
}
|
|
5963
|
+
/**
|
|
5964
|
+
* Each Mnemon Native space's vectors under the status line. Mnemon counts one Store at a
|
|
5965
|
+
* time, so the total alone could read as every space's health while one lacked vectors (#392).
|
|
5966
|
+
* A space that lacks them can have them filled in here while the embedding service answers.
|
|
5967
|
+
*/
|
|
5968
|
+
function EmbeddingSpaces(props) {
|
|
5969
|
+
const { t, fill } = props;
|
|
5970
|
+
const css = dsh_mnemon_client.memorySettingsStyles;
|
|
5971
|
+
const missing = (space) => space.error === void 0 && space.embedded < space.totalInsights;
|
|
5972
|
+
const fillable = props.available && props.canFill;
|
|
5973
|
+
const running = fill?.state === "running" ? fill.memoryBodyId : void 0;
|
|
5974
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5975
|
+
className: css.embeddingSpaces,
|
|
5976
|
+
children: [
|
|
5977
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", {
|
|
5978
|
+
id: "mnemon-embedding-spaces",
|
|
5979
|
+
children: t("config.embeddingSpaces")
|
|
5980
|
+
}),
|
|
5981
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
5982
|
+
"aria-labelledby": "mnemon-embedding-spaces",
|
|
5983
|
+
children: props.spaces.map((space) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
5984
|
+
"data-missing": missing(space) ? "" : void 0,
|
|
5985
|
+
"data-failed": space.error === void 0 ? void 0 : "",
|
|
5986
|
+
children: [
|
|
5987
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5988
|
+
className: css.embeddingSpaceName,
|
|
5989
|
+
title: space.name,
|
|
5990
|
+
children: space.name
|
|
5991
|
+
}),
|
|
5992
|
+
!space.active && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5993
|
+
className: css.embeddingSpaceState,
|
|
5994
|
+
children: t("common.inactive")
|
|
5995
|
+
}),
|
|
5996
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5997
|
+
className: css.embeddingSpaceCount,
|
|
5998
|
+
children: space.error === void 0 ? t("config.embeddingSpaceCounts", {
|
|
5999
|
+
embedded: space.embedded,
|
|
6000
|
+
total: space.totalInsights,
|
|
6001
|
+
coverage: space.coverage
|
|
6002
|
+
}) : t("config.embeddingSpaceFailed", { error: space.error })
|
|
6003
|
+
}),
|
|
6004
|
+
fillable && missing(space) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
6005
|
+
variant: "ghost",
|
|
6006
|
+
size: "sm",
|
|
6007
|
+
disabled: running !== void 0 || props.counting,
|
|
6008
|
+
"aria-busy": running === space.memoryBodyId,
|
|
6009
|
+
"aria-label": t(running === space.memoryBodyId ? "config.embeddingFillingLabel" : "config.embeddingFillLabel", { name: space.name }),
|
|
6010
|
+
onClick: () => props.onFill(space),
|
|
6011
|
+
children: running === space.memoryBodyId ? t("config.embeddingFilling") : t("config.embeddingFill")
|
|
6012
|
+
})
|
|
6013
|
+
]
|
|
6014
|
+
}, space.memoryBodyId))
|
|
6015
|
+
}),
|
|
6016
|
+
props.spaces.some(missing) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t(!props.canFill ? "config.embeddingMissing" : props.available ? "config.embeddingMissingFill" : "config.embeddingMissingOffline") }),
|
|
6017
|
+
props.spaces.some((space) => space.error !== void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("config.embeddingSpacesUnread") })
|
|
6018
|
+
]
|
|
6019
|
+
});
|
|
6020
|
+
}
|
|
6021
|
+
/** What the last fill did. It stays while the counts are read again, and reads as a failure when it wrote no vector. */
|
|
6022
|
+
function EmbeddingFillOutcome(props) {
|
|
6023
|
+
const { fill, t } = props;
|
|
6024
|
+
const css = dsh_mnemon_client.memorySettingsStyles;
|
|
6025
|
+
if (fill === void 0 || fill.state === "running") return null;
|
|
6026
|
+
const failure = (text) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6027
|
+
className: `${css.embeddingFillOutcome} ${css.error}`,
|
|
6028
|
+
role: "alert",
|
|
6029
|
+
children: text
|
|
6030
|
+
});
|
|
6031
|
+
if (fill.state === "failed") return failure(t("config.embeddingFillFailed", {
|
|
6032
|
+
name: fill.name,
|
|
6033
|
+
error: fill.error
|
|
6034
|
+
}));
|
|
6035
|
+
const { filled, remaining, model, stopped } = fill.result;
|
|
6036
|
+
const name = fill.name;
|
|
6037
|
+
if (remaining > 0 && stopped === "refused" && filled === 0) return failure(t("config.embeddingFillRefused", {
|
|
6038
|
+
name,
|
|
6039
|
+
model
|
|
6040
|
+
}));
|
|
6041
|
+
const text = remaining === 0 ? filled > 0 ? t("config.embeddingFillDone", {
|
|
6042
|
+
name,
|
|
6043
|
+
filled
|
|
6044
|
+
}) : void 0 : stopped === "refused" ? t("config.embeddingFillPartly", {
|
|
6045
|
+
name,
|
|
6046
|
+
filled,
|
|
6047
|
+
remaining
|
|
6048
|
+
}) : t("config.embeddingFillMore", {
|
|
6049
|
+
name,
|
|
6050
|
+
filled,
|
|
6051
|
+
remaining
|
|
6052
|
+
});
|
|
6053
|
+
return text === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6054
|
+
className: css.embeddingFillOutcome,
|
|
6055
|
+
role: "status",
|
|
6056
|
+
children: text
|
|
6057
|
+
});
|
|
6058
|
+
}
|
|
4584
6059
|
//#endregion
|
|
4585
6060
|
//#region src/client/ui.tsx
|
|
4586
6061
|
/** The adapter never gets a transport or chooses another Source instance. */
|
|
@@ -4820,6 +6295,7 @@ window.__ModuleLoader__.load({
|
|
|
4820
6295
|
memoryBodies: bodies,
|
|
4821
6296
|
writeEnabled: writable,
|
|
4822
6297
|
seed,
|
|
6298
|
+
embeddingManaged: status?.embeddingManaged,
|
|
4823
6299
|
onMutate: refresh,
|
|
4824
6300
|
onClose: () => setRememberOpen(false),
|
|
4825
6301
|
onView: () => {
|
|
@@ -4900,14 +6376,18 @@ window.__ModuleLoader__.load({
|
|
|
4900
6376
|
const inject = ["slots", "locale"];
|
|
4901
6377
|
function apply(ctx) {
|
|
4902
6378
|
installMemorySpacesUI(ctx, ctx.locale.bind("mnemon"));
|
|
6379
|
+
if (yieldsComponentSettings(dsh_mnemon_client)) installMemorySpacesSettings(ctx);
|
|
4903
6380
|
}
|
|
4904
6381
|
//#endregion
|
|
4905
6382
|
exports.EntitiesPage = EntitiesPage;
|
|
4906
6383
|
exports.ExplorePage = ExplorePage;
|
|
4907
6384
|
exports.ListPage = ListPage;
|
|
6385
|
+
exports.MemorySpacesSettings = MemorySpacesSettings;
|
|
4908
6386
|
exports.MemorySpacesSourcePage = MemorySpacesSourcePage;
|
|
6387
|
+
exports.NATIVE_PROVIDER_ID = NATIVE_PROVIDER_ID;
|
|
4909
6388
|
exports.OverviewPage = OverviewPage;
|
|
4910
6389
|
exports.PersistenceStrategyDialog = PersistenceStrategyDialog;
|
|
6390
|
+
exports.ProviderIcon = ProviderIcon;
|
|
4911
6391
|
exports.RememberPage = RememberPage;
|
|
4912
6392
|
exports.apply = apply;
|
|
4913
6393
|
exports.inject = inject;
|