@strands-agents/sdk 1.4.0 → 1.5.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/README.md +11 -11
- package/dist/src/__fixtures__/agent-helpers.d.ts.map +1 -1
- package/dist/src/__fixtures__/agent-helpers.js +6 -0
- package/dist/src/__fixtures__/agent-helpers.js.map +1 -1
- package/dist/src/__fixtures__/register-node-defaults.d.ts +2 -0
- package/dist/src/__fixtures__/register-node-defaults.d.ts.map +1 -0
- package/dist/src/__fixtures__/register-node-defaults.js +6 -0
- package/dist/src/__fixtures__/register-node-defaults.js.map +1 -0
- package/dist/src/__fixtures__/test-sandbox.node.d.ts.map +1 -1
- package/dist/src/__fixtures__/test-sandbox.node.js +4 -3
- package/dist/src/__fixtures__/test-sandbox.node.js.map +1 -1
- package/dist/src/__tests__/default-slot.test.d.ts +2 -0
- package/dist/src/__tests__/default-slot.test.d.ts.map +1 -0
- package/dist/src/__tests__/default-slot.test.js +33 -0
- package/dist/src/__tests__/default-slot.test.js.map +1 -0
- package/dist/src/a2a/__tests__/async-lock.test.d.ts +2 -0
- package/dist/src/a2a/__tests__/async-lock.test.d.ts.map +1 -0
- package/dist/src/a2a/__tests__/async-lock.test.js +137 -0
- package/dist/src/a2a/__tests__/async-lock.test.js.map +1 -0
- package/dist/src/a2a/__tests__/executor.test.js +146 -8
- package/dist/src/a2a/__tests__/executor.test.js.map +1 -1
- package/dist/src/a2a/__tests__/server.test.js +20 -0
- package/dist/src/a2a/__tests__/server.test.js.map +1 -1
- package/dist/src/a2a/async-lock.d.ts +22 -0
- package/dist/src/a2a/async-lock.d.ts.map +1 -0
- package/dist/src/a2a/async-lock.js +38 -0
- package/dist/src/a2a/async-lock.js.map +1 -0
- package/dist/src/a2a/executor.d.ts +59 -24
- package/dist/src/a2a/executor.d.ts.map +1 -1
- package/dist/src/a2a/executor.js +209 -32
- package/dist/src/a2a/executor.js.map +1 -1
- package/dist/src/a2a/index.d.ts +1 -1
- package/dist/src/a2a/index.d.ts.map +1 -1
- package/dist/src/a2a/index.js +1 -1
- package/dist/src/a2a/index.js.map +1 -1
- package/dist/src/a2a/server.d.ts +18 -2
- package/dist/src/a2a/server.d.ts.map +1 -1
- package/dist/src/a2a/server.js +13 -2
- package/dist/src/a2a/server.js.map +1 -1
- package/dist/src/agent/__tests__/agent.context-manager.test.d.ts +2 -0
- package/dist/src/agent/__tests__/agent.context-manager.test.d.ts.map +1 -0
- package/dist/src/agent/__tests__/agent.context-manager.test.js +107 -0
- package/dist/src/agent/__tests__/agent.context-manager.test.js.map +1 -0
- package/dist/src/agent/__tests__/agent.tracer.test.node.js +14 -0
- package/dist/src/agent/__tests__/agent.tracer.test.node.js.map +1 -1
- package/dist/src/agent/agent.d.ts +132 -2
- package/dist/src/agent/agent.d.ts.map +1 -1
- package/dist/src/agent/agent.js +478 -188
- package/dist/src/agent/agent.js.map +1 -1
- package/dist/src/conversation-manager/__tests__/pin.test.d.ts +2 -0
- package/dist/src/conversation-manager/__tests__/pin.test.d.ts.map +1 -0
- package/dist/src/conversation-manager/__tests__/pin.test.js +119 -0
- package/dist/src/conversation-manager/__tests__/pin.test.js.map +1 -0
- package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.js +49 -0
- package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.js.map +1 -1
- package/dist/src/conversation-manager/__tests__/summarizing-conversation-manager.test.js +58 -0
- package/dist/src/conversation-manager/__tests__/summarizing-conversation-manager.test.js.map +1 -1
- package/dist/src/conversation-manager/pin-message.d.ts +45 -0
- package/dist/src/conversation-manager/pin-message.d.ts.map +1 -0
- package/dist/src/conversation-manager/pin-message.js +106 -0
- package/dist/src/conversation-manager/pin-message.js.map +1 -0
- package/dist/src/conversation-manager/sliding-window-conversation-manager.d.ts +7 -0
- package/dist/src/conversation-manager/sliding-window-conversation-manager.d.ts.map +1 -1
- package/dist/src/conversation-manager/sliding-window-conversation-manager.js +27 -4
- package/dist/src/conversation-manager/sliding-window-conversation-manager.js.map +1 -1
- package/dist/src/conversation-manager/summarizing-conversation-manager.d.ts +7 -0
- package/dist/src/conversation-manager/summarizing-conversation-manager.d.ts.map +1 -1
- package/dist/src/conversation-manager/summarizing-conversation-manager.js +18 -4
- package/dist/src/conversation-manager/summarizing-conversation-manager.js.map +1 -1
- package/dist/src/default-slot.d.ts +6 -0
- package/dist/src/default-slot.d.ts.map +1 -0
- package/dist/src/default-slot.js +18 -0
- package/dist/src/default-slot.js.map +1 -0
- package/dist/src/errors.d.ts +8 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +11 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +8 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/index.node.d.ts +2 -0
- package/dist/src/index.node.d.ts.map +1 -0
- package/dist/src/index.node.js +9 -0
- package/dist/src/index.node.js.map +1 -0
- package/dist/src/interrupt.d.ts +5 -1
- package/dist/src/interrupt.d.ts.map +1 -1
- package/dist/src/interrupt.js +6 -0
- package/dist/src/interrupt.js.map +1 -1
- package/dist/src/memory/__tests__/memory-manager.test.d.ts +2 -0
- package/dist/src/memory/__tests__/memory-manager.test.d.ts.map +1 -0
- package/dist/src/memory/__tests__/memory-manager.test.js +493 -0
- package/dist/src/memory/__tests__/memory-manager.test.js.map +1 -0
- package/dist/src/memory/extraction/__tests__/extraction.test.d.ts +2 -0
- package/dist/src/memory/extraction/__tests__/extraction.test.d.ts.map +1 -0
- package/dist/src/memory/extraction/__tests__/extraction.test.js +637 -0
- package/dist/src/memory/extraction/__tests__/extraction.test.js.map +1 -0
- package/dist/src/memory/extraction/__tests__/model-extractor.test.d.ts +2 -0
- package/dist/src/memory/extraction/__tests__/model-extractor.test.d.ts.map +1 -0
- package/dist/src/memory/extraction/__tests__/model-extractor.test.js +68 -0
- package/dist/src/memory/extraction/__tests__/model-extractor.test.js.map +1 -0
- package/dist/src/memory/extraction/__tests__/resolve-extraction-config.test.d.ts +2 -0
- package/dist/src/memory/extraction/__tests__/resolve-extraction-config.test.d.ts.map +1 -0
- package/dist/src/memory/extraction/__tests__/resolve-extraction-config.test.js +81 -0
- package/dist/src/memory/extraction/__tests__/resolve-extraction-config.test.js.map +1 -0
- package/dist/src/memory/extraction/coordinator.d.ts +128 -0
- package/dist/src/memory/extraction/coordinator.d.ts.map +1 -0
- package/dist/src/memory/extraction/coordinator.js +245 -0
- package/dist/src/memory/extraction/coordinator.js.map +1 -0
- package/dist/src/memory/extraction/model-extractor.d.ts +32 -0
- package/dist/src/memory/extraction/model-extractor.d.ts.map +1 -0
- package/dist/src/memory/extraction/model-extractor.js +118 -0
- package/dist/src/memory/extraction/model-extractor.js.map +1 -0
- package/dist/src/memory/extraction/resolve-extraction-config.d.ts +46 -0
- package/dist/src/memory/extraction/resolve-extraction-config.d.ts.map +1 -0
- package/dist/src/memory/extraction/resolve-extraction-config.js +59 -0
- package/dist/src/memory/extraction/resolve-extraction-config.js.map +1 -0
- package/dist/src/memory/extraction/triggers.d.ts +41 -0
- package/dist/src/memory/extraction/triggers.d.ts.map +1 -0
- package/dist/src/memory/extraction/triggers.js +59 -0
- package/dist/src/memory/extraction/triggers.js.map +1 -0
- package/dist/src/memory/extraction/types.d.ts +133 -0
- package/dist/src/memory/extraction/types.d.ts.map +1 -0
- package/dist/src/memory/extraction/types.js +19 -0
- package/dist/src/memory/extraction/types.js.map +1 -0
- package/dist/src/memory/index.d.ts +9 -0
- package/dist/src/memory/index.d.ts.map +1 -0
- package/dist/src/memory/index.js +5 -0
- package/dist/src/memory/index.js.map +1 -0
- package/dist/src/memory/memory-manager.d.ts +131 -0
- package/dist/src/memory/memory-manager.d.ts.map +1 -0
- package/dist/src/memory/memory-manager.js +404 -0
- package/dist/src/memory/memory-manager.js.map +1 -0
- package/dist/src/memory/types.d.ts +213 -0
- package/dist/src/memory/types.d.ts.map +1 -0
- package/dist/src/memory/types.js +2 -0
- package/dist/src/memory/types.js.map +1 -0
- package/dist/src/middleware/__tests__/agent-middleware.test.d.ts +2 -0
- package/dist/src/middleware/__tests__/agent-middleware.test.d.ts.map +1 -0
- package/dist/src/middleware/__tests__/agent-middleware.test.js +1207 -0
- package/dist/src/middleware/__tests__/agent-middleware.test.js.map +1 -0
- package/dist/src/middleware/__tests__/custom-stages.test.d.ts +2 -0
- package/dist/src/middleware/__tests__/custom-stages.test.d.ts.map +1 -0
- package/dist/src/middleware/__tests__/custom-stages.test.js +97 -0
- package/dist/src/middleware/__tests__/custom-stages.test.js.map +1 -0
- package/dist/src/middleware/__tests__/middleware-interrupts.test.d.ts +2 -0
- package/dist/src/middleware/__tests__/middleware-interrupts.test.d.ts.map +1 -0
- package/dist/src/middleware/__tests__/middleware-interrupts.test.js +267 -0
- package/dist/src/middleware/__tests__/middleware-interrupts.test.js.map +1 -0
- package/dist/src/middleware/__tests__/registry.test.d.ts +2 -0
- package/dist/src/middleware/__tests__/registry.test.d.ts.map +1 -0
- package/dist/src/middleware/__tests__/registry.test.js +525 -0
- package/dist/src/middleware/__tests__/registry.test.js.map +1 -0
- package/dist/src/middleware/index.d.ts +5 -0
- package/dist/src/middleware/index.d.ts.map +1 -0
- package/dist/src/middleware/index.js +3 -0
- package/dist/src/middleware/index.js.map +1 -0
- package/dist/src/middleware/registry.d.ts +58 -0
- package/dist/src/middleware/registry.d.ts.map +1 -0
- package/dist/src/middleware/registry.js +107 -0
- package/dist/src/middleware/registry.js.map +1 -0
- package/dist/src/middleware/stages.d.ts +138 -0
- package/dist/src/middleware/stages.d.ts.map +1 -0
- package/dist/src/middleware/stages.js +31 -0
- package/dist/src/middleware/stages.js.map +1 -0
- package/dist/src/middleware/types.d.ts +88 -0
- package/dist/src/middleware/types.d.ts.map +1 -0
- package/dist/src/middleware/types.js +2 -0
- package/dist/src/middleware/types.js.map +1 -0
- package/dist/src/models/__tests__/anthropic.test.js +16 -1
- package/dist/src/models/__tests__/anthropic.test.js.map +1 -1
- package/dist/src/models/__tests__/bedrock.test.js +39 -0
- package/dist/src/models/__tests__/bedrock.test.js.map +1 -1
- package/dist/src/models/__tests__/model.test.js +46 -3
- package/dist/src/models/__tests__/model.test.js.map +1 -1
- package/dist/src/models/anthropic.js +2 -2
- package/dist/src/models/anthropic.js.map +1 -1
- package/dist/src/models/bedrock.d.ts.map +1 -1
- package/dist/src/models/bedrock.js +12 -5
- package/dist/src/models/bedrock.js.map +1 -1
- package/dist/src/models/defaults.d.ts.map +1 -1
- package/dist/src/models/defaults.js +2 -0
- package/dist/src/models/defaults.js.map +1 -1
- package/dist/src/models/model.d.ts.map +1 -1
- package/dist/src/models/model.js +7 -3
- package/dist/src/models/model.js.map +1 -1
- package/dist/src/models/openai/__tests__/responses.test.js +8 -14
- package/dist/src/models/openai/__tests__/responses.test.js.map +1 -1
- package/dist/src/sandbox/__tests__/default.test.browser.d.ts +2 -0
- package/dist/src/sandbox/__tests__/default.test.browser.d.ts.map +1 -0
- package/dist/src/sandbox/__tests__/default.test.browser.js +11 -0
- package/dist/src/sandbox/__tests__/default.test.browser.js.map +1 -0
- package/dist/src/sandbox/__tests__/default.test.node.d.ts +2 -0
- package/dist/src/sandbox/__tests__/default.test.node.d.ts.map +1 -0
- package/dist/src/sandbox/__tests__/default.test.node.js +23 -0
- package/dist/src/sandbox/__tests__/default.test.node.js.map +1 -0
- package/dist/src/sandbox/__tests__/docker.test.node.d.ts +2 -0
- package/dist/src/sandbox/__tests__/docker.test.node.d.ts.map +1 -0
- package/dist/src/sandbox/__tests__/docker.test.node.js +89 -0
- package/dist/src/sandbox/__tests__/docker.test.node.js.map +1 -0
- package/dist/src/sandbox/__tests__/errors.test.node.d.ts +2 -0
- package/dist/src/sandbox/__tests__/errors.test.node.d.ts.map +1 -0
- package/dist/src/sandbox/__tests__/errors.test.node.js +33 -0
- package/dist/src/sandbox/__tests__/errors.test.node.js.map +1 -0
- package/dist/src/sandbox/__tests__/not-a-sandbox-local-environment.test.node.d.ts +2 -0
- package/dist/src/sandbox/__tests__/not-a-sandbox-local-environment.test.node.d.ts.map +1 -0
- package/dist/src/sandbox/__tests__/not-a-sandbox-local-environment.test.node.js +124 -0
- package/dist/src/sandbox/__tests__/not-a-sandbox-local-environment.test.node.js.map +1 -0
- package/dist/src/sandbox/__tests__/posix-shell.test.node.js +50 -4
- package/dist/src/sandbox/__tests__/posix-shell.test.node.js.map +1 -1
- package/dist/src/sandbox/__tests__/ssh.test.node.d.ts +2 -0
- package/dist/src/sandbox/__tests__/ssh.test.node.d.ts.map +1 -0
- package/dist/src/sandbox/__tests__/ssh.test.node.js +262 -0
- package/dist/src/sandbox/__tests__/ssh.test.node.js.map +1 -0
- package/dist/src/sandbox/base.d.ts +22 -4
- package/dist/src/sandbox/base.d.ts.map +1 -1
- package/dist/src/sandbox/base.js +15 -2
- package/dist/src/sandbox/base.js.map +1 -1
- package/dist/src/sandbox/constants.d.ts +18 -0
- package/dist/src/sandbox/constants.d.ts.map +1 -1
- package/dist/src/sandbox/constants.js +20 -0
- package/dist/src/sandbox/constants.js.map +1 -1
- package/dist/src/sandbox/default.d.ts +3 -0
- package/dist/src/sandbox/default.d.ts.map +1 -0
- package/dist/src/sandbox/default.js +3 -0
- package/dist/src/sandbox/default.js.map +1 -0
- package/dist/src/sandbox/docker.d.ts +38 -0
- package/dist/src/sandbox/docker.d.ts.map +1 -0
- package/dist/src/sandbox/docker.js +59 -0
- package/dist/src/sandbox/docker.js.map +1 -0
- package/dist/src/sandbox/errors.d.ts +26 -0
- package/dist/src/sandbox/errors.d.ts.map +1 -0
- package/dist/src/sandbox/errors.js +35 -0
- package/dist/src/sandbox/errors.js.map +1 -0
- package/dist/src/sandbox/index.d.ts +5 -0
- package/dist/src/sandbox/index.d.ts.map +1 -0
- package/dist/src/sandbox/index.js +4 -0
- package/dist/src/sandbox/index.js.map +1 -0
- package/dist/src/sandbox/not-a-sandbox-local-environment.d.ts +16 -0
- package/dist/src/sandbox/not-a-sandbox-local-environment.d.ts.map +1 -0
- package/dist/src/sandbox/not-a-sandbox-local-environment.js +83 -0
- package/dist/src/sandbox/not-a-sandbox-local-environment.js.map +1 -0
- package/dist/src/sandbox/posix-shell.d.ts +21 -0
- package/dist/src/sandbox/posix-shell.d.ts.map +1 -1
- package/dist/src/sandbox/posix-shell.js +41 -3
- package/dist/src/sandbox/posix-shell.js.map +1 -1
- package/dist/src/sandbox/ssh.d.ts +56 -0
- package/dist/src/sandbox/ssh.d.ts.map +1 -0
- package/dist/src/sandbox/ssh.js +119 -0
- package/dist/src/sandbox/ssh.js.map +1 -0
- package/dist/src/sandbox/stream-process.d.ts.map +1 -1
- package/dist/src/sandbox/stream-process.js +3 -2
- package/dist/src/sandbox/stream-process.js.map +1 -1
- package/dist/src/tsconfig.tsbuildinfo +1 -1
- package/dist/src/types/agent.d.ts +21 -0
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/agent.js.map +1 -1
- package/dist/src/types/messages.d.ts +1 -1
- package/dist/src/types/messages.d.ts.map +1 -1
- package/dist/src/types/messages.js.map +1 -1
- package/dist/src/vended-memory-stores/bedrock-knowledge-base/__tests__/bedrock-knowledge-base-store.test.d.ts +2 -0
- package/dist/src/vended-memory-stores/bedrock-knowledge-base/__tests__/bedrock-knowledge-base-store.test.d.ts.map +1 -0
- package/dist/src/vended-memory-stores/bedrock-knowledge-base/__tests__/bedrock-knowledge-base-store.test.js +611 -0
- package/dist/src/vended-memory-stores/bedrock-knowledge-base/__tests__/bedrock-knowledge-base-store.test.js.map +1 -0
- package/dist/src/vended-memory-stores/bedrock-knowledge-base/index.d.ts +2 -0
- package/dist/src/vended-memory-stores/bedrock-knowledge-base/index.d.ts.map +1 -0
- package/dist/src/vended-memory-stores/bedrock-knowledge-base/index.js +2 -0
- package/dist/src/vended-memory-stores/bedrock-knowledge-base/index.js.map +1 -0
- package/dist/src/vended-memory-stores/bedrock-knowledge-base/store.d.ts +230 -0
- package/dist/src/vended-memory-stores/bedrock-knowledge-base/store.d.ts.map +1 -0
- package/dist/src/vended-memory-stores/bedrock-knowledge-base/store.js +370 -0
- package/dist/src/vended-memory-stores/bedrock-knowledge-base/store.js.map +1 -0
- package/dist/src/vended-plugins/context-offloader/__tests__/file-storage-sandbox.test.node.d.ts +2 -0
- package/dist/src/vended-plugins/context-offloader/__tests__/file-storage-sandbox.test.node.d.ts.map +1 -0
- package/dist/src/vended-plugins/context-offloader/__tests__/file-storage-sandbox.test.node.js +68 -0
- package/dist/src/vended-plugins/context-offloader/__tests__/file-storage-sandbox.test.node.js.map +1 -0
- package/dist/src/vended-plugins/context-offloader/__tests__/plugin.test.node.d.ts +2 -0
- package/dist/src/vended-plugins/context-offloader/__tests__/plugin.test.node.d.ts.map +1 -0
- package/dist/src/vended-plugins/context-offloader/__tests__/plugin.test.node.js +93 -0
- package/dist/src/vended-plugins/context-offloader/__tests__/plugin.test.node.js.map +1 -0
- package/dist/src/vended-plugins/context-offloader/index.d.ts +1 -1
- package/dist/src/vended-plugins/context-offloader/index.d.ts.map +1 -1
- package/dist/src/vended-plugins/context-offloader/plugin.d.ts +4 -1
- package/dist/src/vended-plugins/context-offloader/plugin.d.ts.map +1 -1
- package/dist/src/vended-plugins/context-offloader/plugin.js +29 -7
- package/dist/src/vended-plugins/context-offloader/plugin.js.map +1 -1
- package/dist/src/vended-plugins/context-offloader/search.d.ts.map +1 -1
- package/dist/src/vended-plugins/context-offloader/search.js +3 -5
- package/dist/src/vended-plugins/context-offloader/search.js.map +1 -1
- package/dist/src/vended-plugins/context-offloader/storage.d.ts +29 -5
- package/dist/src/vended-plugins/context-offloader/storage.d.ts.map +1 -1
- package/dist/src/vended-plugins/context-offloader/storage.js +75 -11
- package/dist/src/vended-plugins/context-offloader/storage.js.map +1 -1
- package/dist/src/vended-plugins/goal/__tests__/plugin.test.d.ts +2 -0
- package/dist/src/vended-plugins/goal/__tests__/plugin.test.d.ts.map +1 -0
- package/dist/src/vended-plugins/goal/__tests__/plugin.test.js +736 -0
- package/dist/src/vended-plugins/goal/__tests__/plugin.test.js.map +1 -0
- package/dist/src/vended-plugins/goal/index.d.ts +21 -0
- package/dist/src/vended-plugins/goal/index.d.ts.map +1 -0
- package/dist/src/vended-plugins/goal/index.js +20 -0
- package/dist/src/vended-plugins/goal/index.js.map +1 -0
- package/dist/src/vended-plugins/goal/judge.d.ts +41 -0
- package/dist/src/vended-plugins/goal/judge.d.ts.map +1 -0
- package/dist/src/vended-plugins/goal/judge.js +92 -0
- package/dist/src/vended-plugins/goal/judge.js.map +1 -0
- package/dist/src/vended-plugins/goal/plugin.d.ts +214 -0
- package/dist/src/vended-plugins/goal/plugin.d.ts.map +1 -0
- package/dist/src/vended-plugins/goal/plugin.js +287 -0
- package/dist/src/vended-plugins/goal/plugin.js.map +1 -0
- package/dist/src/vended-plugins/index.d.ts +2 -1
- package/dist/src/vended-plugins/index.d.ts.map +1 -1
- package/dist/src/vended-plugins/index.js +2 -1
- package/dist/src/vended-plugins/index.js.map +1 -1
- package/dist/src/vended-plugins/skills/__tests__/agent-skills.test.node.js +17 -7
- package/dist/src/vended-plugins/skills/__tests__/agent-skills.test.node.js.map +1 -1
- package/dist/src/vended-plugins/skills/agent-skills.d.ts +21 -7
- package/dist/src/vended-plugins/skills/agent-skills.d.ts.map +1 -1
- package/dist/src/vended-plugins/skills/agent-skills.js +144 -77
- package/dist/src/vended-plugins/skills/agent-skills.js.map +1 -1
- package/dist/src/vended-tools/bash/__tests__/bash.test.node.js +44 -4
- package/dist/src/vended-tools/bash/__tests__/bash.test.node.js.map +1 -1
- package/dist/src/vended-tools/bash/bash.d.ts +3 -24
- package/dist/src/vended-tools/bash/bash.d.ts.map +1 -1
- package/dist/src/vended-tools/bash/bash.js +9 -9
- package/dist/src/vended-tools/bash/bash.js.map +1 -1
- package/dist/src/vended-tools/bash/index.d.ts +3 -1
- package/dist/src/vended-tools/bash/index.d.ts.map +1 -1
- package/dist/src/vended-tools/bash/index.js +2 -1
- package/dist/src/vended-tools/bash/index.js.map +1 -1
- package/dist/src/vended-tools/bash/make-bash.d.ts +22 -0
- package/dist/src/vended-tools/bash/make-bash.d.ts.map +1 -0
- package/dist/src/vended-tools/bash/make-bash.js +40 -0
- package/dist/src/vended-tools/bash/make-bash.js.map +1 -0
- package/dist/src/vended-tools/bash/types.d.ts +1 -0
- package/dist/src/vended-tools/bash/types.d.ts.map +1 -1
- package/dist/src/vended-tools/bash/types.js +2 -0
- package/dist/src/vended-tools/bash/types.js.map +1 -1
- package/dist/src/vended-tools/file-editor/__tests__/file-editor.test.node.js +83 -1
- package/dist/src/vended-tools/file-editor/__tests__/file-editor.test.node.js.map +1 -1
- package/dist/src/vended-tools/file-editor/file-editor.d.ts +19 -10
- package/dist/src/vended-tools/file-editor/file-editor.d.ts.map +1 -1
- package/dist/src/vended-tools/file-editor/file-editor.js +188 -218
- package/dist/src/vended-tools/file-editor/file-editor.js.map +1 -1
- package/dist/src/vended-tools/file-editor/index.d.ts +2 -1
- package/dist/src/vended-tools/file-editor/index.d.ts.map +1 -1
- package/dist/src/vended-tools/file-editor/index.js +1 -1
- package/dist/src/vended-tools/file-editor/index.js.map +1 -1
- package/package.json +41 -6
- package/dist/src/utils/shell-quote.d.ts +0 -12
- package/dist/src/utils/shell-quote.d.ts.map +0 -1
- package/dist/src/utils/shell-quote.js +0 -14
- package/dist/src/utils/shell-quote.js.map +0 -1
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { logger } from '../../logging/logger.js';
|
|
2
|
+
import { normalizeError } from '../../errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* Number of consecutive save failures after which a store backs off (stops trying every turn).
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export const SAVE_FAILURES_BEFORE_BACKOFF = 10;
|
|
8
|
+
/**
|
|
9
|
+
* While backed off, a store retries only once every this many save attempts (a probe).
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
export const BACKOFF_PROBE_INTERVAL = 3;
|
|
13
|
+
/** The kind of a content block (e.g. 'text', 'toolUse'), used to match it against a filter. */
|
|
14
|
+
function _blockKind(block) {
|
|
15
|
+
// A text block is `{ text: string }`; every other block is a single-key wrapper (`{ toolUse }`, …).
|
|
16
|
+
if ('text' in block)
|
|
17
|
+
return 'text';
|
|
18
|
+
return Object.keys(block)[0] ?? '';
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Removes excluded content blocks, and drops any message left empty. Does not mutate the input.
|
|
22
|
+
* Carries each message's sequence number through so it stays aligned with the filtered batch.
|
|
23
|
+
*/
|
|
24
|
+
function _filterMessages(buffered, filter) {
|
|
25
|
+
const exclude = new Set(filter.exclude);
|
|
26
|
+
const result = [];
|
|
27
|
+
for (const { seq, message } of buffered) {
|
|
28
|
+
const content = message.content.filter((block) => !exclude.has(_blockKind(block)));
|
|
29
|
+
if (content.length > 0) {
|
|
30
|
+
result.push({
|
|
31
|
+
seq,
|
|
32
|
+
message: {
|
|
33
|
+
role: message.role,
|
|
34
|
+
content,
|
|
35
|
+
...(message.metadata !== undefined && { metadata: message.metadata }),
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Saves conversation messages to memory stores, in the background, without slowing the agent down.
|
|
44
|
+
*
|
|
45
|
+
* How it works, in three pieces:
|
|
46
|
+
*
|
|
47
|
+
* 1. **The buffer.** Every message the agent produces is copied into one shared list (`_pending`).
|
|
48
|
+
* Each gets a number (`seq`) that only ever counts up, so we can tell which messages are newer.
|
|
49
|
+
* We keep our own copy here (rather than reading the agent's live message list) because the agent
|
|
50
|
+
* can delete old messages to stay within its context window; our copy means we never lose one
|
|
51
|
+
* before it's saved.
|
|
52
|
+
*
|
|
53
|
+
* 2. **Per-store progress.** Each store can save at its own pace, so we remember, per store, the
|
|
54
|
+
* `seq` of the last message it has already saved (`_marks`). When a store saves, it only looks at
|
|
55
|
+
* messages newer than that number, so the same message is never saved twice to the same store.
|
|
56
|
+
*
|
|
57
|
+
* 3. **One save at a time per store.** A store might be asked to save again while a previous save is
|
|
58
|
+
* still running. We chain each store's saves one after another (`_chains`) so they can't overlap
|
|
59
|
+
* or run out of order.
|
|
60
|
+
*
|
|
61
|
+
* If a store fails to save {@link SAVE_FAILURES_BEFORE_BACKOFF} times in a row, it backs off: instead
|
|
62
|
+
* of trying every turn, it retries only once every {@link BACKOFF_PROBE_INTERVAL} attempts (a probe).
|
|
63
|
+
* A successful probe clears the failure streak and resumes normal saving - so a transient outage
|
|
64
|
+
* recovers on its own and the messages buffered during it are saved once the store comes back. A
|
|
65
|
+
* permanently broken store keeps probing and logs an error each time, surfacing the misconfiguration.
|
|
66
|
+
*
|
|
67
|
+
* Saving itself either runs the store's extractor to pull out facts, or hands the raw messages to the
|
|
68
|
+
* store - see {@link _write}.
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
export class ExtractionCoordinator {
|
|
72
|
+
_stores;
|
|
73
|
+
/** Per store: its resolved extraction config (triggers, extractor, filter). */
|
|
74
|
+
_storeToExtractionConfig = new Map();
|
|
75
|
+
_defaultModel;
|
|
76
|
+
/** The shared list of messages waiting to be saved, oldest first. Each is tagged with its `seq`. */
|
|
77
|
+
_pending = [];
|
|
78
|
+
/** The number to give the next message added to the buffer. Only ever increases. */
|
|
79
|
+
_nextSeq = 0;
|
|
80
|
+
/** Per store: the `seq` of the last message that store has already saved. Starts at -1 (saved none). */
|
|
81
|
+
_marks = new Map();
|
|
82
|
+
/** Per store: a promise for that store's currently-running save, so the next save waits its turn. */
|
|
83
|
+
_chains = new Map();
|
|
84
|
+
/** Per store: how many saves have failed in a row. Reset to 0 on a successful save. */
|
|
85
|
+
_consecutiveFailures = new Map();
|
|
86
|
+
/** Per store: while backed off, counts save requests so we can let every Nth through as a probe. */
|
|
87
|
+
_backoffCounters = new Map();
|
|
88
|
+
/**
|
|
89
|
+
* @param stores - The extraction-configured stores this coordinator manages, each with its resolved config
|
|
90
|
+
* @param defaultModel - The agent's model, passed to extractors that don't configure their own
|
|
91
|
+
*/
|
|
92
|
+
constructor(stores, defaultModel) {
|
|
93
|
+
this._stores = stores.map((s) => s.store);
|
|
94
|
+
this._defaultModel = defaultModel;
|
|
95
|
+
for (const { store, config } of stores) {
|
|
96
|
+
this._storeToExtractionConfig.set(store, config);
|
|
97
|
+
this._marks.set(store, -1);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/** Adds a message to the buffer. */
|
|
101
|
+
record(message) {
|
|
102
|
+
this._pending.push({ seq: this._nextSeq++, message });
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Saves this store's unsaved messages, in the background. Queued behind the store's previous save so
|
|
106
|
+
* two never run at once. Failures are logged and swallowed - saving must never break the agent loop.
|
|
107
|
+
* The returned promise is for {@link flush}; callers (triggers) ignore it so they don't block.
|
|
108
|
+
*/
|
|
109
|
+
process(store) {
|
|
110
|
+
if (!this._shouldAttempt(store)) {
|
|
111
|
+
return Promise.resolve();
|
|
112
|
+
}
|
|
113
|
+
return this._enqueue(store);
|
|
114
|
+
}
|
|
115
|
+
/** Queues a save for the store behind its previous one, so saves never overlap or reorder. */
|
|
116
|
+
_enqueue(store) {
|
|
117
|
+
const previous = this._chains.get(store) ?? Promise.resolve();
|
|
118
|
+
const next = previous.then(() => this._extract(store));
|
|
119
|
+
this._chains.set(store, next);
|
|
120
|
+
return next;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Whether to attempt a save now. A healthy store always attempts. A backed-off store (too many
|
|
124
|
+
* failures in a row) attempts only once every {@link BACKOFF_PROBE_INTERVAL} requests - a probe to
|
|
125
|
+
* see if it has recovered - and skips the rest.
|
|
126
|
+
*/
|
|
127
|
+
_shouldAttempt(store) {
|
|
128
|
+
if ((this._consecutiveFailures.get(store) ?? 0) < SAVE_FAILURES_BEFORE_BACKOFF) {
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
const count = (this._backoffCounters.get(store) ?? 0) + 1;
|
|
132
|
+
this._backoffCounters.set(store, count);
|
|
133
|
+
return count % BACKOFF_PROBE_INTERVAL === 0;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Saves every store's remaining messages and waits for all saves to finish. Call this once at a
|
|
137
|
+
* boundary you control - typically app shutdown - to make sure nothing in the buffer is lost.
|
|
138
|
+
*
|
|
139
|
+
* It first tells every store to save (even one whose trigger hasn't fired this turn, or one that is
|
|
140
|
+
* backed off - flush bypasses backoff so a recovered store still writes its backlog); stores with
|
|
141
|
+
* nothing to save do nothing. Then it waits, re-checking until no new save has started, so saves
|
|
142
|
+
* that begin while we're waiting are also covered.
|
|
143
|
+
*/
|
|
144
|
+
async flush() {
|
|
145
|
+
for (const store of this._stores) {
|
|
146
|
+
void this._enqueue(store);
|
|
147
|
+
}
|
|
148
|
+
for (;;) {
|
|
149
|
+
const inFlight = [...this._chains.values()];
|
|
150
|
+
await Promise.all(inFlight);
|
|
151
|
+
// If nothing new started while we waited, everything is done.
|
|
152
|
+
if (this._chains.size === inFlight.length && [...this._chains.values()].every((p, i) => p === inFlight[i])) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async _extract(store) {
|
|
158
|
+
const mark = this._marks.get(store) ?? -1;
|
|
159
|
+
const fresh = this._pending.filter((buffered) => buffered.seq > mark);
|
|
160
|
+
if (fresh.length === 0) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
// Mark these messages as saved before we start saving, so a queued save behind this one won't
|
|
164
|
+
// pick them up again. If the save fails we put the mark back (below) and they retry.
|
|
165
|
+
const highestSeq = fresh[fresh.length - 1].seq;
|
|
166
|
+
this._marks.set(store, highestSeq);
|
|
167
|
+
const filter = this._storeToExtractionConfig.get(store).filter;
|
|
168
|
+
const filtered = _filterMessages(fresh, filter);
|
|
169
|
+
try {
|
|
170
|
+
if (filtered.length > 0) {
|
|
171
|
+
await this._write(store, filtered);
|
|
172
|
+
// A successful write clears the failure streak and ends any backoff. Only a real write counts
|
|
173
|
+
// as recovery - a fully-filtered (empty) turn never touched the backend, so it leaves backoff
|
|
174
|
+
// state untouched (it still advances the mark above; those messages had nothing to save).
|
|
175
|
+
this._consecutiveFailures.set(store, 0);
|
|
176
|
+
this._backoffCounters.delete(store);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
this._onSaveFailed(store, mark, err);
|
|
181
|
+
}
|
|
182
|
+
finally {
|
|
183
|
+
this._trim();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Handles a failed save. Puts the mark back so the messages retry next time. Once a store has failed
|
|
188
|
+
* {@link SAVE_FAILURES_BEFORE_BACKOFF} times in a row it logs an error and enters backoff (it then
|
|
189
|
+
* retries only on probes - see {@link _shouldAttempt}); before that it logs a warning. The messages
|
|
190
|
+
* stay buffered either way, so a store that recovers saves them.
|
|
191
|
+
*/
|
|
192
|
+
_onSaveFailed(store, markBeforeSave, err) {
|
|
193
|
+
const failures = (this._consecutiveFailures.get(store) ?? 0) + 1;
|
|
194
|
+
this._consecutiveFailures.set(store, failures);
|
|
195
|
+
this._marks.set(store, markBeforeSave);
|
|
196
|
+
const reason = normalizeError(err).message;
|
|
197
|
+
if (failures >= SAVE_FAILURES_BEFORE_BACKOFF) {
|
|
198
|
+
logger.error(`store=<${store.name}>, failures=<${failures}>, reason=<${reason}> | memory store save failing repeatedly`);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
logger.warn(`store=<${store.name}>, reason=<${reason}> | memory extraction failed`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Saves the messages to the store, one of two ways:
|
|
206
|
+
* - store has an extractor: run it to pull out facts, then write each fact via `add`.
|
|
207
|
+
* - no extractor: hand the raw messages to `addMessages` so the store keeps their roles.
|
|
208
|
+
*
|
|
209
|
+
* Fact writes run in parallel. If any fails we throw, which makes the caller retry the whole batch
|
|
210
|
+
* next time - so a fact that already saved may be written again (stores should expect duplicates).
|
|
211
|
+
*/
|
|
212
|
+
async _write(store, buffered) {
|
|
213
|
+
const extractor = this._storeToExtractionConfig.get(store).extractor;
|
|
214
|
+
const messages = buffered.map((buffer) => buffer.message);
|
|
215
|
+
if (extractor) {
|
|
216
|
+
const entries = await extractor.extract(messages, { defaultModel: this._defaultModel });
|
|
217
|
+
const settled = await Promise.allSettled(entries.map((entry) => store.add(entry.content, entry.metadata)));
|
|
218
|
+
const failures = settled.filter((r) => r.status === 'rejected');
|
|
219
|
+
if (failures.length > 0) {
|
|
220
|
+
throw new AggregateError(failures.map((failure) => failure.reason), `failed to write ${failures.length} of ${entries.length} extracted entries`);
|
|
221
|
+
}
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
// Pass each message's sequence number so a store can build an idempotency key surviving retries.
|
|
225
|
+
await store.addMessages(messages, { sequenceNumbers: buffered.map((buffer) => buffer.seq) });
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Removes messages from the buffer once every store has saved them (so none still needs them).
|
|
229
|
+
*
|
|
230
|
+
* A store that hasn't saved a message yet - because its trigger hasn't fired, or it's failing and
|
|
231
|
+
* waiting to recover - keeps that message buffered. So a store stuck failing for good slowly grows
|
|
232
|
+
* the buffer; that surfaces as repeated error logs and is bounded by the (non-persisted) session.
|
|
233
|
+
*/
|
|
234
|
+
_trim() {
|
|
235
|
+
let minMark = Infinity;
|
|
236
|
+
for (const store of this._stores) {
|
|
237
|
+
minMark = Math.min(minMark, this._marks.get(store) ?? -1);
|
|
238
|
+
}
|
|
239
|
+
if (minMark === Infinity) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
this._pending = this._pending.filter((buffered) => buffered.seq > minMark);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=coordinator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinator.js","sourceRoot":"","sources":["../../../../src/memory/extraction/coordinator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type MessageData } from '../../types/messages.js';
|
|
2
|
+
import type { Model } from '../../models/model.js';
|
|
3
|
+
import type { ExtractionResult, Extractor, ExtractorContext } from './types.js';
|
|
4
|
+
/** Options for {@link ModelExtractor}. */
|
|
5
|
+
export interface ModelExtractorOptions {
|
|
6
|
+
/** Model used to extract facts. Defaults to the agent's own model; set a cheaper one to cut cost. */
|
|
7
|
+
model?: Model;
|
|
8
|
+
/** System prompt steering what counts as a fact. Defaults to a general fact-extraction prompt. */
|
|
9
|
+
systemPrompt?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* An {@link Extractor} that calls a language model to distill messages into discrete facts.
|
|
13
|
+
*
|
|
14
|
+
* Use for self-managed stores that hold plain text and want automatic distillation. Backends that
|
|
15
|
+
* extract server-side should omit the extractor entirely (the no-extractor passthrough hands them
|
|
16
|
+
* raw messages instead).
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* extraction: {
|
|
21
|
+
* trigger: [new InvocationTrigger()],
|
|
22
|
+
* extractor: new ModelExtractor({ model: cheapModel, systemPrompt: 'Extract user preferences.' }),
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare class ModelExtractor implements Extractor {
|
|
27
|
+
private readonly _model?;
|
|
28
|
+
private readonly _systemPrompt;
|
|
29
|
+
constructor(options?: ModelExtractorOptions);
|
|
30
|
+
extract(messages: MessageData[], context?: ExtractorContext): Promise<ExtractionResult[]>;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=model-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-extractor.d.ts","sourceRoot":"","sources":["../../../../src/memory/extraction/model-extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC9E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAGlD,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAO/E,0CAA0C;AAC1C,MAAM,WAAW,qBAAqB;IACpC,qGAAqG;IACrG,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,kGAAkG;IAClG,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,cAAe,YAAW,SAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAO;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAQ;gBAE1B,OAAO,GAAE,qBAA0B;IAOzC,OAAO,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAsChG"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Message, TextBlock } from '../../types/messages.js';
|
|
2
|
+
import { logger } from '../../logging/logger.js';
|
|
3
|
+
/** Default instruction guiding the model to emit discrete, durable facts as a JSON array. */
|
|
4
|
+
const DEFAULT_SYSTEM_PROMPT = `You extract durable facts worth remembering across future conversations from a transcript.
|
|
5
|
+
|
|
6
|
+
Return ONLY a JSON array of objects, each: {"content": string}. Each object is one discrete, self-contained fact (a preference, decision, or stable detail about the user or task). Do not include transient chit-chat, questions, or anything already obvious. If there is nothing worth remembering, return [].`;
|
|
7
|
+
/**
|
|
8
|
+
* An {@link Extractor} that calls a language model to distill messages into discrete facts.
|
|
9
|
+
*
|
|
10
|
+
* Use for self-managed stores that hold plain text and want automatic distillation. Backends that
|
|
11
|
+
* extract server-side should omit the extractor entirely (the no-extractor passthrough hands them
|
|
12
|
+
* raw messages instead).
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* extraction: {
|
|
17
|
+
* trigger: [new InvocationTrigger()],
|
|
18
|
+
* extractor: new ModelExtractor({ model: cheapModel, systemPrompt: 'Extract user preferences.' }),
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export class ModelExtractor {
|
|
23
|
+
_model;
|
|
24
|
+
_systemPrompt;
|
|
25
|
+
constructor(options = {}) {
|
|
26
|
+
if (options.model !== undefined) {
|
|
27
|
+
this._model = options.model;
|
|
28
|
+
}
|
|
29
|
+
this._systemPrompt = options.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
|
|
30
|
+
}
|
|
31
|
+
async extract(messages, context) {
|
|
32
|
+
const model = this._model ?? context?.defaultModel;
|
|
33
|
+
if (!model) {
|
|
34
|
+
throw new Error('ModelExtractor: no model configured and no default model available');
|
|
35
|
+
}
|
|
36
|
+
if (messages.length === 0) {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
// Present the transcript as a single user turn so the system prompt governs extraction, rather
|
|
40
|
+
// than feeding raw roles the model might try to continue.
|
|
41
|
+
const transcript = messages.map((message) => _renderMessage(message)).join('\n');
|
|
42
|
+
const promptMessages = [
|
|
43
|
+
new Message({
|
|
44
|
+
role: 'user',
|
|
45
|
+
content: [new TextBlock(`Extract facts from the following transcript:\n\n${transcript}`)],
|
|
46
|
+
}),
|
|
47
|
+
];
|
|
48
|
+
const stream = model.streamAggregated(promptMessages, { systemPrompt: this._systemPrompt });
|
|
49
|
+
// Manual .next() loop: streamAggregated returns its result as the generator return value
|
|
50
|
+
// (done:true), which for-await-of discards.
|
|
51
|
+
let result;
|
|
52
|
+
for (;;) {
|
|
53
|
+
result = await stream.next();
|
|
54
|
+
if (result.done)
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
if (!result?.done || !result.value) {
|
|
58
|
+
throw new Error('ModelExtractor: model returned no response');
|
|
59
|
+
}
|
|
60
|
+
const text = result.value.message.content
|
|
61
|
+
.map((block) => ('text' in block ? block.text : ''))
|
|
62
|
+
.join('')
|
|
63
|
+
.trim();
|
|
64
|
+
return _parseEntries(text, model.constructor.name);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** Renders one message as `role: text`, joining its text blocks. */
|
|
68
|
+
function _renderMessage(message) {
|
|
69
|
+
const text = message.content
|
|
70
|
+
.map((block) => ('text' in block ? block.text : ''))
|
|
71
|
+
.filter((part) => part.length > 0)
|
|
72
|
+
.join('\n');
|
|
73
|
+
return `${message.role}: ${text}`;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Parses the model's response into entries. Tolerates the array being wrapped in prose or a fenced
|
|
77
|
+
* code block by extracting the first top-level bracketed array. Malformed output yields no entries
|
|
78
|
+
* (logged) rather than throwing, so a single bad extraction never breaks the agent loop.
|
|
79
|
+
*/
|
|
80
|
+
function _parseEntries(text, modelName) {
|
|
81
|
+
const json = _extractJsonArray(text);
|
|
82
|
+
if (json === undefined) {
|
|
83
|
+
logger.warn(`model=<${modelName}> | ModelExtractor: no JSON array in model output, skipping`);
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
let parsed;
|
|
87
|
+
try {
|
|
88
|
+
parsed = JSON.parse(json);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
logger.warn(`model=<${modelName}>, error=<${String(err)}> | ModelExtractor: failed to parse output`);
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
if (!Array.isArray(parsed)) {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
const entries = [];
|
|
98
|
+
for (const item of parsed) {
|
|
99
|
+
if (item && typeof item === 'object' && typeof item.content === 'string') {
|
|
100
|
+
const record = item;
|
|
101
|
+
const content = record.content.trim();
|
|
102
|
+
if (content.length > 0) {
|
|
103
|
+
entries.push({ content, ...(record.metadata !== undefined && { metadata: record.metadata }) });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return entries;
|
|
108
|
+
}
|
|
109
|
+
/** Extracts the substring from the first `[` to the last `]`, or undefined if absent. */
|
|
110
|
+
function _extractJsonArray(text) {
|
|
111
|
+
const start = text.indexOf('[');
|
|
112
|
+
const end = text.lastIndexOf(']');
|
|
113
|
+
if (start === -1 || end === -1 || end < start) {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
return text.slice(start, end + 1);
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=model-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-extractor.js","sourceRoot":"","sources":["../../../../src/memory/extraction/model-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { MemoryStore } from '../types.js';
|
|
2
|
+
import { type ExtractionConfig, type ExtractionTrigger, type Extractor, type MemoryMessageFilter } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Default cadence when an {@link ExtractionConfig} omits its `trigger`: extract every N turns.
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export declare const DEFAULT_EXTRACTION_TRIGGER_TURNS = 5;
|
|
8
|
+
/**
|
|
9
|
+
* An {@link ExtractionConfig} with every field resolved to a concrete value, ready to drive
|
|
10
|
+
* extraction. Produced by {@link resolveExtractionConfig} so the {@link MemoryManager} and
|
|
11
|
+
* {@link ExtractionCoordinator} never have to re-apply defaults or normalize shapes.
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export interface ResolvedExtractionConfig {
|
|
15
|
+
/** Normalized to an array (a single trigger is wrapped). Never empty for a resolved config. */
|
|
16
|
+
triggers: ExtractionTrigger[];
|
|
17
|
+
/**
|
|
18
|
+
* The extractor that distills facts client-side and stores them via the store's `add` method, or
|
|
19
|
+
* `undefined` to use the store's `addMessages` method (server-side extraction).
|
|
20
|
+
*/
|
|
21
|
+
extractor?: Extractor;
|
|
22
|
+
/** The content-block filter applied before extraction. */
|
|
23
|
+
filter: MemoryMessageFilter;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolves a store's `extraction` setting into a {@link ResolvedExtractionConfig}, applying defaults.
|
|
27
|
+
*
|
|
28
|
+
* The single place the `boolean | ExtractionConfig` shorthand is interpreted: `false`/omitted is off
|
|
29
|
+
* (returns `undefined`), `true` enables all defaults, an {@link ExtractionConfig} defaults its unset
|
|
30
|
+
* fields. The defaults are:
|
|
31
|
+
* - **trigger**: every {@link DEFAULT_EXTRACTION_TRIGGER_TURNS} turns. An explicit empty array is left
|
|
32
|
+
* empty for the {@link MemoryManager} to reject.
|
|
33
|
+
* - **extractor**: chosen from the methods the store implements. A store that implements `addMessages`
|
|
34
|
+
* supports server-side extraction, so it defaults to no extractor: the manager hands raw messages to
|
|
35
|
+
* `addMessages` and the backend extracts them itself, with no model call. A store that implements only
|
|
36
|
+
* `add` cannot extract server-side, so it defaults to a {@link ModelExtractor} that distills facts
|
|
37
|
+
* client-side (via model calls) and stores each one through `add`.
|
|
38
|
+
* - **filter**: {@link DEFAULT_MEMORY_MESSAGE_FILTER}.
|
|
39
|
+
*
|
|
40
|
+
* @param extraction - The store's `extraction` setting
|
|
41
|
+
* @param store - The store, inspected for the write methods it implements to pick the default extractor
|
|
42
|
+
* @returns The resolved config, or `undefined` when extraction is disabled
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveExtractionConfig(extraction: boolean | ExtractionConfig | undefined, store: Pick<MemoryStore, 'add' | 'addMessages'>): ResolvedExtractionConfig | undefined;
|
|
46
|
+
//# sourceMappingURL=resolve-extraction-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-extraction-config.d.ts","sourceRoot":"","sources":["../../../../src/memory/extraction/resolve-extraction-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAG9C,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,mBAAmB,EACzB,MAAM,YAAY,CAAA;AAEnB;;;GAGG;AACH,eAAO,MAAM,gCAAgC,IAAI,CAAA;AAEjD;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,+FAA+F;IAC/F,QAAQ,EAAE,iBAAiB,EAAE,CAAA;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,0DAA0D;IAC1D,MAAM,EAAE,mBAAmB,CAAA;CAC5B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,EAClD,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,aAAa,CAAC,GAC9C,wBAAwB,GAAG,SAAS,CAkCtC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { IntervalTrigger } from './triggers.js';
|
|
2
|
+
import { ModelExtractor } from './model-extractor.js';
|
|
3
|
+
import { DEFAULT_MEMORY_MESSAGE_FILTER, } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Default cadence when an {@link ExtractionConfig} omits its `trigger`: extract every N turns.
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export const DEFAULT_EXTRACTION_TRIGGER_TURNS = 5;
|
|
9
|
+
/**
|
|
10
|
+
* Resolves a store's `extraction` setting into a {@link ResolvedExtractionConfig}, applying defaults.
|
|
11
|
+
*
|
|
12
|
+
* The single place the `boolean | ExtractionConfig` shorthand is interpreted: `false`/omitted is off
|
|
13
|
+
* (returns `undefined`), `true` enables all defaults, an {@link ExtractionConfig} defaults its unset
|
|
14
|
+
* fields. The defaults are:
|
|
15
|
+
* - **trigger**: every {@link DEFAULT_EXTRACTION_TRIGGER_TURNS} turns. An explicit empty array is left
|
|
16
|
+
* empty for the {@link MemoryManager} to reject.
|
|
17
|
+
* - **extractor**: chosen from the methods the store implements. A store that implements `addMessages`
|
|
18
|
+
* supports server-side extraction, so it defaults to no extractor: the manager hands raw messages to
|
|
19
|
+
* `addMessages` and the backend extracts them itself, with no model call. A store that implements only
|
|
20
|
+
* `add` cannot extract server-side, so it defaults to a {@link ModelExtractor} that distills facts
|
|
21
|
+
* client-side (via model calls) and stores each one through `add`.
|
|
22
|
+
* - **filter**: {@link DEFAULT_MEMORY_MESSAGE_FILTER}.
|
|
23
|
+
*
|
|
24
|
+
* @param extraction - The store's `extraction` setting
|
|
25
|
+
* @param store - The store, inspected for the write methods it implements to pick the default extractor
|
|
26
|
+
* @returns The resolved config, or `undefined` when extraction is disabled
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
export function resolveExtractionConfig(extraction, store) {
|
|
30
|
+
if (!extraction) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const config = extraction === true ? {} : extraction;
|
|
34
|
+
const triggers = config.trigger === undefined
|
|
35
|
+
? [new IntervalTrigger({ turns: DEFAULT_EXTRACTION_TRIGGER_TURNS })]
|
|
36
|
+
: Array.isArray(config.trigger)
|
|
37
|
+
? config.trigger
|
|
38
|
+
: [config.trigger];
|
|
39
|
+
let extractor = config.extractor;
|
|
40
|
+
if (extractor === undefined) {
|
|
41
|
+
// Pick the default extractor from the store's write methods:
|
|
42
|
+
// - implements `addMessages` (whether or not it also implements `add`): extract server-side. Leave
|
|
43
|
+
// the extractor undefined so raw messages go straight to `addMessages` with no model call.
|
|
44
|
+
// - implements only `add`: it cannot extract server-side, so default to a ModelExtractor that
|
|
45
|
+
// distills facts client-side and stores each via `add`.
|
|
46
|
+
const implementsAdd = typeof store.add === 'function';
|
|
47
|
+
const implementsAddMessages = typeof store.addMessages === 'function';
|
|
48
|
+
if (implementsAdd && !implementsAddMessages) {
|
|
49
|
+
extractor = new ModelExtractor();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const filter = config.filter ?? DEFAULT_MEMORY_MESSAGE_FILTER;
|
|
53
|
+
return {
|
|
54
|
+
triggers,
|
|
55
|
+
...(extractor !== undefined && { extractor }),
|
|
56
|
+
filter,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=resolve-extraction-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-extraction-config.js","sourceRoot":"","sources":["../../../../src/memory/extraction/resolve-extraction-config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EACL,6BAA6B,GAK9B,MAAM,YAAY,CAAA;AAEnB;;;GAGG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAA;AAoBjD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,uBAAuB,CACrC,UAAkD,EAClD,KAA+C;IAE/C,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,MAAM,MAAM,GAAqB,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAA;IAEtE,MAAM,QAAQ,GACZ,MAAM,CAAC,OAAO,KAAK,SAAS;QAC1B,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC,CAAC;QACpE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;YAC7B,CAAC,CAAC,MAAM,CAAC,OAAO;YAChB,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAExB,IAAI,SAAS,GAAG,MAAM,CAAC,SAAS,CAAA;IAChC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,6DAA6D;QAC7D,mGAAmG;QACnG,6FAA6F;QAC7F,8FAA8F;QAC9F,0DAA0D;QAC1D,MAAM,aAAa,GAAG,OAAO,KAAK,CAAC,GAAG,KAAK,UAAU,CAAA;QACrD,MAAM,qBAAqB,GAAG,OAAO,KAAK,CAAC,WAAW,KAAK,UAAU,CAAA;QACrE,IAAI,aAAa,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAC5C,SAAS,GAAG,IAAI,cAAc,EAAE,CAAA;QAClC,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,6BAA6B,CAAA;IAE7D,OAAO;QACL,QAAQ;QACR,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,CAAC;QAC7C,MAAM;KACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ExtractionTrigger, type ExtractionTriggerContext } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Runs extraction after every agent invocation.
|
|
4
|
+
*
|
|
5
|
+
* The highest-fidelity option: nothing said in a turn is missed. Also the most expensive when an
|
|
6
|
+
* {@link Extractor} is configured (a model call per turn) — for a server-side-extraction backend
|
|
7
|
+
* with no extractor it is just a per-turn write.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* extraction: { trigger: [new InvocationTrigger()] }
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare class InvocationTrigger extends ExtractionTrigger {
|
|
15
|
+
readonly name = "invocation";
|
|
16
|
+
attach(context: ExtractionTriggerContext): void;
|
|
17
|
+
}
|
|
18
|
+
/** Options for {@link IntervalTrigger}. */
|
|
19
|
+
export interface IntervalTriggerOptions {
|
|
20
|
+
/** Run extraction once every this many invocations. Must be a positive integer. */
|
|
21
|
+
turns: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Runs extraction every N agent invocations.
|
|
25
|
+
*
|
|
26
|
+
* A controllable middle ground: extraction (and any model call it entails) happens on a cadence
|
|
27
|
+
* rather than every turn, while the high-water mark guarantees the messages from the skipped turns
|
|
28
|
+
* are still processed when the trigger does fire.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* extraction: { trigger: [new IntervalTrigger({ turns: 5 })] }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare class IntervalTrigger extends ExtractionTrigger {
|
|
36
|
+
readonly name = "interval";
|
|
37
|
+
private readonly _turns;
|
|
38
|
+
constructor(options: IntervalTriggerOptions);
|
|
39
|
+
attach(context: ExtractionTriggerContext): void;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=triggers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triggers.d.ts","sourceRoot":"","sources":["../../../../src/memory/extraction/triggers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,MAAM,YAAY,CAAA;AAE7E;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAkB,SAAQ,iBAAiB;IACtD,QAAQ,CAAC,IAAI,gBAAe;IAE5B,MAAM,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI;CAKhD;AAED,2CAA2C;AAC3C,MAAM,WAAW,sBAAsB;IACrC,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,eAAgB,SAAQ,iBAAiB;IACpD,QAAQ,CAAC,IAAI,cAAa;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;gBAEnB,OAAO,EAAE,sBAAsB;IAQ3C,MAAM,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI;CAgBhD"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { AfterInvocationEvent } from '../../hooks/events.js';
|
|
2
|
+
import { HookOrder } from '../../hooks/types.js';
|
|
3
|
+
import { ExtractionTrigger } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Runs extraction after every agent invocation.
|
|
6
|
+
*
|
|
7
|
+
* The highest-fidelity option: nothing said in a turn is missed. Also the most expensive when an
|
|
8
|
+
* {@link Extractor} is configured (a model call per turn) — for a server-side-extraction backend
|
|
9
|
+
* with no extractor it is just a per-turn write.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* extraction: { trigger: [new InvocationTrigger()] }
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export class InvocationTrigger extends ExtractionTrigger {
|
|
17
|
+
name = 'invocation';
|
|
18
|
+
attach(context) {
|
|
19
|
+
// Run after the SDK's own after-invocation hooks (e.g. session persistence) so extraction sees
|
|
20
|
+
// the fully settled turn.
|
|
21
|
+
context.agent.addHook(AfterInvocationEvent, () => context.fire(), { order: HookOrder.SDK_LAST });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Runs extraction every N agent invocations.
|
|
26
|
+
*
|
|
27
|
+
* A controllable middle ground: extraction (and any model call it entails) happens on a cadence
|
|
28
|
+
* rather than every turn, while the high-water mark guarantees the messages from the skipped turns
|
|
29
|
+
* are still processed when the trigger does fire.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* extraction: { trigger: [new IntervalTrigger({ turns: 5 })] }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export class IntervalTrigger extends ExtractionTrigger {
|
|
37
|
+
name = 'interval';
|
|
38
|
+
_turns;
|
|
39
|
+
constructor(options) {
|
|
40
|
+
super();
|
|
41
|
+
if (!Number.isInteger(options.turns) || options.turns < 1) {
|
|
42
|
+
throw new Error(`IntervalTrigger: turns must be a positive integer, got ${options.turns}`);
|
|
43
|
+
}
|
|
44
|
+
this._turns = options.turns;
|
|
45
|
+
}
|
|
46
|
+
attach(context) {
|
|
47
|
+
// Per-attach counter: each store this trigger is configured on gets its own count via a fresh
|
|
48
|
+
// closure, so two stores sharing one IntervalTrigger instance still fire independently.
|
|
49
|
+
let count = 0;
|
|
50
|
+
context.agent.addHook(AfterInvocationEvent, () => {
|
|
51
|
+
count++;
|
|
52
|
+
// `fire` is fire-and-forget (returns void); it dispatches extraction in the background.
|
|
53
|
+
if (count % this._turns === 0) {
|
|
54
|
+
context.fire();
|
|
55
|
+
}
|
|
56
|
+
}, { order: HookOrder.SDK_LAST });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=triggers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triggers.js","sourceRoot":"","sources":["../../../../src/memory/extraction/triggers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAiC,MAAM,YAAY,CAAA;AAE7E;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,iBAAkB,SAAQ,iBAAiB;IAC7C,IAAI,GAAG,YAAY,CAAA;IAE5B,MAAM,CAAC,OAAiC;QACtC,+FAA+F;QAC/F,0BAA0B;QAC1B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAA;IAClG,CAAC;CACF;AAQD;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,eAAgB,SAAQ,iBAAiB;IAC3C,IAAI,GAAG,UAAU,CAAA;IACT,MAAM,CAAQ;IAE/B,YAAY,OAA+B;QACzC,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,0DAA0D,OAAO,CAAC,KAAK,EAAE,CAAC,CAAA;QAC5F,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAA;IAC7B,CAAC;IAED,MAAM,CAAC,OAAiC;QACtC,8FAA8F;QAC9F,wFAAwF;QACxF,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,OAAO,CAAC,KAAK,CAAC,OAAO,CACnB,oBAAoB,EACpB,GAAG,EAAE;YACH,KAAK,EAAE,CAAA;YACP,wFAAwF;YACxF,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO,CAAC,IAAI,EAAE,CAAA;YAChB,CAAC;QACH,CAAC,EACD,EAAE,KAAK,EAAE,SAAS,CAAC,QAAQ,EAAE,CAC9B,CAAA;IACH,CAAC;CACF"}
|