dsh-daoing-memory 0.1.6 → 0.1.8
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/client.js +392 -119
- package/lib/client.js.map +1 -1
- package/lib/index.js +315 -6
- package/lib/typert.host.js +242 -63
- package/lib/typert.remote-client.d.ts +10 -1
- package/lib/typert.remote-client.js +214 -60
- package/lib/types/core.d.ts +39 -1
- package/lib/types/core.js +120 -0
- package/lib/types/index.d.ts +4 -0
- package/lib/types/index.js +5 -0
- package/lib/types/service.d.ts +27 -2
- package/lib/types/service.js +113 -1
- package/lib/types/store.d.ts +16 -0
- package/lib/types/store.js +33 -0
- package/lib/types/types.d.ts +18 -0
- package/lib/types/types.js +14 -1
- package/package.json +1 -1
package/lib/types/core.d.ts
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*
|
|
21
21
|
* @module dsh-daoing-memory/core
|
|
22
22
|
*/
|
|
23
|
-
import type { ConcernTree, ConsolidateRequest, ConsolidateResult, DiaryAppendRequest, DiaryAppendResult, DiaryEntry, ExperienceListFilter, ExperienceSnapshot, ExtractionRecord, ExtractFactsRequest, ExtractFactsResult, FactEntry, HumanAddExperienceRequest, HumanAddFactRequest, HumanAckDiaryRequest, HumanConfirmFactRequest, HumanDeleteConcernRequest, HumanDeleteExperienceRequest, HumanDeleteFactRequest, HumanEditExperienceRequest, HumanEditFactRequest, HumanPinRequest, HumanSetConcernStatusRequest, HumanReleaseColdRequest, IngestRequest, IngestResult, LedgerIntegrityResult, LedgerQueryRequest, MemoryExport, MemoryStats, RecallExperiencesRequest, RecallExperiencesResult, RefineExperienceRequest, RefineExperienceResult, ReportUseRequest, ReportUseResult, ReviseExperienceRequest, RollbackExperienceRequest, VerifyShadowRequest, VerifyShadowResult } from './types.ts';
|
|
23
|
+
import type { ConcernTree, ConsolidateRequest, ConsolidateResult, DiaryAppendRequest, DiaryAppendResult, DiaryEntry, ExperienceListFilter, ExperienceSnapshot, ExtractionRecord, ExtractFactsRequest, ExtractFactsResult, FactEntry, HumanAddExperienceRequest, HumanAddFactRequest, HumanAckDiaryRequest, HumanArchiveExperienceRequest, HumanConfirmFactRequest, HumanDeleteConcernRequest, HumanDeleteExperienceRequest, HumanDeleteFactRequest, HumanEditExperienceRequest, HumanEditFactRequest, HumanPinRequest, HumanSetConcernStatusRequest, HumanReleaseColdRequest, IngestRequest, IngestResult, LedgerIntegrityResult, LedgerQueryRequest, MemoryExport, MemoryStats, RecallExperiencesRequest, RecallExperiencesResult, RefineExperienceRequest, RefineExperienceResult, ReportUseRequest, ReportUseResult, ReviseExperienceRequest, RollbackExperienceRequest, VerifyShadowRequest, VerifyShadowResult } from './types.ts';
|
|
24
24
|
import { MemoryStore } from './store.ts';
|
|
25
25
|
/** Tunable mechanism parameters, all overridable from the plugin config. */
|
|
26
26
|
export interface MemoryCoreConfig {
|
|
@@ -64,6 +64,10 @@ export interface MemoryCoreConfig {
|
|
|
64
64
|
consolidateEveryNew: number;
|
|
65
65
|
/** Consolidation: minimum HOURS elapsed since the last consolidation (interval, not a fixed clock point) (008 §1). */
|
|
66
66
|
consolidateIntervalHours: number;
|
|
67
|
+
/** Deletion-feedback summarization: minimum HOURS between LLM summarization runs. */
|
|
68
|
+
deletionFeedbackIntervalHours: number;
|
|
69
|
+
/** Deletion-feedback summarization: minimum new deletions since last run to trigger. */
|
|
70
|
+
deletionFeedbackMinDeletions: number;
|
|
67
71
|
}
|
|
68
72
|
/** The mechanism defaults (005 mapping documented in the README). */
|
|
69
73
|
export declare const DEFAULT_CORE_CONFIG: MemoryCoreConfig;
|
|
@@ -153,10 +157,44 @@ export declare class MemoryCore {
|
|
|
153
157
|
* — consolidation never hard-deletes). Every step is ledgered.
|
|
154
158
|
*/
|
|
155
159
|
consolidate(request: ConsolidateRequest, actor: string): ConsolidateResult;
|
|
160
|
+
/** Family id for the auto-generated extraction-feedback experience. */
|
|
161
|
+
static readonly DELETION_FEEDBACK_FAMILY = "extraction-feedback";
|
|
162
|
+
/**
|
|
163
|
+
* Check whether a deletion-feedback summarization run is due.
|
|
164
|
+
* Conditions: enough new deletions since last run AND enough time elapsed.
|
|
165
|
+
* @returns { due, lastTs, newDeletions, hoursSince }
|
|
166
|
+
*/
|
|
167
|
+
deletionFeedbackDue(): {
|
|
168
|
+
due: boolean;
|
|
169
|
+
lastTs: number;
|
|
170
|
+
newDeletions: number;
|
|
171
|
+
hoursSince: number;
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* Apply an LLM-generated deletion-feedback summary as an extraction-feedback
|
|
175
|
+
* experience. If one already exists, it is revised in place (new revision);
|
|
176
|
+
* otherwise a new candidate experience is created.
|
|
177
|
+
* @param summary - the LLM-generated summary text (gist + reasoning).
|
|
178
|
+
* @param actor - who triggered the summarization ('system').
|
|
179
|
+
* @returns the upserted experience snapshot.
|
|
180
|
+
*/
|
|
181
|
+
applyDeletionFeedback(summary: string, actor: string): ExperienceSnapshot;
|
|
182
|
+
/**
|
|
183
|
+
* Get the current extraction-feedback experience (if any) for injection into
|
|
184
|
+
* the extraction prompt.
|
|
185
|
+
*/
|
|
186
|
+
getDeletionFeedback(): ExperienceSnapshot | undefined;
|
|
156
187
|
/** Human pin/unpin: pinned cards keep the trust floor and escape budgets. */
|
|
157
188
|
humanPin(request: HumanPinRequest, actor: MemoryActor): ExperienceSnapshot;
|
|
158
189
|
/** Human delete: tombstone the family; the ledger keeps the fingerprint. */
|
|
159
190
|
humanDeleteExperience(request: HumanDeleteExperienceRequest, actor: MemoryActor): void;
|
|
191
|
+
/**
|
|
192
|
+
* Human archive: move an experience to archived status. Unlike delete, the
|
|
193
|
+
* data is preserved (recoverable via deep lookup) but removed from active
|
|
194
|
+
* recall. This is the only way to retire system-managed experiences
|
|
195
|
+
* (e.g. extraction-feedback).
|
|
196
|
+
*/
|
|
197
|
+
humanArchiveExperience(request: HumanArchiveExperienceRequest, actor: MemoryActor): void;
|
|
160
198
|
/** Human edit: rewrite fields of the active revision in place. */
|
|
161
199
|
humanEditExperience(request: HumanEditExperienceRequest, actor: MemoryActor): ExperienceSnapshot;
|
|
162
200
|
/** Human injection: fixed format, source=human, trust floor, directly live. */
|
package/lib/types/core.js
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { randomUUID } from 'node:crypto';
|
|
24
24
|
import { blockHash, estimateTokens, tokenize } from "./store.js";
|
|
25
|
+
import { isSystemExperienceFamily } from "./types.js";
|
|
25
26
|
/** The mechanism defaults (005 mapping documented in the README). */
|
|
26
27
|
export const DEFAULT_CORE_CONFIG = {
|
|
27
28
|
diaryExtractEvery: 8,
|
|
@@ -44,6 +45,8 @@ export const DEFAULT_CORE_CONFIG = {
|
|
|
44
45
|
candidateTrialFloorScore: 0.18,
|
|
45
46
|
consolidateEveryNew: 6,
|
|
46
47
|
consolidateIntervalHours: 24,
|
|
48
|
+
deletionFeedbackIntervalHours: 24,
|
|
49
|
+
deletionFeedbackMinDeletions: 3,
|
|
47
50
|
};
|
|
48
51
|
/** Objective-evidence markers overriding a claimed experience-attributed failure. */
|
|
49
52
|
const ENVIRONMENT_EVIDENCE_PATTERN = /network|timeout|timed out|EPERM|EACCES|ECONNREFUSED|ENOTFOUND|429|503|quota|rate.?limit|unauthorized|dns|proxy|网络|超时|断网|权限|配额|限流|服务不可用|服务繁忙/i;
|
|
@@ -656,6 +659,11 @@ export class MemoryCore {
|
|
|
656
659
|
/** 上升通道: apply extracted facts over the pending diary window. */
|
|
657
660
|
extract(request, actor, trigger = 'manual') {
|
|
658
661
|
const result = { applied: [], conflicts: [], rejected: [], appliedConcerns: 0 };
|
|
662
|
+
// Include deletion-feedback guidance if an extraction-feedback experience exists.
|
|
663
|
+
const feedback = this.getDeletionFeedback();
|
|
664
|
+
if (feedback !== undefined) {
|
|
665
|
+
result.deletionFeedback = feedback.reasoning;
|
|
666
|
+
}
|
|
659
667
|
const now = Date.now();
|
|
660
668
|
const consumedDiary = new Set();
|
|
661
669
|
for (const proposal of request.proposals) {
|
|
@@ -969,6 +977,92 @@ export class MemoryCore {
|
|
|
969
977
|
}
|
|
970
978
|
return result;
|
|
971
979
|
}
|
|
980
|
+
// ── deletion-feedback summarization (P1-2) ────────────────────────────────
|
|
981
|
+
/** Family id for the auto-generated extraction-feedback experience. */
|
|
982
|
+
static DELETION_FEEDBACK_FAMILY = 'extraction-feedback';
|
|
983
|
+
/**
|
|
984
|
+
* Check whether a deletion-feedback summarization run is due.
|
|
985
|
+
* Conditions: enough new deletions since last run AND enough time elapsed.
|
|
986
|
+
* @returns { due, lastTs, newDeletions, hoursSince }
|
|
987
|
+
*/
|
|
988
|
+
deletionFeedbackDue() {
|
|
989
|
+
const lastTs = this.store.lastDeletionFeedbackTs();
|
|
990
|
+
const hoursSince = lastTs === 0 ? Infinity : (Date.now() - lastTs) / (60 * 60 * 1000);
|
|
991
|
+
const newDeletions = this.store.countDeletionsSince(lastTs);
|
|
992
|
+
const enoughDeletions = newDeletions >= this.config.deletionFeedbackMinDeletions;
|
|
993
|
+
const intervalPassed = hoursSince >= this.config.deletionFeedbackIntervalHours;
|
|
994
|
+
return { due: enoughDeletions && intervalPassed, lastTs, newDeletions, hoursSince };
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Apply an LLM-generated deletion-feedback summary as an extraction-feedback
|
|
998
|
+
* experience. If one already exists, it is revised in place (new revision);
|
|
999
|
+
* otherwise a new candidate experience is created.
|
|
1000
|
+
* @param summary - the LLM-generated summary text (gist + reasoning).
|
|
1001
|
+
* @param actor - who triggered the summarization ('system').
|
|
1002
|
+
* @returns the upserted experience snapshot.
|
|
1003
|
+
*/
|
|
1004
|
+
applyDeletionFeedback(summary, actor) {
|
|
1005
|
+
const now = Date.now();
|
|
1006
|
+
const existing = this.store.findExperienceByFamily(MemoryCore.DELETION_FEEDBACK_FAMILY);
|
|
1007
|
+
if (existing !== undefined) {
|
|
1008
|
+
// Revise in place: create a new revision with updated content
|
|
1009
|
+
const next = {
|
|
1010
|
+
...existing,
|
|
1011
|
+
revision: existing.revision + 1,
|
|
1012
|
+
gist: summary.slice(0, 200),
|
|
1013
|
+
reasoning: summary,
|
|
1014
|
+
status: 'live',
|
|
1015
|
+
updatedAt: now,
|
|
1016
|
+
};
|
|
1017
|
+
this.store.upsertExperience(next);
|
|
1018
|
+
this.ledger('revise', 'experience', next.id, actor, {
|
|
1019
|
+
revision: next.revision,
|
|
1020
|
+
previousRevision: existing.revision,
|
|
1021
|
+
}, 'deletion-feedback summarization');
|
|
1022
|
+
return next;
|
|
1023
|
+
}
|
|
1024
|
+
// Create new extraction-feedback experience
|
|
1025
|
+
const id = crypto.randomUUID();
|
|
1026
|
+
const exp = {
|
|
1027
|
+
id,
|
|
1028
|
+
familyId: id,
|
|
1029
|
+
revision: 1,
|
|
1030
|
+
kind: 'positive',
|
|
1031
|
+
source: 'system',
|
|
1032
|
+
family: MemoryCore.DELETION_FEEDBACK_FAMILY,
|
|
1033
|
+
gist: summary.slice(0, 200),
|
|
1034
|
+
situation: ['memory_extract 提炼新记忆时,参考此经验避免重复提取已被用户否定的类型'],
|
|
1035
|
+
path: [{ order: 1, action: '读取此经验的 reasoning 字段,了解哪些类型的记忆曾被用户删除及原因' }, { order: 2, action: '提炼时避开这些类型,优先提取用户认可的记忆模式' }],
|
|
1036
|
+
reasoning: summary,
|
|
1037
|
+
limits: ['此经验由系统自动生成,禁止人工删除(只能归档)', '内容会随删除记录增多而定期更新'],
|
|
1038
|
+
status: 'live',
|
|
1039
|
+
alpha: 5,
|
|
1040
|
+
beta: 2,
|
|
1041
|
+
pinned: false,
|
|
1042
|
+
tokensSaved: 0,
|
|
1043
|
+
tokensSpent: 0,
|
|
1044
|
+
context: '',
|
|
1045
|
+
globalFlag: true,
|
|
1046
|
+
verifiedCount: 0,
|
|
1047
|
+
rejectCount: 0,
|
|
1048
|
+
createdAt: now,
|
|
1049
|
+
updatedAt: now,
|
|
1050
|
+
};
|
|
1051
|
+
this.store.upsertExperience(exp);
|
|
1052
|
+
this.ledger('refine', 'experience', exp.id, actor, {
|
|
1053
|
+
family: exp.family,
|
|
1054
|
+
status: exp.status,
|
|
1055
|
+
}, 'deletion-feedback summarization (initial)');
|
|
1056
|
+
this.store.setLastDeletionFeedbackTs(now);
|
|
1057
|
+
return exp;
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Get the current extraction-feedback experience (if any) for injection into
|
|
1061
|
+
* the extraction prompt.
|
|
1062
|
+
*/
|
|
1063
|
+
getDeletionFeedback() {
|
|
1064
|
+
return this.store.findExperienceByFamily(MemoryCore.DELETION_FEEDBACK_FAMILY);
|
|
1065
|
+
}
|
|
972
1066
|
// ── human operations (all ledgered) ───────────────────────────────────────
|
|
973
1067
|
/** Human pin/unpin: pinned cards keep the trust floor and escape budgets. */
|
|
974
1068
|
humanPin(request, actor) {
|
|
@@ -986,6 +1080,13 @@ export class MemoryCore {
|
|
|
986
1080
|
if (familyRows.length === 0)
|
|
987
1081
|
throw new Error(`memory: experience not found: ${request.id}`);
|
|
988
1082
|
const head = familyRows[familyRows.length - 1];
|
|
1083
|
+
// System-managed families (e.g. extraction-feedback) cannot be deleted —
|
|
1084
|
+
// only archived. Deletion would lose accumulated feedback; archiving
|
|
1085
|
+
// preserves the ledger trail while removing it from active recall.
|
|
1086
|
+
if (isSystemExperienceFamily(head.family)) {
|
|
1087
|
+
throw new Error(`memory: system experience "${head.family}" cannot be deleted (only archived). `
|
|
1088
|
+
+ 'Use the archive action to remove it from active recall while preserving the audit trail.');
|
|
1089
|
+
}
|
|
989
1090
|
this.store.deleteFamily(request.id);
|
|
990
1091
|
this.ledger('delete', 'experience', request.id, actor, {
|
|
991
1092
|
gist: head.gist,
|
|
@@ -993,6 +1094,25 @@ export class MemoryCore {
|
|
|
993
1094
|
revisions: familyRows.length,
|
|
994
1095
|
}, request.reason);
|
|
995
1096
|
}
|
|
1097
|
+
/**
|
|
1098
|
+
* Human archive: move an experience to archived status. Unlike delete, the
|
|
1099
|
+
* data is preserved (recoverable via deep lookup) but removed from active
|
|
1100
|
+
* recall. This is the only way to retire system-managed experiences
|
|
1101
|
+
* (e.g. extraction-feedback).
|
|
1102
|
+
*/
|
|
1103
|
+
humanArchiveExperience(request, actor) {
|
|
1104
|
+
const current = this.store.getActiveRevision(request.id);
|
|
1105
|
+
if (current === undefined)
|
|
1106
|
+
throw new Error(`memory: experience not found: ${request.id}`);
|
|
1107
|
+
if (current.status === 'archived')
|
|
1108
|
+
return; // already archived, idempotent
|
|
1109
|
+
this.store.upsertExperience({ ...current, status: 'archived', updatedAt: Date.now() });
|
|
1110
|
+
this.ledger('archive', 'experience', request.id, actor, {
|
|
1111
|
+
gist: current.gist,
|
|
1112
|
+
family: current.family,
|
|
1113
|
+
previousStatus: current.status,
|
|
1114
|
+
}, request.reason);
|
|
1115
|
+
}
|
|
996
1116
|
/** Human edit: rewrite fields of the active revision in place. */
|
|
997
1117
|
humanEditExperience(request, actor) {
|
|
998
1118
|
const current = this.store.getActiveRevision(request.id);
|
package/lib/types/index.d.ts
CHANGED
|
@@ -55,6 +55,10 @@ export interface Config {
|
|
|
55
55
|
recallFloorScore?: number;
|
|
56
56
|
/** Shadow replay agreement required to adopt a draft. */
|
|
57
57
|
shadowPassRate?: number;
|
|
58
|
+
/** Minimum hours between deletion-feedback LLM summarization runs. */
|
|
59
|
+
deletionFeedbackIntervalHours?: number;
|
|
60
|
+
/** Minimum new deletions since last run to trigger summarization. */
|
|
61
|
+
deletionFeedbackMinDeletions?: number;
|
|
58
62
|
}
|
|
59
63
|
/** Resolve the plugin config with explicit defaults; unknown keys fail loud. */
|
|
60
64
|
export declare function resolveConfig(config: Config): Required<Omit<Config, 'databasePath' | 'workspacePath'>> & {
|
package/lib/types/index.js
CHANGED
|
@@ -25,6 +25,7 @@ export function resolveConfig(config) {
|
|
|
25
25
|
'challengeConsecutiveFails', 'challengeWindow', 'challengeWindowFailRate',
|
|
26
26
|
'familyLiveCap', 'complexityTokenGate', 'complexityStepGate',
|
|
27
27
|
'duplicateOverlapGate', 'recallFloorScore', 'shadowPassRate',
|
|
28
|
+
'deletionFeedbackIntervalHours', 'deletionFeedbackMinDeletions',
|
|
28
29
|
];
|
|
29
30
|
const unknown = Object.keys(config).filter(key => !known.includes(key));
|
|
30
31
|
if (unknown.length > 0) {
|
|
@@ -49,6 +50,8 @@ export function resolveConfig(config) {
|
|
|
49
50
|
duplicateOverlapGate: config.duplicateOverlapGate ?? DEFAULT_CORE_CONFIG.duplicateOverlapGate,
|
|
50
51
|
recallFloorScore: config.recallFloorScore ?? DEFAULT_CORE_CONFIG.recallFloorScore,
|
|
51
52
|
shadowPassRate: config.shadowPassRate ?? DEFAULT_CORE_CONFIG.shadowPassRate,
|
|
53
|
+
deletionFeedbackIntervalHours: config.deletionFeedbackIntervalHours ?? DEFAULT_CORE_CONFIG.deletionFeedbackIntervalHours,
|
|
54
|
+
deletionFeedbackMinDeletions: config.deletionFeedbackMinDeletions ?? DEFAULT_CORE_CONFIG.deletionFeedbackMinDeletions,
|
|
52
55
|
};
|
|
53
56
|
}
|
|
54
57
|
/**
|
|
@@ -74,6 +77,8 @@ export function apply(ctx, config = {}) {
|
|
|
74
77
|
duplicateOverlapGate: resolved.duplicateOverlapGate,
|
|
75
78
|
recallFloorScore: resolved.recallFloorScore,
|
|
76
79
|
shadowPassRate: resolved.shadowPassRate,
|
|
80
|
+
deletionFeedbackIntervalHours: resolved.deletionFeedbackIntervalHours,
|
|
81
|
+
deletionFeedbackMinDeletions: resolved.deletionFeedbackMinDeletions,
|
|
77
82
|
};
|
|
78
83
|
mkdirSync(join(resolved.databasePath, '..'), { recursive: true });
|
|
79
84
|
const db = new DatabaseSync(resolved.databasePath);
|
package/lib/types/service.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type { Context } from '@deepseek-ai/cordis';
|
|
|
9
9
|
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
10
10
|
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
11
11
|
import type { MemoryCore } from './core.ts';
|
|
12
|
-
import type { ConcernTree, ConsolidateRequest, ConsolidateResult, DiaryAppendRequest, DiaryAppendResult, DiaryEntry, ExperienceListFilter, ExperienceSnapshot, ExtractionRecord, ExtractFactsRequest, ExtractFactsResult, FactEntry, HumanAddExperienceRequest, HumanAddFactRequest, HumanAckDiaryRequest, HumanConfirmFactRequest, HumanDeleteConcernRequest, HumanDeleteExperienceRequest, HumanDeleteFactRequest, HumanEditExperienceRequest, HumanEditFactRequest, HumanPinRequest, HumanReleaseColdRequest, HumanSetConcernStatusRequest, IngestRequest, IngestResult, LedgerBlock, LedgerIntegrityResult, LedgerQueryRequest, MemoryExport, MemoryStats, MemoryWorkbenchInfo, RecallExperiencesRequest, RecallExperiencesResult, RefineExperienceRequest, RefineExperienceResult, ReportUseRequest, ReportUseResult, ReviseExperienceRequest, RollbackExperienceRequest, VerifyShadowRequest, VerifyShadowResult } from './types.ts';
|
|
12
|
+
import type { ConcernTree, ConsolidateRequest, ConsolidateResult, DiaryAppendRequest, DiaryAppendResult, DiaryEntry, ExperienceListFilter, ExperienceSnapshot, ExtractionRecord, ExtractFactsRequest, ExtractFactsResult, FactEntry, HumanAddExperienceRequest, HumanAddFactRequest, HumanAckDiaryRequest, HumanConfirmFactRequest, HumanArchiveExperienceRequest, HumanDeleteConcernRequest, HumanDeleteExperienceRequest, HumanDeleteFactRequest, HumanEditExperienceRequest, HumanEditFactRequest, HumanPinRequest, HumanReleaseColdRequest, HumanSetConcernStatusRequest, IngestRequest, IngestResult, LedgerBlock, LedgerIntegrityResult, LedgerQueryRequest, MemoryExport, MemoryStats, MemoryWorkbenchInfo, RecallExperiencesRequest, RecallExperiencesResult, RefineExperienceRequest, RefineExperienceResult, ReportUseRequest, ReportUseResult, ReviseExperienceRequest, RollbackExperienceRequest, VerifyShadowRequest, VerifyShadowResult } from './types.ts';
|
|
13
13
|
/**
|
|
14
14
|
* Remote face of the memory library. All methods delegate to the core; the
|
|
15
15
|
* core carries the 生·用·修·记 mechanism semantics.
|
|
@@ -44,7 +44,28 @@ export declare class MemoryService extends TypertRemoteService {
|
|
|
44
44
|
/** 记: append one diary entry; signals the extraction duty when due. */
|
|
45
45
|
appendDiary(agent: Agent, request: DiaryAppendRequest): DiaryAppendResult;
|
|
46
46
|
/** 上升通道: apply extracted facts over the pending diary window. */
|
|
47
|
-
extract(agent: Agent, request: ExtractFactsRequest): ExtractFactsResult
|
|
47
|
+
extract(agent: Agent, request: ExtractFactsRequest): Promise<ExtractFactsResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Check if deletion-feedback summarization is due and run it if so.
|
|
50
|
+
* Uses the agent's current model route for the LLM call.
|
|
51
|
+
*/
|
|
52
|
+
private maybeRunDeletionFeedbackSummarization;
|
|
53
|
+
/**
|
|
54
|
+
* Call the LLM to summarize deletion records into extraction feedback rules.
|
|
55
|
+
* Uses ctx.llm.stream() with the agent's current model route.
|
|
56
|
+
*/
|
|
57
|
+
private summarizeDeletionsWithLlm;
|
|
58
|
+
/**
|
|
59
|
+
* Remote: manually trigger deletion-feedback summarization (for testing/debugging).
|
|
60
|
+
*/
|
|
61
|
+
runDeletionFeedback(agent: Agent): Promise<{
|
|
62
|
+
ran: boolean;
|
|
63
|
+
summary?: string;
|
|
64
|
+
}>;
|
|
65
|
+
/**
|
|
66
|
+
* Remote: get the current deletion-feedback experience (for debugging).
|
|
67
|
+
*/
|
|
68
|
+
getDeletionFeedback(agent: Agent): ExperienceSnapshot | null;
|
|
48
69
|
/** Diary timeline for the workbench (007 §2: server-side pagination, newest first). */
|
|
49
70
|
listDiary(agent: Agent, limit: number, offset: number, onlyUnextracted: boolean): DiaryEntry[];
|
|
50
71
|
/** Several diary entries by id (008 Path A: fact→diary provenance). */
|
|
@@ -96,6 +117,10 @@ export declare class MemoryService extends TypertRemoteService {
|
|
|
96
117
|
humanDeleteExperience(agent: Agent, request: HumanDeleteExperienceRequest): {
|
|
97
118
|
deleted: true;
|
|
98
119
|
};
|
|
120
|
+
/** Human archive (move to archived status; preserves data, removes from recall). */
|
|
121
|
+
humanArchiveExperience(agent: Agent, request: HumanArchiveExperienceRequest): {
|
|
122
|
+
archived: true;
|
|
123
|
+
};
|
|
99
124
|
/** Human edit of the active revision. */
|
|
100
125
|
humanEditExperience(agent: Agent, request: HumanEditExperienceRequest): ExperienceSnapshot;
|
|
101
126
|
/** Human injection in the fixed experience format. */
|
package/lib/types/service.js
CHANGED
|
@@ -64,6 +64,8 @@ let MemoryService = (() => {
|
|
|
64
64
|
let _family_decorators;
|
|
65
65
|
let _appendDiary_decorators;
|
|
66
66
|
let _extract_decorators;
|
|
67
|
+
let _runDeletionFeedback_decorators;
|
|
68
|
+
let _getDeletionFeedback_decorators;
|
|
67
69
|
let _listDiary_decorators;
|
|
68
70
|
let _getDiaryByIds_decorators;
|
|
69
71
|
let _listFacts_decorators;
|
|
@@ -82,6 +84,7 @@ let MemoryService = (() => {
|
|
|
82
84
|
let _exportLibrary_decorators;
|
|
83
85
|
let _humanPin_decorators;
|
|
84
86
|
let _humanDeleteExperience_decorators;
|
|
87
|
+
let _humanArchiveExperience_decorators;
|
|
85
88
|
let _humanEditExperience_decorators;
|
|
86
89
|
let _humanAddExperience_decorators;
|
|
87
90
|
let _humanPromote_decorators;
|
|
@@ -109,6 +112,8 @@ let MemoryService = (() => {
|
|
|
109
112
|
_family_decorators = [Remote('family')];
|
|
110
113
|
_appendDiary_decorators = [Remote('appendDiary')];
|
|
111
114
|
_extract_decorators = [Remote('extract')];
|
|
115
|
+
_runDeletionFeedback_decorators = [Remote('runDeletionFeedback')];
|
|
116
|
+
_getDeletionFeedback_decorators = [Remote('getDeletionFeedback')];
|
|
112
117
|
_listDiary_decorators = [Remote('listDiary')];
|
|
113
118
|
_getDiaryByIds_decorators = [Remote('getDiaryByIds')];
|
|
114
119
|
_listFacts_decorators = [Remote('listFacts')];
|
|
@@ -127,6 +132,7 @@ let MemoryService = (() => {
|
|
|
127
132
|
_exportLibrary_decorators = [Remote('exportLibrary')];
|
|
128
133
|
_humanPin_decorators = [Remote('humanPin')];
|
|
129
134
|
_humanDeleteExperience_decorators = [Remote('humanDeleteExperience')];
|
|
135
|
+
_humanArchiveExperience_decorators = [Remote('humanArchiveExperience')];
|
|
130
136
|
_humanEditExperience_decorators = [Remote('humanEditExperience')];
|
|
131
137
|
_humanAddExperience_decorators = [Remote('humanAddExperience')];
|
|
132
138
|
_humanPromote_decorators = [Remote('humanPromote')];
|
|
@@ -151,6 +157,8 @@ let MemoryService = (() => {
|
|
|
151
157
|
__esDecorate(this, null, _family_decorators, { kind: "method", name: "family", static: false, private: false, access: { has: obj => "family" in obj, get: obj => obj.family }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
152
158
|
__esDecorate(this, null, _appendDiary_decorators, { kind: "method", name: "appendDiary", static: false, private: false, access: { has: obj => "appendDiary" in obj, get: obj => obj.appendDiary }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
153
159
|
__esDecorate(this, null, _extract_decorators, { kind: "method", name: "extract", static: false, private: false, access: { has: obj => "extract" in obj, get: obj => obj.extract }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
160
|
+
__esDecorate(this, null, _runDeletionFeedback_decorators, { kind: "method", name: "runDeletionFeedback", static: false, private: false, access: { has: obj => "runDeletionFeedback" in obj, get: obj => obj.runDeletionFeedback }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
161
|
+
__esDecorate(this, null, _getDeletionFeedback_decorators, { kind: "method", name: "getDeletionFeedback", static: false, private: false, access: { has: obj => "getDeletionFeedback" in obj, get: obj => obj.getDeletionFeedback }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
154
162
|
__esDecorate(this, null, _listDiary_decorators, { kind: "method", name: "listDiary", static: false, private: false, access: { has: obj => "listDiary" in obj, get: obj => obj.listDiary }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
155
163
|
__esDecorate(this, null, _getDiaryByIds_decorators, { kind: "method", name: "getDiaryByIds", static: false, private: false, access: { has: obj => "getDiaryByIds" in obj, get: obj => obj.getDiaryByIds }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
156
164
|
__esDecorate(this, null, _listFacts_decorators, { kind: "method", name: "listFacts", static: false, private: false, access: { has: obj => "listFacts" in obj, get: obj => obj.listFacts }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
@@ -169,6 +177,7 @@ let MemoryService = (() => {
|
|
|
169
177
|
__esDecorate(this, null, _exportLibrary_decorators, { kind: "method", name: "exportLibrary", static: false, private: false, access: { has: obj => "exportLibrary" in obj, get: obj => obj.exportLibrary }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
170
178
|
__esDecorate(this, null, _humanPin_decorators, { kind: "method", name: "humanPin", static: false, private: false, access: { has: obj => "humanPin" in obj, get: obj => obj.humanPin }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
171
179
|
__esDecorate(this, null, _humanDeleteExperience_decorators, { kind: "method", name: "humanDeleteExperience", static: false, private: false, access: { has: obj => "humanDeleteExperience" in obj, get: obj => obj.humanDeleteExperience }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
180
|
+
__esDecorate(this, null, _humanArchiveExperience_decorators, { kind: "method", name: "humanArchiveExperience", static: false, private: false, access: { has: obj => "humanArchiveExperience" in obj, get: obj => obj.humanArchiveExperience }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
172
181
|
__esDecorate(this, null, _humanEditExperience_decorators, { kind: "method", name: "humanEditExperience", static: false, private: false, access: { has: obj => "humanEditExperience" in obj, get: obj => obj.humanEditExperience }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
173
182
|
__esDecorate(this, null, _humanAddExperience_decorators, { kind: "method", name: "humanAddExperience", static: false, private: false, access: { has: obj => "humanAddExperience" in obj, get: obj => obj.humanAddExperience }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
174
183
|
__esDecorate(this, null, _humanPromote_decorators, { kind: "method", name: "humanPromote", static: false, private: false, access: { has: obj => "humanPromote" in obj, get: obj => obj.humanPromote }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
@@ -241,9 +250,106 @@ let MemoryService = (() => {
|
|
|
241
250
|
return this.core.appendDiary(request, actorOf(agent));
|
|
242
251
|
}
|
|
243
252
|
/** 上升通道: apply extracted facts over the pending diary window. */
|
|
244
|
-
extract(agent, request) {
|
|
253
|
+
async extract(agent, request) {
|
|
254
|
+
// P1-2: lazy-trigger deletion-feedback summarization before extraction.
|
|
255
|
+
// If enough deletions have accumulated and enough time has passed, run an
|
|
256
|
+
// LLM summarization to update the extraction-feedback experience. This
|
|
257
|
+
// ensures the feedback is fresh when the extraction prompt references it.
|
|
258
|
+
await this.maybeRunDeletionFeedbackSummarization(agent);
|
|
245
259
|
return this.core.extract(request, actorOf(agent), 'manual');
|
|
246
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* Check if deletion-feedback summarization is due and run it if so.
|
|
263
|
+
* Uses the agent's current model route for the LLM call.
|
|
264
|
+
*/
|
|
265
|
+
async maybeRunDeletionFeedbackSummarization(agent) {
|
|
266
|
+
const check = this.core.deletionFeedbackDue();
|
|
267
|
+
if (!check.due)
|
|
268
|
+
return;
|
|
269
|
+
try {
|
|
270
|
+
const records = this.core['store'].getDeletionRecordsSince(check.lastTs, 50);
|
|
271
|
+
if (records.length === 0)
|
|
272
|
+
return;
|
|
273
|
+
const summary = await this.summarizeDeletionsWithLlm(agent, records);
|
|
274
|
+
if (summary.length > 0) {
|
|
275
|
+
this.core.applyDeletionFeedback(summary, 'system');
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch {
|
|
279
|
+
// Summarization failure is non-fatal — extraction proceeds without updated feedback.
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Call the LLM to summarize deletion records into extraction feedback rules.
|
|
284
|
+
* Uses ctx.llm.stream() with the agent's current model route.
|
|
285
|
+
*/
|
|
286
|
+
async summarizeDeletionsWithLlm(agent, records) {
|
|
287
|
+
const header = agent.session.requestHeader()?.config;
|
|
288
|
+
if (header === undefined)
|
|
289
|
+
return ''; // no model route available
|
|
290
|
+
const provider = header.provider;
|
|
291
|
+
const model = header.model;
|
|
292
|
+
if (provider === undefined || model === undefined)
|
|
293
|
+
return '';
|
|
294
|
+
const deletionList = records.map((r, i) => `${i + 1}. [${new Date(r.ts).toLocaleDateString('zh-CN')}] 删除的经验:「${r.gist.slice(0, 80)}」\n 原因:${r.reason || '(未填写)'}`).join('\n\n');
|
|
295
|
+
const systemPrompt = `你是一个记忆系统的反馈分析器。你的任务是分析用户删除记忆时填写的原因,总结出"什么类型的记忆不值得提取"的规则。
|
|
296
|
+
|
|
297
|
+
输出要求:
|
|
298
|
+
1. 用简洁的中文列出 3-5 条规则
|
|
299
|
+
2. 每条规则说明:什么类型的记忆应该避免提取,以及为什么
|
|
300
|
+
3. 规则要具体可操作,不要泛泛而谈
|
|
301
|
+
4. 如果删除原因都很相似,合并为更精炼的规则`;
|
|
302
|
+
const userPrompt = `以下是近期被用户删除的记忆及其删除原因:
|
|
303
|
+
|
|
304
|
+
${deletionList}
|
|
305
|
+
|
|
306
|
+
请总结成提取反馈规则。`;
|
|
307
|
+
const messages = [{
|
|
308
|
+
role: 'user',
|
|
309
|
+
content: [{ type: 'text', text: userPrompt }],
|
|
310
|
+
}];
|
|
311
|
+
let text = '';
|
|
312
|
+
const options = {
|
|
313
|
+
provider,
|
|
314
|
+
model,
|
|
315
|
+
messages,
|
|
316
|
+
system: systemPrompt,
|
|
317
|
+
maxTokens: 1500,
|
|
318
|
+
sessionId: agent.session.id,
|
|
319
|
+
};
|
|
320
|
+
for await (const chunk of this.ctx.llm.stream(options)) {
|
|
321
|
+
if (chunk.type === 'text-delta')
|
|
322
|
+
text += chunk.text;
|
|
323
|
+
}
|
|
324
|
+
return text.trim();
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Remote: manually trigger deletion-feedback summarization (for testing/debugging).
|
|
328
|
+
*/
|
|
329
|
+
async runDeletionFeedback(agent) {
|
|
330
|
+
const check = this.core.deletionFeedbackDue();
|
|
331
|
+
const records = this.core['store'].getDeletionRecordsSince(check.lastTs, 50);
|
|
332
|
+
if (records.length === 0)
|
|
333
|
+
return { ran: false };
|
|
334
|
+
try {
|
|
335
|
+
const summary = await this.summarizeDeletionsWithLlm(agent, records);
|
|
336
|
+
if (summary.length > 0) {
|
|
337
|
+
this.core.applyDeletionFeedback(summary, 'system');
|
|
338
|
+
return { ran: true, summary };
|
|
339
|
+
}
|
|
340
|
+
return { ran: false };
|
|
341
|
+
}
|
|
342
|
+
catch (e) {
|
|
343
|
+
return { ran: false, summary: String(e) };
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Remote: get the current deletion-feedback experience (for debugging).
|
|
348
|
+
*/
|
|
349
|
+
getDeletionFeedback(agent) {
|
|
350
|
+
void agent;
|
|
351
|
+
return this.core.getDeletionFeedback() ?? null;
|
|
352
|
+
}
|
|
247
353
|
/** Diary timeline for the workbench (007 §2: server-side pagination, newest first). */
|
|
248
354
|
listDiary(agent, limit, offset, onlyUnextracted) {
|
|
249
355
|
void agent;
|
|
@@ -348,6 +454,12 @@ let MemoryService = (() => {
|
|
|
348
454
|
this.core.humanDeleteExperience(request, 'human');
|
|
349
455
|
return { deleted: true };
|
|
350
456
|
}
|
|
457
|
+
/** Human archive (move to archived status; preserves data, removes from recall). */
|
|
458
|
+
humanArchiveExperience(agent, request) {
|
|
459
|
+
void agent;
|
|
460
|
+
this.core.humanArchiveExperience(request, 'human');
|
|
461
|
+
return { archived: true };
|
|
462
|
+
}
|
|
351
463
|
/** Human edit of the active revision. */
|
|
352
464
|
humanEditExperience(agent, request) {
|
|
353
465
|
void agent;
|
package/lib/types/store.d.ts
CHANGED
|
@@ -224,6 +224,22 @@ export declare class MemoryStore {
|
|
|
224
224
|
lastConsolidationTs(): number;
|
|
225
225
|
/** Non-deleted experiences created strictly after `ts` (new material since last consolidation). */
|
|
226
226
|
countExperiencesSince(ts: number): number;
|
|
227
|
+
/** Last deletion-feedback summarization ts (0 = never). Stored in memory_meta. */
|
|
228
|
+
lastDeletionFeedbackTs(): number;
|
|
229
|
+
/** Record the timestamp of a deletion-feedback summarization run. */
|
|
230
|
+
setLastDeletionFeedbackTs(ts: number): void;
|
|
231
|
+
/** Count experience deletions (ledger op='delete', objectType='experience') since a given ts. */
|
|
232
|
+
countDeletionsSince(ts: number): number;
|
|
233
|
+
/** Get the deletion ledger blocks since a given ts (for LLM summarization input). */
|
|
234
|
+
getDeletionRecordsSince(ts: number, limit?: number): Array<{
|
|
235
|
+
seq: number;
|
|
236
|
+
ts: number;
|
|
237
|
+
objectId: string;
|
|
238
|
+
reason: string;
|
|
239
|
+
gist: string;
|
|
240
|
+
}>;
|
|
241
|
+
/** Find the active (non-deleted) experience by family name. Returns the latest revision. */
|
|
242
|
+
findExperienceByFamily(family: string): ExperienceSnapshot | undefined;
|
|
227
243
|
/** Archive a set of experiences by family_id (leave recall; recoverable — never hard-deleted autonomously). */
|
|
228
244
|
archiveExperienceIds(ids: string[], ts: number): void;
|
|
229
245
|
/** Record one recall event. */
|
package/lib/types/store.js
CHANGED
|
@@ -724,6 +724,39 @@ export class MemoryStore {
|
|
|
724
724
|
const row = this.db.prepare('SELECT COUNT(*) AS n FROM experiences WHERE deleted = 0 AND created_at > ?').get(ts);
|
|
725
725
|
return row.n;
|
|
726
726
|
}
|
|
727
|
+
// ── deletion-feedback summarization (P1-2) ────────────────────────────────
|
|
728
|
+
/** Last deletion-feedback summarization ts (0 = never). Stored in memory_meta. */
|
|
729
|
+
lastDeletionFeedbackTs() {
|
|
730
|
+
const row = this.db.prepare("SELECT value FROM memory_meta WHERE key = 'last_deletion_feedback_ts'").get();
|
|
731
|
+
return row ? Number(row.value) : 0;
|
|
732
|
+
}
|
|
733
|
+
/** Record the timestamp of a deletion-feedback summarization run. */
|
|
734
|
+
setLastDeletionFeedbackTs(ts) {
|
|
735
|
+
this.db.prepare("INSERT OR REPLACE INTO memory_meta (key, value) VALUES ('last_deletion_feedback_ts', ?)").run(String(ts));
|
|
736
|
+
}
|
|
737
|
+
/** Count experience deletions (ledger op='delete', objectType='experience') since a given ts. */
|
|
738
|
+
countDeletionsSince(ts) {
|
|
739
|
+
const row = this.db.prepare("SELECT COUNT(*) AS n FROM ledger WHERE op = 'delete' AND object_type = 'experience' AND ts > ?").get(ts);
|
|
740
|
+
return row.n;
|
|
741
|
+
}
|
|
742
|
+
/** Get the deletion ledger blocks since a given ts (for LLM summarization input). */
|
|
743
|
+
getDeletionRecordsSince(ts, limit = 50) {
|
|
744
|
+
const rows = this.db.prepare("SELECT seq, ts, object_id, reason, payload FROM ledger WHERE op = 'delete' AND object_type = 'experience' AND ts > ? ORDER BY ts DESC LIMIT ?").all(ts, limit);
|
|
745
|
+
return rows.map(r => {
|
|
746
|
+
let gist = '';
|
|
747
|
+
try {
|
|
748
|
+
const p = JSON.parse(r.payload);
|
|
749
|
+
gist = p.gist ?? '';
|
|
750
|
+
}
|
|
751
|
+
catch { /* ignore parse errors */ }
|
|
752
|
+
return { seq: r.seq, ts: r.ts, objectId: r.object_id, reason: r.reason ?? '', gist };
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
/** Find the active (non-deleted) experience by family name. Returns the latest revision. */
|
|
756
|
+
findExperienceByFamily(family) {
|
|
757
|
+
const row = this.db.prepare("SELECT * FROM experiences WHERE family = ? AND deleted = 0 ORDER BY revision DESC LIMIT 1").get(family);
|
|
758
|
+
return row ? this.rowToExperience(row) : undefined;
|
|
759
|
+
}
|
|
727
760
|
/** Archive a set of experiences by family_id (leave recall; recoverable — never hard-deleted autonomously). */
|
|
728
761
|
archiveExperienceIds(ids, ts) {
|
|
729
762
|
const stmt = this.db.prepare(`UPDATE experiences SET status = ?, updated_at = ? WHERE family_id = ? AND deleted = 0 AND status IN ('candidate','live','challenged')`);
|
package/lib/types/types.d.ts
CHANGED
|
@@ -4,6 +4,15 @@
|
|
|
4
4
|
* append-only ledger. Types only — no runtime code.
|
|
5
5
|
* @module dsh-daoing-memory/types
|
|
6
6
|
*/
|
|
7
|
+
/**
|
|
8
|
+
* System-managed experience families that cannot be deleted by human operators
|
|
9
|
+
* (only archived). The extraction-feedback family is auto-generated by the
|
|
10
|
+
* daily deletion-reason summarizer and serves as negative guidance for future
|
|
11
|
+
* memory extraction.
|
|
12
|
+
*/
|
|
13
|
+
export declare const SYSTEM_EXPERIENCE_FAMILIES: ReadonlySet<string>;
|
|
14
|
+
/** Check whether an experience family is system-managed (delete-protected). */
|
|
15
|
+
export declare function isSystemExperienceFamily(family: string): boolean;
|
|
7
16
|
/** Lifecycle status of one experience revision (005 §3 state machine + 006 §3 cold palace). */
|
|
8
17
|
export type ExperienceStatus = 'candidate' | 'live' | 'challenged' | 'superseded' | 'archived' | 'cold';
|
|
9
18
|
/** Positive = a path that works; negative = a confirmed dead end + reason. */
|
|
@@ -443,6 +452,8 @@ export interface ExtractFactsResult {
|
|
|
443
452
|
}[];
|
|
444
453
|
/** Concern nodes created/extended by this extraction (007 §2). */
|
|
445
454
|
appliedConcerns: number;
|
|
455
|
+
/** Deletion-feedback guidance (if an extraction-feedback experience exists). The agent should reference this when forming future extraction proposals. */
|
|
456
|
+
deletionFeedback?: string;
|
|
446
457
|
}
|
|
447
458
|
/** Concern shape (open by design; the enum only guides the model). */
|
|
448
459
|
/**
|
|
@@ -576,6 +587,13 @@ export interface HumanDeleteExperienceRequest {
|
|
|
576
587
|
/** Required reason (audited). */
|
|
577
588
|
reason: string;
|
|
578
589
|
}
|
|
590
|
+
/** Human archive (move to archived status; preserves data, removes from active recall). */
|
|
591
|
+
export interface HumanArchiveExperienceRequest {
|
|
592
|
+
/** Experience family id. */
|
|
593
|
+
id: string;
|
|
594
|
+
/** Required reason (audited). */
|
|
595
|
+
reason: string;
|
|
596
|
+
}
|
|
579
597
|
/** Human edit of one experience field set (creates no new revision). */
|
|
580
598
|
export interface HumanEditExperienceRequest {
|
|
581
599
|
/** Experience family id. */
|
package/lib/types/types.js
CHANGED
|
@@ -4,5 +4,18 @@
|
|
|
4
4
|
* append-only ledger. Types only — no runtime code.
|
|
5
5
|
* @module dsh-daoing-memory/types
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
// ── experience lifecycle ────────────────────────────────────────────────────
|
|
8
|
+
/**
|
|
9
|
+
* System-managed experience families that cannot be deleted by human operators
|
|
10
|
+
* (only archived). The extraction-feedback family is auto-generated by the
|
|
11
|
+
* daily deletion-reason summarizer and serves as negative guidance for future
|
|
12
|
+
* memory extraction.
|
|
13
|
+
*/
|
|
14
|
+
export const SYSTEM_EXPERIENCE_FAMILIES = new Set([
|
|
15
|
+
'extraction-feedback',
|
|
16
|
+
]);
|
|
17
|
+
/** Check whether an experience family is system-managed (delete-protected). */
|
|
18
|
+
export function isSystemExperienceFamily(family) {
|
|
19
|
+
return SYSTEM_EXPERIENCE_FAMILIES.has(family);
|
|
20
|
+
}
|
|
8
21
|
//# sourceMappingURL=types.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-daoing-memory",
|
|
3
3
|
"description": "Self-evolving memory for DeepSeek Harness (DSH): earned experiences, diary/fact semantic memory, concern tracking, and an append-only audit ledger.",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.8",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "daoing",
|