dsh-mnemon 0.3.2 → 0.3.3

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
@@ -9,6 +9,7 @@
9
9
  <a href="https://github.com/omdsh-dev/dsh-mnemon/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/omdsh-dev/dsh-mnemon" /></a>
10
10
  <a href="./LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-yellow.svg" /></a>
11
11
  <a href="https://dshfind.com/en/plugins/omdsh-dev/dsh-mnemon?ref=badge"><img alt="dshfind" src="https://dshfind.com/api/badge/omdsh-dev/dsh-mnemon?lang=en" /></a>
12
+ <a href="https://dshfind.com/en/plugins/omdsh-dev/dsh-mnemon?ref=badge"><img alt="dshfind downloads" src="https://dshfind.com/api/badge/omdsh-dev/dsh-mnemon?metric=downloads&amp;lang=en" /></a>
12
13
  </p>
13
14
 
14
15
  <p align="center"><strong>The three-tier, pluggable, Agent-driven memory system for DeepSeek Harness.</strong></p>
@@ -23,7 +24,7 @@
23
24
  <p align="center">
24
25
  <a href="./docs/en/capabilities.md"><strong>Explore the capability map</strong></a> ·
25
26
  <a href="./docs/en/getting-started.md">Start in five minutes</a> ·
26
- <a href="./docs/en/releases/v0.3.2.md">Read the v0.3.2 notes</a> ·
27
+ <a href="./docs/en/releases/v0.3.3.md">Read the v0.3.3 notes</a> ·
27
28
  <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>
28
29
  </p>
29
30
 
@@ -205,7 +206,7 @@ See [Operations, security, and troubleshooting](./docs/en/operations.md) for bac
205
206
  | Back up, update, or troubleshoot | [Operations](./docs/en/operations.md) |
206
207
  | Integrate tools, commands, or RPC | [Interface reference](./docs/en/interfaces.md) |
207
208
  | Build a Layer, Adapter, Strategy, Guard, or MemorySource extension | [Extension guide](./docs/en/extensions.md) |
208
- | Review the release | [v0.3.2 release notes](./docs/en/releases/v0.3.2.md) |
209
+ | Review the release | [v0.3.3 release notes](./docs/en/releases/v0.3.3.md) |
209
210
 
210
211
  See the [documentation hub](./docs/en/README.md) for the full map.
211
212
 
package/README.zh-CN.md CHANGED
@@ -9,6 +9,7 @@
9
9
  <a href="https://github.com/omdsh-dev/dsh-mnemon/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/omdsh-dev/dsh-mnemon" /></a>
10
10
  <a href="./LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-yellow.svg" /></a>
11
11
  <a href="https://dshfind.com/zh/plugins/omdsh-dev/dsh-mnemon?ref=badge"><img alt="dshfind" src="https://dshfind.com/api/badge/omdsh-dev/dsh-mnemon?lang=zh" /></a>
12
+ <a href="https://dshfind.com/zh/plugins/omdsh-dev/dsh-mnemon?ref=badge"><img alt="dshfind 下载量" src="https://dshfind.com/api/badge/omdsh-dev/dsh-mnemon?metric=downloads&amp;lang=zh" /></a>
12
13
  </p>
13
14
 
14
15
  <p align="center"><strong>DeepSeek Harness 的三层、可插拔、Agent 驱动记忆系统。</strong></p>
@@ -23,7 +24,7 @@
23
24
  <p align="center">
24
25
  <a href="./docs/zh-CN/capabilities.md"><strong>先看能力地图</strong></a> ·
25
26
  <a href="./docs/zh-CN/getting-started.md">5 分钟开始</a> ·
26
- <a href="./docs/zh-CN/releases/v0.3.2.md">v0.3.2 升级说明</a> ·
27
+ <a href="./docs/zh-CN/releases/v0.3.3.md">v0.3.3 升级说明</a> ·
27
28
  <a href="https://github.com/omdsh-dev/dsh-mnemon/blob/e6ca446e45bdd17991f3c7c98560456de465282b/docs/assets/media/dsh-mnemon-memory-system-demo.mp4">观看宽屏实机演示</a>
