@codemieai/code 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +357 -719
- package/bin/codemie-claude.js +145 -0
- package/bin/codemie-code.js +128 -15
- package/bin/codemie-codex.js +137 -0
- package/bin/codemie.js +1 -1
- package/dist/agents/adapters/claude-code.d.ts +7 -2
- package/dist/agents/adapters/claude-code.d.ts.map +1 -1
- package/dist/agents/adapters/claude-code.js +94 -58
- package/dist/agents/adapters/claude-code.js.map +1 -1
- package/dist/agents/adapters/codemie-code.d.ts +11 -2
- package/dist/agents/adapters/codemie-code.d.ts.map +1 -1
- package/dist/agents/adapters/codemie-code.js +93 -25
- package/dist/agents/adapters/codemie-code.js.map +1 -1
- package/dist/agents/adapters/codex.d.ts +7 -2
- package/dist/agents/adapters/codex.d.ts.map +1 -1
- package/dist/agents/adapters/codex.js +104 -39
- package/dist/agents/adapters/codex.js.map +1 -1
- package/dist/agents/codemie-code/agent.d.ts +89 -0
- package/dist/agents/codemie-code/agent.d.ts.map +1 -0
- package/dist/agents/codemie-code/agent.js +689 -0
- package/dist/agents/codemie-code/agent.js.map +1 -0
- package/dist/agents/codemie-code/config.d.ts +40 -0
- package/dist/agents/codemie-code/config.d.ts.map +1 -0
- package/dist/agents/codemie-code/config.js +278 -0
- package/dist/agents/codemie-code/config.js.map +1 -0
- package/dist/agents/codemie-code/filters.d.ts +91 -0
- package/dist/agents/codemie-code/filters.d.ts.map +1 -0
- package/dist/agents/codemie-code/filters.js +328 -0
- package/dist/agents/codemie-code/filters.js.map +1 -0
- package/dist/agents/codemie-code/index.d.ts +92 -0
- package/dist/agents/codemie-code/index.d.ts.map +1 -0
- package/dist/agents/codemie-code/index.js +327 -0
- package/dist/agents/codemie-code/index.js.map +1 -0
- package/dist/agents/codemie-code/modes/contextAwarePlanning.d.ts +87 -0
- package/dist/agents/codemie-code/modes/contextAwarePlanning.d.ts.map +1 -0
- package/dist/agents/codemie-code/modes/contextAwarePlanning.js +957 -0
- package/dist/agents/codemie-code/modes/contextAwarePlanning.js.map +1 -0
- package/dist/agents/codemie-code/modes/planMode.d.ts +116 -0
- package/dist/agents/codemie-code/modes/planMode.d.ts.map +1 -0
- package/dist/agents/codemie-code/modes/planMode.js +537 -0
- package/dist/agents/codemie-code/modes/planMode.js.map +1 -0
- package/dist/agents/codemie-code/prompts.d.ts +40 -0
- package/dist/agents/codemie-code/prompts.d.ts.map +1 -0
- package/dist/agents/codemie-code/prompts.js +160 -0
- package/dist/agents/codemie-code/prompts.js.map +1 -0
- package/dist/agents/codemie-code/storage/todoStorage.d.ts +78 -0
- package/dist/agents/codemie-code/storage/todoStorage.d.ts.map +1 -0
- package/dist/agents/codemie-code/storage/todoStorage.js +225 -0
- package/dist/agents/codemie-code/storage/todoStorage.js.map +1 -0
- package/dist/agents/codemie-code/tokenUtils.d.ts +108 -0
- package/dist/agents/codemie-code/tokenUtils.d.ts.map +1 -0
- package/dist/agents/codemie-code/tokenUtils.js +220 -0
- package/dist/agents/codemie-code/tokenUtils.js.map +1 -0
- package/dist/agents/codemie-code/toolMetadata.d.ts +15 -0
- package/dist/agents/codemie-code/toolMetadata.d.ts.map +1 -0
- package/dist/agents/codemie-code/toolMetadata.js +315 -0
- package/dist/agents/codemie-code/toolMetadata.js.map +1 -0
- package/dist/agents/codemie-code/tools/index.d.ts +45 -0
- package/dist/agents/codemie-code/tools/index.d.ts.map +1 -0
- package/dist/agents/codemie-code/tools/index.js +407 -0
- package/dist/agents/codemie-code/tools/index.js.map +1 -0
- package/dist/agents/codemie-code/tools/planning.d.ts +53 -0
- package/dist/agents/codemie-code/tools/planning.d.ts.map +1 -0
- package/dist/agents/codemie-code/tools/planning.js +224 -0
- package/dist/agents/codemie-code/tools/planning.js.map +1 -0
- package/dist/agents/codemie-code/types.d.ts +418 -0
- package/dist/agents/codemie-code/types.d.ts.map +1 -0
- package/dist/agents/codemie-code/types.js +35 -0
- package/dist/agents/codemie-code/types.js.map +1 -0
- package/dist/agents/codemie-code/ui/progressTracker.d.ts +125 -0
- package/dist/agents/codemie-code/ui/progressTracker.d.ts.map +1 -0
- package/dist/agents/codemie-code/ui/progressTracker.js +343 -0
- package/dist/agents/codemie-code/ui/progressTracker.js.map +1 -0
- package/dist/agents/codemie-code/ui/todoPanel.d.ts +112 -0
- package/dist/agents/codemie-code/ui/todoPanel.d.ts.map +1 -0
- package/dist/agents/codemie-code/ui/todoPanel.js +318 -0
- package/dist/agents/codemie-code/ui/todoPanel.js.map +1 -0
- package/dist/agents/codemie-code/ui.d.ts +179 -0
- package/dist/agents/codemie-code/ui.d.ts.map +1 -0
- package/dist/agents/codemie-code/ui.js +1408 -0
- package/dist/agents/codemie-code/ui.js.map +1 -0
- package/dist/agents/codemie-code/utils/progressionEnforcer.d.ts +87 -0
- package/dist/agents/codemie-code/utils/progressionEnforcer.d.ts.map +1 -0
- package/dist/agents/codemie-code/utils/progressionEnforcer.js +293 -0
- package/dist/agents/codemie-code/utils/progressionEnforcer.js.map +1 -0
- package/dist/agents/codemie-code/utils/todoParser.d.ts +41 -0
- package/dist/agents/codemie-code/utils/todoParser.d.ts.map +1 -0
- package/dist/agents/codemie-code/utils/todoParser.js +305 -0
- package/dist/agents/codemie-code/utils/todoParser.js.map +1 -0
- package/dist/agents/codemie-code/utils/todoValidator.d.ts +65 -0
- package/dist/agents/codemie-code/utils/todoValidator.d.ts.map +1 -0
- package/dist/agents/codemie-code/utils/todoValidator.js +249 -0
- package/dist/agents/codemie-code/utils/todoValidator.js.map +1 -0
- package/dist/agents/codemie-code/validators/planValidator.d.ts +94 -0
- package/dist/agents/codemie-code/validators/planValidator.d.ts.map +1 -0
- package/dist/agents/codemie-code/validators/planValidator.js +281 -0
- package/dist/agents/codemie-code/validators/planValidator.js.map +1 -0
- package/dist/agents/registry.d.ts +1 -1
- package/dist/agents/registry.d.ts.map +1 -1
- package/dist/agents/registry.js +11 -15
- package/dist/agents/registry.js.map +1 -1
- package/dist/cli/commands/auth.d.ts +3 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +170 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/config.d.ts +3 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +350 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +308 -71
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/env.d.ts +3 -0
- package/dist/cli/commands/env.d.ts.map +1 -0
- package/dist/cli/commands/env.js +19 -0
- package/dist/cli/commands/env.js.map +1 -0
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +28 -33
- package/dist/cli/commands/install.js.map +1 -1
- package/dist/cli/commands/list.js +18 -24
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +297 -31
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/setup.d.ts +3 -0
- package/dist/cli/commands/setup.d.ts.map +1 -0
- package/dist/cli/commands/setup.js +523 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/tools.d.ts +6 -0
- package/dist/cli/commands/tools.d.ts.map +1 -0
- package/dist/cli/commands/tools.js +244 -0
- package/dist/cli/commands/tools.js.map +1 -0
- package/dist/cli/commands/uninstall.js +24 -30
- package/dist/cli/commands/uninstall.js.map +1 -1
- package/dist/cli/commands/version.d.ts.map +1 -1
- package/dist/cli/commands/version.js +11 -16
- package/dist/cli/commands/version.js.map +1 -1
- package/dist/cli/commands/workflow.d.ts +6 -0
- package/dist/cli/commands/workflow.d.ts.map +1 -0
- package/dist/cli/commands/workflow.js +424 -0
- package/dist/cli/commands/workflow.js.map +1 -0
- package/dist/cli/index.js +85 -35
- package/dist/cli/index.js.map +1 -1
- package/dist/clients/adapters/github.d.ts +17 -0
- package/dist/clients/adapters/github.d.ts.map +1 -0
- package/dist/clients/adapters/github.js +150 -0
- package/dist/clients/adapters/github.js.map +1 -0
- package/dist/clients/adapters/gitlab.d.ts +17 -0
- package/dist/clients/adapters/gitlab.d.ts.map +1 -0
- package/dist/clients/adapters/gitlab.js +147 -0
- package/dist/clients/adapters/gitlab.js.map +1 -0
- package/dist/clients/registry.d.ts +20 -0
- package/dist/clients/registry.d.ts.map +1 -0
- package/dist/clients/registry.js +27 -0
- package/dist/clients/registry.js.map +1 -0
- package/dist/env/manager.js +9 -46
- package/dist/env/manager.js.map +1 -1
- package/dist/index.d.ts +6 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -43
- package/dist/index.js.map +1 -1
- package/dist/tools/detector.d.ts +33 -0
- package/dist/tools/detector.d.ts.map +1 -0
- package/dist/tools/detector.js +145 -0
- package/dist/tools/detector.js.map +1 -0
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +8 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/manager.d.ts +21 -0
- package/dist/tools/manager.d.ts.map +1 -0
- package/dist/tools/manager.js +104 -0
- package/dist/tools/manager.js.map +1 -0
- package/dist/tools/registry.d.ts +8 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +36 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +41 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +5 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/types/sso.d.ts +42 -0
- package/dist/types/sso.d.ts.map +1 -0
- package/dist/types/sso.js +2 -0
- package/dist/types/sso.js.map +1 -0
- package/dist/utils/agent-compatibility.d.ts +32 -0
- package/dist/utils/agent-compatibility.d.ts.map +1 -0
- package/dist/utils/agent-compatibility.js +140 -0
- package/dist/utils/agent-compatibility.js.map +1 -0
- package/dist/utils/async-tips.d.ts.map +1 -1
- package/dist/utils/async-tips.js +16 -55
- package/dist/utils/async-tips.js.map +1 -1
- package/dist/utils/clipboard.d.ts +16 -0
- package/dist/utils/clipboard.d.ts.map +1 -0
- package/dist/utils/clipboard.js +179 -0
- package/dist/utils/clipboard.js.map +1 -0
- package/dist/utils/codemie-integration-validator.d.ts +17 -0
- package/dist/utils/codemie-integration-validator.d.ts.map +1 -0
- package/dist/utils/codemie-integration-validator.js +105 -0
- package/dist/utils/codemie-integration-validator.js.map +1 -0
- package/dist/utils/codemie-model-fetcher.d.ts +11 -0
- package/dist/utils/codemie-model-fetcher.d.ts.map +1 -0
- package/dist/utils/codemie-model-fetcher.js +242 -0
- package/dist/utils/codemie-model-fetcher.js.map +1 -0
- package/dist/utils/config-loader.d.ts +118 -0
- package/dist/utils/config-loader.d.ts.map +1 -0
- package/dist/utils/config-loader.js +397 -0
- package/dist/utils/config-loader.js.map +1 -0
- package/dist/utils/credential-store.d.ts +16 -0
- package/dist/utils/credential-store.d.ts.map +1 -0
- package/dist/utils/credential-store.js +109 -0
- package/dist/utils/credential-store.js.map +1 -0
- package/dist/utils/dirname.d.ts +7 -0
- package/dist/utils/dirname.d.ts.map +1 -0
- package/dist/utils/dirname.js +11 -0
- package/dist/utils/dirname.js.map +1 -0
- package/dist/utils/errors.js +7 -17
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/exec.js +3 -6
- package/dist/utils/exec.js.map +1 -1
- package/dist/utils/first-time.d.ts +34 -0
- package/dist/utils/first-time.d.ts.map +1 -0
- package/dist/utils/first-time.js +226 -0
- package/dist/utils/first-time.js.map +1 -0
- package/dist/utils/health-checker.d.ts +20 -0
- package/dist/utils/health-checker.d.ts.map +1 -0
- package/dist/utils/health-checker.js +172 -0
- package/dist/utils/health-checker.js.map +1 -0
- package/dist/utils/logger.js +12 -18
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/model-fetcher.d.ts +21 -0
- package/dist/utils/model-fetcher.d.ts.map +1 -0
- package/dist/utils/model-fetcher.js +150 -0
- package/dist/utils/model-fetcher.js.map +1 -0
- package/dist/utils/sso-auth.d.ts +15 -0
- package/dist/utils/sso-auth.d.ts.map +1 -0
- package/dist/utils/sso-auth.js +207 -0
- package/dist/utils/sso-auth.js.map +1 -0
- package/dist/utils/sso-gateway.d.ts +47 -0
- package/dist/utils/sso-gateway.d.ts.map +1 -0
- package/dist/utils/sso-gateway.js +298 -0
- package/dist/utils/sso-gateway.js.map +1 -0
- package/dist/utils/tips.d.ts.map +1 -1
- package/dist/utils/tips.js +13 -52
- package/dist/utils/tips.js.map +1 -1
- package/dist/workflows/detector.d.ts +37 -0
- package/dist/workflows/detector.d.ts.map +1 -0
- package/dist/workflows/detector.js +160 -0
- package/dist/workflows/detector.js.map +1 -0
- package/dist/workflows/index.d.ts +8 -0
- package/dist/workflows/index.d.ts.map +1 -0
- package/dist/workflows/index.js +8 -0
- package/dist/workflows/index.js.map +1 -0
- package/dist/workflows/installer.d.ts +24 -0
- package/dist/workflows/installer.d.ts.map +1 -0
- package/dist/workflows/installer.js +105 -0
- package/dist/workflows/installer.js.map +1 -0
- package/dist/workflows/registry.d.ts +29 -0
- package/dist/workflows/registry.d.ts.map +1 -0
- package/dist/workflows/registry.js +54 -0
- package/dist/workflows/registry.js.map +1 -0
- package/dist/workflows/templates/github/metadata.d.ts +6 -0
- package/dist/workflows/templates/github/metadata.d.ts.map +1 -0
- package/dist/workflows/templates/github/metadata.js +111 -0
- package/dist/workflows/templates/github/metadata.js.map +1 -0
- package/dist/workflows/templates/gitlab/metadata.d.ts +6 -0
- package/dist/workflows/templates/gitlab/metadata.d.ts.map +1 -0
- package/dist/workflows/templates/gitlab/metadata.js +14 -0
- package/dist/workflows/templates/gitlab/metadata.js.map +1 -0
- package/dist/workflows/types.d.ts +71 -0
- package/dist/workflows/types.d.ts.map +1 -0
- package/dist/workflows/types.js +5 -0
- package/dist/workflows/types.js.map +1 -0
- package/package.json +32 -25
- package/src/workflows/templates/github/code-ci.yml +529 -0
- package/src/workflows/templates/github/inline-fix.yml +665 -0
- package/src/workflows/templates/github/pr-review.yml +677 -0
- package/.claude/agents/README.md +0 -298
- package/.claude/agents/release-manager.md +0 -857
- package/.codemie/guides/git-workflow.md +0 -493
- package/CLAUDE.md +0 -855
- package/dist/agents/adapters/aider.d.ts +0 -12
- package/dist/agents/adapters/aider.d.ts.map +0 -1
- package/dist/agents/adapters/aider.js +0 -80
- package/dist/agents/adapters/aider.js.map +0 -1
- package/dist/cli/cli.d.ts +0 -4
- package/dist/cli/cli.d.ts.map +0 -1
- package/dist/cli/cli.js +0 -107
- package/dist/cli/cli.js.map +0 -1
- package/dist/cli/commands/mcp.d.ts +0 -3
- package/dist/cli/commands/mcp.d.ts.map +0 -1
- package/dist/cli/commands/mcp.js +0 -459
- package/dist/cli/commands/mcp.js.map +0 -1
- package/dist/code/agent-events.d.ts +0 -39
- package/dist/code/agent-events.d.ts.map +0 -1
- package/dist/code/agent-events.js +0 -4
- package/dist/code/agent-events.js.map +0 -1
- package/dist/code/agent.d.ts +0 -19
- package/dist/code/agent.d.ts.map +0 -1
- package/dist/code/agent.js +0 -144
- package/dist/code/agent.js.map +0 -1
- package/dist/code/config.d.ts +0 -13
- package/dist/code/config.d.ts.map +0 -1
- package/dist/code/config.js +0 -41
- package/dist/code/config.js.map +0 -1
- package/dist/code/index.d.ts +0 -19
- package/dist/code/index.d.ts.map +0 -1
- package/dist/code/index.js +0 -400
- package/dist/code/index.js.map +0 -1
- package/dist/code/prompts.d.ts +0 -2
- package/dist/code/prompts.d.ts.map +0 -1
- package/dist/code/prompts.js +0 -45
- package/dist/code/prompts.js.map +0 -1
- package/dist/code/tools/command.d.ts +0 -8
- package/dist/code/tools/command.d.ts.map +0 -1
- package/dist/code/tools/command.js +0 -83
- package/dist/code/tools/command.js.map +0 -1
- package/dist/code/tools/diff-utils.d.ts +0 -2
- package/dist/code/tools/diff-utils.d.ts.map +0 -1
- package/dist/code/tools/diff-utils.js +0 -45
- package/dist/code/tools/diff-utils.js.map +0 -1
- package/dist/code/tools/filesystem.d.ts +0 -11
- package/dist/code/tools/filesystem.d.ts.map +0 -1
- package/dist/code/tools/filesystem.js +0 -442
- package/dist/code/tools/filesystem.js.map +0 -1
- package/dist/code/tools/git.d.ts +0 -7
- package/dist/code/tools/git.d.ts.map +0 -1
- package/dist/code/tools/git.js +0 -111
- package/dist/code/tools/git.js.map +0 -1
- package/dist/code/tools/mcp.d.ts +0 -13
- package/dist/code/tools/mcp.d.ts.map +0 -1
- package/dist/code/tools/mcp.js +0 -230
- package/dist/code/tools/mcp.js.map +0 -1
- package/dist/data/tips.json +0 -118
- package/dist/ui/terminal-ui.d.ts +0 -73
- package/dist/ui/terminal-ui.d.ts.map +0 -1
- package/dist/ui/terminal-ui.js +0 -900
- package/dist/ui/terminal-ui.js.map +0 -1
- package/dist/utils/env-mapper.d.ts +0 -40
- package/dist/utils/env-mapper.d.ts.map +0 -1
- package/dist/utils/env-mapper.js +0 -122
- package/dist/utils/env-mapper.js.map +0 -1
- package/docs/USER_GUIDE.md +0 -573
- package/eslint.config.mjs +0 -43
- package/tests/agent-direct.test.mjs +0 -45
- package/tests/agent-output.test.mjs +0 -64
- package/tests/codemie-code.test.mjs +0 -42
- package/tests/context7-only.test.mjs +0 -42
- package/tests/conversation-flow.test.mjs +0 -63
- package/tests/interactive-simulation.test.mjs +0 -60
- package/tests/live-output.test.mjs +0 -53
- package/tests/mcp-context7.test.mjs +0 -105
- package/tests/mcp-e2e.test.mjs +0 -109
- package/tests/mcp-time-server.test.mjs +0 -58
- package/tests/streaming.test.mjs +0 -57
- package/tests/test-helpers.mjs +0 -94
- package/tests/text-wrapping.test.mjs +0 -33
- package/tests/tool-count.test.mjs +0 -81
- package/tests/ui-format.test.mjs +0 -39
- package/tests/ui-state.test.mjs +0 -72
|
@@ -0,0 +1,689 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeMie Native Agent Implementation
|
|
3
|
+
*
|
|
4
|
+
* Core LangGraph ReAct agent using LangChain v1.0+ with streaming support
|
|
5
|
+
*/
|
|
6
|
+
import { createReactAgent } from '@langchain/langgraph/prebuilt';
|
|
7
|
+
import { ChatOpenAI } from '@langchain/openai';
|
|
8
|
+
import { HumanMessage } from '@langchain/core/messages';
|
|
9
|
+
import { getSystemPrompt } from './prompts.js';
|
|
10
|
+
import { CodeMieAgentError } from './types.js';
|
|
11
|
+
import { extractToolMetadata } from './toolMetadata.js';
|
|
12
|
+
import { extractTokenUsageFromStreamChunk, extractTokenUsageFromFinalState } from './tokenUtils.js';
|
|
13
|
+
import { setGlobalToolEventCallback } from './tools/index.js';
|
|
14
|
+
export class CodeMieAgent {
|
|
15
|
+
agent;
|
|
16
|
+
config;
|
|
17
|
+
tools;
|
|
18
|
+
conversationHistory = [];
|
|
19
|
+
toolCallArgs = new Map(); // Store tool args by tool call ID
|
|
20
|
+
currentExecutionSteps = [];
|
|
21
|
+
currentStepNumber = 0;
|
|
22
|
+
currentLLMTokenUsage = null; // Store token usage for associating with next tool call
|
|
23
|
+
isFirstLLMCall = true; // Track if this is the initial user input processing
|
|
24
|
+
stats = {
|
|
25
|
+
inputTokens: 0,
|
|
26
|
+
outputTokens: 0,
|
|
27
|
+
cachedTokens: 0,
|
|
28
|
+
totalTokens: 0,
|
|
29
|
+
estimatedTotalCost: 0,
|
|
30
|
+
executionTime: 0,
|
|
31
|
+
toolCalls: 0,
|
|
32
|
+
successfulTools: 0,
|
|
33
|
+
failedTools: 0,
|
|
34
|
+
llmCalls: 0,
|
|
35
|
+
executionSteps: []
|
|
36
|
+
};
|
|
37
|
+
constructor(config, tools) {
|
|
38
|
+
this.config = config;
|
|
39
|
+
this.tools = tools;
|
|
40
|
+
// Create the appropriate LLM based on provider
|
|
41
|
+
const llm = this.createLLM();
|
|
42
|
+
// Create LangGraph ReAct agent with system prompt
|
|
43
|
+
this.agent = createReactAgent({
|
|
44
|
+
llm,
|
|
45
|
+
tools: this.tools,
|
|
46
|
+
messageModifier: getSystemPrompt(config.workingDirectory)
|
|
47
|
+
});
|
|
48
|
+
if (config.debug) {
|
|
49
|
+
console.log(`[DEBUG] CodeMie Agent initialized with ${tools.length} tools`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create the appropriate LLM instance based on provider configuration
|
|
54
|
+
*/
|
|
55
|
+
createLLM() {
|
|
56
|
+
const commonConfig = {
|
|
57
|
+
temperature: 0.7,
|
|
58
|
+
maxTokens: 4096,
|
|
59
|
+
timeout: this.config.timeout * 1000
|
|
60
|
+
};
|
|
61
|
+
switch (this.config.provider) {
|
|
62
|
+
case 'openai':
|
|
63
|
+
return new ChatOpenAI({
|
|
64
|
+
model: this.config.model,
|
|
65
|
+
apiKey: this.config.authToken,
|
|
66
|
+
configuration: {
|
|
67
|
+
...(this.config.baseUrl !== 'https://api.openai.com/v1' && {
|
|
68
|
+
baseURL: this.config.baseUrl
|
|
69
|
+
}),
|
|
70
|
+
// Add client tracking header to all OpenAI requests
|
|
71
|
+
fetch: async (input, init) => {
|
|
72
|
+
const updatedInit = {
|
|
73
|
+
...init,
|
|
74
|
+
headers: {
|
|
75
|
+
...init?.headers,
|
|
76
|
+
'X-CodeMie-Client': 'codemie-code'
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
return fetch(input, updatedInit);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
...commonConfig
|
|
83
|
+
});
|
|
84
|
+
case 'azure':
|
|
85
|
+
return new ChatOpenAI({
|
|
86
|
+
model: this.config.model,
|
|
87
|
+
apiKey: this.config.authToken,
|
|
88
|
+
configuration: {
|
|
89
|
+
baseURL: this.config.baseUrl,
|
|
90
|
+
defaultQuery: { 'api-version': '2024-02-01' },
|
|
91
|
+
// Add client tracking header to all Azure requests
|
|
92
|
+
fetch: async (input, init) => {
|
|
93
|
+
const updatedInit = {
|
|
94
|
+
...init,
|
|
95
|
+
headers: {
|
|
96
|
+
...init?.headers,
|
|
97
|
+
'X-CodeMie-Client': 'codemie-code'
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
return fetch(input, updatedInit);
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
...commonConfig
|
|
104
|
+
});
|
|
105
|
+
case 'bedrock':
|
|
106
|
+
// For Bedrock, use OpenAI format with AWS Bedrock credentials
|
|
107
|
+
// Bedrock uses OpenAI-compatible API with special model IDs
|
|
108
|
+
return new ChatOpenAI({
|
|
109
|
+
model: this.config.model,
|
|
110
|
+
apiKey: this.config.authToken,
|
|
111
|
+
configuration: {
|
|
112
|
+
baseURL: this.config.baseUrl !== 'bedrock' ? this.config.baseUrl : undefined,
|
|
113
|
+
// Add client tracking header to all Bedrock requests
|
|
114
|
+
fetch: async (input, init) => {
|
|
115
|
+
const updatedInit = {
|
|
116
|
+
...init,
|
|
117
|
+
headers: {
|
|
118
|
+
...init?.headers,
|
|
119
|
+
'X-CodeMie-Client': 'codemie-code'
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
return fetch(input, updatedInit);
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
...commonConfig
|
|
126
|
+
});
|
|
127
|
+
case 'litellm': {
|
|
128
|
+
// LiteLLM proxy - use OpenAI format as it's most compatible
|
|
129
|
+
// For SSO, we need to inject cookies into requests
|
|
130
|
+
// NOTE: ChatOpenAI appends '/chat/completions' directly, not '/v1/chat/completions'
|
|
131
|
+
// So if baseUrl ends with '/v1', use it as is, otherwise append '/v1'
|
|
132
|
+
let baseURL = this.config.baseUrl;
|
|
133
|
+
if (!baseURL.endsWith('/v1')) {
|
|
134
|
+
baseURL = `${baseURL}/v1`;
|
|
135
|
+
}
|
|
136
|
+
const ssoConfig = {
|
|
137
|
+
baseURL
|
|
138
|
+
};
|
|
139
|
+
// Check if we have SSO cookies to inject (following codemie-ide-plugin pattern)
|
|
140
|
+
const ssoCookies = global.codemieSSOCookies;
|
|
141
|
+
if (this.config.debug) {
|
|
142
|
+
console.log(`[DEBUG] SSO Cookies available:`, ssoCookies ? Object.keys(ssoCookies) : 'none');
|
|
143
|
+
console.log(`[DEBUG] Auth token:`, this.config.authToken);
|
|
144
|
+
}
|
|
145
|
+
if (ssoCookies && this.config.authToken === 'sso-authenticated') {
|
|
146
|
+
// Create custom fetch function that includes SSO cookies (matches oauth2Proxy.js line 134)
|
|
147
|
+
ssoConfig.fetch = async (input, init) => {
|
|
148
|
+
const cookieString = Object.entries(ssoCookies)
|
|
149
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
150
|
+
.join('; '); // Note: using '; ' separator (semicolon + space) for HTTP standard
|
|
151
|
+
const updatedInit = {
|
|
152
|
+
...init,
|
|
153
|
+
headers: {
|
|
154
|
+
...init?.headers,
|
|
155
|
+
'cookie': cookieString, // lowercase 'cookie' header like IDE plugin
|
|
156
|
+
'X-CodeMie-Client': 'codemie-code' // Track client type for request metrics
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
// Handle SSL verification consistently with SSO Gateway (rejectUnauthorized: false)
|
|
160
|
+
// SSO Gateway always allows self-signed certificates like codemie-model-fetcher does
|
|
161
|
+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
|
162
|
+
// Suppress the NODE_TLS_REJECT_UNAUTHORIZED warning since this is expected behavior
|
|
163
|
+
// that matches how codemie-claude works through SSO Gateway
|
|
164
|
+
process.removeAllListeners('warning');
|
|
165
|
+
if (this.config.debug) {
|
|
166
|
+
console.log('[DEBUG] Disabled SSL verification (like SSO Gateway and codemie-model-fetcher)');
|
|
167
|
+
}
|
|
168
|
+
if (this.config.debug) {
|
|
169
|
+
console.log(`[DEBUG] SSO request to ${input}`);
|
|
170
|
+
console.log(`[DEBUG] Cookies: ${Object.keys(ssoCookies).join(', ')}`);
|
|
171
|
+
console.log(`[DEBUG] Full cookie string length: ${cookieString.length}`);
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
const response = await fetch(input, updatedInit);
|
|
175
|
+
if (this.config.debug && !response.ok) {
|
|
176
|
+
console.log(`[DEBUG] SSO request failed: ${response.status} ${response.statusText}`);
|
|
177
|
+
}
|
|
178
|
+
return response;
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
if (this.config.debug) {
|
|
182
|
+
console.log(`[DEBUG] SSO request error:`, error);
|
|
183
|
+
}
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
// Even without SSO cookies, we still want to add the client tracking header
|
|
190
|
+
ssoConfig.fetch = async (input, init) => {
|
|
191
|
+
const updatedInit = {
|
|
192
|
+
...init,
|
|
193
|
+
headers: {
|
|
194
|
+
...init?.headers,
|
|
195
|
+
'X-CodeMie-Client': 'codemie-code' // Track client type for request metrics
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
if (this.config.debug) {
|
|
199
|
+
console.log(`[DEBUG] Non-SSO request to ${input} with client header`);
|
|
200
|
+
}
|
|
201
|
+
return fetch(input, updatedInit);
|
|
202
|
+
};
|
|
203
|
+
if (this.config.debug) {
|
|
204
|
+
console.log(`[DEBUG] WARNING: SSO cookies not found or auth token mismatch`);
|
|
205
|
+
console.log(`[DEBUG] Will attempt request without SSO cookies but with client header`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return new ChatOpenAI({
|
|
209
|
+
model: this.config.model,
|
|
210
|
+
apiKey: this.config.authToken,
|
|
211
|
+
configuration: ssoConfig,
|
|
212
|
+
...commonConfig
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
default:
|
|
216
|
+
throw new CodeMieAgentError(`Unsupported provider: ${this.config.provider}`, 'INVALID_PROVIDER', { provider: this.config.provider });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Create a HumanMessage with optional image support (multiple images)
|
|
221
|
+
*/
|
|
222
|
+
createHumanMessage(text, images = []) {
|
|
223
|
+
if (images.length === 0) {
|
|
224
|
+
// Text-only message
|
|
225
|
+
return new HumanMessage(text);
|
|
226
|
+
}
|
|
227
|
+
// Multimodal message with images
|
|
228
|
+
const content = [
|
|
229
|
+
{
|
|
230
|
+
type: "text",
|
|
231
|
+
text: text
|
|
232
|
+
}
|
|
233
|
+
];
|
|
234
|
+
// Add all images to the content
|
|
235
|
+
for (const image of images) {
|
|
236
|
+
content.push({
|
|
237
|
+
type: "image_url",
|
|
238
|
+
image_url: `data:${image.mimeType};base64,${image.data}`
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
return new HumanMessage({
|
|
242
|
+
content: content
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Stream a chat interaction with the agent
|
|
247
|
+
*/
|
|
248
|
+
async chatStream(message, onEvent, images = []) {
|
|
249
|
+
const startTime = Date.now();
|
|
250
|
+
let currentToolCall = null;
|
|
251
|
+
let currentStep = null;
|
|
252
|
+
let streamAborted = false;
|
|
253
|
+
// Reset execution steps for new conversation
|
|
254
|
+
this.currentExecutionSteps = [];
|
|
255
|
+
this.currentStepNumber = 0;
|
|
256
|
+
this.isFirstLLMCall = true;
|
|
257
|
+
// Set up global tool event callback for progress reporting
|
|
258
|
+
setGlobalToolEventCallback((event) => {
|
|
259
|
+
onEvent({
|
|
260
|
+
type: 'tool_call_progress',
|
|
261
|
+
toolName: event.toolName,
|
|
262
|
+
toolProgress: event.progress
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
// Create an AbortController for proper stream cancellation
|
|
266
|
+
const abortController = new AbortController();
|
|
267
|
+
// Set up Ctrl+C handler for graceful stream termination
|
|
268
|
+
const originalSigintHandler = process.listeners('SIGINT');
|
|
269
|
+
const sigintHandler = () => {
|
|
270
|
+
if (this.config.debug) {
|
|
271
|
+
console.log('\n[DEBUG] Received SIGINT - aborting stream...');
|
|
272
|
+
}
|
|
273
|
+
streamAborted = true;
|
|
274
|
+
abortController.abort();
|
|
275
|
+
onEvent({ type: 'error', error: 'Stream interrupted by user (Ctrl+C)' });
|
|
276
|
+
};
|
|
277
|
+
process.once('SIGINT', sigintHandler);
|
|
278
|
+
try {
|
|
279
|
+
if (this.config.debug) {
|
|
280
|
+
console.log(`[DEBUG] Processing message: ${message.substring(0, 100)}...`);
|
|
281
|
+
}
|
|
282
|
+
// Add user message to conversation history (with optional images)
|
|
283
|
+
const userMessage = this.createHumanMessage(message, images);
|
|
284
|
+
this.conversationHistory.push(userMessage);
|
|
285
|
+
// Notify start of thinking
|
|
286
|
+
onEvent({ type: 'thinking_start' });
|
|
287
|
+
// Start the first LLM call step
|
|
288
|
+
currentStep = this.startLLMStep();
|
|
289
|
+
// Create the stream with conversation history
|
|
290
|
+
const stream = await this.agent.stream({ messages: this.conversationHistory }, {
|
|
291
|
+
streamMode: 'updates',
|
|
292
|
+
recursionLimit: 50,
|
|
293
|
+
signal: abortController.signal // Add abort signal for stream cancellation
|
|
294
|
+
});
|
|
295
|
+
let hasContent = false;
|
|
296
|
+
// Process stream chunks with interruption handling
|
|
297
|
+
for await (const chunk of stream) {
|
|
298
|
+
// Check if stream was aborted
|
|
299
|
+
if (streamAborted || abortController.signal.aborted) {
|
|
300
|
+
if (this.config.debug) {
|
|
301
|
+
console.log('[DEBUG] Stream processing aborted');
|
|
302
|
+
}
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
// Try to extract token usage from stream chunk
|
|
306
|
+
const tokenUsage = extractTokenUsageFromStreamChunk(chunk, this.config.model, this.config.provider);
|
|
307
|
+
if (tokenUsage && currentStep && currentStep.type === 'llm_call') {
|
|
308
|
+
// Update current step with token usage
|
|
309
|
+
currentStep.tokenUsage = tokenUsage;
|
|
310
|
+
this.updateStatsWithTokenUsage(tokenUsage);
|
|
311
|
+
// Store token usage to associate with next tool call
|
|
312
|
+
this.currentLLMTokenUsage = tokenUsage;
|
|
313
|
+
if (this.config.debug) {
|
|
314
|
+
console.log(`[DEBUG] Token usage: ${tokenUsage.inputTokens} in, ${tokenUsage.outputTokens} out`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
this.processStreamChunk(chunk, onEvent, (toolStarted) => {
|
|
318
|
+
if (toolStarted) {
|
|
319
|
+
// Complete current LLM step if it exists
|
|
320
|
+
if (currentStep && currentStep.type === 'llm_call') {
|
|
321
|
+
this.completeStep(currentStep);
|
|
322
|
+
currentStep = null;
|
|
323
|
+
}
|
|
324
|
+
// Start tool execution step
|
|
325
|
+
currentStep = this.startToolStep(toolStarted);
|
|
326
|
+
currentToolCall = toolStarted;
|
|
327
|
+
this.stats.toolCalls++;
|
|
328
|
+
}
|
|
329
|
+
else if (currentToolCall && currentStep) {
|
|
330
|
+
// Complete tool step
|
|
331
|
+
currentStep.toolSuccess = true;
|
|
332
|
+
this.completeStep(currentStep);
|
|
333
|
+
currentStep = null;
|
|
334
|
+
this.stats.successfulTools++;
|
|
335
|
+
currentToolCall = null;
|
|
336
|
+
// Start new LLM step for next reasoning cycle (processing tool result)
|
|
337
|
+
currentStep = this.startLLMStep();
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
// Check if we have content
|
|
341
|
+
if (chunk.agent?.messages) {
|
|
342
|
+
const lastMessage = chunk.agent.messages.at(-1);
|
|
343
|
+
if (lastMessage?.content && !hasContent) {
|
|
344
|
+
hasContent = true;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
// Complete any remaining step
|
|
349
|
+
if (currentStep) {
|
|
350
|
+
this.completeStep(currentStep);
|
|
351
|
+
}
|
|
352
|
+
// Update conversation history with final messages and try to extract any missed token usage
|
|
353
|
+
try {
|
|
354
|
+
const finalState = await this.agent.getState();
|
|
355
|
+
if (finalState?.messages) {
|
|
356
|
+
this.conversationHistory = finalState.messages;
|
|
357
|
+
// Try to extract token usage from final state if we missed it during streaming
|
|
358
|
+
const finalTokenUsage = extractTokenUsageFromFinalState(finalState, this.config.model, this.config.provider);
|
|
359
|
+
if (finalTokenUsage && this.currentExecutionSteps.length > 0) {
|
|
360
|
+
// Find the last LLM step that doesn't have token usage
|
|
361
|
+
for (let i = this.currentExecutionSteps.length - 1; i >= 0; i--) {
|
|
362
|
+
const step = this.currentExecutionSteps[i];
|
|
363
|
+
if (step.type === 'llm_call' && !step.tokenUsage) {
|
|
364
|
+
step.tokenUsage = finalTokenUsage;
|
|
365
|
+
this.updateStatsWithTokenUsage(finalTokenUsage);
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
// If getState fails, continue without updating history
|
|
374
|
+
if (this.config.debug) {
|
|
375
|
+
console.log('[DEBUG] Could not get final state, continuing...');
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
// Finalize execution statistics
|
|
379
|
+
this.stats.executionTime = Date.now() - startTime;
|
|
380
|
+
this.stats.executionSteps = [...this.currentExecutionSteps];
|
|
381
|
+
// Notify thinking end and completion
|
|
382
|
+
onEvent({ type: 'thinking_end' });
|
|
383
|
+
onEvent({ type: 'complete' });
|
|
384
|
+
if (this.config.debug) {
|
|
385
|
+
console.log(`[DEBUG] Agent completed in ${this.stats.executionTime}ms`);
|
|
386
|
+
console.log(`[DEBUG] Total tokens: ${this.stats.totalTokens} (${this.stats.inputTokens} in, ${this.stats.outputTokens} out)`);
|
|
387
|
+
console.log(`[DEBUG] Estimated cost: $${this.stats.estimatedTotalCost.toFixed(4)}`);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
catch (error) {
|
|
391
|
+
this.stats.executionTime = Date.now() - startTime;
|
|
392
|
+
if (currentToolCall) {
|
|
393
|
+
this.stats.failedTools++;
|
|
394
|
+
}
|
|
395
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
396
|
+
// Handle AbortError from user interruption gracefully
|
|
397
|
+
if (error instanceof Error && (error.name === 'AbortError' || streamAborted)) {
|
|
398
|
+
if (this.config.debug) {
|
|
399
|
+
console.log('[DEBUG] Stream aborted by user');
|
|
400
|
+
}
|
|
401
|
+
onEvent({
|
|
402
|
+
type: 'error',
|
|
403
|
+
error: 'Operation interrupted by user'
|
|
404
|
+
});
|
|
405
|
+
return; // Don't throw error for user interruptions
|
|
406
|
+
}
|
|
407
|
+
if (this.config.debug) {
|
|
408
|
+
console.error(`[DEBUG] Agent error:`, error);
|
|
409
|
+
}
|
|
410
|
+
onEvent({
|
|
411
|
+
type: 'error',
|
|
412
|
+
error: errorMessage
|
|
413
|
+
});
|
|
414
|
+
throw new CodeMieAgentError(`Agent execution failed: ${errorMessage}`, 'EXECUTION_ERROR', { originalError: error, stats: this.stats });
|
|
415
|
+
}
|
|
416
|
+
finally {
|
|
417
|
+
// Clean up global tool event callback
|
|
418
|
+
setGlobalToolEventCallback(null);
|
|
419
|
+
// Always clean up signal handler
|
|
420
|
+
process.removeListener('SIGINT', sigintHandler);
|
|
421
|
+
// Restore original handlers if they existed
|
|
422
|
+
if (originalSigintHandler.length > 0) {
|
|
423
|
+
originalSigintHandler.forEach(handler => {
|
|
424
|
+
process.on('SIGINT', handler);
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Process individual stream chunks from LangGraph
|
|
431
|
+
*/
|
|
432
|
+
processStreamChunk(chunk, onEvent, onToolEvent) {
|
|
433
|
+
try {
|
|
434
|
+
// Handle agent node updates (LLM responses)
|
|
435
|
+
if (chunk.agent?.messages) {
|
|
436
|
+
const messages = chunk.agent.messages;
|
|
437
|
+
const lastMessage = messages[messages.length - 1];
|
|
438
|
+
// Stream content chunks
|
|
439
|
+
if (lastMessage?.content && typeof lastMessage.content === 'string') {
|
|
440
|
+
onEvent({
|
|
441
|
+
type: 'content_chunk',
|
|
442
|
+
content: lastMessage.content
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
// Handle tool calls
|
|
446
|
+
if (lastMessage?.tool_calls && lastMessage.tool_calls.length > 0) {
|
|
447
|
+
for (const toolCall of lastMessage.tool_calls) {
|
|
448
|
+
// Store tool args for later use in result processing
|
|
449
|
+
// Use tool name as key since LangGraph may not preserve IDs consistently
|
|
450
|
+
this.toolCallArgs.set(toolCall.name, toolCall.args);
|
|
451
|
+
onEvent({
|
|
452
|
+
type: 'tool_call_start',
|
|
453
|
+
toolName: toolCall.name,
|
|
454
|
+
toolArgs: toolCall.args
|
|
455
|
+
});
|
|
456
|
+
if (onToolEvent) {
|
|
457
|
+
onToolEvent(toolCall.name);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
// Handle tool node updates (tool execution results)
|
|
463
|
+
if (chunk.tools?.messages) {
|
|
464
|
+
const messages = chunk.tools.messages;
|
|
465
|
+
for (const toolMessage of messages) {
|
|
466
|
+
const toolName = toolMessage.name || 'unknown';
|
|
467
|
+
const result = toolMessage.content || '';
|
|
468
|
+
// Get the stored tool args for this tool name
|
|
469
|
+
const toolArgs = this.toolCallArgs.get(toolName);
|
|
470
|
+
if (toolArgs) {
|
|
471
|
+
this.toolCallArgs.delete(toolName); // Clean up after use
|
|
472
|
+
}
|
|
473
|
+
// Extract enhanced metadata from the tool result
|
|
474
|
+
let toolMetadata = extractToolMetadata(toolName, result, toolArgs);
|
|
475
|
+
// Associate token usage from the LLM call that triggered this tool
|
|
476
|
+
if (toolMetadata && this.currentLLMTokenUsage) {
|
|
477
|
+
toolMetadata = {
|
|
478
|
+
...toolMetadata,
|
|
479
|
+
tokenUsage: this.currentLLMTokenUsage
|
|
480
|
+
};
|
|
481
|
+
// Clear the stored token usage after associating it
|
|
482
|
+
this.currentLLMTokenUsage = null;
|
|
483
|
+
}
|
|
484
|
+
onEvent({
|
|
485
|
+
type: 'tool_call_result',
|
|
486
|
+
toolName,
|
|
487
|
+
result,
|
|
488
|
+
toolMetadata
|
|
489
|
+
});
|
|
490
|
+
if (onToolEvent) {
|
|
491
|
+
onToolEvent(); // Signal tool completion
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
catch (error) {
|
|
497
|
+
if (this.config.debug) {
|
|
498
|
+
console.error(`[DEBUG] Error processing stream chunk:`, error);
|
|
499
|
+
}
|
|
500
|
+
// Don't throw here, just log - let the main stream continue
|
|
501
|
+
onEvent({
|
|
502
|
+
type: 'error',
|
|
503
|
+
error: `Stream processing error: ${error instanceof Error ? error.message : String(error)}`
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Execute a single message without streaming (for non-interactive use)
|
|
509
|
+
*/
|
|
510
|
+
async executeMessage(message) {
|
|
511
|
+
return new Promise((resolve, reject) => {
|
|
512
|
+
let response = '';
|
|
513
|
+
let hasError = false;
|
|
514
|
+
this.chatStream(message, (event) => {
|
|
515
|
+
switch (event.type) {
|
|
516
|
+
case 'content_chunk':
|
|
517
|
+
response += event.content || '';
|
|
518
|
+
break;
|
|
519
|
+
case 'complete':
|
|
520
|
+
if (!hasError) {
|
|
521
|
+
resolve(response.trim());
|
|
522
|
+
}
|
|
523
|
+
break;
|
|
524
|
+
case 'error':
|
|
525
|
+
hasError = true;
|
|
526
|
+
reject(new Error(event.error));
|
|
527
|
+
break;
|
|
528
|
+
}
|
|
529
|
+
}).catch(reject);
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Clear conversation history
|
|
534
|
+
*/
|
|
535
|
+
clearHistory() {
|
|
536
|
+
this.conversationHistory = [];
|
|
537
|
+
this.toolCallArgs.clear(); // Clear stored tool args
|
|
538
|
+
this.currentExecutionSteps = [];
|
|
539
|
+
this.currentStepNumber = 0;
|
|
540
|
+
this.currentLLMTokenUsage = null;
|
|
541
|
+
this.isFirstLLMCall = true;
|
|
542
|
+
// Reset stats
|
|
543
|
+
this.stats = {
|
|
544
|
+
inputTokens: 0,
|
|
545
|
+
outputTokens: 0,
|
|
546
|
+
cachedTokens: 0,
|
|
547
|
+
totalTokens: 0,
|
|
548
|
+
estimatedTotalCost: 0,
|
|
549
|
+
executionTime: 0,
|
|
550
|
+
toolCalls: 0,
|
|
551
|
+
successfulTools: 0,
|
|
552
|
+
failedTools: 0,
|
|
553
|
+
llmCalls: 0,
|
|
554
|
+
executionSteps: []
|
|
555
|
+
};
|
|
556
|
+
if (this.config.debug) {
|
|
557
|
+
console.log('[DEBUG] Conversation history cleared');
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Get current conversation history
|
|
562
|
+
*/
|
|
563
|
+
getHistory() {
|
|
564
|
+
return [...this.conversationHistory];
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Get agent runtime statistics
|
|
568
|
+
*/
|
|
569
|
+
getStats() {
|
|
570
|
+
return { ...this.stats };
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Get available tools
|
|
574
|
+
*/
|
|
575
|
+
getTools() {
|
|
576
|
+
return [...this.tools];
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Get agent configuration
|
|
580
|
+
*/
|
|
581
|
+
getConfig() {
|
|
582
|
+
// Return sanitized config (without sensitive data)
|
|
583
|
+
return {
|
|
584
|
+
...this.config,
|
|
585
|
+
authToken: `${this.config.authToken.substring(0, 8)}***`
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Health check for the agent
|
|
590
|
+
*/
|
|
591
|
+
async healthCheck() {
|
|
592
|
+
try {
|
|
593
|
+
// Simple test message
|
|
594
|
+
await this.executeMessage('Hello, can you confirm you are working?');
|
|
595
|
+
return {
|
|
596
|
+
status: 'healthy',
|
|
597
|
+
provider: this.config.provider,
|
|
598
|
+
model: this.config.model,
|
|
599
|
+
toolCount: this.tools.length
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
catch (error) {
|
|
603
|
+
return {
|
|
604
|
+
status: 'unhealthy',
|
|
605
|
+
provider: this.config.provider,
|
|
606
|
+
model: this.config.model,
|
|
607
|
+
toolCount: this.tools.length,
|
|
608
|
+
error: error instanceof Error ? error.message : String(error)
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Start a new LLM call step
|
|
614
|
+
*/
|
|
615
|
+
startLLMStep() {
|
|
616
|
+
// Determine the context based on whether this is the first call and if we just had a tool execution
|
|
617
|
+
let llmContext;
|
|
618
|
+
if (this.isFirstLLMCall) {
|
|
619
|
+
llmContext = 'initial_input';
|
|
620
|
+
this.isFirstLLMCall = false;
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
// Check if the previous step was a tool execution
|
|
624
|
+
const prevStep = this.currentExecutionSteps[this.currentExecutionSteps.length - 1];
|
|
625
|
+
llmContext = (prevStep?.type === 'tool_execution') ? 'processing_tool_result' : 'final_response';
|
|
626
|
+
}
|
|
627
|
+
const step = {
|
|
628
|
+
stepNumber: ++this.currentStepNumber,
|
|
629
|
+
type: 'llm_call',
|
|
630
|
+
startTime: Date.now(),
|
|
631
|
+
llmContext
|
|
632
|
+
};
|
|
633
|
+
this.currentExecutionSteps.push(step);
|
|
634
|
+
this.stats.llmCalls++;
|
|
635
|
+
if (this.config.debug) {
|
|
636
|
+
console.log(`[DEBUG] Started LLM step ${step.stepNumber} (${llmContext})`);
|
|
637
|
+
}
|
|
638
|
+
return step;
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Start a new tool execution step
|
|
642
|
+
*/
|
|
643
|
+
startToolStep(toolName) {
|
|
644
|
+
const step = {
|
|
645
|
+
stepNumber: ++this.currentStepNumber,
|
|
646
|
+
type: 'tool_execution',
|
|
647
|
+
startTime: Date.now(),
|
|
648
|
+
toolName
|
|
649
|
+
};
|
|
650
|
+
this.currentExecutionSteps.push(step);
|
|
651
|
+
if (this.config.debug) {
|
|
652
|
+
// Get the stored tool args for enhanced logging
|
|
653
|
+
const toolArgs = this.toolCallArgs.get(toolName);
|
|
654
|
+
if (toolArgs && Object.keys(toolArgs).length > 0) {
|
|
655
|
+
console.log(`[DEBUG] Started tool step ${step.stepNumber}: ${toolName} ${JSON.stringify(toolArgs)}`);
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
console.log(`[DEBUG] Started tool step ${step.stepNumber}: ${toolName}`);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
return step;
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Complete an execution step
|
|
665
|
+
*/
|
|
666
|
+
completeStep(step) {
|
|
667
|
+
step.endTime = Date.now();
|
|
668
|
+
step.duration = step.endTime - step.startTime;
|
|
669
|
+
if (this.config.debug) {
|
|
670
|
+
const type = step.type === 'llm_call' ? 'LLM' : `Tool (${step.toolName})`;
|
|
671
|
+
console.log(`[DEBUG] Completed ${type} step ${step.stepNumber} in ${step.duration}ms`);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Update aggregate statistics with token usage
|
|
676
|
+
*/
|
|
677
|
+
updateStatsWithTokenUsage(tokenUsage) {
|
|
678
|
+
this.stats.inputTokens += tokenUsage.inputTokens;
|
|
679
|
+
this.stats.outputTokens += tokenUsage.outputTokens;
|
|
680
|
+
if (tokenUsage.cachedTokens) {
|
|
681
|
+
this.stats.cachedTokens += tokenUsage.cachedTokens;
|
|
682
|
+
}
|
|
683
|
+
this.stats.totalTokens = this.stats.inputTokens + this.stats.outputTokens;
|
|
684
|
+
if (tokenUsage.estimatedCost) {
|
|
685
|
+
this.stats.estimatedTotalCost += tokenUsage.estimatedCost;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
//# sourceMappingURL=agent.js.map
|