@zooique/memora 2.0.0 → 3.0.0
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/CHANGELOG.md +1028 -0
- package/README.en.md +305 -0
- package/README.md +303 -148
- package/config.example.json +43 -0
- package/dist/agent/agent.d.ts +438 -295
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/agent.js +1368 -836
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/assembler.d.ts +117 -39
- package/dist/agent/assembler.d.ts.map +1 -1
- package/dist/agent/assembler.js +574 -71
- package/dist/agent/assembler.js.map +1 -1
- package/dist/agent/budget.d.ts +131 -0
- package/dist/agent/budget.d.ts.map +1 -0
- package/dist/agent/budget.js +128 -0
- package/dist/agent/budget.js.map +1 -0
- package/dist/agent/builtinToolHandlers.d.ts +229 -17
- package/dist/agent/builtinToolHandlers.d.ts.map +1 -1
- package/dist/agent/builtinToolHandlers.js +758 -70
- package/dist/agent/builtinToolHandlers.js.map +1 -1
- package/dist/agent/builtinTools.d.ts +198 -7
- package/dist/agent/builtinTools.d.ts.map +1 -1
- package/dist/agent/builtinTools.js +646 -14
- package/dist/agent/builtinTools.js.map +1 -1
- package/dist/agent/compaction.d.ts +93 -0
- package/dist/agent/compaction.d.ts.map +1 -0
- package/dist/agent/compaction.js +192 -0
- package/dist/agent/compaction.js.map +1 -0
- package/dist/agent/constants.d.ts +139 -18
- package/dist/agent/constants.d.ts.map +1 -1
- package/dist/agent/constants.js +154 -18
- package/dist/agent/constants.js.map +1 -1
- package/dist/agent/contextManager.d.ts +126 -76
- package/dist/agent/contextManager.d.ts.map +1 -1
- package/dist/agent/contextManager.js +197 -135
- package/dist/agent/contextManager.js.map +1 -1
- package/dist/agent/contextPreparer.d.ts +78 -0
- package/dist/agent/contextPreparer.d.ts.map +1 -0
- package/dist/agent/contextPreparer.js +128 -0
- package/dist/agent/contextPreparer.js.map +1 -0
- package/dist/agent/duplicateInterceptor.d.ts +67 -0
- package/dist/agent/duplicateInterceptor.d.ts.map +1 -0
- package/dist/agent/duplicateInterceptor.js +82 -0
- package/dist/agent/duplicateInterceptor.js.map +1 -0
- package/dist/agent/guardRail.d.ts +166 -0
- package/dist/agent/guardRail.d.ts.map +1 -0
- package/dist/agent/guardRail.js +333 -0
- package/dist/agent/guardRail.js.map +1 -0
- package/dist/agent/loop.d.ts +718 -253
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +2215 -648
- package/dist/agent/loop.js.map +1 -1
- package/dist/agent/managers/archiveCoordinator.d.ts +21 -74
- package/dist/agent/managers/archiveCoordinator.d.ts.map +1 -1
- package/dist/agent/managers/archiveCoordinator.js +32 -105
- package/dist/agent/managers/archiveCoordinator.js.map +1 -1
- package/dist/agent/managers/chatLockManager.d.ts +20 -88
- package/dist/agent/managers/chatLockManager.d.ts.map +1 -1
- package/dist/agent/managers/chatLockManager.js +31 -103
- package/dist/agent/managers/chatLockManager.js.map +1 -1
- package/dist/agent/managers/dedupManager.d.ts +85 -0
- package/dist/agent/managers/dedupManager.d.ts.map +1 -0
- package/dist/agent/managers/dedupManager.js +248 -0
- package/dist/agent/managers/dedupManager.js.map +1 -0
- package/dist/agent/managers/goalConsistencyChecker.d.ts +42 -0
- package/dist/agent/managers/goalConsistencyChecker.d.ts.map +1 -0
- package/dist/agent/managers/goalConsistencyChecker.js +178 -0
- package/dist/agent/managers/goalConsistencyChecker.js.map +1 -0
- package/dist/agent/managers/llmCaller.d.ts +124 -0
- package/dist/agent/managers/llmCaller.d.ts.map +1 -0
- package/dist/agent/managers/llmCaller.js +417 -0
- package/dist/agent/managers/llmCaller.js.map +1 -0
- package/dist/agent/managers/llmJudgeHelper.d.ts +21 -0
- package/dist/agent/managers/llmJudgeHelper.d.ts.map +1 -0
- package/dist/agent/managers/llmJudgeHelper.js +32 -0
- package/dist/agent/managers/llmJudgeHelper.js.map +1 -0
- package/dist/agent/managers/loopMetrics.d.ts +58 -0
- package/dist/agent/managers/loopMetrics.d.ts.map +1 -0
- package/dist/agent/managers/loopMetrics.js +68 -0
- package/dist/agent/managers/loopMetrics.js.map +1 -0
- package/dist/agent/managers/memoryAdvisor.d.ts +27 -120
- package/dist/agent/managers/memoryAdvisor.d.ts.map +1 -1
- package/dist/agent/managers/memoryAdvisor.js +56 -192
- package/dist/agent/managers/memoryAdvisor.js.map +1 -1
- package/dist/agent/managers/memoryGovernance.d.ts +24 -0
- package/dist/agent/managers/memoryGovernance.d.ts.map +1 -0
- package/dist/agent/managers/memoryGovernance.js +46 -0
- package/dist/agent/managers/memoryGovernance.js.map +1 -0
- package/dist/agent/managers/memoryInspector.d.ts +59 -393
- package/dist/agent/managers/memoryInspector.d.ts.map +1 -1
- package/dist/agent/managers/memoryInspector.js +92 -736
- package/dist/agent/managers/memoryInspector.js.map +1 -1
- package/dist/agent/managers/roundSummaryGenerator.d.ts +56 -0
- package/dist/agent/managers/roundSummaryGenerator.d.ts.map +1 -0
- package/dist/agent/managers/roundSummaryGenerator.js +201 -0
- package/dist/agent/managers/roundSummaryGenerator.js.map +1 -0
- package/dist/agent/managers/sessionArchiver.d.ts +19 -63
- package/dist/agent/managers/sessionArchiver.d.ts.map +1 -1
- package/dist/agent/managers/sessionArchiver.js +83 -157
- package/dist/agent/managers/sessionArchiver.js.map +1 -1
- package/dist/agent/managers/sessionManager.d.ts +286 -57
- package/dist/agent/managers/sessionManager.d.ts.map +1 -1
- package/dist/agent/managers/sessionManager.js +846 -85
- package/dist/agent/managers/sessionManager.js.map +1 -1
- package/dist/agent/managers/sessionNamer.d.ts +35 -0
- package/dist/agent/managers/sessionNamer.d.ts.map +1 -0
- package/dist/agent/managers/sessionNamer.js +104 -0
- package/dist/agent/managers/sessionNamer.js.map +1 -0
- package/dist/agent/managers/streamAccumulator.d.ts +20 -0
- package/dist/agent/managers/streamAccumulator.d.ts.map +1 -0
- package/dist/agent/managers/streamAccumulator.js +15 -0
- package/dist/agent/managers/streamAccumulator.js.map +1 -0
- package/dist/agent/managers/textPolishManager.d.ts +8 -44
- package/dist/agent/managers/textPolishManager.d.ts.map +1 -1
- package/dist/agent/managers/textPolishManager.js +12 -47
- package/dist/agent/managers/textPolishManager.js.map +1 -1
- package/dist/agent/managers/toolCallHelpers.d.ts +105 -0
- package/dist/agent/managers/toolCallHelpers.d.ts.map +1 -0
- package/dist/agent/managers/toolCallHelpers.js +161 -0
- package/dist/agent/managers/toolCallHelpers.js.map +1 -0
- package/dist/agent/managers/workProjection.d.ts +57 -87
- package/dist/agent/managers/workProjection.d.ts.map +1 -1
- package/dist/agent/managers/workProjection.js +166 -246
- package/dist/agent/managers/workProjection.js.map +1 -1
- package/dist/agent/messageHistory.d.ts +134 -84
- package/dist/agent/messageHistory.d.ts.map +1 -1
- package/dist/agent/messageHistory.js +419 -133
- package/dist/agent/messageHistory.js.map +1 -1
- package/dist/agent/needsPlanning.d.ts +28 -0
- package/dist/agent/needsPlanning.d.ts.map +1 -0
- package/dist/agent/needsPlanning.js +68 -0
- package/dist/agent/needsPlanning.js.map +1 -0
- package/dist/agent/seed/index.d.ts +11 -0
- package/dist/agent/seed/index.d.ts.map +1 -0
- package/dist/agent/seed/index.js +10 -0
- package/dist/agent/seed/index.js.map +1 -0
- package/dist/agent/seed/orchestrator.d.ts +83 -0
- package/dist/agent/seed/orchestrator.d.ts.map +1 -0
- package/dist/agent/seed/orchestrator.js +260 -0
- package/dist/agent/seed/orchestrator.js.map +1 -0
- package/dist/agent/seed/prepare.d.ts +49 -0
- package/dist/agent/seed/prepare.d.ts.map +1 -0
- package/dist/agent/seed/prepare.js +107 -0
- package/dist/agent/seed/prepare.js.map +1 -0
- package/dist/agent/seed/types.d.ts +115 -0
- package/dist/agent/seed/types.d.ts.map +1 -0
- package/dist/agent/seed/types.js +15 -0
- package/dist/agent/seed/types.js.map +1 -0
- package/dist/agent/sessionStateMachine.d.ts +78 -0
- package/dist/agent/sessionStateMachine.d.ts.map +1 -0
- package/dist/agent/sessionStateMachine.js +182 -0
- package/dist/agent/sessionStateMachine.js.map +1 -0
- package/dist/agent/taskTableRenderer.d.ts +51 -0
- package/dist/agent/taskTableRenderer.d.ts.map +1 -0
- package/dist/agent/taskTableRenderer.js +115 -0
- package/dist/agent/taskTableRenderer.js.map +1 -0
- package/dist/agent/toolExecutor.d.ts +255 -9
- package/dist/agent/toolExecutor.d.ts.map +1 -1
- package/dist/agent/toolExecutor.js +956 -20
- package/dist/agent/toolExecutor.js.map +1 -1
- package/dist/agent/toolLedger.d.ts +120 -0
- package/dist/agent/toolLedger.d.ts.map +1 -0
- package/dist/agent/toolLedger.js +149 -0
- package/dist/agent/toolLedger.js.map +1 -0
- package/dist/agent/toolResultCache.d.ts +134 -0
- package/dist/agent/toolResultCache.d.ts.map +1 -0
- package/dist/agent/toolResultCache.js +243 -0
- package/dist/agent/toolResultCache.js.map +1 -0
- package/dist/agent/toolResultOffload.d.ts +59 -0
- package/dist/agent/toolResultOffload.d.ts.map +1 -0
- package/dist/agent/toolResultOffload.js +70 -0
- package/dist/agent/toolResultOffload.js.map +1 -0
- package/dist/agent/toolRunner.d.ts +59 -0
- package/dist/agent/toolRunner.d.ts.map +1 -0
- package/dist/agent/toolRunner.js +147 -0
- package/dist/agent/toolRunner.js.map +1 -0
- package/dist/agent/tracer.d.ts +99 -107
- package/dist/agent/tracer.d.ts.map +1 -1
- package/dist/agent/tracer.js +24 -69
- package/dist/agent/tracer.js.map +1 -1
- package/dist/agent/types.d.ts +512 -162
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js +2 -51
- package/dist/agent/types.js.map +1 -1
- package/dist/code-exec/codeExecutionProvider.d.ts +16 -0
- package/dist/code-exec/codeExecutionProvider.d.ts.map +1 -0
- package/dist/code-exec/codeExecutionProvider.js +57 -0
- package/dist/code-exec/codeExecutionProvider.js.map +1 -0
- package/dist/code-exec/types.d.ts +37 -0
- package/dist/code-exec/types.d.ts.map +1 -0
- package/dist/code-exec/types.js +12 -0
- package/dist/code-exec/types.js.map +1 -0
- package/dist/config/expandEnvVars.d.ts +22 -0
- package/dist/config/expandEnvVars.d.ts.map +1 -0
- package/dist/config/expandEnvVars.js +38 -0
- package/dist/config/expandEnvVars.js.map +1 -0
- package/dist/config/loader.d.ts +59 -242
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +237 -194
- package/dist/config/loader.js.map +1 -1
- package/dist/index.d.ts +69 -74
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +93 -63
- package/dist/index.js.map +1 -1
- package/dist/llm/abortSignal.d.ts +2 -3
- package/dist/llm/abortSignal.d.ts.map +1 -1
- package/dist/llm/abortSignal.js +2 -3
- package/dist/llm/abortSignal.js.map +1 -1
- package/dist/llm/factory.d.ts +29 -25
- package/dist/llm/factory.d.ts.map +1 -1
- package/dist/llm/factory.js +34 -69
- package/dist/llm/factory.js.map +1 -1
- package/dist/llm/openaiCompatible.d.ts +25 -40
- package/dist/llm/openaiCompatible.d.ts.map +1 -1
- package/dist/llm/openaiCompatible.js +181 -129
- package/dist/llm/openaiCompatible.js.map +1 -1
- package/dist/llm/provider.d.ts +29 -42
- package/dist/llm/provider.d.ts.map +1 -1
- package/dist/llm/provider.js +11 -10
- package/dist/llm/provider.js.map +1 -1
- package/dist/llm/types.d.ts +54 -11
- package/dist/llm/types.d.ts.map +1 -1
- package/dist/llm/types.js +0 -5
- package/dist/llm/types.js.map +1 -1
- package/dist/logging/logger.d.ts +8 -29
- package/dist/logging/logger.d.ts.map +1 -1
- package/dist/logging/logger.js +43 -233
- package/dist/logging/logger.js.map +1 -1
- package/dist/logging/loggerInterface.d.ts +9 -8
- package/dist/logging/loggerInterface.d.ts.map +1 -1
- package/dist/memory/gcService.d.ts +164 -0
- package/dist/memory/gcService.d.ts.map +1 -0
- package/dist/memory/gcService.js +215 -0
- package/dist/memory/gcService.js.map +1 -0
- package/dist/memory/governance.d.ts +17 -0
- package/dist/memory/governance.d.ts.map +1 -0
- package/dist/memory/governance.js +17 -0
- package/dist/memory/governance.js.map +1 -0
- package/dist/memory/inMemoryRoundStore.d.ts +124 -0
- package/dist/memory/inMemoryRoundStore.d.ts.map +1 -0
- package/dist/memory/inMemoryRoundStore.js +216 -0
- package/dist/memory/inMemoryRoundStore.js.map +1 -0
- package/dist/memory/inMemorySessionStore.d.ts +92 -0
- package/dist/memory/inMemorySessionStore.d.ts.map +1 -0
- package/dist/memory/inMemorySessionStore.js +219 -0
- package/dist/memory/inMemorySessionStore.js.map +1 -0
- package/dist/memory/inMemorySessionViewLoader.d.ts +89 -0
- package/dist/memory/inMemorySessionViewLoader.d.ts.map +1 -0
- package/dist/memory/inMemorySessionViewLoader.js +183 -0
- package/dist/memory/inMemorySessionViewLoader.js.map +1 -0
- package/dist/memory/inMemoryStorage.d.ts +26 -141
- package/dist/memory/inMemoryStorage.d.ts.map +1 -1
- package/dist/memory/inMemoryStorage.js +48 -187
- package/dist/memory/inMemoryStorage.js.map +1 -1
- package/dist/memory/keywordsTouch.d.ts +20 -0
- package/dist/memory/keywordsTouch.d.ts.map +1 -0
- package/dist/memory/keywordsTouch.js +25 -0
- package/dist/memory/keywordsTouch.js.map +1 -0
- package/dist/memory/lockManager.d.ts +7 -2
- package/dist/memory/lockManager.d.ts.map +1 -1
- package/dist/memory/lockManager.js +35 -11
- package/dist/memory/lockManager.js.map +1 -1
- package/dist/memory/projectManager.d.ts +30 -128
- package/dist/memory/projectManager.d.ts.map +1 -1
- package/dist/memory/projectManager.js +39 -171
- package/dist/memory/projectManager.js.map +1 -1
- package/dist/memory/projectRegistry.d.ts +22 -37
- package/dist/memory/projectRegistry.d.ts.map +1 -1
- package/dist/memory/projectRegistry.js +78 -85
- package/dist/memory/projectRegistry.js.map +1 -1
- package/dist/memory/roundStore.d.ts +629 -0
- package/dist/memory/roundStore.d.ts.map +1 -0
- package/dist/memory/roundStore.js +116 -0
- package/dist/memory/roundStore.js.map +1 -0
- package/dist/memory/sessionStore.d.ts +70 -61
- package/dist/memory/sessionStore.d.ts.map +1 -1
- package/dist/memory/sessionStore.js +23 -1
- package/dist/memory/sessionStore.js.map +1 -1
- package/dist/memory/sessionViewLoader.d.ts +141 -0
- package/dist/memory/sessionViewLoader.d.ts.map +1 -0
- package/dist/memory/sessionViewLoader.js +65 -0
- package/dist/memory/sessionViewLoader.js.map +1 -0
- package/dist/memory/sourceValidation.d.ts +18 -9
- package/dist/memory/sourceValidation.d.ts.map +1 -1
- package/dist/memory/sourceValidation.js +35 -29
- package/dist/memory/sourceValidation.js.map +1 -1
- package/dist/memory/storageInterface.d.ts +45 -126
- package/dist/memory/storageInterface.d.ts.map +1 -1
- package/dist/memory/types.d.ts +82 -168
- package/dist/memory/types.d.ts.map +1 -1
- package/dist/memory/types.js +116 -79
- package/dist/memory/types.js.map +1 -1
- package/dist/project-search/projectSearchProvider.d.ts +29 -0
- package/dist/project-search/projectSearchProvider.d.ts.map +1 -0
- package/dist/project-search/projectSearchProvider.js +57 -0
- package/dist/project-search/projectSearchProvider.js.map +1 -0
- package/dist/project-search/terms.d.ts +14 -0
- package/dist/project-search/terms.d.ts.map +1 -0
- package/dist/project-search/terms.js +68 -0
- package/dist/project-search/terms.js.map +1 -0
- package/dist/project-search/types.d.ts +139 -0
- package/dist/project-search/types.d.ts.map +1 -0
- package/dist/project-search/types.js +8 -0
- package/dist/project-search/types.js.map +1 -0
- package/dist/role-pack/capabilityMap.d.ts +28 -0
- package/dist/role-pack/capabilityMap.d.ts.map +1 -0
- package/dist/role-pack/capabilityMap.js +56 -0
- package/dist/role-pack/capabilityMap.js.map +1 -0
- package/dist/role-pack/constants.d.ts +21 -0
- package/dist/role-pack/constants.d.ts.map +1 -0
- package/dist/role-pack/constants.js +21 -0
- package/dist/role-pack/constants.js.map +1 -0
- package/dist/role-pack/rolePackManager.d.ts +269 -0
- package/dist/role-pack/rolePackManager.d.ts.map +1 -0
- package/dist/role-pack/rolePackManager.js +1082 -0
- package/dist/role-pack/rolePackManager.js.map +1 -0
- package/dist/role-pack/strategyKeys.d.ts +100 -0
- package/dist/role-pack/strategyKeys.d.ts.map +1 -0
- package/dist/role-pack/strategyKeys.js +184 -0
- package/dist/role-pack/strategyKeys.js.map +1 -0
- package/dist/role-pack/strategyResolver.d.ts +109 -0
- package/dist/role-pack/strategyResolver.d.ts.map +1 -0
- package/dist/role-pack/strategyResolver.js +304 -0
- package/dist/role-pack/strategyResolver.js.map +1 -0
- package/dist/role-pack/types.d.ts +237 -0
- package/dist/role-pack/types.d.ts.map +1 -0
- package/dist/role-pack/types.js +8 -0
- package/dist/role-pack/types.js.map +1 -0
- package/dist/role-pack/validator.d.ts +38 -0
- package/dist/role-pack/validator.d.ts.map +1 -0
- package/dist/role-pack/validator.js +436 -0
- package/dist/role-pack/validator.js.map +1 -0
- package/dist/security/pathGuard.d.ts +69 -72
- package/dist/security/pathGuard.d.ts.map +1 -1
- package/dist/security/pathGuard.js +151 -131
- package/dist/security/pathGuard.js.map +1 -1
- package/dist/skill/skillLayer3.d.ts +91 -0
- package/dist/skill/skillLayer3.d.ts.map +1 -0
- package/dist/skill/skillLayer3.js +104 -0
- package/dist/skill/skillLayer3.js.map +1 -0
- package/dist/skill/skillManager.d.ts +127 -56
- package/dist/skill/skillManager.d.ts.map +1 -1
- package/dist/skill/skillManager.js +318 -163
- package/dist/skill/skillManager.js.map +1 -1
- package/dist/skill/skillScriptRunner.d.ts +97 -0
- package/dist/skill/skillScriptRunner.d.ts.map +1 -0
- package/dist/skill/skillScriptRunner.js +271 -0
- package/dist/skill/skillScriptRunner.js.map +1 -0
- package/dist/skill/types.d.ts +73 -17
- package/dist/skill/types.d.ts.map +1 -1
- package/dist/skill/types.js +5 -1
- package/dist/skill/types.js.map +1 -1
- package/dist/utils/array.d.ts +5 -6
- package/dist/utils/array.d.ts.map +1 -1
- package/dist/utils/array.js +6 -6
- package/dist/utils/array.js.map +1 -1
- package/dist/utils/atomicWrite.d.ts +8 -0
- package/dist/utils/atomicWrite.d.ts.map +1 -0
- package/dist/utils/atomicWrite.js +31 -0
- package/dist/utils/atomicWrite.js.map +1 -0
- package/dist/utils/backgroundTask.d.ts +38 -0
- package/dist/utils/backgroundTask.d.ts.map +1 -0
- package/dist/utils/backgroundTask.js +117 -0
- package/dist/utils/backgroundTask.js.map +1 -0
- package/dist/utils/configResourceManager.d.ts +79 -0
- package/dist/utils/configResourceManager.d.ts.map +1 -0
- package/dist/utils/configResourceManager.js +150 -0
- package/dist/utils/configResourceManager.js.map +1 -0
- package/dist/utils/errors.d.ts +48 -56
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +60 -58
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/eventEmitter.d.ts +141 -63
- package/dist/utils/eventEmitter.d.ts.map +1 -1
- package/dist/utils/eventEmitter.js +50 -35
- package/dist/utils/eventEmitter.js.map +1 -1
- package/dist/utils/fileSafe.d.ts +20 -0
- package/dist/utils/fileSafe.d.ts.map +1 -0
- package/dist/utils/fileSafe.js +56 -0
- package/dist/utils/fileSafe.js.map +1 -0
- package/dist/utils/frontmatter.d.ts +2 -3
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js +6 -5
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/hash.d.ts +12 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +27 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/http.d.ts +17 -0
- package/dist/utils/http.d.ts.map +1 -0
- package/dist/utils/http.js +29 -0
- package/dist/utils/http.js.map +1 -0
- package/dist/utils/json.d.ts +1 -1
- package/dist/utils/json.js +1 -1
- package/dist/utils/math.d.ts +34 -1
- package/dist/utils/math.d.ts.map +1 -1
- package/dist/utils/math.js +47 -14
- package/dist/utils/math.js.map +1 -1
- package/dist/utils/objects.d.ts +2 -3
- package/dist/utils/objects.d.ts.map +1 -1
- package/dist/utils/objects.js +2 -3
- package/dist/utils/objects.js.map +1 -1
- package/dist/utils/recallDefaults.d.ts +16 -0
- package/dist/utils/recallDefaults.d.ts.map +1 -0
- package/dist/utils/recallDefaults.js +16 -0
- package/dist/utils/recallDefaults.js.map +1 -0
- package/dist/utils/safeTimer.d.ts +8 -36
- package/dist/utils/safeTimer.d.ts.map +1 -1
- package/dist/utils/safeTimer.js +9 -37
- package/dist/utils/safeTimer.js.map +1 -1
- package/dist/utils/scanner.d.ts +97 -17
- package/dist/utils/scanner.d.ts.map +1 -1
- package/dist/utils/scanner.js +269 -47
- package/dist/utils/scanner.js.map +1 -1
- package/dist/utils/segmenter.d.ts +20 -29
- package/dist/utils/segmenter.d.ts.map +1 -1
- package/dist/utils/segmenter.js +230 -88
- package/dist/utils/segmenter.js.map +1 -1
- package/dist/utils/strings.d.ts +15 -32
- package/dist/utils/strings.d.ts.map +1 -1
- package/dist/utils/strings.js +25 -44
- package/dist/utils/strings.js.map +1 -1
- package/dist/utils/time.d.ts +37 -0
- package/dist/utils/time.d.ts.map +1 -1
- package/dist/utils/time.js +56 -0
- package/dist/utils/time.js.map +1 -1
- package/dist/utils/toError.d.ts +13 -1
- package/dist/utils/toError.d.ts.map +1 -1
- package/dist/utils/toError.js +18 -1
- package/dist/utils/toError.js.map +1 -1
- package/dist/web-fetch/fetchWebFetchProvider.d.ts +14 -0
- package/dist/web-fetch/fetchWebFetchProvider.d.ts.map +1 -0
- package/dist/web-fetch/fetchWebFetchProvider.js +69 -0
- package/dist/web-fetch/fetchWebFetchProvider.js.map +1 -0
- package/dist/web-fetch/types.d.ts +30 -0
- package/dist/web-fetch/types.d.ts.map +1 -0
- package/dist/web-fetch/types.js +7 -0
- package/dist/web-fetch/types.js.map +1 -0
- package/dist/web-fetch/webFetchProvider.d.ts +10 -0
- package/dist/web-fetch/webFetchProvider.d.ts.map +1 -0
- package/dist/web-fetch/webFetchProvider.js +28 -0
- package/dist/web-fetch/webFetchProvider.js.map +1 -0
- package/dist/web-search/fetchWebSearchProvider.d.ts +27 -0
- package/dist/web-search/fetchWebSearchProvider.d.ts.map +1 -0
- package/dist/web-search/fetchWebSearchProvider.js +199 -0
- package/dist/web-search/fetchWebSearchProvider.js.map +1 -0
- package/dist/web-search/types.d.ts +46 -0
- package/dist/web-search/types.d.ts.map +1 -0
- package/dist/web-search/types.js +2 -0
- package/dist/{persona → web-search}/types.js.map +1 -1
- package/dist/web-search/webSearchProvider.d.ts +10 -0
- package/dist/web-search/webSearchProvider.d.ts.map +1 -0
- package/dist/web-search/webSearchProvider.js +30 -0
- package/dist/web-search/webSearchProvider.js.map +1 -0
- package/docs/architecture/role-pack-authoring-guide.md +243 -0
- package/docs/architecture/role-pack-spec.md +767 -0
- package/docs/memora-api-reference.md +1175 -0
- package/docs/memora-/346/216/245/345/205/245/346/214/207/345/215/227.md +843 -0
- package/docs/role-pack-/345/274/200/346/224/276/351/224/256/346/214/207/345/215/227.md +148 -0
- package/package.json +105 -83
- package/role-packs/README.md +41 -0
- package/role-packs/memora/345/212/251/346/211/213/manifest.json +12 -0
- package/role-packs/memora/345/212/251/346/211/213/persona.md +12 -0
- package/role-packs/memora/345/212/251/346/211/213/rules.md +4 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/manifest.json +44 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/persona.md +46 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/rules.md +15 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/character-sheet.md +34 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/core-extractor.md +37 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/craft-review.md +69 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/dialogue-craft.md +45 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/emotion-wave.md +46 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/empathy-craft.md +79 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/foreshadow.md +29 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/hotspot-mapping.md +121 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/idea-lever.md +42 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/logline-craft.md +47 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/longform-guard.md +64 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/need-finder.md +40 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/outline-expand.md +46 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/pacing-hook.md +34 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/polish-method.md +113 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/pov-discipline.md +79 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/project-init/SKILL.md +112 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/project-init/scripts/init-novel-project.mjs +441 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/relationship-web.md +47 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/scene-craft.md +46 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/story-bible.md +60 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/story-structure.md +36 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/style-weaver.md +109 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/three-layer-check.md +27 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/world-builder.md +41 -0
- package/role-packs//347/231/275/350/257/235/346/226/271/346/241/210/350/256/276/350/256/241/345/270/210/manifest.json +48 -0
- package/role-packs//347/231/275/350/257/235/346/226/271/346/241/210/350/256/276/350/256/241/345/270/210/persona.md +73 -0
- package/role-packs//347/231/275/350/257/235/346/226/271/346/241/210/350/256/276/350/256/241/345/270/210/rules.md +19 -0
- package/role-packs//347/231/275/350/257/235/346/226/271/346/241/210/350/256/276/350/256/241/345/270/210/skills/api-doc-writer.md +40 -0
- package/role-packs//347/231/275/350/257/235/346/226/271/346/241/210/350/256/276/350/256/241/345/270/210/skills/doc-planner.md +42 -0
- package/role-packs//347/231/275/350/257/235/346/226/271/346/241/210/350/256/276/350/256/241/345/270/210/skills/nutrient-search.md +28 -0
- package/role-packs//347/231/275/350/257/235/346/226/271/346/241/210/350/256/276/350/256/241/345/270/210/skills/seed-finder.md +28 -0
- package/role-packs//347/231/275/350/257/235/346/226/271/346/241/210/350/256/276/350/256/241/345/270/210/skills/ssot-audit.md +34 -0
- package/role-packs//347/231/275/350/257/235/346/226/271/346/241/210/350/256/276/350/256/241/345/270/210/skills/style-guide.md +40 -0
- package/dist/agent/guardrail.d.ts +0 -47
- package/dist/agent/guardrail.d.ts.map +0 -1
- package/dist/agent/guardrail.js +0 -51
- package/dist/agent/guardrail.js.map +0 -1
- package/dist/agent/managers/autoConfigRefiner.d.ts +0 -39
- package/dist/agent/managers/autoConfigRefiner.d.ts.map +0 -1
- package/dist/agent/managers/autoConfigRefiner.js +0 -150
- package/dist/agent/managers/autoConfigRefiner.js.map +0 -1
- package/dist/agent/managers/configManager.d.ts +0 -125
- package/dist/agent/managers/configManager.d.ts.map +0 -1
- package/dist/agent/managers/configManager.js +0 -194
- package/dist/agent/managers/configManager.js.map +0 -1
- package/dist/agent/managers/insightExtractor.d.ts +0 -139
- package/dist/agent/managers/insightExtractor.d.ts.map +0 -1
- package/dist/agent/managers/insightExtractor.js +0 -401
- package/dist/agent/managers/insightExtractor.js.map +0 -1
- package/dist/agent/managers/memoryDecayScheduler.d.ts +0 -198
- package/dist/agent/managers/memoryDecayScheduler.d.ts.map +0 -1
- package/dist/agent/managers/memoryDecayScheduler.js +0 -349
- package/dist/agent/managers/memoryDecayScheduler.js.map +0 -1
- package/dist/agent/managers/relationBuilder.d.ts +0 -131
- package/dist/agent/managers/relationBuilder.d.ts.map +0 -1
- package/dist/agent/managers/relationBuilder.js +0 -192
- package/dist/agent/managers/relationBuilder.js.map +0 -1
- package/dist/agent/personaMatcher.d.ts +0 -29
- package/dist/agent/personaMatcher.d.ts.map +0 -1
- package/dist/agent/personaMatcher.js +0 -60
- package/dist/agent/personaMatcher.js.map +0 -1
- package/dist/agent/userFactExtractor.d.ts +0 -25
- package/dist/agent/userFactExtractor.d.ts.map +0 -1
- package/dist/agent/userFactExtractor.js +0 -81
- package/dist/agent/userFactExtractor.js.map +0 -1
- package/dist/eval/evalRunner.d.ts +0 -94
- package/dist/eval/evalRunner.d.ts.map +0 -1
- package/dist/eval/evalRunner.js +0 -141
- package/dist/eval/evalRunner.js.map +0 -1
- package/dist/eval/evalTypes.d.ts +0 -148
- package/dist/eval/evalTypes.d.ts.map +0 -1
- package/dist/eval/evalTypes.js +0 -118
- package/dist/eval/evalTypes.js.map +0 -1
- package/dist/eval/scenarios.d.ts +0 -33
- package/dist/eval/scenarios.d.ts.map +0 -1
- package/dist/eval/scenarios.js +0 -109
- package/dist/eval/scenarios.js.map +0 -1
- package/dist/llm/embedding.d.ts +0 -67
- package/dist/llm/embedding.d.ts.map +0 -1
- package/dist/llm/embedding.js +0 -184
- package/dist/llm/embedding.js.map +0 -1
- package/dist/memory/hybridMerge.d.ts +0 -54
- package/dist/memory/hybridMerge.d.ts.map +0 -1
- package/dist/memory/hybridMerge.js +0 -36
- package/dist/memory/hybridMerge.js.map +0 -1
- package/dist/memory/inMemoryRelationStore.d.ts +0 -51
- package/dist/memory/inMemoryRelationStore.d.ts.map +0 -1
- package/dist/memory/inMemoryRelationStore.js +0 -65
- package/dist/memory/inMemoryRelationStore.js.map +0 -1
- package/dist/memory/loader.d.ts +0 -49
- package/dist/memory/loader.d.ts.map +0 -1
- package/dist/memory/loader.js +0 -93
- package/dist/memory/loader.js.map +0 -1
- package/dist/memory/recall.d.ts +0 -66
- package/dist/memory/recall.d.ts.map +0 -1
- package/dist/memory/recall.js +0 -142
- package/dist/memory/recall.js.map +0 -1
- package/dist/memory/relationStore.d.ts +0 -78
- package/dist/memory/relationStore.d.ts.map +0 -1
- package/dist/memory/relationStore.js +0 -2
- package/dist/memory/relationStore.js.map +0 -1
- package/dist/memory/store.d.ts +0 -50
- package/dist/memory/store.d.ts.map +0 -1
- package/dist/memory/store.js +0 -161
- package/dist/memory/store.js.map +0 -1
- package/dist/memory/userProfile.d.ts +0 -156
- package/dist/memory/userProfile.d.ts.map +0 -1
- package/dist/memory/userProfile.js +0 -320
- package/dist/memory/userProfile.js.map +0 -1
- package/dist/memory/vectorStore.d.ts +0 -185
- package/dist/memory/vectorStore.d.ts.map +0 -1
- package/dist/memory/vectorStore.js +0 -257
- package/dist/memory/vectorStore.js.map +0 -1
- package/dist/persona/personaManager.d.ts +0 -160
- package/dist/persona/personaManager.d.ts.map +0 -1
- package/dist/persona/personaManager.js +0 -414
- package/dist/persona/personaManager.js.map +0 -1
- package/dist/persona/types.d.ts +0 -32
- package/dist/persona/types.d.ts.map +0 -1
- package/dist/persona/types.js +0 -5
|
@@ -0,0 +1,843 @@
|
|
|
1
|
+
# Memora · 接入指南 v3.0.0
|
|
2
|
+
|
|
3
|
+
> 帮助宿主项目开发者快速理解 Memora 的设计理念和接入方法。
|
|
4
|
+
>
|
|
5
|
+
> **当前稳定版**:v3.0.0。各版完整变更见 [CHANGELOG](../CHANGELOG.md)。
|
|
6
|
+
>
|
|
7
|
+
> **对接入者有影响的迁移结论**(不含历史流水,细节见 [API 参考手册](./memora-api-reference.md)):
|
|
8
|
+
> - 1.0 为正式发布,API 已稳定;2.0 起设定记忆(persona/rules/skills)解耦为纯文件 + 内存缓存,唯一归角色包、不进记忆库(ADR-025),角色管理统一走 `agent.rolePack`。
|
|
9
|
+
> - 已移除:`SqliteStorage`(移出内核,由宿主实现 `IMemoryStorage`)、洞察层(`insight.*`)、AutoConfigRefiner / ConfigManager、记忆关系图谱与用户画像层(偏好收敛为 round-summary,冲突改用 `supersededBy` 布尔标记)。
|
|
10
|
+
>
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 目录
|
|
14
|
+
|
|
15
|
+
- [一、核心理念](#一核心理念)
|
|
16
|
+
- [二、三重数据存续路径](#二三重数据存续路径)
|
|
17
|
+
- [三、最小接入步骤](#三最小接入步骤)
|
|
18
|
+
- [四、会话持久化](#四会话持久化)
|
|
19
|
+
- [五、API 速查](#五api-速查)
|
|
20
|
+
- [六、宿主工具函数](#六宿主工具函数)
|
|
21
|
+
- [七、可观测性接入(ITracer)](#七可观测性接入itracer)
|
|
22
|
+
- [八、工具错误反思(Reflection)](#八工具错误反思reflection)
|
|
23
|
+
- [九、多步骤编排](#九多步骤编排)
|
|
24
|
+
- [十、关键约束](#十关键约束)
|
|
25
|
+
- [十一、用户档案实现指南(宿主扩展)](#十一用户档案实现指南宿主扩展)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 一、核心理念
|
|
30
|
+
|
|
31
|
+
**Memora 是一个无法独立运行的智能大脑内核。** 它只有接口,没有"形态"——宿主负责给它身体(UI)、血管(Provider)、神经网络(事件回路)。
|
|
32
|
+
|
|
33
|
+
**摘要即记忆(memory-as-summary)。** Memora 的记忆只有单一轨道——**对话记忆**(round-summary 摘要,宿主持久化 + **纯关键词召回**,带 `summaryType` 语义标签);**设定**(角色包 persona/rules/skills)是 Agent 的骨骼,.md 文件 + 内存缓存,唯一归角色包、确定性注入不经过召回,不属记忆库(ADR-025)。二者边界一刀切:记忆系统只承载对话摘要、角色包承载设定;偏好类信息沉淀为摘要记忆,不设独立"用户画像"记忆层。
|
|
34
|
+
|
|
35
|
+
**单 Agent 模型。** 一个 Agent 实例的对话与记忆由**同一组存储实例**承载(`storage` / `sessionStore` 均在构造时注入、实例级),**`switchProject()` 切换项目时复用同一实例,不重建、不丢记忆**。要按工作区彼此隔离,就各自 `new Agent`——隔离粒度由宿主决定,内核不规定。
|
|
36
|
+
|
|
37
|
+
**配置文件是真理源,对话记忆由宿主持久化。** 角色包(persona/rules/skills)为纯文件 + 内存缓存,设定记忆唯一归角色包、不进记忆库(ADR-025);对话记忆(round-summary 摘要记忆,带 `summaryType` 标签)经宿主注入的 `IMemoryStorage` 持久化——**后端由宿主自选**(SQLite / JSON 文件 / 内存皆可),检索为 **纯关键词召回**(向量语义通道已随 2026-09-18 B0 收编移除,见 [API 参考手册](./memora-api-reference.md) §〇.5 构造参数表)。
|
|
38
|
+
|
|
39
|
+
**内核零越界。** 核心库模块不直接调用 `console.*`(唯一日志出口为 `logging/` 单例,默认实现写 stderr)、不读 `process.stdin`、不管理 API Key、不写用户配置文件。
|
|
40
|
+
|
|
41
|
+
**Manager 委托模式。** Agent 面类只做编排,领域操作委托给专职 Manager:`agent.rolePack`(角色包)/ `agent.tools`(工具)/ `agent.skills`(技能)/ `agent.memory`(记忆查询+写入)/ `agent.governance`(记忆治理)/ `agent.works`(作品投影)/ `agent.polish`(文本润色)共 7 个业务 Manager(另有 `projects` / `security` / `sessionManager` 等)。
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
┌────────────────────────────────────────────────────────────┐
|
|
45
|
+
│ 宿主程序 │
|
|
46
|
+
│ ┌─────────────────┐ ┌──────────────────┐ │
|
|
47
|
+
│ │ LLM Provider 实例 │◄───│ API Key / baseUrl │ ← 宿主职责 │
|
|
48
|
+
│ └────────┬────────┘ └──────────────────┘ │
|
|
49
|
+
│ │ 注入 │
|
|
50
|
+
│ ▼ │
|
|
51
|
+
│ ┌──────────────────────────────────────────┐ │
|
|
52
|
+
│ │ Memora 内核(Agent) │ │
|
|
53
|
+
│ │ - chat(input) → 流式响应 │ │
|
|
54
|
+
│ │ - 7 个业务 Manager getter(rolePack/tools/skills/memory/governance/works/polish,委托模式) │ │
|
|
55
|
+
│ │ ⚠️ 不包含:UI / LLM 配置 / 用户配置模板 │ │
|
|
56
|
+
│ └──────────────────────────────────────────┘ │
|
|
57
|
+
└────────────────────────────────────────────────────────────┘
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 二、三重数据存续路径
|
|
63
|
+
|
|
64
|
+
| 路径 | 用途 | 示例 |
|
|
65
|
+
|------|------|------|
|
|
66
|
+
| `AgentOptions.configDir` | 配置根目录(role-packs / skills) | 嵌入宿主程序 |
|
|
67
|
+
| `AgentOptions.dataDir` | 记忆数据目录(**必填**;记忆库形态由宿主的 `storage` 实现决定) | 宿主自定 |
|
|
68
|
+
| `projectPath/.memora/` | 项目级配置(rules/skills)+ 项目锁文件 `.lock` | 跟作品走 |
|
|
69
|
+
|
|
70
|
+
**小说生成器推荐布局:**
|
|
71
|
+
```
|
|
72
|
+
小说项目/
|
|
73
|
+
├── .memora/ ← 项目级配置(rules + skills)+ 内核写入的 .lock
|
|
74
|
+
└── .memora-data/ ← dataDir 指向此处(记住:内核只往这里写 projects.json 注册表)
|
|
75
|
+
├── projects.json ← 内核写入:项目注册表
|
|
76
|
+
└── <记忆库> ← 由宿主的 storage 决定形态与文件名
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 三、最小接入步骤
|
|
82
|
+
|
|
83
|
+
### 1. 安装
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm install @zooique/memora
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 2. 创建 Provider + Agent
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { Agent, createProviderFromConfig, setLogger } from '@zooique/memora';
|
|
93
|
+
import type { IMemoryStorage, ILogger } from '@zooique/memora';
|
|
94
|
+
|
|
95
|
+
// 宿主职责:创建 LLM Provider(Agent 不关心 API Key)
|
|
96
|
+
// createProviderFromConfig 是"单个 provider"入口;多 provider + active 随 loadConfig 路由见 api-reference §十 Provider 管理
|
|
97
|
+
const provider = createProviderFromConfig('primary', {
|
|
98
|
+
provider: 'openaiCompatible',
|
|
99
|
+
apiKey: process.env.LLM_API_KEY!,
|
|
100
|
+
baseUrl: 'https://api.xiaomimimo.com/v1',
|
|
101
|
+
model: 'deepseek-chat',
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// 可选:后台 Provider(投影等后台操作)
|
|
105
|
+
const backgroundProvider = createProviderFromConfig('background', {
|
|
106
|
+
provider: 'openaiCompatible',
|
|
107
|
+
apiKey: process.env.LLM_API_KEY!,
|
|
108
|
+
baseUrl: 'https://api.xiaomimimo.com/v1',
|
|
109
|
+
model: 'deepseek-chat', // 可用更便宜的模型
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// 可选:注入存储层(不传则使用 InMemoryStorage)。后端由宿主自选,二选一即可:
|
|
113
|
+
const storage: IMemoryStorage = new MySqliteStorage('/path/to/memora.db'); // SQLite(同步实现天然对齐)
|
|
114
|
+
// const storage: IMemoryStorage = new MyJsonStorage('/path/to/memories.json'); // JSON 文件(第一宿主 memora-vscode 的选法)
|
|
115
|
+
|
|
116
|
+
// 可选:全局替换日志实现(不调用则使用内核内置 console fallback,写 stderr;宿主可注入任意 ILogger 实现)
|
|
117
|
+
setLogger(myCustomLogger);
|
|
118
|
+
|
|
119
|
+
// 创建 Agent
|
|
120
|
+
const agent = new Agent({
|
|
121
|
+
projectPath: '/path/to/novel-project',
|
|
122
|
+
provider, // 前台 Provider(必须)
|
|
123
|
+
backgroundProvider, // 后台 Provider(可选)
|
|
124
|
+
configDir: '/path/to/agent-config',
|
|
125
|
+
dataDir: '/path/to/novel-project/.memora-data', // 必填;相对路径会以进程 cwd 为基准,建议传绝对路径
|
|
126
|
+
maxContextTokens: 120000,
|
|
127
|
+
activeRolePack: '作家',
|
|
128
|
+
permission: 'owner',
|
|
129
|
+
allowedPaths: ['.'],
|
|
130
|
+
confirmWrites: false,
|
|
131
|
+
storage, // 存储层注入(可选)
|
|
132
|
+
tracer: myOtelTracer, // 可观测性 Tracer(可选,不传则静默丢弃所有 span)
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
await agent.init();
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 3. 对话
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
// 流式对话(生产推荐)
|
|
142
|
+
for await (const chunk of agent.chat('帮我写一段玄幻小说开头')) {
|
|
143
|
+
switch (chunk.type) {
|
|
144
|
+
case 'text': ui.appendText(chunk.content); break;
|
|
145
|
+
case 'thinking': ui.showThinking(chunk.phase); break;
|
|
146
|
+
case 'tool_start': ui.showToolStart(chunk.name); break;
|
|
147
|
+
case 'tool_result':ui.showToolResult(chunk.ok); break;
|
|
148
|
+
case 'aborted': ui.showCancelled(chunk.reason); break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// 同步对话(测试用)
|
|
153
|
+
const reply = await agent.chatSync('你好');
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### 3.5 事件订阅(可选)
|
|
157
|
+
|
|
158
|
+
Agent 向宿主广播对话外事件(记忆变更、角色切换、会话分叉等)。
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
import type { AgentEventMap } from '@zooique/memora';
|
|
162
|
+
|
|
163
|
+
agent.on('memoryAdded', (e) => console.log(`新记忆: ${e.source}:${e.name}`));
|
|
164
|
+
agent.on('personaSwitched', (e) => console.log(`角色: ${e.from} → ${e.to}`));
|
|
165
|
+
agent.on('memoryRecalled', (e) => console.log(`想起 ${e.count} 条记忆`));
|
|
166
|
+
agent.on('sessionForked', (e) => console.log(`分叉: ${e.from} → ${e.to},${e.roundCount} 个问答闭环`));
|
|
167
|
+
|
|
168
|
+
// close() 自动移除所有监听器
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### 4. 注册领域工具
|
|
172
|
+
|
|
173
|
+
> 1.0.0:工具注册走 `agent.tools.xxx()`。
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
agent.tools.registerTool(
|
|
177
|
+
{
|
|
178
|
+
name: 'create_chapter',
|
|
179
|
+
description: '创建一个新章节',
|
|
180
|
+
parameters: {
|
|
181
|
+
type: 'object',
|
|
182
|
+
properties: { title: { type: 'string', description: '章节标题' } },
|
|
183
|
+
required: ['title'],
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
async (args) => {
|
|
187
|
+
const chapter = await myNovel.createChapter(args.title);
|
|
188
|
+
return `章节 "${args.title}" 已创建`;
|
|
189
|
+
},
|
|
190
|
+
);
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### 4.5 外部世界工具注入(可选,条件性暴露)
|
|
194
|
+
|
|
195
|
+
> 三个「连接外部世界」的条件工具——`web_search` / `web_fetch` / `run_code`——**宿主注入对应 provider 才暴露,未注入则不进入 LLM 工具面**,内核保持零运行时依赖。各工具的用途、参数与单工具注入方式见 [API 参考手册](./memora-api-reference.md) §8;此处演示三者**一起**注入的组合写法。
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
import { Agent, FetchWebFetchProvider } from '@zooique/memora';
|
|
199
|
+
import type { ICodeExecutionProvider } from '@zooique/memora';
|
|
200
|
+
|
|
201
|
+
// ① 网页抓取(搜索→抓取闭环:web_search 找链接,web_fetch 读正文)
|
|
202
|
+
const fetchProvider = new FetchWebFetchProvider(); // 内置零依赖默认实现
|
|
203
|
+
|
|
204
|
+
// ② 代码执行(沙箱完全由宿主提供——语言白名单/资源限制/网络隔离)
|
|
205
|
+
const codeExecutionProvider: ICodeExecutionProvider = {
|
|
206
|
+
async execute(code, language, options) {
|
|
207
|
+
// 例:经宿主沙箱执行,返回 stdout/stderr/exitCode/timedOut
|
|
208
|
+
return { stdout: '42', stderr: '', exitCode: 0, timedOut: false };
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const agent = new Agent({
|
|
213
|
+
projectPath: '/path/to/novel-project',
|
|
214
|
+
dataDir: '/path/to/novel-project/.memora-data', // 必填
|
|
215
|
+
provider,
|
|
216
|
+
// webSearchProvider: new FetchWebSearchProvider(), // 搜索(web_search,参见参考手册 §8.3)
|
|
217
|
+
fetchProvider, // 可选:暴露 web_fetch
|
|
218
|
+
codeExecutionProvider, // 可选:暴露 run_code
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
> **注意**:`run_code` 是通用执行能力(源码不进上下文,仅结果返回),执行隔离等级完全由宿主 provider 决定;接入前务必评估沙箱安全边界(参见参考手册 §8.5)。
|
|
223
|
+
|
|
224
|
+
### 5. 记忆关键词与写入扩展(已移除)
|
|
225
|
+
|
|
226
|
+
> 写入扩展与记忆关键词(`agent.insight.xxx()`)已于 2026-08-14 随洞察层移除,不再提供。记忆统一以 round-summary 沉淀,经 `agent.memory.writeUpsert()` 等 `writeXxx` 方法写入。
|
|
227
|
+
|
|
228
|
+
### 6. 查询记忆
|
|
229
|
+
|
|
230
|
+
> 1.0.0:记忆查询走 `agent.memory.xxx()`。
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
// 3 层记忆快照
|
|
234
|
+
const snap = agent.memory.snapshot();
|
|
235
|
+
console.log('工作记忆:', snap.working.total, '条');
|
|
236
|
+
console.log('引导记忆:', snap.bootstrap.total, '条');
|
|
237
|
+
|
|
238
|
+
// 关键词搜索
|
|
239
|
+
const hits = agent.memory.search('世界观');
|
|
240
|
+
hits.forEach(h => console.log(`${h.source}:${h.name}`));
|
|
241
|
+
|
|
242
|
+
// 记忆库统计
|
|
243
|
+
const stats = agent.memory.stats();
|
|
244
|
+
console.log('记忆总数:', stats.total);
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### 7. 管理角色包
|
|
248
|
+
|
|
249
|
+
> 统一走 `agent.rolePack.xxx`(RolePackManager)。
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
const rp = agent.rolePack;
|
|
253
|
+
if (rp) {
|
|
254
|
+
// 列出所有角色包元数据
|
|
255
|
+
const metas = rp.listMeta();
|
|
256
|
+
|
|
257
|
+
// 手动切换角色包
|
|
258
|
+
rp.activate('作家');
|
|
259
|
+
|
|
260
|
+
// 查询当前状态
|
|
261
|
+
console.log(rp.activeName); // '作家'
|
|
262
|
+
console.log(rp.getActiveTraits());
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### 8. 切换项目
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
// 按路径切换(最稳):传项目根目录的绝对路径,无需预先注册
|
|
270
|
+
const ctx = await agent.switchProject('/path/to/another-novel');
|
|
271
|
+
console.log(`已切换到:${ctx.projectName}`);
|
|
272
|
+
|
|
273
|
+
// 按名切换:依赖项目注册表命中,须先注册
|
|
274
|
+
// 注册表缺省落在 dataDir 内 —— 只有多项目共用同一 dataDir(或显式指定共同的 registryDir)时,
|
|
275
|
+
// 按名切换才成立;若 dataDir 是项目级目录,注册表会随之落进各项目、只含自身条目,按名切换不成立。
|
|
276
|
+
agent.projects.registerProject('/path/to/another-novel', 'another-novel');
|
|
277
|
+
const ctx2 = await agent.switchProject('another-novel');
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
> 未命中注册表且传入的又不是绝对路径时,`switchProject` 直接抛错(相对路径会以进程 cwd 为基准,
|
|
281
|
+
> 可能静默创建出非预期的项目目录并占用其锁)。
|
|
282
|
+
|
|
283
|
+
### 9. 关闭
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
await agent.close(); // 释放项目锁 + 关闭注入的存储实例
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## 四、会话持久化(ISessionStore)
|
|
292
|
+
|
|
293
|
+
Memora 通过 `ISessionStore` 接口支持会话消息的持久化。宿主实现此接口,注入到 Agent。
|
|
294
|
+
|
|
295
|
+
> **⚠ 现行契约以类型定义为准(导出类型 `ISessionStore`,以随包 `.d.ts` 为准)**:下方示例仅示意最小形态。当前接口为 **round-based 单一模式**(`appendRoundId` / `getRoundIds` / `setRoundIds` / `createSession` / `deleteSession` + 标题元数据 `getSessionMeta` / `updateSessionMeta` / `listSessionMetas`)——消息内容只存 RoundStore,`ISessionStore` 只持 Round 指针。
|
|
296
|
+
> **检查点持久化已退役(2026-09-10 减法)**:`saveCheckpoint` / `loadCheckpoint` / `deleteCheckpoint` 已从接口删除;跨重启恢复链整体下线,中止/断电一律把未完成 turn 补全为完整 turn 身份并在下次会话按历史加载,运行时暂停是同 turn 内续跑(内存态)。
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
import type { ISessionStore, SessionMessage } from '@zooique/memora';
|
|
300
|
+
|
|
301
|
+
// 宿主实现接口
|
|
302
|
+
class FileSessionStore implements ISessionStore {
|
|
303
|
+
appendMessage(date: string, session: string, message: SessionMessage): void {
|
|
304
|
+
// 写入文件或数据库
|
|
305
|
+
}
|
|
306
|
+
loadMessages(date: string, session: string): SessionMessage[] {
|
|
307
|
+
// 从文件或数据库读取
|
|
308
|
+
return [];
|
|
309
|
+
}
|
|
310
|
+
listSessions(): string[] {
|
|
311
|
+
// 返回所有会话列表
|
|
312
|
+
return [];
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// 注入到 Agent
|
|
317
|
+
const agent = new Agent({
|
|
318
|
+
// ...其他配置
|
|
319
|
+
sessionStore: new FileSessionStore('./sessions'),
|
|
320
|
+
});
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**会话持久化特性:**
|
|
324
|
+
- 日期使用 `todayDate()` 动态获取,确保跨日后消息写入当天目录
|
|
325
|
+
- `appendUser()` / `appendAssistant()` 自动调用 `appendMessage()`
|
|
326
|
+
- `loadSessionMessages()` 自动调用 `loadMessages()`
|
|
327
|
+
- `SessionMessage.role` 支持 `'user' | 'assistant' | 'system'`,宿主直接调用 `appendMessage()` 时可传入任意角色
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## 四.5、会话分叉(Fork Session)
|
|
332
|
+
|
|
333
|
+
Memora 支持从任意问答闭环(Round)位置创建会话分叉。分叉后,新会话只包含分叉点及之前的问答闭环,后续的问答闭环在原会话中保持不变。
|
|
334
|
+
|
|
335
|
+
**使用场景**:
|
|
336
|
+
- 用户在对话中决定从某个关键点分叉探索不同方向
|
|
337
|
+
- 每个分支只继承到分叉点为止的上下文,避免无关历史干扰
|
|
338
|
+
- 分支完全独立,互不干扰
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
// 从指定 Round 位置分叉(唯一分叉方式,roundId 可选)
|
|
342
|
+
const result = agent.forkSession(roundId);
|
|
343
|
+
console.log(`已分叉到: ${result.newSession},复制了 ${result.roundCount} 个问答闭环`);
|
|
344
|
+
|
|
345
|
+
// 不传 roundId → 默认使用最后一个 Round(等效全量分叉)
|
|
346
|
+
const fullResult = agent.forkSession();
|
|
347
|
+
|
|
348
|
+
// 自定义分支名
|
|
349
|
+
const result2 = agent.forkSession(roundId, 'experiment');
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**命名规则**:
|
|
353
|
+
- 自动生成:平等普通会话名(与手动创建的会话一致,无 `main-b1` 等分叉标记)
|
|
354
|
+
- 自定义名称:直接传入目标名称作为第二参数
|
|
355
|
+
|
|
356
|
+
**记忆处理策略**:
|
|
357
|
+
- 已有记忆:全局共享(记忆是全局知识库,不属于单个会话)
|
|
358
|
+
- 分叉后的 round-summary:各自独立(不同分支探索不同方向)
|
|
359
|
+
|
|
360
|
+
**事件监听**:
|
|
361
|
+
```typescript
|
|
362
|
+
agent.on('sessionForked', (event) => {
|
|
363
|
+
console.log(`从 ${event.from} 分叉到 ${event.to}`);
|
|
364
|
+
console.log(`复制了 ${event.roundCount} 个问答闭环`);
|
|
365
|
+
});
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**边界情况**:
|
|
369
|
+
- 当前会话无问答闭环时抛出错误
|
|
370
|
+
- 传入的 `roundId` 不存在于当前会话时抛出错误
|
|
371
|
+
- `ISessionStore` 未注入时抛出错误
|
|
372
|
+
- 对话正在进行中(`chatBusy`)时抛出错误
|
|
373
|
+
- 自定义名称已存在时抛出错误
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## 四.6、会话归档(Archive Session)—— 宿主独立实现
|
|
378
|
+
|
|
379
|
+
Memora 内核聚焦于“对话与记忆”引擎,不负责管理用户的视觉焦点和会话列表的展示层级。**会话归档(将会话从活跃列表移至历史列表)是一个纯粹的 UI/UX 行为,应由宿主项目独立实现,无需修改 Memora 内核。**
|
|
380
|
+
|
|
381
|
+
### 设计理念
|
|
382
|
+
|
|
383
|
+
- **内核职责**:确保对话内容(消息记录、记忆卡片)的持久化和可召回性。会话一旦创建,其内容在生命周期内始终可用。
|
|
384
|
+
- **宿主职责**:管理“活跃会话”与“已归档会话”的视图分离,为用户提供整洁的交互界面。
|
|
385
|
+
|
|
386
|
+
### 实现方案
|
|
387
|
+
|
|
388
|
+
宿主项目应在自身的数据模型中扩展会话管理功能:
|
|
389
|
+
|
|
390
|
+
#### 1. 数据库调整
|
|
391
|
+
|
|
392
|
+
在宿主的会话数据表中增加一个状态字段,例如 `is_archived`(布尔值或枚举),用于区分会话的展示状态。
|
|
393
|
+
|
|
394
|
+
```sql
|
|
395
|
+
-- 示例:宿主数据库表结构
|
|
396
|
+
ALTER TABLE sessions ADD COLUMN is_archived BOOLEAN DEFAULT 0;
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
#### 2. 前端交互实现
|
|
400
|
+
|
|
401
|
+
- **归档按钮**:在会话列表项中提供“归档”操作按钮。点击时,**不调用** Memora Agent 的任何 API,而是调用宿主自身的后端接口(如 `PUT /api/sessions/{id}/archive`)。
|
|
402
|
+
- **列表分离**:宿主前端应维护两个视图:
|
|
403
|
+
- **活跃列表**:查询 `is_archived = false` 的会话。
|
|
404
|
+
- **历史列表**:查询 `is_archived = true` 的会话。
|
|
405
|
+
- **数据同步**:宿主的后端接口负责更新数据库中的 `is_archived` 字段,并通过 WebSocket 或轮询通知前端刷新列表。
|
|
406
|
+
|
|
407
|
+
### 流程示例
|
|
408
|
+
|
|
409
|
+
```typescript
|
|
410
|
+
// 宿主前端代码
|
|
411
|
+
async function archiveSession(sessionId: string) {
|
|
412
|
+
// 1. 调用宿主后端 API
|
|
413
|
+
const response = await fetch(`/api/sessions/${sessionId}/archive`, {
|
|
414
|
+
method: 'PUT',
|
|
415
|
+
headers: { 'Content-Type': 'application/json' }
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
if (response.ok) {
|
|
419
|
+
// 2. 从活跃列表移除该会话
|
|
420
|
+
removeSessionFromList(sessionId);
|
|
421
|
+
// 3. 可选:提示用户已归档
|
|
422
|
+
showToast('会话已归档至历史记录');
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// 宿主后端路由(伪代码)
|
|
427
|
+
app.put('/api/sessions/:id/archive', (req, res) => {
|
|
428
|
+
const { id } = req.params;
|
|
429
|
+
// 4. 更新数据库状态
|
|
430
|
+
db.updateSessionStatus(id, { is_archived: true });
|
|
431
|
+
res.json({ success: true });
|
|
432
|
+
});
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### 核心优势
|
|
436
|
+
|
|
437
|
+
- **解耦**:Memora 内核无需感知“归档”这一视图行为,保持纯粹的业务逻辑。
|
|
438
|
+
- **灵活**:宿主可自由扩展“归档”的变体,如“收藏夹”、“置顶”、“多级分类”等,均可在宿主侧独立完成。
|
|
439
|
+
- **稳定**:内核代码零风险,记忆召回逻辑完全不受归档行为影响,确保所有对话内容(无论归档与否)都能被准确回忆。
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## 五、API 速查
|
|
444
|
+
|
|
445
|
+
> 构造选项、生命周期、对话、项目/会话、各 Manager、事件、Provider 管理等**完整条目与类型定义**详见 [memora-api-reference.md](./memora-api-reference.md)。此处只列接入期最常用的几个入口:
|
|
446
|
+
|
|
447
|
+
| 操作 | 入口 | 详见参考手册 |
|
|
448
|
+
|------|------|------|
|
|
449
|
+
| 构造 | `new Agent({ projectPath, provider, configDir, dataDir })` | §二 · AgentOptions |
|
|
450
|
+
| 对话 | `agent.chat(input)`(流式)/ `agent.chatSync(input)` | §三 |
|
|
451
|
+
| 记忆 | `agent.memory.snapshot()/search()/writeXxx()` | §四 |
|
|
452
|
+
| 角色包 | `agent.rolePack.listMeta()/activate()` | §七 |
|
|
453
|
+
| 工具 | `agent.tools.registerTool()/execute()` | §八 |
|
|
454
|
+
| 会话 | `agent.forkSession()` / `agent.sessionManager.*` | §六 |
|
|
455
|
+
|
|
456
|
+
> 记忆治理(去重/冲突)统一走 `agent.governance` 或 Agent 层方法,见参考手册 §四 与「记忆治理」章节。
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
## 六、宿主工具函数
|
|
461
|
+
|
|
462
|
+
> 所有可导入工具函数/类型的**完整 import 清单与导出声明**见 [memora-api-reference.md](./memora-api-reference.md) §十六。下表列出常用函数与其用途:
|
|
463
|
+
|
|
464
|
+
| 函数/类型 | 用途 |
|
|
465
|
+
|-----------|------|
|
|
466
|
+
| `createLlmProvider(config)` | 从完整 Config(`llm.providers` + `active`)创建激活 Provider(配合 `loadConfig`) |
|
|
467
|
+
| `createProviderFromConfig(name, config)` | 从命名配置创建单个 Provider 实例(扁平参数) |
|
|
468
|
+
| `loadConfig(path?)` | 加载 `.memora/config.json` 项目级配置文件(或传入显式 configPath) |
|
|
469
|
+
| `InMemoryStorage` | IMemoryStorage 的纯内存实现(测试用) |
|
|
470
|
+
| `setLogger(logger)` | 替换全局日志实现 |
|
|
471
|
+
| `logger` | 全局日志实例 |
|
|
472
|
+
| `segmentText(text)` | 中文分词工具 |
|
|
473
|
+
| `parseFrontmatter(text)` | 解析 Markdown frontmatter |
|
|
474
|
+
| `serializeFrontmatter(fm, body)` | 序列化 frontmatter + body 为 Markdown |
|
|
475
|
+
| `safeSetTimeout(fn, ms)` | 安全定时器(可跟踪清理) |
|
|
476
|
+
| `safeSetInterval(fn, ms)` | 安全间隔器(可跟踪清理) |
|
|
477
|
+
| `clearSafeTimeout(id)` | 清除安全定时器 |
|
|
478
|
+
| `clearSafeInterval(id)` | 清除安全间隔器 |
|
|
479
|
+
| `extractKeywords(text)` | 提取关键词 |
|
|
480
|
+
| `SOURCE_LABELS` | source 标签常量(PERSONA / RULE / SKILL / WORK_PROJECTION / ROUND_SUMMARY / UNKNOWN) |
|
|
481
|
+
| `escapeLike(query)` | 转义 SQLite LIKE 通配符(`%` / `_` → `\%` / `\_`)。**SQL 必须写成 `LIKE ? ESCAPE '\'`**——不写 ESCAPE 子句则反斜杠被视为普通字符,转义后的模式匹配不到任何字面值,查询**静默返回空** |
|
|
482
|
+
| `escapeLikeSnippet(text, maxLen?)` | 截断至 maxLen(默认 50)后转义 LIKE 通配符——搜索输入防超长解析 + 防通配符被当模式符(SQL 后端检索的配套动作,同样须配 `ESCAPE '\'`) |
|
|
483
|
+
| `validateSource(source)` | 校验 source 标签是否为已知标签(返回 warning,不阻止写入) |
|
|
484
|
+
| `MemoraError` | 统一错误类型(结构化错误码 + 上下文) |
|
|
485
|
+
| `toError(err)` | 将任意值转为 Error(浏览器端安全,不引入 `logging/` 模块) |
|
|
486
|
+
| `NOOP_TRACER` | ITracer 的空实现(静默丢弃所有 span,零开销) |
|
|
487
|
+
| `TRACE_SPANS` | AgentLoop 预定义 Span 名称常量(RECALL / LLM_CALL / TOOL_EXEC / RESPONSE) |
|
|
488
|
+
| `ToolErrorCode` | 工具错误码枚举(10 种,含 PATH_NOT_ALLOWED / FILE_NOT_FOUND 等) |
|
|
489
|
+
| `isRetryableErrorCode(code)` | 判断错误码是否可重试(5 种 retryable) |
|
|
490
|
+
| `TypedEventEmitter` | 类型安全的事件发射器(Agent 继承此类) |
|
|
491
|
+
|
|
492
|
+
**注意**:`SqliteStorage` 已移出到宿主项目,不再从 memora 导出。宿主需自行实现 `IMemoryStorage` 接口。
|
|
493
|
+
|
|
494
|
+
`IMemoryStorage` 接口要求实现 `count()` 和 `countBySource(source)` 方法,用于高效统计记忆数量(避免全量加载数据)。详见 [API 参考手册](./memora-api-reference.md)。
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
## 七、可观测性接入(ITracer)
|
|
499
|
+
|
|
500
|
+
Memora 内置了轻量的 Span/Trace 抽象,宿主可注入 OpenTelemetry 等实现来观测 AgentLoop 行为。
|
|
501
|
+
|
|
502
|
+
### 接口定义
|
|
503
|
+
|
|
504
|
+
```typescript
|
|
505
|
+
interface ITracer {
|
|
506
|
+
startSpan(name: string, attributes?: Record<string, string | number | boolean>): ISpan;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
interface ISpan {
|
|
510
|
+
setAttribute(key: string, value: string | number | boolean): void;
|
|
511
|
+
end(): void;
|
|
512
|
+
recordException(error: Error): void;
|
|
513
|
+
}
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### AgentLoop 预定义 Span
|
|
517
|
+
|
|
518
|
+
| Span 名称 | 常量 | 触发时机 | 关键属性 |
|
|
519
|
+
|-----------|------|---------|---------|
|
|
520
|
+
| `llm.call` | `TRACE_SPANS.LLM_CALL` | LLM API 调用(含重试循环) | `model`, `messageCount`, `iteration`,另写 `inputTokens` |
|
|
521
|
+
| `tool.execute` | `TRACE_SPANS.TOOL_EXEC` | 工具执行(并发时多个 span 时间重叠) | `toolName`,另写 `args`(被拒时 `denied`) |
|
|
522
|
+
| `response.generate` | `TRACE_SPANS.RESPONSE` | 整轮响应 | `inputLength`(任务级指标随流结束统一补写) |
|
|
523
|
+
| `context.summary` | `TRACE_SPANS.CONTEXT_SUMMARY` | 消息超 `maxContextTokens` 触发截断、生成"遗忘补偿"摘要 | `messageCount`, `summarizingMessages` |
|
|
524
|
+
| `archive.postProcess` | `TRACE_SPANS.POST_PROCESS` | 每轮 `chat()` 后归档(round-summary、角色/技能匹配) | `archiveMode` |
|
|
525
|
+
| `round.difficulty` | `TRACE_SPANS.DIFFICULTY` | **预留名,内核当前零 emit 点** | — |
|
|
526
|
+
| `round.report` | `TRACE_SPANS.REPORT` | **预留名,内核当前零 emit 点** | — |
|
|
527
|
+
|
|
528
|
+
> 共 **7** 个常量。`TRACE_SPANS.RECALL` / `TRACE_SPANS.RECALL_ACTUAL`(`recall.recall` / `recall.actual`)已于 **2026-09-11 物理删除**(自动记忆召回退役后无 emit 点)——宿主无需为其编写 span 处理逻辑;记忆检索耗时看 `tool.execute`(`search_memories` 工具)。
|
|
529
|
+
|
|
530
|
+
### 宿主接入示例(OpenTelemetry)
|
|
531
|
+
|
|
532
|
+
```typescript
|
|
533
|
+
import { trace } from '@opentelemetry/api';
|
|
534
|
+
import type { ITracer, ISpan } from '@zooique/memora';
|
|
535
|
+
|
|
536
|
+
// 宿主实现 ITracer 接口(桥接 OpenTelemetry)
|
|
537
|
+
class OtelTracer implements ITracer {
|
|
538
|
+
private tracer = trace.getTracer('memora-agent');
|
|
539
|
+
|
|
540
|
+
startSpan(name: string, attributes?: Record<string, string | number | boolean>): ISpan {
|
|
541
|
+
const otelSpan = this.tracer.startSpan(name, { attributes });
|
|
542
|
+
return {
|
|
543
|
+
setAttribute: (key, value) => otelSpan.setAttribute(key, value),
|
|
544
|
+
end: () => otelSpan.end(),
|
|
545
|
+
recordException: (error) => otelSpan.recordException(error),
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// 注入到 Agent
|
|
551
|
+
const agent = new Agent({
|
|
552
|
+
// ...其他配置
|
|
553
|
+
tracer: new OtelTracer(),
|
|
554
|
+
});
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
> **不注入时**:默认使用 `NOOP_TRACER`(静默丢弃所有 span,零运行时开销)。
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
## 八、工具错误反思(Reflection)
|
|
562
|
+
|
|
563
|
+
> 注:原「内容护栏(Guardrails)」章节已移除——guardrail 是「零规则、无扫描映射、无消费者」的空转链,已随内核摘除(2026-08-17,见 memory-role-pack-boundary.md §4.4)。
|
|
564
|
+
|
|
565
|
+
当工具执行失败时,错误结果包含 `[ERR:TOOL:code]` 前缀。如果错误码标记为 retryable(如 `FILE_NOT_FOUND`、`ARGUMENT_ERROR`),AgentLoop 会自动注入 `[REFLECTION_HINT]` 系统消息,引导 LLM 修正参数后重试。
|
|
566
|
+
|
|
567
|
+
```typescript
|
|
568
|
+
import { ToolErrorCode, isRetryableErrorCode } from '@zooique/memora';
|
|
569
|
+
|
|
570
|
+
// 判断错误码是否可重试
|
|
571
|
+
isRetryableErrorCode(ToolErrorCode.FILE_NOT_FOUND); // true
|
|
572
|
+
isRetryableErrorCode(ToolErrorCode.PATH_NOT_ALLOWED); // false
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
Reflection 默认最多重试 2 次(`maxReflectionRetries`),防止无限循环。
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
579
|
+
## 九、多步骤编排
|
|
580
|
+
|
|
581
|
+
Memora 是单 Agent 模型(ADR-011),不内置多 Agent 编排。宿主项目可通过多次调用 `agent.chat()` 实现复杂工作流:
|
|
582
|
+
|
|
583
|
+
```typescript
|
|
584
|
+
// 示例:分析项目 → 生成大纲 → 逐章写作
|
|
585
|
+
const analysis = await agent.chatSync('分析这个项目的风格和主题');
|
|
586
|
+
const outline = await agent.chatSync('基于分析结果,生成章节大纲');
|
|
587
|
+
for (const chapter of chapters) {
|
|
588
|
+
const content = await agent.chatSync(`根据大纲,写第${chapter.num}章:${chapter.title}`);
|
|
589
|
+
// 写入文件...
|
|
590
|
+
}
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
**编排要点**:
|
|
594
|
+
- 每次 `chat()` 共享同一个 AgentLoop 上下文(记忆、角色、技能)
|
|
595
|
+
- 宿主负责流程控制(条件分支、并行、错误处理)
|
|
596
|
+
- 如需隔离上下文,使用 `agent.sessionManager.switchSession()` 或 `agent.forkSession()`
|
|
597
|
+
|
|
598
|
+
---
|
|
599
|
+
|
|
600
|
+
## 十、关键约束
|
|
601
|
+
|
|
602
|
+
**前提:存储方案由宿主自选,内核只定契约。** 内核只定义 `IMemoryStorage` / `ISessionStore` 接口,**不规定后端**——SQLite(better-sqlite3)、JSON 文件、内存实现一视同仁,任何后端都不得被写进内核逻辑。接口方法为**同步语义**(对齐 better-sqlite3),异步后端需另行扩展接口;JSON 落地实现在同步路径上做全量重写,记忆量增长时由宿主自行评估更优后端(阈值与权衡见 `storageInterface.ts` 头注释)。第一宿主 memora-vscode 当前用 JSON 文件,换成 SQLite **不需要改内核**。
|
|
603
|
+
|
|
604
|
+
1. **`provider` 是必填项** — Agent 无法独立运行
|
|
605
|
+
2. **configDir** 指向 Agent 级配置目录,所有项目共享
|
|
606
|
+
3. **项目级 `.memora/`** 放项目级配置(`rules/`、`skills/`)与内核写入的项目锁 `.lock`;`dataDir` 若指向此处(第一宿主 memora-vscode 即如此),记忆库与会话也落在这里
|
|
607
|
+
4. **角色包只能手动切换**(`agent.switchRolePack(name)` / `agent.rolePack.activate(name)`)——无输入自动匹配、无粘性锁存、无互斥触发;已激活的角色包在当前会话内保持固定(v0.13 已移除自动匹配全链)
|
|
608
|
+
5. **对话历史随 Agent 持久化** — `sessionStore` 是实例级注入的,`switchProject()` 不换存储;未注入则仅内存保存
|
|
609
|
+
6. **Manager 访问器在 `init()` 前返回 `null`** — 所有 `agent.rolePack.xxx()` / `agent.memory.xxx()` 等调用必须在 `init()` 之后
|
|
610
|
+
7. **作品原始内容不进记忆库**,Agent 通过工具按需读取(大文本走 `read_file` 分段,提炼后只留情报,不全量入库 / 入上下文)
|
|
611
|
+
8. **配置文件是真理源**,`<configDir>/role-packs/` 下的角色包由 RolePackManager 启动时扫描加载
|
|
612
|
+
9. **一个 Agent = 一份记忆库** — `storage` 与 `dataDir` 都是 **Agent 实例级**的:`switchProject()` 复用同一实例,不按项目 / 子项目分裂。**要按工作区彼此隔离,就各自 `new Agent`**——隔离粒度归宿主决定,内核不规定
|
|
613
|
+
10. **项目切换不重建、不关闭存储** — `switchProject()` 复用已注入的实例,只在 `close()` 时关闭(`ProjectManager` 在 Agent 生命周期内缓存)
|
|
614
|
+
11. **禁止把配置放进记忆库** — 配置(角色包 / persona / rules / skills)的真理源是文件(`configDir` / 角色包),设定记忆归角色包内容层、不进记忆库(ADR-025 / `memory-role-pack-boundary`)
|
|
615
|
+
12. **项目切换** `switchProject()` 已自动 rebuild,通常无需手动调用 `rebuildComponents()`
|
|
616
|
+
13. **Tracer 未注入时**自动降级为 NoopTracer,零运行时开销
|
|
617
|
+
|
|
618
|
+
---
|
|
619
|
+
|
|
620
|
+
## 十.5、执行前检查决策(preExecutionCheck)⚠️ 安全基线
|
|
621
|
+
|
|
622
|
+
`preExecutionCheck` 是工具执行前的统一闸门(内核 `ToolExecutor` 单点聚合检查:只读 → 审批 → 执行三态)。宿主经 `AgentOptions.preExecutionCheck` 注入,返回 `allow` / `skip` / `confirm` 三态。
|
|
623
|
+
|
|
624
|
+
### 单用户桌面场景(可恒放行)
|
|
625
|
+
|
|
626
|
+
本地运行的单用户宿主(VS Code 插件 / 桌面应用)可注入恒放行:
|
|
627
|
+
|
|
628
|
+
```ts
|
|
629
|
+
preExecutionCheck: () => ({ skip: false }), // 放行,等价于 allow
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
**理由**(宿主装配注入点见仓库内参考实现 `hosts/memora-vscode/src/extension/host/assemble.ts`,**非随包产物**):
|
|
633
|
+
1. 宿主运行在用户本地,天然信任模型;
|
|
634
|
+
2. 工具审计已由 `tool_start` / `tool_result` chunk + `tool.execute` span 承担,不重复记录。
|
|
635
|
+
|
|
636
|
+
### 多用户 / 服务端部署(必须替换)⚠️
|
|
637
|
+
|
|
638
|
+
**恒放行仅限单用户本地场景。** 一旦接入多用户或服务端部署,必须替换为真实审批策略,否则任意用户可经工具读写任意文件 / 执行任意命令。最小实现要点:
|
|
639
|
+
|
|
640
|
+
- **审批在宿主侧实现**:内核 3.0.0 已删内核审批键(`toolApproval`,理由见下 §十.7 补记),多用户场景须由宿主在 `preExecutionCheck` 实现真实审批(返回 `denied` 拒绝),高危操作(写文件 / 执行命令)默认拒绝而非放行;
|
|
641
|
+
- **路径守卫**:结合内核 `SecurityGuard` 的 `allowedPaths` 白名单 + 28 类禁止规则做硬性拦截,返回 `skip` 阻断越权调用;
|
|
642
|
+
- **只读策略**:角色包 `toolReadonly: 'readonly'` 时,preExecutionCheck 须拒绝一切写操作。
|
|
643
|
+
|
|
644
|
+
> 本决策同时受 `tasks/待完成任务.md` 设计纪律 **D5** 约束:恒放行属单用户场景可接受,但必须显式标注,未来多用户/服务端再接入真实策略。
|
|
645
|
+
|
|
646
|
+
---
|
|
647
|
+
|
|
648
|
+
## 十.6、存储单例约束(sessionStore / roundStore)⚠️ 契约基线
|
|
649
|
+
|
|
650
|
+
`sessionStore`(会话元数据)与 `roundStore`(问答闭环 / round 落盘)**必须全局唯一单例,且 UI 面板与 Agent 装配共享同一实例**。
|
|
651
|
+
|
|
652
|
+
### 为什么是硬约束(双实例覆盖写)
|
|
653
|
+
|
|
654
|
+
会话与 round 落盘的最终载体是同一份磁盘文件(`*.memora/sessions.json` + 各 round 文件)。若 UI 面板与 Agent 各自 `new` 一份 store:
|
|
655
|
+
|
|
656
|
+
- 两侧各自 `load()` 后内存状态分叉;
|
|
657
|
+
- 任一侧 `save()` 都只写自己内存视角,**后写覆盖先写** → 另一侧已追加的会话 / 消息丢失;
|
|
658
|
+
- 典型症状:重启后"会话记录加载不全"、跨面板操作互相吞掉对方写入。
|
|
659
|
+
|
|
660
|
+
这是数据正确性 bug,**不是性能或风格问题**,任何宿主对接都会踩。
|
|
661
|
+
|
|
662
|
+
### 规范模式(VS Code 宿主实证)
|
|
663
|
+
|
|
664
|
+
在 `activate()` 中创建一次,注入两侧(见仓库内参考实现 `hosts/memora-vscode/src/extension/extension.ts`,**非随包产物**:`activate()` 内 `new WorkspaceRoundStore(...)` 与 `new WorkspaceSessionStore(workspacePath, roundStore)` 各建一次;面板侧经 `new MemoraChatViewProvider(..., sessionStore, ...)` 与 `settingsProvider.setAgentFactory(...)`,Agent 侧经 `getOrCreateAgent(..., sessionStore, roundStore, ...)` → `assembleAgent(...)`):
|
|
665
|
+
|
|
666
|
+
```ts
|
|
667
|
+
// 单例:activate 中创建一次
|
|
668
|
+
const sessionStore = new WorkspaceSessionStore(workspacePath, roundStore);
|
|
669
|
+
sessionStore.load();
|
|
670
|
+
|
|
671
|
+
// 注入 UI 面板:面板经 setAgentFactory 复用同一 agentPromise → 同一份 store
|
|
672
|
+
chatProvider.setAgentFactory((projectPath) =>
|
|
673
|
+
getOrCreateAgent(projectPath, providerStore, sessionStore, roundStore, /* ... */));
|
|
674
|
+
|
|
675
|
+
// 注入 Agent 装配:assembleAgent 透传同一 sessionStore / roundStore 进内核
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
`sessionStore` 经 `getOrCreateAgent` → `assembleAgent` 透传进内核;UI 面板经 `chatProvider.setAgentFactory` 复用同一 `agentPromise`,从而共用同一份 store。**两侧的 store 引用必须指向同一对象**,禁止各建各的。
|
|
679
|
+
|
|
680
|
+
### 单例 / 原子写各防什么(边界辨析)
|
|
681
|
+
|
|
682
|
+
- **单例**防**同进程内**两个代码路径各 `new` 一份 store → 内存分叉 → 互相覆盖写。VS Code 单宿主下,单例已彻底封死这条路。
|
|
683
|
+
- **原子写**(`atomicWriteFileSync`:先写 `.tmp` 再 `renameSync`)防**写一半进程崩了**导致文件损坏——落盘要么旧内容、要么完整新内容,不会半截。memora 已实现,且**内核与宿主各有一份**:内核 `src/utils/atomicWrite.ts` 的 `atomicWriteFile`(异步,当前生产消费者为 `WorkProjectionManager`);宿主 `hosts/memora-vscode/src/extension/host/atomicWriteSync.ts` 的 `atomicWriteFileSync`(同步,供 `WorkspaceSessionStore` / `WorkspaceRoundStore` / `WorkspaceStorage` 等宿主存储消费,**非随包产物**)。
|
|
684
|
+
- **两者都不防"跨进程双开"**:同工作区开两个窗口 / 两个宿主进程 = 两个 `sessionStore` 单例 = 两个进程各原子写同一 `*.memora/sessions.json`。原子写保"不损坏"但不保"不丢更新"(后 rename 覆盖先 rename)。此场景须靠**进程锁 / 单实例守卫**兜底(参考 grida 对 `sessions.db` 加进程锁、重复启动直接拒绝)。
|
|
685
|
+
|
|
686
|
+
### 新宿主接入检查清单
|
|
687
|
+
|
|
688
|
+
- [ ] `sessionStore` / `roundStore` 在宿主生命周期内只 `new` 一次;
|
|
689
|
+
- [ ] UI 面板(对话视图 / 会话树 / 设置)与 Agent 装配引用**同一个** store 实例;
|
|
690
|
+
- [ ] 落盘走**原子写**(`tmp` + `rename`),禁止裸 `writeFile` 覆盖(防崩溃损坏);
|
|
691
|
+
- [ ] **跨进程 / 多窗口宿主须加文件锁或单实例守卫**:单例只防同进程双实例,不防同工作区双开各自写同一 `sessions.json`;原子写保证不损坏但不保证不丢更新,须进程锁兜底;
|
|
692
|
+
- [ ] 测试覆盖:模拟"面板先写、Agent 后写"或反之,断言最终落盘含两侧写入(防回归双实例覆盖写)。
|
|
693
|
+
|
|
694
|
+
> 本约束原仅存于宿主实现注释(`extension.ts` 的"杜绝双实例覆盖写";仓库内参考实现,**非随包产物**),现提升为宿主接入契约基线,避免新宿主对接踩坑。原子写实锤已具备(`atomicWriteFileSync`),单例 + 原子写已对齐主流硬化做法(grida / Chatbox 同款 tmp+rename);唯一真实残留为跨进程锁,已列入检查清单第 4 项。
|
|
695
|
+
|
|
696
|
+
## 十.7、策略键消费矩阵(16 键 SSOT 落点)📌 参考
|
|
697
|
+
|
|
698
|
+
> 逐键矩阵(16 键 × 内核消费位置 × UI 侧消费)为仓库内开发文档(SSOT:`src/role-pack/strategyKeys.ts`),**不随包发布**;宿主对接所需的键语义见 [role-pack-authoring-guide.md](./architecture/role-pack-authoring-guide.md) §三。此处只给新宿主对接必知的结论与边界。
|
|
699
|
+
|
|
700
|
+
- **16 键全部被内核真实消费、零 `[草案]`**(prepare 1 / act 7 / reflect 3 / global 5)。解析层 `rolePackManager` + `strategyResolver` 84 项测试守护,消费层跨 `contextPreparer` / `loop` / `agent` / `managers/llmCaller` / `toolRunner` / `orchestrator` / `prepare` 多文件覆盖。
|
|
701
|
+
- **三类流向,单一收口无镜像**:
|
|
702
|
+
1. act 5 键(`toolMode`/`toolStepLimit`/`providerRouting`/`multiStepReasoning`/`toolReadonly`)+ `selfReview` + global 4 键(`errorHandling`/`contextLimit`/`stepBudget`/`askLimit`),统一经 `resolveL2Strategy()` 聚合注入 `L2RuntimeStrategy`,loop 经 `this.strategy.<field>` 读取;`act.temperature`/`outputLimit` 由 `agent.ts` 直映射 `ChatOptions`(不经聚合);
|
|
703
|
+
2. prepare 键经 `resolveActiveStrategy()` 单一真理源流入 `contextPreparer` / `roundSummaryGenerator`;
|
|
704
|
+
3. persona 指令类(`userFollowup`/`askOn`/`askLimit`)由 `assembleRolePack()` 单收口注入。
|
|
705
|
+
- **⚠️ 边界纠正:`toolReadonly` 内核已执行,非「无宿主执行方」**。`toolRunner.ts` 只剩两层闸:闸①(只读闸 `toolReadonly==='readonly'`)**由内核执行**;闸③(宿主 `preExecutionCheck` 注入点)当前 VS Code 宿主恒放行(`assemble.ts` 恒返回 `() => ({ skip: false })`)只是单用户信任模型下的显式让行(关联 十.5 / 设计纪律 D5),未来多用户/服务端须替换真实审批。原闸② `toolApproval` 审批链已随 3.0.0 删键(2026-09-11,故代码注释 ①/③ 编号保留):单用户本地无真实审批场景,原"通知宿主 + UI 需审批 chip"是展示性假承诺——整键删除,新宿主切勿再期待 `onToolApproval` 回调或 `toolApproval==='confirm'` 语义,审批须自行在 `preExecutionCheck` 实现。
|
|
706
|
+
- **UI 侧 6 键有呈现**:宿主角色列表视图渲染策略 chip 5 键(`toolReadonly` / `summaryFocus` / `outputLimit` / `temperature` / `multiStepReasoning`)+ `toolMode` 经对话视图 capability badge 渲染('纯 LLM' / '全部工具')。能力名映射与策略键无关,**勿混淆**。(上述 UI 实现均为仓库内宿主参考实现,**非随包产物**。)
|
|
707
|
+
|
|
708
|
+
---
|
|
709
|
+
|
|
710
|
+
## 十一、用户档案实现指南(宿主扩展)
|
|
711
|
+
|
|
712
|
+
> **为什么内核没有独立的用户档案模块?**
|
|
713
|
+
|
|
714
|
+
### 设计哲学:偏好涌现 vs 配置驱动
|
|
715
|
+
|
|
716
|
+
Memora 的记忆系统通过 `round-summary` 的 `type=preference` 类型承载"偏好涌现"的核心需求。用户在对话中的偏好(如"喜欢简洁回答"、"偏好中文沟通")会自然沉淀为摘要记忆,并在后续对话中随召回注入上下文。
|
|
717
|
+
|
|
718
|
+
这种"涌现驱动"的设计与传统"配置驱动"的用户档案方案有本质区别:
|
|
719
|
+
|
|
720
|
+
| 维度 | WorkBuddy 类方案(配置驱动) | Memora 方案(涌现驱动) |
|
|
721
|
+
|------|---------------------------|----------------------|
|
|
722
|
+
| 更新方式 | 手动编辑档案文档 | 对话自然沉淀 |
|
|
723
|
+
| 结构化程度 | 强(schema 约束) | 弱(LLM 理解) |
|
|
724
|
+
| 内核侵入性 | 高(需新模块) | 低(复用现有机制) |
|
|
725
|
+
|
|
726
|
+
**Memora 选择"涌现驱动"的核心理由**:
|
|
727
|
+
1. **单一真理源**:偏好从对话中涌现,而非外部注入,避免双写冲突
|
|
728
|
+
2. **自然生长**:不预埋用户画像结构,符合"种子决定长势、土壤决定养分"哲学
|
|
729
|
+
3. **零新增模块**:复用现有记忆/召回机制
|
|
730
|
+
|
|
731
|
+
### 宿主实现方案
|
|
732
|
+
|
|
733
|
+
如果宿主确实需要"预配置用户身份"的场景(如"我叫张三、后端工程师、偏好 Go 语言"),可以通过以下两种方式扩展,**内核零改动**。
|
|
734
|
+
|
|
735
|
+
#### 方案一:工具注册(LLM 按需查询)
|
|
736
|
+
|
|
737
|
+
适合场景:用户身份信息在对话中被 LLM 按需查询。
|
|
738
|
+
|
|
739
|
+
```typescript
|
|
740
|
+
// 宿主实现用户档案读取逻辑
|
|
741
|
+
async function loadUserProfile(): Promise<Record<string, unknown>> {
|
|
742
|
+
// 从文件、数据库或环境变量读取
|
|
743
|
+
return {
|
|
744
|
+
name: '张三',
|
|
745
|
+
role: '后端工程师',
|
|
746
|
+
preferredLanguage: 'zh-CN',
|
|
747
|
+
codingLanguage: 'Go',
|
|
748
|
+
// ...其他用户信息
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
// 注册为工具,LLM 需要时主动调用
|
|
753
|
+
agent.tools.registerTool(
|
|
754
|
+
{
|
|
755
|
+
name: 'read_user_profile',
|
|
756
|
+
description: '读取当前用户的档案信息(姓名、角色、偏好等)',
|
|
757
|
+
parameters: {
|
|
758
|
+
type: 'object',
|
|
759
|
+
properties: {}, // 无参数
|
|
760
|
+
},
|
|
761
|
+
},
|
|
762
|
+
async () => {
|
|
763
|
+
const profile = await loadUserProfile();
|
|
764
|
+
return `用户档案:姓名=${profile.name},角色=${profile.role},偏好语言=${profile.preferredLanguage}`;
|
|
765
|
+
},
|
|
766
|
+
);
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
#### 方案二:复用 `agent.injectAffect()` 固定注入(设计定案)
|
|
770
|
+
|
|
771
|
+
适合场景:用户身份 / 基础设定需要**始终在上下文中**,且与角色包解耦(切换角色不丢失)。
|
|
772
|
+
|
|
773
|
+
内核公开 API `agent.injectAffect(text)`(见 [API 参考手册](./memora-api-reference.md) §十二 完整 API 一览·角色条目)是「宿主可控的 system prompt 固定文本槽」:文本原样插在**角色包 prompt 与 bootstrap 记忆之间**,角色切换不清除、实时重建,传空串清除。名字虽沿用"情感基调",机制即通用文本注入,正适合承载用户基础设定。
|
|
774
|
+
|
|
775
|
+
```typescript
|
|
776
|
+
// 宿主启动装配、agent.init() 完成后调用一次(内存态——每次启动从宿主自有存储读取后注入)
|
|
777
|
+
async function loadUserProfile(): Promise<{
|
|
778
|
+
name: string;
|
|
779
|
+
role?: string;
|
|
780
|
+
background?: string;
|
|
781
|
+
preferences?: string[];
|
|
782
|
+
} | null> {
|
|
783
|
+
// 宿主实现:文件 / SQLite / 环境变量均可
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
const profile = await loadUserProfile();
|
|
787
|
+
if (profile) {
|
|
788
|
+
agent.injectAffect(
|
|
789
|
+
[
|
|
790
|
+
'【用户基础设定】',
|
|
791
|
+
`姓名:${profile.name}`,
|
|
792
|
+
`角色:${profile.role ?? '未指定'}`,
|
|
793
|
+
`背景:${profile.background ?? '未指定'}`,
|
|
794
|
+
`偏好:${profile.preferences?.join('、') ?? '无'}`,
|
|
795
|
+
].join('\n'),
|
|
796
|
+
);
|
|
797
|
+
}
|
|
798
|
+
// 需要清除时:agent.injectAffect('');
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
### 两种方案对比
|
|
802
|
+
|
|
803
|
+
| 维度 | 方案一:工具注册 | 方案二:injectAffect 固定注入 |
|
|
804
|
+
|------|---------------|-------------------|
|
|
805
|
+
| 触发方式 | LLM 按需调用 | 装配时注入一次,始终在上下文 |
|
|
806
|
+
| Token 效率 | 高(仅需要时消耗) | 低-中(每轮随 system prompt 携带) |
|
|
807
|
+
| 实现复杂度 | 低 | 低 |
|
|
808
|
+
| 适用场景 | 身份信息偶尔被查询 | 身份信息必须始终可见、且与角色解耦 |
|
|
809
|
+
|
|
810
|
+
### 用户档案文件格式示例
|
|
811
|
+
|
|
812
|
+
宿主可以使用任意格式存储用户档案,推荐 JSON 或 Markdown:
|
|
813
|
+
|
|
814
|
+
**`user-profile.json`**
|
|
815
|
+
```json
|
|
816
|
+
{
|
|
817
|
+
"name": "张三",
|
|
818
|
+
"role": "后端工程师",
|
|
819
|
+
"background": "5 年 Go 开发经验,熟悉微服务架构",
|
|
820
|
+
"preferences": ["简洁回答", "中文沟通", "代码优先"]
|
|
821
|
+
}
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
**`user-profile.md`**
|
|
825
|
+
```markdown
|
|
826
|
+
# 用户档案
|
|
827
|
+
|
|
828
|
+
- **姓名**:张三
|
|
829
|
+
- **角色**:后端工程师
|
|
830
|
+
- **背景**:5 年 Go 开发经验,熟悉微服务架构
|
|
831
|
+
- **偏好**:简洁回答、中文沟通、代码优先
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
### 核心约束
|
|
835
|
+
|
|
836
|
+
1. **用户档案完全由宿主管理**:存储、更新、版本管理
|
|
837
|
+
2. **内核零新增**:不新增存储、不新增 API——方案二复用现有公开方法 `agent.injectAffect()`,仅以文本形式注入,内核不感知"档案"语义
|
|
838
|
+
3. **不注入时零影响**:未实现用户档案的宿主,Agent 行为不变
|
|
839
|
+
4. **偏好记忆仍走涌现路径**:对话中涌现的偏好(如"用户喜欢简洁回答")仍通过 `preference` 摘要沉淀,用户档案仅承载**静态/半静态身份信息**
|
|
840
|
+
|
|
841
|
+
---
|
|
842
|
+
|
|
843
|
+
> 更多细节参见 [memora-api-reference.md](./memora-api-reference.md)(完整 API 参考)
|