28
29
  </p>
29
30
 
@@ -205,7 +206,7 @@ dsh plugin --profile headless add "link:/absolute/path/to/dsh-mnemon"
205
206
  | 备份、更新或排障 | [运维指南](./docs/zh-CN/operations.md) |
206
207
  | 接入工具、命令或 RPC | [接口参考](./docs/zh-CN/interfaces.md) |
207
208
  | 开发 Layer、Adapter、Strategy、Guard 或 MemorySource 扩展 | [扩展开发指南](./docs/zh-CN/extensions.md) |
208
- | 查看本次升级 | [v0.3.2 发布说明](./docs/zh-CN/releases/v0.3.2.md) |
209
+ | 查看本次升级 | [v0.3.3 发布说明](./docs/zh-CN/releases/v0.3.3.md) |
209
210
 
210
211
  完整目录见[文档中心](./docs/zh-CN/README.md)。
211
212
 
package/lib/client.js CHANGED
@@ -12515,6 +12515,106 @@ window.__ModuleLoader__.load({
12515
12515
  };
12516
12516
  }
12517
12517
  //#endregion
12518
+ //#region src/client/subagent-token-usage.tsx
12519
+ /** Mnemon compatibility shim for DSH's fork-backed subagent token metric. */
12520
+ const MNEMON_SUBAGENT_TOKEN_USAGE_KEY = "mnemonSubagentTokenUsage";
12521
+ const SUBAGENT_LINEAGE_SLOT = "conversation.session.header.lineage";
12522
+ const SUBAGENT_LOCALE = "subagent";
12523
+ const MNEMON_SHADOW_PRIORITY = -100;
12524
+ const scopedSnapshots = /* @__PURE__ */ new WeakMap();
12525
+ function isTokenUsage(value) {
12526
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
12527
+ const usage = value;
12528
+ return [
12529
+ "uncachedInputTokens",
12530
+ "outputTokens",
12531
+ "cacheReadTokens",
12532
+ "cacheWriteTokens"
12533
+ ].every((key) => {
12534
+ const count = usage[key];
12535
+ return typeof count === "number" && Number.isSafeInteger(count) && count >= 0;
12536
+ });
12537
+ }
12538
+ /**
12539
+ * Present the child-local projection under the generic key expected by the
12540
+ * released official catalog component. All other consumers continue seeing
12541
+ * DSH's complete-log `tokenUsage` value.
12542
+ */
12543
+ function scopeSubagentTokenUsage(state) {
12544
+ const cached = scopedSnapshots.get(state);
12545
+ if (cached !== void 0) return cached;
12546
+ let byId;
12547
+ for (const [id, summary] of Object.entries(state.byId)) {
12548
+ if (summary.origin !== "subagent") continue;
12549
+ const projections = summary.projectionValues;
12550
+ const scopedUsage = projections?.[MNEMON_SUBAGENT_TOKEN_USAGE_KEY];
12551
+ if (!isTokenUsage(scopedUsage)) continue;
12552
+ byId ??= { ...state.byId };
12553
+ byId[id] = {
12554
+ ...summary,
12555
+ projectionValues: {
12556
+ ...projections,
12557
+ tokenUsage: scopedUsage
12558
+ }
12559
+ };
12560
+ }
12561
+ const scoped = byId === void 0 ? state : {
12562
+ ...state,
12563
+ byId
12564
+ };
12565
+ scopedSnapshots.set(state, scoped);
12566
+ return scoped;
12567
+ }
12568
+ /** Wrap the framework hook while preserving its selector/equality contract. */
12569
+ function createScopedUseSessions(useSessions) {
12570
+ return (selector, equal) => useSessions((state) => selector(scopeSubagentTokenUsage(state)), equal);
12571
+ }
12572
+ function lineageShadow(official) {
12573
+ return function MnemonSubagentHeaderLineage(props) {
12574
+ return (0, react.createElement)(official, {
12575
+ ...props,
12576
+ useSessions: createScopedUseSessions(props.useSessions)
12577
+ });
12578
+ };
12579
+ }
12580
+ function officialLineage(entries) {
12581
+ return entries.find((entry) => (entry.options.priority ?? 0) === 0 && entry.locale === SUBAGENT_LOCALE && typeof entry.component === "function" && typeof entry.inject === "function");
12582
+ }
12583
+ /**
12584
+ * Shadow the released official single-slot entry at a lower priority. The
12585
+ * component and action factory are captured from the public slot ledger, so
12586
+ * Mnemon keeps the official UI, styles, locale, and navigation behavior.
12587
+ */
12588
+ function mountSubagentTokenUsageOverride(ctx) {
12589
+ const slots = ctx.slots;
12590
+ if (typeof slots.entries !== "function" || typeof slots.subscribe !== "function" || typeof slots.register !== "function") return () => {};
12591
+ let official;
12592
+ let disposeShadow;
12593
+ const reconcile = () => {
12594
+ const entries = slots.entries(SUBAGENT_LINEAGE_SLOT);
12595
+ if (official !== void 0 && entries.includes(official)) return;
12596
+ const disposePreviousShadow = disposeShadow;
12597
+ disposeShadow = void 0;
12598
+ official = void 0;
12599
+ disposePreviousShadow?.();
12600
+ official = officialLineage(entries);
12601
+ if (official === void 0) return;
12602
+ disposeShadow = slots.register({
12603
+ name: SUBAGENT_LINEAGE_SLOT,
12604
+ priority: MNEMON_SHADOW_PRIORITY,
12605
+ locale: official.locale,
12606
+ inject: official.inject,
12607
+ registrant: "dsh-mnemon/subagent-token-usage"
12608
+ }, lineageShadow(official.component));
12609
+ };
12610
+ const unsubscribe = slots.subscribe(SUBAGENT_LINEAGE_SLOT, reconcile);
12611
+ reconcile();
12612
+ return () => {
12613
+ unsubscribe();
12614
+ disposeShadow?.();
12615
+ };
12616
+ }
12617
+ //#endregion
12518
12618
  //#region src/client/index.ts
