@defai.digital/ax-cli 4.4.7 → 4.4.11
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/bin/ax-cli +1 -5
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +158 -9
- package/dist/index.js.map +1 -1
- package/dist/setup.d.ts +27 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +591 -0
- package/dist/setup.js.map +1 -0
- package/package.json +43 -135
- package/LICENSE +0 -22
- package/README.md +0 -420
- package/config-defaults/messages.yaml +0 -75
- package/config-defaults/models.yaml +0 -57
- package/config-defaults/prompts.yaml +0 -948
- package/config-defaults/settings.yaml +0 -157
- package/dist/agent/agent-executor.d.ts +0 -61
- package/dist/agent/agent-executor.js +0 -194
- package/dist/agent/agent-executor.js.map +0 -1
- package/dist/agent/agent-router.d.ts +0 -68
- package/dist/agent/agent-router.js +0 -242
- package/dist/agent/agent-router.js.map +0 -1
- package/dist/agent/context-manager.d.ts +0 -122
- package/dist/agent/context-manager.js +0 -406
- package/dist/agent/context-manager.js.map +0 -1
- package/dist/agent/core/index.d.ts +0 -8
- package/dist/agent/core/index.js +0 -9
- package/dist/agent/core/index.js.map +0 -1
- package/dist/agent/core/types.d.ts +0 -92
- package/dist/agent/core/types.js +0 -11
- package/dist/agent/core/types.js.map +0 -1
- package/dist/agent/dependency-resolver.d.ts +0 -90
- package/dist/agent/dependency-resolver.js +0 -366
- package/dist/agent/dependency-resolver.js.map +0 -1
- package/dist/agent/execution/index.d.ts +0 -9
- package/dist/agent/execution/index.js +0 -9
- package/dist/agent/execution/index.js.map +0 -1
- package/dist/agent/execution/tool-executor.d.ts +0 -93
- package/dist/agent/execution/tool-executor.js +0 -552
- package/dist/agent/execution/tool-executor.js.map +0 -1
- package/dist/agent/index.d.ts +0 -14
- package/dist/agent/index.js +0 -145
- package/dist/agent/index.js.map +0 -1
- package/dist/agent/llm-agent.d.ts +0 -368
- package/dist/agent/llm-agent.js +0 -1931
- package/dist/agent/llm-agent.js.map +0 -1
- package/dist/agent/loop-detector.d.ts +0 -72
- package/dist/agent/loop-detector.js +0 -335
- package/dist/agent/loop-detector.js.map +0 -1
- package/dist/agent/parallel-tools.d.ts +0 -69
- package/dist/agent/parallel-tools.js +0 -188
- package/dist/agent/parallel-tools.js.map +0 -1
- package/dist/agent/planning/index.d.ts +0 -9
- package/dist/agent/planning/index.js +0 -9
- package/dist/agent/planning/index.js.map +0 -1
- package/dist/agent/planning/plan-executor.d.ts +0 -79
- package/dist/agent/planning/plan-executor.js +0 -240
- package/dist/agent/planning/plan-executor.js.map +0 -1
- package/dist/agent/progress-tracker.d.ts +0 -94
- package/dist/agent/progress-tracker.js +0 -225
- package/dist/agent/progress-tracker.js.map +0 -1
- package/dist/agent/specialized/analysis-agent.d.ts +0 -11
- package/dist/agent/specialized/analysis-agent.js +0 -24
- package/dist/agent/specialized/analysis-agent.js.map +0 -1
- package/dist/agent/specialized/debug-agent.d.ts +0 -11
- package/dist/agent/specialized/debug-agent.js +0 -46
- package/dist/agent/specialized/debug-agent.js.map +0 -1
- package/dist/agent/specialized/documentation-agent.d.ts +0 -11
- package/dist/agent/specialized/documentation-agent.js +0 -24
- package/dist/agent/specialized/documentation-agent.js.map +0 -1
- package/dist/agent/specialized/index.d.ts +0 -11
- package/dist/agent/specialized/index.js +0 -12
- package/dist/agent/specialized/index.js.map +0 -1
- package/dist/agent/specialized/performance-agent.d.ts +0 -11
- package/dist/agent/specialized/performance-agent.js +0 -24
- package/dist/agent/specialized/performance-agent.js.map +0 -1
- package/dist/agent/specialized/refactoring-agent.d.ts +0 -11
- package/dist/agent/specialized/refactoring-agent.js +0 -24
- package/dist/agent/specialized/refactoring-agent.js.map +0 -1
- package/dist/agent/specialized/testing-agent.d.ts +0 -11
- package/dist/agent/specialized/testing-agent.js +0 -24
- package/dist/agent/specialized/testing-agent.js.map +0 -1
- package/dist/agent/status-reporter.d.ts +0 -114
- package/dist/agent/status-reporter.js +0 -335
- package/dist/agent/status-reporter.js.map +0 -1
- package/dist/agent/streaming/index.d.ts +0 -9
- package/dist/agent/streaming/index.js +0 -9
- package/dist/agent/streaming/index.js.map +0 -1
- package/dist/agent/streaming/stream-handler.d.ts +0 -62
- package/dist/agent/streaming/stream-handler.js +0 -217
- package/dist/agent/streaming/stream-handler.js.map +0 -1
- package/dist/agent/subagent-orchestrator.d.ts +0 -166
- package/dist/agent/subagent-orchestrator.js +0 -487
- package/dist/agent/subagent-orchestrator.js.map +0 -1
- package/dist/agent/subagent-types.d.ts +0 -261
- package/dist/agent/subagent-types.js +0 -257
- package/dist/agent/subagent-types.js.map +0 -1
- package/dist/agent/subagent.d.ts +0 -116
- package/dist/agent/subagent.js +0 -507
- package/dist/agent/subagent.js.map +0 -1
- package/dist/checkpoint/index.d.ts +0 -9
- package/dist/checkpoint/index.js +0 -11
- package/dist/checkpoint/index.js.map +0 -1
- package/dist/checkpoint/manager.d.ts +0 -101
- package/dist/checkpoint/manager.js +0 -407
- package/dist/checkpoint/manager.js.map +0 -1
- package/dist/checkpoint/storage.d.ts +0 -39
- package/dist/checkpoint/storage.js +0 -350
- package/dist/checkpoint/storage.js.map +0 -1
- package/dist/checkpoint/types.d.ts +0 -111
- package/dist/checkpoint/types.js +0 -17
- package/dist/checkpoint/types.js.map +0 -1
- package/dist/commands/cache.d.ts +0 -7
- package/dist/commands/cache.js +0 -284
- package/dist/commands/cache.js.map +0 -1
- package/dist/commands/custom-commands.d.ts +0 -77
- package/dist/commands/custom-commands.js +0 -251
- package/dist/commands/custom-commands.js.map +0 -1
- package/dist/commands/design.d.ts +0 -18
- package/dist/commands/design.js +0 -511
- package/dist/commands/design.js.map +0 -1
- package/dist/commands/doctor.d.ts +0 -6
- package/dist/commands/doctor.js +0 -773
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/frontend.d.ts +0 -9
- package/dist/commands/frontend.js +0 -645
- package/dist/commands/frontend.js.map +0 -1
- package/dist/commands/init/wizard.d.ts +0 -55
- package/dist/commands/init/wizard.js +0 -189
- package/dist/commands/init/wizard.js.map +0 -1
- package/dist/commands/init.d.ts +0 -8
- package/dist/commands/init.js +0 -195
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/mcp-migrate.d.ts +0 -9
- package/dist/commands/mcp-migrate.js +0 -175
- package/dist/commands/mcp-migrate.js.map +0 -1
- package/dist/commands/mcp.d.ts +0 -2
- package/dist/commands/mcp.js +0 -1292
- package/dist/commands/mcp.js.map +0 -1
- package/dist/commands/memory.d.ts +0 -6
- package/dist/commands/memory.js +0 -555
- package/dist/commands/memory.js.map +0 -1
- package/dist/commands/models.d.ts +0 -5
- package/dist/commands/models.js +0 -213
- package/dist/commands/models.js.map +0 -1
- package/dist/commands/plan.d.ts +0 -43
- package/dist/commands/plan.js +0 -362
- package/dist/commands/plan.js.map +0 -1
- package/dist/commands/rewind.d.ts +0 -19
- package/dist/commands/rewind.js +0 -221
- package/dist/commands/rewind.js.map +0 -1
- package/dist/commands/setup.d.ts +0 -14
- package/dist/commands/setup.js +0 -733
- package/dist/commands/setup.js.map +0 -1
- package/dist/commands/status.d.ts +0 -7
- package/dist/commands/status.js +0 -437
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/templates.d.ts +0 -5
- package/dist/commands/templates.js +0 -245
- package/dist/commands/templates.js.map +0 -1
- package/dist/commands/update.d.ts +0 -49
- package/dist/commands/update.js +0 -366
- package/dist/commands/update.js.map +0 -1
- package/dist/commands/usage.d.ts +0 -8
- package/dist/commands/usage.js +0 -264
- package/dist/commands/usage.js.map +0 -1
- package/dist/commands/vscode.d.ts +0 -7
- package/dist/commands/vscode.js +0 -419
- package/dist/commands/vscode.js.map +0 -1
- package/dist/constants.d.ts +0 -236
- package/dist/constants.js +0 -288
- package/dist/constants.js.map +0 -1
- package/dist/design/figma-alias.d.ts +0 -170
- package/dist/design/figma-alias.js +0 -577
- package/dist/design/figma-alias.js.map +0 -1
- package/dist/design/figma-audit.d.ts +0 -40
- package/dist/design/figma-audit.js +0 -383
- package/dist/design/figma-audit.js.map +0 -1
- package/dist/design/figma-client.d.ts +0 -131
- package/dist/design/figma-client.js +0 -369
- package/dist/design/figma-client.js.map +0 -1
- package/dist/design/figma-map.d.ts +0 -29
- package/dist/design/figma-map.js +0 -346
- package/dist/design/figma-map.js.map +0 -1
- package/dist/design/figma-tokens.d.ts +0 -73
- package/dist/design/figma-tokens.js +0 -448
- package/dist/design/figma-tokens.js.map +0 -1
- package/dist/design/index.d.ts +0 -13
- package/dist/design/index.js +0 -20
- package/dist/design/index.js.map +0 -1
- package/dist/design/types.d.ts +0 -98
- package/dist/design/types.js +0 -9
- package/dist/design/types.js.map +0 -1
- package/dist/hooks/hook-runner.d.ts +0 -142
- package/dist/hooks/hook-runner.js +0 -436
- package/dist/hooks/hook-runner.js.map +0 -1
- package/dist/hooks/index.d.ts +0 -9
- package/dist/hooks/index.js +0 -10
- package/dist/hooks/index.js.map +0 -1
- package/dist/hooks/manager.d.ts +0 -84
- package/dist/hooks/manager.js +0 -348
- package/dist/hooks/manager.js.map +0 -1
- package/dist/hooks/types.d.ts +0 -134
- package/dist/hooks/types.js +0 -9
- package/dist/hooks/types.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/ipc/index.d.ts +0 -9
- package/dist/ipc/index.js +0 -10
- package/dist/ipc/index.js.map +0 -1
- package/dist/ipc/vscode-client.d.ts +0 -200
- package/dist/ipc/vscode-client.js +0 -495
- package/dist/ipc/vscode-client.js.map +0 -1
- package/dist/llm/client.d.ts +0 -205
- package/dist/llm/client.js +0 -735
- package/dist/llm/client.js.map +0 -1
- package/dist/llm/tools.d.ts +0 -102
- package/dist/llm/tools.js +0 -275
- package/dist/llm/tools.js.map +0 -1
- package/dist/llm/types.d.ts +0 -428
- package/dist/llm/types.js +0 -194
- package/dist/llm/types.js.map +0 -1
- package/dist/mcp/automatosx-auto-discovery.d.ts +0 -66
- package/dist/mcp/automatosx-auto-discovery.js +0 -169
- package/dist/mcp/automatosx-auto-discovery.js.map +0 -1
- package/dist/mcp/automatosx-loader.d.ts +0 -99
- package/dist/mcp/automatosx-loader.js +0 -250
- package/dist/mcp/automatosx-loader.js.map +0 -1
- package/dist/mcp/cancellation.d.ts +0 -182
- package/dist/mcp/cancellation.js +0 -275
- package/dist/mcp/cancellation.js.map +0 -1
- package/dist/mcp/client-v2.d.ts +0 -500
- package/dist/mcp/client-v2.js +0 -1433
- package/dist/mcp/client-v2.js.map +0 -1
- package/dist/mcp/client.d.ts +0 -170
- package/dist/mcp/client.js +0 -232
- package/dist/mcp/client.js.map +0 -1
- package/dist/mcp/config-detector.d.ts +0 -90
- package/dist/mcp/config-detector.js +0 -250
- package/dist/mcp/config-detector.js.map +0 -1
- package/dist/mcp/config-migrator.d.ts +0 -68
- package/dist/mcp/config-migrator.js +0 -291
- package/dist/mcp/config-migrator.js.map +0 -1
- package/dist/mcp/config.d.ts +0 -24
- package/dist/mcp/config.js +0 -273
- package/dist/mcp/config.js.map +0 -1
- package/dist/mcp/constants.d.ts +0 -66
- package/dist/mcp/constants.js +0 -85
- package/dist/mcp/constants.js.map +0 -1
- package/dist/mcp/content-length-transport.d.ts +0 -106
- package/dist/mcp/content-length-transport.js +0 -413
- package/dist/mcp/content-length-transport.js.map +0 -1
- package/dist/mcp/debug.d.ts +0 -211
- package/dist/mcp/debug.js +0 -404
- package/dist/mcp/debug.js.map +0 -1
- package/dist/mcp/error-formatter.d.ts +0 -40
- package/dist/mcp/error-formatter.js +0 -207
- package/dist/mcp/error-formatter.js.map +0 -1
- package/dist/mcp/error-remediation.d.ts +0 -45
- package/dist/mcp/error-remediation.js +0 -291
- package/dist/mcp/error-remediation.js.map +0 -1
- package/dist/mcp/health.d.ts +0 -120
- package/dist/mcp/health.js +0 -267
- package/dist/mcp/health.js.map +0 -1
- package/dist/mcp/index.d.ts +0 -56
- package/dist/mcp/index.js +0 -89
- package/dist/mcp/index.js.map +0 -1
- package/dist/mcp/invariants.d.ts +0 -141
- package/dist/mcp/invariants.js +0 -243
- package/dist/mcp/invariants.js.map +0 -1
- package/dist/mcp/mutex-safe.d.ts +0 -151
- package/dist/mcp/mutex-safe.js +0 -260
- package/dist/mcp/mutex-safe.js.map +0 -1
- package/dist/mcp/progress.d.ts +0 -155
- package/dist/mcp/progress.js +0 -252
- package/dist/mcp/progress.js.map +0 -1
- package/dist/mcp/prompts.d.ts +0 -68
- package/dist/mcp/prompts.js +0 -129
- package/dist/mcp/prompts.js.map +0 -1
- package/dist/mcp/provider-mcp-loader.d.ts +0 -130
- package/dist/mcp/provider-mcp-loader.js +0 -292
- package/dist/mcp/provider-mcp-loader.js.map +0 -1
- package/dist/mcp/reconnection.d.ts +0 -101
- package/dist/mcp/reconnection.js +0 -253
- package/dist/mcp/reconnection.js.map +0 -1
- package/dist/mcp/registry.d.ts +0 -75
- package/dist/mcp/registry.js +0 -276
- package/dist/mcp/registry.js.map +0 -1
- package/dist/mcp/resources.d.ts +0 -58
- package/dist/mcp/resources.js +0 -144
- package/dist/mcp/resources.js.map +0 -1
- package/dist/mcp/schema-validator.d.ts +0 -82
- package/dist/mcp/schema-validator.js +0 -161
- package/dist/mcp/schema-validator.js.map +0 -1
- package/dist/mcp/ssrf-protection.d.ts +0 -86
- package/dist/mcp/ssrf-protection.js +0 -311
- package/dist/mcp/ssrf-protection.js.map +0 -1
- package/dist/mcp/subscriptions.d.ts +0 -168
- package/dist/mcp/subscriptions.js +0 -248
- package/dist/mcp/subscriptions.js.map +0 -1
- package/dist/mcp/templates.d.ts +0 -52
- package/dist/mcp/templates.js +0 -627
- package/dist/mcp/templates.js.map +0 -1
- package/dist/mcp/transports.d.ts +0 -80
- package/dist/mcp/transports.js +0 -237
- package/dist/mcp/transports.js.map +0 -1
- package/dist/mcp/type-safety.d.ts +0 -225
- package/dist/mcp/type-safety.js +0 -237
- package/dist/mcp/type-safety.js.map +0 -1
- package/dist/mcp/validation.d.ts +0 -29
- package/dist/mcp/validation.js +0 -339
- package/dist/mcp/validation.js.map +0 -1
- package/dist/mcp/zai-detector.d.ts +0 -63
- package/dist/mcp/zai-detector.js +0 -193
- package/dist/mcp/zai-detector.js.map +0 -1
- package/dist/mcp/zai-templates.d.ts +0 -90
- package/dist/mcp/zai-templates.js +0 -157
- package/dist/mcp/zai-templates.js.map +0 -1
- package/dist/memory/context-generator.d.ts +0 -84
- package/dist/memory/context-generator.js +0 -546
- package/dist/memory/context-generator.js.map +0 -1
- package/dist/memory/context-injector.d.ts +0 -97
- package/dist/memory/context-injector.js +0 -159
- package/dist/memory/context-injector.js.map +0 -1
- package/dist/memory/context-store.d.ts +0 -103
- package/dist/memory/context-store.js +0 -264
- package/dist/memory/context-store.js.map +0 -1
- package/dist/memory/index.d.ts +0 -43
- package/dist/memory/index.js +0 -49
- package/dist/memory/index.js.map +0 -1
- package/dist/memory/provider-context-store.d.ts +0 -127
- package/dist/memory/provider-context-store.js +0 -385
- package/dist/memory/provider-context-store.js.map +0 -1
- package/dist/memory/schemas.d.ts +0 -118
- package/dist/memory/schemas.js +0 -106
- package/dist/memory/schemas.js.map +0 -1
- package/dist/memory/stats-collector.d.ts +0 -73
- package/dist/memory/stats-collector.js +0 -170
- package/dist/memory/stats-collector.js.map +0 -1
- package/dist/memory/types.d.ts +0 -177
- package/dist/memory/types.js +0 -73
- package/dist/memory/types.js.map +0 -1
- package/dist/permissions/index.d.ts +0 -6
- package/dist/permissions/index.js +0 -7
- package/dist/permissions/index.js.map +0 -1
- package/dist/permissions/permission-manager.d.ts +0 -149
- package/dist/permissions/permission-manager.js +0 -410
- package/dist/permissions/permission-manager.js.map +0 -1
- package/dist/planner/dependency-resolver.d.ts +0 -72
- package/dist/planner/dependency-resolver.js +0 -272
- package/dist/planner/dependency-resolver.js.map +0 -1
- package/dist/planner/index.d.ts +0 -12
- package/dist/planner/index.js +0 -28
- package/dist/planner/index.js.map +0 -1
- package/dist/planner/plan-generator.d.ts +0 -74
- package/dist/planner/plan-generator.js +0 -244
- package/dist/planner/plan-generator.js.map +0 -1
- package/dist/planner/plan-storage.d.ts +0 -113
- package/dist/planner/plan-storage.js +0 -398
- package/dist/planner/plan-storage.js.map +0 -1
- package/dist/planner/prompts/planning-prompt.d.ts +0 -62
- package/dist/planner/prompts/planning-prompt.js +0 -414
- package/dist/planner/prompts/planning-prompt.js.map +0 -1
- package/dist/planner/task-planner.d.ts +0 -139
- package/dist/planner/task-planner.js +0 -532
- package/dist/planner/task-planner.js.map +0 -1
- package/dist/planner/token-estimator.d.ts +0 -63
- package/dist/planner/token-estimator.js +0 -295
- package/dist/planner/token-estimator.js.map +0 -1
- package/dist/planner/types.d.ts +0 -425
- package/dist/planner/types.js +0 -213
- package/dist/planner/types.js.map +0 -1
- package/dist/provider/config.d.ts +0 -227
- package/dist/provider/config.js +0 -430
- package/dist/provider/config.js.map +0 -1
- package/dist/schemas/api-schemas.d.ts +0 -45
- package/dist/schemas/api-schemas.js +0 -129
- package/dist/schemas/api-schemas.js.map +0 -1
- package/dist/schemas/confirmation-schemas.d.ts +0 -39
- package/dist/schemas/confirmation-schemas.js +0 -48
- package/dist/schemas/confirmation-schemas.js.map +0 -1
- package/dist/schemas/index-unified.d.ts +0 -12
- package/dist/schemas/index-unified.js +0 -17
- package/dist/schemas/index-unified.js.map +0 -1
- package/dist/schemas/index.d.ts +0 -83
- package/dist/schemas/index.js +0 -139
- package/dist/schemas/index.js.map +0 -1
- package/dist/schemas/settings-schemas.d.ts +0 -186
- package/dist/schemas/settings-schemas.js +0 -324
- package/dist/schemas/settings-schemas.js.map +0 -1
- package/dist/schemas/tool-schemas.d.ts +0 -127
- package/dist/schemas/tool-schemas.js +0 -84
- package/dist/schemas/tool-schemas.js.map +0 -1
- package/dist/schemas/yaml-schemas.d.ts +0 -231
- package/dist/schemas/yaml-schemas.js +0 -199
- package/dist/schemas/yaml-schemas.js.map +0 -1
- package/dist/sdk/errors.d.ts +0 -100
- package/dist/sdk/errors.js +0 -138
- package/dist/sdk/errors.js.map +0 -1
- package/dist/sdk/index.d.ts +0 -901
- package/dist/sdk/index.js +0 -1272
- package/dist/sdk/index.js.map +0 -1
- package/dist/sdk/progress-reporter.d.ts +0 -123
- package/dist/sdk/progress-reporter.js +0 -220
- package/dist/sdk/progress-reporter.js.map +0 -1
- package/dist/sdk/testing.d.ts +0 -427
- package/dist/sdk/testing.js +0 -725
- package/dist/sdk/testing.js.map +0 -1
- package/dist/sdk/tool-registry.d.ts +0 -194
- package/dist/sdk/tool-registry.js +0 -326
- package/dist/sdk/tool-registry.js.map +0 -1
- package/dist/sdk/types.d.ts +0 -53
- package/dist/sdk/types.js +0 -8
- package/dist/sdk/types.js.map +0 -1
- package/dist/sdk/unified-logger.d.ts +0 -173
- package/dist/sdk/unified-logger.js +0 -327
- package/dist/sdk/unified-logger.js.map +0 -1
- package/dist/sdk/version.d.ts +0 -163
- package/dist/sdk/version.js +0 -205
- package/dist/sdk/version.js.map +0 -1
- package/dist/tools/ask-user.d.ts +0 -126
- package/dist/tools/ask-user.js +0 -290
- package/dist/tools/ask-user.js.map +0 -1
- package/dist/tools/ax-agent.d.ts +0 -71
- package/dist/tools/ax-agent.js +0 -283
- package/dist/tools/ax-agent.js.map +0 -1
- package/dist/tools/bash-output.d.ts +0 -25
- package/dist/tools/bash-output.js +0 -146
- package/dist/tools/bash-output.js.map +0 -1
- package/dist/tools/bash.d.ts +0 -67
- package/dist/tools/bash.js +0 -522
- package/dist/tools/bash.js.map +0 -1
- package/dist/tools/confirmation-tool.d.ts +0 -16
- package/dist/tools/confirmation-tool.js +0 -76
- package/dist/tools/confirmation-tool.js.map +0 -1
- package/dist/tools/definitions/ask-user.d.ts +0 -8
- package/dist/tools/definitions/ask-user.js +0 -168
- package/dist/tools/definitions/ask-user.js.map +0 -1
- package/dist/tools/definitions/ax-agent.d.ts +0 -8
- package/dist/tools/definitions/ax-agent.js +0 -276
- package/dist/tools/definitions/ax-agent.js.map +0 -1
- package/dist/tools/definitions/bash-output.d.ts +0 -7
- package/dist/tools/definitions/bash-output.js +0 -78
- package/dist/tools/definitions/bash-output.js.map +0 -1
- package/dist/tools/definitions/bash.d.ts +0 -8
- package/dist/tools/definitions/bash.js +0 -152
- package/dist/tools/definitions/bash.js.map +0 -1
- package/dist/tools/definitions/create-file.d.ts +0 -7
- package/dist/tools/definitions/create-file.js +0 -129
- package/dist/tools/definitions/create-file.js.map +0 -1
- package/dist/tools/definitions/design.d.ts +0 -12
- package/dist/tools/definitions/design.js +0 -368
- package/dist/tools/definitions/design.js.map +0 -1
- package/dist/tools/definitions/index.d.ts +0 -49
- package/dist/tools/definitions/index.js +0 -87
- package/dist/tools/definitions/index.js.map +0 -1
- package/dist/tools/definitions/multi-edit.d.ts +0 -7
- package/dist/tools/definitions/multi-edit.js +0 -123
- package/dist/tools/definitions/multi-edit.js.map +0 -1
- package/dist/tools/definitions/search.d.ts +0 -7
- package/dist/tools/definitions/search.js +0 -159
- package/dist/tools/definitions/search.js.map +0 -1
- package/dist/tools/definitions/str-replace-editor.d.ts +0 -7
- package/dist/tools/definitions/str-replace-editor.js +0 -145
- package/dist/tools/definitions/str-replace-editor.js.map +0 -1
- package/dist/tools/definitions/todo.d.ts +0 -8
- package/dist/tools/definitions/todo.js +0 -261
- package/dist/tools/definitions/todo.js.map +0 -1
- package/dist/tools/definitions/view-file.d.ts +0 -7
- package/dist/tools/definitions/view-file.js +0 -111
- package/dist/tools/definitions/view-file.js.map +0 -1
- package/dist/tools/design-tool.d.ts +0 -68
- package/dist/tools/design-tool.js +0 -299
- package/dist/tools/design-tool.js.map +0 -1
- package/dist/tools/format-generators.d.ts +0 -62
- package/dist/tools/format-generators.js +0 -291
- package/dist/tools/format-generators.js.map +0 -1
- package/dist/tools/index.d.ts +0 -8
- package/dist/tools/index.js +0 -11
- package/dist/tools/index.js.map +0 -1
- package/dist/tools/priority-registry.d.ts +0 -124
- package/dist/tools/priority-registry.js +0 -401
- package/dist/tools/priority-registry.js.map +0 -1
- package/dist/tools/priority.d.ts +0 -158
- package/dist/tools/priority.js +0 -350
- package/dist/tools/priority.js.map +0 -1
- package/dist/tools/registry.d.ts +0 -146
- package/dist/tools/registry.js +0 -171
- package/dist/tools/registry.js.map +0 -1
- package/dist/tools/search.d.ts +0 -85
- package/dist/tools/search.js +0 -430
- package/dist/tools/search.js.map +0 -1
- package/dist/tools/text-editor.d.ts +0 -87
- package/dist/tools/text-editor.js +0 -1369
- package/dist/tools/text-editor.js.map +0 -1
- package/dist/tools/todo-tool.d.ts +0 -20
- package/dist/tools/todo-tool.js +0 -186
- package/dist/tools/todo-tool.js.map +0 -1
- package/dist/tools/types.d.ts +0 -175
- package/dist/tools/types.js +0 -11
- package/dist/tools/types.js.map +0 -1
- package/dist/types/index.d.ts +0 -30
- package/dist/types/index.js +0 -2
- package/dist/types/index.js.map +0 -1
- package/dist/types/project-analysis.d.ts +0 -84
- package/dist/types/project-analysis.js +0 -5
- package/dist/types/project-analysis.js.map +0 -1
- package/dist/types/template.d.ts +0 -53
- package/dist/types/template.js +0 -5
- package/dist/types/template.js.map +0 -1
- package/dist/ui/app.d.ts +0 -7
- package/dist/ui/app.js +0 -102
- package/dist/ui/app.js.map +0 -1
- package/dist/ui/components/api-key-input.d.ts +0 -7
- package/dist/ui/components/api-key-input.js +0 -92
- package/dist/ui/components/api-key-input.js.map +0 -1
- package/dist/ui/components/chat-history.d.ts +0 -12
- package/dist/ui/components/chat-history.js +0 -391
- package/dist/ui/components/chat-history.js.map +0 -1
- package/dist/ui/components/chat-input.d.ts +0 -13
- package/dist/ui/components/chat-input.js +0 -179
- package/dist/ui/components/chat-input.js.map +0 -1
- package/dist/ui/components/chat-interface.d.ts +0 -11
- package/dist/ui/components/chat-interface.js +0 -830
- package/dist/ui/components/chat-interface.js.map +0 -1
- package/dist/ui/components/collapsible-tool-result.d.ts +0 -42
- package/dist/ui/components/collapsible-tool-result.js +0 -216
- package/dist/ui/components/collapsible-tool-result.js.map +0 -1
- package/dist/ui/components/command-suggestions.d.ts +0 -29
- package/dist/ui/components/command-suggestions.js +0 -88
- package/dist/ui/components/command-suggestions.js.map +0 -1
- package/dist/ui/components/confirmation-dialog.d.ts +0 -11
- package/dist/ui/components/confirmation-dialog.js +0 -100
- package/dist/ui/components/confirmation-dialog.js.map +0 -1
- package/dist/ui/components/context-breakdown.d.ts +0 -23
- package/dist/ui/components/context-breakdown.js +0 -124
- package/dist/ui/components/context-breakdown.js.map +0 -1
- package/dist/ui/components/diff-renderer.d.ts +0 -13
- package/dist/ui/components/diff-renderer.js +0 -192
- package/dist/ui/components/diff-renderer.js.map +0 -1
- package/dist/ui/components/index.d.ts +0 -18
- package/dist/ui/components/index.js +0 -20
- package/dist/ui/components/index.js.map +0 -1
- package/dist/ui/components/keyboard-help.d.ts +0 -17
- package/dist/ui/components/keyboard-help.js +0 -122
- package/dist/ui/components/keyboard-help.js.map +0 -1
- package/dist/ui/components/keyboard-hints.d.ts +0 -35
- package/dist/ui/components/keyboard-hints.js +0 -142
- package/dist/ui/components/keyboard-hints.js.map +0 -1
- package/dist/ui/components/loading-spinner.d.ts +0 -9
- package/dist/ui/components/loading-spinner.js +0 -120
- package/dist/ui/components/loading-spinner.js.map +0 -1
- package/dist/ui/components/mcp-dashboard.d.ts +0 -15
- package/dist/ui/components/mcp-dashboard.js +0 -520
- package/dist/ui/components/mcp-dashboard.js.map +0 -1
- package/dist/ui/components/mcp-status.d.ts +0 -5
- package/dist/ui/components/mcp-status.js +0 -58
- package/dist/ui/components/mcp-status.js.map +0 -1
- package/dist/ui/components/model-selection.d.ts +0 -12
- package/dist/ui/components/model-selection.js +0 -17
- package/dist/ui/components/model-selection.js.map +0 -1
- package/dist/ui/components/phase-progress.d.ts +0 -21
- package/dist/ui/components/phase-progress.js +0 -185
- package/dist/ui/components/phase-progress.js.map +0 -1
- package/dist/ui/components/question-dialog.d.ts +0 -17
- package/dist/ui/components/question-dialog.js +0 -181
- package/dist/ui/components/question-dialog.js.map +0 -1
- package/dist/ui/components/quick-actions.d.ts +0 -12
- package/dist/ui/components/quick-actions.js +0 -171
- package/dist/ui/components/quick-actions.js.map +0 -1
- package/dist/ui/components/reasoning-display.d.ts +0 -36
- package/dist/ui/components/reasoning-display.js +0 -46
- package/dist/ui/components/reasoning-display.js.map +0 -1
- package/dist/ui/components/status-bar.d.ts +0 -47
- package/dist/ui/components/status-bar.js +0 -310
- package/dist/ui/components/status-bar.js.map +0 -1
- package/dist/ui/components/subagent-monitor.d.ts +0 -41
- package/dist/ui/components/subagent-monitor.js +0 -122
- package/dist/ui/components/subagent-monitor.js.map +0 -1
- package/dist/ui/components/toast-notification.d.ts +0 -197
- package/dist/ui/components/toast-notification.js +0 -190
- package/dist/ui/components/toast-notification.js.map +0 -1
- package/dist/ui/components/tool-group-display.d.ts +0 -19
- package/dist/ui/components/tool-group-display.js +0 -222
- package/dist/ui/components/tool-group-display.js.map +0 -1
- package/dist/ui/components/virtualized-chat-history.d.ts +0 -33
- package/dist/ui/components/virtualized-chat-history.js +0 -182
- package/dist/ui/components/virtualized-chat-history.js.map +0 -1
- package/dist/ui/components/welcome-panel.d.ts +0 -11
- package/dist/ui/components/welcome-panel.js +0 -225
- package/dist/ui/components/welcome-panel.js.map +0 -1
- package/dist/ui/hooks/use-chat-reducer.d.ts +0 -69
- package/dist/ui/hooks/use-chat-reducer.js +0 -118
- package/dist/ui/hooks/use-chat-reducer.js.map +0 -1
- package/dist/ui/hooks/use-enhanced-input.d.ts +0 -53
- package/dist/ui/hooks/use-enhanced-input.js +0 -1275
- package/dist/ui/hooks/use-enhanced-input.js.map +0 -1
- package/dist/ui/hooks/use-input-handler.d.ts +0 -79
- package/dist/ui/hooks/use-input-handler.js +0 -2251
- package/dist/ui/hooks/use-input-handler.js.map +0 -1
- package/dist/ui/hooks/use-input-history.d.ts +0 -9
- package/dist/ui/hooks/use-input-history.js +0 -168
- package/dist/ui/hooks/use-input-history.js.map +0 -1
- package/dist/ui/shared/max-sized-box.d.ts +0 -17
- package/dist/ui/shared/max-sized-box.js +0 -14
- package/dist/ui/shared/max-sized-box.js.map +0 -1
- package/dist/ui/themes/index.d.ts +0 -5
- package/dist/ui/themes/index.js +0 -5
- package/dist/ui/themes/index.js.map +0 -1
- package/dist/ui/themes/theme-registry.d.ts +0 -55
- package/dist/ui/themes/theme-registry.js +0 -202
- package/dist/ui/themes/theme-registry.js.map +0 -1
- package/dist/ui/utils/bracketed-paste-handler.d.ts +0 -97
- package/dist/ui/utils/bracketed-paste-handler.js +0 -322
- package/dist/ui/utils/bracketed-paste-handler.js.map +0 -1
- package/dist/ui/utils/change-summarizer.d.ts +0 -20
- package/dist/ui/utils/change-summarizer.js +0 -282
- package/dist/ui/utils/change-summarizer.js.map +0 -1
- package/dist/ui/utils/code-colorizer.d.ts +0 -9
- package/dist/ui/utils/code-colorizer.js +0 -13
- package/dist/ui/utils/code-colorizer.js.map +0 -1
- package/dist/ui/utils/colors.d.ts +0 -41
- package/dist/ui/utils/colors.js +0 -80
- package/dist/ui/utils/colors.js.map +0 -1
- package/dist/ui/utils/image-handler.d.ts +0 -29
- package/dist/ui/utils/image-handler.js +0 -129
- package/dist/ui/utils/image-handler.js.map +0 -1
- package/dist/ui/utils/markdown-renderer.d.ts +0 -4
- package/dist/ui/utils/markdown-renderer.js +0 -40
- package/dist/ui/utils/markdown-renderer.js.map +0 -1
- package/dist/ui/utils/semantic-action-detector.d.ts +0 -49
- package/dist/ui/utils/semantic-action-detector.js +0 -339
- package/dist/ui/utils/semantic-action-detector.js.map +0 -1
- package/dist/ui/utils/tool-grouper.d.ts +0 -94
- package/dist/ui/utils/tool-grouper.js +0 -618
- package/dist/ui/utils/tool-grouper.js.map +0 -1
- package/dist/utils/api-error.d.ts +0 -61
- package/dist/utils/api-error.js +0 -176
- package/dist/utils/api-error.js.map +0 -1
- package/dist/utils/audit-logger.d.ts +0 -206
- package/dist/utils/audit-logger.js +0 -286
- package/dist/utils/audit-logger.js.map +0 -1
- package/dist/utils/auto-accept-logger.d.ts +0 -175
- package/dist/utils/auto-accept-logger.js +0 -423
- package/dist/utils/auto-accept-logger.js.map +0 -1
- package/dist/utils/automatosx-detector.d.ts +0 -19
- package/dist/utils/automatosx-detector.js +0 -52
- package/dist/utils/automatosx-detector.js.map +0 -1
- package/dist/utils/background-task-manager.d.ts +0 -114
- package/dist/utils/background-task-manager.js +0 -470
- package/dist/utils/background-task-manager.js.map +0 -1
- package/dist/utils/cache.d.ts +0 -77
- package/dist/utils/cache.js +0 -180
- package/dist/utils/cache.js.map +0 -1
- package/dist/utils/command-security.d.ts +0 -85
- package/dist/utils/command-security.js +0 -210
- package/dist/utils/command-security.js.map +0 -1
- package/dist/utils/config-loader.d.ts +0 -190
- package/dist/utils/config-loader.js +0 -108
- package/dist/utils/config-loader.js.map +0 -1
- package/dist/utils/confirmation-service.d.ts +0 -51
- package/dist/utils/confirmation-service.js +0 -220
- package/dist/utils/confirmation-service.js.map +0 -1
- package/dist/utils/console-messenger.d.ts +0 -80
- package/dist/utils/console-messenger.js +0 -142
- package/dist/utils/console-messenger.js.map +0 -1
- package/dist/utils/custom-instructions.d.ts +0 -1
- package/dist/utils/custom-instructions.js +0 -24
- package/dist/utils/custom-instructions.js.map +0 -1
- package/dist/utils/encryption.d.ts +0 -86
- package/dist/utils/encryption.js +0 -236
- package/dist/utils/encryption.js.map +0 -1
- package/dist/utils/enhanced-error-messages.d.ts +0 -33
- package/dist/utils/enhanced-error-messages.js +0 -440
- package/dist/utils/enhanced-error-messages.js.map +0 -1
- package/dist/utils/error-handler.d.ts +0 -65
- package/dist/utils/error-handler.js +0 -148
- package/dist/utils/error-handler.js.map +0 -1
- package/dist/utils/error-translator.d.ts +0 -25
- package/dist/utils/error-translator.js +0 -203
- package/dist/utils/error-translator.js.map +0 -1
- package/dist/utils/external-editor.d.ts +0 -47
- package/dist/utils/external-editor.js +0 -179
- package/dist/utils/external-editor.js.map +0 -1
- package/dist/utils/file-cache.d.ts +0 -148
- package/dist/utils/file-cache.js +0 -413
- package/dist/utils/file-cache.js.map +0 -1
- package/dist/utils/file-lock.d.ts +0 -141
- package/dist/utils/file-lock.js +0 -554
- package/dist/utils/file-lock.js.map +0 -1
- package/dist/utils/file-mentions.d.ts +0 -68
- package/dist/utils/file-mentions.js +0 -225
- package/dist/utils/file-mentions.js.map +0 -1
- package/dist/utils/history-manager.d.ts +0 -52
- package/dist/utils/history-manager.js +0 -211
- package/dist/utils/history-manager.js.map +0 -1
- package/dist/utils/history-migration.d.ts +0 -9
- package/dist/utils/history-migration.js +0 -37
- package/dist/utils/history-migration.js.map +0 -1
- package/dist/utils/image-processor.d.ts +0 -33
- package/dist/utils/image-processor.js +0 -124
- package/dist/utils/image-processor.js.map +0 -1
- package/dist/utils/index.d.ts +0 -92
- package/dist/utils/index.js +0 -111
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/init-previewer.d.ts +0 -56
- package/dist/utils/init-previewer.js +0 -239
- package/dist/utils/init-previewer.js.map +0 -1
- package/dist/utils/init-validator.d.ts +0 -65
- package/dist/utils/init-validator.js +0 -252
- package/dist/utils/init-validator.js.map +0 -1
- package/dist/utils/input-sanitizer.d.ts +0 -210
- package/dist/utils/input-sanitizer.js +0 -362
- package/dist/utils/input-sanitizer.js.map +0 -1
- package/dist/utils/instruction-generator.d.ts +0 -21
- package/dist/utils/instruction-generator.js +0 -233
- package/dist/utils/instruction-generator.js.map +0 -1
- package/dist/utils/json-utils.d.ts +0 -72
- package/dist/utils/json-utils.js +0 -226
- package/dist/utils/json-utils.js.map +0 -1
- package/dist/utils/llm-optimized-instruction-generator.d.ts +0 -36
- package/dist/utils/llm-optimized-instruction-generator.js +0 -365
- package/dist/utils/llm-optimized-instruction-generator.js.map +0 -1
- package/dist/utils/message-optimizer.d.ts +0 -100
- package/dist/utils/message-optimizer.js +0 -297
- package/dist/utils/message-optimizer.js.map +0 -1
- package/dist/utils/onboarding-manager.d.ts +0 -45
- package/dist/utils/onboarding-manager.js +0 -131
- package/dist/utils/onboarding-manager.js.map +0 -1
- package/dist/utils/parallel-analyzer.d.ts +0 -123
- package/dist/utils/parallel-analyzer.js +0 -241
- package/dist/utils/parallel-analyzer.js.map +0 -1
- package/dist/utils/paste-utils.d.ts +0 -99
- package/dist/utils/paste-utils.js +0 -295
- package/dist/utils/paste-utils.js.map +0 -1
- package/dist/utils/path-helpers.d.ts +0 -8
- package/dist/utils/path-helpers.js +0 -35
- package/dist/utils/path-helpers.js.map +0 -1
- package/dist/utils/path-security.d.ts +0 -92
- package/dist/utils/path-security.js +0 -300
- package/dist/utils/path-security.js.map +0 -1
- package/dist/utils/path-utils.d.ts +0 -83
- package/dist/utils/path-utils.js +0 -122
- package/dist/utils/path-utils.js.map +0 -1
- package/dist/utils/path-validator.d.ts +0 -66
- package/dist/utils/path-validator.js +0 -141
- package/dist/utils/path-validator.js.map +0 -1
- package/dist/utils/performance.d.ts +0 -74
- package/dist/utils/performance.js +0 -133
- package/dist/utils/performance.js.map +0 -1
- package/dist/utils/process-pool.d.ts +0 -109
- package/dist/utils/process-pool.js +0 -332
- package/dist/utils/process-pool.js.map +0 -1
- package/dist/utils/progress-tracker.d.ts +0 -51
- package/dist/utils/progress-tracker.js +0 -152
- package/dist/utils/progress-tracker.js.map +0 -1
- package/dist/utils/project-analyzer.d.ts +0 -49
- package/dist/utils/project-analyzer.js +0 -396
- package/dist/utils/project-analyzer.js.map +0 -1
- package/dist/utils/prompt-builder.d.ts +0 -14
- package/dist/utils/prompt-builder.js +0 -100
- package/dist/utils/prompt-builder.js.map +0 -1
- package/dist/utils/provider-context.d.ts +0 -243
- package/dist/utils/provider-context.js +0 -421
- package/dist/utils/provider-context.js.map +0 -1
- package/dist/utils/provider-file-cache.d.ts +0 -91
- package/dist/utils/provider-file-cache.js +0 -165
- package/dist/utils/provider-file-cache.js.map +0 -1
- package/dist/utils/provider-settings.d.ts +0 -181
- package/dist/utils/provider-settings.js +0 -450
- package/dist/utils/provider-settings.js.map +0 -1
- package/dist/utils/rate-limiter.d.ts +0 -222
- package/dist/utils/rate-limiter.js +0 -338
- package/dist/utils/rate-limiter.js.map +0 -1
- package/dist/utils/retry-helper.d.ts +0 -81
- package/dist/utils/retry-helper.js +0 -244
- package/dist/utils/retry-helper.js.map +0 -1
- package/dist/utils/safety-rules.d.ts +0 -64
- package/dist/utils/safety-rules.js +0 -225
- package/dist/utils/safety-rules.js.map +0 -1
- package/dist/utils/settings-manager.d.ts +0 -256
- package/dist/utils/settings-manager.js +0 -967
- package/dist/utils/settings-manager.js.map +0 -1
- package/dist/utils/setup-validator.d.ts +0 -47
- package/dist/utils/setup-validator.js +0 -304
- package/dist/utils/setup-validator.js.map +0 -1
- package/dist/utils/string-utils.d.ts +0 -19
- package/dist/utils/string-utils.js +0 -28
- package/dist/utils/string-utils.js.map +0 -1
- package/dist/utils/template-manager.d.ts +0 -62
- package/dist/utils/template-manager.js +0 -366
- package/dist/utils/template-manager.js.map +0 -1
- package/dist/utils/text-utils.d.ts +0 -82
- package/dist/utils/text-utils.js +0 -203
- package/dist/utils/text-utils.js.map +0 -1
- package/dist/utils/token-counter.d.ts +0 -76
- package/dist/utils/token-counter.js +0 -231
- package/dist/utils/token-counter.js.map +0 -1
- package/dist/utils/usage-tracker.d.ts +0 -78
- package/dist/utils/usage-tracker.js +0 -126
- package/dist/utils/usage-tracker.js.map +0 -1
- package/dist/utils/version.d.ts +0 -14
- package/dist/utils/version.js +0 -70
- package/dist/utils/version.js.map +0 -1
|
@@ -1,2251 +0,0 @@
|
|
|
1
|
-
import { useState, useMemo, useEffect, useCallback, useRef } from "react";
|
|
2
|
-
import { useInput } from "ink";
|
|
3
|
-
import { ConfirmationService } from "../../utils/confirmation-service.js";
|
|
4
|
-
import { useEnhancedInput } from "./use-enhanced-input.js";
|
|
5
|
-
import { escapeShellArg } from "../../tools/bash.js";
|
|
6
|
-
import { VerbosityLevel, TIMEOUT_CONFIG, FILE_NAMES } from "../../constants.js";
|
|
7
|
-
import { filterCommandSuggestions } from "../components/command-suggestions.js";
|
|
8
|
-
import { getSettingsManager } from "../../utils/settings-manager.js";
|
|
9
|
-
import { ProjectAnalyzer } from "../../utils/project-analyzer.js";
|
|
10
|
-
// Dynamic import is used for LLMOptimizedInstructionGenerator to avoid circular imports
|
|
11
|
-
import { getUsageTracker } from "../../utils/usage-tracker.js";
|
|
12
|
-
import { getActiveProvider, getActiveConfigPaths } from "../../provider/config.js";
|
|
13
|
-
import { getHistoryManager } from "../../utils/history-manager.js";
|
|
14
|
-
import { handleRewindCommand, handleCheckpointsCommand, handleCheckpointCleanCommand } from "../../commands/rewind.js";
|
|
15
|
-
import { handlePlansCommand, handlePlanCommand, handlePhasesCommand, handlePauseCommand, handleResumeCommand, handleSkipPhaseCommand, handleAbandonCommand, handleResumableCommand, } from "../../commands/plan.js";
|
|
16
|
-
import { BashOutputTool } from "../../tools/bash-output.js";
|
|
17
|
-
import { getKeyboardShortcutGuideText } from "../components/keyboard-hints.js";
|
|
18
|
-
import { clearToolGroupCache } from "../utils/tool-grouper.js";
|
|
19
|
-
import { getContextStore, ContextGenerator, getStatsCollector, } from "../../memory/index.js";
|
|
20
|
-
import { openExternalEditor, getPreferredEditor, getEditorDisplayName } from "../../utils/external-editor.js";
|
|
21
|
-
import { extractErrorMessage } from "../../utils/error-handler.js";
|
|
22
|
-
import { getCustomCommandsManager } from "../../commands/custom-commands.js";
|
|
23
|
-
import { getHooksManager } from "../../hooks/index.js";
|
|
24
|
-
import { getMCPPrompts, getMCPManager, getMCPResources } from "../../llm/tools.js";
|
|
25
|
-
import { promptToSlashCommand, parsePromptCommand, formatPromptResult, getPromptDescription } from "../../mcp/prompts.js";
|
|
26
|
-
import { getPermissionManager, PermissionTier } from "../../permissions/permission-manager.js";
|
|
27
|
-
import { parseFileMentions } from "../../utils/file-mentions.js";
|
|
28
|
-
import { parseImageInput, formatAttachmentForDisplay, buildMessageContent } from "../utils/image-handler.js";
|
|
29
|
-
import { routeToAgent } from "../../agent/agent-router.js";
|
|
30
|
-
import { executeAgent } from "../../agent/agent-executor.js";
|
|
31
|
-
import * as fs from "fs";
|
|
32
|
-
import * as path from "path";
|
|
33
|
-
export function useInputHandler({ agent, chatHistory, setChatHistory, setIsProcessing, setIsStreaming, setTokenCount, setProcessingTime, processingStartTime, isProcessing, isStreaming, isConfirmationActive = false, onQuickActionsToggle, onVerboseModeChange, onBackgroundModeChange, onAutoEditModeChange, onTaskMovedToBackground, onOperationInterrupted, onChatCleared, onCopyLastResponse, onMemoryWarmed, onMemoryRefreshed, onCheckpointCreated: _onCheckpointCreated, // Reserved for future checkpoint UI
|
|
34
|
-
onCheckpointRestored: _onCheckpointRestored, // Reserved for future checkpoint UI
|
|
35
|
-
onLargePaste, onPasteTruncated, onKeyboardHelp, onMcpDashboardToggle, onThinkingModeChange, onEditorOpening, onEditorSuccess, onEditorCancelled, onEditorError, agentFirstDisabled = false, forcedAgent, onAgentSelected, }) {
|
|
36
|
-
const [showCommandSuggestions, setShowCommandSuggestions] = useState(false);
|
|
37
|
-
const [selectedCommandIndex, setSelectedCommandIndex] = useState(0);
|
|
38
|
-
const [resourceSuggestions, setResourceSuggestions] = useState([]);
|
|
39
|
-
const [suggestionMode, setSuggestionMode] = useState("command");
|
|
40
|
-
// BUG FIX: Track current MCP query to prevent race condition with stale async results
|
|
41
|
-
const currentMcpQueryRef = useRef(null);
|
|
42
|
-
const retryTimeoutRef = useRef(null);
|
|
43
|
-
const [autoEditEnabled, setAutoEditEnabled] = useState(() => {
|
|
44
|
-
const confirmationService = ConfirmationService.getInstance();
|
|
45
|
-
const sessionFlags = confirmationService.getSessionFlags();
|
|
46
|
-
// Default to true (auto-edit enabled by default)
|
|
47
|
-
return sessionFlags.allOperations !== undefined ? sessionFlags.allOperations : true;
|
|
48
|
-
});
|
|
49
|
-
const [verboseMode, setVerboseMode] = useState(false); // Legacy boolean for backward compat
|
|
50
|
-
const [verbosityLevel, setVerbosityLevel] = useState(VerbosityLevel.QUIET);
|
|
51
|
-
const [backgroundMode, setBackgroundMode] = useState(false);
|
|
52
|
-
const [thinkingModeEnabled, setThinkingModeEnabled] = useState(true);
|
|
53
|
-
const toggleAutoEditMode = useCallback(() => {
|
|
54
|
-
const newAutoEditState = !autoEditEnabled;
|
|
55
|
-
setAutoEditEnabled(newAutoEditState);
|
|
56
|
-
const confirmationService = ConfirmationService.getInstance();
|
|
57
|
-
if (newAutoEditState) {
|
|
58
|
-
// Enable auto-edit: set all operations to be accepted
|
|
59
|
-
confirmationService.setSessionFlag("allOperations", true);
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
// Disable auto-edit: reset session flags
|
|
63
|
-
confirmationService.resetSession();
|
|
64
|
-
}
|
|
65
|
-
// Notify parent for toast/flash feedback
|
|
66
|
-
onAutoEditModeChange?.(newAutoEditState);
|
|
67
|
-
}, [autoEditEnabled, onAutoEditModeChange]);
|
|
68
|
-
const handleSpecialKey = (key) => {
|
|
69
|
-
// Don't handle input if confirmation dialog is active
|
|
70
|
-
if (isConfirmationActive) {
|
|
71
|
-
return true; // Prevent default handling
|
|
72
|
-
}
|
|
73
|
-
// Handle shift+tab to toggle auto-edit mode
|
|
74
|
-
if (key.shift && key.tab) {
|
|
75
|
-
toggleAutoEditMode();
|
|
76
|
-
return true; // Handled
|
|
77
|
-
}
|
|
78
|
-
// Handle escape key for closing menus
|
|
79
|
-
if (key.escape) {
|
|
80
|
-
if (showCommandSuggestions) {
|
|
81
|
-
setShowCommandSuggestions(false);
|
|
82
|
-
setSelectedCommandIndex(0);
|
|
83
|
-
// Reset resource mode if active
|
|
84
|
-
if (suggestionMode === "resource") {
|
|
85
|
-
setResourceSuggestions([]);
|
|
86
|
-
setSuggestionMode("command");
|
|
87
|
-
}
|
|
88
|
-
return true;
|
|
89
|
-
}
|
|
90
|
-
if (isProcessing || isStreaming) {
|
|
91
|
-
agent.abortCurrentOperation();
|
|
92
|
-
setIsProcessing(false);
|
|
93
|
-
setIsStreaming(false);
|
|
94
|
-
setTokenCount(0);
|
|
95
|
-
setProcessingTime(0);
|
|
96
|
-
processingStartTime.current = 0;
|
|
97
|
-
// Notify parent for toast feedback
|
|
98
|
-
onOperationInterrupted?.();
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
return false; // Let default escape handling work
|
|
102
|
-
}
|
|
103
|
-
// Handle command/resource suggestions navigation
|
|
104
|
-
if (showCommandSuggestions) {
|
|
105
|
-
// Get appropriate suggestions based on mode
|
|
106
|
-
const currentSuggestions = suggestionMode === "resource"
|
|
107
|
-
? resourceSuggestions.map((r) => ({ command: r.reference, description: r.description || r.name }))
|
|
108
|
-
: filterCommandSuggestions(commandSuggestions, input);
|
|
109
|
-
if (currentSuggestions.length === 0) {
|
|
110
|
-
setShowCommandSuggestions(false);
|
|
111
|
-
setSelectedCommandIndex(0);
|
|
112
|
-
return false; // Continue processing
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
if (key.upArrow) {
|
|
116
|
-
setSelectedCommandIndex((prev) => prev === 0 ? currentSuggestions.length - 1 : prev - 1);
|
|
117
|
-
return true;
|
|
118
|
-
}
|
|
119
|
-
if (key.downArrow) {
|
|
120
|
-
setSelectedCommandIndex((prev) => (prev + 1) % currentSuggestions.length);
|
|
121
|
-
return true;
|
|
122
|
-
}
|
|
123
|
-
if (key.tab || key.return) {
|
|
124
|
-
// Check if there are any suggestions available
|
|
125
|
-
if (currentSuggestions.length === 0) {
|
|
126
|
-
return true; // No suggestions, do nothing
|
|
127
|
-
}
|
|
128
|
-
const safeIndex = Math.min(selectedCommandIndex, currentSuggestions.length - 1);
|
|
129
|
-
const selected = currentSuggestions[safeIndex];
|
|
130
|
-
if (suggestionMode === "resource") {
|
|
131
|
-
// Replace @mcp:partial with the full reference
|
|
132
|
-
const mcpMatch = input.match(/@mcp:[^\s]*$/);
|
|
133
|
-
if (mcpMatch) {
|
|
134
|
-
const newInput = input.replace(/@mcp:[^\s]*$/, selected.command + " ");
|
|
135
|
-
setInput(newInput);
|
|
136
|
-
setCursorPosition(newInput.length);
|
|
137
|
-
}
|
|
138
|
-
// Reset resource mode
|
|
139
|
-
setResourceSuggestions([]);
|
|
140
|
-
setSuggestionMode("command");
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
// Command suggestion - replace entire input
|
|
144
|
-
const newInput = selected.command + " ";
|
|
145
|
-
setInput(newInput);
|
|
146
|
-
setCursorPosition(newInput.length);
|
|
147
|
-
}
|
|
148
|
-
setShowCommandSuggestions(false);
|
|
149
|
-
setSelectedCommandIndex(0);
|
|
150
|
-
return true;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return false; // Let default handling proceed
|
|
155
|
-
};
|
|
156
|
-
const handleInputSubmit = async (userInput) => {
|
|
157
|
-
if (userInput === "exit" || userInput === "quit") {
|
|
158
|
-
process.exit(0);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
if (userInput.trim()) {
|
|
162
|
-
const directCommandResult = await handleDirectCommand(userInput);
|
|
163
|
-
if (!directCommandResult) {
|
|
164
|
-
await processUserMessage(userInput);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
const handleInputChange = useCallback((newInput) => {
|
|
169
|
-
// Check for @mcp: resource auto-complete
|
|
170
|
-
const mcpMatch = newInput.match(/@mcp:([^\s]*)$/);
|
|
171
|
-
if (mcpMatch) {
|
|
172
|
-
const query = mcpMatch[1].toLowerCase();
|
|
173
|
-
// BUG FIX: Track current query to prevent race condition
|
|
174
|
-
// If user types faster than async completes, stale results are discarded
|
|
175
|
-
currentMcpQueryRef.current = query;
|
|
176
|
-
// Load resources asynchronously
|
|
177
|
-
getMCPResources().then((resources) => {
|
|
178
|
-
// BUG FIX: Only apply results if query hasn't changed (prevents stale suggestions)
|
|
179
|
-
if (currentMcpQueryRef.current !== query) {
|
|
180
|
-
return; // Query changed, discard stale results
|
|
181
|
-
}
|
|
182
|
-
const filtered = resources.filter((r) => r.reference.toLowerCase().includes(query) ||
|
|
183
|
-
r.name.toLowerCase().includes(query) ||
|
|
184
|
-
(r.description && r.description.toLowerCase().includes(query)));
|
|
185
|
-
setResourceSuggestions(filtered);
|
|
186
|
-
setSuggestionMode("resource");
|
|
187
|
-
setShowCommandSuggestions(true);
|
|
188
|
-
setSelectedCommandIndex(0);
|
|
189
|
-
}).catch(() => {
|
|
190
|
-
// Only clear if this is still the current query
|
|
191
|
-
if (currentMcpQueryRef.current === query) {
|
|
192
|
-
setResourceSuggestions([]);
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
// Reset resource mode if it was active but no longer matches
|
|
198
|
-
// BUG FIX: Also clear the query ref when leaving resource mode
|
|
199
|
-
if (suggestionMode === "resource") {
|
|
200
|
-
currentMcpQueryRef.current = null;
|
|
201
|
-
setResourceSuggestions([]);
|
|
202
|
-
setSuggestionMode("command");
|
|
203
|
-
}
|
|
204
|
-
// Update command suggestions based on input
|
|
205
|
-
if (newInput.startsWith("/")) {
|
|
206
|
-
setShowCommandSuggestions(true);
|
|
207
|
-
setSelectedCommandIndex(0);
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
setShowCommandSuggestions(false);
|
|
211
|
-
setSelectedCommandIndex(0);
|
|
212
|
-
}
|
|
213
|
-
}, [suggestionMode]);
|
|
214
|
-
const handleVerboseToggle = useCallback(() => {
|
|
215
|
-
// Cycle through verbosity levels: QUIET -> CONCISE -> VERBOSE -> QUIET
|
|
216
|
-
setVerbosityLevel((prev) => {
|
|
217
|
-
const nextLevel = (prev + 1) % 3; // Cycle through 0, 1, 2
|
|
218
|
-
// Update legacy verboseMode for backward compatibility
|
|
219
|
-
setVerboseMode(nextLevel === VerbosityLevel.VERBOSE);
|
|
220
|
-
// Notify parent for toast/flash feedback
|
|
221
|
-
onVerboseModeChange?.(nextLevel === VerbosityLevel.VERBOSE);
|
|
222
|
-
return nextLevel;
|
|
223
|
-
});
|
|
224
|
-
}, [onVerboseModeChange]);
|
|
225
|
-
const handleBackgroundModeToggle = useCallback(() => {
|
|
226
|
-
// Check if a bash command is currently executing
|
|
227
|
-
if (agent.isBashExecuting()) {
|
|
228
|
-
const taskId = agent.moveBashToBackground();
|
|
229
|
-
if (taskId) {
|
|
230
|
-
// Notify parent for toast feedback
|
|
231
|
-
onTaskMovedToBackground?.(taskId);
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
// Otherwise toggle background mode preference
|
|
236
|
-
setBackgroundMode((prev) => {
|
|
237
|
-
const newState = !prev;
|
|
238
|
-
// Notify parent for toast/flash feedback instead of polluting chat history
|
|
239
|
-
onBackgroundModeChange?.(newState);
|
|
240
|
-
return newState;
|
|
241
|
-
});
|
|
242
|
-
}, [agent, onBackgroundModeChange, onTaskMovedToBackground]);
|
|
243
|
-
const handleThinkingModeToggle = useCallback(() => {
|
|
244
|
-
setThinkingModeEnabled((prev) => {
|
|
245
|
-
const newState = !prev;
|
|
246
|
-
// Update agent thinking configuration
|
|
247
|
-
if (newState) {
|
|
248
|
-
agent.setThinkingConfig({ type: "enabled" });
|
|
249
|
-
}
|
|
250
|
-
else {
|
|
251
|
-
agent.setThinkingConfig({ type: "disabled" });
|
|
252
|
-
}
|
|
253
|
-
// Notify parent for toast/flash feedback
|
|
254
|
-
onThinkingModeChange?.(newState);
|
|
255
|
-
return newState;
|
|
256
|
-
});
|
|
257
|
-
}, [agent, onThinkingModeChange]);
|
|
258
|
-
const handleExternalEditor = useCallback(async (currentInput) => {
|
|
259
|
-
try {
|
|
260
|
-
// Get editor name for toast notification
|
|
261
|
-
const editor = getPreferredEditor();
|
|
262
|
-
const editorName = getEditorDisplayName(editor);
|
|
263
|
-
// Notify user that editor is opening
|
|
264
|
-
onEditorOpening?.(editorName);
|
|
265
|
-
const result = await openExternalEditor({
|
|
266
|
-
initialContent: currentInput,
|
|
267
|
-
fileExtension: '.md', // Use markdown for syntax highlighting
|
|
268
|
-
});
|
|
269
|
-
if (result.success && result.content) {
|
|
270
|
-
// Successfully edited - return new content
|
|
271
|
-
onEditorSuccess?.();
|
|
272
|
-
return result.content;
|
|
273
|
-
}
|
|
274
|
-
else if (result.cancelled) {
|
|
275
|
-
// User cancelled - no changes
|
|
276
|
-
onEditorCancelled?.();
|
|
277
|
-
return null;
|
|
278
|
-
}
|
|
279
|
-
else {
|
|
280
|
-
// Error occurred
|
|
281
|
-
onEditorError?.(result.error || 'Unknown error');
|
|
282
|
-
return null;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
catch (error) {
|
|
286
|
-
onEditorError?.(error.message || 'Failed to open editor');
|
|
287
|
-
return null;
|
|
288
|
-
}
|
|
289
|
-
}, [onEditorOpening, onEditorSuccess, onEditorCancelled, onEditorError]);
|
|
290
|
-
const { input, cursorPosition, pastedBlocks, currentBlockAtCursor, isPasting, setInput, setCursorPosition, clearInput, resetHistory, handleInput, expandPlaceholdersForSubmit: _expandPlaceholdersForSubmit, // Part of hook interface, reserved for future use
|
|
291
|
-
} = useEnhancedInput({
|
|
292
|
-
onSubmit: handleInputSubmit,
|
|
293
|
-
onSpecialKey: handleSpecialKey,
|
|
294
|
-
onVerboseToggle: handleVerboseToggle,
|
|
295
|
-
onQuickActions: onQuickActionsToggle,
|
|
296
|
-
onBackgroundModeToggle: handleBackgroundModeToggle,
|
|
297
|
-
onCopyLastResponse,
|
|
298
|
-
onThinkingModeToggle: handleThinkingModeToggle,
|
|
299
|
-
onExternalEditor: handleExternalEditor,
|
|
300
|
-
onLargePaste,
|
|
301
|
-
onPasteTruncated,
|
|
302
|
-
onKeyboardHelp,
|
|
303
|
-
disabled: isConfirmationActive,
|
|
304
|
-
projectDir: process.cwd(),
|
|
305
|
-
});
|
|
306
|
-
void _expandPlaceholdersForSubmit; // Suppress unused warning - reserved for future use
|
|
307
|
-
// Hook up the actual input handling
|
|
308
|
-
useInput((inputChar, key) => {
|
|
309
|
-
handleInput(inputChar, key);
|
|
310
|
-
});
|
|
311
|
-
// Update command suggestions when input changes
|
|
312
|
-
useEffect(() => {
|
|
313
|
-
handleInputChange(input);
|
|
314
|
-
}, [input, handleInputChange]);
|
|
315
|
-
// Cleanup retry timeout on unmount
|
|
316
|
-
useEffect(() => {
|
|
317
|
-
return () => {
|
|
318
|
-
if (retryTimeoutRef.current) {
|
|
319
|
-
clearTimeout(retryTimeoutRef.current);
|
|
320
|
-
retryTimeoutRef.current = null; // Clear ref to prevent dangling reference
|
|
321
|
-
}
|
|
322
|
-
};
|
|
323
|
-
}, []);
|
|
324
|
-
// Get custom commands manager
|
|
325
|
-
const customCommandsManager = useMemo(() => getCustomCommandsManager(), []);
|
|
326
|
-
// Build command suggestions including custom commands
|
|
327
|
-
const commandSuggestions = useMemo(() => {
|
|
328
|
-
const builtIn = [
|
|
329
|
-
{ command: "/help", description: "Show help information" },
|
|
330
|
-
{ command: "/shortcuts", description: "Show keyboard shortcuts guide" },
|
|
331
|
-
{ command: "/continue", description: "Continue incomplete response" },
|
|
332
|
-
{ command: "/retry", description: "Re-send the last message" },
|
|
333
|
-
{ command: "/clear", description: "Clear chat history" },
|
|
334
|
-
{ command: "/init", description: "Initialize project with smart analysis" },
|
|
335
|
-
{ command: "/usage", description: "Show API usage statistics" },
|
|
336
|
-
{ command: "/doctor", description: "Run health check diagnostics" },
|
|
337
|
-
{ command: "/mcp", description: "Open MCP server dashboard" },
|
|
338
|
-
{ command: "/permissions", description: "View/manage tool permissions" },
|
|
339
|
-
{ command: "/tasks", description: "List background tasks" },
|
|
340
|
-
{ command: "/task", description: "View output of a background task" },
|
|
341
|
-
{ command: "/kill", description: "Kill a background task" },
|
|
342
|
-
{ command: "/rewind", description: "Rewind to previous checkpoint" },
|
|
343
|
-
{ command: "/checkpoints", description: "List checkpoint statistics" },
|
|
344
|
-
{ command: "/checkpoint-clean", description: "Clean old checkpoints" },
|
|
345
|
-
{ command: "/commit-and-push", description: "AI commit & push to remote" },
|
|
346
|
-
{ command: "/plans", description: "List all task plans" },
|
|
347
|
-
{ command: "/plan", description: "Show current plan details" },
|
|
348
|
-
{ command: "/phases", description: "Show phases of current plan" },
|
|
349
|
-
{ command: "/pause", description: "Pause current plan execution" },
|
|
350
|
-
{ command: "/resume", description: "Resume paused plan" },
|
|
351
|
-
{ command: "/skip", description: "Skip current phase" },
|
|
352
|
-
{ command: "/abandon", description: "Abandon current plan" },
|
|
353
|
-
{ command: "/memory", description: "Show project memory status" },
|
|
354
|
-
{ command: "/memory warmup", description: "Generate project memory" },
|
|
355
|
-
{ command: "/memory refresh", description: "Update project memory" },
|
|
356
|
-
{ command: "/commands", description: "List custom commands" },
|
|
357
|
-
{ command: "/theme", description: "Switch color theme (default, dark, light, dracula, monokai)" },
|
|
358
|
-
{ command: "/exit", description: "Exit the application" },
|
|
359
|
-
];
|
|
360
|
-
// Add custom commands
|
|
361
|
-
const customCmds = customCommandsManager.getAllCommands();
|
|
362
|
-
const customSuggestions = customCmds.map((cmd) => ({
|
|
363
|
-
command: `/${cmd.name}`,
|
|
364
|
-
description: `${cmd.description} [${cmd.scope}]`,
|
|
365
|
-
}));
|
|
366
|
-
// Add MCP prompts as slash commands
|
|
367
|
-
const mcpPrompts = getMCPPrompts();
|
|
368
|
-
const mcpPromptSuggestions = mcpPrompts.map((prompt) => ({
|
|
369
|
-
command: promptToSlashCommand(prompt),
|
|
370
|
-
description: getPromptDescription(prompt),
|
|
371
|
-
}));
|
|
372
|
-
return [...builtIn, ...customSuggestions, ...mcpPromptSuggestions];
|
|
373
|
-
}, [customCommandsManager]);
|
|
374
|
-
// Load models from configuration with fallback to defaults
|
|
375
|
-
const availableModels = useMemo(() => {
|
|
376
|
-
const settingsManager = getSettingsManager();
|
|
377
|
-
const models = settingsManager.getAvailableModels();
|
|
378
|
-
return models.map(m => ({ model: m }));
|
|
379
|
-
}, []);
|
|
380
|
-
const handleDirectCommand = async (input) => {
|
|
381
|
-
const trimmedInput = input.trim();
|
|
382
|
-
if (trimmedInput === "/continue") {
|
|
383
|
-
// Send a shorter, more focused continuation prompt to avoid timeout
|
|
384
|
-
// Using a brief prompt reduces token overhead for large contexts
|
|
385
|
-
const continuePrompt = "Continue from where you left off.";
|
|
386
|
-
// Add user continue command to history (showing the actual command for clarity)
|
|
387
|
-
const userEntry = {
|
|
388
|
-
type: "user",
|
|
389
|
-
content: "/continue",
|
|
390
|
-
timestamp: new Date(),
|
|
391
|
-
};
|
|
392
|
-
setChatHistory((prev) => [...prev, userEntry]);
|
|
393
|
-
// Process through agent
|
|
394
|
-
setIsProcessing(true);
|
|
395
|
-
setIsStreaming(true);
|
|
396
|
-
processingStartTime.current = Date.now();
|
|
397
|
-
// Fire async operation with proper error handling
|
|
398
|
-
(async () => {
|
|
399
|
-
try {
|
|
400
|
-
let streamingEntry = null;
|
|
401
|
-
for await (const chunk of agent.processUserMessageStream(continuePrompt)) {
|
|
402
|
-
switch (chunk.type) {
|
|
403
|
-
case "reasoning":
|
|
404
|
-
if (chunk.reasoningContent) {
|
|
405
|
-
if (!streamingEntry) {
|
|
406
|
-
const newStreamingEntry = {
|
|
407
|
-
type: "assistant",
|
|
408
|
-
content: "",
|
|
409
|
-
timestamp: new Date(),
|
|
410
|
-
isStreaming: true,
|
|
411
|
-
reasoningContent: chunk.reasoningContent,
|
|
412
|
-
isReasoningStreaming: true,
|
|
413
|
-
};
|
|
414
|
-
setChatHistory((prev) => [...prev, newStreamingEntry]);
|
|
415
|
-
streamingEntry = newStreamingEntry;
|
|
416
|
-
}
|
|
417
|
-
else {
|
|
418
|
-
setChatHistory((prev) => prev.map((entry, idx) => idx === prev.length - 1 && entry.isStreaming
|
|
419
|
-
? {
|
|
420
|
-
...entry,
|
|
421
|
-
reasoningContent: (entry.reasoningContent || "") +
|
|
422
|
-
chunk.reasoningContent,
|
|
423
|
-
isReasoningStreaming: true,
|
|
424
|
-
}
|
|
425
|
-
: entry));
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
break;
|
|
429
|
-
case "content":
|
|
430
|
-
if (chunk.content) {
|
|
431
|
-
if (!streamingEntry) {
|
|
432
|
-
const newStreamingEntry = {
|
|
433
|
-
type: "assistant",
|
|
434
|
-
content: chunk.content,
|
|
435
|
-
timestamp: new Date(),
|
|
436
|
-
isStreaming: true,
|
|
437
|
-
};
|
|
438
|
-
setChatHistory((prev) => [...prev, newStreamingEntry]);
|
|
439
|
-
streamingEntry = newStreamingEntry;
|
|
440
|
-
}
|
|
441
|
-
else {
|
|
442
|
-
setChatHistory((prev) => prev.map((entry, idx) => idx === prev.length - 1 && entry.isStreaming
|
|
443
|
-
? {
|
|
444
|
-
...entry,
|
|
445
|
-
content: entry.content + chunk.content,
|
|
446
|
-
isReasoningStreaming: false,
|
|
447
|
-
}
|
|
448
|
-
: entry));
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
break;
|
|
452
|
-
case "token_count":
|
|
453
|
-
if (chunk.tokenCount !== undefined) {
|
|
454
|
-
setTokenCount(chunk.tokenCount);
|
|
455
|
-
}
|
|
456
|
-
break;
|
|
457
|
-
case "tool_calls":
|
|
458
|
-
if (chunk.toolCalls) {
|
|
459
|
-
setChatHistory((prev) => prev.map((entry) => entry.isStreaming
|
|
460
|
-
? {
|
|
461
|
-
...entry,
|
|
462
|
-
isStreaming: false,
|
|
463
|
-
toolCalls: chunk.toolCalls,
|
|
464
|
-
}
|
|
465
|
-
: entry));
|
|
466
|
-
streamingEntry = null;
|
|
467
|
-
chunk.toolCalls.forEach((toolCall) => {
|
|
468
|
-
const toolCallEntry = {
|
|
469
|
-
type: "tool_call",
|
|
470
|
-
content: "Executing...",
|
|
471
|
-
timestamp: new Date(),
|
|
472
|
-
toolCall: toolCall,
|
|
473
|
-
};
|
|
474
|
-
setChatHistory((prev) => [...prev, toolCallEntry]);
|
|
475
|
-
});
|
|
476
|
-
}
|
|
477
|
-
break;
|
|
478
|
-
case "tool_result":
|
|
479
|
-
if (chunk.toolCall && chunk.toolResult) {
|
|
480
|
-
setChatHistory((prev) => prev.map((entry) => {
|
|
481
|
-
if (entry.isStreaming) {
|
|
482
|
-
return { ...entry, isStreaming: false };
|
|
483
|
-
}
|
|
484
|
-
if (entry.type === "tool_call" &&
|
|
485
|
-
entry.toolCall?.id === chunk.toolCall?.id) {
|
|
486
|
-
return {
|
|
487
|
-
...entry,
|
|
488
|
-
type: "tool_result",
|
|
489
|
-
content: chunk.toolResult?.success
|
|
490
|
-
? chunk.toolResult?.output || "Success"
|
|
491
|
-
: chunk.toolResult?.error || "Error occurred",
|
|
492
|
-
toolResult: chunk.toolResult,
|
|
493
|
-
executionDurationMs: chunk.executionDurationMs,
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
return entry;
|
|
497
|
-
}));
|
|
498
|
-
streamingEntry = null;
|
|
499
|
-
}
|
|
500
|
-
break;
|
|
501
|
-
case "done":
|
|
502
|
-
if (streamingEntry) {
|
|
503
|
-
// Calculate response duration
|
|
504
|
-
const durationMs = processingStartTime.current > 0
|
|
505
|
-
? Date.now() - processingStartTime.current
|
|
506
|
-
: undefined;
|
|
507
|
-
setChatHistory((prev) => prev.map((entry) => entry.isStreaming ? { ...entry, isStreaming: false, durationMs } : entry));
|
|
508
|
-
}
|
|
509
|
-
setIsStreaming(false);
|
|
510
|
-
break;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
catch (error) {
|
|
515
|
-
const errorObj = error instanceof Error ? error : new Error(String(error));
|
|
516
|
-
let errorMessage = `Error: ${errorObj.message}`;
|
|
517
|
-
// Provide helpful guidance for timeout errors during /continue
|
|
518
|
-
if (errorObj.message?.includes('timeout')) {
|
|
519
|
-
errorMessage += `\n\n💡 Tip: For very long conversations, try:\n`;
|
|
520
|
-
errorMessage += ` • Use /clear to start fresh and ask a more focused question\n`;
|
|
521
|
-
errorMessage += ` • Break down your request into smaller parts\n`;
|
|
522
|
-
errorMessage += ` • Use --continue flag to start a new session with history`;
|
|
523
|
-
}
|
|
524
|
-
const errorEntry = {
|
|
525
|
-
type: "assistant",
|
|
526
|
-
content: errorMessage,
|
|
527
|
-
timestamp: new Date(),
|
|
528
|
-
};
|
|
529
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
530
|
-
setIsStreaming(false);
|
|
531
|
-
}
|
|
532
|
-
setIsProcessing(false);
|
|
533
|
-
processingStartTime.current = 0;
|
|
534
|
-
})().catch((error) => {
|
|
535
|
-
// Safety net: handle any uncaught errors from the async IIFE
|
|
536
|
-
const errorObj = error instanceof Error ? error : new Error(String(error));
|
|
537
|
-
const errorEntry = {
|
|
538
|
-
type: "assistant",
|
|
539
|
-
content: `Unexpected error: ${errorObj.message}`,
|
|
540
|
-
timestamp: new Date(),
|
|
541
|
-
};
|
|
542
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
543
|
-
setIsStreaming(false);
|
|
544
|
-
setIsProcessing(false);
|
|
545
|
-
processingStartTime.current = 0;
|
|
546
|
-
});
|
|
547
|
-
clearInput();
|
|
548
|
-
resetHistory();
|
|
549
|
-
return true;
|
|
550
|
-
}
|
|
551
|
-
if (trimmedInput === "/retry") {
|
|
552
|
-
// Find the last user message index and re-send it
|
|
553
|
-
// Use findLastIndex instead of reverse().find() + lastIndexOf() to avoid object reference issues
|
|
554
|
-
const lastUserIndex = chatHistory.findLastIndex((entry) => entry.type === "user");
|
|
555
|
-
if (lastUserIndex >= 0 && chatHistory[lastUserIndex]?.content) {
|
|
556
|
-
// Store the message content and history state before clearing
|
|
557
|
-
const messageToRetry = chatHistory[lastUserIndex].content;
|
|
558
|
-
const historyBackup = [...chatHistory];
|
|
559
|
-
// Remove the last user message and any assistant responses after it
|
|
560
|
-
setChatHistory(prev => prev.slice(0, lastUserIndex));
|
|
561
|
-
clearInput();
|
|
562
|
-
// Trigger submit after a brief delay to allow state update
|
|
563
|
-
// Track timeout for cleanup on unmount
|
|
564
|
-
retryTimeoutRef.current = setTimeout(() => {
|
|
565
|
-
retryTimeoutRef.current = null;
|
|
566
|
-
// BUG FIX: Properly handle async errors with explicit Promise chain
|
|
567
|
-
// The catch must be attached immediately to prevent unhandled rejection
|
|
568
|
-
void handleInputSubmit(messageToRetry).catch((error) => {
|
|
569
|
-
// Log error for debugging, then restore history
|
|
570
|
-
if (process.env.DEBUG || process.env.AX_DEBUG) {
|
|
571
|
-
console.error('Retry failed:', error);
|
|
572
|
-
}
|
|
573
|
-
setChatHistory(historyBackup);
|
|
574
|
-
});
|
|
575
|
-
}, 50);
|
|
576
|
-
}
|
|
577
|
-
else {
|
|
578
|
-
clearInput();
|
|
579
|
-
}
|
|
580
|
-
return true;
|
|
581
|
-
}
|
|
582
|
-
if (trimmedInput === "/clear") {
|
|
583
|
-
// Reset chat history
|
|
584
|
-
setChatHistory([]);
|
|
585
|
-
// Clear saved history from disk
|
|
586
|
-
const historyManager = getHistoryManager();
|
|
587
|
-
historyManager.clearHistory();
|
|
588
|
-
// Clear tool grouper cache to prevent memory leaks
|
|
589
|
-
clearToolGroupCache();
|
|
590
|
-
// Reset processing states
|
|
591
|
-
setIsProcessing(false);
|
|
592
|
-
setIsStreaming(false);
|
|
593
|
-
setTokenCount(0);
|
|
594
|
-
setProcessingTime(0);
|
|
595
|
-
processingStartTime.current = 0;
|
|
596
|
-
// Reset confirmation service session flags
|
|
597
|
-
const confirmationService = ConfirmationService.getInstance();
|
|
598
|
-
confirmationService.resetSession();
|
|
599
|
-
// Notify parent for toast feedback
|
|
600
|
-
onChatCleared?.();
|
|
601
|
-
clearInput();
|
|
602
|
-
resetHistory();
|
|
603
|
-
return true;
|
|
604
|
-
}
|
|
605
|
-
if (trimmedInput === "/init") {
|
|
606
|
-
const userEntry = {
|
|
607
|
-
type: "user",
|
|
608
|
-
content: "/init",
|
|
609
|
-
timestamp: new Date(),
|
|
610
|
-
};
|
|
611
|
-
setChatHistory((prev) => [...prev, userEntry]);
|
|
612
|
-
setIsProcessing(true);
|
|
613
|
-
try {
|
|
614
|
-
const projectRoot = process.cwd();
|
|
615
|
-
// Add analysis message
|
|
616
|
-
const analyzingEntry = {
|
|
617
|
-
type: "assistant",
|
|
618
|
-
content: "🔍 Analyzing project with deep analysis (Tier 3)...\n",
|
|
619
|
-
timestamp: new Date(),
|
|
620
|
-
};
|
|
621
|
-
setChatHistory((prev) => [...prev, analyzingEntry]);
|
|
622
|
-
// Get provider-specific config paths
|
|
623
|
-
const activeConfigPaths = getActiveConfigPaths();
|
|
624
|
-
const configDirName = activeConfigPaths.DIR_NAME; // e.g., '.ax-glm' or '.ax-grok'
|
|
625
|
-
const axCliDir = path.join(projectRoot, configDirName);
|
|
626
|
-
const customMdPath = path.join(axCliDir, "CUSTOM.md");
|
|
627
|
-
// Shared project index at root (used by all CLIs)
|
|
628
|
-
const sharedIndexPath = path.join(projectRoot, FILE_NAMES.AX_INDEX_JSON);
|
|
629
|
-
// /init always rebuilds ax.index.json (no --force needed for index)
|
|
630
|
-
// Only CUSTOM.md requires --force to overwrite (use terminal command)
|
|
631
|
-
const customMdExists = fs.existsSync(customMdPath);
|
|
632
|
-
// If CUSTOM.md exists, warn user but still rebuild ax.index.json
|
|
633
|
-
const willSkipCustomMd = customMdExists;
|
|
634
|
-
// Analyze project with deep analysis (Tier 3 - default)
|
|
635
|
-
const analyzer = new ProjectAnalyzer(projectRoot);
|
|
636
|
-
const result = await analyzer.analyze();
|
|
637
|
-
if (!result.success || !result.projectInfo) {
|
|
638
|
-
const errorEntry = {
|
|
639
|
-
type: "assistant",
|
|
640
|
-
content: `❌ Failed to analyze project: ${result.error || "Unknown error"}`,
|
|
641
|
-
timestamp: new Date(),
|
|
642
|
-
};
|
|
643
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
644
|
-
setIsProcessing(false);
|
|
645
|
-
clearInput();
|
|
646
|
-
return true;
|
|
647
|
-
}
|
|
648
|
-
const projectInfo = result.projectInfo;
|
|
649
|
-
// Generate LLM-optimized instructions
|
|
650
|
-
const { LLMOptimizedInstructionGenerator } = await import("../../utils/llm-optimized-instruction-generator.js");
|
|
651
|
-
const generator = new LLMOptimizedInstructionGenerator({
|
|
652
|
-
compressionLevel: "moderate",
|
|
653
|
-
hierarchyEnabled: true,
|
|
654
|
-
criticalRulesCount: 5,
|
|
655
|
-
includeDODONT: true,
|
|
656
|
-
includeTroubleshooting: true,
|
|
657
|
-
});
|
|
658
|
-
const instructions = generator.generateInstructions(projectInfo);
|
|
659
|
-
const index = generator.generateIndex(projectInfo);
|
|
660
|
-
// Create provider-specific directory
|
|
661
|
-
if (!fs.existsSync(axCliDir)) {
|
|
662
|
-
fs.mkdirSync(axCliDir, { recursive: true });
|
|
663
|
-
}
|
|
664
|
-
// Write custom instructions (provider-specific) - only if doesn't exist
|
|
665
|
-
if (!willSkipCustomMd) {
|
|
666
|
-
fs.writeFileSync(customMdPath, instructions, "utf-8");
|
|
667
|
-
}
|
|
668
|
-
// Always write shared project index at root (no --force needed)
|
|
669
|
-
fs.writeFileSync(sharedIndexPath, index, "utf-8");
|
|
670
|
-
// Display success
|
|
671
|
-
const provider = getActiveProvider();
|
|
672
|
-
const cliName = provider.branding.cliName;
|
|
673
|
-
let successMessage = willSkipCustomMd
|
|
674
|
-
? `🔄 Project index rebuilt!\n\n`
|
|
675
|
-
: `🎉 Project initialized successfully!\n\n`;
|
|
676
|
-
successMessage += `📋 Analysis Results:\n`;
|
|
677
|
-
successMessage += ` Name: ${projectInfo.name}\n`;
|
|
678
|
-
successMessage += ` Type: ${projectInfo.projectType}\n`;
|
|
679
|
-
successMessage += ` Language: ${projectInfo.primaryLanguage}\n`;
|
|
680
|
-
if (projectInfo.techStack.length > 0) {
|
|
681
|
-
successMessage += ` Stack: ${projectInfo.techStack.join(", ")}\n`;
|
|
682
|
-
}
|
|
683
|
-
if (result.duration) {
|
|
684
|
-
successMessage += ` Analysis time: ${result.duration}ms\n`;
|
|
685
|
-
}
|
|
686
|
-
successMessage += `\n✅ Rebuilt shared project index: ${sharedIndexPath}\n`;
|
|
687
|
-
if (willSkipCustomMd) {
|
|
688
|
-
successMessage += `⏭️ Skipped CUSTOM.md (already exists): ${customMdPath}\n`;
|
|
689
|
-
successMessage += ` Use '${cliName} init --force' from terminal to regenerate CUSTOM.md\n`;
|
|
690
|
-
}
|
|
691
|
-
else {
|
|
692
|
-
successMessage += `✅ Generated custom instructions: ${customMdPath}\n`;
|
|
693
|
-
}
|
|
694
|
-
successMessage += `\n💡 The ax.index.json is shared by ax-cli, ax-glm, and ax-grok`;
|
|
695
|
-
const successEntry = {
|
|
696
|
-
type: "assistant",
|
|
697
|
-
content: successMessage,
|
|
698
|
-
timestamp: new Date(),
|
|
699
|
-
};
|
|
700
|
-
setChatHistory((prev) => [...prev, successEntry]);
|
|
701
|
-
}
|
|
702
|
-
catch (error) {
|
|
703
|
-
const errorEntry = {
|
|
704
|
-
type: "assistant",
|
|
705
|
-
content: `❌ Error during initialization: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
706
|
-
timestamp: new Date(),
|
|
707
|
-
};
|
|
708
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
709
|
-
}
|
|
710
|
-
setIsProcessing(false);
|
|
711
|
-
clearInput();
|
|
712
|
-
return true;
|
|
713
|
-
}
|
|
714
|
-
if (trimmedInput === "/help") {
|
|
715
|
-
const helpEntry = {
|
|
716
|
-
type: "assistant",
|
|
717
|
-
content: `AX CLI Help:
|
|
718
|
-
|
|
719
|
-
Built-in Commands:
|
|
720
|
-
/continue - Continue incomplete response from where it left off
|
|
721
|
-
/clear - Clear chat history
|
|
722
|
-
/init - Initialize project with smart analysis
|
|
723
|
-
/help - Show this help
|
|
724
|
-
/shortcuts - Show keyboard shortcuts guide
|
|
725
|
-
/usage - Show API usage statistics
|
|
726
|
-
/doctor - Run health check diagnostics
|
|
727
|
-
/mcp - Open MCP server dashboard
|
|
728
|
-
/exit - Exit application
|
|
729
|
-
exit, quit - Exit application
|
|
730
|
-
|
|
731
|
-
Background Task Commands:
|
|
732
|
-
/tasks - List all background tasks
|
|
733
|
-
/task <id> - View output of a background task
|
|
734
|
-
/kill <id> - Kill a running background task
|
|
735
|
-
|
|
736
|
-
Tip: Append ' &' to any bash command to run it in background
|
|
737
|
-
Example: npm run dev &
|
|
738
|
-
|
|
739
|
-
Checkpoint Commands:
|
|
740
|
-
/rewind - Rewind to a previous checkpoint (interactive)
|
|
741
|
-
/checkpoints - Show checkpoint statistics
|
|
742
|
-
/checkpoint-clean - Clean old checkpoints (compress and prune)
|
|
743
|
-
|
|
744
|
-
Plan Commands (Multi-Phase Task Planning):
|
|
745
|
-
/plans - List all task plans
|
|
746
|
-
/plan [id] - Show current or specific plan details
|
|
747
|
-
/phases - Show phases of current plan
|
|
748
|
-
/pause - Pause current plan execution
|
|
749
|
-
/resume [id] - Resume current or specific plan
|
|
750
|
-
/skip - Skip current phase
|
|
751
|
-
/abandon - Abandon current plan
|
|
752
|
-
|
|
753
|
-
Git Commands:
|
|
754
|
-
/commit-and-push - AI-generated commit + push to remote
|
|
755
|
-
|
|
756
|
-
Memory Commands (z.ai GLM-4.6 caching):
|
|
757
|
-
/memory - Show project memory status
|
|
758
|
-
/memory warmup - Generate project memory context
|
|
759
|
-
/memory refresh - Update memory after changes
|
|
760
|
-
|
|
761
|
-
UI Commands:
|
|
762
|
-
/theme - Show current theme and list available themes
|
|
763
|
-
/theme <name> - Switch color theme (default, dark, light, dracula, monokai)
|
|
764
|
-
|
|
765
|
-
Enhanced Input Features:
|
|
766
|
-
↑/↓ Arrow - Navigate command history
|
|
767
|
-
Ctrl+C - Clear input (press twice to exit)
|
|
768
|
-
Ctrl+X - Clear entire input line
|
|
769
|
-
Esc×2 - Clear input (press Escape twice quickly)
|
|
770
|
-
Ctrl+←/→ - Move by word
|
|
771
|
-
Ctrl+A/E - Move to line start/end
|
|
772
|
-
Ctrl+W - Delete word before cursor
|
|
773
|
-
Ctrl+K - Delete to end of line
|
|
774
|
-
Ctrl+U - Delete to start of line
|
|
775
|
-
Ctrl+O - Toggle verbose mode (show full output, default: concise)
|
|
776
|
-
Ctrl+B - Toggle background mode (run all commands in background)
|
|
777
|
-
Ctrl+P - Expand/collapse pasted text at cursor
|
|
778
|
-
Ctrl+Y - Copy last assistant response to clipboard
|
|
779
|
-
Shift+Tab - Toggle auto-edit mode (bypass confirmations)
|
|
780
|
-
1-4 keys - Quick select in confirmation dialogs
|
|
781
|
-
|
|
782
|
-
Paste Handling:
|
|
783
|
-
When you paste 5+ lines, it's automatically collapsed to a preview.
|
|
784
|
-
Position cursor on collapsed text and press Ctrl+P to expand/collapse.
|
|
785
|
-
Full content is always sent to AI (display-only feature).
|
|
786
|
-
|
|
787
|
-
Direct Commands (executed immediately):
|
|
788
|
-
ls [path] - List directory contents
|
|
789
|
-
pwd - Show current directory
|
|
790
|
-
cd <path> - Change directory
|
|
791
|
-
cat <file> - View file contents
|
|
792
|
-
mkdir <dir> - Create directory
|
|
793
|
-
touch <file>- Create empty file
|
|
794
|
-
|
|
795
|
-
Model Configuration:
|
|
796
|
-
Edit ~/.ax-cli/config.json to configure default model and settings
|
|
797
|
-
|
|
798
|
-
For complex operations, just describe what you want in natural language.
|
|
799
|
-
Examples:
|
|
800
|
-
"edit package.json and add a new script"
|
|
801
|
-
"create a new React component called Header"
|
|
802
|
-
"show me all TypeScript files in this project"`,
|
|
803
|
-
timestamp: new Date(),
|
|
804
|
-
};
|
|
805
|
-
setChatHistory((prev) => [...prev, helpEntry]);
|
|
806
|
-
clearInput();
|
|
807
|
-
return true;
|
|
808
|
-
}
|
|
809
|
-
if (trimmedInput === "/shortcuts") {
|
|
810
|
-
const shortcutsEntry = {
|
|
811
|
-
type: "assistant",
|
|
812
|
-
content: getKeyboardShortcutGuideText(),
|
|
813
|
-
timestamp: new Date(),
|
|
814
|
-
};
|
|
815
|
-
setChatHistory((prev) => [...prev, shortcutsEntry]);
|
|
816
|
-
clearInput();
|
|
817
|
-
return true;
|
|
818
|
-
}
|
|
819
|
-
if (trimmedInput === "/usage") {
|
|
820
|
-
const tracker = getUsageTracker();
|
|
821
|
-
const stats = tracker.getSessionStats();
|
|
822
|
-
const provider = getActiveProvider();
|
|
823
|
-
const isGrok = provider.name === 'grok';
|
|
824
|
-
const currentModel = getSettingsManager().getCurrentModel() || provider.defaultModel;
|
|
825
|
-
const providerName = isGrok ? 'xAI (Grok)' : 'Z.AI (GLM)';
|
|
826
|
-
let usageContent = `📊 **API Usage & Limits (${providerName})**\n\n`;
|
|
827
|
-
// Session statistics
|
|
828
|
-
usageContent += "**📱 Current Session:**\n";
|
|
829
|
-
usageContent += ` • Model: ${currentModel}\n`;
|
|
830
|
-
if (stats.totalRequests === 0) {
|
|
831
|
-
usageContent += " No API requests made yet. Ask me something to start tracking!\n";
|
|
832
|
-
}
|
|
833
|
-
else {
|
|
834
|
-
usageContent += ` • Requests: ${stats.totalRequests.toLocaleString()}\n`;
|
|
835
|
-
usageContent += ` • Prompt Tokens: ${stats.totalPromptTokens.toLocaleString()}\n`;
|
|
836
|
-
usageContent += ` • Completion Tokens: ${stats.totalCompletionTokens.toLocaleString()}\n`;
|
|
837
|
-
usageContent += ` • Total Tokens: ${stats.totalTokens.toLocaleString()}\n`;
|
|
838
|
-
if (stats.totalReasoningTokens > 0) {
|
|
839
|
-
usageContent += ` • Reasoning Tokens: ${stats.totalReasoningTokens.toLocaleString()}\n`;
|
|
840
|
-
}
|
|
841
|
-
if (stats.byModel.size > 0) {
|
|
842
|
-
usageContent += `\n **Models Used:**\n`;
|
|
843
|
-
for (const [model, modelStats] of stats.byModel.entries()) {
|
|
844
|
-
usageContent += ` - ${model}: ${modelStats.totalTokens.toLocaleString()} tokens (${modelStats.requests} requests)\n`;
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
if (isGrok) {
|
|
849
|
-
// xAI/Grok account information
|
|
850
|
-
usageContent += `\n**🔑 xAI Account Usage & Limits:**\n`;
|
|
851
|
-
usageContent += ` ⚠️ API does not provide programmatic access to usage data\n`;
|
|
852
|
-
usageContent += `\n **Check your account:**\n`;
|
|
853
|
-
usageContent += ` • Usage Explorer: https://console.x.ai\n`;
|
|
854
|
-
usageContent += ` • Billing & Team: https://console.x.ai/team\n`;
|
|
855
|
-
usageContent += ` • API Keys: https://console.x.ai/api-keys\n`;
|
|
856
|
-
usageContent += `\n**ℹ️ Notes:**\n`;
|
|
857
|
-
usageContent += ` • Usage is tracked in real-time on the xAI console\n`;
|
|
858
|
-
usageContent += ` • Cached input tokens: 75% discount\n`;
|
|
859
|
-
// Grok pricing based on model (Grok-4 only)
|
|
860
|
-
const modelLower = currentModel.toLowerCase();
|
|
861
|
-
if (modelLower.includes('grok-4.1-fast')) {
|
|
862
|
-
usageContent += `\n**💰 Grok 4.1 Fast Pricing:**\n`;
|
|
863
|
-
usageContent += ` • Input: $0.20 per 1M tokens\n`;
|
|
864
|
-
usageContent += ` • Output: $0.50 per 1M tokens\n`;
|
|
865
|
-
}
|
|
866
|
-
else {
|
|
867
|
-
// Grok 4 default pricing
|
|
868
|
-
usageContent += `\n**💰 Grok 4 Pricing:**\n`;
|
|
869
|
-
usageContent += ` • Input: $3.00 per 1M tokens\n`;
|
|
870
|
-
usageContent += ` • Output: $15.00 per 1M tokens\n`;
|
|
871
|
-
usageContent += ` • Cached: $0.75 per 1M tokens\n`;
|
|
872
|
-
}
|
|
873
|
-
if (stats.totalRequests > 0) {
|
|
874
|
-
// Calculate estimated cost based on model
|
|
875
|
-
let inputRate = 3.0, outputRate = 15.0;
|
|
876
|
-
if (modelLower.includes('grok-4.1-fast')) {
|
|
877
|
-
inputRate = 0.20;
|
|
878
|
-
outputRate = 0.50;
|
|
879
|
-
}
|
|
880
|
-
const inputCost = (stats.totalPromptTokens / 1000000) * inputRate;
|
|
881
|
-
const outputCost = (stats.totalCompletionTokens / 1000000) * outputRate;
|
|
882
|
-
const totalCost = inputCost + outputCost;
|
|
883
|
-
usageContent += `\n**💵 Estimated Session Cost:**\n`;
|
|
884
|
-
usageContent += ` • Input: $${inputCost.toFixed(6)} (${stats.totalPromptTokens.toLocaleString()} tokens)\n`;
|
|
885
|
-
usageContent += ` • Output: $${outputCost.toFixed(6)} (${stats.totalCompletionTokens.toLocaleString()} tokens)\n`;
|
|
886
|
-
usageContent += ` • **Total: ~$${totalCost.toFixed(6)}**\n`;
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
else {
|
|
890
|
-
// Z.AI/GLM account information
|
|
891
|
-
usageContent += `\n**🔑 Z.AI Account Usage & Limits:**\n`;
|
|
892
|
-
usageContent += ` ⚠️ API does not provide programmatic access to usage data\n`;
|
|
893
|
-
usageContent += `\n **Check your account:**\n`;
|
|
894
|
-
usageContent += ` • Billing & Usage: https://z.ai/manage-apikey/billing\n`;
|
|
895
|
-
usageContent += ` • Rate Limits: https://z.ai/manage-apikey/rate-limits\n`;
|
|
896
|
-
usageContent += ` • API Keys: https://z.ai/manage-apikey/apikey-list\n`;
|
|
897
|
-
usageContent += `\n**ℹ️ Notes:**\n`;
|
|
898
|
-
usageContent += ` • Billing reflects previous day (n-1) consumption\n`;
|
|
899
|
-
usageContent += ` • Current day usage may not be immediately visible\n`;
|
|
900
|
-
usageContent += ` • Cached content: 1/5 of original price\n`;
|
|
901
|
-
usageContent += `\n**💰 GLM-4.6 Pricing:**\n`;
|
|
902
|
-
usageContent += ` • Input: $2.00 per 1M tokens\n`;
|
|
903
|
-
usageContent += ` • Output: $10.00 per 1M tokens\n`;
|
|
904
|
-
usageContent += ` • Cached: $0.50 per 1M tokens\n`;
|
|
905
|
-
if (stats.totalRequests > 0) {
|
|
906
|
-
// Calculate estimated cost for this session
|
|
907
|
-
const inputCost = (stats.totalPromptTokens / 1000000) * 2.0;
|
|
908
|
-
const outputCost = (stats.totalCompletionTokens / 1000000) * 10.0;
|
|
909
|
-
const totalCost = inputCost + outputCost;
|
|
910
|
-
usageContent += `\n**💵 Estimated Session Cost:**\n`;
|
|
911
|
-
usageContent += ` • Input: $${inputCost.toFixed(6)} (${stats.totalPromptTokens.toLocaleString()} tokens)\n`;
|
|
912
|
-
usageContent += ` • Output: $${outputCost.toFixed(6)} (${stats.totalCompletionTokens.toLocaleString()} tokens)\n`;
|
|
913
|
-
usageContent += ` • **Total: ~$${totalCost.toFixed(6)}**\n`;
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
const usageEntry = {
|
|
917
|
-
type: "assistant",
|
|
918
|
-
content: usageContent,
|
|
919
|
-
timestamp: new Date(),
|
|
920
|
-
};
|
|
921
|
-
setChatHistory((prev) => [...prev, usageEntry]);
|
|
922
|
-
clearInput();
|
|
923
|
-
return true;
|
|
924
|
-
}
|
|
925
|
-
if (trimmedInput === "/doctor") {
|
|
926
|
-
// Run doctor diagnostics
|
|
927
|
-
const doctorContent = "🏥 **Running AX CLI Diagnostics...**\n\n";
|
|
928
|
-
const doctorEntry = {
|
|
929
|
-
type: "assistant",
|
|
930
|
-
content: doctorContent,
|
|
931
|
-
timestamp: new Date(),
|
|
932
|
-
};
|
|
933
|
-
setChatHistory((prev) => [...prev, doctorEntry]);
|
|
934
|
-
// Execute doctor command asynchronously (non-blocking)
|
|
935
|
-
(async () => {
|
|
936
|
-
try {
|
|
937
|
-
const { exec } = await import("child_process");
|
|
938
|
-
const { promisify } = await import("util");
|
|
939
|
-
const execAsync = promisify(exec);
|
|
940
|
-
// Use 'ax-cli doctor' command which will use the globally installed binary
|
|
941
|
-
// This works whether installed globally or linked locally
|
|
942
|
-
// Disable chalk colors (FORCE_COLOR=0) since output goes to markdown
|
|
943
|
-
const { stdout, stderr } = await execAsync("ax-cli doctor", {
|
|
944
|
-
encoding: "utf-8",
|
|
945
|
-
timeout: TIMEOUT_CONFIG.BASH_DEFAULT,
|
|
946
|
-
maxBuffer: 10 * 1024 * 1024, // 10MB buffer
|
|
947
|
-
env: { ...process.env, FORCE_COLOR: "0" },
|
|
948
|
-
});
|
|
949
|
-
// Convert plain text output to markdown with proper emoji indicators
|
|
950
|
-
const output = (stdout || stderr)
|
|
951
|
-
.replace(/✓/g, "✅")
|
|
952
|
-
.replace(/✗/g, "❌")
|
|
953
|
-
.replace(/⚠/g, "⚠️");
|
|
954
|
-
const resultEntry = {
|
|
955
|
-
type: "assistant",
|
|
956
|
-
content: output,
|
|
957
|
-
timestamp: new Date(),
|
|
958
|
-
};
|
|
959
|
-
setChatHistory((prev) => [...prev, resultEntry]);
|
|
960
|
-
}
|
|
961
|
-
catch (error) {
|
|
962
|
-
const errorMessage = extractErrorMessage(error);
|
|
963
|
-
const errorEntry = {
|
|
964
|
-
type: "assistant",
|
|
965
|
-
content: `❌ **Doctor diagnostics failed:**\n\n\`\`\`\n${errorMessage}\n\`\`\``,
|
|
966
|
-
timestamp: new Date(),
|
|
967
|
-
};
|
|
968
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
969
|
-
}
|
|
970
|
-
})();
|
|
971
|
-
clearInput();
|
|
972
|
-
return true;
|
|
973
|
-
}
|
|
974
|
-
// MCP Dashboard command
|
|
975
|
-
if (trimmedInput === "/mcp") {
|
|
976
|
-
if (onMcpDashboardToggle) {
|
|
977
|
-
onMcpDashboardToggle();
|
|
978
|
-
}
|
|
979
|
-
clearInput();
|
|
980
|
-
return true;
|
|
981
|
-
}
|
|
982
|
-
// Permissions management command
|
|
983
|
-
if (trimmedInput === "/permissions" || trimmedInput.startsWith("/permissions ")) {
|
|
984
|
-
const args = trimmedInput.replace("/permissions", "").trim();
|
|
985
|
-
const permManager = getPermissionManager();
|
|
986
|
-
const config = permManager.getConfig();
|
|
987
|
-
if (!args || args === "show" || args === "list") {
|
|
988
|
-
// Show current permissions configuration
|
|
989
|
-
const permissionLines = [
|
|
990
|
-
"**Permission Configuration**\n",
|
|
991
|
-
`Default Tier: **${config.permissions.default_tier}**\n`,
|
|
992
|
-
"\n**Tool Permissions:**\n",
|
|
993
|
-
];
|
|
994
|
-
const tierEmoji = {
|
|
995
|
-
[PermissionTier.AutoApprove]: "✅",
|
|
996
|
-
[PermissionTier.Notify]: "🔔",
|
|
997
|
-
[PermissionTier.Confirm]: "⚠️",
|
|
998
|
-
[PermissionTier.Block]: "🚫",
|
|
999
|
-
};
|
|
1000
|
-
for (const [tool, toolConfig] of Object.entries(config.permissions.tools)) {
|
|
1001
|
-
const emoji = tierEmoji[toolConfig.tier] || "❓";
|
|
1002
|
-
permissionLines.push(`- ${emoji} **${tool}**: ${toolConfig.tier}\n`);
|
|
1003
|
-
}
|
|
1004
|
-
permissionLines.push("\n**Session Settings:**\n");
|
|
1005
|
-
permissionLines.push(`- Allow all bash: ${config.permissions.session_approvals.allow_all_bash ? "Yes" : "No"}\n`);
|
|
1006
|
-
permissionLines.push(`- Trust current directory: ${config.permissions.session_approvals.trust_current_directory ? "Yes" : "No"}\n`);
|
|
1007
|
-
permissionLines.push("\n*Tip: Use `/permissions set <tool> <tier>` to change permissions*\n");
|
|
1008
|
-
permissionLines.push("*Tiers: auto_approve, notify, confirm, block*");
|
|
1009
|
-
const permEntry = {
|
|
1010
|
-
type: "assistant",
|
|
1011
|
-
content: permissionLines.join(""),
|
|
1012
|
-
timestamp: new Date(),
|
|
1013
|
-
};
|
|
1014
|
-
setChatHistory((prev) => [...prev, permEntry]);
|
|
1015
|
-
}
|
|
1016
|
-
else if (args.startsWith("set ")) {
|
|
1017
|
-
// Set permission for a tool
|
|
1018
|
-
const setArgs = args.replace("set ", "").trim().split(/\s+/);
|
|
1019
|
-
if (setArgs.length >= 2) {
|
|
1020
|
-
const [tool, tier] = setArgs;
|
|
1021
|
-
const validTiers = ["auto_approve", "notify", "confirm", "block"];
|
|
1022
|
-
if (!validTiers.includes(tier)) {
|
|
1023
|
-
const errorEntry = {
|
|
1024
|
-
type: "assistant",
|
|
1025
|
-
content: `❌ Invalid tier: "${tier}"\n\nValid tiers are: ${validTiers.join(", ")}`,
|
|
1026
|
-
timestamp: new Date(),
|
|
1027
|
-
};
|
|
1028
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
1029
|
-
}
|
|
1030
|
-
else {
|
|
1031
|
-
// Update the permission
|
|
1032
|
-
const newTools = { ...config.permissions.tools };
|
|
1033
|
-
newTools[tool] = { tier: tier };
|
|
1034
|
-
permManager.updateConfig({ tools: newTools }).then(() => {
|
|
1035
|
-
const successEntry = {
|
|
1036
|
-
type: "assistant",
|
|
1037
|
-
content: `✅ Set **${tool}** permission to **${tier}**`,
|
|
1038
|
-
timestamp: new Date(),
|
|
1039
|
-
};
|
|
1040
|
-
setChatHistory((prev) => [...prev, successEntry]);
|
|
1041
|
-
}).catch((error) => {
|
|
1042
|
-
const errorEntry = {
|
|
1043
|
-
type: "assistant",
|
|
1044
|
-
content: `❌ Failed to update permission: ${extractErrorMessage(error)}`,
|
|
1045
|
-
timestamp: new Date(),
|
|
1046
|
-
};
|
|
1047
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
1048
|
-
});
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
else {
|
|
1052
|
-
const helpEntry = {
|
|
1053
|
-
type: "assistant",
|
|
1054
|
-
content: "Usage: `/permissions set <tool> <tier>`\n\nExample: `/permissions set bash confirm`",
|
|
1055
|
-
timestamp: new Date(),
|
|
1056
|
-
};
|
|
1057
|
-
setChatHistory((prev) => [...prev, helpEntry]);
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
else if (args === "reset") {
|
|
1061
|
-
// Reset to default permissions
|
|
1062
|
-
permManager.clearSessionApprovals();
|
|
1063
|
-
const resetEntry = {
|
|
1064
|
-
type: "assistant",
|
|
1065
|
-
content: "✅ Session permissions cleared. Tool permissions reset to defaults.",
|
|
1066
|
-
timestamp: new Date(),
|
|
1067
|
-
};
|
|
1068
|
-
setChatHistory((prev) => [...prev, resetEntry]);
|
|
1069
|
-
}
|
|
1070
|
-
else {
|
|
1071
|
-
// Show help
|
|
1072
|
-
const helpEntry = {
|
|
1073
|
-
type: "assistant",
|
|
1074
|
-
content: "**Permission Commands:**\n\n" +
|
|
1075
|
-
"- `/permissions` - Show current permissions\n" +
|
|
1076
|
-
"- `/permissions set <tool> <tier>` - Set tool permission tier\n" +
|
|
1077
|
-
"- `/permissions reset` - Reset session approvals\n\n" +
|
|
1078
|
-
"**Permission Tiers:**\n" +
|
|
1079
|
-
"- `auto_approve` - Automatically allow (safe operations)\n" +
|
|
1080
|
-
"- `notify` - Allow with notification\n" +
|
|
1081
|
-
"- `confirm` - Require user confirmation\n" +
|
|
1082
|
-
"- `block` - Always block",
|
|
1083
|
-
timestamp: new Date(),
|
|
1084
|
-
};
|
|
1085
|
-
setChatHistory((prev) => [...prev, helpEntry]);
|
|
1086
|
-
}
|
|
1087
|
-
clearInput();
|
|
1088
|
-
return true;
|
|
1089
|
-
}
|
|
1090
|
-
// MCP Prompt commands (format: /mcp__servername__promptname [args])
|
|
1091
|
-
if (trimmedInput.startsWith("/mcp__")) {
|
|
1092
|
-
const parts = trimmedInput.split(" ");
|
|
1093
|
-
const commandPart = parts[0];
|
|
1094
|
-
const argsPart = parts.slice(1).join(" ");
|
|
1095
|
-
const parsed = parsePromptCommand(commandPart);
|
|
1096
|
-
if (parsed) {
|
|
1097
|
-
const { serverName, promptName } = parsed;
|
|
1098
|
-
// Add user command to chat history
|
|
1099
|
-
const userEntry = {
|
|
1100
|
-
type: "user",
|
|
1101
|
-
content: trimmedInput,
|
|
1102
|
-
timestamp: new Date(),
|
|
1103
|
-
};
|
|
1104
|
-
setChatHistory((prev) => [...prev, userEntry]);
|
|
1105
|
-
// Execute the prompt asynchronously
|
|
1106
|
-
(async () => {
|
|
1107
|
-
try {
|
|
1108
|
-
const manager = getMCPManager();
|
|
1109
|
-
const v2 = manager.getV2Instance();
|
|
1110
|
-
const { createServerName } = await import("../../mcp/client-v2.js");
|
|
1111
|
-
const serverNameBranded = createServerName(serverName);
|
|
1112
|
-
if (!serverNameBranded) {
|
|
1113
|
-
throw new Error(`Invalid server name: ${serverName}`);
|
|
1114
|
-
}
|
|
1115
|
-
// Parse arguments if provided (format: key=value key2=value2)
|
|
1116
|
-
const promptArgs = {};
|
|
1117
|
-
if (argsPart) {
|
|
1118
|
-
const argMatches = argsPart.match(/(\w+)=("[^"]+"|[^\s]+)/g);
|
|
1119
|
-
if (argMatches) {
|
|
1120
|
-
for (const match of argMatches) {
|
|
1121
|
-
const [key, ...valueParts] = match.split("=");
|
|
1122
|
-
let value = valueParts.join("=");
|
|
1123
|
-
// Remove quotes if present
|
|
1124
|
-
if (value.startsWith('"') && value.endsWith('"')) {
|
|
1125
|
-
value = value.slice(1, -1);
|
|
1126
|
-
}
|
|
1127
|
-
promptArgs[key] = value;
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
}
|
|
1131
|
-
const result = await v2.getPrompt(serverNameBranded, promptName, Object.keys(promptArgs).length > 0 ? promptArgs : undefined);
|
|
1132
|
-
if (!result.success) {
|
|
1133
|
-
throw result.error;
|
|
1134
|
-
}
|
|
1135
|
-
// Cast to GetPromptResult format for formatPromptResult
|
|
1136
|
-
const promptResult = result.value;
|
|
1137
|
-
const formattedContent = formatPromptResult(promptResult);
|
|
1138
|
-
// Add the prompt result as an assistant message
|
|
1139
|
-
const promptEntry = {
|
|
1140
|
-
type: "assistant",
|
|
1141
|
-
content: `**MCP Prompt: ${serverName}/${promptName}**\n\n${formattedContent}`,
|
|
1142
|
-
timestamp: new Date(),
|
|
1143
|
-
};
|
|
1144
|
-
setChatHistory((prev) => [...prev, promptEntry]);
|
|
1145
|
-
}
|
|
1146
|
-
catch (error) {
|
|
1147
|
-
const errorMessage = extractErrorMessage(error);
|
|
1148
|
-
// Use assistant type with error content since "error" is not a valid ChatEntry type
|
|
1149
|
-
const errorEntry = {
|
|
1150
|
-
type: "assistant",
|
|
1151
|
-
content: `❌ **Failed to execute MCP prompt:** ${errorMessage}`,
|
|
1152
|
-
timestamp: new Date(),
|
|
1153
|
-
};
|
|
1154
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
1155
|
-
}
|
|
1156
|
-
})();
|
|
1157
|
-
clearInput();
|
|
1158
|
-
return true;
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
if (trimmedInput === "/exit") {
|
|
1162
|
-
process.exit(0);
|
|
1163
|
-
return true;
|
|
1164
|
-
}
|
|
1165
|
-
// Memory commands
|
|
1166
|
-
if (trimmedInput === "/memory" || trimmedInput === "/memory status") {
|
|
1167
|
-
const store = getContextStore();
|
|
1168
|
-
const metadata = store.getMetadata();
|
|
1169
|
-
let memoryContent = "🧠 **Project Memory Status**\n\n";
|
|
1170
|
-
if (!metadata.exists) {
|
|
1171
|
-
memoryContent += "❌ No project memory found.\n\n";
|
|
1172
|
-
memoryContent += "Run `/memory warmup` to generate project memory for z.ai caching.\n";
|
|
1173
|
-
}
|
|
1174
|
-
else {
|
|
1175
|
-
memoryContent += `✅ Memory initialized\n\n`;
|
|
1176
|
-
memoryContent += `**Token Estimate:** ${metadata.tokenEstimate?.toLocaleString() || 'N/A'} tokens\n`;
|
|
1177
|
-
memoryContent += `**Last Updated:** ${metadata.updatedAt ? new Date(metadata.updatedAt).toLocaleString() : 'N/A'}\n`;
|
|
1178
|
-
memoryContent += `**Usage Count:** ${metadata.usageCount || 0}\n`;
|
|
1179
|
-
// Try to get section breakdown
|
|
1180
|
-
const loadResult = store.load();
|
|
1181
|
-
if (loadResult.success) {
|
|
1182
|
-
const sections = loadResult.data.context.sections;
|
|
1183
|
-
memoryContent += `\n**📊 Token Distribution:**\n`;
|
|
1184
|
-
const total = Object.values(sections).reduce((a, b) => a + b, 0);
|
|
1185
|
-
for (const [name, tokens] of Object.entries(sections)) {
|
|
1186
|
-
const pct = total > 0 ? Math.round((tokens / total) * 100) : 0;
|
|
1187
|
-
const bar = '█'.repeat(Math.round(pct / 5)) + '░'.repeat(20 - Math.round(pct / 5));
|
|
1188
|
-
memoryContent += ` ${bar} ${name.charAt(0).toUpperCase() + name.slice(1)} (${pct}%)\n`;
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
|
-
// Show cache stats if available
|
|
1192
|
-
const statsCollector = getStatsCollector();
|
|
1193
|
-
const formattedStats = statsCollector.getFormattedStats();
|
|
1194
|
-
if (formattedStats && formattedStats.usageCount > 0) {
|
|
1195
|
-
memoryContent += `\n**💾 Cache Statistics:**\n`;
|
|
1196
|
-
memoryContent += ` • Usage Count: ${formattedStats.usageCount}\n`;
|
|
1197
|
-
memoryContent += ` • Tokens Saved: ${formattedStats.tokensSaved.toLocaleString()}\n`;
|
|
1198
|
-
memoryContent += ` • Cache Rate: ${formattedStats.cacheRate}%\n`;
|
|
1199
|
-
memoryContent += ` • Est. Savings: $${formattedStats.estimatedSavings.toFixed(4)}\n`;
|
|
1200
|
-
}
|
|
1201
|
-
}
|
|
1202
|
-
const memoryEntry = {
|
|
1203
|
-
type: "assistant",
|
|
1204
|
-
content: memoryContent,
|
|
1205
|
-
timestamp: new Date(),
|
|
1206
|
-
};
|
|
1207
|
-
setChatHistory((prev) => [...prev, memoryEntry]);
|
|
1208
|
-
clearInput();
|
|
1209
|
-
return true;
|
|
1210
|
-
}
|
|
1211
|
-
if (trimmedInput === "/memory warmup") {
|
|
1212
|
-
setIsProcessing(true);
|
|
1213
|
-
const warmupEntry = {
|
|
1214
|
-
type: "assistant",
|
|
1215
|
-
content: "🔄 Generating project memory...",
|
|
1216
|
-
timestamp: new Date(),
|
|
1217
|
-
};
|
|
1218
|
-
// Track the entry index BEFORE any async operations to prevent race conditions
|
|
1219
|
-
let entryIndex = -1;
|
|
1220
|
-
setChatHistory((prev) => {
|
|
1221
|
-
entryIndex = prev.length; // Store index before pushing
|
|
1222
|
-
return [...prev, warmupEntry];
|
|
1223
|
-
});
|
|
1224
|
-
try {
|
|
1225
|
-
const generator = new ContextGenerator();
|
|
1226
|
-
const result = await generator.generate();
|
|
1227
|
-
if (result.success && result.memory) {
|
|
1228
|
-
const store = getContextStore();
|
|
1229
|
-
const memory = result.memory;
|
|
1230
|
-
const saveResult = store.save(memory);
|
|
1231
|
-
if (saveResult.success) {
|
|
1232
|
-
const sections = memory.context.sections;
|
|
1233
|
-
const tokenEstimate = memory.context.token_estimate;
|
|
1234
|
-
let resultContent = `✅ Project memory generated (${tokenEstimate.toLocaleString()} tokens)\n\n`;
|
|
1235
|
-
resultContent += `**📊 Context breakdown:**\n`;
|
|
1236
|
-
for (const [name, tokens] of Object.entries(sections)) {
|
|
1237
|
-
if (tokens !== undefined) {
|
|
1238
|
-
const tokenCount = tokens;
|
|
1239
|
-
const pct = Math.round((tokenCount / tokenEstimate) * 100);
|
|
1240
|
-
resultContent += ` ${name.charAt(0).toUpperCase() + name.slice(1)}: ${tokenCount.toLocaleString()} tokens (${pct}%)\n`;
|
|
1241
|
-
}
|
|
1242
|
-
}
|
|
1243
|
-
resultContent += `\n💾 Saved to .ax-cli/memory.json`;
|
|
1244
|
-
// Update the specific entry by index to avoid race conditions
|
|
1245
|
-
setChatHistory((prev) => {
|
|
1246
|
-
const updated = [...prev];
|
|
1247
|
-
if (entryIndex >= 0 && entryIndex < updated.length) {
|
|
1248
|
-
updated[entryIndex] = {
|
|
1249
|
-
type: "assistant",
|
|
1250
|
-
content: resultContent,
|
|
1251
|
-
timestamp: new Date(),
|
|
1252
|
-
};
|
|
1253
|
-
}
|
|
1254
|
-
return updated;
|
|
1255
|
-
});
|
|
1256
|
-
// Trigger toast notification
|
|
1257
|
-
onMemoryWarmed?.(tokenEstimate);
|
|
1258
|
-
}
|
|
1259
|
-
else {
|
|
1260
|
-
throw new Error(saveResult.error);
|
|
1261
|
-
}
|
|
1262
|
-
}
|
|
1263
|
-
else {
|
|
1264
|
-
throw new Error(result.error);
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
|
-
catch (error) {
|
|
1268
|
-
const errorMessage = extractErrorMessage(error);
|
|
1269
|
-
// Update the specific entry by index to avoid race conditions
|
|
1270
|
-
setChatHistory((prev) => {
|
|
1271
|
-
const updated = [...prev];
|
|
1272
|
-
if (entryIndex >= 0 && entryIndex < updated.length) {
|
|
1273
|
-
updated[entryIndex] = {
|
|
1274
|
-
type: "assistant",
|
|
1275
|
-
content: `❌ Failed to generate memory: ${errorMessage}`,
|
|
1276
|
-
timestamp: new Date(),
|
|
1277
|
-
};
|
|
1278
|
-
}
|
|
1279
|
-
return updated;
|
|
1280
|
-
});
|
|
1281
|
-
}
|
|
1282
|
-
setIsProcessing(false);
|
|
1283
|
-
clearInput();
|
|
1284
|
-
return true;
|
|
1285
|
-
}
|
|
1286
|
-
if (trimmedInput === "/memory refresh") {
|
|
1287
|
-
setIsProcessing(true);
|
|
1288
|
-
const refreshEntry = {
|
|
1289
|
-
type: "assistant",
|
|
1290
|
-
content: "🔄 Refreshing project memory...",
|
|
1291
|
-
timestamp: new Date(),
|
|
1292
|
-
};
|
|
1293
|
-
// Track the entry index BEFORE any async operations to prevent race conditions
|
|
1294
|
-
let entryIndex = -1;
|
|
1295
|
-
setChatHistory((prev) => {
|
|
1296
|
-
entryIndex = prev.length; // Store index before pushing
|
|
1297
|
-
return [...prev, refreshEntry];
|
|
1298
|
-
});
|
|
1299
|
-
try {
|
|
1300
|
-
const store = getContextStore();
|
|
1301
|
-
const existing = store.load();
|
|
1302
|
-
const generator = new ContextGenerator();
|
|
1303
|
-
const result = await generator.generate();
|
|
1304
|
-
if (result.success && result.memory) {
|
|
1305
|
-
const memory = result.memory;
|
|
1306
|
-
const hasChanges = !existing.success ||
|
|
1307
|
-
existing.data.content_hash !== memory.content_hash;
|
|
1308
|
-
if (hasChanges) {
|
|
1309
|
-
const saveResult = store.save(memory);
|
|
1310
|
-
if (saveResult.success) {
|
|
1311
|
-
// Update the specific entry by index to avoid race conditions
|
|
1312
|
-
setChatHistory((prev) => {
|
|
1313
|
-
const updated = [...prev];
|
|
1314
|
-
if (entryIndex >= 0 && entryIndex < updated.length) {
|
|
1315
|
-
updated[entryIndex] = {
|
|
1316
|
-
type: "assistant",
|
|
1317
|
-
content: `✅ Memory updated (${memory.context.token_estimate.toLocaleString()} tokens)`,
|
|
1318
|
-
timestamp: new Date(),
|
|
1319
|
-
};
|
|
1320
|
-
}
|
|
1321
|
-
return updated;
|
|
1322
|
-
});
|
|
1323
|
-
// Trigger toast notification
|
|
1324
|
-
onMemoryRefreshed?.();
|
|
1325
|
-
}
|
|
1326
|
-
else {
|
|
1327
|
-
throw new Error(saveResult.error);
|
|
1328
|
-
}
|
|
1329
|
-
}
|
|
1330
|
-
else {
|
|
1331
|
-
// Update the specific entry by index to avoid race conditions
|
|
1332
|
-
setChatHistory((prev) => {
|
|
1333
|
-
const updated = [...prev];
|
|
1334
|
-
if (entryIndex >= 0 && entryIndex < updated.length) {
|
|
1335
|
-
updated[entryIndex] = {
|
|
1336
|
-
type: "assistant",
|
|
1337
|
-
content: `✅ No changes detected - memory is up to date`,
|
|
1338
|
-
timestamp: new Date(),
|
|
1339
|
-
};
|
|
1340
|
-
}
|
|
1341
|
-
return updated;
|
|
1342
|
-
});
|
|
1343
|
-
}
|
|
1344
|
-
}
|
|
1345
|
-
else {
|
|
1346
|
-
throw new Error(result.error);
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1349
|
-
catch (error) {
|
|
1350
|
-
const errorMessage = extractErrorMessage(error);
|
|
1351
|
-
// Update the specific entry by index to avoid race conditions
|
|
1352
|
-
setChatHistory((prev) => {
|
|
1353
|
-
const updated = [...prev];
|
|
1354
|
-
if (entryIndex >= 0 && entryIndex < updated.length) {
|
|
1355
|
-
updated[entryIndex] = {
|
|
1356
|
-
type: "assistant",
|
|
1357
|
-
content: `❌ Failed to refresh memory: ${errorMessage}`,
|
|
1358
|
-
timestamp: new Date(),
|
|
1359
|
-
};
|
|
1360
|
-
}
|
|
1361
|
-
return updated;
|
|
1362
|
-
});
|
|
1363
|
-
}
|
|
1364
|
-
setIsProcessing(false);
|
|
1365
|
-
clearInput();
|
|
1366
|
-
return true;
|
|
1367
|
-
}
|
|
1368
|
-
// Theme command
|
|
1369
|
-
if (trimmedInput === "/theme" || trimmedInput.startsWith("/theme ")) {
|
|
1370
|
-
try {
|
|
1371
|
-
// Convert to lowercase for case-insensitive theme name matching
|
|
1372
|
-
const arg = trimmedInput.substring(7).trim().toLowerCase();
|
|
1373
|
-
const settings = getSettingsManager();
|
|
1374
|
-
const { getAllThemes, isValidTheme } = await import("../themes/index.js");
|
|
1375
|
-
const { clearThemeCache } = await import("../utils/colors.js");
|
|
1376
|
-
const allThemes = getAllThemes();
|
|
1377
|
-
if (!arg || arg === "list") {
|
|
1378
|
-
// Show current theme and list available themes
|
|
1379
|
-
const uiConfig = settings.getUIConfig();
|
|
1380
|
-
const currentTheme = (uiConfig && uiConfig.theme) ? uiConfig.theme : 'default';
|
|
1381
|
-
let themeContent = "🎨 **Color Themes**\n\n";
|
|
1382
|
-
themeContent += `**Current theme:** ${currentTheme}\n\n`;
|
|
1383
|
-
themeContent += "**Available themes:**\n";
|
|
1384
|
-
for (const theme of allThemes) {
|
|
1385
|
-
const isCurrent = theme.name === currentTheme ? " ✓" : "";
|
|
1386
|
-
themeContent += ` • \`${theme.name}\` - ${theme.description}${isCurrent}\n`;
|
|
1387
|
-
}
|
|
1388
|
-
themeContent += "\n**Usage:** `/theme <name>` to switch themes";
|
|
1389
|
-
const themeEntry = {
|
|
1390
|
-
type: "assistant",
|
|
1391
|
-
content: themeContent,
|
|
1392
|
-
timestamp: new Date(),
|
|
1393
|
-
};
|
|
1394
|
-
setChatHistory((prev) => [...prev, themeEntry]);
|
|
1395
|
-
clearInput();
|
|
1396
|
-
return true;
|
|
1397
|
-
}
|
|
1398
|
-
// Set a specific theme
|
|
1399
|
-
if (isValidTheme(arg)) {
|
|
1400
|
-
settings.updateUIConfig({ theme: arg });
|
|
1401
|
-
clearThemeCache(); // Clear cached theme colors
|
|
1402
|
-
const selectedTheme = allThemes.find(t => t.name === arg);
|
|
1403
|
-
const themeEntry = {
|
|
1404
|
-
type: "assistant",
|
|
1405
|
-
content: `✅ Theme changed to **${selectedTheme?.displayName}** (${selectedTheme?.description}).\n\n💡 The new theme will be applied to UI elements.`,
|
|
1406
|
-
timestamp: new Date(),
|
|
1407
|
-
};
|
|
1408
|
-
setChatHistory((prev) => [...prev, themeEntry]);
|
|
1409
|
-
clearInput();
|
|
1410
|
-
return true;
|
|
1411
|
-
}
|
|
1412
|
-
else {
|
|
1413
|
-
// Invalid theme name
|
|
1414
|
-
const themeEntry = {
|
|
1415
|
-
type: "assistant",
|
|
1416
|
-
content: `❌ Unknown theme: \`${arg}\`\n\nAvailable themes: ${allThemes.map(t => t.name).join(", ")}`,
|
|
1417
|
-
timestamp: new Date(),
|
|
1418
|
-
};
|
|
1419
|
-
setChatHistory((prev) => [...prev, themeEntry]);
|
|
1420
|
-
clearInput();
|
|
1421
|
-
return true;
|
|
1422
|
-
}
|
|
1423
|
-
}
|
|
1424
|
-
catch (error) {
|
|
1425
|
-
const errorMessage = extractErrorMessage(error);
|
|
1426
|
-
const errorEntry = {
|
|
1427
|
-
type: "assistant",
|
|
1428
|
-
content: `❌ Failed to process theme command: ${errorMessage}`,
|
|
1429
|
-
timestamp: new Date(),
|
|
1430
|
-
};
|
|
1431
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
1432
|
-
clearInput();
|
|
1433
|
-
return true;
|
|
1434
|
-
}
|
|
1435
|
-
}
|
|
1436
|
-
// Background task commands
|
|
1437
|
-
if (trimmedInput === "/tasks") {
|
|
1438
|
-
const bashOutputTool = new BashOutputTool();
|
|
1439
|
-
const result = bashOutputTool.listTasks();
|
|
1440
|
-
const tasksEntry = {
|
|
1441
|
-
type: "assistant",
|
|
1442
|
-
content: result.output || "No background tasks",
|
|
1443
|
-
timestamp: new Date(),
|
|
1444
|
-
};
|
|
1445
|
-
setChatHistory((prev) => [...prev, tasksEntry]);
|
|
1446
|
-
clearInput();
|
|
1447
|
-
return true;
|
|
1448
|
-
}
|
|
1449
|
-
if (trimmedInput.startsWith("/task ")) {
|
|
1450
|
-
const taskId = trimmedInput.substring(6).trim();
|
|
1451
|
-
if (!taskId) {
|
|
1452
|
-
const errorEntry = {
|
|
1453
|
-
type: "assistant",
|
|
1454
|
-
content: "Usage: /task <task_id>",
|
|
1455
|
-
timestamp: new Date(),
|
|
1456
|
-
};
|
|
1457
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
1458
|
-
clearInput();
|
|
1459
|
-
return true;
|
|
1460
|
-
}
|
|
1461
|
-
const bashOutputTool = new BashOutputTool();
|
|
1462
|
-
const result = await bashOutputTool.execute(taskId);
|
|
1463
|
-
const taskEntry = {
|
|
1464
|
-
type: "assistant",
|
|
1465
|
-
content: result.success ? result.output || "No output" : result.error || "Task not found",
|
|
1466
|
-
timestamp: new Date(),
|
|
1467
|
-
};
|
|
1468
|
-
setChatHistory((prev) => [...prev, taskEntry]);
|
|
1469
|
-
clearInput();
|
|
1470
|
-
return true;
|
|
1471
|
-
}
|
|
1472
|
-
if (trimmedInput.startsWith("/kill ")) {
|
|
1473
|
-
const taskId = trimmedInput.substring(6).trim();
|
|
1474
|
-
if (!taskId) {
|
|
1475
|
-
const errorEntry = {
|
|
1476
|
-
type: "assistant",
|
|
1477
|
-
content: "Usage: /kill <task_id>",
|
|
1478
|
-
timestamp: new Date(),
|
|
1479
|
-
};
|
|
1480
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
1481
|
-
clearInput();
|
|
1482
|
-
return true;
|
|
1483
|
-
}
|
|
1484
|
-
const bashOutputTool = new BashOutputTool();
|
|
1485
|
-
const result = bashOutputTool.killTask(taskId);
|
|
1486
|
-
const killEntry = {
|
|
1487
|
-
type: "assistant",
|
|
1488
|
-
content: result.success ? result.output || "Task killed" : result.error || "Failed to kill task",
|
|
1489
|
-
timestamp: new Date(),
|
|
1490
|
-
};
|
|
1491
|
-
setChatHistory((prev) => [...prev, killEntry]);
|
|
1492
|
-
clearInput();
|
|
1493
|
-
return true;
|
|
1494
|
-
}
|
|
1495
|
-
if (trimmedInput === "/rewind") {
|
|
1496
|
-
await handleRewindCommand(agent);
|
|
1497
|
-
clearInput();
|
|
1498
|
-
return true;
|
|
1499
|
-
}
|
|
1500
|
-
if (trimmedInput === "/checkpoints") {
|
|
1501
|
-
await handleCheckpointsCommand();
|
|
1502
|
-
clearInput();
|
|
1503
|
-
return true;
|
|
1504
|
-
}
|
|
1505
|
-
if (trimmedInput === "/checkpoint-clean") {
|
|
1506
|
-
await handleCheckpointCleanCommand();
|
|
1507
|
-
clearInput();
|
|
1508
|
-
return true;
|
|
1509
|
-
}
|
|
1510
|
-
// Plan commands
|
|
1511
|
-
if (trimmedInput === "/plans") {
|
|
1512
|
-
const result = await handlePlansCommand();
|
|
1513
|
-
const plansEntry = {
|
|
1514
|
-
type: "assistant",
|
|
1515
|
-
content: result.output,
|
|
1516
|
-
timestamp: new Date(),
|
|
1517
|
-
};
|
|
1518
|
-
setChatHistory((prev) => [...prev, plansEntry]);
|
|
1519
|
-
clearInput();
|
|
1520
|
-
return true;
|
|
1521
|
-
}
|
|
1522
|
-
if (trimmedInput === "/plan" || trimmedInput.startsWith("/plan ")) {
|
|
1523
|
-
const planId = trimmedInput === "/plan" ? undefined : trimmedInput.substring(6).trim();
|
|
1524
|
-
const result = await handlePlanCommand(planId || undefined);
|
|
1525
|
-
const planEntry = {
|
|
1526
|
-
type: "assistant",
|
|
1527
|
-
content: result.output,
|
|
1528
|
-
timestamp: new Date(),
|
|
1529
|
-
};
|
|
1530
|
-
setChatHistory((prev) => [...prev, planEntry]);
|
|
1531
|
-
clearInput();
|
|
1532
|
-
return true;
|
|
1533
|
-
}
|
|
1534
|
-
if (trimmedInput === "/phases") {
|
|
1535
|
-
const result = await handlePhasesCommand();
|
|
1536
|
-
const phasesEntry = {
|
|
1537
|
-
type: "assistant",
|
|
1538
|
-
content: result.output,
|
|
1539
|
-
timestamp: new Date(),
|
|
1540
|
-
};
|
|
1541
|
-
setChatHistory((prev) => [...prev, phasesEntry]);
|
|
1542
|
-
clearInput();
|
|
1543
|
-
return true;
|
|
1544
|
-
}
|
|
1545
|
-
if (trimmedInput === "/pause") {
|
|
1546
|
-
const result = await handlePauseCommand();
|
|
1547
|
-
const pauseEntry = {
|
|
1548
|
-
type: "assistant",
|
|
1549
|
-
content: result.output,
|
|
1550
|
-
timestamp: new Date(),
|
|
1551
|
-
};
|
|
1552
|
-
setChatHistory((prev) => [...prev, pauseEntry]);
|
|
1553
|
-
clearInput();
|
|
1554
|
-
return true;
|
|
1555
|
-
}
|
|
1556
|
-
if (trimmedInput === "/resume" || trimmedInput.startsWith("/resume ")) {
|
|
1557
|
-
const planId = trimmedInput === "/resume" ? undefined : trimmedInput.substring(8).trim();
|
|
1558
|
-
const result = await handleResumeCommand(planId || undefined);
|
|
1559
|
-
const resumeEntry = {
|
|
1560
|
-
type: "assistant",
|
|
1561
|
-
content: result.output,
|
|
1562
|
-
timestamp: new Date(),
|
|
1563
|
-
};
|
|
1564
|
-
setChatHistory((prev) => [...prev, resumeEntry]);
|
|
1565
|
-
clearInput();
|
|
1566
|
-
return true;
|
|
1567
|
-
}
|
|
1568
|
-
if (trimmedInput === "/skip") {
|
|
1569
|
-
const result = await handleSkipPhaseCommand();
|
|
1570
|
-
const skipEntry = {
|
|
1571
|
-
type: "assistant",
|
|
1572
|
-
content: result.output,
|
|
1573
|
-
timestamp: new Date(),
|
|
1574
|
-
};
|
|
1575
|
-
setChatHistory((prev) => [...prev, skipEntry]);
|
|
1576
|
-
clearInput();
|
|
1577
|
-
return true;
|
|
1578
|
-
}
|
|
1579
|
-
if (trimmedInput === "/abandon") {
|
|
1580
|
-
const result = await handleAbandonCommand();
|
|
1581
|
-
const abandonEntry = {
|
|
1582
|
-
type: "assistant",
|
|
1583
|
-
content: result.output,
|
|
1584
|
-
timestamp: new Date(),
|
|
1585
|
-
};
|
|
1586
|
-
setChatHistory((prev) => [...prev, abandonEntry]);
|
|
1587
|
-
clearInput();
|
|
1588
|
-
return true;
|
|
1589
|
-
}
|
|
1590
|
-
if (trimmedInput === "/resumable") {
|
|
1591
|
-
const result = await handleResumableCommand();
|
|
1592
|
-
const resumableEntry = {
|
|
1593
|
-
type: "assistant",
|
|
1594
|
-
content: result.output,
|
|
1595
|
-
timestamp: new Date(),
|
|
1596
|
-
};
|
|
1597
|
-
setChatHistory((prev) => [...prev, resumableEntry]);
|
|
1598
|
-
clearInput();
|
|
1599
|
-
return true;
|
|
1600
|
-
}
|
|
1601
|
-
if (trimmedInput === "/commit-and-push") {
|
|
1602
|
-
const userEntry = {
|
|
1603
|
-
type: "user",
|
|
1604
|
-
content: "/commit-and-push",
|
|
1605
|
-
timestamp: new Date(),
|
|
1606
|
-
};
|
|
1607
|
-
setChatHistory((prev) => [...prev, userEntry]);
|
|
1608
|
-
setIsProcessing(true);
|
|
1609
|
-
setIsStreaming(true);
|
|
1610
|
-
try {
|
|
1611
|
-
// First check if there are any changes at all
|
|
1612
|
-
const initialStatusResult = await agent.executeBashCommand("git status --porcelain");
|
|
1613
|
-
if (!initialStatusResult.success ||
|
|
1614
|
-
!initialStatusResult.output?.trim()) {
|
|
1615
|
-
const noChangesEntry = {
|
|
1616
|
-
type: "assistant",
|
|
1617
|
-
content: "No changes to commit. Working directory is clean.",
|
|
1618
|
-
timestamp: new Date(),
|
|
1619
|
-
};
|
|
1620
|
-
setChatHistory((prev) => [...prev, noChangesEntry]);
|
|
1621
|
-
setIsProcessing(false);
|
|
1622
|
-
setIsStreaming(false);
|
|
1623
|
-
setInput("");
|
|
1624
|
-
return true;
|
|
1625
|
-
}
|
|
1626
|
-
// Add all changes
|
|
1627
|
-
const addResult = await agent.executeBashCommand("git add .");
|
|
1628
|
-
if (!addResult.success) {
|
|
1629
|
-
const addErrorEntry = {
|
|
1630
|
-
type: "assistant",
|
|
1631
|
-
content: `Failed to stage changes: ${addResult.error || "Unknown error"}`,
|
|
1632
|
-
timestamp: new Date(),
|
|
1633
|
-
};
|
|
1634
|
-
setChatHistory((prev) => [...prev, addErrorEntry]);
|
|
1635
|
-
setIsProcessing(false);
|
|
1636
|
-
setIsStreaming(false);
|
|
1637
|
-
setInput("");
|
|
1638
|
-
return true;
|
|
1639
|
-
}
|
|
1640
|
-
// Show that changes were staged
|
|
1641
|
-
const addEntry = {
|
|
1642
|
-
type: "tool_result",
|
|
1643
|
-
content: "Changes staged successfully",
|
|
1644
|
-
timestamp: new Date(),
|
|
1645
|
-
toolCall: {
|
|
1646
|
-
id: `git_add_${Date.now()}`,
|
|
1647
|
-
type: "function",
|
|
1648
|
-
function: {
|
|
1649
|
-
name: "bash",
|
|
1650
|
-
arguments: JSON.stringify({ command: "git add ." }),
|
|
1651
|
-
},
|
|
1652
|
-
},
|
|
1653
|
-
toolResult: addResult,
|
|
1654
|
-
};
|
|
1655
|
-
setChatHistory((prev) => [...prev, addEntry]);
|
|
1656
|
-
// Get staged changes for commit message generation
|
|
1657
|
-
const diffResult = await agent.executeBashCommand("git diff --cached");
|
|
1658
|
-
// Generate commit message using AI
|
|
1659
|
-
const commitPrompt = `Generate a concise, professional git commit message for these changes:
|
|
1660
|
-
|
|
1661
|
-
Git Status:
|
|
1662
|
-
${initialStatusResult.output}
|
|
1663
|
-
|
|
1664
|
-
Git Diff (staged changes):
|
|
1665
|
-
${diffResult.output || "No staged changes shown"}
|
|
1666
|
-
|
|
1667
|
-
Follow conventional commit format (feat:, fix:, docs:, etc.) and keep it under 72 characters.
|
|
1668
|
-
Respond with ONLY the commit message, no additional text.`;
|
|
1669
|
-
let commitMessage = "";
|
|
1670
|
-
let streamingEntry = null;
|
|
1671
|
-
for await (const chunk of agent.processUserMessageStream(commitPrompt)) {
|
|
1672
|
-
if (chunk.type === "content" && chunk.content) {
|
|
1673
|
-
if (!streamingEntry) {
|
|
1674
|
-
const newEntry = {
|
|
1675
|
-
type: "assistant",
|
|
1676
|
-
content: `Generating commit message...\n\n${chunk.content}`,
|
|
1677
|
-
timestamp: new Date(),
|
|
1678
|
-
isStreaming: true,
|
|
1679
|
-
};
|
|
1680
|
-
setChatHistory((prev) => [...prev, newEntry]);
|
|
1681
|
-
streamingEntry = newEntry;
|
|
1682
|
-
commitMessage = chunk.content;
|
|
1683
|
-
}
|
|
1684
|
-
else {
|
|
1685
|
-
commitMessage += chunk.content;
|
|
1686
|
-
setChatHistory((prev) => prev.map((entry, idx) => idx === prev.length - 1 && entry.isStreaming
|
|
1687
|
-
? {
|
|
1688
|
-
...entry,
|
|
1689
|
-
content: `Generating commit message...\n\n${commitMessage}`,
|
|
1690
|
-
}
|
|
1691
|
-
: entry));
|
|
1692
|
-
}
|
|
1693
|
-
}
|
|
1694
|
-
else if (chunk.type === "done") {
|
|
1695
|
-
if (streamingEntry) {
|
|
1696
|
-
setChatHistory((prev) => prev.map((entry) => entry.isStreaming
|
|
1697
|
-
? {
|
|
1698
|
-
...entry,
|
|
1699
|
-
content: `Generated commit message: "${commitMessage.trim()}"`,
|
|
1700
|
-
isStreaming: false,
|
|
1701
|
-
}
|
|
1702
|
-
: entry));
|
|
1703
|
-
}
|
|
1704
|
-
break;
|
|
1705
|
-
}
|
|
1706
|
-
}
|
|
1707
|
-
// Execute the commit with properly escaped message to prevent command injection
|
|
1708
|
-
const cleanCommitMessage = commitMessage.trim();
|
|
1709
|
-
const commitCommand = `git commit -m ${escapeShellArg(cleanCommitMessage)}`;
|
|
1710
|
-
const commitResult = await agent.executeBashCommand(commitCommand);
|
|
1711
|
-
const commitEntry = {
|
|
1712
|
-
type: "tool_result",
|
|
1713
|
-
content: commitResult.success
|
|
1714
|
-
? commitResult.output || "Commit successful"
|
|
1715
|
-
: commitResult.error || "Commit failed",
|
|
1716
|
-
timestamp: new Date(),
|
|
1717
|
-
toolCall: {
|
|
1718
|
-
id: `git_commit_${Date.now()}`,
|
|
1719
|
-
type: "function",
|
|
1720
|
-
function: {
|
|
1721
|
-
name: "bash",
|
|
1722
|
-
arguments: JSON.stringify({ command: commitCommand }),
|
|
1723
|
-
},
|
|
1724
|
-
},
|
|
1725
|
-
toolResult: commitResult,
|
|
1726
|
-
};
|
|
1727
|
-
setChatHistory((prev) => [...prev, commitEntry]);
|
|
1728
|
-
// If commit was successful, push to remote
|
|
1729
|
-
if (commitResult.success) {
|
|
1730
|
-
// First try regular push, if it fails try with upstream setup
|
|
1731
|
-
let pushResult = await agent.executeBashCommand("git push");
|
|
1732
|
-
let pushCommand = "git push";
|
|
1733
|
-
if (!pushResult.success &&
|
|
1734
|
-
pushResult.error?.includes("no upstream branch")) {
|
|
1735
|
-
pushCommand = "git push -u origin HEAD";
|
|
1736
|
-
pushResult = await agent.executeBashCommand(pushCommand);
|
|
1737
|
-
}
|
|
1738
|
-
const pushEntry = {
|
|
1739
|
-
type: "tool_result",
|
|
1740
|
-
content: pushResult.success
|
|
1741
|
-
? pushResult.output || "Push successful"
|
|
1742
|
-
: pushResult.error || "Push failed",
|
|
1743
|
-
timestamp: new Date(),
|
|
1744
|
-
toolCall: {
|
|
1745
|
-
id: `git_push_${Date.now()}`,
|
|
1746
|
-
type: "function",
|
|
1747
|
-
function: {
|
|
1748
|
-
name: "bash",
|
|
1749
|
-
arguments: JSON.stringify({ command: pushCommand }),
|
|
1750
|
-
},
|
|
1751
|
-
},
|
|
1752
|
-
toolResult: pushResult,
|
|
1753
|
-
};
|
|
1754
|
-
setChatHistory((prev) => [...prev, pushEntry]);
|
|
1755
|
-
}
|
|
1756
|
-
}
|
|
1757
|
-
catch (error) {
|
|
1758
|
-
const errorMessage = extractErrorMessage(error);
|
|
1759
|
-
const errorEntry = {
|
|
1760
|
-
type: "assistant",
|
|
1761
|
-
content: `Error during commit and push: ${errorMessage}`,
|
|
1762
|
-
timestamp: new Date(),
|
|
1763
|
-
};
|
|
1764
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
1765
|
-
}
|
|
1766
|
-
setIsProcessing(false);
|
|
1767
|
-
setIsStreaming(false);
|
|
1768
|
-
clearInput();
|
|
1769
|
-
return true;
|
|
1770
|
-
}
|
|
1771
|
-
// Handle /commands - list all custom commands
|
|
1772
|
-
if (trimmedInput === "/commands") {
|
|
1773
|
-
const customCmds = customCommandsManager.getAllCommands();
|
|
1774
|
-
let content = "**Custom Commands:**\n\n";
|
|
1775
|
-
if (customCmds.length === 0) {
|
|
1776
|
-
content += "No custom commands found.\n\n";
|
|
1777
|
-
content += "Create commands by adding markdown files to:\n";
|
|
1778
|
-
content += " • `.ax-cli/commands/` (project-level)\n";
|
|
1779
|
-
content += " • `~/.ax-cli/commands/` (user-level)\n";
|
|
1780
|
-
}
|
|
1781
|
-
else {
|
|
1782
|
-
const projectCmds = customCmds.filter((c) => c.scope === "project");
|
|
1783
|
-
const userCmds = customCmds.filter((c) => c.scope === "user");
|
|
1784
|
-
if (projectCmds.length > 0) {
|
|
1785
|
-
content += "**Project Commands:**\n";
|
|
1786
|
-
for (const cmd of projectCmds) {
|
|
1787
|
-
content += ` /${cmd.name} - ${cmd.description}\n`;
|
|
1788
|
-
}
|
|
1789
|
-
content += "\n";
|
|
1790
|
-
}
|
|
1791
|
-
if (userCmds.length > 0) {
|
|
1792
|
-
content += "**User Commands:**\n";
|
|
1793
|
-
for (const cmd of userCmds) {
|
|
1794
|
-
content += ` /${cmd.name} - ${cmd.description}\n`;
|
|
1795
|
-
}
|
|
1796
|
-
}
|
|
1797
|
-
}
|
|
1798
|
-
const commandsEntry = {
|
|
1799
|
-
type: "assistant",
|
|
1800
|
-
content,
|
|
1801
|
-
timestamp: new Date(),
|
|
1802
|
-
};
|
|
1803
|
-
setChatHistory((prev) => [...prev, commandsEntry]);
|
|
1804
|
-
clearInput();
|
|
1805
|
-
return true;
|
|
1806
|
-
}
|
|
1807
|
-
// Handle custom commands (starts with / but not a built-in command)
|
|
1808
|
-
if (trimmedInput.startsWith("/")) {
|
|
1809
|
-
const parts = trimmedInput.slice(1).split(/\s+/);
|
|
1810
|
-
const cmdName = parts[0];
|
|
1811
|
-
const cmdArgs = parts.slice(1).join(" ");
|
|
1812
|
-
if (customCommandsManager.hasCommand(cmdName)) {
|
|
1813
|
-
let expandedPrompt = customCommandsManager.expandCommand(cmdName, cmdArgs);
|
|
1814
|
-
if (expandedPrompt) {
|
|
1815
|
-
// Show what command was invoked
|
|
1816
|
-
const userEntry = {
|
|
1817
|
-
type: "user",
|
|
1818
|
-
content: trimmedInput,
|
|
1819
|
-
timestamp: new Date(),
|
|
1820
|
-
};
|
|
1821
|
-
setChatHistory((prev) => [...prev, userEntry]);
|
|
1822
|
-
// Process the expanded prompt through the agent
|
|
1823
|
-
setIsProcessing(true);
|
|
1824
|
-
clearInput();
|
|
1825
|
-
try {
|
|
1826
|
-
// Apply hooks and file mentions to expanded prompt
|
|
1827
|
-
const hooksManager = getHooksManager();
|
|
1828
|
-
expandedPrompt = await hooksManager.processUserInput(expandedPrompt);
|
|
1829
|
-
const fileMentionResult = await parseFileMentions(expandedPrompt, {
|
|
1830
|
-
baseDir: process.cwd(),
|
|
1831
|
-
maxFileSize: 100 * 1024,
|
|
1832
|
-
maxMentions: 10,
|
|
1833
|
-
includeContents: true,
|
|
1834
|
-
});
|
|
1835
|
-
if (fileMentionResult.hasMentions) {
|
|
1836
|
-
expandedPrompt = fileMentionResult.expandedInput;
|
|
1837
|
-
}
|
|
1838
|
-
setIsStreaming(true);
|
|
1839
|
-
let streamingEntry = null;
|
|
1840
|
-
for await (const chunk of agent.processUserMessageStream(expandedPrompt)) {
|
|
1841
|
-
switch (chunk.type) {
|
|
1842
|
-
case "content":
|
|
1843
|
-
if (chunk.content) {
|
|
1844
|
-
if (!streamingEntry) {
|
|
1845
|
-
const newEntry = {
|
|
1846
|
-
type: "assistant",
|
|
1847
|
-
content: chunk.content,
|
|
1848
|
-
timestamp: new Date(),
|
|
1849
|
-
isStreaming: true,
|
|
1850
|
-
};
|
|
1851
|
-
setChatHistory((prev) => [...prev, newEntry]);
|
|
1852
|
-
streamingEntry = newEntry;
|
|
1853
|
-
}
|
|
1854
|
-
else {
|
|
1855
|
-
setChatHistory((prev) => prev.map((entry, idx) => idx === prev.length - 1 && entry.isStreaming
|
|
1856
|
-
? { ...entry, content: entry.content + chunk.content }
|
|
1857
|
-
: entry));
|
|
1858
|
-
}
|
|
1859
|
-
}
|
|
1860
|
-
break;
|
|
1861
|
-
case "token_count":
|
|
1862
|
-
if (chunk.tokenCount !== undefined) {
|
|
1863
|
-
setTokenCount(chunk.tokenCount);
|
|
1864
|
-
}
|
|
1865
|
-
break;
|
|
1866
|
-
case "tool_calls":
|
|
1867
|
-
if (chunk.toolCalls) {
|
|
1868
|
-
setChatHistory((prev) => prev.map((entry) => entry.isStreaming
|
|
1869
|
-
? { ...entry, isStreaming: false, toolCalls: chunk.toolCalls }
|
|
1870
|
-
: entry));
|
|
1871
|
-
streamingEntry = null;
|
|
1872
|
-
chunk.toolCalls.forEach((toolCall) => {
|
|
1873
|
-
const toolCallEntry = {
|
|
1874
|
-
type: "tool_call",
|
|
1875
|
-
content: "Executing...",
|
|
1876
|
-
timestamp: new Date(),
|
|
1877
|
-
toolCall: toolCall,
|
|
1878
|
-
};
|
|
1879
|
-
setChatHistory((prev) => [...prev, toolCallEntry]);
|
|
1880
|
-
});
|
|
1881
|
-
}
|
|
1882
|
-
break;
|
|
1883
|
-
case "tool_result":
|
|
1884
|
-
if (chunk.toolCall && chunk.toolResult) {
|
|
1885
|
-
setChatHistory((prev) => prev.map((entry) => {
|
|
1886
|
-
if (entry.isStreaming) {
|
|
1887
|
-
return { ...entry, isStreaming: false };
|
|
1888
|
-
}
|
|
1889
|
-
if (entry.type === "tool_call" &&
|
|
1890
|
-
entry.toolCall?.id === chunk.toolCall?.id) {
|
|
1891
|
-
return {
|
|
1892
|
-
...entry,
|
|
1893
|
-
type: "tool_result",
|
|
1894
|
-
content: chunk.toolResult?.success
|
|
1895
|
-
? chunk.toolResult?.output || "Success"
|
|
1896
|
-
: chunk.toolResult?.error || "Error occurred",
|
|
1897
|
-
toolResult: chunk.toolResult,
|
|
1898
|
-
executionDurationMs: chunk.executionDurationMs,
|
|
1899
|
-
};
|
|
1900
|
-
}
|
|
1901
|
-
return entry;
|
|
1902
|
-
}));
|
|
1903
|
-
streamingEntry = null;
|
|
1904
|
-
}
|
|
1905
|
-
break;
|
|
1906
|
-
case "done":
|
|
1907
|
-
if (streamingEntry) {
|
|
1908
|
-
setChatHistory((prev) => prev.map((entry) => entry.isStreaming ? { ...entry, isStreaming: false } : entry));
|
|
1909
|
-
}
|
|
1910
|
-
setIsStreaming(false);
|
|
1911
|
-
break;
|
|
1912
|
-
}
|
|
1913
|
-
}
|
|
1914
|
-
}
|
|
1915
|
-
catch (error) {
|
|
1916
|
-
const errorMessage = extractErrorMessage(error);
|
|
1917
|
-
const errorEntry = {
|
|
1918
|
-
type: "assistant",
|
|
1919
|
-
content: `Error: ${errorMessage}`,
|
|
1920
|
-
timestamp: new Date(),
|
|
1921
|
-
};
|
|
1922
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
1923
|
-
setIsStreaming(false);
|
|
1924
|
-
}
|
|
1925
|
-
setIsProcessing(false);
|
|
1926
|
-
return true;
|
|
1927
|
-
}
|
|
1928
|
-
}
|
|
1929
|
-
}
|
|
1930
|
-
const directBashCommands = [
|
|
1931
|
-
"ls",
|
|
1932
|
-
"pwd",
|
|
1933
|
-
"cd",
|
|
1934
|
-
"cat",
|
|
1935
|
-
"mkdir",
|
|
1936
|
-
"touch",
|
|
1937
|
-
"echo",
|
|
1938
|
-
"grep",
|
|
1939
|
-
"find",
|
|
1940
|
-
"cp",
|
|
1941
|
-
"mv",
|
|
1942
|
-
"rm",
|
|
1943
|
-
];
|
|
1944
|
-
// BUG FIX: Added fallback for empty input to prevent undefined access
|
|
1945
|
-
const firstWord = trimmedInput.split(" ")[0] || "";
|
|
1946
|
-
if (directBashCommands.includes(firstWord)) {
|
|
1947
|
-
const userEntry = {
|
|
1948
|
-
type: "user",
|
|
1949
|
-
content: trimmedInput,
|
|
1950
|
-
timestamp: new Date(),
|
|
1951
|
-
};
|
|
1952
|
-
setChatHistory((prev) => [...prev, userEntry]);
|
|
1953
|
-
try {
|
|
1954
|
-
const result = await agent.executeBashCommand(trimmedInput);
|
|
1955
|
-
const commandEntry = {
|
|
1956
|
-
type: "tool_result",
|
|
1957
|
-
content: result.success
|
|
1958
|
-
? result.output || "Command completed"
|
|
1959
|
-
: result.error || "Command failed",
|
|
1960
|
-
timestamp: new Date(),
|
|
1961
|
-
toolCall: {
|
|
1962
|
-
id: `bash_${Date.now()}`,
|
|
1963
|
-
type: "function",
|
|
1964
|
-
function: {
|
|
1965
|
-
name: "bash",
|
|
1966
|
-
arguments: JSON.stringify({ command: trimmedInput }),
|
|
1967
|
-
},
|
|
1968
|
-
},
|
|
1969
|
-
toolResult: result,
|
|
1970
|
-
};
|
|
1971
|
-
setChatHistory((prev) => [...prev, commandEntry]);
|
|
1972
|
-
}
|
|
1973
|
-
catch (error) {
|
|
1974
|
-
const errorMessage = extractErrorMessage(error);
|
|
1975
|
-
const errorEntry = {
|
|
1976
|
-
type: "assistant",
|
|
1977
|
-
content: `Error executing command: ${errorMessage}`,
|
|
1978
|
-
timestamp: new Date(),
|
|
1979
|
-
};
|
|
1980
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
1981
|
-
}
|
|
1982
|
-
clearInput();
|
|
1983
|
-
return true;
|
|
1984
|
-
}
|
|
1985
|
-
return false;
|
|
1986
|
-
};
|
|
1987
|
-
const processUserMessage = async (userInput) => {
|
|
1988
|
-
const userEntry = {
|
|
1989
|
-
type: "user",
|
|
1990
|
-
content: userInput,
|
|
1991
|
-
timestamp: new Date(),
|
|
1992
|
-
};
|
|
1993
|
-
setChatHistory((prev) => [...prev, userEntry]);
|
|
1994
|
-
setIsProcessing(true);
|
|
1995
|
-
clearInput();
|
|
1996
|
-
try {
|
|
1997
|
-
// Process UserPromptSubmit hooks (may modify input)
|
|
1998
|
-
const hooksManager = getHooksManager();
|
|
1999
|
-
let processedInput = await hooksManager.processUserInput(userInput);
|
|
2000
|
-
// Check for image references (e.g., @image.png, /path/to/image.png)
|
|
2001
|
-
const imageResult = await parseImageInput(processedInput, process.cwd());
|
|
2002
|
-
// Show image processing errors if any
|
|
2003
|
-
if (imageResult.errors.length > 0) {
|
|
2004
|
-
const errorEntry = {
|
|
2005
|
-
type: "assistant",
|
|
2006
|
-
content: `⚠️ Image processing warnings:\n${imageResult.errors.map(e => ` - ${e}`).join('\n')}`,
|
|
2007
|
-
timestamp: new Date(),
|
|
2008
|
-
};
|
|
2009
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
2010
|
-
}
|
|
2011
|
-
// If images found, show info about model switch
|
|
2012
|
-
if (imageResult.hasImages) {
|
|
2013
|
-
const imageInfo = imageResult.images.map((img, i) => formatAttachmentForDisplay(img, i + 1)).join('\n');
|
|
2014
|
-
const infoEntry = {
|
|
2015
|
-
type: "assistant",
|
|
2016
|
-
content: `📷 Processing ${imageResult.images.length} image(s):\n${imageInfo}\n\n*Auto-switching to vision model for analysis*`,
|
|
2017
|
-
timestamp: new Date(),
|
|
2018
|
-
};
|
|
2019
|
-
setChatHistory((prev) => [...prev, infoEntry]);
|
|
2020
|
-
}
|
|
2021
|
-
// Parse and expand @file mentions (only if no images, to avoid conflicts)
|
|
2022
|
-
if (!imageResult.hasImages) {
|
|
2023
|
-
const fileMentionResult = await parseFileMentions(processedInput, {
|
|
2024
|
-
baseDir: process.cwd(),
|
|
2025
|
-
maxFileSize: 100 * 1024, // 100KB limit
|
|
2026
|
-
maxMentions: 10,
|
|
2027
|
-
includeContents: true,
|
|
2028
|
-
});
|
|
2029
|
-
// Use expanded input if file mentions were found
|
|
2030
|
-
processedInput = fileMentionResult.hasMentions
|
|
2031
|
-
? fileMentionResult.expandedInput
|
|
2032
|
-
: processedInput;
|
|
2033
|
-
}
|
|
2034
|
-
// Agent-First Mode: Check if we should route to an AutomatosX agent
|
|
2035
|
-
// Skip for image inputs (not supported by agents) and when disabled
|
|
2036
|
-
if (!agentFirstDisabled && !imageResult.hasImages) {
|
|
2037
|
-
const settings = getSettingsManager();
|
|
2038
|
-
const agentFirstSettings = settings.getAgentFirstSettings();
|
|
2039
|
-
if (agentFirstSettings.enabled) {
|
|
2040
|
-
// Determine which agent to use
|
|
2041
|
-
const selectedAgent = forcedAgent || (() => {
|
|
2042
|
-
const routerConfig = {
|
|
2043
|
-
enabled: agentFirstSettings.enabled,
|
|
2044
|
-
defaultAgent: agentFirstSettings.defaultAgent,
|
|
2045
|
-
confidenceThreshold: agentFirstSettings.confidenceThreshold,
|
|
2046
|
-
excludedAgents: agentFirstSettings.excludedAgents,
|
|
2047
|
-
};
|
|
2048
|
-
const routingResult = routeToAgent(processedInput, routerConfig);
|
|
2049
|
-
return routingResult.agent;
|
|
2050
|
-
})();
|
|
2051
|
-
// If an agent is selected, execute via ax run
|
|
2052
|
-
if (selectedAgent) {
|
|
2053
|
-
onAgentSelected?.(selectedAgent);
|
|
2054
|
-
// Add routing info to chat
|
|
2055
|
-
const routingEntry = {
|
|
2056
|
-
type: "assistant",
|
|
2057
|
-
content: `⚡ Routing to **${selectedAgent}** agent...`,
|
|
2058
|
-
timestamp: new Date(),
|
|
2059
|
-
};
|
|
2060
|
-
setChatHistory((prev) => [...prev, routingEntry]);
|
|
2061
|
-
setIsStreaming(true);
|
|
2062
|
-
let agentOutput = '';
|
|
2063
|
-
try {
|
|
2064
|
-
for await (const chunk of executeAgent({
|
|
2065
|
-
agent: selectedAgent,
|
|
2066
|
-
task: processedInput,
|
|
2067
|
-
streaming: true,
|
|
2068
|
-
})) {
|
|
2069
|
-
switch (chunk.type) {
|
|
2070
|
-
case 'output':
|
|
2071
|
-
if (chunk.content) {
|
|
2072
|
-
agentOutput += chunk.content;
|
|
2073
|
-
// Update the routing entry with accumulated output
|
|
2074
|
-
setChatHistory((prev) => prev.map((entry, idx) => idx === prev.length - 1
|
|
2075
|
-
? { ...entry, content: `⚡ **${selectedAgent}** agent:\n\n${agentOutput}`, isStreaming: true }
|
|
2076
|
-
: entry));
|
|
2077
|
-
}
|
|
2078
|
-
break;
|
|
2079
|
-
case 'error':
|
|
2080
|
-
if (chunk.content) {
|
|
2081
|
-
agentOutput += `\n⚠️ ${chunk.content}`;
|
|
2082
|
-
}
|
|
2083
|
-
break;
|
|
2084
|
-
case 'done':
|
|
2085
|
-
// Finalize the entry
|
|
2086
|
-
setChatHistory((prev) => prev.map((entry, idx) => idx === prev.length - 1
|
|
2087
|
-
? { ...entry, content: `⚡ **${selectedAgent}** agent:\n\n${agentOutput}`, isStreaming: false }
|
|
2088
|
-
: entry));
|
|
2089
|
-
break;
|
|
2090
|
-
}
|
|
2091
|
-
}
|
|
2092
|
-
// Agent execution succeeded
|
|
2093
|
-
setIsStreaming(false);
|
|
2094
|
-
setIsProcessing(false);
|
|
2095
|
-
// Keep agent name visible in status bar - don't reset to null
|
|
2096
|
-
return; // Agent handled the request
|
|
2097
|
-
}
|
|
2098
|
-
catch (agentError) {
|
|
2099
|
-
// Agent execution failed, show error and fall through to direct LLM
|
|
2100
|
-
const errorMessage = extractErrorMessage(agentError);
|
|
2101
|
-
setChatHistory((prev) => prev.map((entry, idx) => idx === prev.length - 1
|
|
2102
|
-
? { ...entry, content: `⚡ **${selectedAgent}** agent failed:\n\n❌ ${errorMessage}\n\nFalling back to direct LLM...`, isStreaming: false }
|
|
2103
|
-
: entry));
|
|
2104
|
-
// Keep agent name visible even on failure (shows which agent was attempted)
|
|
2105
|
-
setIsStreaming(false);
|
|
2106
|
-
// Fall through to direct LLM processing below
|
|
2107
|
-
}
|
|
2108
|
-
}
|
|
2109
|
-
}
|
|
2110
|
-
}
|
|
2111
|
-
setIsStreaming(true);
|
|
2112
|
-
let streamingEntry = null;
|
|
2113
|
-
// Build message content - multimodal if images, otherwise text
|
|
2114
|
-
const messageContent = imageResult.hasImages
|
|
2115
|
-
? buildMessageContent(imageResult)
|
|
2116
|
-
: processedInput;
|
|
2117
|
-
for await (const chunk of agent.processUserMessageStream(messageContent)) {
|
|
2118
|
-
switch (chunk.type) {
|
|
2119
|
-
case "content":
|
|
2120
|
-
if (chunk.content !== undefined) {
|
|
2121
|
-
const shouldIgnore = shouldIgnoreContentChunk(chunk.content, !!streamingEntry);
|
|
2122
|
-
if (shouldIgnore) {
|
|
2123
|
-
break;
|
|
2124
|
-
}
|
|
2125
|
-
const contentChunk = chunk.content;
|
|
2126
|
-
if (!streamingEntry) {
|
|
2127
|
-
const newStreamingEntry = {
|
|
2128
|
-
type: "assistant",
|
|
2129
|
-
content: contentChunk,
|
|
2130
|
-
timestamp: new Date(),
|
|
2131
|
-
isStreaming: true,
|
|
2132
|
-
};
|
|
2133
|
-
setChatHistory((prev) => [...prev, newStreamingEntry]);
|
|
2134
|
-
streamingEntry = newStreamingEntry;
|
|
2135
|
-
}
|
|
2136
|
-
else {
|
|
2137
|
-
setChatHistory((prev) => prev.map((entry, idx) => idx === prev.length - 1 && entry.isStreaming
|
|
2138
|
-
? { ...entry, content: entry.content + contentChunk }
|
|
2139
|
-
: entry));
|
|
2140
|
-
}
|
|
2141
|
-
}
|
|
2142
|
-
break;
|
|
2143
|
-
case "token_count":
|
|
2144
|
-
if (chunk.tokenCount !== undefined) {
|
|
2145
|
-
setTokenCount(chunk.tokenCount);
|
|
2146
|
-
}
|
|
2147
|
-
break;
|
|
2148
|
-
case "tool_calls":
|
|
2149
|
-
if (chunk.toolCalls) {
|
|
2150
|
-
// Stop streaming for the current assistant message
|
|
2151
|
-
setChatHistory((prev) => prev.map((entry) => entry.isStreaming
|
|
2152
|
-
? {
|
|
2153
|
-
...entry,
|
|
2154
|
-
isStreaming: false,
|
|
2155
|
-
toolCalls: chunk.toolCalls,
|
|
2156
|
-
}
|
|
2157
|
-
: entry));
|
|
2158
|
-
streamingEntry = null;
|
|
2159
|
-
// Add individual tool call entries to show tools are being executed
|
|
2160
|
-
chunk.toolCalls.forEach((toolCall) => {
|
|
2161
|
-
const toolCallEntry = {
|
|
2162
|
-
type: "tool_call",
|
|
2163
|
-
content: "Executing...",
|
|
2164
|
-
timestamp: new Date(),
|
|
2165
|
-
toolCall: toolCall,
|
|
2166
|
-
};
|
|
2167
|
-
setChatHistory((prev) => [...prev, toolCallEntry]);
|
|
2168
|
-
});
|
|
2169
|
-
}
|
|
2170
|
-
break;
|
|
2171
|
-
case "tool_result":
|
|
2172
|
-
if (chunk.toolCall && chunk.toolResult) {
|
|
2173
|
-
setChatHistory((prev) => prev.map((entry) => {
|
|
2174
|
-
if (entry.isStreaming) {
|
|
2175
|
-
return { ...entry, isStreaming: false };
|
|
2176
|
-
}
|
|
2177
|
-
// Update the existing tool_call entry with the result
|
|
2178
|
-
if (entry.type === "tool_call" &&
|
|
2179
|
-
entry.toolCall?.id === chunk.toolCall?.id) {
|
|
2180
|
-
return {
|
|
2181
|
-
...entry,
|
|
2182
|
-
type: "tool_result",
|
|
2183
|
-
content: chunk.toolResult?.success
|
|
2184
|
-
? chunk.toolResult?.output || "Success"
|
|
2185
|
-
: chunk.toolResult?.error || "Error occurred",
|
|
2186
|
-
toolResult: chunk.toolResult,
|
|
2187
|
-
executionDurationMs: chunk.executionDurationMs,
|
|
2188
|
-
};
|
|
2189
|
-
}
|
|
2190
|
-
return entry;
|
|
2191
|
-
}));
|
|
2192
|
-
streamingEntry = null;
|
|
2193
|
-
}
|
|
2194
|
-
break;
|
|
2195
|
-
case "done":
|
|
2196
|
-
if (streamingEntry) {
|
|
2197
|
-
setChatHistory((prev) => prev.map((entry) => entry.isStreaming ? { ...entry, isStreaming: false } : entry));
|
|
2198
|
-
}
|
|
2199
|
-
setIsStreaming(false);
|
|
2200
|
-
break;
|
|
2201
|
-
}
|
|
2202
|
-
}
|
|
2203
|
-
}
|
|
2204
|
-
catch (error) {
|
|
2205
|
-
const errorMessage = extractErrorMessage(error);
|
|
2206
|
-
const errorEntry = {
|
|
2207
|
-
type: "assistant",
|
|
2208
|
-
content: `Error: ${errorMessage}`,
|
|
2209
|
-
timestamp: new Date(),
|
|
2210
|
-
};
|
|
2211
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
2212
|
-
setIsStreaming(false);
|
|
2213
|
-
}
|
|
2214
|
-
setIsProcessing(false);
|
|
2215
|
-
processingStartTime.current = 0;
|
|
2216
|
-
};
|
|
2217
|
-
return {
|
|
2218
|
-
input,
|
|
2219
|
-
cursorPosition,
|
|
2220
|
-
showCommandSuggestions,
|
|
2221
|
-
selectedCommandIndex,
|
|
2222
|
-
commandSuggestions,
|
|
2223
|
-
resourceSuggestions,
|
|
2224
|
-
suggestionMode,
|
|
2225
|
-
availableModels,
|
|
2226
|
-
agent,
|
|
2227
|
-
autoEditEnabled,
|
|
2228
|
-
verboseMode,
|
|
2229
|
-
verbosityLevel,
|
|
2230
|
-
backgroundMode,
|
|
2231
|
-
thinkingModeEnabled,
|
|
2232
|
-
pastedBlocks,
|
|
2233
|
-
currentBlockAtCursor,
|
|
2234
|
-
isPasting,
|
|
2235
|
-
toggleVerbosity: handleVerboseToggle,
|
|
2236
|
-
toggleAutoEdit: toggleAutoEditMode,
|
|
2237
|
-
toggleThinkingMode: handleThinkingModeToggle,
|
|
2238
|
-
toggleBackgroundMode: handleBackgroundModeToggle,
|
|
2239
|
-
};
|
|
2240
|
-
}
|
|
2241
|
-
/**
|
|
2242
|
-
* Determine whether a streaming content chunk should be ignored.
|
|
2243
|
-
* We ignore whitespace-only chunks before any assistant content exists to avoid
|
|
2244
|
-
* creating empty assistant messages that break tool grouping.
|
|
2245
|
-
*/
|
|
2246
|
-
export function shouldIgnoreContentChunk(content, hasActiveStreamingEntry) {
|
|
2247
|
-
if (hasActiveStreamingEntry)
|
|
2248
|
-
return false;
|
|
2249
|
-
return !content || content.trim() === "";
|
|
2250
|
-
}
|
|
2251
|
-
//# sourceMappingURL=use-input-handler.js.map
|