dsh-mnemon 0.2.1 → 0.2.2

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 CHANGED
@@ -3,7 +3,7 @@
3
3
  <p align="center"><strong>English</strong> · <a href="./README.zh-CN.md">简体中文</a></p>
4
4
 
5
5
  <p align="center">
6
- <img src="https://img.shields.io/badge/release-v0.2.1-5b5bd6" alt="release v0.2.1">
6
+ <img src="https://img.shields.io/badge/release-v0.2.2-5b5bd6" alt="release v0.2.2">
7
7
  <img src="https://img.shields.io/badge/memory-3%20tiers-087c5b" alt="three memory tiers">
8
8
  <img src="https://img.shields.io/badge/providers-9-c66a09" alt="nine providers">
9
9
  <img src="https://img.shields.io/badge/Node.js-%E2%89%A520-43853d" alt="Node.js 20 or newer">
@@ -22,7 +22,7 @@
22
22
  <p align="center">
23
23
  <a href="./docs/en/capabilities.md"><strong>Explore the capability map</strong></a> ·
24
24
  <a href="./docs/en/getting-started.md">Start in five minutes</a> ·
25
- <a href="./docs/en/releases/v0.2.1.md">Read the v0.2.1 notes</a> ·
25
+ <a href="./docs/en/releases/v0.2.2.md">Read the v0.2.2 notes</a> ·
26
26
  <a href="https://github.com/omdsh-dev/dsh-mnemon/blob/e6ca446e45bdd17991f3c7c98560456de465282b/docs/assets/media/dsh-mnemon-memory-system-demo.mp4">Watch the widescreen demo</a>
27
27
  </p>
28
28
 
@@ -190,7 +190,7 @@ See [Operations, security, and troubleshooting](./docs/en/operations.md) for bac
190
190
  | Configure scope, routing, and model selection | [Configuration](./docs/en/configuration.md) |
191
191
  | Back up, update, or troubleshoot | [Operations](./docs/en/operations.md) |
192
192
  | Integrate tools, commands, or RPC | [Interface reference](./docs/en/interfaces.md) |
193
- | Review the release | [v0.2.1 release notes](./docs/en/releases/v0.2.1.md) |
193
+ | Review the release | [v0.2.2 release notes](./docs/en/releases/v0.2.2.md) |
194
194
 
195
195
  See the [documentation hub](./docs/en/README.md) for the full map.
196
196
 
package/README.zh-CN.md CHANGED
@@ -3,7 +3,7 @@
3
3
  <p align="center"><a href="./README.md">English</a> · <strong>简体中文</strong></p>
4
4
 
5
5
  <p align="center">
6
- <img src="https://img.shields.io/badge/release-v0.2.1-5b5bd6" alt="发布版本 v0.2.1">
6
+ <img src="https://img.shields.io/badge/release-v0.2.2-5b5bd6" alt="发布版本 v0.2.2">
7
7
  <img src="https://img.shields.io/badge/%E8%AE%B0%E5%BF%86-3%20%E5%B1%82-087c5b" alt="三层记忆">
8
8
  <img src="https://img.shields.io/badge/Provider-9-c66a09" alt="九种 Provider">
9
9
  <img src="https://img.shields.io/badge/Node.js-%E2%89%A520-43853d" alt="Node.js 20 或更新版本">
@@ -22,7 +22,7 @@
22
22
  <p align="center">
23
23
  <a href="./docs/zh-CN/capabilities.md"><strong>先看能力地图</strong></a> ·
24
24
  <a href="./docs/zh-CN/getting-started.md">5 分钟开始</a> ·
25
- <a href="./docs/zh-CN/releases/v0.2.1.md">v0.2.1 升级说明</a> ·
25
+ <a href="./docs/zh-CN/releases/v0.2.2.md">v0.2.2 升级说明</a> ·
26
26
  <a href="https://github.com/omdsh-dev/dsh-mnemon/blob/e6ca446e45bdd17991f3c7c98560456de465282b/docs/assets/media/dsh-mnemon-memory-system-demo.mp4">观看宽屏实机演示</a>
27
27
  </p>
28
28
 
