@deepmaid/maid-curator 0.1.0-alpha.1 → 0.1.0-alpha.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.
Files changed (3) hide show
  1. package/lib/index.d.ts +110 -11
  2. package/lib/index.js +163 -35
  3. package/package.json +10 -9
package/lib/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { ToolDefinition } from "@deepseek-ai/dsh-tools";
2
2
  //#region ../maid-memory/src/types.d.ts
3
- /** maid-memory 契约:唯一事实来源,后续任务(T2-T5)与 provider 包全部 import 此处。 */
4
3
  interface ProviderCapabilities {
5
4
  readonly forget: boolean;
6
5
  readonly sharedScopes: boolean;
@@ -63,7 +62,7 @@ interface MemoryRecord {
63
62
  */
64
63
  interface WriteOpts {
65
64
  readonly scope?: 'personal' | 'global';
66
- readonly provenanceKind?: string;
65
+ readonly provenanceKind?: 'world' | 'private' | 'curated' | 'legacy';
67
66
  }
68
67
  interface WriteReceipt {
69
68
  readonly id: string;
@@ -79,7 +78,7 @@ interface WriteReceipt {
79
78
  */
80
79
  interface UpdateOpts {
81
80
  readonly scope?: 'personal' | 'shared' | 'global';
82
- readonly provenanceKind?: string;
81
+ readonly provenanceKind?: 'world' | 'private' | 'curated' | 'legacy';
83
82
  readonly content?: string;
84
83
  }
85
84
  interface MaidMemoryProvider {
@@ -171,7 +170,7 @@ interface CuratorMemoryFace {
171
170
  * 不是故障——策展链路在无该能力的部署上静默无事可做)。provider 内部失败照原样抛出
172
171
  * (fail-loud:空页与「无事可分拣」不可区分,SLM 扫描面同款裁定)。
173
172
  */
174
- declare function scanUnsortedFacts(memory: CuratorMemoryFace | undefined, ns: string): Promise<CuratorFact[]>;
173
+ declare function scanUnsortedFacts(memory: (() => CuratorMemoryFace | undefined) | CuratorMemoryFace | undefined, ns: string): Promise<CuratorFact[]>;
175
174
  //#endregion
176
175
  //#region src/execute.d.ts
177
176
  /**
@@ -256,6 +255,83 @@ interface MslmHttpClient {
256
255
  declare function defaultMslmBaseUrl(): string;
257
256
  declare function createMslmHttpClient(options?: MslmHttpOptions): MslmHttpClient;
258
257
  //#endregion
258
+ //#region src/approvals.d.ts
259
+ /**
260
+ * M3e §6.3:主人批准语法——限定短语 + 前四字否定词检测。
261
+ * 批准只能由主人原话产生;模型 approved 数组只能缩小集合(intersect)。
262
+ * 无 pending snapshot 时,批准词不产生任何 grant(null)。
263
+ */
264
+ interface ApprovalResult {
265
+ approvedIds: ReadonlySet<string>;
266
+ }
267
+ interface ApprovalContext {
268
+ snapshot: ProposalSnapshotLike | null;
269
+ approvalTurn: number;
270
+ masterTexts: readonly string[];
271
+ }
272
+ /** 最小提案快照面(真 ProposalSnapshot 结构兼容)。 */
273
+ interface ProposalSnapshotLike {
274
+ proposalId: string;
275
+ ns: string;
276
+ sessionId: string;
277
+ proposalTurn: number;
278
+ factIds: readonly string[];
279
+ }
280
+ declare function createApprovals(): {
281
+ /**
282
+ * 解析批准:检查主人原话是否含批准语义 + 快照不过期。
283
+ * 通过 → 返回 { approvedIds }(全量或点名子集);不通过 → undefined。
284
+ */
285
+ parse(ctx: ApprovalContext): ApprovalResult | undefined;
286
+ /**
287
+ * 工具 approved 与主人批准的交集(工具只能缩小,不能扩大)。
288
+ */
289
+ intersect(approval: ApprovalResult, toolApproved: readonly string[]): ReadonlySet<string>;
290
+ };
291
+ //#endregion
292
+ //#region src/proposal-store.d.ts
293
+ /**
294
+ * M3e §6.3:提案快照存储——dry-run 后保存 {ns, sessionId, turn, 规范化 plan} 的 hash。
295
+ * proposalId = sha256(sorted(factIds + content + action)) 前 16 位,确定性。
296
+ * 快照在当轮或次轮有效(isStale);跨 session/ns 隔离。
297
+ */
298
+ interface ProposalPlan {
299
+ facts: ReadonlyArray<{
300
+ id: string;
301
+ content: string;
302
+ scope: string;
303
+ }>;
304
+ proposals: ReadonlyArray<{
305
+ factId: string;
306
+ action: string;
307
+ reason: string;
308
+ }>;
309
+ }
310
+ interface ProposalSnapshot {
311
+ proposalId: string;
312
+ ns: string;
313
+ sessionId: string;
314
+ proposalTurn: number;
315
+ factIds: readonly string[];
316
+ /** 规范化排序后的 factIds+content+action(用于 proposalHash 校验)。 */
317
+ normalizedPlan: string;
318
+ }
319
+ declare function createProposalStore(): {
320
+ /** 注册提案快照(dry-run 后调用;同 ns+session 覆写旧快照)。 */
321
+ register(input: {
322
+ ns: string;
323
+ sessionId: string;
324
+ turn: number;
325
+ plan: ProposalPlan;
326
+ }): ProposalSnapshot;
327
+ /** 取最近快照(按 ns+sessionId)。 */
328
+ get(ns: string, sessionId: string): ProposalSnapshot | undefined;
329
+ /** 快照是否过期(当轮或次轮有效)。 */
330
+ isStale(snapshot: ProposalSnapshot, currentTurn: number): boolean;
331
+ /** 清除快照(消费后/burn)。 */
332
+ clear(ns: string, sessionId: string): void;
333
+ };
334
+ //#endregion
259
335
  //#region src/plugin.d.ts
260
336
  /**
261
337
  * maid-curator cordis 插件形态(M3b 任务 12,三闸门之策展修订的挂载面)。
@@ -296,7 +372,20 @@ interface MaidCuratorConfig {
296
372
  /** maidMemory 服务的策展消费面(鸭子收口,照 scan.ts CuratorMemoryFace 先例,不引
297
373
  * maid-memory 运行时依赖;真 MaidMemoryService 结构兼容)。 */
298
374
  interface CuratorMemoryServiceFace extends CuratorMemoryFace {
299
- resolveNamespace?(agentPreset: string | undefined): string | undefined;
375
+ /** M3f:统一 resolution → 命名空间(allowMaids 守卫在 maid-memory service 层)。 */
376
+ resolveNamespace?(resolution: {
377
+ maidId?: string;
378
+ record?: {
379
+ maidId: string;
380
+ memoryNamespace: string;
381
+ };
382
+ source: string;
383
+ midSessionSwitch: boolean;
384
+ } | undefined): string | undefined;
385
+ /** M3f:maidId 正向直取(固定面/后台任务用)。 */
386
+ namespaceForMaid?(maidId: string): string | undefined;
387
+ /** M3e:本会话当前主人原话快照(批准检查用;由 maid-memory lifecycle 装配)。 */
388
+ masterTextsOf?(sessionId: string): readonly string[];
300
389
  }
301
390
  /** 一次策展计划:待分拣事实快照 + 确定性提案(同输入必同输出,纯函数产物)。 */
302
391
  interface CuratorPlan {
@@ -318,18 +407,28 @@ interface MaidCuratorService {
318
407
  * 已离开待分拣集的 approved id 计入 skipped(重复 apply 同批第二次全 skipped)。 */
319
408
  apply(ns: string, approved: readonly string[]): Promise<ApplyReport>;
320
409
  }
321
- declare function createMaidCuratorService(memory: CuratorMemoryServiceFace | undefined, guide?: CurationGuide): MaidCuratorService;
410
+ declare function createMaidCuratorService(memoryOf: () => CuratorMemoryServiceFace | undefined, guide?: CurationGuide): MaidCuratorService;
322
411
  /** 工具装配依赖:ns 解析(config.namespace 覆写 / 会话 preset 单点解析)。 */
323
412
  interface CuratorToolDeps {
324
413
  resolveNamespace(exec: unknown): string;
414
+ /** M3e:批准解析 + 提案快照(apply 闭包传入;缺席 → apply fail-closed)。 */
415
+ approvals?: ReturnType<typeof createApprovals>;
416
+ proposalStore?: ReturnType<typeof createProposalStore>;
417
+ /** M3e:主人原话快照(memory.masterTextsOf 透传;apply 闭包传入)。 */
418
+ masterTextsOf?: (sessionId: string) => readonly string[];
325
419
  }
326
420
  /** 恰一个 scoped 工具(照 maid-memory「恰好两个工具」纪律):三模式覆盖策展全流程。 */
327
421
  declare function buildCuratorTool(service: MaidCuratorService, deps: CuratorToolDeps): ToolDefinition[];
328
- declare function registerCuratorTool(ctx: {
329
- tools: {
330
- register(definition: ToolDefinition): () => void;
422
+ declare function registerCuratorTool(ctx: any, service: MaidCuratorService, deps: CuratorToolDeps): () => void;
423
+ declare const apply: (ctx: {
424
+ reflect: {
425
+ get(name: string, optional?: boolean): unknown;
426
+ };
427
+ logger?: (name: string) => {
428
+ warn(m: string): void;
429
+ info(m: string): void;
331
430
  };
332
- }, service: MaidCuratorService, deps: CuratorToolDeps): () => void;
333
- declare const apply: (ctx: any, config: MaidCuratorConfig) => (() => void);
431
+ provide(name: string, value: unknown): () => void;
432
+ } & Record<string, unknown>, config: MaidCuratorConfig) => (() => void);
334
433
  //#endregion
335
434
  export { type ApplyFailure, type ApplyReport, type CurationGuide, type CuratorApplyFace, type CuratorDryRun, type CuratorFact, type CuratorMemoryFace, type CuratorMemoryServiceFace, type CuratorPlan, type CuratorToolDeps, DEFAULT_FALLBACK_ACTION, type GuideRule, type MaidCuratorConfig, type MaidCuratorService, type MslmCurateOptions, type MslmCurationPatch, type MslmHttpClient, type MslmHttpOptions, type Proposal, type ProposalAction, apply, applyProposals, buildCuratorTool, createMaidCuratorService, createMslmHttpClient, defaultCurationGuide, defaultMslmBaseUrl, inject, name, proposeDisposition, registerCuratorTool, renderDryRun, scanUnsortedFacts };
package/lib/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { defineTool } from "@deepseek-ai/dsh-tools";
2
+ import { createHash } from "node:crypto";
2
3
  //#region src/propose.ts
3
4
  /** 兜底缺省(M3b 任务 10 裁定):'curate'——留共享层补标注。delete 不可逆、personalize
4
5
  * 迁移有observable 后果,规则未说清的事实宁可原样升格,分拣报告里再由人/知惠复核。 */
@@ -111,7 +112,7 @@ const defaultCurationGuide = {
111
112
  * (fail-loud:空页与「无事可分拣」不可区分,SLM 扫描面同款裁定)。
112
113
  */
113
114
  async function scanUnsortedFacts(memory, ns) {
114
- const provider = memory?.activeProvider();
115
+ const provider = (typeof memory === "function" ? memory() : memory)?.activeProvider();
115
116
  if (provider === void 0 || provider.scanUnsorted === void 0) return [];
116
117
  return provider.scanUnsorted(ns);
117
118
  }
@@ -233,6 +234,107 @@ function createMslmHttpClient(options = {}) {
233
234
  } };
234
235
  }
235
236
  //#endregion
237
+ //#region src/approvals.ts
238
+ /** 批准语义短语(命中任一 → 候选批准;配合前四字否定词检测)。 */
239
+ const APPROVAL_PHRASES = [
240
+ /批准/,
241
+ /同意/,
242
+ /可以/,
243
+ /执行/,
244
+ /就这么办/,
245
+ /做吧/,
246
+ /开始吧/,
247
+ /按这个来/
248
+ ];
249
+ /** 句首肯定词(与批准短语共现时放行)。 */
250
+ const LEAD_ASSent = /^(好的|好|行)[,,!!。]/;
251
+ /** 否定词(命中前四字 → 拒绝)。 */
252
+ const NEGATION = /^(不|别|先不|不要|暂不|莫|勿|無|没)/;
253
+ /** 从主人原话提取点名的 factIds(模式:f1、f2 等)。 */
254
+ const FACT_ID_PATTERN = /\bf(\d+)\b/g;
255
+ function createApprovals() {
256
+ /** 检查单条主人文本是否含批准语义(无否定)。 */
257
+ const isApprovalText = (text) => {
258
+ const trimmed = text.trim();
259
+ if (trimmed.length === 0) return false;
260
+ const head = trimmed.slice(0, 4);
261
+ if (NEGATION.test(head) || NEGATION.test(trimmed.slice(0, 2))) return false;
262
+ const hasPhrase = APPROVAL_PHRASES.some((p) => p.test(trimmed));
263
+ const hasLead = LEAD_ASSent.test(trimmed) && APPROVAL_PHRASES.some((p) => p.test(trimmed.slice(4)));
264
+ return hasPhrase || hasLead;
265
+ };
266
+ return {
267
+ /**
268
+ * 解析批准:检查主人原话是否含批准语义 + 快照不过期。
269
+ * 通过 → 返回 { approvedIds }(全量或点名子集);不通过 → undefined。
270
+ */
271
+ parse(ctx) {
272
+ if (ctx.snapshot === null) return void 0;
273
+ if (ctx.approvalTurn > ctx.snapshot.proposalTurn + 1) return void 0;
274
+ const approvalText = ctx.masterTexts.find(isApprovalText);
275
+ if (approvalText === void 0) return void 0;
276
+ const named = [...approvalText.matchAll(FACT_ID_PATTERN)].map((m) => `f${m[1]}`);
277
+ const allIds = new Set(ctx.snapshot.factIds);
278
+ const approvedIds = named.length > 0 ? new Set(named.filter((id) => allIds.has(id))) : allIds;
279
+ if (approvedIds.size === 0) return void 0;
280
+ return { approvedIds };
281
+ },
282
+ /**
283
+ * 工具 approved 与主人批准的交集(工具只能缩小,不能扩大)。
284
+ */
285
+ intersect(approval, toolApproved) {
286
+ const toolSet = new Set(toolApproved);
287
+ return new Set([...approval.approvedIds].filter((id) => toolSet.has(id)));
288
+ }
289
+ };
290
+ }
291
+ //#endregion
292
+ //#region src/proposal-store.ts
293
+ /** 计算 proposalId(确定性:排序 factIds+content+action)。 */
294
+ function computeProposalId(plan) {
295
+ const entries = plan.proposals.map((p) => {
296
+ const fact = plan.facts.find((f) => f.id === p.factId);
297
+ return `${p.factId}:${fact?.content ?? ""}:${p.action}`;
298
+ }).sort();
299
+ return createHash("sha256").update(entries.join("\n")).digest("hex").slice(0, 16);
300
+ }
301
+ function createProposalStore() {
302
+ const snapshots = /* @__PURE__ */ new Map();
303
+ return {
304
+ /** 注册提案快照(dry-run 后调用;同 ns+session 覆写旧快照)。 */
305
+ register(input) {
306
+ const proposalId = computeProposalId(input.plan);
307
+ const factIds = input.plan.proposals.map((p) => p.factId);
308
+ const entries = input.plan.proposals.map((p) => {
309
+ const fact = input.plan.facts.find((f) => f.id === p.factId);
310
+ return `${p.factId}:${fact?.content ?? ""}:${p.action}`;
311
+ }).sort();
312
+ const snapshot = {
313
+ proposalId,
314
+ ns: input.ns,
315
+ sessionId: input.sessionId,
316
+ proposalTurn: input.turn,
317
+ factIds,
318
+ normalizedPlan: entries.join("\n")
319
+ };
320
+ snapshots.set(`${input.ns}:${input.sessionId}`, snapshot);
321
+ return snapshot;
322
+ },
323
+ /** 取最近快照(按 ns+sessionId)。 */
324
+ get(ns, sessionId) {
325
+ return snapshots.get(`${ns}:${sessionId}`);
326
+ },
327
+ /** 快照是否过期(当轮或次轮有效)。 */
328
+ isStale(snapshot, currentTurn) {
329
+ return currentTurn > snapshot.proposalTurn + 1;
330
+ },
331
+ /** 清除快照(消费后/burn)。 */
332
+ clear(ns, sessionId) {
333
+ snapshots.delete(`${ns}:${sessionId}`);
334
+ }
335
+ };
336
+ }
337
+ //#endregion
236
338
  //#region src/plugin.ts
237
339
  /**
238
340
  * maid-curator cordis 插件形态(M3b 任务 12,三闸门之策展修订的挂载面)。
@@ -261,16 +363,16 @@ function createMslmHttpClient(options = {}) {
261
363
  */
262
364
  const name = "maid-curator";
263
365
  const inject = ["tools"];
264
- function createMaidCuratorService(memory, guide = defaultCurationGuide) {
366
+ function createMaidCuratorService(memoryOf, guide = defaultCurationGuide) {
265
367
  const plan = async (ns) => {
266
- const facts = await scanUnsortedFacts(memory, ns);
368
+ const facts = await scanUnsortedFacts(memoryOf(), ns);
267
369
  return {
268
370
  facts,
269
371
  proposals: facts.map((fact) => proposeDisposition(fact, guide))
270
372
  };
271
373
  };
272
374
  return {
273
- scan: (ns) => scanUnsortedFacts(memory, ns),
375
+ scan: (ns) => scanUnsortedFacts(memoryOf(), ns),
274
376
  propose: plan,
275
377
  dryRun: async (ns) => {
276
378
  const p = await plan(ns);
@@ -280,7 +382,7 @@ function createMaidCuratorService(memory, guide = defaultCurationGuide) {
280
382
  };
281
383
  },
282
384
  apply: async (ns, approved) => {
283
- const provider = memory?.activeProvider();
385
+ const provider = memoryOf()?.activeProvider();
284
386
  if (provider === void 0) throw new Error("maid-curator: 无可用记忆 provider,策展执行被拒绝");
285
387
  const { proposals } = await plan(ns);
286
388
  const report = await applyProposals(provider, ns, proposals, new Set(approved));
@@ -395,7 +497,22 @@ function buildCuratorTool(service, deps) {
395
497
  if (typed.mode === "apply") {
396
498
  const approved = typed.approved ?? [];
397
499
  if (approved.length === 0) throw new Error("maid-curator: mode=apply 须携带非空 approved(主人批准的 fact_id 列表);主人未批准任何条目时不要调用 apply");
398
- const report = await service.apply(ns, approved);
500
+ const sessionId = exec.agent?.id ?? "";
501
+ if (deps.proposalStore === void 0 || deps.approvals === void 0) throw new Error("maid-curator: approvals/proposalStore 不可用——策展执行须走完整装配(插件 apply),不能在纯工具注册态调用 apply");
502
+ const snapshot = deps.proposalStore.get(ns, sessionId);
503
+ if (snapshot === void 0) throw new Error("maid-curator: 无待批准的提案快照——请先以 mode=dry-run 产出分拣报告并呈主人过目,主人点头后才能 apply");
504
+ if (deps.proposalStore.isStale(snapshot, 0) && deps.proposalStore.isStale(snapshot, 1)) throw new Error("maid-curator: 提案快照已过期——请重新 dry-run 并再次获得主人批准");
505
+ const masterTexts = deps.masterTextsOf?.(sessionId) ?? [];
506
+ const parsed = deps.approvals.parse({
507
+ snapshot,
508
+ approvalTurn: snapshot.proposalTurn + 1,
509
+ masterTexts
510
+ });
511
+ if (parsed === void 0) throw new Error("maid-curator: 未在主人原话中找到对当前提案的批准(限定短语:批准/同意/可以/执行/就这么办/做吧/按这个来);先呈报告再等主人点头");
512
+ const effective = deps.approvals.intersect(parsed, approved);
513
+ if (effective.size === 0) throw new Error("maid-curator: 工具 approved 与主人批准的交集为空——主人只批准了部分条目,请在 approved 中只填主人点头的 fact_id");
514
+ deps.proposalStore.clear(ns, sessionId);
515
+ const report = await service.apply(ns, [...effective]);
399
516
  return {
400
517
  mode: "apply",
401
518
  applied: report.applied,
@@ -405,6 +522,12 @@ function buildCuratorTool(service, deps) {
405
522
  }
406
523
  if (typed.mode === "dry-run") {
407
524
  const dry = await service.dryRun(ns);
525
+ deps.proposalStore?.register({
526
+ ns,
527
+ sessionId: exec.agent?.id ?? "",
528
+ turn: 0,
529
+ plan: dry
530
+ });
408
531
  return {
409
532
  mode: "dry-run",
410
533
  count: dry.facts.length,
@@ -429,40 +552,45 @@ function registerCuratorTool(ctx, service, deps) {
429
552
  for (const dispose of disposers.reverse()) dispose();
430
553
  };
431
554
  }
432
- function resolveSessionPreset(events, headerPreset) {
433
- let selected;
434
- let sawConversation = false;
435
- let midSessionSwitch = false;
436
- for (const entry of events ?? []) {
437
- const event = entry;
438
- if (event?.type === "turn/start" || event?.type === "turn/end" || event?.type === "user/message" || event?.type === "assistant/message") sawConversation = true;
439
- if (event?.type === "agent-preset/selected" && typeof event.data?.agentPreset === "string") {
440
- selected = event.data.agentPreset;
441
- if (sawConversation) midSessionSwitch = true;
442
- }
443
- }
444
- return {
445
- preset: selected ?? headerPreset,
446
- midSessionSwitch
447
- };
448
- }
449
555
  const apply = (ctx, config) => {
450
556
  const logger = ctx.logger?.("maid-curator") ?? console;
451
557
  const guide = typeof config?.guide === "object" && config.guide !== null ? config.guide : defaultCurationGuide;
452
558
  const fixedNs = typeof config?.namespace === "string" && config.namespace.trim() !== "" ? config.namespace : void 0;
453
- const memory = ctx.reflect.get("maidMemory", false);
454
- if (memory === void 0) logger.warn("maid-curator: maidMemory 未挂载——scan/dry-run 将返回空,apply 将被拒绝(maid-memory 须先于 maid-curator 装配)");
455
- const service = createMaidCuratorService(memory, guide);
559
+ let memoryWarned = false;
560
+ const memoryOf = () => {
561
+ const found = ctx.reflect.get("maidMemory", false);
562
+ if (found === void 0 && !memoryWarned) {
563
+ memoryWarned = true;
564
+ logger.warn("maid-curator: maidMemory 未挂载——scan/dry-run 将返回空,apply 将被拒绝(maid-memory 须先于 maid-curator 装配)");
565
+ }
566
+ return found;
567
+ };
568
+ const service = createMaidCuratorService(memoryOf, guide);
569
+ const approvals = createApprovals();
570
+ const proposalStore = createProposalStore();
456
571
  const disposeProvide = ctx.provide("maidCurator", service);
457
- const disposeTools = registerCuratorTool(ctx, service, { resolveNamespace: (exec) => {
458
- if (fixedNs !== void 0) return fixedNs;
459
- const session = exec?.agent?.session;
460
- const resolution = resolveSessionPreset(session?.snapshotEvents?.(), session?.header?.agentPreset);
461
- if (resolution.midSessionSwitch) throw new Error(`maid-curator: 会话存在 0.1.5 遗留中途切换(头部 ${JSON.stringify(session?.header?.agentPreset)}),策展操作被拒绝;请新建会话`);
462
- const ns = memory?.resolveNamespace?.(resolution.preset);
463
- if (ns === void 0) throw new Error(`maid-curator: 无法为该会话解析记忆命名空间(agentPreset=${JSON.stringify(resolution.preset)}),策展操作被拒绝`);
464
- return ns;
465
- } });
572
+ const identityOf = () => ctx.reflect.get("maidIdentity", false);
573
+ const disposeTools = registerCuratorTool(ctx, service, {
574
+ approvals,
575
+ proposalStore,
576
+ ...memoryOf()?.masterTextsOf !== void 0 ? { masterTextsOf: (sid) => memoryOf().masterTextsOf(sid) } : {},
577
+ resolveNamespace: (exec) => {
578
+ if (fixedNs !== void 0) return fixedNs;
579
+ const agent = exec?.agent;
580
+ const session = agent?.session;
581
+ if (typeof identityOf()?.resolveSession !== "function") throw new Error("maid-curator: maidIdentity 缺统一解析面(resolveSession),策展操作被拒绝;请在 maid.yml/固定 namespace 配置后再用");
582
+ const resolution = identityOf().resolveSession({
583
+ sessionId: agent?.id,
584
+ events: session?.snapshotEvents?.(),
585
+ headerPreset: session?.header?.agentPreset
586
+ });
587
+ if (resolution.midSessionSwitch && resolution.source !== "session" && resolution.source !== "route") throw new Error(`maid-curator: 会话存在 0.1.5 遗留中途切换(头部 ${JSON.stringify(session?.header?.agentPreset)} → ${JSON.stringify(resolution.presetId)}),策展操作被拒绝;请新建会话`);
588
+ if (resolution.maidId === void 0) throw new Error(`maid-curator: 当前会话未绑定女仆,且未配置固定 namespace(preset ${JSON.stringify(resolution.presetId)})`);
589
+ const ns = memoryOf()?.resolveNamespace?.(resolution);
590
+ if (ns === void 0) throw new Error(`maid-curator: 无法为该会话解析记忆命名空间(maid=${JSON.stringify(resolution.maidId)}),策展操作被拒绝`);
591
+ return ns;
592
+ }
593
+ });
466
594
  return () => {
467
595
  disposeTools();
468
596
  disposeProvide();
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "@deepmaid/maid-curator",
3
- "version": "0.1.0-alpha.1",
4
- "license": "MIT",
3
+ "version": "0.1.0-alpha.3",
5
4
  "type": "module",
5
+ "license": "MIT",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
6
9
  "main": "lib/index.js",
7
10
  "types": "lib/index.d.ts",
8
11
  "exports": {
@@ -27,16 +30,14 @@
27
30
  "description": "策展技能包:共享层三闸门的策展执行面(策展扫描/遗产分拣技能,namespace 可覆写)。关闭=策展技能从女仆工具面消失,共享知识层治理失工具。"
28
31
  }
29
32
  },
30
- "dependencies": {
31
- "@deepseek-ai/dsh-tools": "0.2.1-rc.2"
33
+ "peerDependencies": {
34
+ "@deepseek-ai/dsh-tools": "0.2.2-rc.1"
32
35
  },
33
36
  "devDependencies": {
34
- "@deepseek-ai/cordis": "4.0.5",
37
+ "@deepseek-ai/cordis": "4.1.0",
35
38
  "tsdown": "0.22.14",
36
- "typescript": "6.0.3"
37
- },
38
- "publishConfig": {
39
- "access": "public"
39
+ "typescript": "6.0.3",
40
+ "@deepseek-ai/dsh-tools": "0.2.1-rc.2"
40
41
  },
41
42
  "scripts": {
42
43
  "build": "tsdown"