@winspan/claude-forge 3.1.0 → 3.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/ai/base-provider.d.ts.map +1 -0
- package/dist/ai/base-provider.js.map +1 -0
- package/dist/ai/factory.d.ts.map +1 -0
- package/dist/ai/factory.js.map +1 -0
- package/dist/{ai-gateway → ai}/index.d.ts +2 -2
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/model-selector.d.ts.map +1 -0
- package/dist/ai/model-selector.js.map +1 -0
- package/dist/ai/ollama-provider.d.ts.map +1 -0
- package/dist/ai/ollama-provider.js.map +1 -0
- package/dist/ai/openai-provider.d.ts.map +1 -0
- package/dist/ai/openai-provider.js.map +1 -0
- package/dist/ai/rate-limiter.d.ts.map +1 -0
- package/dist/ai/rate-limiter.js.map +1 -0
- package/dist/ai/response-cache.d.ts.map +1 -0
- package/dist/ai/response-cache.js.map +1 -0
- package/dist/ai/token-budget.d.ts.map +1 -0
- package/dist/ai/token-budget.js.map +1 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js.map +1 -0
- package/dist/autopilot/index.d.ts +0 -1
- package/dist/autopilot/index.d.ts.map +1 -1
- package/dist/autopilot/index.js +0 -1
- package/dist/autopilot/index.js.map +1 -1
- package/dist/autopilot/issue-tracker.d.ts +1 -1
- package/dist/autopilot/issue-tracker.d.ts.map +1 -1
- package/dist/autopilot/issue-tracker.js +1 -1
- package/dist/autopilot/issue-tracker.js.map +1 -1
- package/dist/autopilot/phase-gap-detector.d.ts +1 -1
- package/dist/autopilot/phase-gap-detector.d.ts.map +1 -1
- package/dist/autopilot/phase-gap-detector.js +1 -1
- package/dist/autopilot/phase-gap-detector.js.map +1 -1
- package/dist/autopilot/quality-gate.d.ts +2 -2
- package/dist/autopilot/quality-gate.d.ts.map +1 -1
- package/dist/autopilot/quality-gate.js +2 -2
- package/dist/autopilot/quality-gate.js.map +1 -1
- package/dist/autopilot/rule-distiller.d.ts +1 -1
- package/dist/autopilot/rule-distiller.d.ts.map +1 -1
- package/dist/autopilot/task-completion-detector.d.ts +2 -2
- package/dist/autopilot/task-completion-detector.d.ts.map +1 -1
- package/dist/claudemd/index.d.ts +1 -1
- package/dist/claudemd/index.d.ts.map +1 -1
- package/dist/claudemd/writer.js +1 -1
- package/dist/claudemd/writer.js.map +1 -1
- package/dist/cli/commands/pipeline.d.ts.map +1 -1
- package/dist/cli/commands/pipeline.js +3 -13
- package/dist/cli/commands/pipeline.js.map +1 -1
- package/dist/convention/convention-distiller.d.ts +1 -1
- package/dist/convention/convention-distiller.d.ts.map +1 -1
- package/dist/convention/convention-evolver.d.ts +1 -1
- package/dist/convention/convention-evolver.d.ts.map +1 -1
- package/dist/daemon/engine-registry/init-autopilot.d.ts +3 -3
- package/dist/daemon/engine-registry/init-autopilot.d.ts.map +1 -1
- package/dist/daemon/engine-registry/init-autopilot.js +7 -8
- package/dist/daemon/engine-registry/init-autopilot.js.map +1 -1
- package/dist/daemon/engine-registry/init-distill.d.ts +1 -1
- package/dist/daemon/engine-registry/init-distill.d.ts.map +1 -1
- package/dist/daemon/engine-registry/init-pipeline.d.ts +1 -1
- package/dist/daemon/engine-registry/init-pipeline.d.ts.map +1 -1
- package/dist/daemon/engine-registry/init-resume.d.ts +1 -1
- package/dist/daemon/engine-registry/init-resume.d.ts.map +1 -1
- package/dist/daemon/engine-registry/init-skill-registry.d.ts +1 -1
- package/dist/daemon/engine-registry/init-skill-registry.d.ts.map +1 -1
- package/dist/daemon/engine-registry.d.ts +1 -1
- package/dist/daemon/engine-registry.d.ts.map +1 -1
- package/dist/daemon/engine-registry.js +6 -6
- package/dist/daemon/engine-registry.js.map +1 -1
- package/dist/daemon/handler-context.d.ts +6 -6
- package/dist/daemon/handler-context.d.ts.map +1 -1
- package/dist/daemon/handlers/context-builder.js +1 -1
- package/dist/daemon/handlers/context-builder.js.map +1 -1
- package/dist/daemon/handlers/orchestration-context.d.ts +1 -1
- package/dist/daemon/handlers/orchestration-context.d.ts.map +1 -1
- package/dist/daemon/handlers/post-tool-use-handler.js +4 -4
- package/dist/daemon/handlers/post-tool-use-handler.js.map +1 -1
- package/dist/daemon/handlers/session-cleanup.d.ts.map +1 -1
- package/dist/daemon/handlers/session-cleanup.js +2 -16
- package/dist/daemon/handlers/session-cleanup.js.map +1 -1
- package/dist/daemon/handlers/stages/06-engine-check.js +1 -1
- package/dist/daemon/handlers/stages/06-engine-check.js.map +1 -1
- package/dist/daemon/handlers/stages/09-pipeline-active.d.ts.map +1 -1
- package/dist/daemon/handlers/stages/09-pipeline-active.js +0 -7
- package/dist/daemon/handlers/stages/09-pipeline-active.js.map +1 -1
- package/dist/daemon/handlers/stages/11-intent-analysis.d.ts +1 -1
- package/dist/daemon/handlers/stages/11-intent-analysis.d.ts.map +1 -1
- package/dist/daemon/handlers/stages/11-intent-analysis.js +12 -6
- package/dist/daemon/handlers/stages/11-intent-analysis.js.map +1 -1
- package/dist/daemon/handlers/stages/18-complex-task.js +1 -1
- package/dist/daemon/handlers/stages/18-complex-task.js.map +1 -1
- package/dist/daemon/handlers/stages/19-moderate-task.js +2 -2
- package/dist/daemon/handlers/stages/19-moderate-task.js.map +1 -1
- package/dist/daemon/handlers/stop-handler.js +3 -3
- package/dist/daemon/handlers/stop-handler.js.map +1 -1
- package/dist/daemon/handlers/user-prompt-handler.js +1 -1
- package/dist/daemon/handlers/user-prompt-handler.js.map +1 -1
- package/dist/daemon/index.js +3 -3
- package/dist/daemon/index.js.map +1 -1
- package/dist/distill/index.d.ts +1 -1
- package/dist/distill/index.d.ts.map +1 -1
- package/dist/distill/tree-index.d.ts +1 -1
- package/dist/distill/tree-index.d.ts.map +1 -1
- package/dist/distill/trigger.js +1 -1
- package/dist/distill/trigger.js.map +1 -1
- package/dist/distill/writer.d.ts +1 -1
- package/dist/distill/writer.d.ts.map +1 -1
- package/dist/goal/goal-classifier.d.ts +38 -0
- package/dist/goal/goal-classifier.d.ts.map +1 -0
- package/dist/{autopilot/intent-engine.js → goal/goal-classifier.js} +187 -297
- package/dist/goal/goal-classifier.js.map +1 -0
- package/dist/goal/goal-decomposer.d.ts +32 -0
- package/dist/goal/goal-decomposer.d.ts.map +1 -0
- package/dist/{pipeline/analyzer.js → goal/goal-decomposer.js} +45 -112
- package/dist/goal/goal-decomposer.js.map +1 -0
- package/dist/goal/goal-planner.d.ts +16 -0
- package/dist/goal/goal-planner.d.ts.map +1 -0
- package/dist/goal/goal-planner.js +90 -0
- package/dist/goal/goal-planner.js.map +1 -0
- package/dist/goal/goal-types.d.ts +62 -0
- package/dist/goal/goal-types.d.ts.map +1 -0
- package/dist/goal/goal-types.js +8 -0
- package/dist/goal/goal-types.js.map +1 -0
- package/dist/goal/index.d.ts +5 -0
- package/dist/goal/index.d.ts.map +1 -0
- package/dist/goal/index.js +4 -0
- package/dist/goal/index.js.map +1 -0
- package/dist/pipeline/artifact-generator.d.ts +1 -1
- package/dist/pipeline/artifact-generator.d.ts.map +1 -1
- package/dist/pipeline/artifact-generator.js +0 -1
- package/dist/pipeline/artifact-generator.js.map +1 -1
- package/dist/pipeline/dynamic-node-executor.d.ts +3 -29
- package/dist/pipeline/dynamic-node-executor.d.ts.map +1 -1
- package/dist/pipeline/dynamic-node-executor.js +49 -115
- package/dist/pipeline/dynamic-node-executor.js.map +1 -1
- package/dist/pipeline/execution-plan.d.ts +1 -1
- package/dist/pipeline/execution-plan.d.ts.map +1 -1
- package/dist/pipeline/index.d.ts +5 -13
- package/dist/pipeline/index.d.ts.map +1 -1
- package/dist/pipeline/index.js +23 -63
- package/dist/pipeline/index.js.map +1 -1
- package/dist/pipeline/node-runtime.d.ts +41 -0
- package/dist/pipeline/node-runtime.d.ts.map +1 -0
- package/dist/pipeline/node-runtime.js +73 -0
- package/dist/pipeline/node-runtime.js.map +1 -0
- package/dist/pipeline/semantic-validator.d.ts +1 -1
- package/dist/pipeline/semantic-validator.d.ts.map +1 -1
- package/dist/pipeline/step-orchestrator.d.ts +1 -1
- package/dist/pipeline/step-orchestrator.d.ts.map +1 -1
- package/dist/pipeline/store.d.ts +18 -48
- package/dist/pipeline/store.d.ts.map +1 -1
- package/dist/pipeline/store.js +101 -424
- package/dist/pipeline/store.js.map +1 -1
- package/dist/pipeline/template-router.d.ts +1 -1
- package/dist/pipeline/template-router.d.ts.map +1 -1
- package/dist/pipeline/types.d.ts +3 -3
- package/dist/pipeline/types.d.ts.map +1 -1
- package/dist/pipeline/types.js +1 -1
- package/dist/pipeline/types.js.map +1 -1
- package/dist/resume/context-gen.d.ts +1 -1
- package/dist/resume/context-gen.d.ts.map +1 -1
- package/dist/resume/index.d.ts +1 -1
- package/dist/resume/index.d.ts.map +1 -1
- package/dist/retrospective/index.d.ts +1 -1
- package/dist/retrospective/index.d.ts.map +1 -1
- package/dist/retrospective/pattern-learner.d.ts +1 -1
- package/dist/retrospective/pattern-learner.d.ts.map +1 -1
- package/dist/skill-registry/collector.d.ts +1 -1
- package/dist/skill-registry/collector.d.ts.map +1 -1
- package/dist/skill-registry/evolver/community-distiller.d.ts +1 -1
- package/dist/skill-registry/evolver/community-distiller.d.ts.map +1 -1
- package/dist/skill-registry/evolver/generation-engine.d.ts +1 -1
- package/dist/skill-registry/evolver/generation-engine.d.ts.map +1 -1
- package/dist/skill-registry/evolver/index.d.ts +1 -1
- package/dist/skill-registry/evolver/index.d.ts.map +1 -1
- package/dist/skill-registry/evolver/keyword-evolver.d.ts +1 -1
- package/dist/skill-registry/evolver/keyword-evolver.d.ts.map +1 -1
- package/dist/skill-registry/evolver/official-evolver.d.ts +1 -1
- package/dist/skill-registry/evolver/official-evolver.d.ts.map +1 -1
- package/dist/skill-registry/evolver/optimization-engine.d.ts +1 -1
- package/dist/skill-registry/evolver/optimization-engine.d.ts.map +1 -1
- package/dist/skill-registry/evolver/repair-engine.d.ts +1 -1
- package/dist/skill-registry/evolver/repair-engine.d.ts.map +1 -1
- package/dist/skill-registry/index.d.ts +1 -1
- package/dist/skill-registry/index.d.ts.map +1 -1
- package/dist/skill-registry/official-sync/skill-definitions.d.ts.map +1 -1
- package/dist/skill-registry/official-sync/skill-definitions.js +675 -0
- package/dist/skill-registry/official-sync/skill-definitions.js.map +1 -1
- package/dist/skill-registry/orchestrator.d.ts +1 -1
- package/dist/skill-registry/orchestrator.d.ts.map +1 -1
- package/dist/skill-registry/pattern-evolver.d.ts +1 -1
- package/dist/skill-registry/pattern-evolver.d.ts.map +1 -1
- package/dist/skill-registry/project-learner.d.ts +1 -1
- package/dist/skill-registry/project-learner.d.ts.map +1 -1
- package/dist/{core/types.d.ts → types/core-types.d.ts} +1 -1
- package/dist/types/core-types.d.ts.map +1 -0
- package/dist/{core/types.js → types/core-types.js} +1 -1
- package/dist/types/core-types.js.map +1 -0
- package/dist/utils/cache-registry.d.ts.map +1 -0
- package/dist/utils/cache-registry.js.map +1 -0
- package/dist/utils/circuit-breaker.js +1 -1
- package/dist/utils/circuit-breaker.js.map +1 -1
- package/dist/utils/claude-api.d.ts +3 -3
- package/dist/utils/claude-api.d.ts.map +1 -1
- package/dist/utils/claude-api.js +2 -2
- package/dist/utils/claude-api.js.map +1 -1
- package/dist/utils/error-handler.d.ts +0 -4
- package/dist/utils/error-handler.d.ts.map +1 -1
- package/dist/utils/error-handler.js +0 -20
- package/dist/utils/error-handler.js.map +1 -1
- package/dist/utils/pending-prompt-sink.d.ts.map +1 -0
- package/dist/utils/pending-prompt-sink.js.map +1 -0
- package/dist/web/routes/pipelines.d.ts.map +1 -1
- package/dist/web/routes/pipelines.js +68 -12
- package/dist/web/routes/pipelines.js.map +1 -1
- package/dist/web/routes/quality.d.ts +1 -1
- package/dist/web/routes/quality.d.ts.map +1 -1
- package/dist/web/server.d.ts +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web-static/assets/{index-DABYEmUB.js → index-3iTzJKjz.js} +1 -1
- package/dist/web-static/index.html +1 -1
- package/package.json +1 -1
- package/dist/ai-gateway/index.d.ts.map +0 -1
- package/dist/ai-gateway/index.js.map +0 -1
- package/dist/ai-gateway/model-selector.d.ts.map +0 -1
- package/dist/ai-gateway/model-selector.js.map +0 -1
- package/dist/ai-gateway/rate-limiter.d.ts.map +0 -1
- package/dist/ai-gateway/rate-limiter.js.map +0 -1
- package/dist/ai-gateway/response-cache.d.ts.map +0 -1
- package/dist/ai-gateway/response-cache.js.map +0 -1
- package/dist/ai-gateway/token-budget.d.ts.map +0 -1
- package/dist/ai-gateway/token-budget.js.map +0 -1
- package/dist/ai-provider/base-provider.d.ts.map +0 -1
- package/dist/ai-provider/base-provider.js.map +0 -1
- package/dist/ai-provider/factory.d.ts.map +0 -1
- package/dist/ai-provider/factory.js.map +0 -1
- package/dist/ai-provider/index.d.ts +0 -7
- package/dist/ai-provider/index.d.ts.map +0 -1
- package/dist/ai-provider/index.js +0 -6
- package/dist/ai-provider/index.js.map +0 -1
- package/dist/ai-provider/ollama-provider.d.ts.map +0 -1
- package/dist/ai-provider/ollama-provider.js.map +0 -1
- package/dist/ai-provider/openai-provider.d.ts.map +0 -1
- package/dist/ai-provider/openai-provider.js.map +0 -1
- package/dist/ai-provider/types.d.ts.map +0 -1
- package/dist/ai-provider/types.js.map +0 -1
- package/dist/autopilot/intent-engine.d.ts +0 -100
- package/dist/autopilot/intent-engine.d.ts.map +0 -1
- package/dist/autopilot/intent-engine.js.map +0 -1
- package/dist/autopilot/knowledge-engine.d.ts +0 -67
- package/dist/autopilot/knowledge-engine.d.ts.map +0 -1
- package/dist/autopilot/knowledge-engine.js +0 -262
- package/dist/autopilot/knowledge-engine.js.map +0 -1
- package/dist/core/cache-registry.d.ts.map +0 -1
- package/dist/core/cache-registry.js.map +0 -1
- package/dist/core/pending-prompt-sink.d.ts.map +0 -1
- package/dist/core/pending-prompt-sink.js.map +0 -1
- package/dist/core/types.d.ts.map +0 -1
- package/dist/core/types.js.map +0 -1
- package/dist/doc-sync/index.d.ts +0 -29
- package/dist/doc-sync/index.d.ts.map +0 -1
- package/dist/doc-sync/index.js +0 -276
- package/dist/doc-sync/index.js.map +0 -1
- package/dist/pipeline/aggregator.d.ts +0 -161
- package/dist/pipeline/aggregator.d.ts.map +0 -1
- package/dist/pipeline/aggregator.js +0 -261
- package/dist/pipeline/aggregator.js.map +0 -1
- package/dist/pipeline/analyzer.d.ts +0 -46
- package/dist/pipeline/analyzer.d.ts.map +0 -1
- package/dist/pipeline/analyzer.js.map +0 -1
- package/dist/pipeline/artifact-enforcement.d.ts +0 -74
- package/dist/pipeline/artifact-enforcement.d.ts.map +0 -1
- package/dist/pipeline/artifact-enforcement.js +0 -187
- package/dist/pipeline/artifact-enforcement.js.map +0 -1
- package/dist/pipeline/artifact-rules.d.ts +0 -39
- package/dist/pipeline/artifact-rules.d.ts.map +0 -1
- package/dist/pipeline/artifact-rules.js +0 -104
- package/dist/pipeline/artifact-rules.js.map +0 -1
- package/dist/pipeline/checkpoint.d.ts +0 -38
- package/dist/pipeline/checkpoint.d.ts.map +0 -1
- package/dist/pipeline/checkpoint.js +0 -132
- package/dist/pipeline/checkpoint.js.map +0 -1
- package/dist/pipeline/dynamic-aggregator.d.ts +0 -83
- package/dist/pipeline/dynamic-aggregator.d.ts.map +0 -1
- package/dist/pipeline/dynamic-aggregator.js +0 -303
- package/dist/pipeline/dynamic-aggregator.js.map +0 -1
- package/dist/pipeline/event-sourced-engine.d.ts +0 -77
- package/dist/pipeline/event-sourced-engine.d.ts.map +0 -1
- package/dist/pipeline/event-sourced-engine.js +0 -267
- package/dist/pipeline/event-sourced-engine.js.map +0 -1
- package/dist/pipeline/event-store.d.ts +0 -58
- package/dist/pipeline/event-store.d.ts.map +0 -1
- package/dist/pipeline/event-store.js +0 -184
- package/dist/pipeline/event-store.js.map +0 -1
- package/dist/pipeline/events.d.ts +0 -308
- package/dist/pipeline/events.d.ts.map +0 -1
- package/dist/pipeline/events.js +0 -49
- package/dist/pipeline/events.js.map +0 -1
- package/dist/pipeline/execution-plan-builder.d.ts +0 -20
- package/dist/pipeline/execution-plan-builder.d.ts.map +0 -1
- package/dist/pipeline/execution-plan-builder.js +0 -100
- package/dist/pipeline/execution-plan-builder.js.map +0 -1
- package/dist/pipeline/optimized-aggregator.d.ts +0 -36
- package/dist/pipeline/optimized-aggregator.d.ts.map +0 -1
- package/dist/pipeline/optimized-aggregator.js +0 -93
- package/dist/pipeline/optimized-aggregator.js.map +0 -1
- package/dist/pipeline/progress-tracker.d.ts +0 -29
- package/dist/pipeline/progress-tracker.d.ts.map +0 -1
- package/dist/pipeline/progress-tracker.js +0 -99
- package/dist/pipeline/progress-tracker.js.map +0 -1
- package/dist/pipeline/snapshot-store.d.ts +0 -45
- package/dist/pipeline/snapshot-store.d.ts.map +0 -1
- package/dist/pipeline/snapshot-store.js +0 -89
- package/dist/pipeline/snapshot-store.js.map +0 -1
- package/dist/pipeline/state-machine-types.d.ts +0 -157
- package/dist/pipeline/state-machine-types.d.ts.map +0 -1
- package/dist/pipeline/state-machine-types.js +0 -2
- package/dist/pipeline/state-machine-types.js.map +0 -1
- package/dist/pipeline/state-machine.d.ts +0 -44
- package/dist/pipeline/state-machine.d.ts.map +0 -1
- package/dist/pipeline/state-machine.js +0 -206
- package/dist/pipeline/state-machine.js.map +0 -1
- package/dist/pipeline/state-query.d.ts +0 -71
- package/dist/pipeline/state-query.d.ts.map +0 -1
- package/dist/pipeline/state-query.js +0 -213
- package/dist/pipeline/state-query.js.map +0 -1
- package/dist/pipeline/transitions.d.ts +0 -28
- package/dist/pipeline/transitions.d.ts.map +0 -1
- package/dist/pipeline/transitions.js +0 -336
- package/dist/pipeline/transitions.js.map +0 -1
- package/dist/strategy/bandit.d.ts +0 -51
- package/dist/strategy/bandit.d.ts.map +0 -1
- package/dist/strategy/bandit.js +0 -116
- package/dist/strategy/bandit.js.map +0 -1
- /package/dist/{ai-provider → ai}/base-provider.d.ts +0 -0
- /package/dist/{ai-provider → ai}/base-provider.js +0 -0
- /package/dist/{ai-provider → ai}/factory.d.ts +0 -0
- /package/dist/{ai-provider → ai}/factory.js +0 -0
- /package/dist/{ai-gateway → ai}/index.js +0 -0
- /package/dist/{ai-gateway → ai}/model-selector.d.ts +0 -0
- /package/dist/{ai-gateway → ai}/model-selector.js +0 -0
- /package/dist/{ai-provider → ai}/ollama-provider.d.ts +0 -0
- /package/dist/{ai-provider → ai}/ollama-provider.js +0 -0
- /package/dist/{ai-provider → ai}/openai-provider.d.ts +0 -0
- /package/dist/{ai-provider → ai}/openai-provider.js +0 -0
- /package/dist/{ai-gateway → ai}/rate-limiter.d.ts +0 -0
- /package/dist/{ai-gateway → ai}/rate-limiter.js +0 -0
- /package/dist/{ai-gateway → ai}/response-cache.d.ts +0 -0
- /package/dist/{ai-gateway → ai}/response-cache.js +0 -0
- /package/dist/{ai-gateway → ai}/token-budget.d.ts +0 -0
- /package/dist/{ai-gateway → ai}/token-budget.js +0 -0
- /package/dist/{ai-provider → ai}/types.d.ts +0 -0
- /package/dist/{ai-provider → ai}/types.js +0 -0
- /package/dist/{core → utils}/cache-registry.d.ts +0 -0
- /package/dist/{core → utils}/cache-registry.js +0 -0
- /package/dist/{core → utils}/pending-prompt-sink.d.ts +0 -0
- /package/dist/{core → utils}/pending-prompt-sink.js +0 -0
|
@@ -3,31 +3,19 @@ import path from 'path';
|
|
|
3
3
|
import { logger } from '../utils/logger.js';
|
|
4
4
|
import { TreeIndexEngine } from '../distill/tree-index.js';
|
|
5
5
|
import { readActivePlanSummary } from '../utils/plan-reader.js';
|
|
6
|
-
import { RuleDistiller } from '
|
|
6
|
+
import { RuleDistiller } from '../autopilot/rule-distiller.js';
|
|
7
7
|
import { PromptRegistry } from '../prompts/registry.js';
|
|
8
|
-
import { cacheRegistry } from '../
|
|
8
|
+
import { cacheRegistry } from '../utils/cache-registry.js';
|
|
9
9
|
import { CACHE, TIME } from '../constants.js';
|
|
10
|
-
import { matchGroundTruth } from '
|
|
11
|
-
|
|
12
|
-
* IntentEngine — 意图识别引擎
|
|
13
|
-
*
|
|
14
|
-
* 所有用户输入都会拦截分析,根据项目实际情况判断:
|
|
15
|
-
* - simple: 纯对话、查看文件、运行命令等不涉及代码改动的操作 → 直接放行
|
|
16
|
-
* - moderate: 改动范围较小(少量文件) → 注入提示,不启动 Pipeline
|
|
17
|
-
* - complex: 改动范围大、需求不明确、需要任务拆分和质量管控 → 启动 Pipeline 编排
|
|
18
|
-
*/
|
|
19
|
-
export class IntentEngine {
|
|
10
|
+
import { matchGroundTruth } from '../autopilot/ground-truth-rules.js';
|
|
11
|
+
export class GoalClassifier {
|
|
20
12
|
api;
|
|
21
13
|
storage = null;
|
|
22
14
|
ruleDistiller = null;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
/** 意图规则缓存,TTL=5min,避免每次 analyze 都查 DB */
|
|
28
|
-
rulesCache = cacheRegistry.register('intent:rules', { max: CACHE.INTENT_STRUCTURE_MAX, ttl: TIME.FIVE_MINUTES });
|
|
29
|
-
/** TreeIndex 推理检索结果缓存,key=projectPath:requirement,TTL=2min */
|
|
30
|
-
treeIndexCache = cacheRegistry.register('intent:treeIndex', { max: CACHE.INTENT_TREE_MAX, ttl: TIME.TWO_MINUTES });
|
|
15
|
+
structureCache = cacheRegistry.register('goal:structure', { max: CACHE.INTENT_STRUCTURE_MAX, ttl: TIME.TWO_MINUTES });
|
|
16
|
+
decisionsCache = cacheRegistry.register('goal:decisions', { max: CACHE.INTENT_STRUCTURE_MAX, ttl: TIME.FIVE_MINUTES });
|
|
17
|
+
rulesCache = cacheRegistry.register('goal:rules', { max: CACHE.INTENT_STRUCTURE_MAX, ttl: TIME.FIVE_MINUTES });
|
|
18
|
+
treeIndexCache = cacheRegistry.register('goal:treeIndex', { max: CACHE.INTENT_TREE_MAX, ttl: TIME.TWO_MINUTES });
|
|
31
19
|
constructor(api, storage) {
|
|
32
20
|
this.api = api;
|
|
33
21
|
if (storage) {
|
|
@@ -35,60 +23,22 @@ export class IntentEngine {
|
|
|
35
23
|
this.ruleDistiller = new RuleDistiller(storage);
|
|
36
24
|
}
|
|
37
25
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
async distillRules(projectPath) {
|
|
42
|
-
if (!this.ruleDistiller)
|
|
43
|
-
return 0;
|
|
44
|
-
const count = await this.ruleDistiller.distillRules(projectPath);
|
|
45
|
-
// 规则更新后失效缓存,下次 analyze 重新加载
|
|
46
|
-
this.rulesCache.delete(projectPath);
|
|
47
|
-
return count;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* daemon 启动时预热规则缓存,降低首次 analyze 的数据库读取延迟
|
|
51
|
-
*/
|
|
52
|
-
warmupRulesCache(projectPath) {
|
|
53
|
-
if (!this.ruleDistiller)
|
|
54
|
-
return;
|
|
55
|
-
try {
|
|
56
|
-
const rules = this.getRulesFromStorage(projectPath);
|
|
57
|
-
if (rules.length > 0) {
|
|
58
|
-
logger.info(`[意图分析] 已预热规则缓存:${projectPath}(${rules.length} 条)`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
catch (err) {
|
|
62
|
-
logger.warn(`[意图分析] 规则缓存预热失败:${err}`);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* 分析用户输入的意图和复杂度
|
|
67
|
-
* @param conversationHistory 会话上下文(最近的用户输入和工具调用摘要)
|
|
68
|
-
* @param activePlan 当前活跃计划摘要(跨 session 的任务续接状态)
|
|
69
|
-
* @param sessionId 当前 session ID(用于决策日志)
|
|
70
|
-
*/
|
|
71
|
-
async analyze(userPrompt, projectPath, techStack, conversationHistory, isForgeManaged, activePlan, sessionId) {
|
|
72
|
-
// 快速放行:纯对话和无改动操作
|
|
73
|
-
// 注意:有会话上下文时(多轮对话中),短输入可能是确认回复,不应被快速过滤
|
|
26
|
+
async classify(userPrompt, projectPath, options = {}) {
|
|
27
|
+
const { techStack, conversationHistory, isForgeManaged, activePlan, sessionId } = options;
|
|
28
|
+
const sessionIdVal = sessionId ?? '';
|
|
74
29
|
const quickResult = this.quickFilter(userPrompt, !!conversationHistory);
|
|
75
30
|
if (quickResult) {
|
|
76
31
|
logger.info(`快速判定:${quickResult.complexity} | 理由=${quickResult.reasoning}`);
|
|
77
|
-
return quickResult;
|
|
32
|
+
return { ...quickResult, projectPath, sessionId: sessionIdVal, taskType: 'other' };
|
|
78
33
|
}
|
|
79
|
-
//
|
|
34
|
+
// Layer 1: Ground Truth
|
|
80
35
|
const gtMatch = matchGroundTruth(userPrompt);
|
|
81
36
|
if (gtMatch) {
|
|
82
|
-
// 需要上下文检查的规则(如"执行已有规划"):验证活跃计划是否存在
|
|
83
37
|
if (gtMatch.requiresContextCheck) {
|
|
84
38
|
const plan = activePlan ?? this.getActivePlan(projectPath);
|
|
85
|
-
if (
|
|
86
|
-
logger.info(`[
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
logger.info(`[意图分析] Ground Truth 命中: ${gtMatch.id} → ${gtMatch.complexity}(检测到活跃计划:${plan.title})`);
|
|
91
|
-
const gtResult = {
|
|
39
|
+
if (plan) {
|
|
40
|
+
logger.info(`[GoalClassifier] Ground Truth 命中: ${gtMatch.id} → ${gtMatch.complexity}(活跃计划:${plan.title})`);
|
|
41
|
+
const goal = {
|
|
92
42
|
complexity: gtMatch.complexity,
|
|
93
43
|
requiresPipeline: false,
|
|
94
44
|
requirement: userPrompt,
|
|
@@ -97,14 +47,17 @@ export class IntentEngine {
|
|
|
97
47
|
suggestedPhases: ['code', 'test'],
|
|
98
48
|
skipPhases: ['analyze', 'design'],
|
|
99
49
|
confidence: 1.0,
|
|
50
|
+
projectPath,
|
|
51
|
+
sessionId: sessionIdVal,
|
|
52
|
+
taskType: 'other',
|
|
100
53
|
};
|
|
101
|
-
this.logDecision(
|
|
102
|
-
return
|
|
54
|
+
this.logDecision(sessionIdVal, projectPath, userPrompt, gtMatch.complexity, 'ground_truth', gtMatch.id, 1.0);
|
|
55
|
+
return goal;
|
|
103
56
|
}
|
|
104
57
|
}
|
|
105
58
|
else {
|
|
106
|
-
logger.info(`[
|
|
107
|
-
const
|
|
59
|
+
logger.info(`[GoalClassifier] Ground Truth 命中: ${gtMatch.id} → ${gtMatch.complexity}`);
|
|
60
|
+
const goal = {
|
|
108
61
|
complexity: gtMatch.complexity,
|
|
109
62
|
requiresPipeline: gtMatch.complexity === 'complex',
|
|
110
63
|
requirement: userPrompt,
|
|
@@ -112,111 +65,104 @@ export class IntentEngine {
|
|
|
112
65
|
estimatedFiles: gtMatch.complexity === 'simple' ? 0 : gtMatch.complexity === 'moderate' ? 3 : 8,
|
|
113
66
|
suggestedPhases: gtMatch.complexity === 'complex' ? ['analyze', 'code', 'test'] : gtMatch.complexity === 'moderate' ? ['code', 'test'] : [],
|
|
114
67
|
confidence: 1.0,
|
|
68
|
+
projectPath,
|
|
69
|
+
sessionId: sessionIdVal,
|
|
70
|
+
taskType: 'other',
|
|
115
71
|
};
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return gtResult;
|
|
72
|
+
this.logDecision(sessionIdVal, projectPath, userPrompt, gtMatch.complexity, 'ground_truth', gtMatch.id, 1.0);
|
|
73
|
+
return goal;
|
|
119
74
|
}
|
|
120
75
|
}
|
|
121
|
-
//
|
|
76
|
+
// Layer 2: Learned Rules
|
|
122
77
|
if (this.ruleDistiller) {
|
|
123
78
|
try {
|
|
124
79
|
const rules = this.getActiveLearnedRulesFromStorage(projectPath);
|
|
125
80
|
if (rules.length > 0) {
|
|
126
81
|
const ruleResult = this.ruleDistiller.matchRules(userPrompt, rules);
|
|
127
|
-
// 提高置信度门槛到 0.7,只有高质量规则才能跳过 AI
|
|
128
82
|
if (ruleResult && (ruleResult.confidence ?? 0) >= 0.7) {
|
|
129
|
-
logger.info(`[
|
|
130
|
-
this.logDecision(
|
|
131
|
-
return ruleResult;
|
|
83
|
+
logger.info(`[GoalClassifier] 规则库命中: complexity=${ruleResult.complexity}`);
|
|
84
|
+
this.logDecision(sessionIdVal, projectPath, userPrompt, ruleResult.complexity, 'learned', null, ruleResult.confidence ?? 0);
|
|
85
|
+
return { ...ruleResult, projectPath, sessionId: sessionIdVal, taskType: inferTaskType(userPrompt) };
|
|
132
86
|
}
|
|
133
87
|
}
|
|
134
88
|
}
|
|
135
|
-
catch {
|
|
136
|
-
// 规则库查询失败,继续走 AI 分析
|
|
137
|
-
}
|
|
89
|
+
catch { /* continue to AI */ }
|
|
138
90
|
}
|
|
139
|
-
//
|
|
91
|
+
// Layer 3: AI Fallback
|
|
140
92
|
try {
|
|
141
93
|
const result = await this.aiAnalyze(userPrompt, projectPath, techStack, conversationHistory, activePlan);
|
|
142
|
-
// 低置信度主动澄清:confidence < 0.6 且有澄清问题时,强制降级为 simple + 附带澄清问题
|
|
143
94
|
if (result.confidence !== undefined && result.confidence < 0.6 && result.clarifyQuestions && result.clarifyQuestions.length > 0) {
|
|
144
|
-
logger.warn(`[
|
|
145
|
-
this.logDecision(
|
|
95
|
+
logger.warn(`[GoalClassifier] 置信度过低 (${result.confidence.toFixed(2)}),触发主动澄清`);
|
|
96
|
+
this.logDecision(sessionIdVal, projectPath, userPrompt, 'simple', 'ai_fallback', null, result.confidence);
|
|
146
97
|
return {
|
|
147
98
|
...result,
|
|
148
99
|
complexity: 'simple',
|
|
149
100
|
requiresPipeline: false,
|
|
150
101
|
reasoning: `${result.reasoning}\n\n⚠️ 置信度过低 (${(result.confidence * 100).toFixed(0)}%),建议先澄清需求`,
|
|
102
|
+
projectPath,
|
|
103
|
+
sessionId: sessionIdVal,
|
|
104
|
+
taskType: inferTaskType(userPrompt),
|
|
151
105
|
};
|
|
152
106
|
}
|
|
153
|
-
this.logDecision(
|
|
154
|
-
return result;
|
|
107
|
+
this.logDecision(sessionIdVal, projectPath, userPrompt, result.complexity, 'ai_fallback', null, result.confidence ?? 0.5);
|
|
108
|
+
return { ...result, projectPath, sessionId: sessionIdVal, taskType: inferTaskType(userPrompt) };
|
|
155
109
|
}
|
|
156
110
|
catch (err) {
|
|
157
|
-
logger.warn(`[
|
|
158
|
-
|
|
111
|
+
logger.warn(`[GoalClassifier] AI 分析失败,使用降级方案:${err}`);
|
|
112
|
+
const fb = this.fallbackAnalyze(userPrompt, isForgeManaged);
|
|
113
|
+
return { ...fb, projectPath, sessionId: sessionIdVal, taskType: inferTaskType(userPrompt) };
|
|
159
114
|
}
|
|
160
115
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
116
|
+
async distillRules(projectPath) {
|
|
117
|
+
if (!this.ruleDistiller)
|
|
118
|
+
return 0;
|
|
119
|
+
const count = await this.ruleDistiller.distillRules(projectPath);
|
|
120
|
+
this.rulesCache.delete(projectPath);
|
|
121
|
+
return count;
|
|
122
|
+
}
|
|
123
|
+
warmupRulesCache(projectPath) {
|
|
124
|
+
if (!this.ruleDistiller)
|
|
164
125
|
return;
|
|
165
126
|
try {
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
project_path: projectPath,
|
|
171
|
-
requirement,
|
|
172
|
-
predicted_complexity: complexity,
|
|
173
|
-
matched_rule_id: matchedRuleId,
|
|
174
|
-
matched_layer: layer,
|
|
175
|
-
confidence,
|
|
176
|
-
});
|
|
127
|
+
const rules = this.getActiveLearnedRulesFromStorage(projectPath);
|
|
128
|
+
if (rules.length > 0) {
|
|
129
|
+
logger.info(`[GoalClassifier] 已预热规则缓存:${projectPath}(${rules.length} 条)`);
|
|
130
|
+
}
|
|
177
131
|
}
|
|
178
132
|
catch (err) {
|
|
179
|
-
logger.
|
|
133
|
+
logger.warn(`[GoalClassifier] 规则缓存预热失败:${err}`);
|
|
180
134
|
}
|
|
181
135
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
const cached = this.rulesCache.get(projectPath);
|
|
185
|
-
if (cached)
|
|
186
|
-
return cached;
|
|
187
|
-
// 优先使用 getActiveLearnedRules(v20 新方法),降级到 getIntentRules
|
|
188
|
-
const data = this.storage?.getActiveLearnedRules?.() ??
|
|
189
|
-
this.ruleDistiller?.storage?.getIntentRules() ?? [];
|
|
190
|
-
this.rulesCache.set(projectPath, data);
|
|
191
|
-
return data;
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* @deprecated Use getActiveLearnedRulesFromStorage instead
|
|
195
|
-
*/
|
|
196
|
-
getRulesFromStorage(projectPath) {
|
|
197
|
-
return this.getActiveLearnedRulesFromStorage(projectPath);
|
|
136
|
+
invalidateStructureCache(projectPath) {
|
|
137
|
+
this.structureCache.delete(projectPath);
|
|
198
138
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
139
|
+
generateDirective(analysis) {
|
|
140
|
+
if (analysis.complexity === 'simple')
|
|
141
|
+
return null;
|
|
142
|
+
const parts = [];
|
|
143
|
+
if (analysis.requiresPipeline) {
|
|
144
|
+
parts.push(`[Forge Autopilot] 检测到复杂需求,已启动 Pipeline 编排。`);
|
|
145
|
+
parts.push(`需求:${analysis.requirement}`);
|
|
146
|
+
parts.push(`阶段:${analysis.suggestedPhases.join(' → ')}`);
|
|
147
|
+
parts.push('');
|
|
148
|
+
parts.push('请按 Pipeline 阶段指令逐步执行,每步完成后等待质量门禁审查。');
|
|
203
149
|
}
|
|
204
|
-
|
|
205
|
-
|
|
150
|
+
else {
|
|
151
|
+
parts.push(`[Forge] 建议关注:${analysis.requirement}`);
|
|
152
|
+
if (analysis.searchKeywords && analysis.searchKeywords.length > 0) {
|
|
153
|
+
parts.push(`参考关键词:${analysis.searchKeywords.join(', ')}`);
|
|
154
|
+
}
|
|
206
155
|
}
|
|
156
|
+
return parts.join('\n');
|
|
157
|
+
}
|
|
158
|
+
getProvider() {
|
|
159
|
+
return this.api;
|
|
207
160
|
}
|
|
208
|
-
/**
|
|
209
|
-
* 快速放行:只过滤明确不涉及代码改动的操作。
|
|
210
|
-
* @param hasConversation 是否有会话上下文(多轮对话中)。有上下文时短输入可能是确认回复,应交给 AI 判断。
|
|
211
|
-
*/
|
|
212
161
|
quickFilter(prompt, hasConversation) {
|
|
213
162
|
const lower = prompt.toLowerCase().trim();
|
|
214
|
-
// 确认类回复(同意/好的/是/继续/A/B/C 等)不应被截胡,直接透传给 Claude
|
|
215
163
|
const confirmPatterns = /^(同意|好的|好|是|是的|可以|行|ok|yes|sure|继续|go|proceed|确认|没问题|对|嗯|[a-c])$/i;
|
|
216
|
-
if (confirmPatterns.test(lower))
|
|
217
|
-
return null;
|
|
218
|
-
}
|
|
219
|
-
// 纯对话 / 提问:不涉及改动
|
|
164
|
+
if (confirmPatterns.test(lower))
|
|
165
|
+
return null;
|
|
220
166
|
const conversationPatterns = [
|
|
221
167
|
/^(看|查看|显示|cat|show|read|explain|解释|描述)/i,
|
|
222
168
|
/^(help|帮助|what|什么|how|怎么|为什么|why|where|哪)/i,
|
|
@@ -225,17 +171,9 @@ export class IntentEngine {
|
|
|
225
171
|
];
|
|
226
172
|
for (const pattern of conversationPatterns) {
|
|
227
173
|
if (pattern.test(lower)) {
|
|
228
|
-
return {
|
|
229
|
-
complexity: 'simple',
|
|
230
|
-
requiresPipeline: false,
|
|
231
|
-
requirement: prompt,
|
|
232
|
-
reasoning: '纯对话/提问,不涉及代码改动',
|
|
233
|
-
estimatedFiles: 0,
|
|
234
|
-
suggestedPhases: [],
|
|
235
|
-
};
|
|
174
|
+
return { complexity: 'simple', requiresPipeline: false, requirement: prompt, reasoning: '纯对话/提问,不涉及代码改动', estimatedFiles: 0, suggestedPhases: [] };
|
|
236
175
|
}
|
|
237
176
|
}
|
|
238
|
-
// git / 运行命令:不涉及代码改动
|
|
239
177
|
const commandPatterns = [
|
|
240
178
|
/^(commit|push|pull|merge|rebase|stash|checkout|branch)/i,
|
|
241
179
|
/^(run|执行|启动)\s+(test|lint|build|dev|start|serve)/i,
|
|
@@ -243,43 +181,22 @@ export class IntentEngine {
|
|
|
243
181
|
];
|
|
244
182
|
for (const pattern of commandPatterns) {
|
|
245
183
|
if (pattern.test(lower)) {
|
|
246
|
-
return {
|
|
247
|
-
complexity: 'simple',
|
|
248
|
-
requiresPipeline: false,
|
|
249
|
-
requirement: prompt,
|
|
250
|
-
reasoning: '运行命令/Git 操作,不涉及代码改动',
|
|
251
|
-
estimatedFiles: 0,
|
|
252
|
-
suggestedPhases: [],
|
|
253
|
-
};
|
|
184
|
+
return { complexity: 'simple', requiresPipeline: false, requirement: prompt, reasoning: '运行命令/Git 操作,不涉及代码改动', estimatedFiles: 0, suggestedPhases: [] };
|
|
254
185
|
}
|
|
255
186
|
}
|
|
256
|
-
// 极短输入且不含动词:有会话上下文时不过滤(可能是对上轮问题的回复)
|
|
257
187
|
if (!hasConversation) {
|
|
258
188
|
const hasActionVerb = /修|改|加|删|实现|重构|优化|fix|add|remove|create|update|refactor|implement|build/i.test(lower);
|
|
259
189
|
if (prompt.length < 4 && !hasActionVerb) {
|
|
260
|
-
return {
|
|
261
|
-
complexity: 'simple',
|
|
262
|
-
requiresPipeline: false,
|
|
263
|
-
requirement: prompt,
|
|
264
|
-
reasoning: '极短输入且无改动动词(无会话上下文),判定为对话',
|
|
265
|
-
estimatedFiles: 0,
|
|
266
|
-
suggestedPhases: [],
|
|
267
|
-
};
|
|
190
|
+
return { complexity: 'simple', requiresPipeline: false, requirement: prompt, reasoning: '极短输入且无改动动词(无会话上下文),判定为对话', estimatedFiles: 0, suggestedPhases: [] };
|
|
268
191
|
}
|
|
269
192
|
}
|
|
270
|
-
return null;
|
|
193
|
+
return null;
|
|
271
194
|
}
|
|
272
|
-
/**
|
|
273
|
-
* AI 分析意图(带项目上下文)
|
|
274
|
-
*/
|
|
275
195
|
async aiAnalyze(userPrompt, projectPath, techStack, conversationHistory, activePlan) {
|
|
276
196
|
const contextInfo = await this.readDecisionsContext(userPrompt, projectPath);
|
|
277
197
|
const projectStructure = this.getProjectStructure(projectPath);
|
|
278
|
-
const historySection = conversationHistory
|
|
279
|
-
|
|
280
|
-
: '';
|
|
281
|
-
const planSection = activePlan
|
|
282
|
-
? `\n## 当前活跃计划(跨 session 任务续接状态)
|
|
198
|
+
const historySection = conversationHistory ? `\n## 会话上下文(最近的对话和操作)\n${conversationHistory}\n` : '';
|
|
199
|
+
const planSection = activePlan ? `\n## 当前活跃计划(跨 session 任务续接状态)
|
|
283
200
|
计划文件: ${activePlan.relPath}
|
|
284
201
|
计划标题: ${activePlan.title}
|
|
285
202
|
进行中任务: ${activePlan.inProgress.length > 0 ? activePlan.inProgress.map(t => `\n - ${t}`).join('') : '无'}
|
|
@@ -287,8 +204,7 @@ export class IntentEngine {
|
|
|
287
204
|
已完成: ${activePlan.doneCount} 个任务
|
|
288
205
|
|
|
289
206
|
**重要**:如果用户输入是对上述任务的续接(如"继续"、"下一步"、任务相关的具体指令),应判定为 simple 或 moderate,直接执行,不要重新启动 Pipeline 或 Plan Mode。
|
|
290
|
-
`
|
|
291
|
-
: '';
|
|
207
|
+
` : '';
|
|
292
208
|
const techStackSection = techStack ? `技术栈: ${techStack}` : '';
|
|
293
209
|
const projectStructureSection = projectStructure ? `项目结构:\n${projectStructure}` : '';
|
|
294
210
|
const contextInfoSection = contextInfo ? `近期工作上下文: ${contextInfo}` : '';
|
|
@@ -304,94 +220,16 @@ export class IntentEngine {
|
|
|
304
220
|
const response = await this.api.complete(prompt, 'intent');
|
|
305
221
|
return this.parseAnalysis(response, userPrompt);
|
|
306
222
|
}
|
|
307
|
-
/**
|
|
308
|
-
* 获取项目结构摘要(给 AI 提供上下文)
|
|
309
|
-
*/
|
|
310
|
-
getProjectStructure(projectPath) {
|
|
311
|
-
const cached = this.structureCache.get(projectPath);
|
|
312
|
-
if (cached)
|
|
313
|
-
return cached;
|
|
314
|
-
try {
|
|
315
|
-
if (!fs.existsSync(projectPath))
|
|
316
|
-
return '';
|
|
317
|
-
const lines = [];
|
|
318
|
-
const entries = fs.readdirSync(projectPath, { withFileTypes: true });
|
|
319
|
-
// 收集一级目录和关键文件
|
|
320
|
-
const dirs = [];
|
|
321
|
-
const files = [];
|
|
322
|
-
const skipDirs = new Set(['node_modules', '.git', 'dist', 'build', '.next', '__pycache__', '.claude', '.claude-forge', 'vendor', 'target']);
|
|
323
|
-
for (const entry of entries) {
|
|
324
|
-
if (entry.name.startsWith('.') && entry.name !== '.env.example')
|
|
325
|
-
continue;
|
|
326
|
-
if (skipDirs.has(entry.name))
|
|
327
|
-
continue;
|
|
328
|
-
if (entry.isDirectory()) {
|
|
329
|
-
dirs.push(entry.name + '/');
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
files.push(entry.name);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
if (dirs.length > 0)
|
|
336
|
-
lines.push(`目录: ${dirs.join(', ')}`);
|
|
337
|
-
if (files.length > 0)
|
|
338
|
-
lines.push(`文件: ${files.join(', ')}`);
|
|
339
|
-
// 尝试读取 src/ 的一级子目录,了解模块划分
|
|
340
|
-
const srcPath = path.join(projectPath, 'src');
|
|
341
|
-
if (fs.existsSync(srcPath)) {
|
|
342
|
-
const srcEntries = fs.readdirSync(srcPath, { withFileTypes: true });
|
|
343
|
-
const srcDirs = srcEntries
|
|
344
|
-
.filter(e => e.isDirectory() && !e.name.startsWith('.'))
|
|
345
|
-
.map(e => e.name + '/');
|
|
346
|
-
if (srcDirs.length > 0) {
|
|
347
|
-
lines.push(`src/ 模块: ${srcDirs.join(', ')}`);
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
const data = lines.join('\n');
|
|
351
|
-
this.structureCache.set(projectPath, data);
|
|
352
|
-
return data;
|
|
353
|
-
}
|
|
354
|
-
catch {
|
|
355
|
-
return '';
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
/**
|
|
359
|
-
* 降级分析:AI 不可用时的保底策略
|
|
360
|
-
* Forge 管理项目:检测到改动动词时保守判定为需要 Pipeline,防止绕过编排
|
|
361
|
-
*/
|
|
362
223
|
fallbackAnalyze(prompt, isForgeManaged) {
|
|
363
|
-
// 有明确的代码改动动词 → moderate
|
|
364
224
|
const hasAction = /修|改|加|删|实现|重构|优化|fix|add|remove|create|update|refactor|implement|build/i.test(prompt);
|
|
365
225
|
if (!hasAction) {
|
|
366
|
-
return {
|
|
367
|
-
complexity: 'simple',
|
|
368
|
-
requiresPipeline: false,
|
|
369
|
-
requirement: prompt,
|
|
370
|
-
reasoning: 'AI 分析不可用,未检测到改动动词,降级判定为对话',
|
|
371
|
-
estimatedFiles: 0,
|
|
372
|
-
suggestedPhases: [],
|
|
373
|
-
};
|
|
226
|
+
return { complexity: 'simple', requiresPipeline: false, requirement: prompt, reasoning: 'AI 分析不可用,未检测到改动动词,降级判定为对话', estimatedFiles: 0, suggestedPhases: [] };
|
|
374
227
|
}
|
|
375
|
-
// Forge 管理项目:AI 失败时保守判定,要求 Pipeline 编排,防止代码变更绕过产物生成
|
|
376
228
|
if (isForgeManaged) {
|
|
377
|
-
logger.warn('[
|
|
378
|
-
return {
|
|
379
|
-
complexity: 'moderate',
|
|
380
|
-
requiresPipeline: true,
|
|
381
|
-
requirement: prompt,
|
|
382
|
-
reasoning: 'AI 分析不可用,Forge 管理项目检测到改动动词,保守判定为需要 Pipeline 编排',
|
|
383
|
-
estimatedFiles: 0,
|
|
384
|
-
suggestedPhases: ['analyze', 'code', 'test'],
|
|
385
|
-
};
|
|
229
|
+
logger.warn('[GoalClassifier] AI 不可用,Forge 管理项目检测到改动动词,保守判定为需要 Pipeline');
|
|
230
|
+
return { complexity: 'moderate', requiresPipeline: true, requirement: prompt, reasoning: 'AI 分析不可用,Forge 管理项目检测到改动动词,保守判定为需要 Pipeline 编排', estimatedFiles: 0, suggestedPhases: ['analyze', 'code', 'test'] };
|
|
386
231
|
}
|
|
387
|
-
return {
|
|
388
|
-
complexity: 'moderate',
|
|
389
|
-
requiresPipeline: false,
|
|
390
|
-
requirement: prompt,
|
|
391
|
-
reasoning: 'AI 分析不可用,检测到改动动词,降级判定为中等复杂度',
|
|
392
|
-
estimatedFiles: 0,
|
|
393
|
-
suggestedPhases: ['code', 'test'],
|
|
394
|
-
};
|
|
232
|
+
return { complexity: 'moderate', requiresPipeline: false, requirement: prompt, reasoning: 'AI 分析不可用,检测到改动动词,降级判定为中等复杂度', estimatedFiles: 0, suggestedPhases: ['code', 'test'] };
|
|
395
233
|
}
|
|
396
234
|
parseAnalysis(response, originalPrompt) {
|
|
397
235
|
try {
|
|
@@ -414,44 +252,33 @@ export class IntentEngine {
|
|
|
414
252
|
};
|
|
415
253
|
}
|
|
416
254
|
catch {
|
|
417
|
-
logger.warn('[
|
|
255
|
+
logger.warn('[GoalClassifier] AI 响应解析失败');
|
|
418
256
|
return this.fallbackAnalyze(originalPrompt);
|
|
419
257
|
}
|
|
420
258
|
}
|
|
421
|
-
/**
|
|
422
|
-
* 读取项目蒸馏产出的 decisions.md 作为上下文
|
|
423
|
-
* 优先走树索引推理检索,降级到关键词切片
|
|
424
|
-
*/
|
|
425
259
|
async readDecisionsContext(requirement, projectPath) {
|
|
426
260
|
const decisionsPath = path.join(projectPath, '.claude-forge', 'decisions.md');
|
|
427
|
-
// 先查 TreeIndex 结果缓存
|
|
428
261
|
const cacheKey = `${projectPath}:${requirement.slice(0, 100)}`;
|
|
429
262
|
const cached = this.treeIndexCache.get(cacheKey);
|
|
430
263
|
if (cached) {
|
|
431
|
-
logger.debug(`[
|
|
264
|
+
logger.debug(`[GoalClassifier] TreeIndex 缓存命中`);
|
|
432
265
|
return cached;
|
|
433
266
|
}
|
|
434
|
-
// 优先走树索引推理检索
|
|
435
267
|
try {
|
|
436
268
|
const index = TreeIndexEngine.loadFromFile(decisionsPath);
|
|
437
269
|
if (index && !TreeIndexEngine.isStale(decisionsPath)) {
|
|
438
270
|
const engine = new TreeIndexEngine(this.api);
|
|
439
271
|
const result = await engine.search(index, requirement);
|
|
440
272
|
if (result) {
|
|
441
|
-
logger.debug(`[
|
|
273
|
+
logger.debug(`[GoalClassifier] 树索引推理检索成功,返回 ${result.length} 字符`);
|
|
442
274
|
this.treeIndexCache.set(cacheKey, result);
|
|
443
275
|
return result;
|
|
444
276
|
}
|
|
445
277
|
}
|
|
446
278
|
}
|
|
447
|
-
catch {
|
|
448
|
-
// 降级到关键词切片
|
|
449
|
-
}
|
|
279
|
+
catch { /* fallback */ }
|
|
450
280
|
return this.readDecisionsContextFallback(projectPath);
|
|
451
281
|
}
|
|
452
|
-
/**
|
|
453
|
-
* 降级方案:读取 decisions.md 末尾内容(TTL 缓存)
|
|
454
|
-
*/
|
|
455
282
|
readDecisionsContextFallback(projectPath) {
|
|
456
283
|
const cached = this.decisionsCache.get(projectPath);
|
|
457
284
|
if (cached)
|
|
@@ -461,7 +288,6 @@ export class IntentEngine {
|
|
|
461
288
|
if (!fs.existsSync(decisionsPath))
|
|
462
289
|
return '';
|
|
463
290
|
const content = fs.readFileSync(decisionsPath, 'utf-8');
|
|
464
|
-
// 只取最近的内容,避免 prompt 过长
|
|
465
291
|
const data = content.trim();
|
|
466
292
|
this.decisionsCache.set(projectPath, data);
|
|
467
293
|
return data;
|
|
@@ -470,36 +296,100 @@ export class IntentEngine {
|
|
|
470
296
|
return '';
|
|
471
297
|
}
|
|
472
298
|
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
299
|
+
getProjectStructure(projectPath) {
|
|
300
|
+
const cached = this.structureCache.get(projectPath);
|
|
301
|
+
if (cached)
|
|
302
|
+
return cached;
|
|
303
|
+
try {
|
|
304
|
+
if (!fs.existsSync(projectPath))
|
|
305
|
+
return '';
|
|
306
|
+
const lines = [];
|
|
307
|
+
const entries = fs.readdirSync(projectPath, { withFileTypes: true });
|
|
308
|
+
const dirs = [];
|
|
309
|
+
const files = [];
|
|
310
|
+
const skipDirs = new Set(['node_modules', '.git', 'dist', 'build', '.next', '__pycache__', '.claude', '.claude-forge', 'vendor', 'target']);
|
|
311
|
+
for (const entry of entries) {
|
|
312
|
+
if (entry.name.startsWith('.') && entry.name !== '.env.example')
|
|
313
|
+
continue;
|
|
314
|
+
if (skipDirs.has(entry.name))
|
|
315
|
+
continue;
|
|
316
|
+
if (entry.isDirectory()) {
|
|
317
|
+
dirs.push(entry.name + '/');
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
files.push(entry.name);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (dirs.length > 0)
|
|
324
|
+
lines.push(`目录: ${dirs.join(', ')}`);
|
|
325
|
+
if (files.length > 0)
|
|
326
|
+
lines.push(`文件: ${files.join(', ')}`);
|
|
327
|
+
const srcPath = path.join(projectPath, 'src');
|
|
328
|
+
if (fs.existsSync(srcPath)) {
|
|
329
|
+
const srcEntries = fs.readdirSync(srcPath, { withFileTypes: true });
|
|
330
|
+
const srcDirs = srcEntries.filter(e => e.isDirectory() && !e.name.startsWith('.')).map(e => e.name + '/');
|
|
331
|
+
if (srcDirs.length > 0) {
|
|
332
|
+
lines.push(`src/ 模块: ${srcDirs.join(', ')}`);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const data = lines.join('\n');
|
|
336
|
+
this.structureCache.set(projectPath, data);
|
|
337
|
+
return data;
|
|
338
|
+
}
|
|
339
|
+
catch {
|
|
340
|
+
return '';
|
|
341
|
+
}
|
|
478
342
|
}
|
|
479
|
-
|
|
480
|
-
|
|
343
|
+
getActiveLearnedRulesFromStorage(projectPath) {
|
|
344
|
+
const cached = this.rulesCache.get(projectPath);
|
|
345
|
+
if (cached)
|
|
346
|
+
return cached;
|
|
347
|
+
const data = this.storage?.getActiveLearnedRules?.() ??
|
|
348
|
+
this.ruleDistiller?.storage?.getIntentRules() ?? [];
|
|
349
|
+
this.rulesCache.set(projectPath, data);
|
|
350
|
+
return data;
|
|
481
351
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
if (analysis.complexity === 'simple')
|
|
486
|
-
return null;
|
|
487
|
-
const parts = [];
|
|
488
|
-
if (analysis.requiresPipeline) {
|
|
489
|
-
parts.push(`[Forge Autopilot] 检测到复杂需求,已启动 Pipeline 编排。`);
|
|
490
|
-
parts.push(`需求:${analysis.requirement}`);
|
|
491
|
-
parts.push(`阶段:${analysis.suggestedPhases.join(' → ')}`);
|
|
492
|
-
parts.push('');
|
|
493
|
-
parts.push('请按 Pipeline 阶段指令逐步执行,每步完成后等待质量门禁审查。');
|
|
352
|
+
getActivePlan(projectPath) {
|
|
353
|
+
try {
|
|
354
|
+
return readActivePlanSummary(projectPath) ?? undefined;
|
|
494
355
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
parts.push(`[Forge] 建议关注:${analysis.requirement}`);
|
|
498
|
-
if (analysis.searchKeywords && analysis.searchKeywords.length > 0) {
|
|
499
|
-
parts.push(`参考关键词:${analysis.searchKeywords.join(', ')}`);
|
|
500
|
-
}
|
|
356
|
+
catch {
|
|
357
|
+
return undefined;
|
|
501
358
|
}
|
|
502
|
-
return parts.join('\n');
|
|
503
359
|
}
|
|
360
|
+
logDecision(sessionId, projectPath, requirement, complexity, layer, matchedRuleId, confidence) {
|
|
361
|
+
if (!sessionId || !this.storage)
|
|
362
|
+
return;
|
|
363
|
+
try {
|
|
364
|
+
const id = `dec_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
|
|
365
|
+
this.storage.logIntentDecision({
|
|
366
|
+
id,
|
|
367
|
+
session_id: sessionId,
|
|
368
|
+
project_path: projectPath,
|
|
369
|
+
requirement,
|
|
370
|
+
predicted_complexity: complexity,
|
|
371
|
+
matched_rule_id: matchedRuleId,
|
|
372
|
+
matched_layer: layer,
|
|
373
|
+
confidence,
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
catch (err) {
|
|
377
|
+
logger.debug(`[GoalClassifier] 决策日志写入失败(非致命):${err}`);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
function inferTaskType(requirement) {
|
|
382
|
+
const lower = requirement.toLowerCase();
|
|
383
|
+
if (lower.includes('bug') || lower.includes('fix') || lower.includes('修复'))
|
|
384
|
+
return 'bugfix';
|
|
385
|
+
if (lower.includes('feature') || lower.includes('功能') || lower.includes('新增'))
|
|
386
|
+
return 'feature';
|
|
387
|
+
if (lower.includes('refactor') || lower.includes('重构'))
|
|
388
|
+
return 'refactor';
|
|
389
|
+
if (lower.includes('performance') || lower.includes('性能') || lower.includes('优化'))
|
|
390
|
+
return 'performance';
|
|
391
|
+
if (lower.includes('doc') || lower.includes('文档'))
|
|
392
|
+
return 'documentation';
|
|
393
|
+
return 'other';
|
|
504
394
|
}
|
|
505
|
-
//# sourceMappingURL=
|
|
395
|
+
//# sourceMappingURL=goal-classifier.js.map
|