@@ -190,7 +190,7 @@ dsh plugin --profile headless add "link:/absolute/path/to/dsh-mnemon"
190
190
  | 配置范围、路由与模型 | [配置参考](./docs/zh-CN/configuration.md) |
191
191
  | 备份、更新或排障 | [运维指南](./docs/zh-CN/operations.md) |
192
192
  | 接入工具、命令或 RPC | [接口参考](./docs/zh-CN/interfaces.md) |
193
- | 查看本次升级 | [v0.2.1 发布说明](./docs/zh-CN/releases/v0.2.1.md) |
193
+ | 查看本次升级 | [v0.2.2 发布说明](./docs/zh-CN/releases/v0.2.2.md) |
194
194
 
195
195
  完整目录见[文档中心](./docs/zh-CN/README.md)。
196
196
 
package/lib/client.js CHANGED
@@ -33,6 +33,7 @@ window.__ModuleLoader__.load({
33
33
  let react_dom_client = require("react-dom/client");
34
34
  //#region src/shared/contracts.ts
35
35
  const MNEMON_READ_CHANNEL = "/dsh-mnemon-read";
36
+ const MNEMON_ACTIVATION_CHANNEL = "/dsh-mnemon-activation";
36
37
  const MNEMON_WRITE_CHANNEL = "/dsh-mnemon-write";
37
38
  const MNEMON_PACK_CHANNEL = "/dsh-mnemon-pack";
38
39
  const MNEMON_SETTINGS_CHANNEL = "/dsh-mnemon-settings";
@@ -49,6 +50,15 @@ window.__ModuleLoader__.load({
49
50
  //#endregion
50
51
  //#region src/client/api.ts
51
52
  const turnActivityCache = /* @__PURE__ */ new WeakMap();
53
+ function isActivationOnly(request) {
54
+ return typeof request.active === "boolean" && Object.entries(request).every(([field, value]) => field === "active" || value === void 0);
55
+ }
56
+ function isMissingActivationChannel(reason) {
57
+ return reason instanceof Error && reason.message === `transport failure for /dsh-mnemon-activation/body: HTTP 404`;
58
+ }
59
+ function isMissingPrivateProviderServices(reason) {
60
+ return reason instanceof Error && reason.message === "unknown write endpoint: provider-services";
61
+ }
52
62
  async function loadTurnActivities(connection, sessionId, requiredCursor) {
53
63
  let sessions = turnActivityCache.get(connection);
54
64
  if (sessions === void 0) {
@@ -155,7 +165,11 @@ window.__ModuleLoader__.load({
155
165
  return this.call(MNEMON_READ_CHANNEL, "body-directory", this.scoped()).catch(() => this.bodies());
156
166
  }
157
167
  providerServices() {
158
- return this.call(MNEMON_READ_CHANNEL, "provider-services", this.scoped());
168
+ const payload = this.scoped();
169
+ return this.call(MNEMON_WRITE_CHANNEL, "provider-services", payload).catch((reason) => {
170
+ if (!isMissingPrivateProviderServices(reason)) throw reason;
171
+ return this.call(MNEMON_READ_CHANNEL, "provider-services", payload);
172
+ });
159
173
  }
160
174
  updateProviderService(request) {
161
175
  return this.call(MNEMON_WRITE_CHANNEL, "provider-service-update", this.scoped(request));
@@ -215,10 +229,18 @@ window.__ModuleLoader__.load({
215
229
  return this.call(MNEMON_WRITE_CHANNEL, "body-create", this.scoped(request));
216
230
  }
217
231
  updateBody(memoryBodyId, request) {
218
- return this.call(MNEMON_WRITE_CHANNEL, "body-update", this.scoped({
232
+ if (!isActivationOnly(request)) return this.call(MNEMON_WRITE_CHANNEL, "body-update", this.scoped({
219
233
  memoryBodyId,
220
234
  ...request
221
235
  }));
236
+ const payload = this.scoped({
237
+ memoryBodyId,
238
+ active: request.active
239
+ });
240
+ return this.call(MNEMON_ACTIVATION_CHANNEL, "body", payload).catch((reason) => {
241
+ if (!isMissingActivationChannel(reason)) throw reason;
242
+ return this.call(MNEMON_WRITE_CHANNEL, "body-update", payload);
243
+ });
222
244
  }
223
245
  reconnectBody(memoryBodyId) {
224
246
  return this.call(MNEMON_WRITE_CHANNEL, "body-reconnect", this.scoped({ memoryBodyId }));
@@ -416,6 +438,7 @@ window.__ModuleLoader__.load({
416
438
  "common.cancel": "取消",
417
439
  "common.copyId": "复制 ID",
418
440
  "common.readOnly": "只读模式",
441
+ "common.activationOnly": "仅可切换激活状态",
419
442
  "common.agentSupervised": "独立任务 Agent",
420
443
  "common.active": "已激活",
421
444
  "common.inactive": "未激活",
@@ -1271,6 +1294,7 @@ window.__ModuleLoader__.load({
1271
1294
  "common.cancel": "Cancel",
1272
1295
  "common.copyId": "Copy ID",
1273
1296
  "common.readOnly": "Read only",
1297
+ "common.activationOnly": "Activation control only",
1274
1298
  "common.agentSupervised": "Subagent supervised",
1275
1299
  "common.active": "Active",
1276
1300
  "common.inactive": "Inactive",
@@ -2138,7 +2162,7 @@ window.__ModuleLoader__.load({
2138
2162
  return `${(bytes / 1048576).toFixed(1)} MB`;
2139
2163
  }
2140
2164
  function MnemonPackSection({ connection, sessionId, workspaceId, refreshKey, t, embedded = false }) {
2141
- const client = (0, react.useMemo)(() => connection === void 0 ? null : new MnemonClient(connection, sessionId, workspaceId), [
2165
+ const client = (0, react.useMemo)(() => connection === void 0 || connection.isLoopback === false ? null : new MnemonClient(connection, sessionId, workspaceId), [
2142
2166
  connection,
2143
2167
  sessionId,
2144
2168
  workspaceId
@@ -2968,7 +2992,7 @@ window.__ModuleLoader__.load({
2968
2992
  });
2969
2993
  }
2970
2994
  function ProviderSettingsSection(props) {
2971
- const client = (0, react.useMemo)(() => props.connection === void 0 ? null : new MnemonClient(props.connection, props.sessionId, props.workspaceId), [
2995
+ const client = (0, react.useMemo)(() => props.connection === void 0 || props.connection.isLoopback === false ? null : new MnemonClient(props.connection, props.sessionId, props.workspaceId), [
2972
2996
  props.connection,
2973
2997
  props.sessionId,
2974
2998
  props.workspaceId
@@ -3250,7 +3274,8 @@ window.__ModuleLoader__.load({
3250
3274
  const activeScope = coreDraft(coreSnapshot.value).storageScope === "workspace" ? "workspace" : "global";
3251
3275
  const error = validation(t, draft);
3252
3276
  const loading = coreSnapshot.status === "loading" || interactionSnapshot.status === "loading";
3253
- const writable = coreSnapshot.writable && interactionSnapshot.writable;
3277
+ const localWrites = connection?.isLoopback !== false;
3278
+ const writable = localWrites && coreSnapshot.writable && interactionSnapshot.writable;
3254
3279
  if (coreSnapshot.status === "unavailable" && interactionSnapshot.status === "unavailable") return null;
3255
3280
  const edit = (field, value) => {
3256
3281
  setDraft((current) => ({
@@ -3314,8 +3339,8 @@ window.__ModuleLoader__.load({
3314
3339
  setSaving(false);
3315
3340
  }
3316
3341
  };
3317
- const coreDisabled = loading || saving || !coreSnapshot.writable;
3318
- const interactionDisabled = loading || saving || !interactionSnapshot.writable;
3342
+ const coreDisabled = loading || saving || !localWrites || !coreSnapshot.writable;
3343
+ const interactionDisabled = loading || saving || !localWrites || !interactionSnapshot.writable;
3319
3344
  const scopeChanging = dirty.has("storageScope") || dirty.has("dataDir");
3320
3345
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
3321
3346
  className: MnemonSettingsCard_module_css_default.page,
@@ -5715,7 +5740,7 @@ window.__ModuleLoader__.load({
5715
5740
  children: [
5716
5741
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("sidebar.activeSpaces") }),
5717
5742
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: props.catalogKnown ? `${props.activeBodies} / ${props.bodyCount}` : "— / —" }),
5718
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: props.writeEnabled ? t("common.agentSupervised") : t("common.readOnly") })
5743
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: props.writeEnabled ? t("common.agentSupervised") : props.activationEnabled ? t("common.activationOnly") : t("common.readOnly") })
5719
5744
  ]
5720
5745
  })]
5721
5746
  });
@@ -5730,6 +5755,7 @@ window.__ModuleLoader__.load({
5730
5755
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageHeader, {
5731
5756
  title: t("nav.bodies"),
5732
5757
  description: t("overview.description"),
5758
+ meta: props.writeEnabled ? t("common.agentSupervised") : props.activationEnabled ? t("common.activationOnly") : t("common.readOnly"),
5733
5759
  action: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5734
5760
  className: MnemonView_module_css_default.memoryHeaderActions,
5735
5761
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -7099,7 +7125,7 @@ window.__ModuleLoader__.load({
7099
7125
  role: "switch",
7100
7126
  "aria-checked": body.active,
7101
7127
  "aria-label": t("overview.toggleAria", { name: body.name }),
7102
- disabled: !props.writeEnabled || changing === body.id || deletingBody === body.id,
7128
+ disabled: !props.activationEnabled || changing === body.id || deletingBody === body.id,
7103
7129
  onClick: () => void toggle(body),
7104
7130
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7105
7131
  className: MnemonView_module_css_default.bodySwitchTrack,
@@ -10012,7 +10038,7 @@ window.__ModuleLoader__.load({
10012
10038
  snapshot !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
10013
10039
  className: MnemonView_module_css_default.versionList,
10014
10040
  children: snapshot.components.map((component) => {
10015
- const canUpdate = component.outdated && component.updateSupported && component.checkError === void 0;
10041
+ const canUpdate = props.writeEnabled && component.outdated && component.updateSupported && component.checkError === void 0;
10016
10042
  const state = component.checkError !== void 0 ? t("versions.unknown") : component.outdated ? t("versions.available") : t("versions.current");
10017
10043
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
10018
10044
  "data-outdated": component.outdated || void 0,
@@ -10162,6 +10188,7 @@ window.__ModuleLoader__.load({
10162
10188
  }),
10163
10189
  versionsOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VersionDialog, {
10164
10190
  client: props.client,
10191
+ writeEnabled: props.writeEnabled,
10165
10192
  onClose: () => setVersionsOpen(false),
10166
10193
  onRefreshStatus: props.onRefresh
10167
10194
  })
@@ -10559,7 +10586,8 @@ window.__ModuleLoader__.load({
10559
10586
  setRevision((value) => value + 1);
10560
10587
  loadStatus();
10561
10588
  };
10562
- const writeEnabled = status?.writeEnabled === true;
10589
+ const activationEnabled = status?.writeEnabled === true;
10590
+ const writeEnabled = activationEnabled && connection.isLoopback !== false;
10563
10591
  const stats = status?.stats;
10564
10592
  const catalogKnown = status?.memoryBodies !== void 0;
10565
10593
  const memoryBodies = (0, react.useMemo)(() => (status?.memoryBodies ?? []).map(normalizeMemoryBody), [status]);
@@ -10693,10 +10721,12 @@ window.__ModuleLoader__.load({
10693
10721
  activeBodies,
10694
10722
  bodyCount: memoryBodies.length,
10695
10723
  catalogKnown,
10724
+ activationEnabled,
10696
10725
  writeEnabled
10697
10726
  }),
10698
10727
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoryNavigation, {
10699
10728
  page,
10729
+ activationEnabled,
10700
10730
  writeEnabled,
10701
10731
  onSelect: selectPage,
10702
10732
  onRemember: () => openRemember(),
@@ -10712,6 +10742,7 @@ window.__ModuleLoader__.load({
10712
10742
  client,
10713
10743
  metadataClient: taskClient,
10714
10744
  revision,
10745
+ activationEnabled,
10715
10746
  writeEnabled,
10716
10747
  agentAvailable: taskAgentAvailable,
10717
10748
  fallbackBodies: memoryBodies,
@@ -10772,6 +10803,7 @@ window.__ModuleLoader__.load({
10772
10803
  client,
10773
10804
  status,
10774
10805
  loading: statusLoading,
10806
+ writeEnabled,
10775
10807
  onRefresh: () => void loadStatus()
10776
10808
  })
10777
10809
  ]
@@ -10993,7 +11025,7 @@ window.__ModuleLoader__.load({
10993
11025
  setSubmitting(submitActiveRef.current);
10994
11026
  const client = new MnemonClient(connection, sessionId);
10995
11027
  client.status().then((status) => {
10996
- if (alive && requestVersionRef.current === requestVersion) setWriteEnabled(status.writeEnabled);
11028
+ if (alive && requestVersionRef.current === requestVersion) setWriteEnabled(status.writeEnabled && connection.isLoopback !== false);
10997
11029
  }).catch(() => {
10998
11030
  if (alive && requestVersionRef.current === requestVersion) setWriteEnabled(false);
10999
11031
  });
package/lib/index.js CHANGED
@@ -5365,6 +5365,7 @@ var HindsightProvider = class extends HttpMemoryProvider {
5365
5365
  //#endregion
5366
5366
  //#region src/shared/contracts.ts
5367
5367
  const MNEMON_READ_CHANNEL = "/dsh-mnemon-read";
5368
+ const MNEMON_ACTIVATION_CHANNEL = "/dsh-mnemon-activation";
5368
5369
  const MNEMON_WRITE_CHANNEL = "/dsh-mnemon-write";
5369
5370
  const MNEMON_PACK_CHANNEL = "/dsh-mnemon-pack";
5370
5371
  const MNEMON_SETTINGS_CHANNEL = "/dsh-mnemon-settings";
@@ -9139,7 +9140,7 @@ function createReadHandler(input, lifecycle, runtimeMemory, storage, versions) {
9139
9140
  case "graph": return success$1(await service.graph(void 0, Array.isArray(payload.memoryBodyIds) ? payload.memoryBodyIds.map(String) : void 0));
9140
9141
  case "bodies": return success$1(await service.bodies());
9141
9142
  case "body-directory": return success$1(service.bodyDirectory());
9142
- case "provider-services": return success$1(service.memoryBodies.providerServices({ includeSecrets: true }));
9143
+ case "provider-services": return success$1(service.memoryBodies.providerServices());
9143
9144
  case "list": return success$1(await service.list({
9144
9145
  ...payload.query === void 0 ? {} : { query: String(payload.query) },
9145
9146
  ...payload.category === void 0 ? {} : { category: payload.category },
@@ -9198,6 +9199,36 @@ function createReadHandler(input, lifecycle, runtimeMemory, storage, versions) {
9198
9199
  }
9199
9200
  };
9200
9201
  }
9202
+ const ACTIVATION_PAYLOAD_FIELDS = /* @__PURE__ */ new Set([
9203
+ "memoryBodyId",
9204
+ "active",
9205
+ "sessionId",
9206
+ "workspaceId"
9207
+ ]);
9208
+ /**
9209
+ * Expose only DSH read-routing activation to trusted Web hosts. Metadata,
9210
+ * provider connections, credentials, and durable memory writes stay on the
9211
+ * loopback-only write channel.
9212
+ */
9213
+ function createActivationHandler(input) {
9214
+ return async (endpoint, rawPayload) => {
9215
+ try {
9216
+ if (endpoint !== "body") return badRequest$1(`unknown activation endpoint: ${endpoint}`);
9217
+ const payload = object$1(rawPayload);
9218
+ const unexpected = Object.keys(payload).filter((field) => !ACTIVATION_PAYLOAD_FIELDS.has(field));
9219
+ if (unexpected.length > 0) return badRequest$1(`unsupported activation fields: ${unexpected.join(", ")}`);
9220
+ if (typeof payload.memoryBodyId !== "string" || payload.memoryBodyId.trim() === "") return badRequest$1("memoryBodyId must be a non-empty string");
9221
+ if (typeof payload.active !== "boolean") return badRequest$1("active must be a boolean");
9222
+ if (payload.sessionId !== void 0 && typeof payload.sessionId !== "string") return badRequest$1("sessionId must be a string");
9223
+ if (payload.workspaceId !== void 0 && typeof payload.workspaceId !== "string") return badRequest$1("workspaceId must be a string");
9224
+ const { graph } = runtimeFor(input, payload);
9225
+ if (!graph.service.config.writeEnabled) throw new Error("dsh-mnemon is configured read-only (writeEnabled: false)");
9226
+ return success$1(graph.service.updateBody(payload.memoryBodyId.trim(), { active: payload.active }));
9227
+ } catch (error) {
9228
+ return failure$1(error);
9229
+ }
9230
+ };
9231
+ }
9201
9232
  function createWriteHandler(input, lifecycle, runtimeMemory, versions) {
9202
9233
  return async (endpoint, rawPayload) => {
9203
9234
  try {
@@ -9210,6 +9241,7 @@ function createWriteHandler(input, lifecycle, runtimeMemory, versions) {
9210
9241
  }
9211
9242
  const resolved = runtimeFor(input, payload, runtimeMemory);
9212
9243
  const { service } = resolved.graph;
9244
+ if (endpoint === "provider-services") return success$1(service.memoryBodies.providerServices({ includeSecrets: true }));
9213
9245
  if (!service.config.writeEnabled) throw new Error("dsh-mnemon is configured read-only (writeEnabled: false)");
9214
9246
  const selectedWorkspace = resolved.route?.selectedWorkspace;
9215
9247
  const documentController = resolved.explicitWorkspace && selectedWorkspace !== void 0 ? resolved.graph.documents.forWorkspace(selectedWorkspace.path) : void 0;
@@ -9420,10 +9452,11 @@ function createPackHandler(input, writeEnabled = true) {
9420
9452
  }
9421
9453
  };
9422
9454
  }
9423
- /** Read operations are available to trusted Web hosts; local mutations stay loopback-only. */
9455
+ /** Read and activation control are available to trusted Web hosts; all other mutations stay loopback-only. */
9424
9456
  function registerRpc(connection, input, lifecycle, runtimeMemory, storage, packs, versions) {
9425
9457
  const versionManager = versions ?? new VersionUpdateManager({ mnemonCliPath: () => findVersionCli(input) });
9426
9458
  connection.rpc.handle(MNEMON_READ_CHANNEL, createReadHandler(input, lifecycle, runtimeMemory, storage, versionManager), { authority: "trusted-host" });
9459
+ connection.rpc.handle(MNEMON_ACTIVATION_CHANNEL, createActivationHandler(input), { authority: "trusted-host" });
9427
9460
  connection.rpc.handle(MNEMON_WRITE_CHANNEL, createWriteHandler(input, lifecycle, runtimeMemory, versionManager), { authority: "loopback" });
9428
9461
  const packManager = isRoutedRuntime(input) ? input : packs;
9429
9462
  const config = input.config;
@@ -1 +1 @@
1
- export { MNEMON_PACK_CHANNEL, MNEMON_READ_CHANNEL, MNEMON_WRITE_CHANNEL } from './shared/contracts.ts';
1
+ export { MNEMON_ACTIVATION_CHANNEL, MNEMON_PACK_CHANNEL, MNEMON_READ_CHANNEL, MNEMON_WRITE_CHANNEL } from './shared/contracts.ts';
@@ -37,6 +37,7 @@ export declare const zh: {
37
37
  'common.cancel': string;
38
38
  'common.copyId': string;
39
39
  'common.readOnly': string;
40
+ 'common.activationOnly': string;
40
41
  'common.agentSupervised': string;
41
42
  'common.active': string;
42
43
  'common.inactive': string;
@@ -893,6 +894,7 @@ export declare const en: {
893
894
  'common.cancel': string;
894
895
  'common.copyId': string;
895
896
  'common.readOnly': string;
897
+ 'common.activationOnly': string;
896
898
  'common.agentSupervised': string;
897
899
  'common.active': string;
898
900
  'common.inactive': string;
@@ -6,11 +6,17 @@ import type { StorageScopeInspector } from './storage-scope.ts';
6
6
  import type { MnemonPackManager } from './pack.ts';
7
7
  import type { LiveMnemonRuntime } from './live-runtime.ts';
8
8
  import { VersionUpdateManager } from './version-updates.ts';
9
- export { MNEMON_PACK_CHANNEL, MNEMON_READ_CHANNEL, MNEMON_WRITE_CHANNEL } from './channels.ts';
9
+ export { MNEMON_ACTIVATION_CHANNEL, MNEMON_PACK_CHANNEL, MNEMON_READ_CHANNEL, MNEMON_WRITE_CHANNEL } from './channels.ts';
10
10
  type RuntimeInput = MnemonService | LiveMnemonRuntime;
11
11
  export declare function createReadHandler(input: RuntimeInput, lifecycle?: MnemonLifecycle, runtimeMemory?: RuntimeMemoryController, storage?: StorageScopeInspector, versions?: VersionUpdateManager): HostRpcHandler;
12
+ /**
13
+ * Expose only DSH read-routing activation to trusted Web hosts. Metadata,
14
+ * provider connections, credentials, and durable memory writes stay on the
15
+ * loopback-only write channel.
16
+ */
17
+ export declare function createActivationHandler(input: RuntimeInput): HostRpcHandler;
12
18
  export declare function createWriteHandler(input: RuntimeInput, lifecycle?: MnemonLifecycle, runtimeMemory?: RuntimeMemoryController, versions?: VersionUpdateManager): HostRpcHandler;
13
19
  /** Backup payloads contain private memory and therefore remain loopback-only. */
14
20
  export declare function createPackHandler(input: MnemonPackManager | LiveMnemonRuntime, writeEnabled?: boolean | (() => boolean)): HostRpcHandler;
15
- /** Read operations are available to trusted Web hosts; local mutations stay loopback-only. */
21
+ /** Read and activation control are available to trusted Web hosts; all other mutations stay loopback-only. */
16
22
  export declare function registerRpc(connection: HostConnectionHandle, input: RuntimeInput, lifecycle?: MnemonLifecycle, runtimeMemory?: RuntimeMemoryController, storage?: StorageScopeInspector, packs?: MnemonPackManager, versions?: VersionUpdateManager): void;
@@ -1,5 +1,6 @@
1
1
  import type { ConnectionHandle as DshClientConnectionHandle } from '@deepseek-ai/dsh-client-connection/client';
2
2
  export declare const MNEMON_READ_CHANNEL = "/dsh-mnemon-read";
3
+ export declare const MNEMON_ACTIVATION_CHANNEL = "/dsh-mnemon-activation";
3
4
  export declare const MNEMON_WRITE_CHANNEL = "/dsh-mnemon-write";
4
5
  export declare const MNEMON_PACK_CHANNEL = "/dsh-mnemon-pack";
5
6
  export declare const MNEMON_SETTINGS_CHANNEL = "/dsh-mnemon-settings";
@@ -33,8 +34,8 @@ export type RpcResult<T = JsonValue> = {
33
34
  ok: false;
34
35
  error: RpcError;
35
36
  };
36
- /** Public DSH browser RPC face; the plugin intentionally consumes no other connection state. */
37
- export type ClientConnectionHandle = Pick<DshClientConnectionHandle, 'rpc'>;
37
+ /** Public DSH browser RPC face plus the transport boundary needed to gate local-only writes. */
38
+ export type ClientConnectionHandle = Pick<DshClientConnectionHandle, 'rpc'> & Partial<Pick<DshClientConnectionHandle, 'isLoopback'>>;
38
39
  export interface ClientSettingsSnapshot<T> {
39
40
  status: 'loading' | 'ready' | 'unavailable';
40
41
  value?: T;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-mnemon",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Three-tier memory system for DeepSeek Harness with nine pluggable providers, smart routing, independent task Agents, WebUI, and headless tools.",
5
5
  "keywords": [
6
6
  "deepseek-harness",