/* Memory 记忆中心(拾忆)模块 一张 memory_item 表承载全部分类(闹钟/待办/灵感/花销),另有 memory_report 存周报月报。 由 home 服务装载(不是独立服务),HTTP 接口经反射注册为 memory_<方法名小写>, 客户端路径 /api/home/memory_xxx。 */ package memory import ( "yunyan/comm" "yunyan/modules" "yunyan/lego/base" "yunyan/lego/core" ) func NewModule() core.IModule { m := new(Memory) return m } type Memory struct { modules.ModuleBase service base.IRPCXService api *apiComp model *modelComp report *reportComp options *Options // echo 是同进程的 echomeet 模块:走它的后台编排选 LLM,而不是各自 import // sys/doubao 把服务商写死(allhelp/summary.go 就是写死的,海外应用照样调国内豆包)。 // 取不到时所有 LLM 相关能力降级:报告只出统计不出文案、会议抽取整条跳过。 echo comm.IEchomeet } func (this *Memory) GetType() core.M_Modules { return comm.ModuleMemory } func (this *Memory) NewOptions() (options core.IModuleOptions) { return new(Options) } func (this *Memory) Init(service core.IService, module core.IModule, options core.IModuleOptions) (err error) { this.service = service.(base.IRPCXService) this.options = options.(*Options) if err = this.ModuleBase.Init(service, module, options); err != nil { return } return } func (this *Memory) Start() (err error) { if err = this.ModuleBase.Start(); err != nil { return } if m, e := this.service.GetModule(comm.ModuleEchomeet); e == nil { if em, ok := m.(comm.IEchomeet); ok { this.echo = em } } if this.echo == nil { this.Warnf("未取到 echomeet 模块:周期报告将只有统计没有播报文案,会议待办抽取不可用") } // 存量 DBTask → memory_item 的一次性迁移。幂等,失败不阻断启动 // (它是补数据不是启动前置;这里返回 error 会让 home 退出、五个服务连坐全挂)。 go func() { if n, err := this.model.migrateTasks(); err != nil { this.Errorf("存量任务迁移失败(不影响服务): %v", err) } else if n > 0 { this.Infof("存量任务迁移完成,搬入 %d 条记忆项", n) } }() return } func (this *Memory) OnInstallComp() { this.ModuleBase.OnInstallComp() this.api = this.RegisterComp(new(apiComp)).(*apiComp) this.model = this.RegisterComp(new(modelComp)).(*modelComp) this.report = this.RegisterComp(new(reportComp)).(*reportComp) }