dsh-mnemon 0.5.26 → 0.5.27

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/lib/bundle.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as prepareStarterResolution } from "./starter-resolution-BjfPGF8R.js";
1
+ import { t as prepareStarterResolution } from "./starter-resolution-C2z8b9AZ.js";
2
2
  //#region src/bundle.ts
3
3
  const groupKey = Symbol.for("cordis.group");
4
4
  const init = Symbol.for("cordis.init");
package/lib/client.js CHANGED
@@ -8396,6 +8396,10 @@ window.__ModuleLoader__.load({
8396
8396
  subscribe: () => () => {},
8397
8397
  getSnapshot: () => 0
8398
8398
  };
8399
+ const NO_COMPONENT_LIST = {
8400
+ subscribe: () => () => {},
8401
+ getSnapshot: () => void 0
8402
+ };
8399
8403
  /**
8400
8404
  * The dsh-mnemon configuration, shown on its bundle page under DSH Plugins:
8401
8405
  * the memory composition, then only what belongs to no component — where
@@ -8406,12 +8410,14 @@ window.__ModuleLoader__.load({
8406
8410
  * Typed values wait for their group's Apply; the storage location waits too,
8407
8411
  * because it moves where every component reads and writes.
8408
8412
  */
8409
- function MnemonSettingsCard({ scope, interactionScope: suppliedInteractionScope, connection, sessionId, workspaceId, workspaceLabel, t = translateZh, language = "zh", componentChanges = NO_CHANGE_SIGNAL$1, componentSettings, component }) {
8413
+ function MnemonSettingsCard({ scope, interactionScope: suppliedInteractionScope, connection, sessionId, workspaceId, workspaceLabel, t = translateZh, language = "zh", componentChanges = NO_CHANGE_SIGNAL$1, componentSettings, component, componentList = NO_COMPONENT_LIST }) {
8410
8414
  const interactionScope = suppliedInteractionScope ?? scope;
8411
8415
  const coreSnapshot = useScope(scope);
8412
8416
  const interactionSnapshot = useScope(interactionScope);
8413
8417
  const [targetRevision, setTargetRevision] = (0, react.useState)(0);
8414
- const dataRevision = targetRevision + (0, react.useSyncExternalStore)(componentChanges.subscribe, componentChanges.getSnapshot, componentChanges.getSnapshot) + (coreSnapshot.revision ?? 0);
8418
+ const componentRevision = (0, react.useSyncExternalStore)(componentChanges.subscribe, componentChanges.getSnapshot, componentChanges.getSnapshot);
8419
+ const groupRowListed = (0, react.useSyncExternalStore)(componentList.subscribe, componentList.getSnapshot, componentList.getSnapshot) === true;
8420
+ const dataRevision = targetRevision + componentRevision + (coreSnapshot.revision ?? 0);
8415
8421
  const view = useViewStore((0, react.useMemo)(() => connection === void 0 ? void 0 : new MnemonClient(connection, sessionId, workspaceId), [
8416
8422
  connection,
8417
8423
  sessionId,
@@ -8640,7 +8646,7 @@ window.__ModuleLoader__.load({
8640
8646
  })
8641
8647
  ]
8642
8648
  }),
8643
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8649
+ groupRowListed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8644
8650
  className: MnemonSettingsCard_module_css_default.componentListNote,
8645
8651
  children: t("config.componentListNote")
8646
8652
  }),
@@ -9536,6 +9542,7 @@ window.__ModuleLoader__.load({
9536
9542
  settings,
9537
9543
  enabled: true
9538
9544
  }));
9545
+ props.onChanged?.();
9539
9546
  };
9540
9547
  const toggle = async (provider, enabled) => {
9541
9548
  if (client === null) throw new Error(props.t("config.providerUnavailable"));
@@ -9545,6 +9552,7 @@ window.__ModuleLoader__.load({
9545
9552
  enabled
9546
9553
  });
9547
9554
  acceptService(updated);
9555
+ props.onChanged?.();
9548
9556
  return updated;
9549
9557
  };
9550
9558
  const disabled = props.disabled || props.scopeChanging || client === null || loading || catalog.generatedAt === "";
