@vibeframe/cli 0.27.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/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-lint.log +21 -0
- package/.turbo/turbo-test.log +689 -0
- package/dist/agent/adapters/claude.d.ts +15 -0
- package/dist/agent/adapters/claude.d.ts.map +1 -0
- package/dist/agent/adapters/claude.js +119 -0
- package/dist/agent/adapters/claude.js.map +1 -0
- package/dist/agent/adapters/gemini.d.ts +15 -0
- package/dist/agent/adapters/gemini.d.ts.map +1 -0
- package/dist/agent/adapters/gemini.js +132 -0
- package/dist/agent/adapters/gemini.js.map +1 -0
- package/dist/agent/adapters/index.d.ts +27 -0
- package/dist/agent/adapters/index.d.ts.map +1 -0
- package/dist/agent/adapters/index.js +38 -0
- package/dist/agent/adapters/index.js.map +1 -0
- package/dist/agent/adapters/ollama.d.ts +20 -0
- package/dist/agent/adapters/ollama.d.ts.map +1 -0
- package/dist/agent/adapters/ollama.js +186 -0
- package/dist/agent/adapters/ollama.js.map +1 -0
- package/dist/agent/adapters/openai.d.ts +15 -0
- package/dist/agent/adapters/openai.d.ts.map +1 -0
- package/dist/agent/adapters/openai.js +92 -0
- package/dist/agent/adapters/openai.js.map +1 -0
- package/dist/agent/adapters/xai.d.ts +15 -0
- package/dist/agent/adapters/xai.d.ts.map +1 -0
- package/dist/agent/adapters/xai.js +95 -0
- package/dist/agent/adapters/xai.js.map +1 -0
- package/dist/agent/index.d.ts +69 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +180 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/memory/index.d.ts +70 -0
- package/dist/agent/memory/index.d.ts.map +1 -0
- package/dist/agent/memory/index.js +132 -0
- package/dist/agent/memory/index.js.map +1 -0
- package/dist/agent/prompts/system.d.ts +6 -0
- package/dist/agent/prompts/system.d.ts.map +1 -0
- package/dist/agent/prompts/system.js +103 -0
- package/dist/agent/prompts/system.js.map +1 -0
- package/dist/agent/tools/ai-editing.d.ts +15 -0
- package/dist/agent/tools/ai-editing.d.ts.map +1 -0
- package/dist/agent/tools/ai-editing.js +763 -0
- package/dist/agent/tools/ai-editing.js.map +1 -0
- package/dist/agent/tools/ai-generation.d.ts +13 -0
- package/dist/agent/tools/ai-generation.d.ts.map +1 -0
- package/dist/agent/tools/ai-generation.js +973 -0
- package/dist/agent/tools/ai-generation.js.map +1 -0
- package/dist/agent/tools/ai-pipeline.d.ts +14 -0
- package/dist/agent/tools/ai-pipeline.d.ts.map +1 -0
- package/dist/agent/tools/ai-pipeline.js +961 -0
- package/dist/agent/tools/ai-pipeline.js.map +1 -0
- package/dist/agent/tools/ai.d.ts +13 -0
- package/dist/agent/tools/ai.d.ts.map +1 -0
- package/dist/agent/tools/ai.js +19 -0
- package/dist/agent/tools/ai.js.map +1 -0
- package/dist/agent/tools/batch.d.ts +6 -0
- package/dist/agent/tools/batch.d.ts.map +1 -0
- package/dist/agent/tools/batch.js +383 -0
- package/dist/agent/tools/batch.js.map +1 -0
- package/dist/agent/tools/e2e.test.d.ts +26 -0
- package/dist/agent/tools/e2e.test.d.ts.map +1 -0
- package/dist/agent/tools/e2e.test.js +397 -0
- package/dist/agent/tools/e2e.test.js.map +1 -0
- package/dist/agent/tools/export.d.ts +6 -0
- package/dist/agent/tools/export.d.ts.map +1 -0
- package/dist/agent/tools/export.js +171 -0
- package/dist/agent/tools/export.js.map +1 -0
- package/dist/agent/tools/filesystem.d.ts +6 -0
- package/dist/agent/tools/filesystem.d.ts.map +1 -0
- package/dist/agent/tools/filesystem.js +212 -0
- package/dist/agent/tools/filesystem.js.map +1 -0
- package/dist/agent/tools/index.d.ts +65 -0
- package/dist/agent/tools/index.d.ts.map +1 -0
- package/dist/agent/tools/index.js +120 -0
- package/dist/agent/tools/index.js.map +1 -0
- package/dist/agent/tools/integration.test.d.ts +11 -0
- package/dist/agent/tools/integration.test.d.ts.map +1 -0
- package/dist/agent/tools/integration.test.js +659 -0
- package/dist/agent/tools/integration.test.js.map +1 -0
- package/dist/agent/tools/media.d.ts +6 -0
- package/dist/agent/tools/media.d.ts.map +1 -0
- package/dist/agent/tools/media.js +616 -0
- package/dist/agent/tools/media.js.map +1 -0
- package/dist/agent/tools/project.d.ts +6 -0
- package/dist/agent/tools/project.d.ts.map +1 -0
- package/dist/agent/tools/project.js +284 -0
- package/dist/agent/tools/project.js.map +1 -0
- package/dist/agent/tools/timeline.d.ts +6 -0
- package/dist/agent/tools/timeline.d.ts.map +1 -0
- package/dist/agent/tools/timeline.js +873 -0
- package/dist/agent/tools/timeline.js.map +1 -0
- package/dist/agent/types.d.ts +59 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +5 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/commands/agent.d.ts +21 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +290 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/ai-analyze.d.ts +106 -0
- package/dist/commands/ai-analyze.d.ts.map +1 -0
- package/dist/commands/ai-analyze.js +327 -0
- package/dist/commands/ai-analyze.js.map +1 -0
- package/dist/commands/ai-animated-caption.d.ts +64 -0
- package/dist/commands/ai-animated-caption.d.ts.map +1 -0
- package/dist/commands/ai-animated-caption.js +272 -0
- package/dist/commands/ai-animated-caption.js.map +1 -0
- package/dist/commands/ai-audio.d.ts +20 -0
- package/dist/commands/ai-audio.d.ts.map +1 -0
- package/dist/commands/ai-audio.js +808 -0
- package/dist/commands/ai-audio.js.map +1 -0
- package/dist/commands/ai-broll.d.ts +15 -0
- package/dist/commands/ai-broll.d.ts.map +1 -0
- package/dist/commands/ai-broll.js +406 -0
- package/dist/commands/ai-broll.js.map +1 -0
- package/dist/commands/ai-edit-cli.d.ts +14 -0
- package/dist/commands/ai-edit-cli.d.ts.map +1 -0
- package/dist/commands/ai-edit-cli.js +579 -0
- package/dist/commands/ai-edit-cli.js.map +1 -0
- package/dist/commands/ai-edit.d.ts +398 -0
- package/dist/commands/ai-edit.d.ts.map +1 -0
- package/dist/commands/ai-edit.js +1019 -0
- package/dist/commands/ai-edit.js.map +1 -0
- package/dist/commands/ai-fill-gaps.d.ts +14 -0
- package/dist/commands/ai-fill-gaps.d.ts.map +1 -0
- package/dist/commands/ai-fill-gaps.js +451 -0
- package/dist/commands/ai-fill-gaps.js.map +1 -0
- package/dist/commands/ai-helpers.d.ts +20 -0
- package/dist/commands/ai-helpers.d.ts.map +1 -0
- package/dist/commands/ai-helpers.js +59 -0
- package/dist/commands/ai-helpers.js.map +1 -0
- package/dist/commands/ai-highlights.d.ts +127 -0
- package/dist/commands/ai-highlights.d.ts.map +1 -0
- package/dist/commands/ai-highlights.js +1026 -0
- package/dist/commands/ai-highlights.js.map +1 -0
- package/dist/commands/ai-image.d.ts +34 -0
- package/dist/commands/ai-image.d.ts.map +1 -0
- package/dist/commands/ai-image.js +653 -0
- package/dist/commands/ai-image.js.map +1 -0
- package/dist/commands/ai-motion.d.ts +50 -0
- package/dist/commands/ai-motion.d.ts.map +1 -0
- package/dist/commands/ai-motion.js +271 -0
- package/dist/commands/ai-motion.js.map +1 -0
- package/dist/commands/ai-narrate.d.ts +66 -0
- package/dist/commands/ai-narrate.d.ts.map +1 -0
- package/dist/commands/ai-narrate.js +329 -0
- package/dist/commands/ai-narrate.js.map +1 -0
- package/dist/commands/ai-review.d.ts +57 -0
- package/dist/commands/ai-review.d.ts.map +1 -0
- package/dist/commands/ai-review.js +251 -0
- package/dist/commands/ai-review.js.map +1 -0
- package/dist/commands/ai-script-pipeline-cli.d.ts +9 -0
- package/dist/commands/ai-script-pipeline-cli.d.ts.map +1 -0
- package/dist/commands/ai-script-pipeline-cli.js +1494 -0
- package/dist/commands/ai-script-pipeline-cli.js.map +1 -0
- package/dist/commands/ai-script-pipeline.d.ts +259 -0
- package/dist/commands/ai-script-pipeline.d.ts.map +1 -0
- package/dist/commands/ai-script-pipeline.js +1027 -0
- package/dist/commands/ai-script-pipeline.js.map +1 -0
- package/dist/commands/ai-suggest-edit.d.ts +14 -0
- package/dist/commands/ai-suggest-edit.d.ts.map +1 -0
- package/dist/commands/ai-suggest-edit.js +220 -0
- package/dist/commands/ai-suggest-edit.js.map +1 -0
- package/dist/commands/ai-video-fx.d.ts +14 -0
- package/dist/commands/ai-video-fx.d.ts.map +1 -0
- package/dist/commands/ai-video-fx.js +395 -0
- package/dist/commands/ai-video-fx.js.map +1 -0
- package/dist/commands/ai-video.d.ts +15 -0
- package/dist/commands/ai-video.d.ts.map +1 -0
- package/dist/commands/ai-video.js +785 -0
- package/dist/commands/ai-video.js.map +1 -0
- package/dist/commands/ai-viral.d.ts +15 -0
- package/dist/commands/ai-viral.d.ts.map +1 -0
- package/dist/commands/ai-viral.js +519 -0
- package/dist/commands/ai-viral.js.map +1 -0
- package/dist/commands/ai-visual-fx.d.ts +14 -0
- package/dist/commands/ai-visual-fx.d.ts.map +1 -0
- package/dist/commands/ai-visual-fx.js +505 -0
- package/dist/commands/ai-visual-fx.js.map +1 -0
- package/dist/commands/ai.d.ts +38 -0
- package/dist/commands/ai.d.ts.map +1 -0
- package/dist/commands/ai.js +225 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/ai.test.d.ts +2 -0
- package/dist/commands/ai.test.d.ts.map +1 -0
- package/dist/commands/ai.test.js +554 -0
- package/dist/commands/ai.test.js.map +1 -0
- package/dist/commands/analyze.d.ts +16 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +247 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/audio.d.ts +18 -0
- package/dist/commands/audio.d.ts.map +1 -0
- package/dist/commands/audio.js +539 -0
- package/dist/commands/audio.js.map +1 -0
- package/dist/commands/batch.d.ts +3 -0
- package/dist/commands/batch.d.ts.map +1 -0
- package/dist/commands/batch.js +366 -0
- package/dist/commands/batch.js.map +1 -0
- package/dist/commands/batch.test.d.ts +2 -0
- package/dist/commands/batch.test.d.ts.map +1 -0
- package/dist/commands/batch.test.js +203 -0
- package/dist/commands/batch.test.js.map +1 -0
- package/dist/commands/detect.d.ts +3 -0
- package/dist/commands/detect.d.ts.map +1 -0
- package/dist/commands/detect.js +273 -0
- package/dist/commands/detect.js.map +1 -0
- package/dist/commands/doctor.d.ts +6 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +191 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/edit-cmd.d.ts +26 -0
- package/dist/commands/edit-cmd.d.ts.map +1 -0
- package/dist/commands/edit-cmd.js +870 -0
- package/dist/commands/edit-cmd.js.map +1 -0
- package/dist/commands/export.d.ts +39 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +730 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/generate.d.ts +25 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +1885 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/media.d.ts +3 -0
- package/dist/commands/media.d.ts.map +1 -0
- package/dist/commands/media.js +165 -0
- package/dist/commands/media.js.map +1 -0
- package/dist/commands/output.d.ts +45 -0
- package/dist/commands/output.d.ts.map +1 -0
- package/dist/commands/output.js +122 -0
- package/dist/commands/output.js.map +1 -0
- package/dist/commands/pipeline.d.ts +19 -0
- package/dist/commands/pipeline.d.ts.map +1 -0
- package/dist/commands/pipeline.js +345 -0
- package/dist/commands/pipeline.js.map +1 -0
- package/dist/commands/project.d.ts +3 -0
- package/dist/commands/project.d.ts.map +1 -0
- package/dist/commands/project.js +139 -0
- package/dist/commands/project.js.map +1 -0
- package/dist/commands/project.test.d.ts +2 -0
- package/dist/commands/project.test.d.ts.map +1 -0
- package/dist/commands/project.test.js +105 -0
- package/dist/commands/project.test.js.map +1 -0
- package/dist/commands/sanitize.d.ts +21 -0
- package/dist/commands/sanitize.d.ts.map +1 -0
- package/dist/commands/sanitize.js +56 -0
- package/dist/commands/sanitize.js.map +1 -0
- package/dist/commands/schema.d.ts +11 -0
- package/dist/commands/schema.d.ts.map +1 -0
- package/dist/commands/schema.js +101 -0
- package/dist/commands/schema.js.map +1 -0
- package/dist/commands/setup.d.ts +6 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +440 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/timeline.d.ts +3 -0
- package/dist/commands/timeline.d.ts.map +1 -0
- package/dist/commands/timeline.js +469 -0
- package/dist/commands/timeline.js.map +1 -0
- package/dist/commands/timeline.test.d.ts +2 -0
- package/dist/commands/timeline.test.d.ts.map +1 -0
- package/dist/commands/timeline.test.js +320 -0
- package/dist/commands/timeline.test.js.map +1 -0
- package/dist/commands/validate.d.ts +32 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +63 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/config/config.test.d.ts +2 -0
- package/dist/config/config.test.d.ts.map +1 -0
- package/dist/config/config.test.js +164 -0
- package/dist/config/config.test.js.map +1 -0
- package/dist/config/index.d.ts +35 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +101 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/schema.d.ts +43 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +42 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/engine/index.d.ts +3 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +2 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/project.d.ts +84 -0
- package/dist/engine/project.d.ts.map +1 -0
- package/dist/engine/project.js +355 -0
- package/dist/engine/project.js.map +1 -0
- package/dist/engine/project.test.d.ts +2 -0
- package/dist/engine/project.test.d.ts.map +1 -0
- package/dist/engine/project.test.js +599 -0
- package/dist/engine/project.test.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +131 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/api-key.d.ts +36 -0
- package/dist/utils/api-key.d.ts.map +1 -0
- package/dist/utils/api-key.js +211 -0
- package/dist/utils/api-key.js.map +1 -0
- package/dist/utils/api-key.test.d.ts +2 -0
- package/dist/utils/api-key.test.d.ts.map +1 -0
- package/dist/utils/api-key.test.js +35 -0
- package/dist/utils/api-key.test.js.map +1 -0
- package/dist/utils/audio.d.ts +23 -0
- package/dist/utils/audio.d.ts.map +1 -0
- package/dist/utils/audio.js +79 -0
- package/dist/utils/audio.js.map +1 -0
- package/dist/utils/exec-safe.d.ts +22 -0
- package/dist/utils/exec-safe.d.ts.map +1 -0
- package/dist/utils/exec-safe.js +62 -0
- package/dist/utils/exec-safe.js.map +1 -0
- package/dist/utils/first-run.d.ts +13 -0
- package/dist/utils/first-run.d.ts.map +1 -0
- package/dist/utils/first-run.js +48 -0
- package/dist/utils/first-run.js.map +1 -0
- package/dist/utils/provider-resolver.d.ts +15 -0
- package/dist/utils/provider-resolver.d.ts.map +1 -0
- package/dist/utils/provider-resolver.js +42 -0
- package/dist/utils/provider-resolver.js.map +1 -0
- package/dist/utils/remotion.d.ts +210 -0
- package/dist/utils/remotion.d.ts.map +1 -0
- package/dist/utils/remotion.js +731 -0
- package/dist/utils/remotion.js.map +1 -0
- package/dist/utils/subtitle.d.ts +65 -0
- package/dist/utils/subtitle.d.ts.map +1 -0
- package/dist/utils/subtitle.js +135 -0
- package/dist/utils/subtitle.js.map +1 -0
- package/dist/utils/subtitle.test.d.ts +2 -0
- package/dist/utils/subtitle.test.d.ts.map +1 -0
- package/dist/utils/subtitle.test.js +175 -0
- package/dist/utils/subtitle.test.js.map +1 -0
- package/dist/utils/tty.d.ts +45 -0
- package/dist/utils/tty.d.ts.map +1 -0
- package/dist/utils/tty.js +172 -0
- package/dist/utils/tty.js.map +1 -0
- package/package.json +102 -0
- package/src/agent/adapters/claude.ts +143 -0
- package/src/agent/adapters/gemini.ts +159 -0
- package/src/agent/adapters/index.ts +61 -0
- package/src/agent/adapters/ollama.ts +231 -0
- package/src/agent/adapters/openai.ts +116 -0
- package/src/agent/adapters/xai.ts +119 -0
- package/src/agent/index.ts +251 -0
- package/src/agent/memory/index.ts +151 -0
- package/src/agent/prompts/system.ts +106 -0
- package/src/agent/tools/ai-editing.ts +845 -0
- package/src/agent/tools/ai-generation.ts +1073 -0
- package/src/agent/tools/ai-pipeline.ts +1055 -0
- package/src/agent/tools/ai.ts +21 -0
- package/src/agent/tools/batch.ts +429 -0
- package/src/agent/tools/e2e.test.ts +545 -0
- package/src/agent/tools/export.ts +184 -0
- package/src/agent/tools/filesystem.ts +237 -0
- package/src/agent/tools/index.ts +150 -0
- package/src/agent/tools/integration.test.ts +775 -0
- package/src/agent/tools/media.ts +697 -0
- package/src/agent/tools/project.ts +313 -0
- package/src/agent/tools/timeline.ts +951 -0
- package/src/agent/types.ts +68 -0
- package/src/commands/agent.ts +340 -0
- package/src/commands/ai-analyze.ts +429 -0
- package/src/commands/ai-animated-caption.ts +390 -0
- package/src/commands/ai-audio.ts +941 -0
- package/src/commands/ai-broll.ts +490 -0
- package/src/commands/ai-edit-cli.ts +658 -0
- package/src/commands/ai-edit.ts +1542 -0
- package/src/commands/ai-fill-gaps.ts +566 -0
- package/src/commands/ai-helpers.ts +65 -0
- package/src/commands/ai-highlights.ts +1303 -0
- package/src/commands/ai-image.ts +761 -0
- package/src/commands/ai-motion.ts +347 -0
- package/src/commands/ai-narrate.ts +451 -0
- package/src/commands/ai-review.ts +309 -0
- package/src/commands/ai-script-pipeline-cli.ts +1710 -0
- package/src/commands/ai-script-pipeline.ts +1365 -0
- package/src/commands/ai-suggest-edit.ts +264 -0
- package/src/commands/ai-video-fx.ts +445 -0
- package/src/commands/ai-video.ts +915 -0
- package/src/commands/ai-viral.ts +595 -0
- package/src/commands/ai-visual-fx.ts +601 -0
- package/src/commands/ai.test.ts +627 -0
- package/src/commands/ai.ts +307 -0
- package/src/commands/analyze.ts +282 -0
- package/src/commands/audio.ts +644 -0
- package/src/commands/batch.test.ts +279 -0
- package/src/commands/batch.ts +440 -0
- package/src/commands/detect.ts +329 -0
- package/src/commands/doctor.ts +237 -0
- package/src/commands/edit-cmd.ts +1014 -0
- package/src/commands/export.ts +918 -0
- package/src/commands/generate.ts +2146 -0
- package/src/commands/media.ts +177 -0
- package/src/commands/output.ts +142 -0
- package/src/commands/pipeline.ts +398 -0
- package/src/commands/project.test.ts +127 -0
- package/src/commands/project.ts +149 -0
- package/src/commands/sanitize.ts +60 -0
- package/src/commands/schema.ts +130 -0
- package/src/commands/setup.ts +509 -0
- package/src/commands/timeline.test.ts +499 -0
- package/src/commands/timeline.ts +529 -0
- package/src/commands/validate.ts +77 -0
- package/src/config/config.test.ts +197 -0
- package/src/config/index.ts +125 -0
- package/src/config/schema.ts +82 -0
- package/src/engine/index.ts +2 -0
- package/src/engine/project.test.ts +702 -0
- package/src/engine/project.ts +439 -0
- package/src/index.ts +146 -0
- package/src/utils/api-key.test.ts +41 -0
- package/src/utils/api-key.ts +247 -0
- package/src/utils/audio.ts +83 -0
- package/src/utils/exec-safe.ts +75 -0
- package/src/utils/first-run.ts +52 -0
- package/src/utils/provider-resolver.ts +56 -0
- package/src/utils/remotion.ts +951 -0
- package/src/utils/subtitle.test.ts +227 -0
- package/src/utils/subtitle.ts +169 -0
- package/src/utils/tty.ts +196 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama LLM Adapter with JSON-based tool calling
|
|
3
|
+
* Uses prompt engineering to simulate tool calling for local models
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { LLMAdapter } from "./index.js";
|
|
7
|
+
import type {
|
|
8
|
+
ToolDefinition,
|
|
9
|
+
LLMResponse,
|
|
10
|
+
AgentMessage,
|
|
11
|
+
ToolCall,
|
|
12
|
+
LLMProvider,
|
|
13
|
+
} from "../types.js";
|
|
14
|
+
|
|
15
|
+
interface OllamaResponse {
|
|
16
|
+
model: string;
|
|
17
|
+
created_at: string;
|
|
18
|
+
message: {
|
|
19
|
+
role: string;
|
|
20
|
+
content: string;
|
|
21
|
+
};
|
|
22
|
+
done: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class OllamaAdapter implements LLMAdapter {
|
|
26
|
+
readonly provider: LLMProvider = "ollama";
|
|
27
|
+
private baseUrl: string = "http://localhost:11434";
|
|
28
|
+
private model: string = "llama3.2";
|
|
29
|
+
private initialized: boolean = false;
|
|
30
|
+
|
|
31
|
+
async initialize(apiKey: string): Promise<void> {
|
|
32
|
+
// apiKey is ignored for Ollama, but we use it to set custom URL if provided
|
|
33
|
+
if (apiKey && apiKey.startsWith("http")) {
|
|
34
|
+
this.baseUrl = apiKey;
|
|
35
|
+
}
|
|
36
|
+
this.initialized = true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
isInitialized(): boolean {
|
|
40
|
+
return this.initialized;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
setModel(model: string): void {
|
|
44
|
+
this.model = model;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
setBaseUrl(url: string): void {
|
|
48
|
+
this.baseUrl = url;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async chat(
|
|
52
|
+
messages: AgentMessage[],
|
|
53
|
+
tools: ToolDefinition[]
|
|
54
|
+
): Promise<LLMResponse> {
|
|
55
|
+
if (!this.initialized) {
|
|
56
|
+
throw new Error("Ollama adapter not initialized");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Build system prompt with tool definitions
|
|
60
|
+
const systemMessage = messages.find((m) => m.role === "system");
|
|
61
|
+
let systemPrompt = systemMessage?.content || "";
|
|
62
|
+
|
|
63
|
+
if (tools.length > 0) {
|
|
64
|
+
systemPrompt += "\n\n## IMPORTANT: Tool Usage Instructions\n";
|
|
65
|
+
systemPrompt += "You have access to tools that you MUST use to complete tasks. Do NOT describe how to do something - USE THE TOOLS.\n\n";
|
|
66
|
+
systemPrompt += "To call a tool, respond with ONLY a JSON object in this exact format:\n";
|
|
67
|
+
systemPrompt += '```json\n{"tool_calls": [{"name": "tool_name", "arguments": {"param": "value"}}]}\n```\n\n';
|
|
68
|
+
systemPrompt += "Example - If the user asks to list files:\n";
|
|
69
|
+
systemPrompt += '```json\n{"tool_calls": [{"name": "fs_list", "arguments": {"path": "."}}]}\n```\n\n';
|
|
70
|
+
systemPrompt += "Example - If the user asks to create a project:\n";
|
|
71
|
+
systemPrompt += '```json\n{"tool_calls": [{"name": "project_create", "arguments": {"name": "my-project"}}]}\n```\n\n';
|
|
72
|
+
systemPrompt += "RULES:\n";
|
|
73
|
+
systemPrompt += "1. When asked to DO something, ALWAYS use the appropriate tool\n";
|
|
74
|
+
systemPrompt += "2. Do NOT explain how to use terminal commands - use tools instead\n";
|
|
75
|
+
systemPrompt += "3. After tool results, summarize what was done\n\n";
|
|
76
|
+
systemPrompt += "## Available Tools:\n";
|
|
77
|
+
|
|
78
|
+
for (const tool of tools) {
|
|
79
|
+
systemPrompt += `\n### ${tool.name}\n`;
|
|
80
|
+
systemPrompt += `${tool.description}\n`;
|
|
81
|
+
const params = tool.parameters.properties;
|
|
82
|
+
const required = tool.parameters.required || [];
|
|
83
|
+
if (Object.keys(params).length > 0) {
|
|
84
|
+
systemPrompt += `Parameters:\n`;
|
|
85
|
+
for (const [name, param] of Object.entries(params)) {
|
|
86
|
+
const req = required.includes(name) ? "(required)" : "(optional)";
|
|
87
|
+
systemPrompt += ` - ${name} ${req}: ${(param as { description?: string }).description || ""}\n`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Convert messages to Ollama format
|
|
94
|
+
const ollamaMessages: { role: string; content: string }[] = [];
|
|
95
|
+
|
|
96
|
+
// Add system message first
|
|
97
|
+
ollamaMessages.push({
|
|
98
|
+
role: "system",
|
|
99
|
+
content: systemPrompt,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
for (const msg of messages) {
|
|
103
|
+
if (msg.role === "system") continue;
|
|
104
|
+
|
|
105
|
+
if (msg.role === "user") {
|
|
106
|
+
ollamaMessages.push({
|
|
107
|
+
role: "user",
|
|
108
|
+
content: msg.content,
|
|
109
|
+
});
|
|
110
|
+
} else if (msg.role === "assistant") {
|
|
111
|
+
let content = msg.content;
|
|
112
|
+
|
|
113
|
+
// Include tool calls in content for context
|
|
114
|
+
if (msg.toolCalls) {
|
|
115
|
+
content += `\n\nTool calls made:\n${JSON.stringify({ tool_calls: msg.toolCalls }, null, 2)}`;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
ollamaMessages.push({
|
|
119
|
+
role: "assistant",
|
|
120
|
+
content,
|
|
121
|
+
});
|
|
122
|
+
} else if (msg.role === "tool") {
|
|
123
|
+
// Include tool results as user messages for context
|
|
124
|
+
ollamaMessages.push({
|
|
125
|
+
role: "user",
|
|
126
|
+
content: `Tool result (${msg.toolCallId}):\n${msg.content}`,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Make API call
|
|
132
|
+
const response = await fetch(`${this.baseUrl}/api/chat`, {
|
|
133
|
+
method: "POST",
|
|
134
|
+
headers: {
|
|
135
|
+
"Content-Type": "application/json",
|
|
136
|
+
},
|
|
137
|
+
body: JSON.stringify({
|
|
138
|
+
model: this.model,
|
|
139
|
+
messages: ollamaMessages,
|
|
140
|
+
stream: false,
|
|
141
|
+
}),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
if (!response.ok) {
|
|
145
|
+
throw new Error(`Ollama API error: ${response.status} ${response.statusText}`);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const data = (await response.json()) as OllamaResponse;
|
|
149
|
+
const content = data.message.content;
|
|
150
|
+
|
|
151
|
+
// Try to parse tool calls from response
|
|
152
|
+
const toolCalls = this.parseToolCalls(content);
|
|
153
|
+
|
|
154
|
+
if (toolCalls.length > 0) {
|
|
155
|
+
// Extract text content before the JSON
|
|
156
|
+
const textContent = this.extractTextBeforeJson(content);
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
content: textContent,
|
|
160
|
+
toolCalls,
|
|
161
|
+
finishReason: "tool_calls",
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
content,
|
|
167
|
+
finishReason: "stop",
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private parseToolCalls(content: string): ToolCall[] {
|
|
172
|
+
const toolCalls: ToolCall[] = [];
|
|
173
|
+
|
|
174
|
+
// Try to find JSON block with tool_calls
|
|
175
|
+
const jsonMatch = content.match(/```json\s*(\{[\s\S]*?\})\s*```/);
|
|
176
|
+
if (jsonMatch) {
|
|
177
|
+
try {
|
|
178
|
+
const parsed = JSON.parse(jsonMatch[1]);
|
|
179
|
+
if (parsed.tool_calls && Array.isArray(parsed.tool_calls)) {
|
|
180
|
+
for (const tc of parsed.tool_calls) {
|
|
181
|
+
toolCalls.push({
|
|
182
|
+
id: `ollama-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
183
|
+
name: tc.name,
|
|
184
|
+
arguments: tc.arguments || {},
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
} catch {
|
|
189
|
+
// Not valid JSON
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Also try to find raw JSON object
|
|
194
|
+
if (toolCalls.length === 0) {
|
|
195
|
+
const rawJsonMatch = content.match(/\{"tool_calls":\s*\[[\s\S]*?\]\}/);
|
|
196
|
+
if (rawJsonMatch) {
|
|
197
|
+
try {
|
|
198
|
+
const parsed = JSON.parse(rawJsonMatch[0]);
|
|
199
|
+
if (parsed.tool_calls && Array.isArray(parsed.tool_calls)) {
|
|
200
|
+
for (const tc of parsed.tool_calls) {
|
|
201
|
+
toolCalls.push({
|
|
202
|
+
id: `ollama-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
203
|
+
name: tc.name,
|
|
204
|
+
arguments: tc.arguments || {},
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
} catch {
|
|
209
|
+
// Not valid JSON
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return toolCalls;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private extractTextBeforeJson(content: string): string {
|
|
218
|
+
// Find the start of JSON block
|
|
219
|
+
const jsonStart = content.indexOf("```json");
|
|
220
|
+
if (jsonStart > 0) {
|
|
221
|
+
return content.substring(0, jsonStart).trim();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const rawJsonStart = content.indexOf('{"tool_calls"');
|
|
225
|
+
if (rawJsonStart > 0) {
|
|
226
|
+
return content.substring(0, rawJsonStart).trim();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return "";
|
|
230
|
+
}
|
|
231
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI LLM Adapter with Function Calling
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import OpenAI from "openai";
|
|
6
|
+
import type { LLMAdapter } from "./index.js";
|
|
7
|
+
import type {
|
|
8
|
+
ToolDefinition,
|
|
9
|
+
LLMResponse,
|
|
10
|
+
AgentMessage,
|
|
11
|
+
ToolCall,
|
|
12
|
+
LLMProvider,
|
|
13
|
+
} from "../types.js";
|
|
14
|
+
|
|
15
|
+
export class OpenAIAdapter implements LLMAdapter {
|
|
16
|
+
readonly provider: LLMProvider = "openai";
|
|
17
|
+
private client: OpenAI | null = null;
|
|
18
|
+
private model: string = "gpt-5-mini";
|
|
19
|
+
|
|
20
|
+
async initialize(apiKey: string): Promise<void> {
|
|
21
|
+
this.client = new OpenAI({ apiKey });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
isInitialized(): boolean {
|
|
25
|
+
return this.client !== null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
setModel(model: string): void {
|
|
29
|
+
this.model = model;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async chat(
|
|
33
|
+
messages: AgentMessage[],
|
|
34
|
+
tools: ToolDefinition[]
|
|
35
|
+
): Promise<LLMResponse> {
|
|
36
|
+
if (!this.client) {
|
|
37
|
+
throw new Error("OpenAI adapter not initialized");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Convert messages to OpenAI format
|
|
41
|
+
const openaiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = messages.map(
|
|
42
|
+
(msg) => {
|
|
43
|
+
if (msg.role === "tool") {
|
|
44
|
+
return {
|
|
45
|
+
role: "tool" as const,
|
|
46
|
+
tool_call_id: msg.toolCallId!,
|
|
47
|
+
content: msg.content,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (msg.role === "assistant" && msg.toolCalls) {
|
|
51
|
+
return {
|
|
52
|
+
role: "assistant" as const,
|
|
53
|
+
content: msg.content || null,
|
|
54
|
+
tool_calls: msg.toolCalls.map((tc) => ({
|
|
55
|
+
id: tc.id,
|
|
56
|
+
type: "function" as const,
|
|
57
|
+
function: {
|
|
58
|
+
name: tc.name,
|
|
59
|
+
arguments: JSON.stringify(tc.arguments),
|
|
60
|
+
},
|
|
61
|
+
})),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
role: msg.role as "system" | "user" | "assistant",
|
|
66
|
+
content: msg.content,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// Convert tools to OpenAI format
|
|
72
|
+
const openaiTools: OpenAI.Chat.ChatCompletionTool[] = tools.map((tool) => ({
|
|
73
|
+
type: "function" as const,
|
|
74
|
+
function: {
|
|
75
|
+
name: tool.name,
|
|
76
|
+
description: tool.description,
|
|
77
|
+
parameters: tool.parameters as unknown as Record<string, unknown>,
|
|
78
|
+
},
|
|
79
|
+
}));
|
|
80
|
+
|
|
81
|
+
// Make API call
|
|
82
|
+
const response = await this.client.chat.completions.create({
|
|
83
|
+
model: this.model,
|
|
84
|
+
messages: openaiMessages,
|
|
85
|
+
tools: openaiTools.length > 0 ? openaiTools : undefined,
|
|
86
|
+
tool_choice: openaiTools.length > 0 ? "auto" : undefined,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const choice = response.choices[0];
|
|
90
|
+
const message = choice.message;
|
|
91
|
+
|
|
92
|
+
// Parse tool calls
|
|
93
|
+
let toolCalls: ToolCall[] | undefined;
|
|
94
|
+
if (message.tool_calls && message.tool_calls.length > 0) {
|
|
95
|
+
toolCalls = message.tool_calls.map((tc) => ({
|
|
96
|
+
id: tc.id,
|
|
97
|
+
name: tc.function.name,
|
|
98
|
+
arguments: JSON.parse(tc.function.arguments),
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Map finish reason
|
|
103
|
+
let finishReason: LLMResponse["finishReason"] = "stop";
|
|
104
|
+
if (choice.finish_reason === "tool_calls") {
|
|
105
|
+
finishReason = "tool_calls";
|
|
106
|
+
} else if (choice.finish_reason === "length") {
|
|
107
|
+
finishReason = "length";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
content: message.content || "",
|
|
112
|
+
toolCalls,
|
|
113
|
+
finishReason,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* xAI Grok LLM Adapter (OpenAI-compatible)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import OpenAI from "openai";
|
|
6
|
+
import type { LLMAdapter } from "./index.js";
|
|
7
|
+
import type {
|
|
8
|
+
ToolDefinition,
|
|
9
|
+
LLMResponse,
|
|
10
|
+
AgentMessage,
|
|
11
|
+
ToolCall,
|
|
12
|
+
LLMProvider,
|
|
13
|
+
} from "../types.js";
|
|
14
|
+
|
|
15
|
+
export class XAIAdapter implements LLMAdapter {
|
|
16
|
+
readonly provider: LLMProvider = "xai";
|
|
17
|
+
private client: OpenAI | null = null;
|
|
18
|
+
private model: string = "grok-4-1-fast-reasoning";
|
|
19
|
+
|
|
20
|
+
async initialize(apiKey: string): Promise<void> {
|
|
21
|
+
this.client = new OpenAI({
|
|
22
|
+
apiKey,
|
|
23
|
+
baseURL: "https://api.x.ai/v1",
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
isInitialized(): boolean {
|
|
28
|
+
return this.client !== null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
setModel(model: string): void {
|
|
32
|
+
this.model = model;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async chat(
|
|
36
|
+
messages: AgentMessage[],
|
|
37
|
+
tools: ToolDefinition[]
|
|
38
|
+
): Promise<LLMResponse> {
|
|
39
|
+
if (!this.client) {
|
|
40
|
+
throw new Error("xAI adapter not initialized");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Convert messages to OpenAI format
|
|
44
|
+
const openaiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = messages.map(
|
|
45
|
+
(msg) => {
|
|
46
|
+
if (msg.role === "tool") {
|
|
47
|
+
return {
|
|
48
|
+
role: "tool" as const,
|
|
49
|
+
tool_call_id: msg.toolCallId!,
|
|
50
|
+
content: msg.content,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (msg.role === "assistant" && msg.toolCalls) {
|
|
54
|
+
return {
|
|
55
|
+
role: "assistant" as const,
|
|
56
|
+
content: msg.content || null,
|
|
57
|
+
tool_calls: msg.toolCalls.map((tc) => ({
|
|
58
|
+
id: tc.id,
|
|
59
|
+
type: "function" as const,
|
|
60
|
+
function: {
|
|
61
|
+
name: tc.name,
|
|
62
|
+
arguments: JSON.stringify(tc.arguments),
|
|
63
|
+
},
|
|
64
|
+
})),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
role: msg.role as "system" | "user" | "assistant",
|
|
69
|
+
content: msg.content,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
// Convert tools to OpenAI format
|
|
75
|
+
const openaiTools: OpenAI.Chat.ChatCompletionTool[] = tools.map((tool) => ({
|
|
76
|
+
type: "function" as const,
|
|
77
|
+
function: {
|
|
78
|
+
name: tool.name,
|
|
79
|
+
description: tool.description,
|
|
80
|
+
parameters: tool.parameters as unknown as Record<string, unknown>,
|
|
81
|
+
},
|
|
82
|
+
}));
|
|
83
|
+
|
|
84
|
+
// Make API call
|
|
85
|
+
const response = await this.client.chat.completions.create({
|
|
86
|
+
model: this.model,
|
|
87
|
+
messages: openaiMessages,
|
|
88
|
+
tools: openaiTools.length > 0 ? openaiTools : undefined,
|
|
89
|
+
tool_choice: openaiTools.length > 0 ? "auto" : undefined,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const choice = response.choices[0];
|
|
93
|
+
const message = choice.message;
|
|
94
|
+
|
|
95
|
+
// Parse tool calls
|
|
96
|
+
let toolCalls: ToolCall[] | undefined;
|
|
97
|
+
if (message.tool_calls && message.tool_calls.length > 0) {
|
|
98
|
+
toolCalls = message.tool_calls.map((tc) => ({
|
|
99
|
+
id: tc.id,
|
|
100
|
+
name: tc.function.name,
|
|
101
|
+
arguments: JSON.parse(tc.function.arguments),
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Map finish reason
|
|
106
|
+
let finishReason: LLMResponse["finishReason"] = "stop";
|
|
107
|
+
if (choice.finish_reason === "tool_calls") {
|
|
108
|
+
finishReason = "tool_calls";
|
|
109
|
+
} else if (choice.finish_reason === "length") {
|
|
110
|
+
finishReason = "length";
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
content: message.content || "",
|
|
115
|
+
toolCalls,
|
|
116
|
+
finishReason,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentExecutor - Main Agentic Loop
|
|
3
|
+
* Orchestrates LLM reasoning and tool execution
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
AgentMessage,
|
|
8
|
+
AgentContext,
|
|
9
|
+
ToolCall,
|
|
10
|
+
ToolResult,
|
|
11
|
+
LLMProvider,
|
|
12
|
+
} from "./types.js";
|
|
13
|
+
import type { LLMAdapter } from "./adapters/index.js";
|
|
14
|
+
import { createAdapter } from "./adapters/index.js";
|
|
15
|
+
import { ToolRegistry, registerAllTools } from "./tools/index.js";
|
|
16
|
+
import { getSystemPrompt } from "./prompts/system.js";
|
|
17
|
+
import { ConversationMemory } from "./memory/index.js";
|
|
18
|
+
|
|
19
|
+
export interface AgentExecutorOptions {
|
|
20
|
+
provider: LLMProvider;
|
|
21
|
+
apiKey: string;
|
|
22
|
+
model?: string;
|
|
23
|
+
maxTurns?: number;
|
|
24
|
+
verbose?: boolean;
|
|
25
|
+
projectPath?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Callback to confirm before executing each tool.
|
|
28
|
+
* Return true to execute, false to skip.
|
|
29
|
+
*/
|
|
30
|
+
confirmCallback?: (toolName: string, args: Record<string, unknown>) => Promise<boolean>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ExecutionResult {
|
|
34
|
+
response: string;
|
|
35
|
+
toolsUsed: string[];
|
|
36
|
+
turns: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* AgentExecutor class
|
|
41
|
+
* Handles the agentic loop: reason → tool call → result → reason → ...
|
|
42
|
+
*/
|
|
43
|
+
/** Mask sensitive values in tool arguments for verbose logging */
|
|
44
|
+
function maskSensitiveArgs(args: Record<string, unknown>): Record<string, unknown> {
|
|
45
|
+
const sensitiveKeys = ["apiKey", "api_key", "token", "secret", "password", "key"];
|
|
46
|
+
const masked: Record<string, unknown> = {};
|
|
47
|
+
for (const [k, v] of Object.entries(args)) {
|
|
48
|
+
if (sensitiveKeys.some((sk) => k.toLowerCase().includes(sk.toLowerCase())) && typeof v === "string") {
|
|
49
|
+
masked[k] = v.slice(0, 4) + "****";
|
|
50
|
+
} else {
|
|
51
|
+
masked[k] = v;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return masked;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class AgentExecutor {
|
|
58
|
+
private adapter: LLMAdapter | null = null;
|
|
59
|
+
private registry: ToolRegistry;
|
|
60
|
+
private memory: ConversationMemory;
|
|
61
|
+
private context: AgentContext;
|
|
62
|
+
private config: AgentExecutorOptions;
|
|
63
|
+
private initialized = false;
|
|
64
|
+
|
|
65
|
+
constructor(options: AgentExecutorOptions) {
|
|
66
|
+
this.config = {
|
|
67
|
+
maxTurns: 10,
|
|
68
|
+
verbose: false,
|
|
69
|
+
...options,
|
|
70
|
+
};
|
|
71
|
+
this.registry = new ToolRegistry();
|
|
72
|
+
this.memory = new ConversationMemory();
|
|
73
|
+
this.context = {
|
|
74
|
+
projectPath: options.projectPath || null,
|
|
75
|
+
workingDirectory: process.cwd(),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Initialize the agent
|
|
81
|
+
*/
|
|
82
|
+
async initialize(): Promise<void> {
|
|
83
|
+
if (this.initialized) return;
|
|
84
|
+
|
|
85
|
+
// Create and initialize LLM adapter
|
|
86
|
+
this.adapter = await createAdapter(this.config.provider);
|
|
87
|
+
await this.adapter.initialize(this.config.apiKey);
|
|
88
|
+
|
|
89
|
+
// Register all tools
|
|
90
|
+
await registerAllTools(this.registry);
|
|
91
|
+
|
|
92
|
+
// Add system message
|
|
93
|
+
const systemPrompt = getSystemPrompt(this.context);
|
|
94
|
+
this.memory.addSystem(systemPrompt);
|
|
95
|
+
|
|
96
|
+
this.initialized = true;
|
|
97
|
+
|
|
98
|
+
if (this.config.verbose) {
|
|
99
|
+
console.log(`[Agent] Initialized with ${this.registry.size} tools`);
|
|
100
|
+
console.log(`[Agent] Provider: ${this.config.provider}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Execute a user request
|
|
106
|
+
*/
|
|
107
|
+
async execute(userInput: string): Promise<ExecutionResult> {
|
|
108
|
+
if (!this.initialized || !this.adapter) {
|
|
109
|
+
throw new Error("Agent not initialized. Call initialize() first.");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Add user message
|
|
113
|
+
this.memory.addUser(userInput);
|
|
114
|
+
|
|
115
|
+
const toolsUsed: string[] = [];
|
|
116
|
+
let turns = 0;
|
|
117
|
+
|
|
118
|
+
// Agentic loop
|
|
119
|
+
while (turns < this.config.maxTurns!) {
|
|
120
|
+
turns++;
|
|
121
|
+
|
|
122
|
+
if (this.config.verbose) {
|
|
123
|
+
console.log(`[Agent] Turn ${turns}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Get LLM response
|
|
127
|
+
const response = await this.adapter.chat(
|
|
128
|
+
this.memory.getMessages(),
|
|
129
|
+
this.registry.getDefinitions()
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
// Handle tool calls
|
|
133
|
+
if (response.finishReason === "tool_calls" && response.toolCalls) {
|
|
134
|
+
// Add assistant message with tool calls
|
|
135
|
+
this.memory.addAssistant(response.content, response.toolCalls);
|
|
136
|
+
|
|
137
|
+
// Execute each tool
|
|
138
|
+
for (const toolCall of response.toolCalls) {
|
|
139
|
+
if (this.config.verbose) {
|
|
140
|
+
console.log(`[Agent] Calling tool: ${toolCall.name}`);
|
|
141
|
+
const maskedArgs = maskSensitiveArgs(toolCall.arguments);
|
|
142
|
+
console.log(`[Agent] Args: ${JSON.stringify(maskedArgs)}`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const result = await this.executeTool(toolCall);
|
|
146
|
+
toolsUsed.push(toolCall.name);
|
|
147
|
+
|
|
148
|
+
// Add tool result
|
|
149
|
+
this.memory.addToolResult(toolCall.id, result);
|
|
150
|
+
|
|
151
|
+
if (this.config.verbose) {
|
|
152
|
+
console.log(`[Agent] Result: ${result.success ? "success" : "error"}`);
|
|
153
|
+
if (result.output) {
|
|
154
|
+
console.log(`[Agent] Output: ${result.output.substring(0, 200)}...`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Continue loop to get next response
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// No more tool calls - we're done
|
|
164
|
+
this.memory.addAssistant(response.content);
|
|
165
|
+
|
|
166
|
+
return {
|
|
167
|
+
response: response.content,
|
|
168
|
+
toolsUsed: [...new Set(toolsUsed)], // Deduplicate
|
|
169
|
+
turns,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Max turns reached
|
|
174
|
+
return {
|
|
175
|
+
response: "Maximum turns reached. Please try breaking down your request.",
|
|
176
|
+
toolsUsed: [...new Set(toolsUsed)],
|
|
177
|
+
turns,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Execute a single tool
|
|
183
|
+
*/
|
|
184
|
+
private async executeTool(toolCall: ToolCall): Promise<ToolResult> {
|
|
185
|
+
// Check confirmCallback if set
|
|
186
|
+
if (this.config.confirmCallback) {
|
|
187
|
+
const confirmed = await this.config.confirmCallback(
|
|
188
|
+
toolCall.name,
|
|
189
|
+
toolCall.arguments
|
|
190
|
+
);
|
|
191
|
+
if (!confirmed) {
|
|
192
|
+
return {
|
|
193
|
+
toolCallId: toolCall.id,
|
|
194
|
+
success: false,
|
|
195
|
+
output: "Tool execution skipped by user",
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const result = await this.registry.execute(
|
|
201
|
+
toolCall.name,
|
|
202
|
+
toolCall.arguments,
|
|
203
|
+
this.context
|
|
204
|
+
);
|
|
205
|
+
result.toolCallId = toolCall.id;
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Update context (e.g., when project changes)
|
|
211
|
+
*/
|
|
212
|
+
updateContext(updates: Partial<AgentContext>): void {
|
|
213
|
+
this.context = { ...this.context, ...updates };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Reset conversation memory
|
|
218
|
+
*/
|
|
219
|
+
reset(): void {
|
|
220
|
+
this.memory.clear();
|
|
221
|
+
const systemPrompt = getSystemPrompt(this.context);
|
|
222
|
+
this.memory.addSystem(systemPrompt);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Get current context
|
|
227
|
+
*/
|
|
228
|
+
getContext(): AgentContext {
|
|
229
|
+
return { ...this.context };
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Get conversation history
|
|
234
|
+
*/
|
|
235
|
+
getHistory(): AgentMessage[] {
|
|
236
|
+
return this.memory.getMessages();
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Get available tools
|
|
241
|
+
*/
|
|
242
|
+
getTools(): string[] {
|
|
243
|
+
return this.registry.list();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Re-export types
|
|
248
|
+
export type { AgentConfig, AgentContext, AgentMessage, ToolCall, ToolResult } from "./types.js";
|
|
249
|
+
export type { LLMAdapter } from "./adapters/index.js";
|
|
250
|
+
export { ToolRegistry } from "./tools/index.js";
|
|
251
|
+
export { ConversationMemory } from "./memory/index.js";
|