12519
12619
  const inject = [
12520
12620
  "slots",
@@ -12600,6 +12700,7 @@ window.__ModuleLoader__.load({
12600
12700
  zh,
12601
12701
  en
12602
12702
  }), "dsh-mnemon: locale dictionaries");
12703
+ ctx.slots.inject("conversation.session.header.lineage", () => mountSubagentTokenUsageOverride(ctx));
12603
12704
  const translate = ctx.locale.bind(namespace);
12604
12705
  let activeMemoryWorkspace;
12605
12706
  const reconcileMemoryWorkspace = () => {
package/lib/index.js CHANGED
@@ -12,6 +12,7 @@ import { accessSync, closeSync, constants, existsSync, fstatSync, lstatSync, mkd
12
12
  import { homedir, tmpdir } from "node:os";
13
13
  import { strToU8, unzipSync, zipSync } from "fflate";
14
14
  import { fileURLToPath } from "node:url";
15
+ import { z as z$1 } from "zod";
15
16
  //#region src/shared/contracts.ts
16
17
  const MNEMON_READ_CHANNEL = "/dsh-mnemon-read";
17
18
  const MNEMON_ACTIVATION_CHANNEL = "/dsh-mnemon-activation";
@@ -10280,6 +10281,130 @@ function registerTools(ctx, serviceOrSource, coordinator, runtimeMemory, documen
10280
10281
  }));
10281
10282
  }
10282
10283
  //#endregion
