agent-nuvira 1.14.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/LICENSE +21 -0
- package/README.md +891 -0
- package/dist/agent-sdk/src/agent.d.ts +118 -0
- package/dist/agent-sdk/src/agent.d.ts.map +1 -0
- package/dist/agent-sdk/src/agent.js +88 -0
- package/dist/agent-sdk/src/agent.js.map +1 -0
- package/dist/agent-sdk/src/index.d.ts +33 -0
- package/dist/agent-sdk/src/index.d.ts.map +1 -0
- package/dist/agent-sdk/src/index.js +32 -0
- package/dist/agent-sdk/src/index.js.map +1 -0
- package/dist/agent-sdk/src/register.d.ts +70 -0
- package/dist/agent-sdk/src/register.d.ts.map +1 -0
- package/dist/agent-sdk/src/register.js +181 -0
- package/dist/agent-sdk/src/register.js.map +1 -0
- package/dist/agent-sdk/src/scaffold.d.ts +50 -0
- package/dist/agent-sdk/src/scaffold.d.ts.map +1 -0
- package/dist/agent-sdk/src/scaffold.js +291 -0
- package/dist/agent-sdk/src/scaffold.js.map +1 -0
- package/dist/agent-sdk/src/testing.d.ts +187 -0
- package/dist/agent-sdk/src/testing.d.ts.map +1 -0
- package/dist/agent-sdk/src/testing.js +243 -0
- package/dist/agent-sdk/src/testing.js.map +1 -0
- package/dist/agent-sdk/src/types.d.ts +202 -0
- package/dist/agent-sdk/src/types.d.ts.map +1 -0
- package/dist/agent-sdk/src/types.js +11 -0
- package/dist/agent-sdk/src/types.js.map +1 -0
- package/dist/agents/agent.d.ts +132 -0
- package/dist/agents/agent.d.ts.map +1 -0
- package/dist/agents/agent.js +19 -0
- package/dist/agents/agent.js.map +1 -0
- package/dist/agents/agents/context-gatherer.d.ts +42 -0
- package/dist/agents/agents/context-gatherer.d.ts.map +1 -0
- package/dist/agents/agents/context-gatherer.js +366 -0
- package/dist/agents/agents/context-gatherer.js.map +1 -0
- package/dist/agents/agents/debugger.d.ts +58 -0
- package/dist/agents/agents/debugger.d.ts.map +1 -0
- package/dist/agents/agents/debugger.js +257 -0
- package/dist/agents/agents/debugger.js.map +1 -0
- package/dist/agents/agents/git-agent.d.ts +34 -0
- package/dist/agents/agents/git-agent.d.ts.map +1 -0
- package/dist/agents/agents/git-agent.js +200 -0
- package/dist/agents/agents/git-agent.js.map +1 -0
- package/dist/agents/agents/github-release-agent.d.ts +65 -0
- package/dist/agents/agents/github-release-agent.d.ts.map +1 -0
- package/dist/agents/agents/github-release-agent.js +439 -0
- package/dist/agents/agents/github-release-agent.js.map +1 -0
- package/dist/agents/agents/package-agent.d.ts +33 -0
- package/dist/agents/agents/package-agent.d.ts.map +1 -0
- package/dist/agents/agents/package-agent.js +233 -0
- package/dist/agents/agents/package-agent.js.map +1 -0
- package/dist/agents/agents/planner.d.ts +26 -0
- package/dist/agents/agents/planner.d.ts.map +1 -0
- package/dist/agents/agents/planner.js +222 -0
- package/dist/agents/agents/planner.js.map +1 -0
- package/dist/agents/agents/reviewer.d.ts +34 -0
- package/dist/agents/agents/reviewer.d.ts.map +1 -0
- package/dist/agents/agents/reviewer.js +159 -0
- package/dist/agents/agents/reviewer.js.map +1 -0
- package/dist/agents/agents/runner.d.ts +73 -0
- package/dist/agents/agents/runner.d.ts.map +1 -0
- package/dist/agents/agents/runner.js +299 -0
- package/dist/agents/agents/runner.js.map +1 -0
- package/dist/agents/agents/security-agent.d.ts +33 -0
- package/dist/agents/agents/security-agent.d.ts.map +1 -0
- package/dist/agents/agents/security-agent.js +184 -0
- package/dist/agents/agents/security-agent.js.map +1 -0
- package/dist/agents/agents/tester.d.ts +96 -0
- package/dist/agents/agents/tester.d.ts.map +1 -0
- package/dist/agents/agents/tester.js +410 -0
- package/dist/agents/agents/tester.js.map +1 -0
- package/dist/agents/agents/writer.d.ts +51 -0
- package/dist/agents/agents/writer.d.ts.map +1 -0
- package/dist/agents/agents/writer.js +384 -0
- package/dist/agents/agents/writer.js.map +1 -0
- package/dist/agents/context-vault.d.ts +49 -0
- package/dist/agents/context-vault.d.ts.map +1 -0
- package/dist/agents/context-vault.js +134 -0
- package/dist/agents/context-vault.js.map +1 -0
- package/dist/agents/orchestrator.d.ts +97 -0
- package/dist/agents/orchestrator.d.ts.map +1 -0
- package/dist/agents/orchestrator.js +696 -0
- package/dist/agents/orchestrator.js.map +1 -0
- package/dist/agents/utils/file-tree.d.ts +28 -0
- package/dist/agents/utils/file-tree.d.ts.map +1 -0
- package/dist/agents/utils/file-tree.js +93 -0
- package/dist/agents/utils/file-tree.js.map +1 -0
- package/dist/cli/agent.d.ts +25 -0
- package/dist/cli/agent.d.ts.map +1 -0
- package/dist/cli/agent.js +374 -0
- package/dist/cli/agent.js.map +1 -0
- package/dist/cli/benchmark.d.ts +24 -0
- package/dist/cli/benchmark.d.ts.map +1 -0
- package/dist/cli/benchmark.js +235 -0
- package/dist/cli/benchmark.js.map +1 -0
- package/dist/cli/cache.d.ts +12 -0
- package/dist/cli/cache.d.ts.map +1 -0
- package/dist/cli/cache.js +58 -0
- package/dist/cli/cache.js.map +1 -0
- package/dist/cli/chat.d.ts +37 -0
- package/dist/cli/chat.d.ts.map +1 -0
- package/dist/cli/chat.js +393 -0
- package/dist/cli/chat.js.map +1 -0
- package/dist/cli/commands.d.ts +24 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +18 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/config.d.ts +19 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +162 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/dashboard.d.ts +34 -0
- package/dist/cli/dashboard.d.ts.map +1 -0
- package/dist/cli/dashboard.js +126 -0
- package/dist/cli/dashboard.js.map +1 -0
- package/dist/cli/doctor.d.ts +68 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +585 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/edit.d.ts +11 -0
- package/dist/cli/edit.d.ts.map +1 -0
- package/dist/cli/edit.js +86 -0
- package/dist/cli/edit.js.map +1 -0
- package/dist/cli/execute.d.ts +25 -0
- package/dist/cli/execute.d.ts.map +1 -0
- package/dist/cli/execute.js +186 -0
- package/dist/cli/execute.js.map +1 -0
- package/dist/cli/federation.d.ts +31 -0
- package/dist/cli/federation.d.ts.map +1 -0
- package/dist/cli/federation.js +387 -0
- package/dist/cli/federation.js.map +1 -0
- package/dist/cli/history.d.ts +22 -0
- package/dist/cli/history.d.ts.map +1 -0
- package/dist/cli/history.js +140 -0
- package/dist/cli/history.js.map +1 -0
- package/dist/cli/init.d.ts +49 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +423 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/learn.d.ts +31 -0
- package/dist/cli/learn.d.ts.map +1 -0
- package/dist/cli/learn.js +320 -0
- package/dist/cli/learn.js.map +1 -0
- package/dist/cli/memory.d.ts +38 -0
- package/dist/cli/memory.d.ts.map +1 -0
- package/dist/cli/memory.js +295 -0
- package/dist/cli/memory.js.map +1 -0
- package/dist/cli/model-picker.d.ts +18 -0
- package/dist/cli/model-picker.d.ts.map +1 -0
- package/dist/cli/model-picker.js +225 -0
- package/dist/cli/model-picker.js.map +1 -0
- package/dist/cli/models.d.ts +11 -0
- package/dist/cli/models.d.ts.map +1 -0
- package/dist/cli/models.js +132 -0
- package/dist/cli/models.js.map +1 -0
- package/dist/cli/plan.d.ts +11 -0
- package/dist/cli/plan.d.ts.map +1 -0
- package/dist/cli/plan.js +94 -0
- package/dist/cli/plan.js.map +1 -0
- package/dist/cli/plugins.d.ts +15 -0
- package/dist/cli/plugins.d.ts.map +1 -0
- package/dist/cli/plugins.js +123 -0
- package/dist/cli/plugins.js.map +1 -0
- package/dist/cli/router.d.ts +20 -0
- package/dist/cli/router.d.ts.map +1 -0
- package/dist/cli/router.js +142 -0
- package/dist/cli/router.js.map +1 -0
- package/dist/cli/run.d.ts +22 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +110 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/sandbox.d.ts +27 -0
- package/dist/cli/sandbox.d.ts.map +1 -0
- package/dist/cli/sandbox.js +264 -0
- package/dist/cli/sandbox.js.map +1 -0
- package/dist/cli/sdk.d.ts +27 -0
- package/dist/cli/sdk.d.ts.map +1 -0
- package/dist/cli/sdk.js +204 -0
- package/dist/cli/sdk.js.map +1 -0
- package/dist/cli/stats.d.ts +18 -0
- package/dist/cli/stats.d.ts.map +1 -0
- package/dist/cli/stats.js +78 -0
- package/dist/cli/stats.js.map +1 -0
- package/dist/cli/team.d.ts +42 -0
- package/dist/cli/team.d.ts.map +1 -0
- package/dist/cli/team.js +473 -0
- package/dist/cli/team.js.map +1 -0
- package/dist/cli/workflow.d.ts +27 -0
- package/dist/cli/workflow.d.ts.map +1 -0
- package/dist/cli/workflow.js +347 -0
- package/dist/cli/workflow.js.map +1 -0
- package/dist/config/manager.d.ts +37 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +147 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/types.d.ts +53 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/context/cache.d.ts +27 -0
- package/dist/context/cache.d.ts.map +1 -0
- package/dist/context/cache.js +116 -0
- package/dist/context/cache.js.map +1 -0
- package/dist/context/history.d.ts +87 -0
- package/dist/context/history.d.ts.map +1 -0
- package/dist/context/history.js +249 -0
- package/dist/context/history.js.map +1 -0
- package/dist/context/parser.d.ts +61 -0
- package/dist/context/parser.d.ts.map +1 -0
- package/dist/context/parser.js +194 -0
- package/dist/context/parser.js.map +1 -0
- package/dist/federation/client.d.ts +49 -0
- package/dist/federation/client.d.ts.map +1 -0
- package/dist/federation/client.js +239 -0
- package/dist/federation/client.js.map +1 -0
- package/dist/federation/protocol.d.ts +155 -0
- package/dist/federation/protocol.d.ts.map +1 -0
- package/dist/federation/protocol.js +57 -0
- package/dist/federation/protocol.js.map +1 -0
- package/dist/federation/server.d.ts +25 -0
- package/dist/federation/server.d.ts.map +1 -0
- package/dist/federation/server.js +401 -0
- package/dist/federation/server.js.map +1 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/dist/inference/factory.d.ts +20 -0
- package/dist/inference/factory.d.ts.map +1 -0
- package/dist/inference/factory.js +46 -0
- package/dist/inference/factory.js.map +1 -0
- package/dist/inference/gemini-adapter.d.ts +17 -0
- package/dist/inference/gemini-adapter.d.ts.map +1 -0
- package/dist/inference/gemini-adapter.js +176 -0
- package/dist/inference/gemini-adapter.js.map +1 -0
- package/dist/inference/groq-adapter.d.ts +17 -0
- package/dist/inference/groq-adapter.d.ts.map +1 -0
- package/dist/inference/groq-adapter.js +103 -0
- package/dist/inference/groq-adapter.js.map +1 -0
- package/dist/inference/interface.d.ts +49 -0
- package/dist/inference/interface.d.ts.map +1 -0
- package/dist/inference/interface.js +2 -0
- package/dist/inference/interface.js.map +1 -0
- package/dist/inference/local-adapter.d.ts +35 -0
- package/dist/inference/local-adapter.d.ts.map +1 -0
- package/dist/inference/local-adapter.js +311 -0
- package/dist/inference/local-adapter.js.map +1 -0
- package/dist/inference/model-catalog.d.ts +53 -0
- package/dist/inference/model-catalog.d.ts.map +1 -0
- package/dist/inference/model-catalog.js +306 -0
- package/dist/inference/model-catalog.js.map +1 -0
- package/dist/inference/nim-adapter.d.ts +17 -0
- package/dist/inference/nim-adapter.d.ts.map +1 -0
- package/dist/inference/nim-adapter.js +103 -0
- package/dist/inference/nim-adapter.js.map +1 -0
- package/dist/inference/openrouter-adapter.d.ts +17 -0
- package/dist/inference/openrouter-adapter.d.ts.map +1 -0
- package/dist/inference/openrouter-adapter.js +105 -0
- package/dist/inference/openrouter-adapter.js.map +1 -0
- package/dist/inference/sse.d.ts +20 -0
- package/dist/inference/sse.d.ts.map +1 -0
- package/dist/inference/sse.js +91 -0
- package/dist/inference/sse.js.map +1 -0
- package/dist/learning/agent-stats.d.ts +109 -0
- package/dist/learning/agent-stats.d.ts.map +1 -0
- package/dist/learning/agent-stats.js +240 -0
- package/dist/learning/agent-stats.js.map +1 -0
- package/dist/learning/benchmark.d.ts +161 -0
- package/dist/learning/benchmark.d.ts.map +1 -0
- package/dist/learning/benchmark.js +589 -0
- package/dist/learning/benchmark.js.map +1 -0
- package/dist/learning/cost-tracker.d.ts +101 -0
- package/dist/learning/cost-tracker.d.ts.map +1 -0
- package/dist/learning/cost-tracker.js +224 -0
- package/dist/learning/cost-tracker.js.map +1 -0
- package/dist/learning/feedback.d.ts +88 -0
- package/dist/learning/feedback.d.ts.map +1 -0
- package/dist/learning/feedback.js +169 -0
- package/dist/learning/feedback.js.map +1 -0
- package/dist/learning/hybrid-router.d.ts +201 -0
- package/dist/learning/hybrid-router.d.ts.map +1 -0
- package/dist/learning/hybrid-router.js +450 -0
- package/dist/learning/hybrid-router.js.map +1 -0
- package/dist/learning/model-compare.d.ts +76 -0
- package/dist/learning/model-compare.d.ts.map +1 -0
- package/dist/learning/model-compare.js +252 -0
- package/dist/learning/model-compare.js.map +1 -0
- package/dist/learning/model-router.d.ts +68 -0
- package/dist/learning/model-router.d.ts.map +1 -0
- package/dist/learning/model-router.js +140 -0
- package/dist/learning/model-router.js.map +1 -0
- package/dist/learning/pattern-extractor.d.ts +99 -0
- package/dist/learning/pattern-extractor.d.ts.map +1 -0
- package/dist/learning/pattern-extractor.js +310 -0
- package/dist/learning/pattern-extractor.js.map +1 -0
- package/dist/learning/scorer.d.ts +51 -0
- package/dist/learning/scorer.d.ts.map +1 -0
- package/dist/learning/scorer.js +64 -0
- package/dist/learning/scorer.js.map +1 -0
- package/dist/learning/self-improver.d.ts +48 -0
- package/dist/learning/self-improver.d.ts.map +1 -0
- package/dist/learning/self-improver.js +161 -0
- package/dist/learning/self-improver.js.map +1 -0
- package/dist/memory/embedder.d.ts +65 -0
- package/dist/memory/embedder.d.ts.map +1 -0
- package/dist/memory/embedder.js +424 -0
- package/dist/memory/embedder.js.map +1 -0
- package/dist/memory/memory-integration.d.ts +56 -0
- package/dist/memory/memory-integration.d.ts.map +1 -0
- package/dist/memory/memory-integration.js +95 -0
- package/dist/memory/memory-integration.js.map +1 -0
- package/dist/memory/trajectory-store.d.ts +149 -0
- package/dist/memory/trajectory-store.d.ts.map +1 -0
- package/dist/memory/trajectory-store.js +476 -0
- package/dist/memory/trajectory-store.js.map +1 -0
- package/dist/memory/vector-store.d.ts +78 -0
- package/dist/memory/vector-store.d.ts.map +1 -0
- package/dist/memory/vector-store.js +186 -0
- package/dist/memory/vector-store.js.map +1 -0
- package/dist/plugins/agent-plugin.d.ts +73 -0
- package/dist/plugins/agent-plugin.d.ts.map +1 -0
- package/dist/plugins/agent-plugin.js +199 -0
- package/dist/plugins/agent-plugin.js.map +1 -0
- package/dist/plugins/registry.d.ts +61 -0
- package/dist/plugins/registry.d.ts.map +1 -0
- package/dist/plugins/registry.js +67 -0
- package/dist/plugins/registry.js.map +1 -0
- package/dist/sandbox/images.d.ts +31 -0
- package/dist/sandbox/images.d.ts.map +1 -0
- package/dist/sandbox/images.js +129 -0
- package/dist/sandbox/images.js.map +1 -0
- package/dist/sandbox/manager.d.ts +134 -0
- package/dist/sandbox/manager.d.ts.map +1 -0
- package/dist/sandbox/manager.js +470 -0
- package/dist/sandbox/manager.js.map +1 -0
- package/dist/sandbox/types.d.ts +113 -0
- package/dist/sandbox/types.d.ts.map +1 -0
- package/dist/sandbox/types.js +107 -0
- package/dist/sandbox/types.js.map +1 -0
- package/dist/security/scanner.d.ts +53 -0
- package/dist/security/scanner.d.ts.map +1 -0
- package/dist/security/scanner.js +271 -0
- package/dist/security/scanner.js.map +1 -0
- package/dist/team/config.d.ts +50 -0
- package/dist/team/config.d.ts.map +1 -0
- package/dist/team/config.js +108 -0
- package/dist/team/config.js.map +1 -0
- package/dist/team/memory.d.ts +63 -0
- package/dist/team/memory.d.ts.map +1 -0
- package/dist/team/memory.js +282 -0
- package/dist/team/memory.js.map +1 -0
- package/dist/team/review.d.ts +123 -0
- package/dist/team/review.d.ts.map +1 -0
- package/dist/team/review.js +293 -0
- package/dist/team/review.js.map +1 -0
- package/dist/utils/env.d.ts +19 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +250 -0
- package/dist/utils/env.js.map +1 -0
- package/dist/utils/logger.d.ts +11 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +45 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/web-dashboard/server.d.ts +59 -0
- package/dist/web-dashboard/server.d.ts.map +1 -0
- package/dist/web-dashboard/server.js +418 -0
- package/dist/web-dashboard/server.js.map +1 -0
- package/dist/workflow/registry.d.ts +127 -0
- package/dist/workflow/registry.d.ts.map +1 -0
- package/dist/workflow/registry.js +482 -0
- package/dist/workflow/registry.js.map +1 -0
- package/dist/workflow/templates.d.ts +93 -0
- package/dist/workflow/templates.d.ts.map +1 -0
- package/dist/workflow/templates.js +481 -0
- package/dist/workflow/templates.js.map +1 -0
- package/package.json +78 -0
- package/src/web-dashboard/public/assets/index-B08nDkSB.css +1 -0
- package/src/web-dashboard/public/assets/index-BKL8YOFD.js +135 -0
- package/src/web-dashboard/public/assets/index-BKL8YOFD.js.map +1 -0
- package/src/web-dashboard/public/index.html +13 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReviewerAgent — Validates code changes produced by the WriterAgent.
|
|
3
|
+
*
|
|
4
|
+
* The reviewer checks for:
|
|
5
|
+
* - Syntax errors and type mismatches
|
|
6
|
+
* - Security vulnerabilities (SQL injection, XSS, etc.)
|
|
7
|
+
* - Code style and conventions
|
|
8
|
+
* - Correctness of the implementation against the task description
|
|
9
|
+
* - Missing edge cases and error handling
|
|
10
|
+
*
|
|
11
|
+
* Output is stored in the shared context bus as conversation messages.
|
|
12
|
+
*/
|
|
13
|
+
import { Agent } from '../agent.js';
|
|
14
|
+
import { logger } from '../../utils/logger.js';
|
|
15
|
+
const REVIEWER_SYSTEM_PROMPT = `You are a senior code reviewer. Review the following code changes for quality, correctness, and security.
|
|
16
|
+
|
|
17
|
+
Focus on:
|
|
18
|
+
1. **Correctness** — Does the code correctly implement the described task?
|
|
19
|
+
2. **Security** — Any SQL injection, XSS, path traversal, or other vulnerabilities?
|
|
20
|
+
3. **Error handling** — Are edge cases and invalid inputs handled?
|
|
21
|
+
4. **Code quality** — Is the code clean, readable, and maintainable?
|
|
22
|
+
5. **Type safety** — Are there any type mismatches or implicit any types?
|
|
23
|
+
6. **Performance** — Any obvious performance issues?
|
|
24
|
+
|
|
25
|
+
## Output Format
|
|
26
|
+
|
|
27
|
+
ONLY list issues that actually exist. Do NOT describe absent issues.
|
|
28
|
+
|
|
29
|
+
For each issue found, use this exact format:
|
|
30
|
+
- CRITICAL: <description>
|
|
31
|
+
Location: <file/line>
|
|
32
|
+
Fix: <suggestion>
|
|
33
|
+
|
|
34
|
+
- WARNING: <description>
|
|
35
|
+
Location: <file/line>
|
|
36
|
+
Fix: <suggestion>
|
|
37
|
+
|
|
38
|
+
- SUGGESTION: <description>
|
|
39
|
+
Location: <file/line>
|
|
40
|
+
|
|
41
|
+
If NO issues are found, respond ONLY with:
|
|
42
|
+
✅ Review passed. No issues found.
|
|
43
|
+
|
|
44
|
+
Do NOT mention potential issues that don't exist. Do NOT use the words "CRITICAL", "WARNING", or "SUGGESTION" unless you are actually flagging an issue.`;
|
|
45
|
+
/** Maximum API retry attempts for transient LLM failures */
|
|
46
|
+
const MAX_API_RETRIES = 2;
|
|
47
|
+
/** Base delay for exponential backoff (doubles each retry: 1s, 2s) */
|
|
48
|
+
const BASE_RETRY_DELAY_MS = 1000;
|
|
49
|
+
/**
|
|
50
|
+
* ReviewerAgent — Validates code changes produced by WriterAgent.
|
|
51
|
+
*/
|
|
52
|
+
export class ReviewerAgent extends Agent {
|
|
53
|
+
name = 'Reviewer';
|
|
54
|
+
description = 'Validates code changes for correctness, security, and quality';
|
|
55
|
+
async execute(context, callLLM) {
|
|
56
|
+
let lastError;
|
|
57
|
+
if (context.fileChanges.length === 0) {
|
|
58
|
+
return {
|
|
59
|
+
success: true,
|
|
60
|
+
summary: 'No files to review',
|
|
61
|
+
details: 'The WriterAgent did not produce any file changes.',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
for (let attempt = 0; attempt <= MAX_API_RETRIES; attempt++) {
|
|
65
|
+
try {
|
|
66
|
+
const prompt = this.buildPrompt(context);
|
|
67
|
+
const response = await callLLM(prompt, {
|
|
68
|
+
temperature: 0.2,
|
|
69
|
+
maxTokens: 4096,
|
|
70
|
+
});
|
|
71
|
+
// Log the review as a conversation message
|
|
72
|
+
context.conversations.push({
|
|
73
|
+
from: 'Reviewer',
|
|
74
|
+
to: 'Orchestrator',
|
|
75
|
+
content: response,
|
|
76
|
+
timestamp: Date.now(),
|
|
77
|
+
});
|
|
78
|
+
const hasCriticalIssues = this.hasCriticalIssues(response);
|
|
79
|
+
return {
|
|
80
|
+
success: !hasCriticalIssues,
|
|
81
|
+
summary: hasCriticalIssues
|
|
82
|
+
? 'Review found critical issues'
|
|
83
|
+
: 'Review passed',
|
|
84
|
+
details: response,
|
|
85
|
+
error: hasCriticalIssues
|
|
86
|
+
? 'Critical issues found — see review details'
|
|
87
|
+
: undefined,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
lastError = err instanceof Error ? err.message : String(err);
|
|
92
|
+
if (attempt < MAX_API_RETRIES) {
|
|
93
|
+
const delayMs = BASE_RETRY_DELAY_MS * Math.pow(2, attempt);
|
|
94
|
+
logger.warn(`Reviewer API error (attempt ${attempt + 1}/${MAX_API_RETRIES + 1}): ` +
|
|
95
|
+
`${lastError.slice(0, 200)}. Retrying in ${delayMs}ms...`);
|
|
96
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
logger.error(`Reviewer failed after ${MAX_API_RETRIES + 1} API attempts: ${lastError}`);
|
|
100
|
+
return {
|
|
101
|
+
success: false,
|
|
102
|
+
summary: 'Review failed',
|
|
103
|
+
error: lastError,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Unreachable
|
|
108
|
+
return {
|
|
109
|
+
success: false,
|
|
110
|
+
summary: 'Review failed',
|
|
111
|
+
error: lastError || 'Unknown error',
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Build the review prompt from the task plan, relevant context, and changes.
|
|
116
|
+
*/
|
|
117
|
+
buildPrompt(context) {
|
|
118
|
+
// Format the task description
|
|
119
|
+
const taskDescriptions = context.taskPlan
|
|
120
|
+
.filter((s) => s.agentType === 'writer')
|
|
121
|
+
.map((s) => ` - ${s.description}`)
|
|
122
|
+
.join('\n');
|
|
123
|
+
// Format the file changes as diffs
|
|
124
|
+
const diffs = context.fileChanges
|
|
125
|
+
.map((change) => {
|
|
126
|
+
const header = `--- a/${change.path}\n+++ b/${change.path}`;
|
|
127
|
+
if (change.originalContent && change.newContent) {
|
|
128
|
+
// Simple diff: show old and new
|
|
129
|
+
return `${header}\n@@ ... @@\n${change.originalContent}\n---\n${change.newContent}`;
|
|
130
|
+
}
|
|
131
|
+
if (change.status === 'created') {
|
|
132
|
+
return `${header}\n@@ -0,0 +1 @@\n+ (new file)\n${change.newContent}`;
|
|
133
|
+
}
|
|
134
|
+
return header;
|
|
135
|
+
})
|
|
136
|
+
.join('\n\n');
|
|
137
|
+
return `${REVIEWER_SYSTEM_PROMPT}\n\n## Task Description\n${taskDescriptions || context.goal}\n\n## Changes to Review\n${diffs || '(No changes provided)'}\n\n## Instructions\nReview the above changes. Identify any issues and provide feedback.`;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Check if the review response contains any critical issues.
|
|
141
|
+
* Looks for "CRITICAL:" (with colon) at the start of a bullet or line.
|
|
142
|
+
* This avoids false positives from LLMs that say things like
|
|
143
|
+
* "No critical issues found" (which lacks the colon prefix).
|
|
144
|
+
*/
|
|
145
|
+
hasCriticalIssues(review) {
|
|
146
|
+
// Match "CRITICAL:" (with colon) on its own line, as a bullet, or in flow text.
|
|
147
|
+
// The colon prefix is critical — it's how the prompt tells the LLM to format issues.
|
|
148
|
+
// "No critical issues found" won't match; "CRITICAL: SQL injection" will.
|
|
149
|
+
const criticalPrefix = /(?:^|\n|[-*]\s*)CRITICAL\s*:/im;
|
|
150
|
+
// Also match the old patterns for backwards compatibility
|
|
151
|
+
const oldPatterns = [
|
|
152
|
+
/🔴/,
|
|
153
|
+
/\bBlocking\b/,
|
|
154
|
+
/\bSecurity\s*vulnerability\b/i,
|
|
155
|
+
];
|
|
156
|
+
return criticalPrefix.test(review) || oldPatterns.some((p) => p.test(review));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=reviewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviewer.js","sourceRoot":"","sources":["../../../src/agents/agents/reviewer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RunnerAgent — Executes shell commands in the project directory and captures output.
|
|
3
|
+
*
|
|
4
|
+
* This is the agent that makes agent-nuvira capable of *running* the programs
|
|
5
|
+
* it creates. Without this, the system can write files but can never execute
|
|
6
|
+
* them or show the user what happened.
|
|
7
|
+
*
|
|
8
|
+
* Usage in task plans:
|
|
9
|
+
* ```json
|
|
10
|
+
* { "id": "step-03-run", "description": "Run: python hello.py", "agentType": "runner", "dependsOn": ["step-02-write"] }
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* The command to run is determined by:
|
|
14
|
+
* 1. The task description — if it contains a command wrapped in backticks
|
|
15
|
+
* (e.g., "Run `python hello.py`"), that command is extracted and executed.
|
|
16
|
+
* 2. The "Run:" prefix — if the description starts with "Run:", the rest is
|
|
17
|
+
* treated as the command (e.g., "Run: python hello.py").
|
|
18
|
+
* 3. The LLM fallback — if no explicit command is found, the LLM is asked
|
|
19
|
+
* what command to run based on the current context (files created, project type).
|
|
20
|
+
*
|
|
21
|
+
* Output is stored in context metadata as `runResult` and returned in the summary.
|
|
22
|
+
*/
|
|
23
|
+
import { Agent, type AgentContext, type AgentResult } from '../agent.js';
|
|
24
|
+
import type { LLMCallFn } from '../agent.js';
|
|
25
|
+
/**
|
|
26
|
+
* Result of running a command, stored in context.metadata.runResult.
|
|
27
|
+
*/
|
|
28
|
+
export interface RunResult {
|
|
29
|
+
/** Whether the command exited with code 0 */
|
|
30
|
+
success: boolean;
|
|
31
|
+
/** The exact command that was executed */
|
|
32
|
+
command: string;
|
|
33
|
+
/** Process exit code */
|
|
34
|
+
exitCode: number;
|
|
35
|
+
/** Standard output */
|
|
36
|
+
stdout: string;
|
|
37
|
+
/** Standard error */
|
|
38
|
+
stderr: string;
|
|
39
|
+
/** Duration in milliseconds */
|
|
40
|
+
duration: number;
|
|
41
|
+
/** Error message if execSync threw */
|
|
42
|
+
error?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* RunnerAgent — Executes shell commands and captures output.
|
|
46
|
+
*/
|
|
47
|
+
export declare class RunnerAgent extends Agent {
|
|
48
|
+
readonly name = "Runner";
|
|
49
|
+
readonly description = "Executes shell commands and captures output";
|
|
50
|
+
execute(context: AgentContext, callLLM: LLMCallFn): Promise<AgentResult>;
|
|
51
|
+
/**
|
|
52
|
+
* Determine the command to run.
|
|
53
|
+
*
|
|
54
|
+
* Priority order:
|
|
55
|
+
* 1. Parse from task description (backtick-wrapped command or "Run:" prefix)
|
|
56
|
+
* 2. Ask the LLM what command to run based on the files that were created
|
|
57
|
+
*/
|
|
58
|
+
private determineCommand;
|
|
59
|
+
/**
|
|
60
|
+
* Execute a command inside a Docker sandbox container.
|
|
61
|
+
* Falls back to host execution if Docker is not available.
|
|
62
|
+
*/
|
|
63
|
+
private executeWithDocker;
|
|
64
|
+
/**
|
|
65
|
+
* Execute a command directly on the host machine.
|
|
66
|
+
*/
|
|
67
|
+
private executeOnHost;
|
|
68
|
+
/**
|
|
69
|
+
* Fallback: ask the LLM what command to run based on the project context.
|
|
70
|
+
*/
|
|
71
|
+
private askLLMForCommand;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/agents/agents/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH,OAAO,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAY7C;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,6CAA6C;IAC7C,OAAO,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,WAAW,iDAAiD;IAE/D,OAAO,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAiC9E;;;;;;OAMG;YACW,gBAAgB;IAyB9B;;;OAGG;YACW,iBAAiB;IAmG/B;;OAEG;YACW,aAAa;IAiF3B;;OAEG;YACW,gBAAgB;CA8C/B"}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RunnerAgent — Executes shell commands in the project directory and captures output.
|
|
3
|
+
*
|
|
4
|
+
* This is the agent that makes agent-nuvira capable of *running* the programs
|
|
5
|
+
* it creates. Without this, the system can write files but can never execute
|
|
6
|
+
* them or show the user what happened.
|
|
7
|
+
*
|
|
8
|
+
* Usage in task plans:
|
|
9
|
+
* ```json
|
|
10
|
+
* { "id": "step-03-run", "description": "Run: python hello.py", "agentType": "runner", "dependsOn": ["step-02-write"] }
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* The command to run is determined by:
|
|
14
|
+
* 1. The task description — if it contains a command wrapped in backticks
|
|
15
|
+
* (e.g., "Run `python hello.py`"), that command is extracted and executed.
|
|
16
|
+
* 2. The "Run:" prefix — if the description starts with "Run:", the rest is
|
|
17
|
+
* treated as the command (e.g., "Run: python hello.py").
|
|
18
|
+
* 3. The LLM fallback — if no explicit command is found, the LLM is asked
|
|
19
|
+
* what command to run based on the current context (files created, project type).
|
|
20
|
+
*
|
|
21
|
+
* Output is stored in context metadata as `runResult` and returned in the summary.
|
|
22
|
+
*/
|
|
23
|
+
import { execSync } from 'node:child_process';
|
|
24
|
+
import { platform } from 'node:os';
|
|
25
|
+
import { Agent } from '../agent.js';
|
|
26
|
+
import { logger } from '../../utils/logger.js';
|
|
27
|
+
import { SandboxManager } from '../../sandbox/manager.js';
|
|
28
|
+
import { detectProjectImage } from '../../sandbox/images.js';
|
|
29
|
+
import { getSandboxConfig } from '../../sandbox/types.js';
|
|
30
|
+
/** Maximum stdout/stderr length to store in context metadata */
|
|
31
|
+
const MAX_OUTPUT_LENGTH = 10_000;
|
|
32
|
+
/** Timeout per command in milliseconds (default: 2 minutes) */
|
|
33
|
+
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
34
|
+
/**
|
|
35
|
+
* RunnerAgent — Executes shell commands and captures output.
|
|
36
|
+
*/
|
|
37
|
+
export class RunnerAgent extends Agent {
|
|
38
|
+
name = 'Runner';
|
|
39
|
+
description = 'Executes shell commands and captures output';
|
|
40
|
+
async execute(context, callLLM) {
|
|
41
|
+
try {
|
|
42
|
+
// 1. Determine which command to run
|
|
43
|
+
const command = await this.determineCommand(context, callLLM);
|
|
44
|
+
if (!command) {
|
|
45
|
+
return {
|
|
46
|
+
success: false,
|
|
47
|
+
summary: 'No command to run',
|
|
48
|
+
error: 'Could not determine which command to execute from the task description or context.',
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// Check if we should run inside a Docker sandbox
|
|
52
|
+
const useDocker = context.metadata.useDockerSandbox === true ||
|
|
53
|
+
getSandboxConfig().enabled === true;
|
|
54
|
+
if (useDocker) {
|
|
55
|
+
return await this.executeWithDocker(context, command);
|
|
56
|
+
}
|
|
57
|
+
// 2. Execute the command on the host via shared method
|
|
58
|
+
return await this.executeOnHost(context, command);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
62
|
+
return {
|
|
63
|
+
success: false,
|
|
64
|
+
summary: 'Runner failed',
|
|
65
|
+
error: msg,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Determine the command to run.
|
|
71
|
+
*
|
|
72
|
+
* Priority order:
|
|
73
|
+
* 1. Parse from task description (backtick-wrapped command or "Run:" prefix)
|
|
74
|
+
* 2. Ask the LLM what command to run based on the files that were created
|
|
75
|
+
*/
|
|
76
|
+
async determineCommand(context, callLLM) {
|
|
77
|
+
// Find the current 'runner' task in the plan
|
|
78
|
+
const runnerTask = context.taskPlan.find((s) => s.agentType === 'runner' && s.status === 'running');
|
|
79
|
+
const description = runnerTask?.description || context.goal;
|
|
80
|
+
// Strategy 1: Extract command from backticks in the description
|
|
81
|
+
// e.g., "Run `python hello.py` and verify output"
|
|
82
|
+
const backtickMatch = description.match(/`([^`]+)`/);
|
|
83
|
+
if (backtickMatch) {
|
|
84
|
+
return backtickMatch[1].trim();
|
|
85
|
+
}
|
|
86
|
+
// Strategy 2: Extract from "Run:" prefix
|
|
87
|
+
// e.g., "Run: python hello.py"
|
|
88
|
+
const runPrefixMatch = description.match(/^Run:\s*(.+)/i);
|
|
89
|
+
if (runPrefixMatch) {
|
|
90
|
+
return runPrefixMatch[1].trim();
|
|
91
|
+
}
|
|
92
|
+
// Strategy 3: Ask the LLM what command to run
|
|
93
|
+
return await this.askLLMForCommand(context, callLLM);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Execute a command inside a Docker sandbox container.
|
|
97
|
+
* Falls back to host execution if Docker is not available.
|
|
98
|
+
*/
|
|
99
|
+
async executeWithDocker(context, command) {
|
|
100
|
+
const sandboxManager = new SandboxManager();
|
|
101
|
+
let containerId = '';
|
|
102
|
+
try {
|
|
103
|
+
// Check Docker availability
|
|
104
|
+
const dockerAvailable = await sandboxManager.isDockerAvailable();
|
|
105
|
+
if (!dockerAvailable) {
|
|
106
|
+
// Fall back to host execution
|
|
107
|
+
return this.executeOnHost(context, command);
|
|
108
|
+
}
|
|
109
|
+
// Detect the right image for the project
|
|
110
|
+
const image = detectProjectImage(context.workingDirectory);
|
|
111
|
+
// Allow timeout override via context.metadata.runnerTimeout
|
|
112
|
+
const timeoutMs = (typeof context.metadata.runnerTimeout === 'number')
|
|
113
|
+
? context.metadata.runnerTimeout
|
|
114
|
+
: DEFAULT_TIMEOUT_MS;
|
|
115
|
+
// Create a Docker container (use default /workspace as workdir)
|
|
116
|
+
containerId = await sandboxManager.createContainer(image.image, {
|
|
117
|
+
memoryLimit: '512m',
|
|
118
|
+
cpuLimit: 0.5,
|
|
119
|
+
timeoutMs,
|
|
120
|
+
networkAccess: false,
|
|
121
|
+
});
|
|
122
|
+
// Copy project files to the container's workspace
|
|
123
|
+
await sandboxManager.copyProjectToContainer(containerId, context.workingDirectory);
|
|
124
|
+
// Run the command inside the container
|
|
125
|
+
if (context.metadata.verboseLogging) {
|
|
126
|
+
logger.info(` Running (Docker): ${command}`);
|
|
127
|
+
}
|
|
128
|
+
const result = await sandboxManager.runCommand(containerId, command, timeoutMs);
|
|
129
|
+
// Build run result from sandbox result
|
|
130
|
+
const runResult = {
|
|
131
|
+
success: result.success,
|
|
132
|
+
command,
|
|
133
|
+
exitCode: result.exitCode,
|
|
134
|
+
stdout: result.stdout.slice(0, MAX_OUTPUT_LENGTH),
|
|
135
|
+
stderr: result.stderr.slice(0, MAX_OUTPUT_LENGTH),
|
|
136
|
+
duration: result.durationMs,
|
|
137
|
+
error: result.error,
|
|
138
|
+
};
|
|
139
|
+
context.metadata['runResult'] = runResult;
|
|
140
|
+
// Build summary
|
|
141
|
+
const lines = [];
|
|
142
|
+
lines.push(`Command: ${command} (Docker)`);
|
|
143
|
+
lines.push(`Exit code: ${result.exitCode}`);
|
|
144
|
+
lines.push(`Duration: ${result.durationMs}ms`);
|
|
145
|
+
if (result.stdout) {
|
|
146
|
+
const truncated = result.stdout.length > 500;
|
|
147
|
+
lines.push(`stdout:${truncated ? ' (first 500 chars)' : ''}`);
|
|
148
|
+
lines.push(result.stdout.slice(0, 500));
|
|
149
|
+
if (truncated)
|
|
150
|
+
lines.push(`... (${result.stdout.length - 500} more chars)`);
|
|
151
|
+
}
|
|
152
|
+
if (result.stderr && result.exitCode !== 0) {
|
|
153
|
+
const truncated = result.stderr.length > 500;
|
|
154
|
+
lines.push(`stderr:${truncated ? ' (first 500 chars)' : ''}`);
|
|
155
|
+
lines.push(result.stderr.slice(0, 500));
|
|
156
|
+
if (truncated)
|
|
157
|
+
lines.push(`... (${result.stderr.length - 500} more chars)`);
|
|
158
|
+
}
|
|
159
|
+
// Clean up
|
|
160
|
+
await sandboxManager.destroyContainer(containerId).catch(() => { });
|
|
161
|
+
return {
|
|
162
|
+
success: result.exitCode === 0,
|
|
163
|
+
summary: result.exitCode === 0
|
|
164
|
+
? `✅ Command succeeded (Docker): ${command}`
|
|
165
|
+
: `❌ Command failed (exit ${result.exitCode}): ${command}`,
|
|
166
|
+
details: lines.join('\n'),
|
|
167
|
+
error: result.error || undefined,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
if (containerId) {
|
|
172
|
+
await sandboxManager.destroyContainer(containerId).catch(() => { });
|
|
173
|
+
}
|
|
174
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
175
|
+
return {
|
|
176
|
+
success: false,
|
|
177
|
+
summary: 'Docker sandbox execution failed',
|
|
178
|
+
error: msg,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Execute a command directly on the host machine.
|
|
184
|
+
*/
|
|
185
|
+
async executeOnHost(context, command) {
|
|
186
|
+
if (context.metadata.verboseLogging) {
|
|
187
|
+
logger.info(` Running: ${command}`);
|
|
188
|
+
}
|
|
189
|
+
const timeoutMs = (typeof context.metadata.runnerTimeout === 'number')
|
|
190
|
+
? context.metadata.runnerTimeout
|
|
191
|
+
: DEFAULT_TIMEOUT_MS;
|
|
192
|
+
const startTime = Date.now();
|
|
193
|
+
let exitCode = 0;
|
|
194
|
+
let stdout = '';
|
|
195
|
+
let stderr = '';
|
|
196
|
+
let execError;
|
|
197
|
+
try {
|
|
198
|
+
const output = execSync(command, {
|
|
199
|
+
cwd: context.workingDirectory,
|
|
200
|
+
timeout: timeoutMs,
|
|
201
|
+
stdio: 'pipe',
|
|
202
|
+
encoding: 'utf-8',
|
|
203
|
+
shell: platform() === 'win32' ? (process.env.COMSPEC || 'cmd.exe') : '/bin/sh',
|
|
204
|
+
maxBuffer: 1024 * 1024,
|
|
205
|
+
});
|
|
206
|
+
stdout = output.trim();
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
const error = err;
|
|
210
|
+
exitCode = error.status ?? 1;
|
|
211
|
+
stdout = (typeof error.stdout === 'string' ? error.stdout : String(error.stdout || '')).trim();
|
|
212
|
+
stderr = (typeof error.stderr === 'string' ? error.stderr : String(error.stderr || '')).trim();
|
|
213
|
+
execError = error.message;
|
|
214
|
+
}
|
|
215
|
+
const duration = Date.now() - startTime;
|
|
216
|
+
const runResult = {
|
|
217
|
+
success: exitCode === 0,
|
|
218
|
+
command,
|
|
219
|
+
exitCode,
|
|
220
|
+
stdout: stdout.slice(0, MAX_OUTPUT_LENGTH),
|
|
221
|
+
stderr: stderr.slice(0, MAX_OUTPUT_LENGTH),
|
|
222
|
+
duration,
|
|
223
|
+
error: execError,
|
|
224
|
+
};
|
|
225
|
+
context.metadata['runResult'] = runResult;
|
|
226
|
+
const lines = [];
|
|
227
|
+
lines.push(`Command: ${command}`);
|
|
228
|
+
lines.push(`Exit code: ${exitCode}`);
|
|
229
|
+
lines.push(`Duration: ${duration}ms`);
|
|
230
|
+
if (stdout) {
|
|
231
|
+
const truncated = stdout.length > 500;
|
|
232
|
+
lines.push(`stdout:${truncated ? ' (first 500 chars)' : ''}`);
|
|
233
|
+
lines.push(stdout.slice(0, 500));
|
|
234
|
+
if (truncated)
|
|
235
|
+
lines.push(`... (${stdout.length - 500} more chars)`);
|
|
236
|
+
}
|
|
237
|
+
if (stderr && exitCode !== 0) {
|
|
238
|
+
const truncated = stderr.length > 500;
|
|
239
|
+
lines.push(`stderr:${truncated ? ' (first 500 chars)' : ''}`);
|
|
240
|
+
lines.push(stderr.slice(0, 500));
|
|
241
|
+
if (truncated)
|
|
242
|
+
lines.push(`... (${stderr.length - 500} more chars)`);
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
success: exitCode === 0,
|
|
246
|
+
summary: exitCode === 0
|
|
247
|
+
? `✅ Command succeeded: ${command}`
|
|
248
|
+
: `❌ Command failed (exit ${exitCode}): ${command}`,
|
|
249
|
+
details: lines.join('\n'),
|
|
250
|
+
error: execError && exitCode !== 0 ? execError : undefined,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Fallback: ask the LLM what command to run based on the project context.
|
|
255
|
+
*/
|
|
256
|
+
async askLLMForCommand(context, callLLM) {
|
|
257
|
+
const fileList = context.fileChanges
|
|
258
|
+
.map((c) => ` - ${c.path} (${c.status})`)
|
|
259
|
+
.join('\n');
|
|
260
|
+
const artifactList = context.artifacts
|
|
261
|
+
.slice(0, 5)
|
|
262
|
+
.map((a) => ` - ${a.path}`)
|
|
263
|
+
.join('\n');
|
|
264
|
+
const prompt = [
|
|
265
|
+
'You are a build-and-run expert. Given the context below, what single shell command should be executed',
|
|
266
|
+
'to verify the work that was done? Return ONLY the command, no explanation, no markdown.',
|
|
267
|
+
'',
|
|
268
|
+
`Goal: ${context.goal}`,
|
|
269
|
+
'',
|
|
270
|
+
'Files changed:',
|
|
271
|
+
fileList || ' (no files changed)',
|
|
272
|
+
'',
|
|
273
|
+
'Relevant project files:',
|
|
274
|
+
artifactList || ' (empty project)',
|
|
275
|
+
'',
|
|
276
|
+
'Return ONLY the command to run. Example: "python hello.py" or "node index.js" or "npm test" or "go run main.go".',
|
|
277
|
+
'Rules:',
|
|
278
|
+
'- Return a single line command only',
|
|
279
|
+
'- No backticks, no explanation, no $ prefix',
|
|
280
|
+
'- Use absolute or working-directory-relative paths',
|
|
281
|
+
'- If unsure, suggest the most appropriate verification command',
|
|
282
|
+
].join('\n');
|
|
283
|
+
try {
|
|
284
|
+
const response = await callLLM(prompt, {
|
|
285
|
+
temperature: 0.1,
|
|
286
|
+
maxTokens: 256,
|
|
287
|
+
});
|
|
288
|
+
const command = response.trim().replace(/^```(?:bash|sh)?\s*|\s*```$/g, '').trim();
|
|
289
|
+
if (command && !command.includes('\n') && command.length < 500) {
|
|
290
|
+
return command;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
// LLM fallback failed — return null
|
|
295
|
+
}
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/agents/agents/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SecurityAgent — Detects security issues in agent prompts and generated code.
|
|
3
|
+
*
|
|
4
|
+
* Capabilities:
|
|
5
|
+
* - Scan LLM prompts for injection/jailbreak attempts before sending
|
|
6
|
+
* - Scan generated code changes for PII, dangerous patterns, vulnerabilities
|
|
7
|
+
* - Validate file paths for directory traversal attempts
|
|
8
|
+
* - Integrated with the orchestrator pipeline to block unsafe content
|
|
9
|
+
*
|
|
10
|
+
* Usage in task plans:
|
|
11
|
+
* ```json
|
|
12
|
+
* { "id": "step-security", "description": "Scan code for security issues", "agentType": "security", "dependsOn": ["step-write"] }
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
import { Agent, type AgentContext, type AgentResult } from '../agent.js';
|
|
16
|
+
import type { LLMCallFn } from '../agent.js';
|
|
17
|
+
/**
|
|
18
|
+
* SecurityAgent — Scans prompts and generated content for security issues.
|
|
19
|
+
*/
|
|
20
|
+
export declare class SecurityAgent extends Agent {
|
|
21
|
+
readonly name = "Security";
|
|
22
|
+
readonly description = "Scans for PII, prompt injection, and dangerous code patterns";
|
|
23
|
+
execute(context: AgentContext, callLLM: LLMCallFn): Promise<AgentResult>;
|
|
24
|
+
/**
|
|
25
|
+
* Parse which scan types to run based on the task description.
|
|
26
|
+
*/
|
|
27
|
+
private parseScanTypes;
|
|
28
|
+
/**
|
|
29
|
+
* Check if a file path is safe (no directory traversal, no protected paths).
|
|
30
|
+
*/
|
|
31
|
+
private checkPathSafety;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=security-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-agent.d.ts","sourceRoot":"","sources":["../../../src/agents/agents/security-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAgC7C;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,cAAc;IAC3B,QAAQ,CAAC,WAAW,kEAAkE;IAEhF,OAAO,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAwG9E;;OAEG;IACH,OAAO,CAAC,cAAc;IA4BtB;;OAEG;IACH,OAAO,CAAC,eAAe;CA8BxB"}
|