byterover-cli 0.3.4 → 0.4.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 +119 -63
- package/bin/dev.js +8 -1
- package/bin/run.js +7 -0
- package/dist/commands/cipher-agent/run.d.ts +30 -0
- package/dist/commands/cipher-agent/run.js +123 -61
- package/dist/commands/cipher-agent/set-prompt.d.ts +2 -0
- package/dist/commands/cipher-agent/set-prompt.js +13 -8
- package/dist/commands/cipher-agent/show-prompt.d.ts +2 -0
- package/dist/commands/cipher-agent/show-prompt.js +17 -12
- package/dist/commands/curate.d.ts +3 -60
- package/dist/commands/curate.js +45 -341
- package/dist/commands/foo.d.ts +4 -2
- package/dist/commands/foo.js +21 -16
- package/dist/commands/main.d.ts +9 -0
- package/dist/commands/main.js +34 -0
- package/dist/commands/query.d.ts +2 -48
- package/dist/commands/query.js +19 -287
- package/dist/commands/status.d.ts +2 -13
- package/dist/commands/status.js +12 -91
- package/dist/commands/watch.d.ts +2 -0
- package/dist/commands/watch.js +23 -19
- package/dist/config/environment.d.ts +1 -1
- package/dist/config/environment.js +2 -2
- package/dist/constants.d.ts +4 -5
- package/dist/constants.js +5 -5
- package/dist/core/domain/cipher/errors/storage-error.d.ts +89 -0
- package/dist/core/domain/cipher/errors/storage-error.js +130 -0
- package/dist/core/domain/cipher/queue/types.d.ts +71 -0
- package/dist/core/domain/cipher/queue/types.js +9 -0
- package/dist/core/domain/cipher/storage/message-storage-types.d.ts +218 -0
- package/dist/core/domain/cipher/storage/message-storage-types.js +18 -0
- package/dist/core/domain/cipher/tools/constants.d.ts +1 -0
- package/dist/core/domain/cipher/tools/constants.js +1 -0
- package/dist/core/domain/entities/event.d.ts +1 -1
- package/dist/core/domain/entities/event.js +5 -0
- package/dist/core/domain/entities/global-config.d.ts +36 -0
- package/dist/core/domain/entities/global-config.js +66 -0
- package/dist/core/domain/knowledge/directory-manager.d.ts +10 -0
- package/dist/core/domain/knowledge/directory-manager.js +18 -0
- package/dist/core/domain/knowledge/markdown-writer.d.ts +9 -0
- package/dist/core/domain/knowledge/markdown-writer.js +51 -1
- package/dist/core/interfaces/cipher/i-agent-storage.d.ts +152 -0
- package/dist/core/interfaces/cipher/i-agent-storage.js +1 -0
- package/dist/core/interfaces/cipher/i-cipher-agent.d.ts +2 -0
- package/dist/core/interfaces/cipher/i-key-storage.d.ts +91 -0
- package/dist/core/interfaces/cipher/i-key-storage.js +1 -0
- package/dist/core/interfaces/i-global-config-store.d.ts +34 -0
- package/dist/core/interfaces/i-global-config-store.js +1 -0
- package/dist/core/interfaces/i-onboarding-preference-store.d.ts +20 -0
- package/dist/core/interfaces/i-onboarding-preference-store.js +1 -0
- package/dist/core/interfaces/i-terminal.d.ts +146 -0
- package/dist/core/interfaces/i-terminal.js +1 -0
- package/dist/core/interfaces/i-workspace-detector-service.d.ts +8 -0
- package/dist/core/interfaces/i-workspace-detector-service.js +1 -0
- package/dist/core/interfaces/usecase/i-clear-use-case.d.ts +6 -0
- package/dist/core/interfaces/usecase/i-clear-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-curate-use-case.d.ts +10 -0
- package/dist/core/interfaces/usecase/i-curate-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-generate-rules-use-case.d.ts +3 -0
- package/dist/core/interfaces/usecase/i-generate-rules-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-init-use-case.d.ts +5 -0
- package/dist/core/interfaces/usecase/i-init-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-login-use-case.d.ts +3 -0
- package/dist/core/interfaces/usecase/i-login-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-logout-use-case.d.ts +5 -0
- package/dist/core/interfaces/usecase/i-logout-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-pull-use-case.d.ts +5 -0
- package/dist/core/interfaces/usecase/i-pull-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-push-use-case.d.ts +6 -0
- package/dist/core/interfaces/usecase/i-push-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-query-use-case.d.ts +9 -0
- package/dist/core/interfaces/usecase/i-query-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-space-list-use-case.d.ts +3 -0
- package/dist/core/interfaces/usecase/i-space-list-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-space-switch-use-case.d.ts +3 -0
- package/dist/core/interfaces/usecase/i-space-switch-use-case.js +1 -0
- package/dist/core/interfaces/usecase/i-status-use-case.d.ts +5 -0
- package/dist/core/interfaces/usecase/i-status-use-case.js +1 -0
- package/dist/hooks/init/update-notifier.js +1 -5
- package/dist/hooks/init/welcome.js +1 -2
- package/dist/infra/cipher/agent-service-factory.d.ts +13 -6
- package/dist/infra/cipher/agent-service-factory.js +40 -16
- package/dist/infra/cipher/cipher-agent.js +4 -4
- package/dist/infra/cipher/consumer/consumer-lock.d.ts +20 -0
- package/dist/infra/cipher/consumer/consumer-lock.js +40 -0
- package/dist/infra/cipher/consumer/consumer-service.d.ts +99 -0
- package/dist/infra/cipher/consumer/consumer-service.js +165 -0
- package/dist/infra/cipher/consumer/execution-consumer.d.ts +121 -0
- package/dist/infra/cipher/consumer/execution-consumer.js +523 -0
- package/dist/infra/cipher/consumer/index.d.ts +33 -0
- package/dist/infra/cipher/consumer/index.js +33 -0
- package/dist/infra/cipher/consumer/queue-polling-service.d.ts +120 -0
- package/dist/infra/cipher/consumer/queue-polling-service.js +248 -0
- package/dist/infra/cipher/http/internal-llm-http-service.d.ts +94 -0
- package/dist/infra/cipher/http/internal-llm-http-service.js +118 -0
- package/dist/infra/cipher/llm/context/compaction/compaction-service.d.ts +106 -0
- package/dist/infra/cipher/llm/context/compaction/compaction-service.js +132 -0
- package/dist/infra/cipher/llm/context/compaction/index.d.ts +9 -0
- package/dist/infra/cipher/llm/context/compaction/index.js +9 -0
- package/dist/infra/cipher/llm/context/context-manager.d.ts +46 -2
- package/dist/infra/cipher/llm/context/context-manager.js +68 -4
- package/dist/infra/cipher/llm/context/rw-lock.d.ts +72 -0
- package/dist/infra/cipher/llm/context/rw-lock.js +145 -0
- package/dist/infra/cipher/llm/generators/byterover-content-generator.d.ts +7 -7
- package/dist/infra/cipher/llm/generators/byterover-content-generator.js +8 -8
- package/dist/infra/cipher/llm/internal-llm-service.js +2 -0
- package/dist/infra/cipher/session/session-manager.d.ts +4 -4
- package/dist/infra/cipher/session/session-manager.js +5 -5
- package/dist/infra/cipher/storage/agent-storage.d.ts +246 -0
- package/dist/infra/cipher/storage/agent-storage.js +956 -0
- package/dist/infra/cipher/storage/dual-format-history-storage.d.ts +77 -0
- package/dist/infra/cipher/storage/dual-format-history-storage.js +149 -0
- package/dist/infra/cipher/storage/granular-history-storage.d.ts +65 -0
- package/dist/infra/cipher/storage/granular-history-storage.js +118 -0
- package/dist/infra/cipher/storage/message-storage-service.d.ts +108 -0
- package/dist/infra/cipher/storage/message-storage-service.js +529 -0
- package/dist/infra/cipher/storage/process-utils.d.ts +16 -0
- package/dist/infra/cipher/storage/process-utils.js +43 -0
- package/dist/infra/cipher/storage/sqlite-key-storage.d.ts +105 -0
- package/dist/infra/cipher/storage/sqlite-key-storage.js +404 -0
- package/dist/infra/cipher/system-prompt/simple-prompt-factory.d.ts +1 -0
- package/dist/infra/cipher/system-prompt/simple-prompt-factory.js +7 -0
- package/dist/infra/cipher/tools/default-policy-rules.js +1 -1
- package/dist/infra/cipher/tools/implementations/curate-tool.d.ts +10 -0
- package/dist/infra/cipher/tools/implementations/curate-tool.js +371 -0
- package/dist/infra/cipher/tools/implementations/find-knowledge-topics-tool.js +11 -8
- package/dist/infra/cipher/tools/tool-manager.d.ts +8 -2
- package/dist/infra/cipher/tools/tool-manager.js +29 -2
- package/dist/infra/cipher/tools/tool-registry.js +7 -0
- package/dist/infra/http/authenticated-http-client.d.ts +21 -0
- package/dist/infra/http/authenticated-http-client.js +38 -0
- package/dist/infra/repl/commands/arg-parser.d.ts +97 -0
- package/dist/infra/repl/commands/arg-parser.js +129 -0
- package/dist/infra/repl/commands/clear-command.d.ts +5 -0
- package/dist/infra/repl/commands/clear-command.js +61 -0
- package/dist/infra/repl/commands/curate-command.d.ts +9 -0
- package/dist/infra/repl/commands/curate-command.js +88 -0
- package/dist/infra/repl/commands/gen-rules-command.d.ts +7 -0
- package/dist/infra/repl/commands/gen-rules-command.js +38 -0
- package/dist/infra/repl/commands/index.d.ts +8 -0
- package/dist/infra/repl/commands/index.js +36 -0
- package/dist/infra/repl/commands/init-command.d.ts +7 -0
- package/dist/infra/repl/commands/init-command.js +83 -0
- package/dist/infra/repl/commands/login-command.d.ts +7 -0
- package/dist/infra/repl/commands/login-command.js +50 -0
- package/dist/infra/repl/commands/logout-command.d.ts +5 -0
- package/dist/infra/repl/commands/logout-command.js +48 -0
- package/dist/infra/repl/commands/pull-command.d.ts +5 -0
- package/dist/infra/repl/commands/pull-command.js +61 -0
- package/dist/infra/repl/commands/push-command.d.ts +5 -0
- package/dist/infra/repl/commands/push-command.js +66 -0
- package/dist/infra/repl/commands/query-command.d.ts +5 -0
- package/dist/infra/repl/commands/query-command.js +66 -0
- package/dist/infra/repl/commands/space/index.d.ts +5 -0
- package/dist/infra/repl/commands/space/index.js +14 -0
- package/dist/infra/repl/commands/space/list-command.d.ts +5 -0
- package/dist/infra/repl/commands/space/list-command.js +70 -0
- package/dist/infra/repl/commands/space/switch-command.d.ts +5 -0
- package/dist/infra/repl/commands/space/switch-command.js +37 -0
- package/dist/infra/repl/commands/status-command.d.ts +5 -0
- package/dist/infra/repl/commands/status-command.js +39 -0
- package/dist/infra/repl/repl-startup.d.ts +18 -0
- package/dist/infra/repl/repl-startup.js +26 -0
- package/dist/infra/storage/file-global-config-store.d.ts +22 -0
- package/dist/infra/storage/file-global-config-store.js +65 -0
- package/dist/infra/storage/file-onboarding-preference-store.d.ts +10 -0
- package/dist/infra/storage/file-onboarding-preference-store.js +46 -0
- package/dist/infra/terminal/oclif-terminal.d.ts +19 -0
- package/dist/infra/terminal/oclif-terminal.js +60 -0
- package/dist/infra/terminal/repl-terminal.d.ts +31 -0
- package/dist/infra/terminal/repl-terminal.js +116 -0
- package/dist/infra/tracking/mixpanel-tracking-service.d.ts +11 -1
- package/dist/infra/tracking/mixpanel-tracking-service.js +18 -13
- package/dist/infra/usecase/clear-use-case.d.ts +20 -0
- package/dist/infra/usecase/clear-use-case.js +58 -0
- package/dist/infra/usecase/curate-use-case.d.ts +66 -0
- package/dist/infra/usecase/curate-use-case.js +283 -0
- package/dist/{commands/gen-rules.d.ts → infra/usecase/generate-rules-use-case.d.ts} +14 -20
- package/dist/{commands/gen-rules.js → infra/usecase/generate-rules-use-case.js} +59 -78
- package/dist/infra/usecase/init-use-case.d.ts +139 -0
- package/dist/{commands/init.js → infra/usecase/init-use-case.js} +184 -230
- package/dist/infra/usecase/login-use-case.d.ts +28 -0
- package/dist/infra/usecase/login-use-case.js +88 -0
- package/dist/infra/usecase/logout-use-case.d.ts +22 -0
- package/dist/infra/usecase/logout-use-case.js +51 -0
- package/dist/infra/usecase/pull-use-case.d.ts +35 -0
- package/dist/infra/usecase/pull-use-case.js +89 -0
- package/dist/infra/usecase/push-use-case.d.ts +37 -0
- package/dist/infra/usecase/push-use-case.js +124 -0
- package/dist/infra/usecase/query-use-case.d.ts +78 -0
- package/dist/infra/usecase/query-use-case.js +401 -0
- package/dist/infra/usecase/space-list-use-case.d.ts +27 -0
- package/dist/infra/usecase/space-list-use-case.js +64 -0
- package/dist/infra/usecase/space-switch-use-case.d.ts +36 -0
- package/dist/infra/usecase/space-switch-use-case.js +140 -0
- package/dist/infra/usecase/status-use-case.d.ts +27 -0
- package/dist/infra/usecase/status-use-case.js +97 -0
- package/dist/infra/workspace/workspace-detector-service.d.ts +3 -6
- package/dist/resources/prompts/curate-context-tree-curation.yml +23 -11
- package/dist/resources/prompts/query-context-tree-retrieval.yml +3 -4
- package/dist/resources/prompts/system-prompt.yml +1 -1
- package/dist/resources/prompts/tool-outputs.yml +4 -3
- package/dist/templates/sections/command-reference.md +12 -0
- package/dist/templates/sections/workflow.md +10 -1
- package/dist/tui/app.d.ts +9 -0
- package/dist/tui/app.js +26 -0
- package/dist/tui/components/enter-prompt.d.ts +13 -0
- package/dist/tui/components/enter-prompt.js +15 -0
- package/dist/tui/components/execution/execution-changes.d.ts +14 -0
- package/dist/tui/components/execution/execution-changes.js +15 -0
- package/dist/tui/components/execution/execution-content.d.ts +25 -0
- package/dist/tui/components/execution/execution-content.js +67 -0
- package/dist/tui/components/execution/execution-input.d.ts +12 -0
- package/dist/tui/components/execution/execution-input.js +16 -0
- package/dist/tui/components/execution/execution-progress.d.ts +21 -0
- package/dist/tui/components/execution/execution-progress.js +21 -0
- package/dist/tui/components/execution/execution-status.d.ts +13 -0
- package/dist/tui/components/execution/execution-status.js +19 -0
- package/dist/tui/components/execution/index.d.ts +11 -0
- package/dist/tui/components/execution/index.js +11 -0
- package/dist/tui/components/execution/log-item.d.ts +17 -0
- package/dist/tui/components/execution/log-item.js +25 -0
- package/dist/tui/components/footer.d.ts +5 -0
- package/dist/tui/components/footer.js +12 -0
- package/dist/tui/components/header.d.ts +18 -0
- package/dist/tui/components/header.js +18 -0
- package/dist/tui/components/index.d.ts +17 -0
- package/dist/tui/components/index.js +14 -0
- package/dist/tui/components/inline-prompts/index.d.ts +15 -0
- package/dist/tui/components/inline-prompts/index.js +10 -0
- package/dist/tui/components/inline-prompts/inline-confirm.d.ts +17 -0
- package/dist/tui/components/inline-prompts/inline-confirm.js +32 -0
- package/dist/tui/components/inline-prompts/inline-file-selector.d.ts +43 -0
- package/dist/tui/components/inline-prompts/inline-file-selector.js +185 -0
- package/dist/tui/components/inline-prompts/inline-input.d.ts +19 -0
- package/dist/tui/components/inline-prompts/inline-input.js +32 -0
- package/dist/tui/components/inline-prompts/inline-search.d.ts +20 -0
- package/dist/tui/components/inline-prompts/inline-search.js +50 -0
- package/dist/tui/components/inline-prompts/inline-select.d.ts +20 -0
- package/dist/tui/components/inline-prompts/inline-select.js +34 -0
- package/dist/tui/components/logo.d.ts +43 -0
- package/dist/tui/components/logo.js +103 -0
- package/dist/tui/components/message-item.d.ts +12 -0
- package/dist/tui/components/message-item.js +12 -0
- package/dist/tui/components/onboarding/copyable-prompt.d.ts +15 -0
- package/dist/tui/components/onboarding/copyable-prompt.js +65 -0
- package/dist/tui/components/onboarding/index.d.ts +7 -0
- package/dist/tui/components/onboarding/index.js +6 -0
- package/dist/tui/components/onboarding/onboarding-flow.d.ts +13 -0
- package/dist/tui/components/onboarding/onboarding-flow.js +304 -0
- package/dist/tui/components/onboarding/onboarding-step.d.ts +23 -0
- package/dist/tui/components/onboarding/onboarding-step.js +12 -0
- package/dist/tui/components/output-log.d.ts +14 -0
- package/dist/tui/components/output-log.js +13 -0
- package/dist/tui/components/scrollable-list.d.ts +30 -0
- package/dist/tui/components/scrollable-list.js +121 -0
- package/dist/tui/components/suggestions.d.ts +16 -0
- package/dist/tui/components/suggestions.js +162 -0
- package/dist/tui/components/tab-bar.d.ts +10 -0
- package/dist/tui/components/tab-bar.js +12 -0
- package/dist/tui/constants.d.ts +11 -0
- package/dist/tui/constants.js +13 -0
- package/dist/tui/contexts/auth-context.d.ts +30 -0
- package/dist/tui/contexts/auth-context.js +153 -0
- package/dist/tui/contexts/consumer.d.ts +31 -0
- package/dist/tui/contexts/consumer.js +56 -0
- package/dist/tui/contexts/index.d.ts +6 -0
- package/dist/tui/contexts/index.js +6 -0
- package/dist/tui/contexts/onboarding-context.d.ts +43 -0
- package/dist/tui/contexts/onboarding-context.js +181 -0
- package/dist/tui/contexts/services-context.d.ts +29 -0
- package/dist/tui/contexts/services-context.js +20 -0
- package/dist/tui/contexts/use-commands.d.ts +29 -0
- package/dist/tui/contexts/use-commands.js +53 -0
- package/dist/tui/contexts/use-mode.d.ts +43 -0
- package/dist/tui/contexts/use-mode.js +76 -0
- package/dist/tui/contexts/use-theme.d.ts +53 -0
- package/dist/tui/contexts/use-theme.js +60 -0
- package/dist/tui/hooks/index.d.ts +17 -0
- package/dist/tui/hooks/index.js +14 -0
- package/dist/tui/hooks/use-activity-logs.d.ts +26 -0
- package/dist/tui/hooks/use-activity-logs.js +90 -0
- package/dist/tui/hooks/use-consumer.d.ts +12 -0
- package/dist/tui/hooks/use-consumer.js +50 -0
- package/dist/tui/hooks/use-onboarding.d.ts +7 -0
- package/dist/tui/hooks/use-onboarding.js +6 -0
- package/dist/tui/hooks/use-queue-polling.d.ts +31 -0
- package/dist/tui/hooks/use-queue-polling.js +90 -0
- package/dist/tui/hooks/use-slash-command-processor.d.ts +16 -0
- package/dist/tui/hooks/use-slash-command-processor.js +132 -0
- package/dist/tui/hooks/use-slash-completion.d.ts +30 -0
- package/dist/tui/hooks/use-slash-completion.js +230 -0
- package/dist/tui/hooks/use-tab-navigation.d.ts +10 -0
- package/dist/tui/hooks/use-tab-navigation.js +35 -0
- package/dist/tui/hooks/use-visible-window.d.ts +22 -0
- package/dist/tui/hooks/use-visible-window.js +37 -0
- package/dist/tui/index.d.ts +1 -0
- package/dist/tui/index.js +1 -0
- package/dist/tui/providers/app-providers.d.ts +25 -0
- package/dist/tui/providers/app-providers.js +9 -0
- package/dist/tui/types/commands.d.ts +252 -0
- package/dist/tui/types/commands.js +16 -0
- package/dist/tui/types/dialogs.d.ts +37 -0
- package/dist/tui/types/dialogs.js +4 -0
- package/dist/tui/types/index.d.ts +11 -0
- package/dist/tui/types/index.js +7 -0
- package/dist/tui/types/messages.d.ts +55 -0
- package/dist/tui/types/messages.js +4 -0
- package/dist/tui/types/prompts.d.ts +100 -0
- package/dist/tui/types/prompts.js +4 -0
- package/dist/tui/types/ui.d.ts +14 -0
- package/dist/tui/types/ui.js +4 -0
- package/dist/tui/types.d.ts +1 -0
- package/dist/tui/types.js +1 -0
- package/dist/tui/views/command-view.d.ts +12 -0
- package/dist/tui/views/command-view.js +451 -0
- package/dist/tui/views/index.d.ts +6 -0
- package/dist/tui/views/index.js +6 -0
- package/dist/tui/views/login-view.d.ts +10 -0
- package/dist/tui/views/login-view.js +30 -0
- package/dist/tui/views/logs-view.d.ts +11 -0
- package/dist/tui/views/logs-view.js +73 -0
- package/dist/utils/file-validator.d.ts +16 -0
- package/dist/utils/file-validator.js +81 -0
- package/dist/utils/global-config-path.d.ts +15 -0
- package/dist/utils/global-config-path.js +38 -0
- package/oclif.manifest.json +29 -315
- package/package.json +11 -4
- package/dist/commands/clear.d.ts +0 -19
- package/dist/commands/clear.js +0 -78
- package/dist/commands/init.d.ts +0 -130
- package/dist/commands/login.d.ts +0 -22
- package/dist/commands/login.js +0 -108
- package/dist/commands/logout.d.ts +0 -16
- package/dist/commands/logout.js +0 -61
- package/dist/commands/pull.d.ts +0 -33
- package/dist/commands/pull.js +0 -115
- package/dist/commands/push.d.ts +0 -35
- package/dist/commands/push.js +0 -160
- package/dist/commands/space/list.d.ts +0 -25
- package/dist/commands/space/list.js +0 -114
- package/dist/commands/space/switch.d.ts +0 -36
- package/dist/commands/space/switch.js +0 -160
- package/dist/infra/cipher/grpc/internal-llm-grpc-service.d.ts +0 -149
- package/dist/infra/cipher/grpc/internal-llm-grpc-service.js +0 -364
- package/dist/infra/cipher/grpc/internal-llm-grpc.proto +0 -94
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { ToolName } from '../../../../core/domain/cipher/tools/constants.js';
|
|
4
|
+
import { DirectoryManager } from '../../../../core/domain/knowledge/directory-manager.js';
|
|
5
|
+
import { MarkdownWriter } from '../../../../core/domain/knowledge/markdown-writer.js';
|
|
6
|
+
import { sanitizeFolderName } from '../../../../utils/file-helpers.js';
|
|
7
|
+
/**
|
|
8
|
+
* Operation types for curating knowledge topics.
|
|
9
|
+
* Inspired by ACE Curator patterns.
|
|
10
|
+
*/
|
|
11
|
+
const OperationType = z.enum(['ADD', 'UPDATE', 'MERGE', 'DELETE']);
|
|
12
|
+
/**
|
|
13
|
+
* Content structure for ADD and UPDATE operations.
|
|
14
|
+
*/
|
|
15
|
+
const ContentSchema = z.object({
|
|
16
|
+
relations: z
|
|
17
|
+
.array(z.string())
|
|
18
|
+
.optional()
|
|
19
|
+
.describe('Related topics using @domain/topic or @domain/topic/subtopic notation'),
|
|
20
|
+
snippets: z.array(z.string()).optional().describe('Code/text snippets'),
|
|
21
|
+
});
|
|
22
|
+
/**
|
|
23
|
+
* Single operation schema for curating knowledge.
|
|
24
|
+
*/
|
|
25
|
+
const OperationSchema = z.object({
|
|
26
|
+
content: ContentSchema.optional().describe('Content for ADD/UPDATE operations'),
|
|
27
|
+
mergeTarget: z.string().optional().describe('Target path for MERGE operation'),
|
|
28
|
+
path: z.string().describe('Path: domain/topic or domain/topic/subtopic'),
|
|
29
|
+
reason: z.string().describe('Reasoning for this operation'),
|
|
30
|
+
type: OperationType.describe('Operation type: ADD, UPDATE, MERGE, or DELETE'),
|
|
31
|
+
});
|
|
32
|
+
/**
|
|
33
|
+
* Input schema for curate tool.
|
|
34
|
+
*/
|
|
35
|
+
const CurateInputSchema = z.object({
|
|
36
|
+
basePath: z.string().default('.brv/context-tree').describe('Base path for knowledge storage'),
|
|
37
|
+
operations: z.array(OperationSchema).describe('Array of curate operations to apply'),
|
|
38
|
+
});
|
|
39
|
+
/**
|
|
40
|
+
* Parse a path into domain, topic, and optional subtopic.
|
|
41
|
+
*/
|
|
42
|
+
function parsePath(path) {
|
|
43
|
+
const parts = path.split('/');
|
|
44
|
+
if (parts.length < 2 || parts.length > 3) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
domain: parts[0],
|
|
49
|
+
subtopic: parts[2],
|
|
50
|
+
topic: parts[1],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Build the full filesystem path from base path and knowledge path.
|
|
55
|
+
*/
|
|
56
|
+
function buildFullPath(basePath, knowledgePath) {
|
|
57
|
+
const parsed = parsePath(knowledgePath);
|
|
58
|
+
if (!parsed) {
|
|
59
|
+
throw new Error(`Invalid path format: ${knowledgePath}`);
|
|
60
|
+
}
|
|
61
|
+
const domainPath = join(basePath, sanitizeFolderName(parsed.domain));
|
|
62
|
+
const topicPath = join(domainPath, sanitizeFolderName(parsed.topic));
|
|
63
|
+
if (parsed.subtopic) {
|
|
64
|
+
return join(topicPath, sanitizeFolderName(parsed.subtopic));
|
|
65
|
+
}
|
|
66
|
+
return topicPath;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Execute ADD operation - create new domain/topic/subtopic with context.md
|
|
70
|
+
*/
|
|
71
|
+
async function executeAdd(basePath, operation) {
|
|
72
|
+
const { content, path, reason } = operation;
|
|
73
|
+
if (!content) {
|
|
74
|
+
return {
|
|
75
|
+
message: 'ADD operation requires content',
|
|
76
|
+
path,
|
|
77
|
+
status: 'failed',
|
|
78
|
+
type: 'ADD',
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const parsed = parsePath(path);
|
|
83
|
+
if (!parsed) {
|
|
84
|
+
return {
|
|
85
|
+
message: `Invalid path format: ${path}. Expected domain/topic or domain/topic/subtopic`,
|
|
86
|
+
path,
|
|
87
|
+
status: 'failed',
|
|
88
|
+
type: 'ADD',
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
// Ensure base structure exists
|
|
92
|
+
await DirectoryManager.ensureKnowledgeStructure(basePath);
|
|
93
|
+
// Create domain folder
|
|
94
|
+
const domainPath = join(basePath, sanitizeFolderName(parsed.domain));
|
|
95
|
+
await DirectoryManager.createOrUpdateDomain(domainPath);
|
|
96
|
+
// Create topic folder
|
|
97
|
+
const topicPath = join(domainPath, sanitizeFolderName(parsed.topic));
|
|
98
|
+
await DirectoryManager.createOrUpdateTopic(topicPath);
|
|
99
|
+
// Determine final path (topic or subtopic)
|
|
100
|
+
let finalPath = topicPath;
|
|
101
|
+
if (parsed.subtopic) {
|
|
102
|
+
finalPath = join(topicPath, sanitizeFolderName(parsed.subtopic));
|
|
103
|
+
await DirectoryManager.createOrUpdateTopic(finalPath);
|
|
104
|
+
}
|
|
105
|
+
// Generate and write context.md
|
|
106
|
+
const contextContent = MarkdownWriter.generateContext({
|
|
107
|
+
name: parsed.subtopic || parsed.topic,
|
|
108
|
+
relations: content.relations,
|
|
109
|
+
snippets: content.snippets || [],
|
|
110
|
+
});
|
|
111
|
+
const contextPath = join(finalPath, 'context.md');
|
|
112
|
+
await DirectoryManager.writeFileAtomic(contextPath, contextContent);
|
|
113
|
+
return {
|
|
114
|
+
message: `Created ${path} with ${content.snippets?.length || 0} snippets. Reason: ${reason}`,
|
|
115
|
+
path,
|
|
116
|
+
status: 'success',
|
|
117
|
+
type: 'ADD',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
return {
|
|
122
|
+
message: error instanceof Error ? error.message : String(error),
|
|
123
|
+
path,
|
|
124
|
+
status: 'failed',
|
|
125
|
+
type: 'ADD',
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Execute UPDATE operation - modify existing context.md
|
|
131
|
+
*/
|
|
132
|
+
async function executeUpdate(basePath, operation) {
|
|
133
|
+
const { content, path, reason } = operation;
|
|
134
|
+
if (!content) {
|
|
135
|
+
return {
|
|
136
|
+
message: 'UPDATE operation requires content',
|
|
137
|
+
path,
|
|
138
|
+
status: 'failed',
|
|
139
|
+
type: 'UPDATE',
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
const fullPath = buildFullPath(basePath, path);
|
|
144
|
+
const contextPath = join(fullPath, 'context.md');
|
|
145
|
+
// Check if topic exists
|
|
146
|
+
const exists = await DirectoryManager.fileExists(contextPath);
|
|
147
|
+
if (!exists) {
|
|
148
|
+
return {
|
|
149
|
+
message: `Topic does not exist: ${path}`,
|
|
150
|
+
path,
|
|
151
|
+
status: 'failed',
|
|
152
|
+
type: 'UPDATE',
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// Generate and write updated context.md (full replacement)
|
|
156
|
+
const parsed = parsePath(path);
|
|
157
|
+
const contextContent = MarkdownWriter.generateContext({
|
|
158
|
+
name: parsed?.subtopic || parsed?.topic || path,
|
|
159
|
+
relations: content.relations,
|
|
160
|
+
snippets: content.snippets || [],
|
|
161
|
+
});
|
|
162
|
+
await DirectoryManager.writeFileAtomic(contextPath, contextContent);
|
|
163
|
+
return {
|
|
164
|
+
message: `Updated ${path}. Reason: ${reason}`,
|
|
165
|
+
path,
|
|
166
|
+
status: 'success',
|
|
167
|
+
type: 'UPDATE',
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
return {
|
|
172
|
+
message: error instanceof Error ? error.message : String(error),
|
|
173
|
+
path,
|
|
174
|
+
status: 'failed',
|
|
175
|
+
type: 'UPDATE',
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Execute MERGE operation - combine source into target, delete source
|
|
181
|
+
*/
|
|
182
|
+
async function executeMerge(basePath, operation) {
|
|
183
|
+
const { mergeTarget, path, reason } = operation;
|
|
184
|
+
if (!mergeTarget) {
|
|
185
|
+
return {
|
|
186
|
+
message: 'MERGE operation requires mergeTarget',
|
|
187
|
+
path,
|
|
188
|
+
status: 'failed',
|
|
189
|
+
type: 'MERGE',
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
try {
|
|
193
|
+
const sourcePath = buildFullPath(basePath, path);
|
|
194
|
+
const targetPath = buildFullPath(basePath, mergeTarget);
|
|
195
|
+
const sourceContextPath = join(sourcePath, 'context.md');
|
|
196
|
+
const targetContextPath = join(targetPath, 'context.md');
|
|
197
|
+
// Check if both exist
|
|
198
|
+
const sourceExists = await DirectoryManager.fileExists(sourceContextPath);
|
|
199
|
+
const targetExists = await DirectoryManager.fileExists(targetContextPath);
|
|
200
|
+
if (!sourceExists) {
|
|
201
|
+
return {
|
|
202
|
+
message: `Source topic does not exist: ${path}`,
|
|
203
|
+
path,
|
|
204
|
+
status: 'failed',
|
|
205
|
+
type: 'MERGE',
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
if (!targetExists) {
|
|
209
|
+
return {
|
|
210
|
+
message: `Target topic does not exist: ${mergeTarget}`,
|
|
211
|
+
path,
|
|
212
|
+
status: 'failed',
|
|
213
|
+
type: 'MERGE',
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
// Read both contexts
|
|
217
|
+
const sourceContent = await DirectoryManager.readFile(sourceContextPath);
|
|
218
|
+
const targetContent = await DirectoryManager.readFile(targetContextPath);
|
|
219
|
+
// Merge the contexts using MarkdownWriter
|
|
220
|
+
const mergedContent = MarkdownWriter.mergeContexts(sourceContent, targetContent);
|
|
221
|
+
await DirectoryManager.writeFileAtomic(targetContextPath, mergedContent);
|
|
222
|
+
// Delete source folder
|
|
223
|
+
await DirectoryManager.deleteTopicRecursive(sourcePath);
|
|
224
|
+
return {
|
|
225
|
+
message: `Merged ${path} into ${mergeTarget}. Reason: ${reason}`,
|
|
226
|
+
path,
|
|
227
|
+
status: 'success',
|
|
228
|
+
type: 'MERGE',
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
return {
|
|
233
|
+
message: error instanceof Error ? error.message : String(error),
|
|
234
|
+
path,
|
|
235
|
+
status: 'failed',
|
|
236
|
+
type: 'MERGE',
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Execute DELETE operation - remove topic/subtopic folder recursively
|
|
242
|
+
*/
|
|
243
|
+
async function executeDelete(basePath, operation) {
|
|
244
|
+
const { path, reason } = operation;
|
|
245
|
+
try {
|
|
246
|
+
const fullPath = buildFullPath(basePath, path);
|
|
247
|
+
const contextPath = join(fullPath, 'context.md');
|
|
248
|
+
// Check if topic exists
|
|
249
|
+
const exists = await DirectoryManager.fileExists(contextPath);
|
|
250
|
+
if (!exists) {
|
|
251
|
+
return {
|
|
252
|
+
message: `Topic does not exist: ${path}`,
|
|
253
|
+
path,
|
|
254
|
+
status: 'failed',
|
|
255
|
+
type: 'DELETE',
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
// Delete folder recursively
|
|
259
|
+
await DirectoryManager.deleteTopicRecursive(fullPath);
|
|
260
|
+
return {
|
|
261
|
+
message: `Deleted ${path}. Reason: ${reason}`,
|
|
262
|
+
path,
|
|
263
|
+
status: 'success',
|
|
264
|
+
type: 'DELETE',
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
return {
|
|
269
|
+
message: error instanceof Error ? error.message : String(error),
|
|
270
|
+
path,
|
|
271
|
+
status: 'failed',
|
|
272
|
+
type: 'DELETE',
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Execute curate operations on knowledge topics.
|
|
278
|
+
*/
|
|
279
|
+
async function executeCurate(input, _context) {
|
|
280
|
+
const { basePath, operations } = input;
|
|
281
|
+
const applied = [];
|
|
282
|
+
const summary = {
|
|
283
|
+
added: 0,
|
|
284
|
+
deleted: 0,
|
|
285
|
+
failed: 0,
|
|
286
|
+
merged: 0,
|
|
287
|
+
updated: 0,
|
|
288
|
+
};
|
|
289
|
+
// Process operations sequentially to maintain consistency
|
|
290
|
+
/* eslint-disable no-await-in-loop -- Sequential processing required for dependent operations */
|
|
291
|
+
for (const operation of operations) {
|
|
292
|
+
let result;
|
|
293
|
+
switch (operation.type) {
|
|
294
|
+
case 'ADD': {
|
|
295
|
+
result = await executeAdd(basePath, operation);
|
|
296
|
+
if (result.status === 'success')
|
|
297
|
+
summary.added++;
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
case 'DELETE': {
|
|
301
|
+
result = await executeDelete(basePath, operation);
|
|
302
|
+
if (result.status === 'success')
|
|
303
|
+
summary.deleted++;
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
case 'MERGE': {
|
|
307
|
+
result = await executeMerge(basePath, operation);
|
|
308
|
+
if (result.status === 'success')
|
|
309
|
+
summary.merged++;
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
case 'UPDATE': {
|
|
313
|
+
result = await executeUpdate(basePath, operation);
|
|
314
|
+
if (result.status === 'success')
|
|
315
|
+
summary.updated++;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
default: {
|
|
319
|
+
result = {
|
|
320
|
+
message: `Unknown operation type: ${operation.type}`,
|
|
321
|
+
path: operation.path,
|
|
322
|
+
status: 'failed',
|
|
323
|
+
type: operation.type,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (result.status === 'failed') {
|
|
328
|
+
summary.failed++;
|
|
329
|
+
}
|
|
330
|
+
applied.push(result);
|
|
331
|
+
}
|
|
332
|
+
/* eslint-enable no-await-in-loop */
|
|
333
|
+
return { applied, summary };
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Creates the curate tool.
|
|
337
|
+
*
|
|
338
|
+
* This tool manages knowledge topics with atomic operations (ADD, UPDATE, MERGE, DELETE).
|
|
339
|
+
* It applies patterns from the ACE Curator for intelligent knowledge curation.
|
|
340
|
+
*
|
|
341
|
+
* @returns Configured curate tool
|
|
342
|
+
*/
|
|
343
|
+
export function createCurateTool() {
|
|
344
|
+
return {
|
|
345
|
+
description: `Curate knowledge topics with atomic operations. This tool manages the knowledge structure using four operation types:
|
|
346
|
+
|
|
347
|
+
**Operations:**
|
|
348
|
+
1. **ADD** - Create new domain/topic/subtopic with context.md
|
|
349
|
+
- Requires: path, content (snippets and/or relations), reason
|
|
350
|
+
- Example: { type: "ADD", path: "code_style/error-handling", content: { snippets: ["..."], relations: ["logging/basics"] }, reason: "New pattern identified" }
|
|
351
|
+
|
|
352
|
+
2. **UPDATE** - Modify existing context.md (full replacement)
|
|
353
|
+
- Requires: path, content, reason
|
|
354
|
+
- Example: { type: "UPDATE", path: "code_style/error-handling", content: { snippets: ["Updated content"] }, reason: "Improved guidance" }
|
|
355
|
+
|
|
356
|
+
3. **MERGE** - Combine source topic into target, delete source
|
|
357
|
+
- Requires: path (source), mergeTarget (destination), reason
|
|
358
|
+
- Example: { type: "MERGE", path: "code_style/old-topic", mergeTarget: "code_style/new-topic", reason: "Consolidating duplicates" }
|
|
359
|
+
|
|
360
|
+
4. **DELETE** - Remove topic/subtopic folder recursively
|
|
361
|
+
- Requires: path, reason
|
|
362
|
+
- Example: { type: "DELETE", path: "code_style/deprecated-topic", reason: "No longer relevant" }
|
|
363
|
+
|
|
364
|
+
**Path format:** domain/topic or domain/topic/subtopic
|
|
365
|
+
|
|
366
|
+
**Output:** Returns applied operations with status (success/failed) and a summary of counts.`,
|
|
367
|
+
execute: executeCurate,
|
|
368
|
+
id: ToolName.CURATE,
|
|
369
|
+
inputSchema: CurateInputSchema,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import { BRV_DIR, CONTEXT_FILE, CONTEXT_TREE_DIR } from '../../../../constants.js';
|
|
3
4
|
import { ToolName } from '../../../../core/domain/cipher/tools/constants.js';
|
|
4
5
|
import { DirectoryManager } from '../../../../core/domain/knowledge/directory-manager.js';
|
|
5
6
|
import { parseRelations } from '../../../../core/domain/knowledge/relation-parser.js';
|
|
@@ -10,7 +11,7 @@ import { parseRelations } from '../../../../core/domain/knowledge/relation-parse
|
|
|
10
11
|
const FindKnowledgeTopicsInputSchema = z.object({
|
|
11
12
|
basePath: z
|
|
12
13
|
.string()
|
|
13
|
-
.default(
|
|
14
|
+
.default(`${BRV_DIR}/${CONTEXT_TREE_DIR}`)
|
|
14
15
|
.describe('Base path to context tree structure'),
|
|
15
16
|
// Scoping
|
|
16
17
|
domain: z
|
|
@@ -96,7 +97,7 @@ async function processSubtopicFile(params) {
|
|
|
96
97
|
const subtopicRelativePath = subtopicFile.replace(topicPath, '').replace(/^\//, '');
|
|
97
98
|
const subtopicParts = subtopicRelativePath.split('/');
|
|
98
99
|
// Check if this is a subtopic context.md (not the topic's own context.md)
|
|
99
|
-
if (subtopicParts.length <= 1 || subtopicParts.at(-1) !==
|
|
100
|
+
if (subtopicParts.length <= 1 || subtopicParts.at(-1) !== CONTEXT_FILE) {
|
|
100
101
|
return null;
|
|
101
102
|
}
|
|
102
103
|
const subtopicName = subtopicParts[0];
|
|
@@ -106,7 +107,7 @@ async function processSubtopicFile(params) {
|
|
|
106
107
|
}
|
|
107
108
|
const subtopicEntry = {
|
|
108
109
|
name: subtopicName,
|
|
109
|
-
path: `${domainName}/${topicName}/${subtopicName}
|
|
110
|
+
path: `${BRV_DIR}/${CONTEXT_TREE_DIR}/${domainName}/${topicName}/${subtopicName}/${CONTEXT_FILE}` // Full path
|
|
110
111
|
};
|
|
111
112
|
// Include subtopic content preview if requested
|
|
112
113
|
if (includeContent) {
|
|
@@ -210,7 +211,7 @@ async function fetchRelatedTopics(params) {
|
|
|
210
211
|
if (parts.length < 2 || parts.length > 3)
|
|
211
212
|
continue;
|
|
212
213
|
const [domainName, topicName] = parts;
|
|
213
|
-
const contextPath = join(basePath, ...parts,
|
|
214
|
+
const contextPath = join(basePath, ...parts, CONTEXT_FILE);
|
|
214
215
|
try {
|
|
215
216
|
// eslint-disable-next-line no-await-in-loop
|
|
216
217
|
const fileExists = await DirectoryManager.fileExists(contextPath);
|
|
@@ -218,7 +219,7 @@ async function fetchRelatedTopics(params) {
|
|
|
218
219
|
continue;
|
|
219
220
|
const entry = {
|
|
220
221
|
domain: domainName,
|
|
221
|
-
path: relationPath
|
|
222
|
+
path: `${basePath}/${relationPath}/${CONTEXT_FILE}`,
|
|
222
223
|
topic: topicName,
|
|
223
224
|
};
|
|
224
225
|
// Include content preview if requested
|
|
@@ -281,8 +282,10 @@ async function executeFindKnowledgeTopics(input, _context) {
|
|
|
281
282
|
const isSubtopic = rest.length > 1; // Has subtopic folder
|
|
282
283
|
// Skip if not a context.md file (only process context files)
|
|
283
284
|
const fileName = parts.at(-1);
|
|
284
|
-
if (fileName !==
|
|
285
|
+
if (fileName !== CONTEXT_FILE)
|
|
285
286
|
continue;
|
|
287
|
+
if (parts.length === 2)
|
|
288
|
+
continue; // Skip domain context.md files because they don't have much info
|
|
286
289
|
// Handle subtopic pattern filtering (case-insensitive)
|
|
287
290
|
if (isSubtopic) {
|
|
288
291
|
const subtopicName = rest[0];
|
|
@@ -309,7 +312,7 @@ async function executeFindKnowledgeTopics(input, _context) {
|
|
|
309
312
|
// Build result entry for this topic
|
|
310
313
|
const entry = {
|
|
311
314
|
domain: domainName,
|
|
312
|
-
path: `${domainName}/${topicName}`,
|
|
315
|
+
path: `${basePath}/${domainName}/${topicName}/${CONTEXT_FILE}`,
|
|
313
316
|
topic: topicName,
|
|
314
317
|
};
|
|
315
318
|
// Include content preview if requested
|
|
@@ -413,7 +416,7 @@ This tool helps discover what knowledge has been stored and navigate the domain/
|
|
|
413
416
|
|
|
414
417
|
**Returns:**
|
|
415
418
|
- total: Total number of matching topics (before relation traversal)
|
|
416
|
-
- results: Array of topic entries with domain, topic name,
|
|
419
|
+
- results: Array of topic entries with domain, topic name, optional relations, subtopics, and content with complete paths`,
|
|
417
420
|
execute: executeFindKnowledgeTopics,
|
|
418
421
|
id: ToolName.FIND_KNOWLEDGE_TOPICS,
|
|
419
422
|
inputSchema: FindKnowledgeTopicsInputSchema,
|
|
@@ -21,6 +21,10 @@ import { type ToolExecutionResult } from '../../../core/domain/cipher/tools/tool
|
|
|
21
21
|
* Without a scheduler, tools execute directly via the provider.
|
|
22
22
|
*/
|
|
23
23
|
export declare class ToolManager {
|
|
24
|
+
/**
|
|
25
|
+
* Tools allowed for curate operations
|
|
26
|
+
*/
|
|
27
|
+
private static readonly CURATE_TOOL_NAMES;
|
|
24
28
|
/**
|
|
25
29
|
* Read-only tools allowed for query operations
|
|
26
30
|
*/
|
|
@@ -83,9 +87,10 @@ export declare class ToolManager {
|
|
|
83
87
|
/**
|
|
84
88
|
* Get filtered tool names based on command type.
|
|
85
89
|
* For 'query' command, returns only read-only discovery tools.
|
|
90
|
+
* For 'curate' command, returns only curate-specific tools.
|
|
86
91
|
* For other commands, returns all tools.
|
|
87
92
|
*
|
|
88
|
-
* @param commandType - The command type ('
|
|
93
|
+
* @param commandType - The command type ('curate', 'query', etc.)
|
|
89
94
|
* @returns Array of filtered tool names
|
|
90
95
|
*/
|
|
91
96
|
getToolNamesForCommand(commandType?: string): string[];
|
|
@@ -99,9 +104,10 @@ export declare class ToolManager {
|
|
|
99
104
|
/**
|
|
100
105
|
* Get filtered tools based on command type.
|
|
101
106
|
* For 'query' command, returns only read-only discovery tools.
|
|
107
|
+
* For 'curate' command, returns only curate-specific tools.
|
|
102
108
|
* For other commands, returns all tools.
|
|
103
109
|
*
|
|
104
|
-
* @param commandType - The command type ('
|
|
110
|
+
* @param commandType - The command type ('curate', 'query', etc.)
|
|
105
111
|
* @returns Filtered tool set with JSON Schema definitions
|
|
106
112
|
*/
|
|
107
113
|
getToolsForCommand(commandType?: string): ToolSet;
|
|
@@ -17,6 +17,17 @@ import { ToolError, ToolErrorType, ToolErrorUtils } from '../../../core/domain/c
|
|
|
17
17
|
* Without a scheduler, tools execute directly via the provider.
|
|
18
18
|
*/
|
|
19
19
|
export class ToolManager {
|
|
20
|
+
/**
|
|
21
|
+
* Tools allowed for curate operations
|
|
22
|
+
*/
|
|
23
|
+
static CURATE_TOOL_NAMES = [
|
|
24
|
+
'detect_domains',
|
|
25
|
+
'find_knowledge_topics',
|
|
26
|
+
'read_file',
|
|
27
|
+
'grep_content',
|
|
28
|
+
'glob_files',
|
|
29
|
+
'curate',
|
|
30
|
+
];
|
|
20
31
|
/**
|
|
21
32
|
* Read-only tools allowed for query operations
|
|
22
33
|
*/
|
|
@@ -124,9 +135,10 @@ export class ToolManager {
|
|
|
124
135
|
/**
|
|
125
136
|
* Get filtered tool names based on command type.
|
|
126
137
|
* For 'query' command, returns only read-only discovery tools.
|
|
138
|
+
* For 'curate' command, returns only curate-specific tools.
|
|
127
139
|
* For other commands, returns all tools.
|
|
128
140
|
*
|
|
129
|
-
* @param commandType - The command type ('
|
|
141
|
+
* @param commandType - The command type ('curate', 'query', etc.)
|
|
130
142
|
* @returns Array of filtered tool names
|
|
131
143
|
*/
|
|
132
144
|
getToolNamesForCommand(commandType) {
|
|
@@ -134,6 +146,10 @@ export class ToolManager {
|
|
|
134
146
|
// For query: only allow read-only tools
|
|
135
147
|
return [...ToolManager.QUERY_TOOL_NAMES].filter((name) => this.hasTool(name));
|
|
136
148
|
}
|
|
149
|
+
if (commandType === 'curate') {
|
|
150
|
+
// For curate: only allow curate tools
|
|
151
|
+
return [...ToolManager.CURATE_TOOL_NAMES].filter((name) => this.hasTool(name));
|
|
152
|
+
}
|
|
137
153
|
// For all other commands: return all tools
|
|
138
154
|
return this.getToolNames();
|
|
139
155
|
}
|
|
@@ -149,9 +165,10 @@ export class ToolManager {
|
|
|
149
165
|
/**
|
|
150
166
|
* Get filtered tools based on command type.
|
|
151
167
|
* For 'query' command, returns only read-only discovery tools.
|
|
168
|
+
* For 'curate' command, returns only curate-specific tools.
|
|
152
169
|
* For other commands, returns all tools.
|
|
153
170
|
*
|
|
154
|
-
* @param commandType - The command type ('
|
|
171
|
+
* @param commandType - The command type ('curate', 'query', etc.)
|
|
155
172
|
* @returns Filtered tool set with JSON Schema definitions
|
|
156
173
|
*/
|
|
157
174
|
getToolsForCommand(commandType) {
|
|
@@ -166,6 +183,16 @@ export class ToolManager {
|
|
|
166
183
|
}
|
|
167
184
|
return filteredTools;
|
|
168
185
|
}
|
|
186
|
+
if (commandType === 'curate') {
|
|
187
|
+
// For curate: only allow curate tools
|
|
188
|
+
const filteredTools = {};
|
|
189
|
+
for (const toolName of ToolManager.CURATE_TOOL_NAMES) {
|
|
190
|
+
if (allTools[toolName]) {
|
|
191
|
+
filteredTools[toolName] = allTools[toolName];
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return filteredTools;
|
|
195
|
+
}
|
|
169
196
|
// For all other commands: return all tools
|
|
170
197
|
return allTools;
|
|
171
198
|
}
|
|
@@ -2,6 +2,7 @@ import { ToolName } from '../../../core/domain/cipher/tools/constants.js';
|
|
|
2
2
|
import { createBashExecTool } from './implementations/bash-exec-tool.js';
|
|
3
3
|
import { createBashOutputTool } from './implementations/bash-output-tool.js';
|
|
4
4
|
import { createCreateKnowledgeTopicTool } from './implementations/create-knowledge-topic-tool.js';
|
|
5
|
+
import { createCurateTool } from './implementations/curate-tool.js';
|
|
5
6
|
import { createDeleteMemoryTool } from './implementations/delete-memory-tool.js';
|
|
6
7
|
import { createDetectDomainsTool } from './implementations/detect-domains-tool.js';
|
|
7
8
|
import { createEditFileTool } from './implementations/edit-file-tool.js';
|
|
@@ -59,6 +60,12 @@ export const TOOL_REGISTRY = {
|
|
|
59
60
|
outputGuidance: 'create_knowledge_topic',
|
|
60
61
|
requiredServices: [], // Uses DirectoryManager for file operations
|
|
61
62
|
},
|
|
63
|
+
[ToolName.CURATE]: {
|
|
64
|
+
factory: () => createCurateTool(),
|
|
65
|
+
markers: [ToolMarker.ContextBuilding, ToolMarker.Modification],
|
|
66
|
+
outputGuidance: 'curate',
|
|
67
|
+
requiredServices: [], // Uses DirectoryManager and MarkdownWriter for file operations
|
|
68
|
+
},
|
|
62
69
|
[ToolName.DELETE_MEMORY]: {
|
|
63
70
|
factory: (services) => createDeleteMemoryTool(getRequiredService(services.memoryManager, 'memoryManager')),
|
|
64
71
|
markers: [ToolMarker.ContextBuilding],
|
|
@@ -43,4 +43,25 @@ export declare class AuthenticatedHttpClient implements IHttpClient {
|
|
|
43
43
|
* Preserves error information while abstracting axios-specific details.
|
|
44
44
|
*/
|
|
45
45
|
private handleError;
|
|
46
|
+
/**
|
|
47
|
+
* Type guard to check if error is an axios error with response.
|
|
48
|
+
*/
|
|
49
|
+
private isLLMServerError;
|
|
50
|
+
/**
|
|
51
|
+
* Parse HTTP error to extract user-friendly error message.
|
|
52
|
+
*
|
|
53
|
+
* Handles standardized API error responses from the server:
|
|
54
|
+
* ```json
|
|
55
|
+
* {
|
|
56
|
+
* "statusCode": 401,
|
|
57
|
+
* "code": "AUTH_INVALID_TOKEN",
|
|
58
|
+
* "message": "Your authentication token is invalid. Please login again.",
|
|
59
|
+
* "timestamp": "2024-01-01T00:00:00.000Z"
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @param error - HTTP error object (may contain response data)
|
|
64
|
+
* @returns User-friendly error message
|
|
65
|
+
*/
|
|
66
|
+
private parseHttpError;
|
|
46
67
|
}
|
|
@@ -76,6 +76,10 @@ export class AuthenticatedHttpClient {
|
|
|
76
76
|
* Preserves error information while abstracting axios-specific details.
|
|
77
77
|
*/
|
|
78
78
|
handleError(error) {
|
|
79
|
+
if (this.isLLMServerError(error)) {
|
|
80
|
+
// Extract standardized API error message
|
|
81
|
+
return new Error(this.parseHttpError(error));
|
|
82
|
+
}
|
|
79
83
|
if (isAxiosError(error)) {
|
|
80
84
|
if (error.response) {
|
|
81
85
|
// Server responded with error status
|
|
@@ -96,4 +100,38 @@ export class AuthenticatedHttpClient {
|
|
|
96
100
|
}
|
|
97
101
|
return new Error('Unknown error occurred');
|
|
98
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Type guard to check if error is an axios error with response.
|
|
105
|
+
*/
|
|
106
|
+
isLLMServerError(error) {
|
|
107
|
+
return (typeof error === 'object' &&
|
|
108
|
+
error !== null &&
|
|
109
|
+
'response' in error &&
|
|
110
|
+
typeof error.response === 'object');
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Parse HTTP error to extract user-friendly error message.
|
|
114
|
+
*
|
|
115
|
+
* Handles standardized API error responses from the server:
|
|
116
|
+
* ```json
|
|
117
|
+
* {
|
|
118
|
+
* "statusCode": 401,
|
|
119
|
+
* "code": "AUTH_INVALID_TOKEN",
|
|
120
|
+
* "message": "Your authentication token is invalid. Please login again.",
|
|
121
|
+
* "timestamp": "2024-01-01T00:00:00.000Z"
|
|
122
|
+
* }
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* @param error - HTTP error object (may contain response data)
|
|
126
|
+
* @returns User-friendly error message
|
|
127
|
+
*/
|
|
128
|
+
parseHttpError(error) {
|
|
129
|
+
const responseData = error.response.data;
|
|
130
|
+
// If server returned standardized API error format, use the message
|
|
131
|
+
if ('message' in responseData && typeof responseData.message === 'string') {
|
|
132
|
+
return responseData.message;
|
|
133
|
+
}
|
|
134
|
+
// Fallback to HTTP status error
|
|
135
|
+
return `HTTP ${error.response.status}: ${error.response.statusText}`;
|
|
136
|
+
}
|
|
99
137
|
}
|