10284
+ //#region src/subagent-token-usage.ts
10285
+ /**
10286
+ * Mnemon-owned projection for provider usage after a subagent descriptor.
10287
+ *
10288
+ * Fork-backed subagents inherit the parent's durable event prefix. DSH's
10289
+ * generic `tokenUsage` projection intentionally totals that complete log, so
10290
+ * it cannot also represent the cost of the child shown in the subagent
10291
+ * catalog. This independent projection keeps the generic metric untouched
10292
+ * and resets at every durable descriptor.
10293
+ */
10294
+ const tokenCountSchema = z$1.number().int().nonnegative();
10295
+ const tokenUsageSchema = z$1.object({
10296
+ uncachedInputTokens: tokenCountSchema,
10297
+ outputTokens: tokenCountSchema,
10298
+ cacheReadTokens: tokenCountSchema,
10299
+ cacheWriteTokens: tokenCountSchema
10300
+ }).strict();
10301
+ const tokenUsageStateSchema = z$1.object({
10302
+ descriptorSeen: z$1.boolean(),
10303
+ totals: tokenUsageSchema,
10304
+ last: z$1.object({
10305
+ turn: tokenCountSchema,
10306
+ step: tokenCountSchema,
10307
+ buckets: tokenUsageSchema
10308
+ }).strict().nullable()
10309
+ }).strict();
10310
+ const emptyTokenUsage = () => ({
10311
+ uncachedInputTokens: 0,
10312
+ outputTokens: 0,
10313
+ cacheReadTokens: 0,
10314
+ cacheWriteTokens: 0
10315
+ });
10316
+ function nonnegativeInteger(value) {
10317
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
10318
+ }
10319
+ function usageBuckets(value) {
10320
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
10321
+ const usage = value;
10322
+ const inputTokens = nonnegativeInteger(usage.inputTokens);
10323
+ const outputTokens = nonnegativeInteger(usage.outputTokens);
10324
+ const cacheReadTokens = usage.cacheReadTokens === void 0 ? 0 : nonnegativeInteger(usage.cacheReadTokens);
10325
+ const cacheWriteTokens = usage.cacheWriteTokens === void 0 ? 0 : nonnegativeInteger(usage.cacheWriteTokens);
10326
+ if (inputTokens === void 0 || outputTokens === void 0 || cacheReadTokens === void 0 || cacheWriteTokens === void 0) return void 0;
10327
+ return {
10328
+ uncachedInputTokens: inputTokens,
10329
+ outputTokens,
10330
+ cacheReadTokens,
10331
+ cacheWriteTokens
10332
+ };
10333
+ }
10334
+ function usageSample(event) {
10335
+ const turn = nonnegativeInteger(event.data.turn);
10336
+ const step = nonnegativeInteger(event.data.step);
10337
+ if (turn === void 0 || step === void 0) return void 0;
10338
+ let rawUsage;
10339
+ if (event.type === "assistant/chunk") {
10340
+ const chunk = event.data.chunk;
10341
+ if (typeof chunk !== "object" || chunk === null || Array.isArray(chunk)) return void 0;
10342
+ const record = chunk;
10343
+ if (record.type !== "usage") return void 0;
10344
+ rawUsage = record.usage;
10345
+ } else if (event.type === "assistant/message") rawUsage = event.data.usage;
10346
+ else return;
10347
+ const buckets = usageBuckets(rawUsage);
10348
+ return buckets === void 0 ? void 0 : {
10349
+ turn,
10350
+ step,
10351
+ buckets
10352
+ };
10353
+ }
10354
+ function equalTokenUsage(left, right) {
10355
+ return left.uncachedInputTokens === right.uncachedInputTokens && left.outputTokens === right.outputTokens && left.cacheReadTokens === right.cacheReadTokens && left.cacheWriteTokens === right.cacheWriteTokens;
10356
+ }
10357
+ function replaceTokenUsage(totals, previous, next) {
10358
+ return {
10359
+ uncachedInputTokens: totals.uncachedInputTokens - (previous?.uncachedInputTokens ?? 0) + next.uncachedInputTokens,
10360
+ outputTokens: totals.outputTokens - (previous?.outputTokens ?? 0) + next.outputTokens,
10361
+ cacheReadTokens: totals.cacheReadTokens - (previous?.cacheReadTokens ?? 0) + next.cacheReadTokens,
10362
+ cacheWriteTokens: totals.cacheWriteTokens - (previous?.cacheWriteTokens ?? 0) + next.cacheWriteTokens
10363
+ };
10364
+ }
10365
+ /**
10366
+ * Fold provider usage after the latest subagent descriptor. A fork may carry
10367
+ * an ancestor descriptor as part of its seed, so every descriptor resets the
10368
+ * fold and the child's own descriptor becomes the final authoritative origin.
10369
+ */
10370
+ const mnemonSubagentTokenUsageProjectionDefinition = {
10371
+ key: "mnemonSubagentTokenUsage",
10372
+ stateVersion: 1,
10373
+ stateSchema: tokenUsageStateSchema,
10374
+ init: () => ({
10375
+ descriptorSeen: false,
10376
+ totals: emptyTokenUsage(),
10377
+ last: null
10378
+ }),
10379
+ apply: (state, event) => {
10380
+ if (event.type === "subagent/descriptor") return {
10381
+ descriptorSeen: true,
10382
+ totals: emptyTokenUsage(),
10383
+ last: null
10384
+ };
10385
+ if (!state.descriptorSeen) return state;
10386
+ const sample = usageSample(event);
10387
+ if (sample === void 0) return state;
10388
+ const previous = state.last !== null && state.last.turn === sample.turn && state.last.step === sample.step ? state.last.buckets : void 0;
10389
+ if (previous !== void 0 && equalTokenUsage(previous, sample.buckets)) return state;
10390
+ return {
10391
+ descriptorSeen: true,
10392
+ totals: replaceTokenUsage(state.totals, previous, sample.buckets),
10393
+ last: sample
10394
+ };
10395
+ },
10396
+ wire: {
10397
+ viewSchema: tokenUsageSchema.nullable(),
10398
+ view: (state) => state.descriptorSeen ? state.totals : null
10399
+ }
10400
+ };
10401
+ /** Register lazily when the optional DSH projection service is present. */
10402
+ function registerMnemonSubagentTokenUsageProjection(ctx) {
10403
+ ctx.inject(["sessionProjections"], (rawContext) => {
10404
+ rawContext.sessionProjections?.register(mnemonSubagentTokenUsageProjectionDefinition);
10405
+ });
10406
+ }
10407
+ //#endregion
10283
10408
  //#region src/index.ts
