@machina.ai/cell-cli-core 1.10.0-rc1 → 1.13.0-rc1
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/dist/index.d.ts +5 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/package.json +13 -5
- package/dist/src/agents/codebase-investigator.js +2 -5
- package/dist/src/agents/codebase-investigator.js.map +1 -1
- package/dist/src/agents/executor.d.ts +19 -0
- package/dist/src/agents/executor.js +234 -46
- package/dist/src/agents/executor.js.map +1 -1
- package/dist/src/agents/executor.test.js +371 -40
- package/dist/src/agents/executor.test.js.map +1 -1
- package/dist/src/agents/registry.js +4 -3
- package/dist/src/agents/registry.js.map +1 -1
- package/dist/src/agents/subagent-tool-wrapper.test.js +2 -4
- package/dist/src/agents/subagent-tool-wrapper.test.js.map +1 -1
- package/dist/src/agents/types.d.ts +2 -1
- package/dist/src/agents/types.js +1 -0
- package/dist/src/agents/types.js.map +1 -1
- package/dist/src/code_assist/converter.d.ts +1 -0
- package/dist/src/code_assist/converter.js +1 -0
- package/dist/src/code_assist/converter.js.map +1 -1
- package/dist/src/code_assist/converter.test.js +19 -0
- package/dist/src/code_assist/converter.test.js.map +1 -1
- package/dist/src/code_assist/experiments/client_metadata.d.ts +12 -0
- package/dist/src/code_assist/experiments/client_metadata.js +49 -0
- package/dist/src/code_assist/experiments/client_metadata.js.map +1 -0
- package/dist/src/code_assist/experiments/experiments.d.ts +17 -0
- package/dist/src/code_assist/experiments/experiments.js +36 -0
- package/dist/src/code_assist/experiments/experiments.js.map +1 -0
- package/dist/src/code_assist/experiments/types.d.ts +35 -0
- package/dist/src/code_assist/experiments/types.js +7 -0
- package/dist/src/code_assist/experiments/types.js.map +1 -0
- package/dist/src/code_assist/oauth-credential-storage.js +5 -4
- package/dist/src/code_assist/oauth-credential-storage.js.map +1 -1
- package/dist/src/code_assist/oauth-credential-storage.test.js +15 -3
- package/dist/src/code_assist/oauth-credential-storage.test.js.map +1 -1
- package/dist/src/code_assist/oauth2.d.ts +2 -2
- package/dist/src/code_assist/oauth2.js +64 -51
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +65 -33
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/code_assist/server.d.ts +6 -4
- package/dist/src/code_assist/server.js +11 -0
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/server.test.js +17 -0
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/code_assist/setup.d.ts +2 -2
- package/dist/src/code_assist/setup.js.map +1 -1
- package/dist/src/code_assist/types.d.ts +1 -1
- package/dist/src/code_assist/types.js.map +1 -1
- package/dist/src/commands/extensions.d.ts +7 -0
- package/dist/src/commands/extensions.js +9 -0
- package/dist/src/commands/extensions.js.map +1 -0
- package/dist/src/commands/extensions.test.js +19 -0
- package/dist/src/commands/extensions.test.js.map +1 -0
- package/dist/src/config/config.d.ts +81 -32
- package/dist/src/config/config.js +193 -66
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +115 -36
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/models.d.ts +1 -1
- package/dist/src/config/models.js +2 -2
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/config/storage.d.ts +3 -0
- package/dist/src/config/storage.js +20 -0
- package/dist/src/config/storage.js.map +1 -1
- package/dist/src/confirmation-bus/message-bus.d.ts +2 -1
- package/dist/src/confirmation-bus/message-bus.js +7 -1
- package/dist/src/confirmation-bus/message-bus.js.map +1 -1
- package/dist/src/confirmation-bus/types.d.ts +12 -2
- package/dist/src/confirmation-bus/types.js +1 -0
- package/dist/src/confirmation-bus/types.js.map +1 -1
- package/dist/src/core/apiKeyCredentialStorage.d.ts +17 -0
- package/dist/src/core/apiKeyCredentialStorage.js +64 -0
- package/dist/src/core/apiKeyCredentialStorage.js.map +1 -0
- package/dist/src/core/apiKeyCredentialStorage.test.d.ts +6 -0
- package/dist/src/core/apiKeyCredentialStorage.test.js +71 -0
- package/dist/src/core/apiKeyCredentialStorage.test.js.map +1 -0
- package/dist/src/core/client.d.ts +2 -11
- package/dist/src/core/client.js +31 -170
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +107 -429
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.js +64 -59
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +38 -4
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +8 -2
- package/dist/src/core/coreToolScheduler.js +337 -172
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +363 -12
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/fakeContentGenerator.d.ts +33 -0
- package/dist/src/core/fakeContentGenerator.js +58 -0
- package/dist/src/core/fakeContentGenerator.js.map +1 -0
- package/dist/src/core/fakeContentGenerator.test.d.ts +6 -0
- package/dist/src/core/fakeContentGenerator.test.js +127 -0
- package/dist/src/core/fakeContentGenerator.test.js.map +1 -0
- package/dist/src/core/geminiChat.d.ts +2 -0
- package/dist/src/core/geminiChat.js +7 -2
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +15 -3
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/logger.js +21 -19
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.d.ts +1 -0
- package/dist/src/core/loggingContentGenerator.js +113 -33
- package/dist/src/core/loggingContentGenerator.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.js +5 -4
- package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +3 -0
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/prompts.js +115 -72
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/prompts.test.js +30 -108
- package/dist/src/core/prompts.test.js.map +1 -1
- package/dist/src/core/recordingContentGenerator.d.ts +18 -0
- package/dist/src/core/recordingContentGenerator.js +77 -0
- package/dist/src/core/recordingContentGenerator.js.map +1 -0
- package/dist/src/core/recordingContentGenerator.test.d.ts +6 -0
- package/dist/src/core/recordingContentGenerator.test.js +101 -0
- package/dist/src/core/recordingContentGenerator.test.js.map +1 -0
- package/dist/src/core/turn.d.ts +2 -0
- package/dist/src/core/turn.js +3 -1
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/core/turn.test.js +48 -0
- package/dist/src/core/turn.test.js.map +1 -1
- package/dist/src/fallback/handler.js +2 -0
- package/dist/src/fallback/handler.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/hooks/hookPlanner.d.ts +46 -0
- package/dist/src/hooks/hookPlanner.js +108 -0
- package/dist/src/hooks/hookPlanner.js.map +1 -0
- package/dist/src/hooks/hookPlanner.test.d.ts +6 -0
- package/dist/src/hooks/hookPlanner.test.js +255 -0
- package/dist/src/hooks/hookPlanner.test.js.map +1 -0
- package/dist/src/hooks/hookRegistry.d.ts +87 -0
- package/dist/src/hooks/hookRegistry.js +198 -0
- package/dist/src/hooks/hookRegistry.js.map +1 -0
- package/dist/src/hooks/hookRegistry.test.d.ts +6 -0
- package/dist/src/hooks/hookRegistry.test.js +341 -0
- package/dist/src/hooks/hookRegistry.test.js.map +1 -0
- package/dist/src/hooks/hookTranslator.d.ts +113 -0
- package/dist/src/hooks/hookTranslator.js +232 -0
- package/dist/src/hooks/hookTranslator.js.map +1 -0
- package/dist/src/hooks/hookTranslator.test.d.ts +6 -0
- package/dist/src/hooks/hookTranslator.test.js +192 -0
- package/dist/src/hooks/hookTranslator.test.js.map +1 -0
- package/dist/src/hooks/types.d.ts +384 -0
- package/dist/src/hooks/types.js +284 -0
- package/dist/src/hooks/types.js.map +1 -0
- package/dist/src/hooks/types.test.d.ts +6 -0
- package/dist/src/hooks/types.test.js +35 -0
- package/dist/src/hooks/types.test.js.map +1 -0
- package/dist/src/ide/ide-client.js +2 -1
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/index.d.ts +15 -0
- package/dist/src/index.js +18 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/google-auth-provider.d.ts +2 -0
- package/dist/src/mcp/google-auth-provider.js +21 -3
- package/dist/src/mcp/google-auth-provider.js.map +1 -1
- package/dist/src/mcp/google-auth-provider.test.js +42 -9
- package/dist/src/mcp/google-auth-provider.test.js.map +1 -1
- package/dist/src/mcp/mcpLauncher.d.ts +26 -0
- package/dist/src/mcp/mcpLauncher.js +238 -0
- package/dist/src/mcp/mcpLauncher.js.map +1 -0
- package/dist/src/mcp/oauth-provider.d.ts +8 -5
- package/dist/src/mcp/oauth-provider.js +140 -55
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.test.js +191 -2
- package/dist/src/mcp/oauth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.js +5 -4
- package/dist/src/mcp/oauth-token-storage.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.test.js +17 -11
- package/dist/src/mcp/oauth-token-storage.test.js.map +1 -1
- package/dist/src/mcp/oauth-utils.d.ts +7 -0
- package/dist/src/mcp/oauth-utils.js +28 -8
- package/dist/src/mcp/oauth-utils.js.map +1 -1
- package/dist/src/mcp/oauth-utils.test.js +45 -2
- package/dist/src/mcp/oauth-utils.test.js.map +1 -1
- package/dist/src/mcp/sa-impersonation-provider.d.ts +0 -6
- package/dist/src/mcp/sa-impersonation-provider.js +6 -23
- package/dist/src/mcp/sa-impersonation-provider.js.map +1 -1
- package/dist/src/mcp/token-storage/base-token-storage.test.js +75 -84
- package/dist/src/mcp/token-storage/base-token-storage.test.js.map +1 -1
- package/dist/src/mcp/token-storage/file-token-storage.js +1 -1
- package/dist/src/mcp/token-storage/file-token-storage.js.map +1 -1
- package/dist/src/mcp/token-storage/file-token-storage.test.js +7 -5
- package/dist/src/mcp/token-storage/file-token-storage.test.js.map +1 -1
- package/dist/src/mcp/token-storage/hybrid-token-storage.js +1 -1
- package/dist/src/mcp/token-storage/hybrid-token-storage.js.map +1 -1
- package/dist/src/mcp/token-storage/hybrid-token-storage.test.js +2 -2
- package/dist/src/mcp/token-storage/hybrid-token-storage.test.js.map +1 -1
- package/dist/src/mcp/token-storage/keychain-token-storage.d.ts +6 -2
- package/dist/src/mcp/token-storage/keychain-token-storage.js +63 -7
- package/dist/src/mcp/token-storage/keychain-token-storage.js.map +1 -1
- package/dist/src/mcp/token-storage/keychain-token-storage.test.js +54 -3
- package/dist/src/mcp/token-storage/keychain-token-storage.test.js.map +1 -1
- package/dist/src/mcp/token-storage/types.d.ts +6 -0
- package/dist/src/mcp/token-storage/types.js.map +1 -1
- package/dist/src/output/stream-json-formatter.d.ts +32 -0
- package/dist/src/output/stream-json-formatter.js +52 -0
- package/dist/src/output/stream-json-formatter.js.map +1 -0
- package/dist/src/output/stream-json-formatter.test.d.ts +6 -0
- package/dist/src/output/stream-json-formatter.test.js +479 -0
- package/dist/src/output/stream-json-formatter.test.js.map +1 -0
- package/dist/src/output/types.d.ts +63 -1
- package/dist/src/output/types.js +11 -0
- package/dist/src/output/types.js.map +1 -1
- package/dist/src/policy/config.d.ts +31 -0
- package/dist/src/policy/config.js +197 -0
- package/dist/src/policy/config.js.map +1 -0
- package/dist/src/policy/config.test.d.ts +6 -0
- package/dist/src/policy/config.test.js +404 -0
- package/dist/src/policy/config.test.js.map +1 -0
- package/dist/src/policy/index.d.ts +2 -0
- package/dist/src/policy/index.js +2 -0
- package/dist/src/policy/index.js.map +1 -1
- package/dist/src/policy/policies/read-only.toml +56 -0
- package/dist/src/policy/policies/write.toml +63 -0
- package/dist/src/policy/policies/yolo.toml +31 -0
- package/dist/src/policy/policy-engine.js +4 -0
- package/dist/src/policy/policy-engine.js.map +1 -1
- package/dist/src/policy/toml-loader.d.ts +46 -0
- package/dist/src/policy/toml-loader.js +314 -0
- package/dist/src/policy/toml-loader.js.map +1 -0
- package/dist/src/policy/toml-loader.test.d.ts +6 -0
- package/dist/src/policy/toml-loader.test.js +522 -0
- package/dist/src/policy/toml-loader.test.js.map +1 -0
- package/dist/src/policy/types.d.ts +18 -0
- package/dist/src/policy/types.js +6 -0
- package/dist/src/policy/types.js.map +1 -1
- package/dist/src/prompts/prompt-registry.js +2 -1
- package/dist/src/prompts/prompt-registry.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.js +3 -2
- package/dist/src/routing/strategies/classifierStrategy.js.map +1 -1
- package/dist/src/services/chatCompressionService.d.ts +32 -0
- package/dist/src/services/chatCompressionService.js +162 -0
- package/dist/src/services/chatCompressionService.js.map +1 -0
- package/dist/src/services/chatCompressionService.test.d.ts +6 -0
- package/dist/src/services/chatCompressionService.test.js +209 -0
- package/dist/src/services/chatCompressionService.test.js.map +1 -0
- package/dist/src/services/chatRecordingService.js +9 -8
- package/dist/src/services/chatRecordingService.js.map +1 -1
- package/dist/src/services/fileDiscoveryService.d.ts +2 -14
- package/dist/src/services/fileDiscoveryService.js +19 -55
- package/dist/src/services/fileDiscoveryService.js.map +1 -1
- package/dist/src/services/fileDiscoveryService.test.js +91 -11
- package/dist/src/services/fileDiscoveryService.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.d.ts +1 -1
- package/dist/src/services/loopDetectionService.js +27 -13
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +119 -11
- package/dist/src/services/loopDetectionService.test.js.map +1 -1
- package/dist/src/services/shellExecutionService.js +50 -23
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/shellExecutionService.test.js +82 -15
- package/dist/src/services/shellExecutionService.test.js.map +1 -1
- package/dist/src/telemetry/activity-monitor.d.ts +116 -0
- package/dist/src/telemetry/activity-monitor.js +209 -0
- package/dist/src/telemetry/activity-monitor.js.map +1 -0
- package/dist/src/telemetry/activity-monitor.test.d.ts +6 -0
- package/dist/src/telemetry/activity-monitor.test.js +248 -0
- package/dist/src/telemetry/activity-monitor.test.js.map +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +5 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +135 -57
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +43 -75
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +7 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +13 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/gcp-exporters.js +0 -1
- package/dist/src/telemetry/gcp-exporters.js.map +1 -1
- package/dist/src/telemetry/gcp-exporters.test.js +1 -1
- package/dist/src/telemetry/gcp-exporters.test.js.map +1 -1
- package/dist/src/telemetry/index.d.ts +4 -2
- package/dist/src/telemetry/index.js +5 -3
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +2 -1
- package/dist/src/telemetry/loggers.js +37 -26
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +215 -56
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/metrics.d.ts +55 -6
- package/dist/src/telemetry/metrics.js +89 -1
- package/dist/src/telemetry/metrics.js.map +1 -1
- package/dist/src/telemetry/metrics.test.js +172 -213
- package/dist/src/telemetry/metrics.test.js.map +1 -1
- package/dist/src/telemetry/sdk.js +3 -2
- package/dist/src/telemetry/sdk.js.map +1 -1
- package/dist/src/telemetry/semantic.d.ts +82 -0
- package/dist/src/telemetry/semantic.js +269 -0
- package/dist/src/telemetry/semantic.js.map +1 -0
- package/dist/src/telemetry/semantic.test.d.ts +6 -0
- package/dist/src/telemetry/semantic.test.js +387 -0
- package/dist/src/telemetry/semantic.test.js.map +1 -0
- package/dist/src/telemetry/telemetry-utils.test.js +29 -28
- package/dist/src/telemetry/telemetry-utils.test.js.map +1 -1
- package/dist/src/telemetry/trace.d.ts +46 -0
- package/dist/src/telemetry/trace.js +121 -0
- package/dist/src/telemetry/trace.js.map +1 -0
- package/dist/src/telemetry/types.d.ts +79 -34
- package/dist/src/telemetry/types.js +191 -61
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.js +6 -6
- package/dist/src/telemetry/uiTelemetry.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +88 -66
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/tools/edit.d.ts +3 -2
- package/dist/src/tools/edit.js +24 -19
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +78 -2
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/glob.d.ts +3 -2
- package/dist/src/tools/glob.js +15 -19
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/glob.test.js +203 -199
- package/dist/src/tools/glob.test.js.map +1 -1
- package/dist/src/tools/grep.d.ts +3 -2
- package/dist/src/tools/grep.js +22 -16
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/ls.d.ts +3 -2
- package/dist/src/tools/ls.js +15 -20
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.js +2 -9
- package/dist/src/tools/ls.test.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.d.ts +49 -11
- package/dist/src/tools/mcp-client-manager.js +209 -31
- package/dist/src/tools/mcp-client-manager.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.test.js +132 -25
- package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +5 -1
- package/dist/src/tools/mcp-client.js +85 -104
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +65 -6
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/mcp-tool.d.ts +5 -2
- package/dist/src/tools/mcp-tool.js +16 -8
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/memoryTool.d.ts +6 -4
- package/dist/src/tools/memoryTool.js +13 -10
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/message-bus-integration.test.js +14 -1
- package/dist/src/tools/message-bus-integration.test.js.map +1 -1
- package/dist/src/tools/modifiable-tool.js +3 -2
- package/dist/src/tools/modifiable-tool.js.map +1 -1
- package/dist/src/tools/read-file.d.ts +4 -3
- package/dist/src/tools/read-file.js +16 -11
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +25 -2
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.d.ts +4 -3
- package/dist/src/tools/read-many-files.js +19 -37
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +0 -1
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/ripGrep.d.ts +3 -2
- package/dist/src/tools/ripGrep.js +47 -17
- package/dist/src/tools/ripGrep.js.map +1 -1
- package/dist/src/tools/ripGrep.test.js +106 -60
- package/dist/src/tools/ripGrep.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +7 -5
- package/dist/src/tools/shell.js +39 -68
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +69 -9
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/smart-edit.d.ts +3 -2
- package/dist/src/tools/smart-edit.js +30 -18
- package/dist/src/tools/smart-edit.js.map +1 -1
- package/dist/src/tools/smart-edit.test.js +62 -2
- package/dist/src/tools/smart-edit.test.js.map +1 -1
- package/dist/src/tools/tool-names.d.ts +8 -0
- package/dist/src/tools/tool-names.js +8 -5
- package/dist/src/tools/tool-names.js.map +1 -1
- package/dist/src/tools/tool-registry.d.ts +6 -19
- package/dist/src/tools/tool-registry.js +14 -49
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +2 -24
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +22 -8
- package/dist/src/tools/tools.js +65 -36
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/web-fetch.d.ts +4 -3
- package/dist/src/tools/web-fetch.js +37 -25
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-fetch.test.js +262 -1
- package/dist/src/tools/web-fetch.test.js.map +1 -1
- package/dist/src/tools/web-search.d.ts +4 -3
- package/dist/src/tools/web-search.js +8 -6
- package/dist/src/tools/web-search.js.map +1 -1
- package/dist/src/tools/write-file.d.ts +3 -2
- package/dist/src/tools/write-file.js +8 -8
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +1 -2
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/tools/write-todos.d.ts +4 -8
- package/dist/src/tools/write-todos.js +15 -6
- package/dist/src/tools/write-todos.js.map +1 -1
- package/dist/src/tools/write-todos.test.js +2 -2
- package/dist/src/tools/write-todos.test.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.js +3 -2
- package/dist/src/utils/bfsFileSearch.js.map +1 -1
- package/dist/src/utils/channel.d.ts +19 -0
- package/dist/src/utils/channel.js +49 -0
- package/dist/src/utils/channel.js.map +1 -0
- package/dist/src/utils/channel.test.d.ts +6 -0
- package/dist/src/utils/channel.test.js +170 -0
- package/dist/src/utils/channel.test.js.map +1 -0
- package/dist/src/utils/debugLogger.d.ts +25 -0
- package/dist/src/utils/debugLogger.js +33 -0
- package/dist/src/utils/debugLogger.js.map +1 -0
- package/dist/src/utils/debugLogger.test.d.ts +6 -0
- package/dist/src/utils/debugLogger.test.js +67 -0
- package/dist/src/utils/debugLogger.test.js.map +1 -0
- package/dist/src/utils/delay.d.ts +16 -0
- package/dist/src/utils/delay.js +43 -0
- package/dist/src/utils/delay.js.map +1 -0
- package/dist/src/utils/delay.test.d.ts +6 -0
- package/dist/src/utils/delay.test.js +88 -0
- package/dist/src/utils/delay.test.js.map +1 -0
- package/dist/src/utils/editCorrector.js +5 -9
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js +3 -5
- package/dist/src/utils/editCorrector.test.js.map +1 -1
- package/dist/src/utils/editor.js +33 -38
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/environmentContext.d.ts +2 -1
- package/dist/src/utils/environmentContext.js +18 -33
- package/dist/src/utils/environmentContext.js.map +1 -1
- package/dist/src/utils/environmentContext.test.js +0 -34
- package/dist/src/utils/environmentContext.test.js.map +1 -1
- package/dist/src/utils/errorParsing.d.ts +1 -1
- package/dist/src/utils/errorParsing.js +5 -33
- package/dist/src/utils/errorParsing.js.map +1 -1
- package/dist/src/utils/errorParsing.test.js +0 -88
- package/dist/src/utils/errorParsing.test.js.map +1 -1
- package/dist/src/utils/errors.d.ts +3 -0
- package/dist/src/utils/errors.js +6 -0
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/events.d.ts +88 -0
- package/dist/src/utils/events.js +77 -0
- package/dist/src/utils/events.js.map +1 -0
- package/dist/src/utils/events.test.d.ts +6 -0
- package/dist/src/utils/events.test.js +131 -0
- package/dist/src/utils/events.test.js.map +1 -0
- package/dist/src/utils/extensionLoader.d.ts +78 -0
- package/dist/src/utils/extensionLoader.js +162 -0
- package/dist/src/utils/extensionLoader.js.map +1 -0
- package/dist/src/utils/extensionLoader.test.d.ts +6 -0
- package/dist/src/utils/extensionLoader.test.js +90 -0
- package/dist/src/utils/extensionLoader.test.js.map +1 -0
- package/dist/src/utils/fetch.d.ts +1 -0
- package/dist/src/utils/fetch.js +4 -0
- package/dist/src/utils/fetch.js.map +1 -1
- package/dist/src/utils/fileUtils.d.ts +4 -0
- package/dist/src/utils/fileUtils.js +34 -2
- package/dist/src/utils/fileUtils.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +12 -1
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/flashFallback.test.js +26 -45
- package/dist/src/utils/flashFallback.test.js.map +1 -1
- package/dist/src/utils/getFolderStructure.js +9 -17
- package/dist/src/utils/getFolderStructure.js.map +1 -1
- package/dist/src/utils/gitIgnoreParser.d.ts +4 -1
- package/dist/src/utils/gitIgnoreParser.js +28 -10
- package/dist/src/utils/gitIgnoreParser.js.map +1 -1
- package/dist/src/utils/gitIgnoreParser.test.js +58 -0
- package/dist/src/utils/gitIgnoreParser.test.js.map +1 -1
- package/dist/src/utils/googleErrors.d.ts +104 -0
- package/dist/src/utils/googleErrors.js +152 -0
- package/dist/src/utils/googleErrors.js.map +1 -0
- package/dist/src/utils/googleErrors.test.d.ts +6 -0
- package/dist/src/utils/googleErrors.test.js +301 -0
- package/dist/src/utils/googleErrors.test.js.map +1 -0
- package/dist/src/utils/googleQuotaErrors.d.ts +36 -0
- package/dist/src/utils/googleQuotaErrors.js +149 -0
- package/dist/src/utils/googleQuotaErrors.js.map +1 -0
- package/dist/src/utils/googleQuotaErrors.test.d.ts +6 -0
- package/dist/src/utils/googleQuotaErrors.test.js +311 -0
- package/dist/src/utils/googleQuotaErrors.test.js.map +1 -0
- package/dist/src/utils/ignorePatterns.test.js +26 -30
- package/dist/src/utils/ignorePatterns.test.js.map +1 -1
- package/dist/src/utils/installationManager.js +2 -1
- package/dist/src/utils/installationManager.js.map +1 -1
- package/dist/src/utils/installationManager.test.js +3 -3
- package/dist/src/utils/installationManager.test.js.map +1 -1
- package/dist/src/utils/llm-edit-fixer.d.ts +1 -1
- package/dist/src/utils/llm-edit-fixer.js +29 -4
- package/dist/src/utils/llm-edit-fixer.js.map +1 -1
- package/dist/src/utils/llm-edit-fixer.test.js +21 -0
- package/dist/src/utils/llm-edit-fixer.test.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.d.ts +11 -1
- package/dist/src/utils/memoryDiscovery.js +150 -11
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +157 -19
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.js +3 -2
- package/dist/src/utils/memoryImportProcessor.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.js +2 -1
- package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
- package/dist/src/utils/package.d.ts +12 -0
- package/dist/src/utils/package.js +15 -0
- package/dist/src/utils/package.js.map +1 -0
- package/dist/src/utils/paths.js +126 -26
- package/dist/src/utils/paths.js.map +1 -1
- package/dist/src/utils/paths.test.js +200 -68
- package/dist/src/utils/paths.test.js.map +1 -1
- package/dist/src/utils/quotaErrorDetection.d.ts +0 -2
- package/dist/src/utils/quotaErrorDetection.js +0 -46
- package/dist/src/utils/quotaErrorDetection.js.map +1 -1
- package/dist/src/utils/retry.d.ts +1 -0
- package/dist/src/utils/retry.js +57 -158
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js +48 -109
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/src/utils/safeJsonStringify.d.ts +4 -4
- package/dist/src/utils/safeJsonStringify.js +31 -7
- package/dist/src/utils/safeJsonStringify.js.map +1 -1
- package/dist/src/utils/shell-utils.d.ts +14 -2
- package/dist/src/utils/shell-utils.js +381 -136
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/shell-utils.test.js +242 -60
- package/dist/src/utils/shell-utils.test.js.map +1 -1
- package/dist/src/utils/summarizer.js +2 -1
- package/dist/src/utils/summarizer.js.map +1 -1
- package/dist/src/utils/summarizer.test.js +0 -1
- package/dist/src/utils/summarizer.test.js.map +1 -1
- package/dist/src/utils/systemEncoding.js +5 -4
- package/dist/src/utils/systemEncoding.js.map +1 -1
- package/dist/src/utils/tool-utils.d.ts +2 -2
- package/dist/src/utils/tool-utils.js +14 -5
- package/dist/src/utils/tool-utils.js.map +1 -1
- package/dist/src/utils/userAccountManager.js +5 -4
- package/dist/src/utils/userAccountManager.js.map +1 -1
- package/dist/src/utils/workspaceContext.js +3 -2
- package/dist/src/utils/workspaceContext.js.map +1 -1
- package/dist/src/utils/workspaceContext.test.js +2 -2
- package/dist/src/utils/workspaceContext.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -5
- package/dist/src/core/subagent.d.ts +0 -236
- package/dist/src/core/subagent.js +0 -482
- package/dist/src/core/subagent.js.map +0 -1
- package/dist/src/core/subagent.test.js +0 -556
- package/dist/src/core/subagent.test.js.map +0 -1
- /package/dist/src/{core/subagent.test.d.ts → commands/extensions.test.d.ts} +0 -0
|
@@ -8,15 +8,15 @@ import { AgentExecutor } from './executor.js';
|
|
|
8
8
|
import { makeFakeConfig } from '../test-utils/config.js';
|
|
9
9
|
import { ToolRegistry } from '../tools/tool-registry.js';
|
|
10
10
|
import { LSTool } from '../tools/ls.js';
|
|
11
|
-
import {
|
|
11
|
+
import { LS_TOOL_NAME, READ_FILE_TOOL_NAME } from '../tools/tool-names.js';
|
|
12
12
|
import { GeminiChat, StreamEventType, } from '../core/geminiChat.js';
|
|
13
13
|
import {} from '@google/genai';
|
|
14
14
|
import { MockTool } from '../test-utils/mock-tool.js';
|
|
15
15
|
import { getDirectoryContextString } from '../utils/environmentContext.js';
|
|
16
16
|
import { z } from 'zod';
|
|
17
17
|
import { promptIdContext } from '../utils/promptIdContext.js';
|
|
18
|
-
import { logAgentStart, logAgentFinish } from '../telemetry/loggers.js';
|
|
19
|
-
import { AgentStartEvent, AgentFinishEvent } from '../telemetry/types.js';
|
|
18
|
+
import { logAgentStart, logAgentFinish, logRecoveryAttempt, } from '../telemetry/loggers.js';
|
|
19
|
+
import { AgentStartEvent, AgentFinishEvent, RecoveryAttemptEvent, } from '../telemetry/types.js';
|
|
20
20
|
import { AgentTerminateMode } from './types.js';
|
|
21
21
|
const { mockSendMessageStream, mockExecuteToolCall } = vi.hoisted(() => ({
|
|
22
22
|
mockSendMessageStream: vi.fn(),
|
|
@@ -38,6 +38,7 @@ vi.mock('../utils/environmentContext.js');
|
|
|
38
38
|
vi.mock('../telemetry/loggers.js', () => ({
|
|
39
39
|
logAgentStart: vi.fn(),
|
|
40
40
|
logAgentFinish: vi.fn(),
|
|
41
|
+
logRecoveryAttempt: vi.fn(),
|
|
41
42
|
}));
|
|
42
43
|
vi.mock('../utils/promptIdContext.js', async (importOriginal) => {
|
|
43
44
|
const actual = await importOriginal();
|
|
@@ -55,6 +56,7 @@ const mockedGetDirectoryContextString = vi.mocked(getDirectoryContextString);
|
|
|
55
56
|
const mockedPromptIdContext = vi.mocked(promptIdContext);
|
|
56
57
|
const mockedLogAgentStart = vi.mocked(logAgentStart);
|
|
57
58
|
const mockedLogAgentFinish = vi.mocked(logAgentFinish);
|
|
59
|
+
const mockedLogRecoveryAttempt = vi.mocked(logRecoveryAttempt);
|
|
58
60
|
// Constants for testing
|
|
59
61
|
const TASK_COMPLETE_TOOL_NAME = 'complete_task';
|
|
60
62
|
const MOCK_TOOL_NOT_ALLOWED = new MockTool({ name: 'write_file_interactive' });
|
|
@@ -102,7 +104,7 @@ let parentToolRegistry;
|
|
|
102
104
|
/**
|
|
103
105
|
* Type-safe helper to create agent definitions for tests.
|
|
104
106
|
*/
|
|
105
|
-
const createTestDefinition = (tools = [
|
|
107
|
+
const createTestDefinition = (tools = [LS_TOOL_NAME], runConfigOverrides = {}, outputConfigMode = 'default', schema = z.string()) => {
|
|
106
108
|
let outputConfig;
|
|
107
109
|
if (outputConfigMode === 'default') {
|
|
108
110
|
outputConfig = {
|
|
@@ -144,7 +146,7 @@ describe('AgentExecutor', () => {
|
|
|
144
146
|
mockConfig = makeFakeConfig();
|
|
145
147
|
parentToolRegistry = new ToolRegistry(mockConfig);
|
|
146
148
|
parentToolRegistry.registerTool(new LSTool(mockConfig));
|
|
147
|
-
parentToolRegistry.registerTool(new
|
|
149
|
+
parentToolRegistry.registerTool(new MockTool({ name: READ_FILE_TOOL_NAME }));
|
|
148
150
|
parentToolRegistry.registerTool(MOCK_TOOL_NOT_ALLOWED);
|
|
149
151
|
vi.spyOn(mockConfig, 'getToolRegistry').mockResolvedValue(parentToolRegistry);
|
|
150
152
|
mockedGetDirectoryContextString.mockResolvedValue('Mocked Environment Context');
|
|
@@ -158,7 +160,7 @@ describe('AgentExecutor', () => {
|
|
|
158
160
|
});
|
|
159
161
|
describe('create (Initialization and Validation)', () => {
|
|
160
162
|
it('should create successfully with allowed tools', async () => {
|
|
161
|
-
const definition = createTestDefinition([
|
|
163
|
+
const definition = createTestDefinition([LS_TOOL_NAME]);
|
|
162
164
|
const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
|
|
163
165
|
expect(executor).toBeInstanceOf(AgentExecutor);
|
|
164
166
|
});
|
|
@@ -167,11 +169,14 @@ describe('AgentExecutor', () => {
|
|
|
167
169
|
await expect(AgentExecutor.create(definition, mockConfig, onActivity)).rejects.toThrow(/not on the allow-list for non-interactive execution/);
|
|
168
170
|
});
|
|
169
171
|
it('should create an isolated ToolRegistry for the agent', async () => {
|
|
170
|
-
const definition = createTestDefinition([
|
|
172
|
+
const definition = createTestDefinition([
|
|
173
|
+
LS_TOOL_NAME,
|
|
174
|
+
READ_FILE_TOOL_NAME,
|
|
175
|
+
]);
|
|
171
176
|
const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
|
|
172
177
|
const agentRegistry = executor['toolRegistry'];
|
|
173
178
|
expect(agentRegistry).not.toBe(parentToolRegistry);
|
|
174
|
-
expect(agentRegistry.getAllToolNames()).toEqual(expect.arrayContaining([
|
|
179
|
+
expect(agentRegistry.getAllToolNames()).toEqual(expect.arrayContaining([LS_TOOL_NAME, READ_FILE_TOOL_NAME]));
|
|
175
180
|
expect(agentRegistry.getAllToolNames()).toHaveLength(2);
|
|
176
181
|
expect(agentRegistry.getTool(MOCK_TOOL_NOT_ALLOWED.name)).toBeUndefined();
|
|
177
182
|
});
|
|
@@ -204,12 +209,12 @@ describe('AgentExecutor', () => {
|
|
|
204
209
|
const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
|
|
205
210
|
const inputs = { goal: 'Find files' };
|
|
206
211
|
// Turn 1: Model calls ls
|
|
207
|
-
mockModelResponse([{ name:
|
|
212
|
+
mockModelResponse([{ name: LS_TOOL_NAME, args: { path: '.' }, id: 'call1' }], 'T1: Listing');
|
|
208
213
|
mockExecuteToolCall.mockResolvedValueOnce({
|
|
209
214
|
status: 'success',
|
|
210
215
|
request: {
|
|
211
216
|
callId: 'call1',
|
|
212
|
-
name:
|
|
217
|
+
name: LS_TOOL_NAME,
|
|
213
218
|
args: { path: '.' },
|
|
214
219
|
isClientInitiated: false,
|
|
215
220
|
prompt_id: 'test-prompt',
|
|
@@ -222,7 +227,7 @@ describe('AgentExecutor', () => {
|
|
|
222
227
|
responseParts: [
|
|
223
228
|
{
|
|
224
229
|
functionResponse: {
|
|
225
|
-
name:
|
|
230
|
+
name: LS_TOOL_NAME,
|
|
226
231
|
response: { result: 'file1.txt' },
|
|
227
232
|
id: 'call1',
|
|
228
233
|
},
|
|
@@ -255,7 +260,7 @@ describe('AgentExecutor', () => {
|
|
|
255
260
|
const sentTools = firstToolGroup.functionDeclarations;
|
|
256
261
|
expect(sentTools).toBeDefined();
|
|
257
262
|
expect(sentTools).toEqual(expect.arrayContaining([
|
|
258
|
-
expect.objectContaining({ name:
|
|
263
|
+
expect.objectContaining({ name: LS_TOOL_NAME }),
|
|
259
264
|
expect.objectContaining({ name: TASK_COMPLETE_TOOL_NAME }),
|
|
260
265
|
]));
|
|
261
266
|
const completeToolDef = sentTools.find((t) => t.name === TASK_COMPLETE_TOOL_NAME);
|
|
@@ -281,7 +286,7 @@ describe('AgentExecutor', () => {
|
|
|
281
286
|
}),
|
|
282
287
|
expect.objectContaining({
|
|
283
288
|
type: 'TOOL_CALL_END',
|
|
284
|
-
data: { name:
|
|
289
|
+
data: { name: LS_TOOL_NAME, output: 'file1.txt' },
|
|
285
290
|
}),
|
|
286
291
|
expect.objectContaining({
|
|
287
292
|
type: 'TOOL_CALL_START',
|
|
@@ -300,16 +305,16 @@ describe('AgentExecutor', () => {
|
|
|
300
305
|
]));
|
|
301
306
|
});
|
|
302
307
|
it('should execute successfully when model calls complete_task without output (Happy Path No Output)', async () => {
|
|
303
|
-
const definition = createTestDefinition([
|
|
308
|
+
const definition = createTestDefinition([LS_TOOL_NAME], {}, 'none');
|
|
304
309
|
const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
|
|
305
310
|
mockModelResponse([
|
|
306
|
-
{ name:
|
|
311
|
+
{ name: LS_TOOL_NAME, args: { path: '.' }, id: 'call1' },
|
|
307
312
|
]);
|
|
308
313
|
mockExecuteToolCall.mockResolvedValueOnce({
|
|
309
314
|
status: 'success',
|
|
310
315
|
request: {
|
|
311
316
|
callId: 'call1',
|
|
312
|
-
name:
|
|
317
|
+
name: LS_TOOL_NAME,
|
|
313
318
|
args: { path: '.' },
|
|
314
319
|
isClientInitiated: false,
|
|
315
320
|
prompt_id: 'test-prompt',
|
|
@@ -322,7 +327,7 @@ describe('AgentExecutor', () => {
|
|
|
322
327
|
responseParts: [
|
|
323
328
|
{
|
|
324
329
|
functionResponse: {
|
|
325
|
-
name:
|
|
330
|
+
name: LS_TOOL_NAME,
|
|
326
331
|
response: {},
|
|
327
332
|
id: 'call1',
|
|
328
333
|
},
|
|
@@ -353,13 +358,13 @@ describe('AgentExecutor', () => {
|
|
|
353
358
|
const definition = createTestDefinition();
|
|
354
359
|
const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
|
|
355
360
|
mockModelResponse([
|
|
356
|
-
{ name:
|
|
361
|
+
{ name: LS_TOOL_NAME, args: { path: '.' }, id: 'call1' },
|
|
357
362
|
]);
|
|
358
363
|
mockExecuteToolCall.mockResolvedValueOnce({
|
|
359
364
|
status: 'success',
|
|
360
365
|
request: {
|
|
361
366
|
callId: 'call1',
|
|
362
|
-
name:
|
|
367
|
+
name: LS_TOOL_NAME,
|
|
363
368
|
args: { path: '.' },
|
|
364
369
|
isClientInitiated: false,
|
|
365
370
|
prompt_id: 'test-prompt',
|
|
@@ -372,7 +377,7 @@ describe('AgentExecutor', () => {
|
|
|
372
377
|
responseParts: [
|
|
373
378
|
{
|
|
374
379
|
functionResponse: {
|
|
375
|
-
name:
|
|
380
|
+
name: LS_TOOL_NAME,
|
|
376
381
|
response: {},
|
|
377
382
|
id: 'call1',
|
|
378
383
|
},
|
|
@@ -383,15 +388,18 @@ describe('AgentExecutor', () => {
|
|
|
383
388
|
contentLength: undefined,
|
|
384
389
|
},
|
|
385
390
|
});
|
|
391
|
+
// Turn 2 (protocol violation)
|
|
386
392
|
mockModelResponse([], 'I think I am done.');
|
|
393
|
+
// Turn 3 (recovery turn - also fails)
|
|
394
|
+
mockModelResponse([], 'I still give up.');
|
|
387
395
|
const output = await executor.run({ goal: 'Strict test' }, signal);
|
|
388
|
-
expect(mockSendMessageStream).toHaveBeenCalledTimes(
|
|
389
|
-
const expectedError = `Agent stopped calling tools but did not call '${TASK_COMPLETE_TOOL_NAME}'
|
|
390
|
-
expect(output.terminate_reason).toBe(AgentTerminateMode.
|
|
396
|
+
expect(mockSendMessageStream).toHaveBeenCalledTimes(3);
|
|
397
|
+
const expectedError = `Agent stopped calling tools but did not call '${TASK_COMPLETE_TOOL_NAME}'.`;
|
|
398
|
+
expect(output.terminate_reason).toBe(AgentTerminateMode.ERROR_NO_COMPLETE_TASK_CALL);
|
|
391
399
|
expect(output.result).toBe(expectedError);
|
|
392
400
|
// Telemetry check for error
|
|
393
401
|
expect(mockedLogAgentFinish).toHaveBeenCalledWith(mockConfig, expect.objectContaining({
|
|
394
|
-
terminate_reason: AgentTerminateMode.
|
|
402
|
+
terminate_reason: AgentTerminateMode.ERROR_NO_COMPLETE_TASK_CALL,
|
|
395
403
|
}));
|
|
396
404
|
expect(activities).toContainEqual(expect.objectContaining({
|
|
397
405
|
type: 'ERROR',
|
|
@@ -464,15 +472,15 @@ describe('AgentExecutor', () => {
|
|
|
464
472
|
expect(errors[0].data['error']).toContain('Task already marked complete in this turn');
|
|
465
473
|
});
|
|
466
474
|
it('should execute parallel tool calls and then complete', async () => {
|
|
467
|
-
const definition = createTestDefinition([
|
|
475
|
+
const definition = createTestDefinition([LS_TOOL_NAME]);
|
|
468
476
|
const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
|
|
469
477
|
const call1 = {
|
|
470
|
-
name:
|
|
478
|
+
name: LS_TOOL_NAME,
|
|
471
479
|
args: { path: '/a' },
|
|
472
480
|
id: 'c1',
|
|
473
481
|
};
|
|
474
482
|
const call2 = {
|
|
475
|
-
name:
|
|
483
|
+
name: LS_TOOL_NAME,
|
|
476
484
|
args: { path: '/b' },
|
|
477
485
|
id: 'c2',
|
|
478
486
|
};
|
|
@@ -543,13 +551,13 @@ describe('AgentExecutor', () => {
|
|
|
543
551
|
]));
|
|
544
552
|
});
|
|
545
553
|
it('SECURITY: should block unauthorized tools and provide explicit failure to model', async () => {
|
|
546
|
-
const definition = createTestDefinition([
|
|
554
|
+
const definition = createTestDefinition([LS_TOOL_NAME]);
|
|
547
555
|
const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
|
|
548
556
|
// Turn 1: Model tries to use a tool not in its config
|
|
549
557
|
const badCallId = 'bad_call_1';
|
|
550
558
|
mockModelResponse([
|
|
551
559
|
{
|
|
552
|
-
name:
|
|
560
|
+
name: READ_FILE_TOOL_NAME,
|
|
553
561
|
args: { path: 'secret.txt' },
|
|
554
562
|
id: badCallId,
|
|
555
563
|
},
|
|
@@ -578,7 +586,7 @@ describe('AgentExecutor', () => {
|
|
|
578
586
|
expect(parts[0]).toEqual(expect.objectContaining({
|
|
579
587
|
functionResponse: expect.objectContaining({
|
|
580
588
|
id: badCallId,
|
|
581
|
-
name:
|
|
589
|
+
name: READ_FILE_TOOL_NAME,
|
|
582
590
|
response: {
|
|
583
591
|
error: expect.stringContaining('Unauthorized tool call'),
|
|
584
592
|
},
|
|
@@ -589,19 +597,19 @@ describe('AgentExecutor', () => {
|
|
|
589
597
|
type: 'ERROR',
|
|
590
598
|
data: expect.objectContaining({
|
|
591
599
|
context: 'tool_call_unauthorized',
|
|
592
|
-
name:
|
|
600
|
+
name: READ_FILE_TOOL_NAME,
|
|
593
601
|
}),
|
|
594
602
|
}));
|
|
595
603
|
});
|
|
596
604
|
});
|
|
597
605
|
describe('run (Termination Conditions)', () => {
|
|
598
606
|
const mockWorkResponse = (id) => {
|
|
599
|
-
mockModelResponse([{ name:
|
|
607
|
+
mockModelResponse([{ name: LS_TOOL_NAME, args: { path: '.' }, id }]);
|
|
600
608
|
mockExecuteToolCall.mockResolvedValueOnce({
|
|
601
609
|
status: 'success',
|
|
602
610
|
request: {
|
|
603
611
|
callId: id,
|
|
604
|
-
name:
|
|
612
|
+
name: LS_TOOL_NAME,
|
|
605
613
|
args: { path: '.' },
|
|
606
614
|
isClientInitiated: false,
|
|
607
615
|
prompt_id: 'test-prompt',
|
|
@@ -612,7 +620,7 @@ describe('AgentExecutor', () => {
|
|
|
612
620
|
callId: id,
|
|
613
621
|
resultDisplay: 'ok',
|
|
614
622
|
responseParts: [
|
|
615
|
-
{ functionResponse: { name:
|
|
623
|
+
{ functionResponse: { name: LS_TOOL_NAME, response: {}, id } },
|
|
616
624
|
],
|
|
617
625
|
error: undefined,
|
|
618
626
|
errorType: undefined,
|
|
@@ -622,22 +630,66 @@ describe('AgentExecutor', () => {
|
|
|
622
630
|
};
|
|
623
631
|
it('should terminate when max_turns is reached', async () => {
|
|
624
632
|
const MAX = 2;
|
|
625
|
-
const definition = createTestDefinition([
|
|
633
|
+
const definition = createTestDefinition([LS_TOOL_NAME], {
|
|
626
634
|
max_turns: MAX,
|
|
627
635
|
});
|
|
628
636
|
const executor = await AgentExecutor.create(definition, mockConfig);
|
|
629
637
|
mockWorkResponse('t1');
|
|
630
638
|
mockWorkResponse('t2');
|
|
639
|
+
// Recovery turn
|
|
640
|
+
mockModelResponse([], 'I give up');
|
|
631
641
|
const output = await executor.run({ goal: 'Turns test' }, signal);
|
|
632
642
|
expect(output.terminate_reason).toBe(AgentTerminateMode.MAX_TURNS);
|
|
633
|
-
expect(mockSendMessageStream).toHaveBeenCalledTimes(MAX);
|
|
643
|
+
expect(mockSendMessageStream).toHaveBeenCalledTimes(MAX + 1);
|
|
644
|
+
});
|
|
645
|
+
it('should terminate with TIMEOUT if a model call takes too long', async () => {
|
|
646
|
+
const definition = createTestDefinition([LS_TOOL_NAME], {
|
|
647
|
+
max_time_minutes: 0.5, // 30 seconds
|
|
648
|
+
});
|
|
649
|
+
const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
|
|
650
|
+
// Mock a model call that is interruptible by an abort signal.
|
|
651
|
+
mockSendMessageStream.mockImplementationOnce(async (_model, params) => {
|
|
652
|
+
const signal = params?.config?.abortSignal;
|
|
653
|
+
// eslint-disable-next-line require-yield
|
|
654
|
+
return (async function* () {
|
|
655
|
+
await new Promise((resolve) => {
|
|
656
|
+
// This promise resolves when aborted, ending the generator.
|
|
657
|
+
signal?.addEventListener('abort', () => {
|
|
658
|
+
resolve();
|
|
659
|
+
});
|
|
660
|
+
});
|
|
661
|
+
})();
|
|
662
|
+
});
|
|
663
|
+
// Recovery turn
|
|
664
|
+
mockModelResponse([], 'I give up');
|
|
665
|
+
const runPromise = executor.run({ goal: 'Timeout test' }, signal);
|
|
666
|
+
// Advance time past the timeout to trigger the abort.
|
|
667
|
+
await vi.advanceTimersByTimeAsync(31 * 1000);
|
|
668
|
+
const output = await runPromise;
|
|
669
|
+
expect(output.terminate_reason).toBe(AgentTerminateMode.TIMEOUT);
|
|
670
|
+
expect(output.result).toContain('Agent timed out after 0.5 minutes.');
|
|
671
|
+
expect(mockSendMessageStream).toHaveBeenCalledTimes(2);
|
|
672
|
+
// Verify activity stream reported the timeout
|
|
673
|
+
expect(activities).toContainEqual(expect.objectContaining({
|
|
674
|
+
type: 'ERROR',
|
|
675
|
+
data: expect.objectContaining({
|
|
676
|
+
context: 'timeout',
|
|
677
|
+
error: 'Agent timed out after 0.5 minutes.',
|
|
678
|
+
}),
|
|
679
|
+
}));
|
|
680
|
+
// Verify telemetry
|
|
681
|
+
expect(mockedLogAgentFinish).toHaveBeenCalledWith(mockConfig, expect.objectContaining({
|
|
682
|
+
terminate_reason: AgentTerminateMode.TIMEOUT,
|
|
683
|
+
}));
|
|
634
684
|
});
|
|
635
|
-
it('should terminate if
|
|
636
|
-
const definition = createTestDefinition([
|
|
685
|
+
it('should terminate with TIMEOUT if a tool call takes too long', async () => {
|
|
686
|
+
const definition = createTestDefinition([LS_TOOL_NAME], {
|
|
637
687
|
max_time_minutes: 1,
|
|
638
688
|
});
|
|
639
689
|
const executor = await AgentExecutor.create(definition, mockConfig);
|
|
640
|
-
mockModelResponse([
|
|
690
|
+
mockModelResponse([
|
|
691
|
+
{ name: LS_TOOL_NAME, args: { path: '.' }, id: 't1' },
|
|
692
|
+
]);
|
|
641
693
|
// Long running tool
|
|
642
694
|
mockExecuteToolCall.mockImplementationOnce(async (_ctx, reqInfo) => {
|
|
643
695
|
await vi.advanceTimersByTimeAsync(61 * 1000);
|
|
@@ -656,9 +708,11 @@ describe('AgentExecutor', () => {
|
|
|
656
708
|
},
|
|
657
709
|
};
|
|
658
710
|
});
|
|
711
|
+
// Recovery turn
|
|
712
|
+
mockModelResponse([], 'I give up');
|
|
659
713
|
const output = await executor.run({ goal: 'Timeout test' }, signal);
|
|
660
714
|
expect(output.terminate_reason).toBe(AgentTerminateMode.TIMEOUT);
|
|
661
|
-
expect(mockSendMessageStream).toHaveBeenCalledTimes(
|
|
715
|
+
expect(mockSendMessageStream).toHaveBeenCalledTimes(2);
|
|
662
716
|
});
|
|
663
717
|
it('should terminate when AbortSignal is triggered', async () => {
|
|
664
718
|
const definition = createTestDefinition();
|
|
@@ -676,5 +730,282 @@ describe('AgentExecutor', () => {
|
|
|
676
730
|
expect(output.terminate_reason).toBe(AgentTerminateMode.ABORTED);
|
|
677
731
|
});
|
|
678
732
|
});
|
|
733
|
+
describe('run (Recovery Turns)', () => {
|
|
734
|
+
const mockWorkResponse = (id) => {
|
|
735
|
+
mockModelResponse([{ name: LS_TOOL_NAME, args: { path: '.' }, id }]);
|
|
736
|
+
mockExecuteToolCall.mockResolvedValueOnce({
|
|
737
|
+
status: 'success',
|
|
738
|
+
request: {
|
|
739
|
+
callId: id,
|
|
740
|
+
name: LS_TOOL_NAME,
|
|
741
|
+
args: { path: '.' },
|
|
742
|
+
isClientInitiated: false,
|
|
743
|
+
prompt_id: 'test-prompt',
|
|
744
|
+
},
|
|
745
|
+
tool: {},
|
|
746
|
+
invocation: {},
|
|
747
|
+
response: {
|
|
748
|
+
callId: id,
|
|
749
|
+
resultDisplay: 'ok',
|
|
750
|
+
responseParts: [
|
|
751
|
+
{ functionResponse: { name: LS_TOOL_NAME, response: {}, id } },
|
|
752
|
+
],
|
|
753
|
+
error: undefined,
|
|
754
|
+
errorType: undefined,
|
|
755
|
+
contentLength: undefined,
|
|
756
|
+
},
|
|
757
|
+
});
|
|
758
|
+
};
|
|
759
|
+
it('should recover successfully if complete_task is called during the grace turn after MAX_TURNS', async () => {
|
|
760
|
+
const MAX = 1;
|
|
761
|
+
const definition = createTestDefinition([LS_TOOL_NAME], {
|
|
762
|
+
max_turns: MAX,
|
|
763
|
+
});
|
|
764
|
+
const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
|
|
765
|
+
// Turn 1 (hits max_turns)
|
|
766
|
+
mockWorkResponse('t1');
|
|
767
|
+
// Recovery Turn (succeeds)
|
|
768
|
+
mockModelResponse([
|
|
769
|
+
{
|
|
770
|
+
name: TASK_COMPLETE_TOOL_NAME,
|
|
771
|
+
args: { finalResult: 'Recovered!' },
|
|
772
|
+
id: 't2',
|
|
773
|
+
},
|
|
774
|
+
], 'Recovering from max turns');
|
|
775
|
+
const output = await executor.run({ goal: 'Turns recovery' }, signal);
|
|
776
|
+
expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
|
|
777
|
+
expect(output.result).toBe('Recovered!');
|
|
778
|
+
expect(mockSendMessageStream).toHaveBeenCalledTimes(MAX + 1); // 1 regular + 1 recovery
|
|
779
|
+
expect(activities).toContainEqual(expect.objectContaining({
|
|
780
|
+
type: 'THOUGHT_CHUNK',
|
|
781
|
+
data: {
|
|
782
|
+
text: 'Execution limit reached (MAX_TURNS). Attempting one final recovery turn with a grace period.',
|
|
783
|
+
},
|
|
784
|
+
}));
|
|
785
|
+
expect(activities).toContainEqual(expect.objectContaining({
|
|
786
|
+
type: 'THOUGHT_CHUNK',
|
|
787
|
+
data: { text: 'Graceful recovery succeeded.' },
|
|
788
|
+
}));
|
|
789
|
+
});
|
|
790
|
+
it('should fail if complete_task is NOT called during the grace turn after MAX_TURNS', async () => {
|
|
791
|
+
const MAX = 1;
|
|
792
|
+
const definition = createTestDefinition([LS_TOOL_NAME], {
|
|
793
|
+
max_turns: MAX,
|
|
794
|
+
});
|
|
795
|
+
const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
|
|
796
|
+
// Turn 1 (hits max_turns)
|
|
797
|
+
mockWorkResponse('t1');
|
|
798
|
+
// Recovery Turn (fails by calling no tools)
|
|
799
|
+
mockModelResponse([], 'I give up again.');
|
|
800
|
+
const output = await executor.run({ goal: 'Turns recovery fail' }, signal);
|
|
801
|
+
expect(output.terminate_reason).toBe(AgentTerminateMode.MAX_TURNS);
|
|
802
|
+
expect(output.result).toContain('Agent reached max turns limit');
|
|
803
|
+
expect(mockSendMessageStream).toHaveBeenCalledTimes(MAX + 1);
|
|
804
|
+
expect(activities).toContainEqual(expect.objectContaining({
|
|
805
|
+
type: 'ERROR',
|
|
806
|
+
data: expect.objectContaining({
|
|
807
|
+
context: 'recovery_turn',
|
|
808
|
+
error: 'Graceful recovery attempt failed. Reason: stop',
|
|
809
|
+
}),
|
|
810
|
+
}));
|
|
811
|
+
});
|
|
812
|
+
it('should recover successfully from a protocol violation (no complete_task)', async () => {
|
|
813
|
+
const definition = createTestDefinition();
|
|
814
|
+
const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
|
|
815
|
+
// Turn 1: Normal work
|
|
816
|
+
mockWorkResponse('t1');
|
|
817
|
+
// Turn 2: Protocol violation (no tool calls)
|
|
818
|
+
mockModelResponse([], 'I think I am done, but I forgot the right tool.');
|
|
819
|
+
// Turn 3: Recovery turn (succeeds)
|
|
820
|
+
mockModelResponse([
|
|
821
|
+
{
|
|
822
|
+
name: TASK_COMPLETE_TOOL_NAME,
|
|
823
|
+
args: { finalResult: 'Recovered from violation!' },
|
|
824
|
+
id: 't3',
|
|
825
|
+
},
|
|
826
|
+
], 'My mistake, here is the completion.');
|
|
827
|
+
const output = await executor.run({ goal: 'Violation recovery' }, signal);
|
|
828
|
+
expect(mockSendMessageStream).toHaveBeenCalledTimes(3);
|
|
829
|
+
expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
|
|
830
|
+
expect(output.result).toBe('Recovered from violation!');
|
|
831
|
+
expect(activities).toContainEqual(expect.objectContaining({
|
|
832
|
+
type: 'THOUGHT_CHUNK',
|
|
833
|
+
data: {
|
|
834
|
+
text: 'Execution limit reached (ERROR_NO_COMPLETE_TASK_CALL). Attempting one final recovery turn with a grace period.',
|
|
835
|
+
},
|
|
836
|
+
}));
|
|
837
|
+
});
|
|
838
|
+
it('should fail recovery from a protocol violation if it violates again', async () => {
|
|
839
|
+
const definition = createTestDefinition();
|
|
840
|
+
const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
|
|
841
|
+
// Turn 1: Normal work
|
|
842
|
+
mockWorkResponse('t1');
|
|
843
|
+
// Turn 2: Protocol violation (no tool calls)
|
|
844
|
+
mockModelResponse([], 'I think I am done, but I forgot the right tool.');
|
|
845
|
+
// Turn 3: Recovery turn (fails again)
|
|
846
|
+
mockModelResponse([], 'I still dont know what to do.');
|
|
847
|
+
const output = await executor.run({ goal: 'Violation recovery fail' }, signal);
|
|
848
|
+
expect(mockSendMessageStream).toHaveBeenCalledTimes(3);
|
|
849
|
+
expect(output.terminate_reason).toBe(AgentTerminateMode.ERROR_NO_COMPLETE_TASK_CALL);
|
|
850
|
+
expect(output.result).toContain(`Agent stopped calling tools but did not call '${TASK_COMPLETE_TOOL_NAME}'`);
|
|
851
|
+
expect(activities).toContainEqual(expect.objectContaining({
|
|
852
|
+
type: 'ERROR',
|
|
853
|
+
data: expect.objectContaining({
|
|
854
|
+
context: 'recovery_turn',
|
|
855
|
+
error: 'Graceful recovery attempt failed. Reason: stop',
|
|
856
|
+
}),
|
|
857
|
+
}));
|
|
858
|
+
});
|
|
859
|
+
it('should recover successfully from a TIMEOUT', async () => {
|
|
860
|
+
const definition = createTestDefinition([LS_TOOL_NAME], {
|
|
861
|
+
max_time_minutes: 0.5, // 30 seconds
|
|
862
|
+
});
|
|
863
|
+
const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
|
|
864
|
+
// Mock a model call that gets interrupted by the timeout.
|
|
865
|
+
mockSendMessageStream.mockImplementationOnce(async (_model, params) => {
|
|
866
|
+
const signal = params?.config?.abortSignal;
|
|
867
|
+
// eslint-disable-next-line require-yield
|
|
868
|
+
return (async function* () {
|
|
869
|
+
// This promise never resolves, it waits for abort.
|
|
870
|
+
await new Promise((resolve) => {
|
|
871
|
+
signal?.addEventListener('abort', () => resolve());
|
|
872
|
+
});
|
|
873
|
+
})();
|
|
874
|
+
});
|
|
875
|
+
// Recovery turn (succeeds)
|
|
876
|
+
mockModelResponse([
|
|
877
|
+
{
|
|
878
|
+
name: TASK_COMPLETE_TOOL_NAME,
|
|
879
|
+
args: { finalResult: 'Recovered from timeout!' },
|
|
880
|
+
id: 't2',
|
|
881
|
+
},
|
|
882
|
+
], 'Apologies for the delay, finishing up.');
|
|
883
|
+
const runPromise = executor.run({ goal: 'Timeout recovery' }, signal);
|
|
884
|
+
// Advance time past the timeout to trigger the abort and recovery.
|
|
885
|
+
await vi.advanceTimersByTimeAsync(31 * 1000);
|
|
886
|
+
const output = await runPromise;
|
|
887
|
+
expect(mockSendMessageStream).toHaveBeenCalledTimes(2); // 1 failed + 1 recovery
|
|
888
|
+
expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
|
|
889
|
+
expect(output.result).toBe('Recovered from timeout!');
|
|
890
|
+
expect(activities).toContainEqual(expect.objectContaining({
|
|
891
|
+
type: 'THOUGHT_CHUNK',
|
|
892
|
+
data: {
|
|
893
|
+
text: 'Execution limit reached (TIMEOUT). Attempting one final recovery turn with a grace period.',
|
|
894
|
+
},
|
|
895
|
+
}));
|
|
896
|
+
});
|
|
897
|
+
it('should fail recovery from a TIMEOUT if the grace period also times out', async () => {
|
|
898
|
+
const definition = createTestDefinition([LS_TOOL_NAME], {
|
|
899
|
+
max_time_minutes: 0.5, // 30 seconds
|
|
900
|
+
});
|
|
901
|
+
const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
|
|
902
|
+
mockSendMessageStream.mockImplementationOnce(async (_model, params) => {
|
|
903
|
+
const signal = params?.config?.abortSignal;
|
|
904
|
+
// eslint-disable-next-line require-yield
|
|
905
|
+
return (async function* () {
|
|
906
|
+
await new Promise((resolve) => signal?.addEventListener('abort', () => resolve()));
|
|
907
|
+
})();
|
|
908
|
+
});
|
|
909
|
+
// Mock the recovery call to also be long-running
|
|
910
|
+
mockSendMessageStream.mockImplementationOnce(async (_model, params) => {
|
|
911
|
+
const signal = params?.config?.abortSignal;
|
|
912
|
+
// eslint-disable-next-line require-yield
|
|
913
|
+
return (async function* () {
|
|
914
|
+
await new Promise((resolve) => signal?.addEventListener('abort', () => resolve()));
|
|
915
|
+
})();
|
|
916
|
+
});
|
|
917
|
+
const runPromise = executor.run({ goal: 'Timeout recovery fail' }, signal);
|
|
918
|
+
// 1. Trigger the main timeout
|
|
919
|
+
await vi.advanceTimersByTimeAsync(31 * 1000);
|
|
920
|
+
// 2. Let microtasks run (start recovery turn)
|
|
921
|
+
await vi.advanceTimersByTimeAsync(1);
|
|
922
|
+
// 3. Trigger the grace period timeout (60s)
|
|
923
|
+
await vi.advanceTimersByTimeAsync(61 * 1000);
|
|
924
|
+
const output = await runPromise;
|
|
925
|
+
expect(mockSendMessageStream).toHaveBeenCalledTimes(2);
|
|
926
|
+
expect(output.terminate_reason).toBe(AgentTerminateMode.TIMEOUT);
|
|
927
|
+
expect(output.result).toContain('Agent timed out after 0.5 minutes.');
|
|
928
|
+
expect(activities).toContainEqual(expect.objectContaining({
|
|
929
|
+
type: 'ERROR',
|
|
930
|
+
data: expect.objectContaining({
|
|
931
|
+
context: 'recovery_turn',
|
|
932
|
+
error: 'Graceful recovery attempt failed. Reason: stop',
|
|
933
|
+
}),
|
|
934
|
+
}));
|
|
935
|
+
});
|
|
936
|
+
});
|
|
937
|
+
describe('Telemetry and Logging', () => {
|
|
938
|
+
const mockWorkResponse = (id) => {
|
|
939
|
+
mockModelResponse([{ name: LS_TOOL_NAME, args: { path: '.' }, id }]);
|
|
940
|
+
mockExecuteToolCall.mockResolvedValueOnce({
|
|
941
|
+
status: 'success',
|
|
942
|
+
request: {
|
|
943
|
+
callId: id,
|
|
944
|
+
name: LS_TOOL_NAME,
|
|
945
|
+
args: { path: '.' },
|
|
946
|
+
isClientInitiated: false,
|
|
947
|
+
prompt_id: 'test-prompt',
|
|
948
|
+
},
|
|
949
|
+
tool: {},
|
|
950
|
+
invocation: {},
|
|
951
|
+
response: {
|
|
952
|
+
callId: id,
|
|
953
|
+
resultDisplay: 'ok',
|
|
954
|
+
responseParts: [
|
|
955
|
+
{ functionResponse: { name: LS_TOOL_NAME, response: {}, id } },
|
|
956
|
+
],
|
|
957
|
+
error: undefined,
|
|
958
|
+
errorType: undefined,
|
|
959
|
+
contentLength: undefined,
|
|
960
|
+
},
|
|
961
|
+
});
|
|
962
|
+
};
|
|
963
|
+
beforeEach(() => {
|
|
964
|
+
mockedLogRecoveryAttempt.mockClear();
|
|
965
|
+
});
|
|
966
|
+
it('should log a RecoveryAttemptEvent when a recoverable error occurs and recovery fails', async () => {
|
|
967
|
+
const MAX = 1;
|
|
968
|
+
const definition = createTestDefinition([LS_TOOL_NAME], {
|
|
969
|
+
max_turns: MAX,
|
|
970
|
+
});
|
|
971
|
+
const executor = await AgentExecutor.create(definition, mockConfig);
|
|
972
|
+
// Turn 1 (hits max_turns)
|
|
973
|
+
mockWorkResponse('t1');
|
|
974
|
+
// Recovery Turn (fails by calling no tools)
|
|
975
|
+
mockModelResponse([], 'I give up again.');
|
|
976
|
+
await executor.run({ goal: 'Turns recovery fail' }, signal);
|
|
977
|
+
expect(mockedLogRecoveryAttempt).toHaveBeenCalledTimes(1);
|
|
978
|
+
const recoveryEvent = mockedLogRecoveryAttempt.mock.calls[0][1];
|
|
979
|
+
expect(recoveryEvent).toBeInstanceOf(RecoveryAttemptEvent);
|
|
980
|
+
expect(recoveryEvent.agent_name).toBe(definition.name);
|
|
981
|
+
expect(recoveryEvent.reason).toBe(AgentTerminateMode.MAX_TURNS);
|
|
982
|
+
expect(recoveryEvent.success).toBe(false);
|
|
983
|
+
expect(recoveryEvent.turn_count).toBe(1);
|
|
984
|
+
expect(recoveryEvent.duration_ms).toBeGreaterThanOrEqual(0);
|
|
985
|
+
});
|
|
986
|
+
it('should log a successful RecoveryAttemptEvent when recovery succeeds', async () => {
|
|
987
|
+
const MAX = 1;
|
|
988
|
+
const definition = createTestDefinition([LS_TOOL_NAME], {
|
|
989
|
+
max_turns: MAX,
|
|
990
|
+
});
|
|
991
|
+
const executor = await AgentExecutor.create(definition, mockConfig);
|
|
992
|
+
// Turn 1 (hits max_turns)
|
|
993
|
+
mockWorkResponse('t1');
|
|
994
|
+
// Recovery Turn (succeeds)
|
|
995
|
+
mockModelResponse([
|
|
996
|
+
{
|
|
997
|
+
name: TASK_COMPLETE_TOOL_NAME,
|
|
998
|
+
args: { finalResult: 'Recovered!' },
|
|
999
|
+
id: 't2',
|
|
1000
|
+
},
|
|
1001
|
+
], 'Recovering from max turns');
|
|
1002
|
+
await executor.run({ goal: 'Turns recovery success' }, signal);
|
|
1003
|
+
expect(mockedLogRecoveryAttempt).toHaveBeenCalledTimes(1);
|
|
1004
|
+
const recoveryEvent = mockedLogRecoveryAttempt.mock.calls[0][1];
|
|
1005
|
+
expect(recoveryEvent).toBeInstanceOf(RecoveryAttemptEvent);
|
|
1006
|
+
expect(recoveryEvent.success).toBe(true);
|
|
1007
|
+
expect(recoveryEvent.reason).toBe(AgentTerminateMode.MAX_TURNS);
|
|
1008
|
+
});
|
|
1009
|
+
});
|
|
679
1010
|
});
|
|
680
1011
|
//# sourceMappingURL=executor.test.js.map
|