@@ -9836,6 +9844,7 @@ window.__ModuleLoader__.load({
9836
9844
  refreshKey: snapshot.revision ?? 0,
9837
9845
  disabled: disabled || readOnly,
9838
9846
  scopeChanging: false,
9847
+ ...props.componentChanges === void 0 ? {} : { onChanged: props.componentChanges.bump },
9839
9848
  ...readOnly ? { notice: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Callout, {
9840
9849
  tone: "warning",
9841
9850
  className: MnemonSettingsCard_module_css_default.groupCallout,
@@ -10914,12 +10923,53 @@ window.__ModuleLoader__.load({
10914
10923
  });
10915
10924
  });
10916
10925
  //#endregion
10926
+ //#region src/client/component-list-seat.ts
10927
+ /** The id of the Starter's grouping row in its `cordis.patch.yml`. */
10928
+ const STARTER_GROUP_ROW_ID = "mnemon-bundle";
10929
+ /**
10930
+ * Whether DSH's component list on the dsh-mnemon page shows the Starter's
10931
+ * grouping row, which it shows as off. DSH 0.2.0 and earlier list it; DSH
10932
+ * 0.2.1 lists only the components. The page's head controls see the rows DSH
10933
+ * draws and report them here for the configuration above the list.
10934
+ */
10935
+ var MnemonComponentListSeat = class {
10936
+ latest;
10937
+ listeners = /* @__PURE__ */ new Set();
10938
+ /** Undefined until a page reports, so nothing is said about a list not yet seen. */
10939
+ getSnapshot = () => this.latest?.groupRow;
10940
+ subscribe = (listener) => {
10941
+ this.listeners.add(listener);
10942
+ return () => {
10943
+ this.listeners.delete(listener);
10944
+ };
10945
+ };
10946
+ /** Report whether the open page lists the row until the returned disposer runs; a newer report replaces it. */
10947
+ report(groupRow) {
10948
+ const report = { groupRow };
10949
+ this.latest = report;
10950
+ this.emit();
10951
+ return () => {
10952
+ if (this.latest !== report) return;
10953
+ this.latest = void 0;
10954
+ this.emit();
10955
+ };
10956
+ }
10957
+ emit() {
10958
+ for (const listener of [...this.listeners]) listener();
10959
+ }
10960
+ };
10961
+ //#endregion
10917
10962
  //#region src/client/MnemonPluginActions.tsx
10918
10963
  /** The npm package whose page under DSH Plugins carries the Mnemon configuration. */
10919
10964
  const MNEMON_PACKAGE_NAME = "dsh-mnemon";
10920
- /** Head controls on the dsh-mnemon page under Plugins: a way back to the memory workspace. */
10921
- function MnemonPluginActions({ subject, workspace, t }) {
10965
+ /**
10966
+ * Head controls on the dsh-mnemon page under Plugins: a way back to the memory
10967
+ * workspace. They also report the rows DSH lists below the configuration.
10968
+ */
10969
+ function MnemonPluginActions({ subject, workspace, componentList, t }) {
10922
10970
  const open = (0, react.useSyncExternalStore)(workspace.subscribe, workspace.getSnapshot, workspace.getSnapshot);
10971
+ const groupRow = subject.kind === "bundle" && subject.pkg.name === "dsh-mnemon" ? subject.pkg.rows.some((row) => row.rowId === STARTER_GROUP_ROW_ID) : void 0;
10972
+ (0, react.useEffect)(() => groupRow === void 0 ? void 0 : componentList?.report(groupRow), [groupRow, componentList]);
10923
10973
  if (subject.kind !== "bundle" || subject.pkg.name !== "dsh-mnemon" || !subject.pkg.enabled || open === void 0) return null;
10924
10974
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
10925
10975
  variant: "outline",
@@ -13225,8 +13275,8 @@ window.__ModuleLoader__.load({
13225
13275
  (0, react.useEffect)(() => {
13226
13276
  if (componentRevision === seenComponents.current) return;
13227
13277
  seenComponents.current = componentRevision;
13228
- refreshAll();
13229
- }, [componentRevision, refreshAll]);
13278
+ refreshPage();
13279
+ }, [componentRevision, refreshPage]);
13230
13280
  const seenSettings = (0, react.useRef)({
13231
13281
  revision: settingsSnapshot.revision,
13232
13282
  context: viewContextKey
@@ -14622,7 +14672,8 @@ window.__ModuleLoader__.load({
14622
14672
  const seats = {
14623
14673
  configuration: new MnemonActionSeat(),
14624
14674
  workspace: new MnemonActionSeat(),
14625
- components: new MnemonChangeSignal()
14675
+ components: new MnemonChangeSignal(),
14676
+ componentList: new MnemonComponentListSeat()
14626
14677
  };
14627
14678
  const namespace = "mnemon";
14628
14679
  ctx.effect(() => ctx.locale.register(namespace, {
@@ -14679,6 +14730,7 @@ window.__ModuleLoader__.load({
14679
14730
  currentSession: ctx.uiSession.adapter.current,
14680
14731
  localeRuntime: ctx.locale,
14681
14732
  componentChanges: seats.components,
14733
+ componentList: seats.componentList,
14682
14734
  t: translate
14683
14735
  });
14684
14736
  const renderContributed = (packageName, owner) => renderComponentRegion(ctx, MNEMON_COMPONENT_SETTINGS_SLOT, packageName, owner);
@@ -14708,7 +14760,8 @@ window.__ModuleLoader__.load({
14708
14760
  ctx.effect(() => installShippedComponentSettings(ctx, {
14709
14761
  scope: settings,
14710
14762
  connection: ctx.connection,
14711
- t: translate
14763
+ t: translate,
14764
+ componentChanges: seats.components
14712
14765
  }), "dsh-mnemon: shipped component settings");
14713
14766
  ctx.effect(() => installShippedComponentStatus(ctx), "dsh-mnemon: shipped component status");
14714
14767
  ctx.slots.inject("plugins.detail.actions", () => ctx.slots.register({
@@ -14717,6 +14770,7 @@ window.__ModuleLoader__.load({
14717
14770
  locale: namespace,
14718
14771
  inject: () => ({
14719
14772
  workspace: seats.workspace,
14773
+ componentList: seats.componentList,
14720
14774
  t: translate
14721
14775
  })
14722
14776
  }, MnemonPluginActions));
@@ -2,18 +2,34 @@ import { a as memoryConfigurationDigest, c as record, d as truncate, f as withMe
2
2
  import { COMPOSABLE_MEMORY_API_VERSION, MEMORY_VIEW_EXTENSION_SLOTS } from "./contracts.js";
3
3
  import { a as defineMemoryStrategy, i as defineMemorySource, o as defineMemoryStrategyExtension, r as defineMemoryPlugin } from "./definitions-j9QPbrXb.js";
4
4
  //#region src/sdk/install.ts
5
+ function locatedEntryId(ctx) {
6
+ const located = ctx.get("loader", false)?.locate(ctx.fiber)?.trim();
7
+ return located === "" ? void 0 : located;
8
+ }
5
9
  function stableEntryId(ctx, explicit) {
6
10
  const configured = explicit?.trim();
7
11
  if (configured !== void 0 && configured !== "") return configured;
8
- const located = ctx.get("loader", false)?.locate(ctx.fiber)?.trim();
9
- if (located !== void 0 && located !== "") return located;
12
+ const located = locatedEntryId(ctx);
13
+ if (located !== void 0) return located;
10
14
  throw new Error("installMemory requires a stable Loader Entry id; pass options.instanceId for direct ctx.plugin() mounts");
11
15
  }
12
16
  /**
17
+ * dshmarket mounts `mkt-client-<package>` for a profile dependency that
18
+ * declares `dsh.client` without `dsh.bundle`, meant to run no host code. A
19
+ * Source installed on its own in a profile matches that rule although the
20
+ * Starter composes it, and dshmarket 1.66 imports the real module there, so
21
+ * the Source would register a second instance (#359). Nothing installs under
22
+ * such a mount, whatever identity the plugin passes. The Loader prefixes an
23
+ * Entry id with its parents' ids, as in `include:dsh-market:mkt-client-<package>`,
24
+ * so the last segment names it.
25
+ */
26
+ const MARKET_CLIENT_SHIM = /(?:^|:)mkt-client-[^:]*$/u;
27
+ /**
13
28
  * Register a plugin's Source and/or Strategy definitions as one Fiber-owned batch.
14
29
  * Contribution roles do not dictate package or repository boundaries.
15
30
  */
16
31
  function installMemory(ctx, contribution, options = {}) {
32
+ if (MARKET_CLIENT_SHIM.test(locatedEntryId(ctx) ?? "")) return;
17
33
  const entryId = stableEntryId(ctx, options.instanceId);
18
34
  ctx.effect(() => ctx.mnemonMemory.installContributions(contribution, {
19
35
  ...options,
package/lib/index.js CHANGED
@@ -17,6 +17,7 @@ import { StringDecoder } from "node:string_decoder";
17
17
  import { request } from "node:http";
18
18
  import { Agent, request as request$1 } from "node:https";
19
19
  import { connect } from "node:tls";
20
+ import { readFile, stat } from "node:fs/promises";
20
21
  import { threeTierActionWorkflow } from "dsh-mnemon-strategy-default-three-tier/extension-sdk";
21
22
  import { AsyncLocalStorage } from "node:async_hooks";
22
23
  import { fileURLToPath } from "node:url";
@@ -24,7 +25,6 @@ import { findMnemonCommand, mnemonNpmLauncher, nodeLauncherEnvironment, resolveM
24
25
  import { z as z$1 } from "zod";
25
26
  import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
26
27
  import { isVolatile } from "@deepseek-ai/cosmokit";
27
- import { readFile, stat } from "node:fs/promises";
28
28
  import { parseDocument } from "yaml";
29
29
  //#region src/host/view-protocol.ts
30
30
  const MNEMON_VIEW_CHANNEL = "/dsh-mnemon-view";
@@ -9754,6 +9754,9 @@ var MnemonAgentLifecycle = class {
9754
9754
  console.warn(`[dsh-mnemon] idle review failed: ${this.lastError}`);
9755
9755
  }
9756
9756
  };
9757
+ function isDirectory(path) {
9758
+ return stat(path).then((info) => info.isDirectory(), () => false);
9759
+ }
9757
9760
  /** DSH-native owner for per-agent Mnemon lifecycle hooks and UI-triggered LLM work. */
9758
9761
  var MnemonLifecycle = class {
9759
9762
  ctx;
@@ -10079,7 +10082,7 @@ var MnemonLifecycle = class {
10079
10082
  let handle;
10080
10083
  let failure;
10081
10084
  try {
10082
- const creation = await this.taskAgentCreation(fallbackSessionId, workspaceRoot);
10085
+ const creation = await this.taskAgentCreation(fallbackSessionId, workspaceRoot, signal);
10083
10086
  handle = await this.ctx.agents.create({
10084
10087
  sessionId,
10085
10088
  ...creation,
@@ -10099,42 +10102,58 @@ var MnemonLifecycle = class {
10099
10102
  }
10100
10103
  }
10101
10104
  /** Resolve the same model route and preset composition as an ordinary fresh DSH Agent. */
10102
- async taskAgentCreation(fallbackSessionId, workspaceRoot) {
10105
+ async taskAgentCreation(fallbackSessionId, workspaceRoot, signal) {
10103
10106
  const agentOptions = this.taskAgentModelOptions(fallbackSessionId, workspaceRoot);
10104
10107
  if (agentOptions === void 0) throw new Error("no default provider/model is available for a clean task Agent");
10105
- const cwd = this.taskAgentCwd(workspaceRoot);
10108
+ const { cwd, workFrom } = await this.taskAgentDirectories(workspaceRoot);
10106
10109
  const presets = presetService(this.ctx.get("agentPresets"));
10107
- if (presets === void 0) return {
10110
+ const presetId = presets === void 0 ? void 0 : (await presets.resolve()).id;
10111
+ const workingDirectory = workFrom === void 0 ? void 0 : this.ctx.get("workingDirectory");
10112
+ if (presets === void 0 && typeof workingDirectory?.set !== "function") return {
10108
10113
  meta: { cwd },
10109
10114
  agentOptions
10110
10115
  };
10111
- const presetId = (await presets.resolve()).id;
10112
10116
  return {
10113
10117
  meta: {
10114
10118
  cwd,
10115
- agentPreset: presetId
10119
+ ...presetId === void 0 ? {} : { agentPreset: presetId }
10116
10120
  },
10117
10121
  agentOptions,
10118
- setup: async (agentCtx) => {
10119
- await presets.mount(agentCtx, presetId);
10122
+ setup: async (agentCtx, agent) => {
10123
+ if (presets !== void 0 && presetId !== void 0) await presets.mount(agentCtx, presetId);
10124
+ if (workFrom !== void 0 && agent !== void 0 && typeof workingDirectory?.set === "function") await workingDirectory.set(agent, workFrom, signal);
10120
10125
  }
10121
10126
  };
10122
10127
  }
10123
10128
  /**
10124
10129
  * A task Agent runs outside any conversation, so its caller may hold no
10125
- * workspace at all. DSH's Web persona renders `{{cwd}}`, and an Agent created
10126
- * without one fails prompt assembly before its first step, so the registry's
10127
- * default workspace stands in; a profile that mounts no registry keeps the
10128
- * directory the Host was started in.
10130
+ * workspace at all. DSH 0.2.0's Web persona renders `{{cwd}}`, and an Agent
10131
+ * created without one fails prompt assembly before its first step, so the
10132
+ * registry's first workspace stands in; a profile that mounts no registry
10133
+ * keeps the directory the Host was started in.
10134
+ *
10135
+ * The `cwd` is also the workspace whose memory Mnemon reads, so it stays
10136
+ * even when its folder is gone. DSH 0.2.1 checks the working directory
10137
+ * before every step and fails once it and the session's original directory
10138
+ * are gone, so the task then works from the first existing workspace, or the
10139
+ * Host's directory, as DSH's own subagents do; its children inherit both.
10129
10140
  */
10130
- taskAgentCwd(workspaceRoot) {
10141
+ async taskAgentDirectories(workspaceRoot) {
10131
10142
  const requested = workspaceRoot?.trim();
10132
- if (requested !== void 0 && requested !== "") return resolve(requested);
10133
- const registry = this.ctx.get("workspaceRegistry");
10134
- const listed = typeof registry?.list === "function" ? registry.list() : [];
10135
- for (const workspace of listed) if (typeof workspace?.path === "string" && workspace.path.trim() !== "") return resolve(workspace.path);
10143
+ const cwd = requested !== void 0 && requested !== "" ? resolve(requested) : this.registeredWorkspaces()[0] ?? process.cwd();
10144
+ return await isDirectory(cwd) ? { cwd } : {
10145
+ cwd,
10146
+ workFrom: await this.existingWorkspace()
10147
+ };
10148
+ }
10149
+ async existingWorkspace() {
10150
+ for (const workspace of this.registeredWorkspaces()) if (await isDirectory(workspace)) return workspace;
10136
10151
  return process.cwd();
10137
10152
  }
10153
+ registeredWorkspaces() {
10154
+ const registry = this.ctx.get("workspaceRegistry");
10155
+ return (typeof registry?.list === "function" ? registry.list() : []).flatMap((workspace) => typeof workspace?.path === "string" && workspace.path.trim() !== "" ? [resolve(workspace.path)] : []);
10156
+ }
10138
10157
  /** Resolve a complete task route for both status admission and actual creation. */
10139
10158
  taskAgentModelRoute(fallbackSessionId, workspaceRoot) {
10140
10159
  const fallback = this.ctx.agents.get(fallbackSessionId.trim()) ?? this.availableAgent(workspaceRoot) ?? this.availableAgent();
@@ -15,7 +15,7 @@ var dependencies = {
15
15
  "dsh-mnemon-provider-retaindb": "0.5.5",
16
16
  "dsh-mnemon-provider-supermemory": "0.5.5",
17
17
  "dsh-mnemon-source-documents": "0.5.10",
18
- "dsh-mnemon-source-memory-spaces": "0.5.17",
18
+ "dsh-mnemon-source-memory-spaces": "0.5.18",
19
19
  "dsh-mnemon-source-runtime": "0.5.14",
20
20
  "dsh-mnemon-strategy-auto-capture": "0.5.5",
21
21
  "dsh-mnemon-strategy-default-three-tier": "0.5.8",
package/lib/starter.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as prepareStarterResolution } from "./starter-resolution-BjfPGF8R.js";
1
+ import { t as prepareStarterResolution } from "./starter-resolution-C2z8b9AZ.js";
2
2
  //#region src/starter.ts
3
3
  const name = "dsh-mnemon-starter";
4
4
  const provide = ["mnemonStarterReady"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-mnemon",
3
- "version": "0.5.26",
3
+ "version": "0.5.27",
4
4
  "description": "Composable, view-based memory for DeepSeek Harness. Pluggable sources and strategies, with layered memory out of the box.",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -163,7 +163,7 @@
163
163
  "dsh-mnemon-provider-retaindb": "0.5.5",
164
164
  "dsh-mnemon-provider-supermemory": "0.5.5",
165
165
  "dsh-mnemon-source-documents": "0.5.10",
166
- "dsh-mnemon-source-memory-spaces": "0.5.17",
166
+ "dsh-mnemon-source-memory-spaces": "0.5.18",
167
167
  "dsh-mnemon-source-runtime": "0.5.14",
168
168
  "dsh-mnemon-strategy-auto-capture": "0.5.5",
169
169
  "dsh-mnemon-strategy-default-three-tier": "0.5.8",