10284
10409
  const name = "dsh-mnemon";
10285
10410
  const provide = ["mnemonMemory"];
@@ -10301,6 +10426,7 @@ function optionalWorkspaceRegistry(ctx) {
10301
10426
  /** Mount native model tools on every DSH surface and UI RPC only when Web connection exists. */
10302
10427
  function apply(rawContext, config = {}) {
10303
10428
  const ctx = rawContext;
10429
+ registerMnemonSubagentTokenUsageProjection(ctx);
10304
10430
  const extensions = memoryBoot;
10305
10431
  ctx.provide?.("mnemonMemory", extensions);
10306
10432
  const prepared = /* @__PURE__ */ new Map();
@@ -0,0 +1,24 @@
1
+ import type { SessionListState } from '@deepseek-ai/dsh-client-runtime/client';
2
+ import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
3
+ import type { MnemonClientContext } from './dsh-compat.ts';
4
+ export declare const MNEMON_SUBAGENT_TOKEN_USAGE_KEY = "mnemonSubagentTokenUsage";
5
+ export interface MnemonTokenUsageProjection {
6
+ uncachedInputTokens: number;
7
+ outputTokens: number;
8
+ cacheReadTokens: number;
9
+ cacheWriteTokens: number;
10
+ }
11
+ /**
12
+ * Present the child-local projection under the generic key expected by the
13
+ * released official catalog component. All other consumers continue seeing
14
+ * DSH's complete-log `tokenUsage` value.
15
+ */
16
+ export declare function scopeSubagentTokenUsage(state: SessionListState): SessionListState;
17
+ /** Wrap the framework hook while preserving its selector/equality contract. */
18
+ export declare function createScopedUseSessions(useSessions: SnapshotSelectorHook<SessionListState>): SnapshotSelectorHook<SessionListState>;
19
+ /**
20
+ * Shadow the released official single-slot entry at a lower priority. The
21
+ * component and action factory are captured from the public slot ledger, so
22
+ * Mnemon keeps the official UI, styles, locale, and navigation behavior.
23
+ */
24
+ export declare function mountSubagentTokenUsageOverride(ctx: MnemonClientContext): () => void;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Mnemon-owned projection for provider usage after a subagent descriptor.
3
+ *
4
+ * Fork-backed subagents inherit the parent's durable event prefix. DSH's
5
+ * generic `tokenUsage` projection intentionally totals that complete log, so
6
+ * it cannot also represent the cost of the child shown in the subagent
7
+ * catalog. This independent projection keeps the generic metric untouched
8
+ * and resets at every durable descriptor.
9
+ */
10
+ import { z } from 'zod';
11
+ import type { HostContextShape, HostSessionEvent } from './contracts.ts';
12
+ export interface MnemonTokenUsageProjection {
13
+ uncachedInputTokens: number;
14
+ outputTokens: number;
15
+ cacheReadTokens: number;
16
+ cacheWriteTokens: number;
17
+ }
18
+ export interface MnemonSubagentTokenUsageState {
19
+ descriptorSeen: boolean;
20
+ totals: MnemonTokenUsageProjection;
21
+ last: {
22
+ turn: number;
23
+ step: number;
24
+ buckets: MnemonTokenUsageProjection;
25
+ } | null;
26
+ }
27
+ /** Wire key consumed only by Mnemon's subagent-catalog compatibility shim. */
28
+ export declare const MNEMON_SUBAGENT_TOKEN_USAGE_KEY = "mnemonSubagentTokenUsage";
29
+ /**
30
+ * Fold provider usage after the latest subagent descriptor. A fork may carry
31
+ * an ancestor descriptor as part of its seed, so every descriptor resets the
32
+ * fold and the child's own descriptor becomes the final authoritative origin.
33
+ */
34
+ export declare const mnemonSubagentTokenUsageProjectionDefinition: {
35
+ readonly key: "mnemonSubagentTokenUsage";
36
+ readonly stateVersion: 1;
37
+ readonly stateSchema: z.ZodType<MnemonSubagentTokenUsageState, unknown, z.core.$ZodTypeInternals<MnemonSubagentTokenUsageState, unknown>>;
38
+ readonly init: () => MnemonSubagentTokenUsageState;
39
+ readonly apply: (state: MnemonSubagentTokenUsageState, event: HostSessionEvent) => MnemonSubagentTokenUsageState;
40
+ readonly wire: {
41
+ readonly viewSchema: z.ZodNullable<z.ZodType<MnemonTokenUsageProjection, unknown, z.core.$ZodTypeInternals<MnemonTokenUsageProjection, unknown>>>;
42
+ readonly view: (state: MnemonSubagentTokenUsageState) => MnemonTokenUsageProjection | null;
43
+ };
44
+ };
45
+ /** Register lazily when the optional DSH projection service is present. */
46
+ export declare function registerMnemonSubagentTokenUsageProjection(ctx: HostContextShape): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-mnemon",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Composable three-tier memory control plane for DeepSeek Harness: persistent runtime context, searchable project documents, pluggable long-term memory, guarded strategies, WebUI, and headless tools.",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -138,7 +138,8 @@
138
138
  "dependencies": {
139
139
  "fflate": "^0.8.3",
140
140
  "markdown-to-jsx": "^7.7.17",
141
- "schemastery": "^3.18.0"
141
+ "schemastery": "^3.18.0",
142
+ "zod": "^4.4.3"
142
143
  },
143
144
  "peerDependencies": {
144
145
  "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6 || ^0.1.1-rc.1",