mirror of
https://github.com/cjo4m06/mcp-shrimp-task-manager.git
synced 2025-07-26 16:02:26 +08:00
Compare commits
34 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
57f96717f0 | ||
![]() |
99baa0fa63 | ||
![]() |
8771a5bf6f | ||
![]() |
098ed8ae44 | ||
![]() |
54438960b5 | ||
![]() |
28f9a7c15d | ||
![]() |
378e4393cc | ||
![]() |
4fedd78923 | ||
![]() |
c676799e36 | ||
![]() |
c843cbc820 | ||
![]() |
2b2d002f31 | ||
![]() |
0f22b41682 | ||
![]() |
f9a90a8aa6 | ||
![]() |
d26782a633 | ||
![]() |
5cb169f6f8 | ||
![]() |
5a39f9a9a9 | ||
![]() |
1aab4e44b3 | ||
![]() |
dccd4e2b12 | ||
![]() |
288bec9c14 | ||
![]() |
5267fa4490 | ||
![]() |
9d7ed3aabd | ||
![]() |
fd26bfaafc | ||
![]() |
7cf1a1809e | ||
![]() |
5b1e74a2e5 | ||
![]() |
51436bb487 | ||
![]() |
16913ad692 | ||
![]() |
c0aeba0634 | ||
![]() |
cb838cb689 | ||
![]() |
4264fa7ce0 | ||
![]() |
5bb369872a | ||
![]() |
6d8a42206a | ||
![]() |
5d1c28dd97 | ||
![]() |
313e338f7b | ||
![]() |
528984f107 |
@ -8,12 +8,10 @@
|
||||
# Task data storage directory (absolute path)
|
||||
DATA_DIR=
|
||||
|
||||
# Enable thought chain
|
||||
ENABLE_THOUGHT_CHAIN=true
|
||||
|
||||
# Set Templates
|
||||
# Specifies the template set to use for prompts.
|
||||
# Specifies the template set to use for prompts and WebGUI language.
|
||||
# Default is 'en'. Currently available options are 'en' and 'zh'.
|
||||
# When using custom templates, WebGUI will default to English interface.
|
||||
# To use custom templates, copy the 'src/prompts/templates_en' directory
|
||||
# to the location specified by DATA_DIR, rename the copied directory
|
||||
# (e.g., to 'my_templates'), and set TEMPLATES_USE to the new directory name (e.g., 'my_templates').
|
||||
@ -25,6 +23,9 @@ TEMPLATES_USE=en
|
||||
# Default is false.
|
||||
ENABLE_GUI=false
|
||||
|
||||
# WebGUI port
|
||||
WEB_PORT=3000
|
||||
|
||||
# ============================
|
||||
# Prompt Customization
|
||||
# ============================
|
||||
|
44
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
44
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
### Description
|
||||
|
||||
<!--
|
||||
Please include a summary of the change and which issue is fixed if applicable.
|
||||
Please also include relevant motivation and context.
|
||||
List any dependencies that are required for this change.
|
||||
-->
|
||||
|
||||
### Type of change
|
||||
|
||||
<!-- Please delete options that are not relevant. -->
|
||||
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- [ ] This change requires a documentation update
|
||||
|
||||
### How Has This Been Tested?
|
||||
|
||||
<!--
|
||||
Please describe the tests that you ran to verify your changes.
|
||||
Provide instructions so we can reproduce.
|
||||
Please also list any relevant details for your test configuration.
|
||||
-->
|
||||
|
||||
- [ ] `npm run test` (following the project's testing guidelines)
|
||||
- [ ] Manual testing with the following configuration:
|
||||
|
||||
**Test Configuration**:
|
||||
* **Client**: (e.g., Cursor, Claude Code)
|
||||
* **OS**: (e.g., macOS, Windows, Linux)
|
||||
* **Node.js version**:
|
||||
|
||||
### Checklist:
|
||||
|
||||
- [ ] I have performed a self-review of my own code
|
||||
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||
- [ ] I have made corresponding changes to the documentation (`README.md`, `CHANGELOG.md`)
|
||||
- [ ] My changes generate no new warnings
|
||||
- [ ] I have added tests that prove my fix is effective or that my feature works
|
||||
- [ ] New and existing unit tests pass locally with my changes
|
||||
- [ ] I have checked to ensure my PR is focused on a single feature/fix
|
||||
- [ ] I have updated the version number in `package.json`
|
||||
|
88
CHANGELOG.md
88
CHANGELOG.md
@ -2,6 +2,94 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
## [1.0.21]
|
||||
|
||||
### Added
|
||||
|
||||
- Added support for ListRoots protocol and optimized DATA_DIR configuration method (99baa0f)
|
||||
- Added WEB_PORT environment variable to customize WebGUI port number (8771a5b)
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated documentation to reflect new configuration options (99baa0f, 8771a5b)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix #56: Added configurable WebGUI port to avoid port conflicts (8771a5b)
|
||||
|
||||
## [1.0.20]
|
||||
|
||||
### Added
|
||||
|
||||
- Added reset button and thumbnail view
|
||||
- Enhanced interaction between dependency graph and task list, making the dependency graph respond to filtering and task list selection
|
||||
|
||||
### Changed
|
||||
|
||||
- Removed initial animation of dependency graph to avoid animation jumps
|
||||
- Optimized initial state of dependency graph
|
||||
|
||||
## [1.0.19]
|
||||
|
||||
### Added
|
||||
|
||||
- Added research mode functionality for systematic programming research (5267fa4)
|
||||
- Added research mode prompts and templates for both English and Chinese (5267fa4)
|
||||
- Added comprehensive research mode documentation and usage guides (288bec9)
|
||||
|
||||
### Changed
|
||||
|
||||
- Enhanced README with research mode feature description and usage instructions (288bec9)
|
||||
- Updated Chinese documentation to include research mode functionality (288bec9)
|
||||
|
||||
## [1.0.18]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix #29: Removed unnecessary console.log outputs to reduce noise (7cf1a18)
|
||||
- Fix #28: Fixed WebGUI internationalization issues in task detail view (fd26bfa)
|
||||
|
||||
### Changed
|
||||
|
||||
- Enhanced WebGUI task detail view to use proper translation functions for all labels (fd26bfa)
|
||||
- Updated thought process stage description to use English for better consistency (fd26bfa)
|
||||
|
||||
## [1.0.17]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix #26: Fixed issue where task status was displayed in Chinese in WebGUI (16913ad)
|
||||
- Fix #26: Optimized WebGUI default language to change based on env TEMPLATES_USE setting (51436bb)
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated .env.example to include language setting documentation (51436bb)
|
||||
- Enhanced WebGUI language handling logic for better internationalization support (51436bb)
|
||||
|
||||
## [1.0.16]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix: Fixed issue with Augment AI not supporting uuid format by implementing custom regex validation (4264fa7)
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated task planning related prompts, added critical warning prohibiting assumptions, guesses, and imagination, emphasizing the need to use available tools to gather real information (cb838cb)
|
||||
- Adjusted task descriptions to more clearly express task objectives (cb838cb)
|
||||
- Optimized error message prompts, adding batch call suggestions to resolve long text formatting issues (cb838cb)
|
||||
|
||||
## [1.0.15]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix: Corrected an error where gemini-2.5-pro-preview-05-06 would skip task execution and mark it as completed directly (6d8a422)
|
||||
- Fixes issue #20 (5d1c28d)
|
||||
|
||||
### Changed
|
||||
|
||||
- Moved rule.md to the root directory to prepare for future collaborative architecture with DATA_DIR outside the project (313e338)
|
||||
- Updated documentation (28984f)
|
||||
|
||||
## [1.0.14]
|
||||
|
||||
### Changed
|
||||
|
95
CONTRIBUTING.md
Normal file
95
CONTRIBUTING.md
Normal file
@ -0,0 +1,95 @@
|
||||
# Contributing to MCP Shrimp Task Manager
|
||||
|
||||
First off, thank you for considering contributing to MCP Shrimp Task Manager! It's people like you that make this such a great tool. We welcome any and all contributions.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project and everyone participating in it is governed by a simple code of conduct: be respectful. We are committed to providing a friendly, safe and welcoming environment for all.
|
||||
|
||||
## How Can I Contribute?
|
||||
|
||||
There are many ways to contribute, from writing tutorials or blog posts, improving the documentation, submitting bug reports and feature requests or writing code which can be incorporated into the main project.
|
||||
|
||||
### Reporting Bugs
|
||||
|
||||
If you find a bug, you can either open an issue on our [GitHub repository](https://github.com/cjo4m06/mcp-shrimp-task-manager/issues) or submit a direct pull request with the fix. For more complex bugs that require discussion, opening an issue first is recommended.
|
||||
|
||||
Here is a template you can use if you choose to open an issue:
|
||||
|
||||
```markdown
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. **Configuration**: Detail your `mcp.json` or `.env` configuration.
|
||||
2. **Tool Call**: The exact tool call you made (e.g., `plan_task ...`).
|
||||
3. **Context**: Any relevant context, like the state of the `tasks.json` file.
|
||||
4. **Observed Behavior**: The error or incorrect output.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Environment (please complete the following information):**
|
||||
- **OS**: [e.g. macOS, Linux, Windows]
|
||||
- **Client**: [e.g. Cursor, Claude Code, custom script]
|
||||
- **MCP Shrimp Task Manager Version**: [e.g. 1.0.19]
|
||||
|
||||
**Additional context**
|
||||
Add any other logs or context about the problem here.
|
||||
```
|
||||
|
||||
### Suggesting Enhancements
|
||||
|
||||
If you have an idea for a new feature or an enhancement to an existing one, you can either open an issue on our [GitHub repository](https://github.com/cjo4m06/mcp-shrimp-task-manager/issues) to discuss it, or submit a direct pull request for straightforward additions. For significant features that may impact the architecture, it's advisable to open an issue for discussion beforehand.
|
||||
|
||||
Here is a template you can use if you choose to open an issue:
|
||||
|
||||
```markdown
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen. This could include new tools, or changes to existing tool behaviors.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or mock-ups about the feature request here.
|
||||
```
|
||||
|
||||
### Your First Code Contribution
|
||||
|
||||
Unsure where to begin contributing to MCP Shrimp Task Manager? You can start by looking through these `good-first-issue` and `help-wanted` issues:
|
||||
|
||||
- [Good first issues](https://github.com/cjo4m06/mcp-shrimp-task-manager/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) - issues which should only require a few lines of code, and a test or two.
|
||||
- [Help wanted issues](https://github.com/cjo4m06/mcp-shrimp-task-manager/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) - issues which should be a bit more involved than `good-first-issue` issues.
|
||||
|
||||
## Contribution Workflow and Pull Requests
|
||||
|
||||
Since this project maintains a clean commit history and a focused development pace, we follow a strict contribution workflow. All contributions are made via pull requests from forked repositories.
|
||||
|
||||
1. **Fork & Clone**: Fork the repository on GitHub, then clone it to your local machine.
|
||||
2. **Install Dependencies**: Install the dependencies by running `npm install` in the project's root directory.
|
||||
3. **Branch**: Create a new branch for your work, following the convention `feat/your-feature-name` for features or `fix/your-bug-fix` for bug fixes. For example: `git checkout -b feat/new-research-tool`.
|
||||
4. **Make your changes**: Run the build command `npm run build` to make sure everything compiles correctly.
|
||||
5. **Focus Your Work**: Each pull request should address a single issue or feature. Please do not mix bug fixes and new features in the same PR. This focus helps streamline the review process and makes it easier to track changes.
|
||||
6. **Commit**: Commit your changes with a descriptive message that follows the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) format.
|
||||
7. **Push**: Push your branch to your forked repository.
|
||||
8. **Open a Pull Request**:
|
||||
- Navigate to the [main repository](https://github.com/cjo4m06/mcp-shrimp-task-manager/pulls) and open a new pull request from your forked branch.
|
||||
- GitHub will automatically populate the PR description with our template. Please fill it out as completely as possible. The more context you provide, the faster your PR can be reviewed.
|
||||
9. **Code Review**: The repository owner (`@cjo4m06`) will review your pull request. They may ask for changes or clarification.
|
||||
10. **Merge**: Once the PR is approved, the owner will merge it into the `main` branch. We do not allow contributors to merge their own PRs.
|
||||
|
||||
As a part of the review process, please ensure your PR includes:
|
||||
- Corresponding changes to documentation (`README.md`).
|
||||
- Updates to the `CHANGELOG.md`.
|
||||
- An increase in the version number in `package.json` following [SemVer](http://semver.org/).
|
||||
|
||||
### Testing
|
||||
|
||||
As noted in PR [#35](https://github.com/cjo4m06/mcp-shrimp-task-manager/pull/35), we are in the process of migrating our testing framework to [Vitest](https://vitest.dev/). For any new code contributions, please include tests written with Vitest. This will help us accelerate the transition and ensure the quality of our codebase.
|
||||
|
||||
Thank you for your contribution!
|
329
README.md
329
README.md
@ -4,8 +4,8 @@
|
||||
|
||||
- [✨ Features](#features1)
|
||||
- [🧭 Usage Guide](#usage-guide)
|
||||
- [🔬 Research Mode](#research-mode)
|
||||
- [🧠 Task Memory Function](#task-memory-function)
|
||||
- [🤔 Thought Chain Process](#thought-chain)
|
||||
- [📋 Project Rules Initialization](#project-rules)
|
||||
- [🌐 Web GUI](#web-gui)
|
||||
- [📚 Documentation Resources](#documentation)
|
||||
@ -40,9 +40,9 @@ Shrimp Task Manager guides Agents through structured workflows for systematic pr
|
||||
- **Task Complexity Assessment**: Automatically evaluate task complexity and provide optimal handling suggestions
|
||||
- **Automatic Task Summary Updates**: Automatically generate summaries upon task completion, optimizing memory performance
|
||||
- **Task Memory Function**: Automatically backup task history, providing long-term memory and reference capabilities
|
||||
- **Thought Chain Process**: Step-by-step reasoning to analyze complex problems systematically
|
||||
- **Research Mode**: Systematic technical research capabilities with guided workflows for exploring technologies, best practices, and solution comparisons
|
||||
- **Project Rules Initialization**: Define project standards and rules to maintain consistency across large projects
|
||||
- **<a id="web-gui"></a>Web GUI**: Provides an optional web-based graphical user interface for task management. Enable by setting `ENABLE_GUI=true` in your `.env` file. When enabled, a `WebGUI.md` file containing the access address will be created in your `DATA_DIR`.
|
||||
- **<a id="web-gui"></a>Web GUI**: Provides an optional web-based graphical user interface for task management. Enable by setting `ENABLE_GUI=true` in your `.env` file. When enabled, a `WebGUI.md` file containing the access address will be created in your `DATA_DIR`. You can customize the web port by setting `WEB_PORT` (if not specified, an available port will be automatically selected).
|
||||
|
||||
## 🧭 <a id="usage-guide"></a>Usage Guide
|
||||
|
||||
@ -52,6 +52,17 @@ Shrimp Task Manager offers a structured approach to AI-assisted programming thro
|
||||
|
||||
Shrimp is essentially a prompt template that guides AI Agents to better understand and work with your project. It uses a series of prompts to ensure the Agent aligns closely with your project's specific needs and conventions.
|
||||
|
||||
### Research Mode in Practice
|
||||
|
||||
Before diving into task planning, you can leverage the research mode for technical investigation and knowledge gathering. This is particularly useful when:
|
||||
|
||||
- You need to explore new technologies or frameworks
|
||||
- You want to compare different solution approaches
|
||||
- You're investigating best practices for your project
|
||||
- You need to understand complex technical concepts
|
||||
|
||||
Simply tell the Agent "research [your topic]" or "enter research mode for [technology/problem]" to begin systematic investigation. The research findings will then inform your subsequent task planning and development decisions.
|
||||
|
||||
### First-Time Setup
|
||||
|
||||
When working with a new project, simply tell the Agent "init project rules". This will guide the Agent to generate a set of rules tailored to your project's specific requirements and structure.
|
||||
@ -80,6 +91,52 @@ Due to LLM token limits, context may be lost during lengthy conversations. If th
|
||||
|
||||
You can switch the language of system prompts by setting the `TEMPLATES_USE` environment variable. It supports `en` (English) and `zh` (Traditional Chinese) by default. Furthermore, you can copy an existing template directory (e.g., `src/prompts/templates_en`) to the location specified by `DATA_DIR`, modify it, and then point `TEMPLATES_USE` to your custom template directory name. This allows for deeper prompt customization. For detailed instructions.
|
||||
|
||||
## 🔬 <a id="research-mode"></a>Research Mode
|
||||
|
||||
Shrimp Task Manager includes a specialized research mode designed for systematic technical investigation and knowledge gathering.
|
||||
|
||||
### What is Research Mode?
|
||||
|
||||
Research Mode is a guided workflow system that helps AI Agents conduct thorough and systematic technical research. It provides structured approaches to exploring technologies, comparing solutions, investigating best practices, and gathering comprehensive information for programming tasks.
|
||||
|
||||
### Key Features
|
||||
|
||||
- **Systematic Investigation**: Structured workflows ensure comprehensive coverage of research topics
|
||||
- **Multi-Source Research**: Combines web search and codebase analysis for complete understanding
|
||||
- **State Management**: Maintains research context and progress across multiple sessions
|
||||
- **Guided Exploration**: Prevents research from becoming unfocused or going off-topic
|
||||
- **Knowledge Integration**: Seamlessly integrates research findings with task planning and execution
|
||||
|
||||
### When to Use Research Mode
|
||||
|
||||
Research Mode is particularly valuable for:
|
||||
|
||||
- **Technology Exploration**: Investigating new frameworks, libraries, or tools
|
||||
- **Best Practices Research**: Finding industry standards and recommended approaches
|
||||
- **Solution Comparison**: Evaluating different technical approaches or architectures
|
||||
- **Problem Investigation**: Deep-diving into complex technical challenges
|
||||
- **Architecture Planning**: Researching design patterns and system architectures
|
||||
|
||||
### How to Use Research Mode
|
||||
|
||||
Simply tell the Agent to enter research mode with your topic:
|
||||
|
||||
- **Basic usage**: "Enter research mode for [your topic]"
|
||||
- **Specific research**: "Research [specific technology/problem]"
|
||||
- **Comparative analysis**: "Research and compare [options A vs B]"
|
||||
|
||||
The system will guide the Agent through structured research phases, ensuring thorough investigation while maintaining focus on your specific needs.
|
||||
|
||||
### Research Workflow
|
||||
|
||||
1. **Topic Definition**: Clearly define the research scope and objectives
|
||||
2. **Information Gathering**: Systematic collection of relevant information
|
||||
3. **Analysis and Synthesis**: Processing and organizing findings
|
||||
4. **State Updates**: Regular progress tracking and context preservation
|
||||
5. **Integration**: Applying research results to your project context
|
||||
|
||||
> **💡 Recommendation**: For the best research mode experience, we recommend using **Claude 4 Sonnet**, which provides exceptional analytical capabilities and comprehensive research synthesis.
|
||||
|
||||
## 🧠 <a id="task-memory-function"></a>Task Memory Function
|
||||
|
||||
Shrimp Task Manager has long-term memory capabilities, automatically saving task execution history and providing reference experiences when planning new tasks.
|
||||
@ -99,17 +156,6 @@ Shrimp Task Manager has long-term memory capabilities, automatically saving task
|
||||
|
||||
Through effective use of the task memory function, the system can continuously accumulate experience, with intelligence level and work efficiency continuously improving.
|
||||
|
||||
## 🤔 <a id="thought-chain"></a>Thought Chain Process
|
||||
|
||||
The Thought Chain feature enhances problem-solving through structured thinking:
|
||||
|
||||
- **Systematic Reasoning**: Break down complex problems into logical steps
|
||||
- **Assumption Testing**: Challenge assumptions to validate solution approaches
|
||||
- **Critical Analysis**: Evaluate solution options with rigorous criteria
|
||||
- **Improved Decision Making**: Reach more reliable conclusions through deliberate thinking
|
||||
|
||||
When enabled (default setting), the system guides the Agent through step-by-step reasoning using the `process_thought` tool, ensuring thorough problem analysis before implementation.
|
||||
|
||||
## 📋 <a id="project-rules"></a>Project Rules Initialization
|
||||
|
||||
The Project Rules feature helps maintain consistency across your codebase:
|
||||
@ -138,7 +184,6 @@ This tool is particularly valuable when your codebase expands or undergoes signi
|
||||
|
||||
## 📚 <a id="documentation"></a>Documentation Resources
|
||||
|
||||
- [System Architecture](docs/en/architecture.md): Detailed system design and data flow explanation
|
||||
- [Prompt Customization Guide](docs/en/prompt-customization.md): Instructions for customizing tool prompts via environment variables
|
||||
- [Changelog](CHANGELOG.md): Record of all notable changes to this project
|
||||
|
||||
@ -170,54 +215,25 @@ Shrimp Task Manager can be used with any client that supports the Model Context
|
||||
|
||||
Shrimp Task Manager offers two configuration methods: global configuration and project-specific configuration.
|
||||
|
||||
#### ListRoots Protocol Support
|
||||
|
||||
Shrimp Task Manager now supports the **ListRoots protocol**, which enables automatic project isolation and flexible path configuration:
|
||||
|
||||
- **If your client supports ListRoots** (e.g., Cursor IDE):
|
||||
|
||||
- **Absolute path mode**: Create a project folder within the specified DATA_DIR, enabling you to use a global mcp.json configuration while Shrimp automatically isolates projects
|
||||
- **Relative path mode**: Create the DATA_DIR within your project root directory for project-specific data storage
|
||||
|
||||
- **If your client doesn't support ListRoots**:
|
||||
- DATA_DIR maintains the legacy behavior (absolute paths recommended)
|
||||
- We recommend asking your client vendor to support the ListRoots protocol for enhanced functionality
|
||||
|
||||
#### Global Configuration
|
||||
|
||||
1. Open the Cursor IDE global configuration file (usually located at `~/.cursor/mcp.json`)
|
||||
2. Add the following configuration in the `mcpServers` section:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"shrimp-task-manager": {
|
||||
"command": "node",
|
||||
"args": ["/mcp-shrimp-task-manager/dist/index.js"],
|
||||
"env": {
|
||||
"DATA_DIR": "/path/to/project/data", // 必須使用絕對路徑
|
||||
"ENABLE_THOUGHT_CHAIN": "true",
|
||||
"TEMPLATES_USE": "en",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
or
|
||||
|
||||
{
|
||||
"mcpServers": {
|
||||
"shrimp-task-manager": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "mcp-shrimp-task-manager"],
|
||||
"env": {
|
||||
"DATA_DIR": "/mcp-shrimp-task-manager/data",
|
||||
"ENABLE_THOUGHT_CHAIN": "true",
|
||||
"TEMPLATES_USE": "en",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> ⚠️ Please replace `/mcp-shrimp-task-manager` with your actual path.
|
||||
|
||||
#### Project-Specific Configuration
|
||||
|
||||
You can also set up dedicated configurations for each project to use independent data directories for different projects:
|
||||
|
||||
1. Create a `.cursor` directory in the project root
|
||||
2. Create an `mcp.json` file in this directory with the following content:
|
||||
**Option A: Absolute Path (Project Isolation Mode)**
|
||||
|
||||
```json
|
||||
{
|
||||
@ -226,26 +242,7 @@ You can also set up dedicated configurations for each project to use independent
|
||||
"command": "node",
|
||||
"args": ["/path/to/mcp-shrimp-task-manager/dist/index.js"],
|
||||
"env": {
|
||||
"DATA_DIR": "/path/to/project/data", // Must use absolute path
|
||||
"ENABLE_THOUGHT_CHAIN": "true",
|
||||
"TEMPLATES_USE": "en",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
or
|
||||
|
||||
{
|
||||
"mcpServers": {
|
||||
"shrimp-task-manager": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "mcp-shrimp-task-manager"],
|
||||
"env": {
|
||||
"DATA_DIR": "/path/to/project/data", // 必須使用絕對路徑
|
||||
"ENABLE_THOUGHT_CHAIN": "true",
|
||||
"DATA_DIR": "/Users/username/ShrimpData", // Absolute path - creates project folders automatically
|
||||
"TEMPLATES_USE": "en",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
@ -254,17 +251,153 @@ or
|
||||
}
|
||||
```
|
||||
|
||||
**Option B: NPX with Absolute Path**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"shrimp-task-manager": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "mcp-shrimp-task-manager"],
|
||||
"env": {
|
||||
"DATA_DIR": "/Users/username/ShrimpData", // Absolute path - creates project folders automatically
|
||||
"TEMPLATES_USE": "en",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> ⚠️ Please replace `/path/to/mcp-shrimp-task-manager` and `/Users/username/ShrimpData` with your actual paths.
|
||||
>
|
||||
> 💡 **Absolute Path Advantage**: With ListRoots support, Shrimp automatically creates separate folders for each project (e.g., `/Users/username/ShrimpData/my-project/`, `/Users/username/ShrimpData/another-project/`), enabling perfect project isolation with a single global configuration.
|
||||
>
|
||||
> 💡 **Optional:** You can add `"WEB_PORT": "3000"` to the `env` section to specify a custom port for the web GUI. If not specified, an available port will be automatically selected.
|
||||
|
||||
#### Project-Specific Configuration
|
||||
|
||||
You can also set up dedicated configurations for each project. This method allows using relative paths for project-contained data storage:
|
||||
|
||||
1. Create a `.cursor` directory in the project root
|
||||
2. Create an `mcp.json` file in this directory with the following content:
|
||||
|
||||
**Option A: Relative Path (Project-Contained Mode)**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"shrimp-task-manager": {
|
||||
"command": "node",
|
||||
"args": ["/path/to/mcp-shrimp-task-manager/dist/index.js"],
|
||||
"env": {
|
||||
"DATA_DIR": ".shrimp", // Relative path - creates folder within project root
|
||||
"TEMPLATES_USE": "en",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Option B: NPX with Relative Path**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"shrimp-task-manager": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "mcp-shrimp-task-manager"],
|
||||
"env": {
|
||||
"DATA_DIR": "shrimp-data", // Relative path - creates folder within project root
|
||||
"TEMPLATES_USE": "en",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Option C: Absolute Path (Alternative)**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"shrimp-task-manager": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "mcp-shrimp-task-manager"],
|
||||
"env": {
|
||||
"DATA_DIR": "/Users/username/ShrimpData", // Absolute path with project isolation
|
||||
"TEMPLATES_USE": "en",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> ⚠️ Please replace `/path/to/mcp-shrimp-task-manager` with your actual path.
|
||||
>
|
||||
> 💡 **Relative Path Advantage**: Data is stored within your project directory (e.g., `./shrimp-data/`), making it easy to include or exclude from version control as needed.
|
||||
>
|
||||
> 💡 **Optional:** You can add `"WEB_PORT": "3000"` to the `env` section to specify a custom port for the web GUI. If not specified, an available port will be automatically selected.
|
||||
|
||||
### ⚠️ Important Configuration Notes
|
||||
|
||||
The **DATA_DIR parameter** is the directory where Shrimp Task Manager stores task data, conversation logs, and other information. Setting this parameter correctly is crucial for the normal operation of the system. This parameter must use an **absolute path**; using a relative path may cause the system to incorrectly locate the data directory, resulting in data loss or function failure.
|
||||
The **DATA_DIR parameter** is the directory where Shrimp Task Manager stores task data, conversation logs, and other information. The new implementation supports both absolute and relative paths with intelligent behavior based on your client's capabilities.
|
||||
|
||||
> **Warning**: Using relative paths may cause the following issues:
|
||||
#### 🚀 With ListRoots Protocol Support (Recommended)
|
||||
|
||||
If your client supports the **ListRoots protocol** (like Cursor IDE), Shrimp Task Manager automatically detects your project root and provides enhanced functionality:
|
||||
|
||||
**Absolute Path Mode (Project Isolation):**
|
||||
|
||||
- Configuration: `"DATA_DIR": "/Users/username/ShrimpData"`
|
||||
- Behavior: Creates `{DATA_DIR}/{project-name}/` automatically
|
||||
- Example: For project "my-app" → `/Users/username/ShrimpData/my-app/`
|
||||
- **Advantage**: Use one global configuration for all projects with perfect isolation
|
||||
|
||||
**Relative Path Mode (Project-Contained):**
|
||||
|
||||
- Configuration: `"DATA_DIR": ".shrimp"` or `"DATA_DIR": "shrimp-data"`
|
||||
- Behavior: Creates `{project-root}/{DATA_DIR}/` within your project
|
||||
- Example: For DATA_DIR "shrimp-data" → `./shrimp-data/`
|
||||
- **Advantage**: Data stays with your project, easy to include/exclude from version control
|
||||
|
||||
#### ⚠️ Without ListRoots Protocol Support (Legacy Mode)
|
||||
|
||||
If your client **doesn't support ListRoots**, the system falls back to legacy behavior:
|
||||
|
||||
- **Absolute paths are strongly recommended** to avoid path resolution issues
|
||||
- Relative paths may cause inconsistent behavior across different environments
|
||||
- Consider requesting ListRoots support from your client vendor for enhanced functionality
|
||||
|
||||
> **Legacy Warning**: Without ListRoots support, using relative paths may cause:
|
||||
>
|
||||
> - Data files not found, causing system initialization failure
|
||||
> - Task status loss or inability to save correctly
|
||||
> - Inconsistent application behavior across different environments
|
||||
> - System crashes or failure to start
|
||||
|
||||
#### 💡 Choosing the Right Configuration
|
||||
|
||||
**Use Absolute Path (Global) when:**
|
||||
|
||||
- You want to manage multiple projects with one configuration
|
||||
- You prefer centralized data storage
|
||||
- You want automatic project isolation
|
||||
|
||||
**Use Relative Path (Project-Specific) when:**
|
||||
|
||||
- You want data to stay within the project directory
|
||||
- You work on projects in different environments
|
||||
- You need fine control over what gets included in version control
|
||||
|
||||
**Use Legacy Mode when:**
|
||||
|
||||
- Your client doesn't support ListRoots protocol
|
||||
- You need compatibility with older client versions
|
||||
|
||||
### 🔧 Environment Variable Configuration
|
||||
|
||||
Shrimp Task Manager supports customizing prompt behavior through environment variables, allowing you to fine-tune AI assistant responses without modifying code. You can set these variables in the configuration or through an `.env` file:
|
||||
@ -279,7 +412,6 @@ Shrimp Task Manager supports customizing prompt behavior through environment var
|
||||
"DATA_DIR": "/path/to/project/data",
|
||||
"MCP_PROMPT_PLAN_TASK": "Custom planning guidance...",
|
||||
"MCP_PROMPT_EXECUTE_TASK_APPEND": "Additional execution instructions...",
|
||||
"ENABLE_THOUGHT_CHAIN": "true",
|
||||
"TEMPLATES_USE": "en",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
@ -296,8 +428,9 @@ There are two customization methods:
|
||||
Additionally, there are other system configuration variables:
|
||||
|
||||
- **DATA_DIR**: Specifies the directory where task data is stored
|
||||
- **ENABLE_THOUGHT_CHAIN**: Controls the thinking model in task planning workflow. When set to `true` (default), the system guides users to use the `process_thought` tool for step-by-step reasoning. When set to `false`, the system directly uses `analyze_task` to submit analysis results, skipping the detailed thinking process.
|
||||
- **TEMPLATES_USE**: Specifies the template set to use for prompts. Defaults to `en`. Currently available options are `en` and `zh`. To use custom templates, copy the `src/prompts/templates_en` directory to the location specified by `DATA_DIR`, rename the copied directory (e.g., to `my_templates`), and set `TEMPLATES_USE` to the new directory name (e.g., `my_templates`).
|
||||
- **TEMPLATES_USE**: Specifies the template set to use for prompts. Defaults to `en`. Currently available options are `en` and `zh`. To use custom templates, copy the `src/prompts/templates_en` directory to the location specified by `DATA_DIR`, rename the copied directory (e.g., to `my_templates`), and set `TEMPLATES_USE` to the new directory name (e.g., `my_templates`)
|
||||
- **ENABLE_GUI**: Enables or disables the web-based graphical user interface. Set to `true` to enable, `false` to disable (default)
|
||||
- **WEB_PORT**: Specifies the port for the web GUI. If not specified, an available port will be automatically selected. Only takes effect when `ENABLE_GUI` is set to `true`
|
||||
|
||||
For detailed instructions on customizing prompts, including supported parameters and examples, see the [Prompt Customization Guide](docs/en/prompt-customization.md).
|
||||
|
||||
@ -341,21 +474,21 @@ If your tool doesn't support Custom modes, you can:
|
||||
|
||||
After configuration, you can use the following tools:
|
||||
|
||||
| Category | Tool Name | Description |
|
||||
| ----------------------- | -------------------- | ------------------------------------------------ |
|
||||
| **Task Planning** | `plan_task` | Start planning tasks |
|
||||
| **Task Analysis** | `analyze_task` | In-depth analysis of task requirements |
|
||||
| | `process_thought` | Step-by-step reasoning for complex problems |
|
||||
| **Solution Assessment** | `reflect_task` | Reflect and improve solution concepts |
|
||||
| **Project Management** | `init_project_rules` | Initialize or update project standards and rules |
|
||||
| **Task Management** | `split_tasks` | Break tasks into subtasks |
|
||||
| | `list_tasks` | Display all tasks and status |
|
||||
| | `query_task` | Search and list tasks |
|
||||
| | `get_task_detail` | Display complete task details |
|
||||
| | `delete_task` | Delete incomplete tasks |
|
||||
| **Task Execution** | `execute_task` | Execute specific tasks |
|
||||
| | `verify_task` | Verify task completion |
|
||||
| | `complete_task` | Mark tasks as completed |
|
||||
| Category | Tool Name | Description |
|
||||
| ---------------------------- | -------------------- | ------------------------------------------------ |
|
||||
| **Task Planning** | `plan_task` | Start planning tasks |
|
||||
| **Task Analysis** | `analyze_task` | In-depth analysis of task requirements |
|
||||
| | `process_thought` | Step-by-step reasoning for complex problems |
|
||||
| **Solution Assessment** | `reflect_task` | Reflect and improve solution concepts |
|
||||
| **Research & Investigation** | `research_mode` | Enter systematic technical research mode |
|
||||
| **Project Management** | `init_project_rules` | Initialize or update project standards and rules |
|
||||
| **Task Management** | `split_tasks` | Break tasks into subtasks |
|
||||
| | `list_tasks` | Display all tasks and status |
|
||||
| | `query_task` | Search and list tasks |
|
||||
| | `get_task_detail` | Display complete task details |
|
||||
| | `delete_task` | Delete incomplete tasks |
|
||||
| **Task Execution** | `execute_task` | Execute specific tasks |
|
||||
| | `verify_task` | Verify task completion |
|
||||
|
||||
## 🔧 Technical Implementation
|
||||
|
||||
|
@ -1,463 +0,0 @@
|
||||
# Architecture Design Document for Shrimp Task Manager
|
||||
|
||||
[English](../en/architecture.md) | [中文](../zh/architecture.md)
|
||||
|
||||
## 1. System Overview
|
||||
|
||||
The Shrimp Task Manager is designed based on the MCP (Model-Chain-Protocol) framework architecture, implementing a task management system with memory capability. The system's primary functionality is to assist Large Language Models (LLMs) in efficiently managing complex task execution processes.
|
||||
|
||||
## 2. Design Goals
|
||||
|
||||
The core design goals of the Shrimp Task Manager include:
|
||||
|
||||
- **Memory Enhancement**: Overcome the context limitations of LLMs, enabling long-term task processing.
|
||||
- **Context Management**: Provide relevant context for each task based on dependencies and related files.
|
||||
- **Process Standardization**: Establish a standardized process for task planning, execution, and verification.
|
||||
- **Knowledge Accumulation**: Support continuous accumulation of task execution experience.
|
||||
|
||||
## 3. Architecture Layers
|
||||
|
||||
The system architecture consists of the following layers:
|
||||
|
||||
```
|
||||
+-----------------+
|
||||
| User Interface |
|
||||
+-----------------+
|
||||
|
|
||||
+------------------+
|
||||
| Tool Layer |
|
||||
+------------------+
|
||||
|
|
||||
+------------------+
|
||||
| Business Layer |
|
||||
+------------------+
|
||||
|
|
||||
+------------------+
|
||||
| Data Layer |
|
||||
+------------------+
|
||||
```
|
||||
|
||||
### 3.1 User Interface Layer
|
||||
|
||||
The user interface layer provides tool functions for users to interact with the system. These tools are registered through the MCP protocol and can be directly called by the user.
|
||||
|
||||
### 3.2 Tool Layer
|
||||
|
||||
The tool layer implements the specific logic of each tool function, handles parameter validation, and coordinates the business layer's functionality. Core tool implementations are located in the `src/tools` directory.
|
||||
|
||||
### 3.3 Business Layer
|
||||
|
||||
The business layer contains the core business logic, including task processing, task memory management, file relationship processing, etc. The main implementation is in the `src/models` directory.
|
||||
|
||||
### 3.4 Data Layer
|
||||
|
||||
The data layer is responsible for data persistence and retrieval, maintaining task lists, task execution history, etc. It implements file-based storage in the `src/utils` directory.
|
||||
|
||||
## 4. Core Components
|
||||
|
||||
### 4.1 Task Management Module
|
||||
|
||||
Responsible for the entire lifecycle management of tasks, including:
|
||||
|
||||
- Task planning and splitting
|
||||
- Task execution
|
||||
- Task verification
|
||||
- Task completion
|
||||
- Task updates
|
||||
- Task queries
|
||||
|
||||
### 4.2 Task Memory Module
|
||||
|
||||
Manages the execution history and experience of tasks, with key functions:
|
||||
|
||||
- Automatic saving of task execution records
|
||||
- Loading of historical task context
|
||||
- Creation of backup files
|
||||
|
||||
### 4.3 File Association Module
|
||||
|
||||
Manages the relationship between tasks and related files, including:
|
||||
|
||||
- Creating file association information
|
||||
- Loading file summaries
|
||||
- Updating file relationships
|
||||
|
||||
### 4.4 Task Complexity Assessment Module
|
||||
|
||||
Evaluates the complexity of tasks based on various indicators, helping to determine the appropriate execution strategy.
|
||||
|
||||
## 5. Core Interaction Flows
|
||||
|
||||
### 5.1 Task Planning Flow
|
||||
|
||||
```
|
||||
+--------------------+ +------------------+ +---------------+
|
||||
| | | | | |
|
||||
| plan_task Schema |---->| planTask |---->| createTaskPlan|
|
||||
| | | (taskTools.ts) | | (taskModel.ts)|
|
||||
+--------------------+ +--------+---------+ +-------+-------+
|
||||
| |
|
||||
v v
|
||||
+-------+-------------------+------+
|
||||
| Validate Parameters |
|
||||
+-------+-------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------+------+
|
||||
| Create Task Plan with Goals |
|
||||
+-------+-------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------+------+
|
||||
| Save Task Plan to Storage |
|
||||
+-------+-------------------+------+
|
||||
```
|
||||
|
||||
### 5.2 Task Analysis Flow
|
||||
|
||||
```
|
||||
+----------------------+ +-------------------+ +------------------+
|
||||
| | | | | |
|
||||
| analyze_task Schema |---->| analyzeTask |---->| createTaskAnalysis|
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+----------------------+ +---------+---------+ +---------+--------+
|
||||
| |
|
||||
v v
|
||||
+-------+-------------------------+------+
|
||||
| Validate Parameters |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Check for Previous Analysis |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Create Analysis with Technical Details|
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Save Analysis to Storage |
|
||||
+-------+-------------------------+------+
|
||||
```
|
||||
|
||||
### 5.3 Task Reflection Flow
|
||||
|
||||
```
|
||||
+---------------------+ +-------------------+ +-----------------+
|
||||
| | | | | |
|
||||
| reflect_task Schema |---->| reflectTask |---->| createReflection|
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+---------------------+ +---------+---------+ +---------+-------+
|
||||
| |
|
||||
v v
|
||||
+-------+-------------------------+------+
|
||||
| Validate Parameters |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Check for Previous Analysis |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Create Reflection with Review |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Save Reflection to Storage |
|
||||
+-------+-------------------------+------+
|
||||
```
|
||||
|
||||
### 5.4 Task Splitting Flow
|
||||
|
||||
```
|
||||
+--------------------+ +------------------+ +--------------------+
|
||||
| | | | | |
|
||||
| split_tasks Schema |---->| splitTasks |---->| createTaskList |
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+--------------------+ +--------+---------+ +---------+----------+
|
||||
| |
|
||||
v v
|
||||
+-------+-------------------------+------+
|
||||
| Validate Parameters |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Process Update Mode |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Create Atomic Tasks with Dependencies |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Save Task List to Storage |
|
||||
+-------+-------------------------+------+
|
||||
```
|
||||
|
||||
### 5.5 Task Execution Flow
|
||||
|
||||
```
|
||||
+--------------------+ +------------------+ +------------------+
|
||||
| | | | | |
|
||||
| execute_task Schema|---->| executeTask |---->| processExecution |
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+--------------------+ +--------+---------+ +---------+--------+
|
||||
| |
|
||||
v v
|
||||
+-------+-------------------------+------+
|
||||
| Validate Parameters |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Check Dependency Status |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Load Task Context (Plan, Analysis) |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Load Related Files Context |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Mark Task as In Progress |
|
||||
+-------+-------------------------+------+
|
||||
```
|
||||
|
||||
### 5.6 Task Verification Flow
|
||||
|
||||
```
|
||||
+--------------------+ +------------------+ +------------------+
|
||||
| | | | | |
|
||||
| verify_task Schema |---->| verifyTask |---->| processVerification|
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+--------------------+ +--------+---------+ +---------+--------+
|
||||
| |
|
||||
v v
|
||||
+-------+-------------------------+------+
|
||||
| Validate Parameters |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Check Task Exists & In Progress |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Load Task Context (Implementation) |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Generate Verification Report |
|
||||
+-------+-------------------------+------+
|
||||
```
|
||||
|
||||
### 5.7 Task Completion Flow
|
||||
|
||||
```
|
||||
+--------------------+ +------------------+ +--------------------+
|
||||
| | | | | |
|
||||
| complete_task Schema|---->| completeTask |---->| processCompletion |
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+--------------------+ +--------+---------+ +---------+----------+
|
||||
| |
|
||||
v v
|
||||
+-------+-------------------------+------+
|
||||
| Validate Parameters |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Check Task Exists & In Progress |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Generate Completion Summary |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Update Task Status to Complete |
|
||||
+-------+-------------------------+------+
|
||||
```
|
||||
|
||||
### 5.8 Task Deletion Flow
|
||||
|
||||
```
|
||||
+--------------------+ +------------------+ +--------------------+
|
||||
| | | | | |
|
||||
| delete_task Schema |---->| deleteTask |---->| processTaskDeletion|
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+--------------------+ +--------+---------+ +---------+----------+
|
||||
| |
|
||||
v v
|
||||
+-------+-------------------------+------+
|
||||
| Validate Parameters |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Check Task Exists & Not Complete |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Update Dependent Tasks |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Remove Task from Task List |
|
||||
+-------+-------------------------+------+
|
||||
```
|
||||
|
||||
### 5.9 Task Complexity Assessment Flow
|
||||
|
||||
```
|
||||
+-------------------------+ +------------------------+
|
||||
| | | |
|
||||
| assessTaskComplexity |---->| Complex Analysis Logic |
|
||||
| (taskModel.ts) | | |
|
||||
+-------------------------+ +-----------+------------+
|
||||
|
|
||||
v
|
||||
+-----------+------------------------+
|
||||
| Check Task Description Length |
|
||||
+-----------+------------------------+
|
||||
|
|
||||
v
|
||||
+-----------+------------------------+
|
||||
| Count Technical Terms |
|
||||
+-----------+------------------------+
|
||||
|
|
||||
v
|
||||
+-----------+------------------------+
|
||||
| Analyze Dependency Count |
|
||||
+-----------+------------------------+
|
||||
|
|
||||
v
|
||||
+-----------+------------------------+
|
||||
| Count File Operations |
|
||||
+-----------+------------------------+
|
||||
|
|
||||
v
|
||||
+-----------+------------------------+
|
||||
| Calculate Weighted Complexity Score|
|
||||
+-----------+------------------------+
|
||||
```
|
||||
|
||||
### 5.10 Task File Loading Flow
|
||||
|
||||
```
|
||||
+----------------------+ +--------------------+
|
||||
| | | |
|
||||
| loadTaskRelatedFiles |---->| getFileSummaries |
|
||||
| (fileLoader.ts) | | (fileLoader.ts) |
|
||||
+----------------------+ +---------+----------+
|
||||
|
|
||||
v
|
||||
+--------+------------------------+
|
||||
| Format Paths to Absolute Paths |
|
||||
+--------+------------------------+
|
||||
|
|
||||
v
|
||||
+--------+------------------------+
|
||||
| Generate File Type Summaries |
|
||||
+--------+------------------------+
|
||||
|
|
||||
v
|
||||
+--------+------------------------+
|
||||
| Return Formatted File Summaries |
|
||||
+--------+------------------------+
|
||||
|
|
||||
v
|
||||
+--------+------------------------+
|
||||
| |
|
||||
+--------+---------------------+--+
|
||||
```
|
||||
|
||||
### 5.11 Updating Task Related Files Function
|
||||
|
||||
```
|
||||
+----------------------+ +---------------------+ +----------------------+
|
||||
| | | | | |
|
||||
| updateTaskFilesSchema |---->| updateTaskRelatedFiles |---->| updateTaskRelatedFiles |
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+----------------------+ +-----------+---------+ +-----------+----------+
|
||||
| |
|
||||
v v
|
||||
+-------+-------------------------+------+
|
||||
| Validate File Format and Path |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| Update Task Related Files List |
|
||||
+-------+-------------------------+------+
|
||||
```
|
||||
|
||||
## 6. Extensibility Considerations
|
||||
|
||||
### 6.1 Method for New Feature Extensions
|
||||
|
||||
The modular design of the Shrimp Task Manager makes it easy to extend. To add new features, typically you need to:
|
||||
|
||||
1. Define related data types in `types/index.ts`
|
||||
2. Implement core logic in the corresponding model files
|
||||
3. Create corresponding tool functions in the tool layer
|
||||
4. Register new tools in `index.ts`
|
||||
|
||||
### 6.2 Current Extension Points
|
||||
|
||||
The system currently provides the following extension points:
|
||||
|
||||
- **Task Processing Flow Extension**: Can extend the task processing flow by modifying functions like `executeTask`, `verifyTask`, etc.
|
||||
- **Complexity Assessment Extension**: Can add more evaluation metrics in `assessTaskComplexity`
|
||||
- **Summary Generation Extension**: Can enhance algorithms in `summaryExtractor.ts`
|
||||
- **File Processing Extension**: Can support more file type summary formatting in `fileLoader.ts`
|
||||
- **Filter Condition Extension**: Can add more filter condition options in task queries
|
||||
|
||||
## 7. System Limitations and Future Improvements
|
||||
|
||||
### 7.1 Current Limitations
|
||||
|
||||
- Uses file storage, not suitable for multi-user concurrent scenarios
|
||||
- Lacks user authentication and permission control
|
||||
- Summary generation uses simple rules, can be further improved
|
||||
- File processing does not read actual file content, only generates summary information
|
||||
|
||||
### 7.2 Potential Future Improvements
|
||||
|
||||
- Migrate to database storage, improving concurrent processing capabilities
|
||||
- Add user management and access control
|
||||
- Use more advanced algorithms to optimize summary generation
|
||||
- Add task priority and time planning functionality
|
||||
- Implement task execution progress tracking
|
||||
- Enhance file association system, supporting more complex relationship types
|
||||
- Implement automatic identification of related files
|
||||
- Support actual reading of file content, providing more detailed context
|
||||
|
||||
## 8. Conclusion
|
||||
|
||||
The Shrimp Task Manager adopts a modular, layered design, giving the system good maintainability and extensibility. Through 12 core tool functions and a well-developed data model, the system can effectively manage task processes in complex projects, performing exceptionally well in scenarios requiring long-term context memory.
|
||||
|
||||
The design focus of the system is to provide a clear task management process while enhancing the LLM's context memory capability during task execution. Through precise file association and intelligent context loading, it effectively solves the memory limitation problem that LLMs face when handling long-term complex tasks.
|
||||
|
||||
As the system continues to develop, future efforts will focus on improving data storage methods, optimizing summary generation algorithms, enhancing file processing capabilities, and adding more task management features, enabling the system to handle more complex task management scenarios.
|
@ -1,357 +0,0 @@
|
||||
[English](../en/functionality-checklist.md) | [中文](../zh/functionality-checklist.md)
|
||||
|
||||
# Shrimp Task Manager - Functionality Implementation Checklist
|
||||
|
||||
This document lists all the tools, functions, parameter structures, and features actually implemented in the Shrimp Task Manager system. This checklist serves as a reference baseline for documentation review.
|
||||
|
||||
## Type Definitions and Enumerations
|
||||
|
||||
### Task Status Enumeration (TaskStatus)
|
||||
|
||||
- `PENDING = "待處理"` - Tasks that have been created but not yet started
|
||||
- `IN_PROGRESS = "進行中"` - Tasks currently being executed
|
||||
- `COMPLETED = "已完成"` - Tasks that have been successfully completed and verified
|
||||
- `BLOCKED = "被阻擋"` - Tasks that cannot be executed temporarily due to dependencies
|
||||
|
||||
### Task Dependency (TaskDependency)
|
||||
|
||||
- `taskId: string` - Unique identifier of the prerequisite task that must be completed before the current task
|
||||
|
||||
### Related File Type Enumeration (RelatedFileType)
|
||||
|
||||
- `TO_MODIFY = "待修改"` - Files that need to be modified in the task
|
||||
- `REFERENCE = "參考資料"` - Reference materials or related documents for the task
|
||||
- `CREATE = "待建立"` - Files that need to be created in the task
|
||||
- `DEPENDENCY = "依賴文件"` - Component or library files that the task depends on
|
||||
- `OTHER = "其他"` - Other types of related files
|
||||
|
||||
### Related File (RelatedFile)
|
||||
|
||||
- `path: string` - File path, can be relative to the project root directory or an absolute path
|
||||
- `type: RelatedFileType` - Type of relationship between the file and the task
|
||||
- `description?: string` - Supplementary description of the file, explaining its specific relationship or purpose to the task
|
||||
- `lineStart?: number` - Starting line of the relevant code block (optional)
|
||||
- `lineEnd?: number` - Ending line of the relevant code block (optional)
|
||||
|
||||
### Task Interface (Task)
|
||||
|
||||
- `id: string` - Unique identifier of the task
|
||||
- `name: string` - Concise and clear task name
|
||||
- `description: string` - Detailed task description, including implementation points and acceptance criteria
|
||||
- `notes?: string` - Supplementary notes, special processing requirements, or implementation suggestions (optional)
|
||||
- `status: TaskStatus` - Current execution status of the task
|
||||
- `dependencies: TaskDependency[]` - List of prerequisite dependencies for the task
|
||||
- `createdAt: Date` - Timestamp when the task was created
|
||||
- `updatedAt: Date` - Timestamp when the task was last updated
|
||||
- `completedAt?: Date` - Timestamp when the task was completed (only applicable to completed tasks)
|
||||
- `summary?: string` - Task completion summary, concisely describing implementation results and important decisions (only applicable to completed tasks)
|
||||
- `relatedFiles?: RelatedFile[]` - List of files related to the task (optional)
|
||||
|
||||
### Task Complexity Level Enumeration (TaskComplexityLevel)
|
||||
|
||||
- `LOW = "低複雜度"` - Simple and straightforward tasks that usually do not require special handling
|
||||
- `MEDIUM = "中等複雜度"` - Tasks with some complexity but still manageable
|
||||
- `HIGH = "高複雜度"` - Complex and time-consuming tasks that require special attention
|
||||
- `VERY_HIGH = "極高複雜度"` - Extremely complex tasks that are recommended to be broken down
|
||||
|
||||
### Task Complexity Assessment Result (TaskComplexityAssessment)
|
||||
|
||||
- `level: TaskComplexityLevel` - Overall complexity level
|
||||
- `metrics: object` - Detailed data for each evaluation metric
|
||||
- `descriptionLength: number` - Length of description
|
||||
- `dependenciesCount: number` - Number of dependencies
|
||||
- `notesLength: number` - Length of notes
|
||||
- `hasNotes: boolean` - Whether notes are present
|
||||
- `recommendations: string[]` - List of handling recommendations
|
||||
|
||||
## Tool Functions and Parameters
|
||||
|
||||
### 1. plan_task
|
||||
|
||||
**Description**: Initialize and plan the task process in detail, establishing clear goals and success criteria
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `description: string` (required) - Comprehensive and detailed task problem description, should include task objectives, background, and expected outcomes
|
||||
- Must be at least 10 characters
|
||||
- `requirements?: string` (optional) - Specific technical requirements, business constraints, or quality standards for the task
|
||||
|
||||
**Return Value**:
|
||||
|
||||
- Returns a response containing planning prompts to guide the user in starting task analysis
|
||||
|
||||
### 2. analyze_task
|
||||
|
||||
**Description**: Deeply analyze task requirements and systematically check the codebase, evaluating technical feasibility and potential risks
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `summary: string` (required) - Structured task summary, including task objectives, scope, and key technical challenges
|
||||
- Must be at least 20 characters
|
||||
- `initialConcept: string` (required) - Initial solution concept, including technical solutions, architectural design, and implementation strategy
|
||||
- Must be at least 50 characters
|
||||
- `previousAnalysis?: string` (optional) - Analysis results from previous iterations, used for continuous improvement of the solution
|
||||
|
||||
**Return Value**:
|
||||
|
||||
- Returns a response containing technical analysis guidance to direct the user in conducting in-depth analysis
|
||||
|
||||
### 3. reflect_task
|
||||
|
||||
**Description**: Critically review analysis results, evaluate solution completeness, and identify optimization opportunities, ensuring the solution follows best practices
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `summary: string` (required) - Structured task summary, keeping consistent with the analysis phase to ensure continuity
|
||||
- Must be at least 20 characters
|
||||
- `analysis: string` (required) - Comprehensive and thorough technical analysis results, including all technical details, dependent components, and implementation plans
|
||||
- Must be at least 100 characters
|
||||
|
||||
**Return Value**:
|
||||
|
||||
- Returns a response containing reflection prompts and implementation suggestions
|
||||
|
||||
### 4. split_tasks
|
||||
|
||||
**Description**: Break down complex tasks into independent and trackable subtasks, establishing clear dependencies and priorities
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `updateMode: "append" | "overwrite" | "selective" | "clearAllTasks"` (required) - Task update mode selection:
|
||||
- `append`: Preserve all existing tasks and add new tasks
|
||||
- `overwrite`: Clear all incomplete tasks and completely replace them
|
||||
- `selective`: Update existing tasks based on task name matching, preserving tasks not in the list
|
||||
- `clearAllTasks`: Clear all tasks and create a backup
|
||||
- `tasks: Array<object>` (required) - Structured list of tasks, each task should be atomic and have clear completion criteria
|
||||
- `name: string` (required) - Concise and clear task name that should clearly express the task purpose
|
||||
- Not exceeding 100 characters
|
||||
- `description: string` (required) - Detailed task description, including implementation points, technical details, and acceptance criteria
|
||||
- Must be at least 10 characters
|
||||
- `notes?: string` (optional) - Supplementary notes, special processing requirements, or implementation suggestions
|
||||
- `dependencies?: string[]` (optional) - List of prerequisite task IDs or task names that this task depends on
|
||||
- `relatedFiles?: RelatedFile[]` (optional) - List of files related to the task
|
||||
|
||||
**Return Value**:
|
||||
|
||||
- Returns a response containing task splitting results, including the number of successfully created tasks and the list of task IDs
|
||||
|
||||
### 5. list_tasks
|
||||
|
||||
**Description**: Generate a structured task list, including complete status tracking, priorities, and dependencies
|
||||
|
||||
**Parameters**: None
|
||||
|
||||
**Return Value**:
|
||||
|
||||
- Returns a response containing a task list, displaying all tasks grouped by status
|
||||
|
||||
### 6. execute_task
|
||||
|
||||
**Description**: Execute a specific task according to the predefined plan, ensuring that the output of each step meets quality standards
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `taskId: string` (required) - Unique identifier of the task to be executed, must be a valid task ID existing in the system
|
||||
|
||||
**Return Value**:
|
||||
|
||||
- Returns a response containing task execution guidelines, including task details, complexity assessment, and suggested execution steps
|
||||
|
||||
### 7. verify_task
|
||||
|
||||
**Description**: Comprehensively verify task completion, ensuring all requirements and technical standards have been met, with no details omitted
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `taskId: string` (required) - Unique identifier of the task to be verified, must be a valid task ID existing in the system
|
||||
|
||||
**Return Value**:
|
||||
|
||||
- Returns a response containing task verification results, including completion criteria checks and specific verification items
|
||||
|
||||
### 8. complete_task
|
||||
|
||||
**Description**: Formally mark a task as completed, generate a detailed completion report, and update the dependency status of related tasks
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `taskId: string` (required) - Unique identifier of the task to be completed, must be a valid task ID existing in the system
|
||||
- `summary?: string` (optional) - Task completion summary, concisely describing implementation results and important decisions
|
||||
|
||||
**Return Value**:
|
||||
|
||||
- Returns a response containing task completion confirmation, including completion time and updated dependent task status
|
||||
|
||||
### 9. delete_task
|
||||
|
||||
**Description**: Delete an incomplete task, but do not allow deletion of completed tasks, ensuring the integrity of system records
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `taskId: string` (required) - Unique identifier of the task to be deleted, must be a valid and incomplete task ID existing in the system
|
||||
|
||||
**Return Value**:
|
||||
|
||||
- Returns a response containing task deletion results, including success or failure messages
|
||||
|
||||
### 10. clear_all_tasks
|
||||
|
||||
**Description**: Delete all incomplete tasks in the system, this command must be explicitly confirmed by the user to execute. At the same time, back up tasks to the memory subdirectory, saving task history records for future reference.
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `confirm: boolean` (required) - Confirm deletion of all incomplete tasks (this operation is irreversible)
|
||||
|
||||
**Return Value**:
|
||||
|
||||
- Returns a response containing the results of the clear operation, including success or failure messages, backup file name, and backup location
|
||||
|
||||
**Important Details**:
|
||||
|
||||
- Before deleting tasks, the current task list is automatically backed up to the data/memory subdirectory
|
||||
- Backup files are named using timestamps, in the format tasks_memory_YYYY-MM-DDThh-mm-ss.json
|
||||
- The memory subdirectory serves as a long-term memory repository for storing task history records, for future task planning reference
|
||||
|
||||
### 11. query_task
|
||||
|
||||
**Description**: Search for tasks based on keywords or ID, displaying abbreviated task information
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `query: string` (required) - Search query text, can be a task ID or multiple keywords (space-separated)
|
||||
- Must be at least 1 character
|
||||
- `isId: boolean` (optional) - Specify whether it is an ID query mode, default is false (keyword mode)
|
||||
- `page: number` (optional) - Page number, default is page 1
|
||||
- `pageSize: number` (optional) - Number of tasks displayed per page, default is 5 entries, maximum 20
|
||||
- Must be a positive integer, range 1-20
|
||||
|
||||
**Return Value**:
|
||||
|
||||
- Returns a response containing search results, including a list of tasks matching the criteria, pagination information, and total number of results
|
||||
|
||||
**Important Details**:
|
||||
|
||||
- When `isId` is true, the system will precisely query the task with the specified ID
|
||||
- When `isId` is false, the system will search for the specified keywords in task names, descriptions, and summaries
|
||||
- Keyword mode supports multiple keywords (space-separated), returning tasks matching any of the keywords
|
||||
- Results are sorted by task status and update time, making it easy to quickly find the most relevant tasks
|
||||
|
||||
### 12. update_task
|
||||
|
||||
**Description**: Update task content, including name, description, and notes, but do not allow modification of completed tasks
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `taskId: string` (required) - Unique identifier of the task to be updated, must be a valid and incomplete task ID existing in the system
|
||||
- `name?: string` (optional) - New name for the task
|
||||
- `description?: string` (optional) - New description content for the task
|
||||
- `notes?: string` (optional) - New supplementary notes for the task
|
||||
|
||||
**Return Value**:
|
||||
|
||||
- Returns a response containing task update results, including success or failure messages
|
||||
|
||||
### 13. get_task_detail
|
||||
|
||||
**Description**: Get complete detailed information of a task based on the task ID, including untruncated implementation guidelines and verification standards
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `taskId: string` (required) - ID of the task to view details
|
||||
- Must be at least 1 character
|
||||
|
||||
**Return Value**:
|
||||
|
||||
- Returns a response containing complete task details, including all task attributes, especially complete implementation guidelines and verification standards
|
||||
|
||||
**Important Details**:
|
||||
|
||||
- Unlike `list_tasks`, this function returns complete details of a single task, with no content truncation
|
||||
- Suitable for in-depth understanding of specific task requirements and technical details
|
||||
- Provides a complete list of related files and task analysis results
|
||||
- Can be used to view long text content that may be omitted during execution
|
||||
|
||||
### 14. update_task_files
|
||||
|
||||
**Description**: Update the list of related files for a task, used to record code files, reference materials, etc. related to the task
|
||||
|
||||
**Parameters**:
|
||||
|
||||
- `taskId: string` (required) - Unique identifier of the task to be updated, must be a valid and incomplete task ID existing in the system
|
||||
- `relatedFiles: Array<RelatedFile>` (required) - List of files related to the task
|
||||
- `path: string` (required) - File path, can be relative to the project root directory or an absolute path
|
||||
- `type: RelatedFileType` (required) - Type of relationship between the file and the task
|
||||
- `description?: string` (optional) - Supplementary description of the file
|
||||
- `lineStart?: number` (optional) - Starting line of the relevant code block
|
||||
- `lineEnd?: number` (optional) - Ending line of the relevant code block
|
||||
|
||||
**Return Value**:
|
||||
|
||||
- Returns a response containing file update results, including success or failure messages
|
||||
|
||||
## Important Details of Tool Functions
|
||||
|
||||
### Dependency (dependencies) Handling
|
||||
|
||||
- In `splitTasks` and other functions, the `dependencies` parameter accepts task names or task IDs (UUID)
|
||||
- The system converts string arrays to `TaskDependency` object arrays when creating or updating tasks
|
||||
- Task dependencies form a directed acyclic graph (DAG), used to determine task execution order and blocking status
|
||||
|
||||
### Task Complexity Assessment
|
||||
|
||||
- The system uses the `assessTaskComplexity` function to evaluate task complexity
|
||||
- Evaluation is based on multiple metrics: description length, number of dependencies, notes length, etc.
|
||||
- Complexity levels are determined based on thresholds defined in `TaskComplexityThresholds`
|
||||
- Complexity assessment results are used to generate appropriate handling recommendations
|
||||
|
||||
### File Processing Features
|
||||
|
||||
- The `loadTaskRelatedFiles` function does not actually read file contents, it only generates file information summaries
|
||||
- Files are sorted by type priority: TO_MODIFY > REFERENCE > DEPENDENCY > CREATE > OTHER
|
||||
- Supports specifying code block line number ranges for precise localization of key implementations
|
||||
|
||||
## Utility Functions
|
||||
|
||||
### Summary Extraction (summaryExtractor.ts)
|
||||
|
||||
- `extractSummary` - Extract short summaries from text, automatically handling Markdown format
|
||||
- `generateTaskSummary` - Generate task completion summaries based on task names and descriptions
|
||||
- `extractTitle` - Extract text suitable as titles from content
|
||||
|
||||
### File Loading (fileLoader.ts)
|
||||
|
||||
- `loadTaskRelatedFiles` - Generate content summaries of task-related files
|
||||
- `generateFileInfo` - Generate basic file information summaries
|
||||
|
||||
## Task Memory Feature
|
||||
|
||||
The Task Memory feature is an important characteristic of the Shrimp Task Manager, giving the system long-term memory capabilities to save, query, and utilize past task execution experiences.
|
||||
|
||||
### Core Implementation
|
||||
|
||||
1. **Automatic Backup Mechanism**:
|
||||
|
||||
- Dual backup functionality implemented in the `clearAllTasks` function
|
||||
- Task backups are saved in both the data directory and the data/memory subdirectory
|
||||
- Backup files are named using timestamps, in the format tasks_memory_YYYY-MM-DDThh-mm-ss.json
|
||||
|
||||
2. **Intelligent Prompt Guidance**:
|
||||
- Task memory retrieval guidelines added to the prompt in the `planTask` function
|
||||
- Guides Agents on how to find, analyze, and apply historical task records
|
||||
- Provides intelligent reference suggestions, promoting knowledge reuse
|
||||
|
||||
### Use Cases
|
||||
|
||||
- **During Task Planning**: Reference implementation plans and best practices from similar tasks
|
||||
- **During Problem Solving**: Consult similar problems encountered in the past and their solutions
|
||||
- **During Code Reuse**: Identify reusable components or patterns implemented in the past
|
||||
- **During Experience Learning**: Analyze past successful and failed cases, continuously optimize working methods
|
||||
|
||||
### Technical Points
|
||||
|
||||
- Use relative paths to reference the memory directory, maintaining code consistency and maintainability
|
||||
- Ensure the memory directory exists, automatically creating it if it doesn't
|
||||
- Maintain the original error handling pattern, ensuring system stability
|
||||
- The backup process is transparent and unnoticeable, not affecting the user's normal operation flow
|
||||
|
||||
This feature requires no additional tools or configuration. The system automatically saves historical records when tasks are cleared and provides intelligent guidance during task planning, allowing Agents to fully utilize past experiences and knowledge.
|
@ -16,22 +16,64 @@ This system allows users to customize the prompt content for each tool function
|
||||
|
||||
Where `[FUNCTION_NAME]` is the name of the tool function in uppercase. For example, for the task planning function `planTask`, the corresponding environment variable name is `MCP_PROMPT_PLAN_TASK`.
|
||||
|
||||
## Multi-language Prompt Templates
|
||||
|
||||
Shrimp Task Manager supports prompt templates in multiple languages, configurable via the `TEMPLATES_USE` environment variable:
|
||||
|
||||
- Currently supported languages: `en` (English) and `zh` (Traditional Chinese)
|
||||
- Default is `en` (English)
|
||||
|
||||
### Switching Languages
|
||||
|
||||
Set in the `mcp.json` configuration:
|
||||
|
||||
```json
|
||||
"env": {
|
||||
"TEMPLATES_USE": "zh" // Use Traditional Chinese templates
|
||||
}
|
||||
```
|
||||
|
||||
Or in the `.env` file:
|
||||
|
||||
```
|
||||
TEMPLATES_USE=zh
|
||||
```
|
||||
|
||||
### Custom Templates
|
||||
|
||||
You can create your own template set:
|
||||
|
||||
1. Copy an existing template set (e.g., `src/prompts/templates_en` or `src/prompts/templates_zh`) to your directory specified by `DATA_DIR`
|
||||
2. Rename the copied directory (e.g., `my_templates`)
|
||||
3. Modify the template files to meet your needs
|
||||
4. Set the `TEMPLATES_USE` environment variable to your template directory name:
|
||||
|
||||
```json
|
||||
"env": {
|
||||
"DATA_DIR": "/path/to/project/data",
|
||||
"TEMPLATES_USE": "my_templates"
|
||||
}
|
||||
```
|
||||
|
||||
The system will prioritize your custom templates and fall back to the built-in English templates if specific template files cannot be found.
|
||||
|
||||
## Supported Tool Functions
|
||||
|
||||
All major functions in the system support prompt customization through environment variables:
|
||||
|
||||
| Function Name | Environment Variable Prefix | Description |
|
||||
| --------------- | ---------------------------- | ------------------- |
|
||||
| `planTask` | `MCP_PROMPT_PLAN_TASK` | Task planning |
|
||||
| `analyzeTask` | `MCP_PROMPT_ANALYZE_TASK` | Task analysis |
|
||||
| `reflectTask` | `MCP_PROMPT_REFLECT_TASK` | Solution evaluation |
|
||||
| `splitTasks` | `MCP_PROMPT_SPLIT_TASKS` | Task splitting |
|
||||
| `executeTask` | `MCP_PROMPT_EXECUTE_TASK` | Task execution |
|
||||
| `verifyTask` | `MCP_PROMPT_VERIFY_TASK` | Task verification |
|
||||
| `completeTask` | `MCP_PROMPT_COMPLETE_TASK` | Task completion |
|
||||
| `listTasks` | `MCP_PROMPT_LIST_TASKS` | List tasks |
|
||||
| `queryTask` | `MCP_PROMPT_QUERY_TASK` | Query tasks |
|
||||
| `getTaskDetail` | `MCP_PROMPT_GET_TASK_DETAIL` | Get task details |
|
||||
| Function Name | Environment Variable Prefix | Description |
|
||||
| ------------------ | ------------------------------- | ------------------------ |
|
||||
| `planTask` | `MCP_PROMPT_PLAN_TASK` | Task planning |
|
||||
| `analyzeTask` | `MCP_PROMPT_ANALYZE_TASK` | Task analysis |
|
||||
| `reflectTask` | `MCP_PROMPT_REFLECT_TASK` | Solution evaluation |
|
||||
| `splitTasks` | `MCP_PROMPT_SPLIT_TASKS` | Task splitting |
|
||||
| `executeTask` | `MCP_PROMPT_EXECUTE_TASK` | Task execution |
|
||||
| `verifyTask` | `MCP_PROMPT_VERIFY_TASK` | Task verification |
|
||||
| `listTasks` | `MCP_PROMPT_LIST_TASKS` | List tasks |
|
||||
| `queryTask` | `MCP_PROMPT_QUERY_TASK` | Query tasks |
|
||||
| `getTaskDetail` | `MCP_PROMPT_GET_TASK_DETAIL` | Get task details |
|
||||
| `processThought` | `MCP_PROMPT_PROCESS_THOUGHT` | Thought chain processing |
|
||||
| `initProjectRules` | `MCP_PROMPT_INIT_PROJECT_RULES` | Initialize project rules |
|
||||
|
||||
## Environment Variable Configuration Methods
|
||||
|
||||
@ -151,11 +193,6 @@ The parameters supported by each function are as follows:
|
||||
|
||||
- `{task}` - Task details
|
||||
|
||||
### completeTask Supported Parameters
|
||||
|
||||
- `{task}` - Task details
|
||||
- `{completionTime}` - Completion time
|
||||
|
||||
### listTasks Supported Parameters
|
||||
|
||||
- `{status}` - Task status
|
||||
|
@ -2,6 +2,94 @@
|
||||
|
||||
# 更新日誌
|
||||
|
||||
## [1.0.21]
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增對 ListRoots 協議的支援,優化 DATA_DIR 配置方式 (99baa0f)
|
||||
- 新增 WEB_PORT 環境變數以自訂 WebGUI 埠號 (8771a5b)
|
||||
|
||||
### 變更
|
||||
|
||||
- 更新相關文檔說明以反映新的配置選項 (99baa0f, 8771a5b)
|
||||
|
||||
### 修復
|
||||
|
||||
- 修復 #56:新增可配置的 WebGUI 埠號以避免埠號衝突 (8771a5b)
|
||||
|
||||
## [1.0.20]
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增重置按鈕和縮略圖
|
||||
- 增強關係依賴圖和任務列表交互,篩選和點擊任務列表使關係依賴圖響應變化
|
||||
|
||||
### 變更
|
||||
|
||||
- 移除關係依賴圖開頭動畫,避免動畫跳變
|
||||
- 優化關係依賴圖初始狀態
|
||||
|
||||
## [1.0.19]
|
||||
|
||||
### 新增
|
||||
|
||||
- 新增研究模式功能,用於系統性程式編程研究 (5267fa4)
|
||||
- 新增研究模式的英文和中文提示詞模板 (5267fa4)
|
||||
- 新增完整的研究模式文檔和使用指南 (288bec9)
|
||||
|
||||
### 變更
|
||||
|
||||
- 增強 README,新增研究模式功能描述和使用說明 (288bec9)
|
||||
- 更新中文文檔,包含研究模式功能說明 (288bec9)
|
||||
|
||||
## [1.0.18]
|
||||
|
||||
### 修復
|
||||
|
||||
- 修復 #29:移除不必要的 console.log 輸出以減少雜訊 (7cf1a18)
|
||||
- 修復 #28:修正 WebGUI 任務詳情檢視的國際化問題 (fd26bfa)
|
||||
|
||||
### 變更
|
||||
|
||||
- 增強 WebGUI 任務詳情檢視,為所有標籤使用適當的翻譯函數 (fd26bfa)
|
||||
- 更新思維過程階段描述為英文,提升一致性 (fd26bfa)
|
||||
|
||||
## [1.0.17]
|
||||
|
||||
### 修復
|
||||
|
||||
- 修復 #26:修正 WebGUI 中任務狀態顯示為中文的問題 (16913ad)
|
||||
- 修復 #26:優化 WebGUI 預設語系會根據環境變數 TEMPLATES_USE 設定改變 (51436bb)
|
||||
|
||||
### 變更
|
||||
|
||||
- 更新 .env.example 以包含語系設定說明文檔 (51436bb)
|
||||
- 增強 WebGUI 語言處理邏輯,提供更好的國際化支援 (51436bb)
|
||||
|
||||
## [1.0.16]
|
||||
|
||||
### 修復
|
||||
|
||||
- 修復:修正 Augment AI 不支援 uuid format 問題,改用自定義正則表達式進行驗證 (4264fa7)
|
||||
|
||||
### 變更
|
||||
|
||||
- 更新任務規劃相關提示詞,新增嚴重警告以禁止假設、猜測與幻想,強調必須使用可用工具收集真實資訊 (cb838cb)
|
||||
- 調整任務描述以更清楚表達任務目標 (cb838cb)
|
||||
- 優化錯誤訊息提示,增加分批呼叫建議以解決長文本格式問題 (cb838cb)
|
||||
|
||||
## [1.0.15]
|
||||
|
||||
### 修復
|
||||
|
||||
- 修復:修正 gemini-2.5-pro-preview-05-06 會跳過執行任務直接完成的錯誤 (6d8a422)
|
||||
- 修復問題 #20 (5d1c28d)
|
||||
|
||||
### 變更
|
||||
|
||||
- 將 rule.md 改為存放至根目錄,這樣 DATA_DIR 才可以放置在專案外為後續協作架構做準備 (313e338)
|
||||
- 更新文檔 (28984f)
|
||||
|
||||
## [1.0.14]
|
||||
|
||||
### 變更
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
- [✨ 功能特點](#功能特點1)
|
||||
- [📖 使用指南](#使用指南)
|
||||
- [🔬 研究模式](#研究模式)
|
||||
- [🧠 任務記憶功能](#任務記憶功能)
|
||||
- [🤔 思維鏈過程](#思維鏈過程)
|
||||
- [📋 專案規範初始化](#專案規範初始化)
|
||||
- [🌐 網頁圖形介面](#網頁圖形介面)
|
||||
- [📚 文件資源](#文件資源)
|
||||
@ -37,8 +37,9 @@
|
||||
- **任務摘要自動更新**:完成任務時自動產生摘要,優化記憶效能
|
||||
- **任務記憶功能**:自動備份任務歷史記錄,提供長期記憶和參考能力
|
||||
- **思維鏈過程**:通過步驟化的推理系統性地分析複雜問題
|
||||
- **研究模式**:系統性技術研究功能,提供引導式工作流程來探索技術、最佳實踐和解決方案比較
|
||||
- **專案規範初始化**:定義專案標準和規則,維持大型專案的一致性
|
||||
- **<a id="網頁圖形介面"></a>網頁圖形介面**:提供選用的網頁圖形化使用者介面來管理任務。透過在您的 `.env` 檔案中設定 `ENABLE_GUI=true` 來啟用。啟用後,將會在您的 `DATA_DIR` 中建立一個包含存取網址的 `WebGUI.md` 檔案。
|
||||
- **<a id="網頁圖形介面"></a>網頁圖形介面**:提供選用的網頁圖形化使用者介面來管理任務。透過在您的 `.env` 檔案中設定 `ENABLE_GUI=true` 來啟用。啟用後,將會在您的 `DATA_DIR` 中建立一個包含存取網址的 `WebGUI.md` 檔案。您可以透過設定 `WEB_PORT` 來自訂網頁埠號(若未指定,系統將自動選擇可用的埠號)。
|
||||
|
||||
## 🧭 <a id="使用指南"></a>使用指南
|
||||
|
||||
@ -48,6 +49,17 @@
|
||||
|
||||
蝦米本質上是一個提示詞範本,通過一系列提示詞引導 AI Agent 更好地理解和適應您的專案。它確保 Agent 能夠更貼近您專案的特定需求和慣例。
|
||||
|
||||
### 實際應用中的研究模式
|
||||
|
||||
在深入任務規劃之前,您可以善用研究模式進行技術調查和知識收集。這在以下情況特別有用:
|
||||
|
||||
- 您需要探索新的技術或框架
|
||||
- 您想要比較不同的解決方案方法
|
||||
- 您正在調查專案的最佳實踐
|
||||
- 您需要理解複雜的技術概念
|
||||
|
||||
只需告訴 Agent「研究 [您的主題]」或「進入研究模式研究 [技術/問題]」即可開始系統性調查。研究發現將為您後續的任務規劃和開發決策提供資訊基礎。
|
||||
|
||||
### 首次使用設置
|
||||
|
||||
在使用新專案時,只需對 Agent 說「init project rules」(初始化專案規則)。這將引導 Agent 生成一份符合您專案特定需求和結構的規則檔案。
|
||||
@ -76,6 +88,52 @@
|
||||
|
||||
您可以透過設定 `TEMPLATES_USE` 環境變數來切換系統提示詞的語言。預設支援 `en`(英文)和 `zh`(繁體中文)。此外,您也可以複製現有的模板目錄(例如 `src/prompts/templates_en`)到 `DATA_DIR` 指定的位置,進行修改後,將 `TEMPLATES_USE` 指向您的客製化模板目錄名稱,以實現更深度的提示詞客製化
|
||||
|
||||
## 🔬 <a id="研究模式"></a>研究模式
|
||||
|
||||
蝦米任務管理器包含專門的研究模式,專為系統性技術調查和知識收集而設計。
|
||||
|
||||
### 什麼是研究模式?
|
||||
|
||||
研究模式是一個引導式工作流程系統,幫助 AI Agent 進行徹底且系統性的技術研究。它提供結構化的方法來探索技術、比較解決方案、調查最佳實踐,並為程式設計任務收集全面的資訊。
|
||||
|
||||
### 主要功能
|
||||
|
||||
- **系統性調查**:結構化工作流程確保研究主題的全面覆蓋
|
||||
- **多源研究**:結合網路搜尋和程式碼庫分析,實現完整理解
|
||||
- **狀態管理**:在多個會話中維護研究上下文和進度
|
||||
- **引導式探索**:防止研究變得不專注或偏離主題
|
||||
- **知識整合**:將研究發現與任務規劃和執行無縫整合
|
||||
|
||||
### 何時使用研究模式
|
||||
|
||||
研究模式特別適用於:
|
||||
|
||||
- **技術探索**:調查新的框架、函式庫或工具
|
||||
- **最佳實踐研究**:尋找行業標準和推薦方法
|
||||
- **解決方案比較**:評估不同的技術方法或架構
|
||||
- **問題調查**:深入研究複雜的技術挑戰
|
||||
- **架構規劃**:研究設計模式和系統架構
|
||||
|
||||
### 如何使用研究模式
|
||||
|
||||
只需告訴 Agent 進入研究模式並指定您的主題:
|
||||
|
||||
- **基本用法**:「進入研究模式研究 [您的主題]」
|
||||
- **特定研究**:「研究 [特定技術/問題]」
|
||||
- **比較分析**:「研究並比較 [選項 A 與選項 B]」
|
||||
|
||||
系統將引導 Agent 通過結構化的研究階段,確保徹底調查的同時保持對您特定需求的專注。
|
||||
|
||||
### 研究工作流程
|
||||
|
||||
1. **主題定義**:明確定義研究範圍和目標
|
||||
2. **資訊收集**:系統性收集相關資訊
|
||||
3. **分析與綜合**:處理和組織研究發現
|
||||
4. **狀態更新**:定期進度追蹤和上下文保存
|
||||
5. **整合應用**:將研究結果應用到您的專案上下文中
|
||||
|
||||
> **💡 建議**:為了獲得最佳的研究模式體驗,我們建議使用 **Claude 4 Sonnet**,它提供卓越的分析能力和全面的研究綜合功能。
|
||||
|
||||
## 🧠 <a id="任務記憶功能"></a>任務記憶功能
|
||||
|
||||
蝦米任務管理器具備長期記憶功能,可以自動保存任務執行的歷史記錄,並在規劃新任務時提供參考經驗。
|
||||
@ -95,17 +153,6 @@
|
||||
|
||||
通過有效利用任務記憶功能,系統能夠不斷積累經驗,智能化程度和工作效率將持續提升。
|
||||
|
||||
## 🤔 <a id="思維鏈過程"></a>思維鏈過程
|
||||
|
||||
思維鏈功能通過結構化思考增強問題解決能力:
|
||||
|
||||
- **系統化推理**:將複雜問題分解為邏輯步驟
|
||||
- **假設測試**:挑戰假設以驗證解決方案的可行性
|
||||
- **批判性分析**:使用嚴格標準評估各種解決方案選項
|
||||
- **改進決策過程**:通過深思熟慮達成更可靠的結論
|
||||
|
||||
當啟用此功能(預設設定)時,系統會引導 Agent 使用 `process_thought` 工具進行逐步推理,確保在實施前進行徹底的問題分析。
|
||||
|
||||
## 📋 <a id="專案規範初始化"></a>專案規範初始化
|
||||
|
||||
專案規範功能有助於維持代碼庫的一致性:
|
||||
@ -134,7 +181,6 @@
|
||||
|
||||
## 📚 <a id="文件資源"></a>文件資源
|
||||
|
||||
- [系統架構](architecture.md):詳細的系統設計與數據流說明
|
||||
- [提示詞自定義指南](prompt-customization.md):透過環境變數自定義工具提示詞的說明
|
||||
- [更新日誌](CHANGELOG.md):記錄此專案的所有重要變更
|
||||
|
||||
@ -166,53 +212,25 @@ npm run build
|
||||
|
||||
蝦米任務管理器提供兩種配置方式:全局配置和專案特定配置。
|
||||
|
||||
#### ListRoots 協議支援
|
||||
|
||||
蝦米任務管理器現在支援 **ListRoots 協議**,提供自動專案隔離和靈活的路徑配置功能:
|
||||
|
||||
- **如果您的客戶端支援 ListRoots** (例如 Cursor IDE):
|
||||
|
||||
- **絕對路徑模式**:在指定的 DATA_DIR 中建立專案資料夾,讓您可以使用全域 mcp.json 配置,Shrimp 會自動隔離專案
|
||||
- **相對路徑模式**:在專案根目錄中建立 DATA_DIR 來存放 Shrimp 資料
|
||||
|
||||
- **如果您的客戶端不支援 ListRoots**:
|
||||
- DATA_DIR 保持舊版邏輯(建議使用絕對路徑)
|
||||
- 建議向您的客戶端廠商要求支援 ListRoots 協議以獲得增強功能
|
||||
|
||||
#### 全局配置
|
||||
|
||||
1. 開啟 Cursor IDE 的全局設定檔案(通常位於 `~/.cursor/mcp.json`)
|
||||
2. 在 `mcpServers` 區段中添加以下配置:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"shrimp-task-manager": {
|
||||
"command": "node",
|
||||
"args": ["/mcp-shrimp-task-manager/dist/index.js"],
|
||||
"env": {
|
||||
"DATA_DIR": "/mcp-shrimp-task-manager/data",
|
||||
"ENABLE_THOUGHT_CHAIN": "true",
|
||||
"TEMPLATES_USE": "en",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
or
|
||||
|
||||
{
|
||||
"mcpServers": {
|
||||
"shrimp-task-manager": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "mcp-shrimp-task-manager"],
|
||||
"env": {
|
||||
"DATA_DIR": "/mcp-shrimp-task-manager/data",
|
||||
"ENABLE_THOUGHT_CHAIN": "true",
|
||||
"TEMPLATES_USE": "en",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> ⚠️ 請將 `/mcp-shrimp-task-manager` 替換為您的實際路徑。
|
||||
|
||||
#### 專案特定配置
|
||||
|
||||
您也可以為每個專案設定專屬配置,以便針對不同專案使用獨立的數據目錄:
|
||||
|
||||
1. 在專案根目錄創建 `.cursor` 目錄
|
||||
2. 在該目錄下創建 `mcp.json` 文件,內容如下:
|
||||
**選項 A:絕對路徑(專案隔離模式)**
|
||||
|
||||
```json
|
||||
{
|
||||
@ -221,26 +239,8 @@ or
|
||||
"command": "node",
|
||||
"args": ["/path/to/mcp-shrimp-task-manager/dist/index.js"],
|
||||
"env": {
|
||||
"DATA_DIR": "/path/to/project/data", // 必須使用絕對路徑
|
||||
"ENABLE_THOUGHT_CHAIN": "true",
|
||||
"TEMPLATES_USE": "en",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
or
|
||||
|
||||
{
|
||||
"mcpServers": {
|
||||
"shrimp-task-manager": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "mcp-shrimp-task-manager"],
|
||||
"env": {
|
||||
"DATA_DIR": "/path/to/project/data", // 必須使用絕對路徑
|
||||
"ENABLE_THOUGHT_CHAIN": "true",
|
||||
"TEMPLATES_USE": "en",
|
||||
"DATA_DIR": "/Users/username/ShrimpData", // 絕對路徑 - 自動建立專案資料夾
|
||||
"TEMPLATES_USE": "zh",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
@ -248,17 +248,153 @@ or
|
||||
}
|
||||
```
|
||||
|
||||
**選項 B:NPX 配合絕對路徑**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"shrimp-task-manager": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "mcp-shrimp-task-manager"],
|
||||
"env": {
|
||||
"DATA_DIR": "/Users/username/ShrimpData", // 絕對路徑 - 自動建立專案資料夾
|
||||
"TEMPLATES_USE": "zh",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> ⚠️ 請將 `/path/to/mcp-shrimp-task-manager` 和 `/Users/username/ShrimpData` 替換為您的實際路徑。
|
||||
>
|
||||
> 💡 **絕對路徑優勢**:透過 ListRoots 支援,Shrimp 會自動為每個專案建立獨立資料夾(例如 `/Users/username/ShrimpData/my-project/`、`/Users/username/ShrimpData/another-project/`),實現完美的專案隔離,只需要一個全域配置。
|
||||
>
|
||||
> 💡 **可選設定:** 您可以在 `env` 區段中添加 `"WEB_PORT": "3000"` 來指定網頁 GUI 的自訂埠號。若未指定,系統將自動選擇可用的埠號。
|
||||
|
||||
#### 專案特定配置
|
||||
|
||||
您也可以為每個專案設定專屬配置。此方法允許使用相對路徑進行專案內數據存放:
|
||||
|
||||
1. 在專案根目錄創建 `.cursor` 目錄
|
||||
2. 在該目錄下創建 `mcp.json` 文件,內容如下:
|
||||
|
||||
**選項 A:相對路徑(專案內存放模式)**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"shrimp-task-manager": {
|
||||
"command": "node",
|
||||
"args": ["/path/to/mcp-shrimp-task-manager/dist/index.js"],
|
||||
"env": {
|
||||
"DATA_DIR": ".shrimp", // 相對路徑 - 在專案根目錄建立資料夾
|
||||
"TEMPLATES_USE": "zh",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**選項 B:NPX 配合相對路徑**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"shrimp-task-manager": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "mcp-shrimp-task-manager"],
|
||||
"env": {
|
||||
"DATA_DIR": "shrimp-data", // 相對路徑 - 在專案根目錄建立資料夾
|
||||
"TEMPLATES_USE": "zh",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**選項 C:絕對路徑(替代方案)**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"shrimp-task-manager": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "mcp-shrimp-task-manager"],
|
||||
"env": {
|
||||
"DATA_DIR": "/Users/username/ShrimpData", // 絕對路徑配合專案隔離
|
||||
"TEMPLATES_USE": "zh",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> ⚠️ 請將 `/path/to/mcp-shrimp-task-manager` 替換為您的實際路徑。
|
||||
>
|
||||
> 💡 **相對路徑優勢**:資料存放在專案目錄內(例如 `./shrimp-data/`),方便根據需要選擇是否納入版本控制。
|
||||
>
|
||||
> 💡 **可選設定:** 您可以在 `env` 區段中添加 `"WEB_PORT": "3000"` 來指定網頁 GUI 的自訂埠號。若未指定,系統將自動選擇可用的埠號。
|
||||
|
||||
### ⚠️ 重要配置說明
|
||||
|
||||
**DATA_DIR 參數**是蝦米任務管理器存儲任務數據、對話記錄等信息的目錄,正確設置此參數對於系統的正常運行至關重要。此參數必須使用**絕對路徑**,使用相對路徑可能導致系統無法正確定位數據目錄,造成數據丟失或功能失效。
|
||||
**DATA_DIR 參數**是蝦米任務管理器存儲任務數據、對話記錄等資訊的目錄。新的實作支援絕對路徑和相對路徑,並根據您的客戶端功能提供智慧化行為。
|
||||
|
||||
> **警告**:使用相對路徑可能導致以下問題:
|
||||
#### 🚀 支援 ListRoots 協議(建議)
|
||||
|
||||
如果您的客戶端支援 **ListRoots 協議**(如 Cursor IDE),蝦米任務管理器會自動偵測您的專案根目錄並提供增強功能:
|
||||
|
||||
**絕對路徑模式(專案隔離):**
|
||||
|
||||
- 配置:`"DATA_DIR": "/Users/username/ShrimpData"`
|
||||
- 行為:自動建立 `{DATA_DIR}/{專案名稱}/`
|
||||
- 範例:對於專案 "my-app" → `/Users/username/ShrimpData/my-app/`
|
||||
- **優勢**:使用一個全域配置管理所有專案,完美隔離
|
||||
|
||||
**相對路徑模式(專案內存放):**
|
||||
|
||||
- 配置:`"DATA_DIR": ".shrimp"` 或 `"DATA_DIR": "shrimp-data"`
|
||||
- 行為:在專案內建立 `{專案根目錄}/{DATA_DIR}/`
|
||||
- 範例:對於 DATA_DIR "shrimp-data" → `./shrimp-data/`
|
||||
- **優勢**:資料與專案一起存放,方便選擇是否納入版本控制
|
||||
|
||||
#### ⚠️ 不支援 ListRoots 協議(舊版模式)
|
||||
|
||||
如果您的客戶端**不支援 ListRoots**,系統會回退到舊版行為:
|
||||
|
||||
- **強烈建議使用絕對路徑**以避免路徑解析問題
|
||||
- 相對路徑可能在不同環境下導致行為不一致
|
||||
- 建議向您的客戶端廠商要求 ListRoots 支援以獲得增強功能
|
||||
|
||||
> **舊版警告**:沒有 ListRoots 支援時,使用相對路徑可能導致:
|
||||
>
|
||||
> - 數據檔案找不到,導致系統初始化失敗
|
||||
> - 任務狀態丟失或無法正確保存
|
||||
> - 應用程式在不同環境下行為不一致
|
||||
> - 系統崩潰或無法啟動
|
||||
|
||||
#### 💡 選擇合適的配置
|
||||
|
||||
**使用絕對路徑(全域)當:**
|
||||
|
||||
- 您想用一個配置管理多個專案
|
||||
- 您偏好集中式資料存放
|
||||
- 您想要自動專案隔離
|
||||
|
||||
**使用相對路徑(專案特定)當:**
|
||||
|
||||
- 您想讓資料存放在專案目錄內
|
||||
- 您在不同環境中工作
|
||||
- 您需要精確控制版本控制的內容
|
||||
|
||||
**使用舊版模式當:**
|
||||
|
||||
- 您的客戶端不支援 ListRoots 協議
|
||||
- 您需要與較舊的客戶端版本相容
|
||||
|
||||
### 🔧 環境變數配置
|
||||
|
||||
蝦米任務管理器支援透過環境變數自定義提示詞行為,讓您無需修改程式碼即可微調 AI 助手的回應。您可以在配置中或透過 `.env` 文件設置這些變數:
|
||||
@ -273,7 +409,6 @@ or
|
||||
"DATA_DIR": "/path/to/project/data",
|
||||
"MCP_PROMPT_PLAN_TASK": "自定義規劃指導...",
|
||||
"MCP_PROMPT_EXECUTE_TASK_APPEND": "附加執行說明...",
|
||||
"ENABLE_THOUGHT_CHAIN": "true",
|
||||
"TEMPLATES_USE": "en",
|
||||
"ENABLE_GUI": "false"
|
||||
}
|
||||
@ -290,8 +425,9 @@ or
|
||||
此外,還有其他系統配置變數:
|
||||
|
||||
- **DATA_DIR**:指定任務數據存儲的目錄
|
||||
- **ENABLE_THOUGHT_CHAIN**:控制任務規劃工作流中的思考模式。當設置為 `true`(預設值)時,系統引導用戶使用 `process_thought` 工具進行逐步推理。當設置為 `false` 時,系統直接使用 `analyze_task` 提交分析結果,跳過詳細的思考過程。
|
||||
- **TEMPLATES_USE**:指定提示詞使用的模板集。預設為 `en`。目前可用的選項有 `en` 和 `zh`。若要使用自定義模板,請將 `src/prompts/templates_en` 目錄複製到 `DATA_DIR` 指定的位置,重新命名複製的目錄(例如,`my_templates`),並將 `TEMPLATES_USE` 設置為新的目錄名稱(例如,`my_templates`)。
|
||||
- **TEMPLATES_USE**:指定提示詞使用的模板集。預設為 `en`。目前可用的選項有 `en` 和 `zh`。若要使用自定義模板,請將 `src/prompts/templates_en` 目錄複製到 `DATA_DIR` 指定的位置,重新命名複製的目錄(例如,`my_templates`),並將 `TEMPLATES_USE` 設置為新的目錄名稱(例如,`my_templates`)
|
||||
- **ENABLE_GUI**:啟用或停用網頁圖形化使用者介面。設定為 `true` 以啟用,`false` 以停用(預設)
|
||||
- **WEB_PORT**:指定網頁 GUI 的埠號。若未指定,系統將自動選擇可用的埠號。僅在 `ENABLE_GUI` 設定為 `true` 時生效
|
||||
|
||||
有關自定義提示詞的詳細說明,包括支援的參數和範例,請參閱[提示詞自定義指南](prompt-customization.md)。
|
||||
|
||||
@ -341,6 +477,7 @@ or
|
||||
| **任務分析** | `analyze_task` | 深入分析任務需求 |
|
||||
| | `process_thought` | 針對複雜問題進行步驟化推理 |
|
||||
| **方案評估** | `reflect_task` | 反思與改進方案構想 |
|
||||
| **研究調查** | `research_mode` | 進入系統性技術研究模式 |
|
||||
| **專案管理** | `init_project_rules` | 初始化或更新專案標準與規則 |
|
||||
| **任務管理** | `split_tasks` | 將任務拆分為子任務 |
|
||||
| | `list_tasks` | 顯示所有任務及狀態 |
|
||||
@ -349,7 +486,6 @@ or
|
||||
| | `delete_task` | 刪除未完成的任務 |
|
||||
| **任務執行** | `execute_task` | 執行特定任務 |
|
||||
| | `verify_task` | 檢驗任務完成情況 |
|
||||
| | `complete_task` | 標記任務為已完成 |
|
||||
|
||||
## 📄 <a id="許可協議"></a>許可協議
|
||||
|
||||
|
@ -1,573 +0,0 @@
|
||||
# 蝦米任務管理器系統架構
|
||||
|
||||
[English](../en/architecture.md) | [中文](../zh/architecture.md)
|
||||
|
||||
本文檔描述蝦米任務管理器的系統架構設計,包括各組件的功能、交互方式和數據流。
|
||||
|
||||
## 1. 系統整體架構
|
||||
|
||||
蝦米任務管理器採用模塊化設計,基於 MCP (Model Context Protocol) 協議實現與 LLM 的互動。系統由以下核心組件構成:
|
||||
|
||||
```
|
||||
+------------------+
|
||||
| |
|
||||
| MCP 客戶端 |
|
||||
| (如 Cursor IDE) |
|
||||
| |
|
||||
+---------+--------+
|
||||
|
|
||||
| MCP 協議
|
||||
|
|
||||
+---------v--------+
|
||||
| |
|
||||
| 工具註冊層 | <-- 新增 delete_task 工具
|
||||
| (index.ts) | 新增 clear_all_tasks 工具
|
||||
| | 新增 update_task 工具
|
||||
| | 新增 update_task_files 工具
|
||||
+---------+--------+
|
||||
|
|
||||
|
|
||||
+------------------+------------------+
|
||||
| | |
|
||||
+---------v--------+ +-------v---------+
|
||||
| | | |
|
||||
| 工具實現層 | | 模型邏輯層 |
|
||||
| (taskTools.ts) | | (taskModel.ts) |
|
||||
| | | |
|
||||
+------------------+ +-------+---------+
|
||||
|
|
||||
|
|
||||
+---------v--------+
|
||||
| |
|
||||
| 數據存儲層 |
|
||||
| (JSON 文件) |
|
||||
| |
|
||||
+------------------+
|
||||
```
|
||||
|
||||
## 2. 主要組件說明
|
||||
|
||||
### 2.1 工具註冊層 (index.ts)
|
||||
|
||||
工具註冊層負責將各功能工具註冊到 MCP 系統中,使其能夠被 LLM 訪問和使用。
|
||||
|
||||
**主要功能**:
|
||||
|
||||
- 註冊 `plan_task` 工具函數,用於任務規劃
|
||||
- 註冊 `analyze_task` 工具函數,用於任務分析
|
||||
- 註冊 `reflect_task` 工具函數,用於批判性審查分析結果
|
||||
- 註冊 `split_tasks` 工具函數,用於將複雜任務分解為子任務
|
||||
- 註冊 `list_tasks` 工具函數,用於生成任務清單
|
||||
- 註冊 `execute_task` 工具函數,用於執行特定任務
|
||||
- 註冊 `verify_task` 工具函數,用於驗證任務完成度
|
||||
- 註冊 `complete_task` 工具函數,用於標記任務為完成狀態
|
||||
- 註冊 `delete_task` 工具函數,用於刪除未完成的任務
|
||||
- 註冊 `clear_all_tasks` 工具函數,用於清除所有未完成的任務
|
||||
- 註冊 `update_task` 工具函數,用於更新任務內容
|
||||
- 註冊 `update_task_files` 工具函數,用於更新任務相關文件列表
|
||||
|
||||
### 2.2 工具實現層 (tools/\*.ts)
|
||||
|
||||
工具實現層包含具體工具函數的實現,處理參數解析、驗證和結果格式化。
|
||||
|
||||
**核心文件**:
|
||||
|
||||
- `taskTools.ts`: 任務管理相關工具
|
||||
- `fileLoader.ts`: 任務相關文件的摘要生成工具
|
||||
|
||||
**主要功能**:
|
||||
|
||||
- 實現 `planTask` 工具函數,初始化並詳細規劃任務流程
|
||||
- 實現 `analyzeTask` 工具函數,深入分析任務需求
|
||||
- 實現 `reflectTask` 工具函數,批判性審查分析結果
|
||||
- 實現 `splitTasks` 工具函數,將複雜任務分解為獨立且可追蹤的子任務
|
||||
- 實現 `listTasks` 工具函數,生成結構化任務清單
|
||||
- 實現 `executeTask` 工具函數,按照預定義計劃執行特定任務
|
||||
- 實現 `verifyTask` 工具函數,全面驗證任務完成度
|
||||
- 實現 `completeTask` 工具函數,正式標記任務為完成狀態
|
||||
- 實現 `deleteTask` 工具函數,刪除未完成的任務
|
||||
- 實現 `clearAllTasks` 工具函數,刪除所有未完成的任務
|
||||
- 實現 `updateTask` 工具函數,更新任務內容
|
||||
- 實現 `updateTaskRelatedFiles` 工具函數,更新任務相關文件列表
|
||||
|
||||
### 2.3 模型邏輯層 (models/\*.ts)
|
||||
|
||||
模型邏輯層包含核心業務邏輯和數據處理函數,負責實現各種功能的邏輯處理。
|
||||
|
||||
**核心文件**:
|
||||
|
||||
- `taskModel.ts`: 任務數據模型和操作
|
||||
|
||||
**主要功能**:
|
||||
|
||||
- 在 `taskModel.ts` 中實現創建、讀取、更新和刪除任務的功能
|
||||
- 在 `taskModel.ts` 中實現 `deleteTask` 函數,刪除未完成的任務
|
||||
- 在 `taskModel.ts` 中實現 `clearAllTasks` 函數,刪除所有未完成的任務
|
||||
- 在 `taskModel.ts` 中實現 `updateTask` 函數,更新任務內容
|
||||
- 在 `taskModel.ts` 中實現 `updateTaskRelatedFiles` 函數,更新任務相關文件列表
|
||||
- 在 `taskModel.ts` 中實現 `assessTaskComplexity` 函數,評估任務複雜度
|
||||
- 在 `taskModel.ts` 中實現 `loadTaskById` 函數,載入特定任務
|
||||
- 在 `taskModel.ts` 中實現 `completeTask` 函數,標記任務為完成狀態
|
||||
|
||||
### 2.4 數據模型定義 (types/index.ts)
|
||||
|
||||
定義系統中使用的所有數據類型和接口。
|
||||
|
||||
**主要類型**:
|
||||
|
||||
- `TaskStatus` 枚舉:定義任務狀態,包括待處理、進行中、已完成和被阻擋
|
||||
- `TaskDependency` 接口:定義任務依賴關係
|
||||
- `RelatedFileType` 枚舉:定義文件關聯類型,如待修改、參考資料、待建立、依賴文件和其他
|
||||
- `RelatedFile` 接口:定義任務相關文件結構
|
||||
- `Task` 接口:定義任務的完整數據結構
|
||||
- `TaskComplexityLevel` 枚舉:定義任務複雜度級別,如低複雜度、中等複雜度、高複雜度和極高複雜度
|
||||
- `TaskComplexityThresholds` 常量:定義複雜度評估閾值
|
||||
- `TaskComplexityAssessment` 接口:記錄複雜度評估結果
|
||||
|
||||
### 2.5 工具函數 (utils/\*.ts)
|
||||
|
||||
提供各種輔助功能的工具函數。
|
||||
|
||||
**核心文件**:
|
||||
|
||||
- `summaryExtractor.ts`: 實現摘要提取和生成功能
|
||||
- `fileLoader.ts`: 實現任務相關文件的摘要生成功能
|
||||
|
||||
**主要功能**:
|
||||
|
||||
- 實現 `extractSummary` 函數,從文本中提取簡短摘要
|
||||
- 實現 `generateTaskSummary` 函數,基於任務名稱和描述生成任務完成摘要
|
||||
- 實現 `extractTitle` 函數,從內容中提取適合作為標題的文本
|
||||
- 實現 `loadTaskRelatedFiles` 函數,生成任務相關文件的內容摘要
|
||||
- 實現 `generateFileInfo` 函數,生成文件基本資訊摘要
|
||||
|
||||
### 2.6 數據存儲層
|
||||
|
||||
使用 JSON 文件作為數據存儲,保存任務信息。
|
||||
|
||||
**核心文件**:
|
||||
|
||||
- `data/tasks.json`: 存儲所有任務數據
|
||||
- `data/backups/`: 存儲任務數據備份
|
||||
|
||||
## 3. 數據流
|
||||
|
||||
### 3.1 任務刪除流程
|
||||
|
||||
```
|
||||
LLM 調用 delete_task
|
||||
|
|
||||
v
|
||||
識別任務是否存在
|
||||
|
|
||||
v
|
||||
檢查任務狀態(拒絕刪除已完成任務)
|
||||
|
|
||||
v
|
||||
檢查依賴關係(拒絕刪除有依賴的任務)
|
||||
|
|
||||
v
|
||||
執行刪除操作
|
||||
|
|
||||
v
|
||||
返回結果給 LLM
|
||||
```
|
||||
|
||||
### 3.2 任務複雜度評估流程
|
||||
|
||||
```
|
||||
LLM 調用 execute_task
|
||||
|
|
||||
v
|
||||
載入任務信息
|
||||
|
|
||||
v
|
||||
評估任務複雜度
|
||||
|
|
||||
+------------> 計算描述長度
|
||||
| |
|
||||
+------------> 計算依賴數量
|
||||
| |
|
||||
+------------> 計算注記長度
|
||||
| |
|
||||
+------------> 檢查是否有注記
|
||||
| |
|
||||
v v
|
||||
確定複雜度級別 <----- 應用評估閾值
|
||||
|
|
||||
v
|
||||
生成處理建議
|
||||
|
|
||||
v
|
||||
更新任務提示,包含複雜度信息
|
||||
|
|
||||
v
|
||||
返回增強後的任務執行提示給 LLM
|
||||
```
|
||||
|
||||
### 3.3 任務完成流程
|
||||
|
||||
```
|
||||
LLM 調用 complete_task
|
||||
|
|
||||
v
|
||||
載入任務信息
|
||||
|
|
||||
v
|
||||
檢查是否提供摘要
|
||||
|
|
||||
+---- 有 ----> 使用提供的摘要
|
||||
|
|
||||
+---- 無 ----> 自動生成摘要
|
||||
|
|
||||
+---> 基於任務名稱和描述
|
||||
|
|
||||
+---> 提取關鍵信息
|
||||
|
|
||||
+---> 格式化摘要文本
|
||||
|
|
||||
v
|
||||
更新任務狀態為已完成
|
||||
|
|
||||
v
|
||||
保存摘要到任務記錄
|
||||
|
|
||||
v
|
||||
返回結果給 LLM
|
||||
```
|
||||
|
||||
### 3.4 清除所有任務流程
|
||||
|
||||
```
|
||||
LLM 調用 clear_all_tasks
|
||||
|
|
||||
v
|
||||
檢查確認參數(必須為 true)
|
||||
|
|
||||
v
|
||||
創建數據備份
|
||||
|
|
||||
v
|
||||
載入當前任務列表
|
||||
|
|
||||
|
|
||||
v
|
||||
篩選出未完成的任務
|
||||
|
|
||||
v
|
||||
執行批量刪除
|
||||
|
|
||||
v
|
||||
更新數據文件
|
||||
|
|
||||
v
|
||||
返回清除結果給 LLM
|
||||
```
|
||||
|
||||
### 3.5 更新任務內容流程
|
||||
|
||||
```
|
||||
LLM 調用 update_task
|
||||
|
|
||||
v
|
||||
載入任務信息
|
||||
|
|
||||
v
|
||||
檢查任務是否存在
|
||||
|
|
||||
v
|
||||
檢查任務狀態(阻止更新已完成任務)
|
||||
|
|
||||
v
|
||||
驗證更新參數(至少提供一個更新字段)
|
||||
|
|
||||
v
|
||||
執行更新操作
|
||||
|
|
||||
v
|
||||
返回更新結果給 LLM
|
||||
```
|
||||
|
||||
### 3.6 更新任務相關文件流程
|
||||
|
||||
```
|
||||
LLM 調用 update_task_files
|
||||
|
|
||||
v
|
||||
載入任務信息
|
||||
|
|
||||
v
|
||||
檢查任務是否存在
|
||||
|
|
||||
v
|
||||
檢查任務狀態(阻止更新已完成任務)
|
||||
|
|
||||
v
|
||||
驗證文件列表格式
|
||||
|
|
||||
v
|
||||
處理每個相關文件
|
||||
| |
|
||||
| +---> 驗證文件路徑
|
||||
| |
|
||||
| +---> 檢查行號範圍(如有提供)
|
||||
| |
|
||||
| +---> 驗證文件類型
|
||||
|
|
||||
v
|
||||
更新任務的相關文件列表
|
||||
|
|
||||
v
|
||||
返回更新結果給 LLM
|
||||
```
|
||||
|
||||
### 3.7 文件處理流程
|
||||
|
||||
```
|
||||
處理任務相關文件
|
||||
|
|
||||
v
|
||||
根據文件類型進行優先級排序
|
||||
| |
|
||||
| +---> 待修改 > 參考資料 > 依賴文件 > 待建立 > 其他
|
||||
|
|
||||
v
|
||||
生成文件摘要
|
||||
| |
|
||||
| +---> 對於指定行號範圍的文件,生成該範圍的摘要
|
||||
| |
|
||||
| +---> 對於一般文件,生成整體內容摘要
|
||||
|
|
||||
v
|
||||
返回文件摘要結果
|
||||
```
|
||||
|
||||
## 4. 系統交互圖
|
||||
|
||||
### 4.1 LLM 與任務管理器交互
|
||||
|
||||
```
|
||||
+-------+ 1.調用工具 +----------------+
|
||||
| |------------------>| |
|
||||
| LLM | | 蝦米任務管理器 |
|
||||
| |<------------------| |
|
||||
+-------+ 4.返回結果 +-------+--------+
|
||||
|
|
||||
+-------v--------+
|
||||
| |
|
||||
| JSON 數據存儲 |
|
||||
| |
|
||||
+----------------+
|
||||
```
|
||||
|
||||
### 4.2 工具層與模型層交互
|
||||
|
||||
```
|
||||
+-------------+ 調用 +-------------+ 讀寫 +------------+
|
||||
| |------------->| |------------>| |
|
||||
| 工具實現層 | | 模型邏輯層 | | 數據存儲層 |
|
||||
| |<-------------| |<------------| |
|
||||
+-------------+ 返回結果 +-------------+ 返回數據 +------------+
|
||||
```
|
||||
|
||||
## 5. 核心功能架構圖
|
||||
|
||||
### 5.1 任務規劃功能
|
||||
|
||||
```
|
||||
+----------------+ +----------------+ +------------------+
|
||||
| | | | | |
|
||||
| planTaskSchema |---->| planTask |---->| 任務規劃響應生成 |
|
||||
| | | (taskTools.ts) | | |
|
||||
+----------------+ +-------+--------+ +------------------+
|
||||
```
|
||||
|
||||
### 5.2 任務分析功能
|
||||
|
||||
```
|
||||
+----------------+ +----------------+ +------------------+
|
||||
| | | | | |
|
||||
| analyzeTaskSchema|---->| analyzeTask |---->| 技術分析指引生成 |
|
||||
| | | (taskTools.ts) | | |
|
||||
+----------------+ +-------+--------+ +------------------+
|
||||
```
|
||||
|
||||
### 5.3 任務反思功能
|
||||
|
||||
```
|
||||
+----------------+ +----------------+ +------------------+
|
||||
| | | | | |
|
||||
| reflectTaskSchema|---->| reflectTask |---->| 反思提示與建議生成|
|
||||
| | | (taskTools.ts) | | |
|
||||
+----------------+ +-------+--------+ +------------------+
|
||||
```
|
||||
|
||||
### 5.4 任務拆分功能
|
||||
|
||||
```
|
||||
+----------------+ +----------------+ +------------------+
|
||||
| | | | | |
|
||||
| splitTasksSchema|---->| splitTasks |---->| createTasks |
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+----------------+ +-------+--------+ +------------------+
|
||||
```
|
||||
|
||||
### 5.5 任務執行功能
|
||||
|
||||
```
|
||||
+----------------+ +----------------+ +------------------+
|
||||
| | | | | |
|
||||
| executeTaskSchema|---->| executeTask |---->| assessTaskComplexity|
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+----------------+ +-------+--------+ +------------------+
|
||||
|
|
||||
v
|
||||
+------+---------------------+------+
|
||||
| 任務執行指南和上下文生成 |
|
||||
+------+---------------------+------+
|
||||
```
|
||||
|
||||
### 5.6 任務驗證功能
|
||||
|
||||
```
|
||||
+----------------+ +----------------+ +------------------+
|
||||
| | | | | |
|
||||
| verifyTaskSchema|---->| verifyTask |---->| 任務驗證評估 |
|
||||
| | | (taskTools.ts) | | |
|
||||
+----------------+ +-------+--------+ +------------------+
|
||||
```
|
||||
|
||||
### 5.7 完成任務功能
|
||||
|
||||
```
|
||||
+----------------+ +----------------+ +------------------+
|
||||
| | | | | |
|
||||
| completeTaskSchema|---->| completeTask |---->| updateTaskSummary|
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+----------------+ +-------+--------+ +------------------+
|
||||
|
|
||||
v
|
||||
+------+--------+
|
||||
| summaryExtractor|
|
||||
| (utils) |
|
||||
+---------------+
|
||||
```
|
||||
|
||||
### 5.8 任務刪除功能
|
||||
|
||||
```
|
||||
+----------------+ +----------------+ +------------------+
|
||||
| | | | | |
|
||||
| deleteTaskSchema|---->| deleteTask |---->| modelDeleteTask |
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+----------------+ +-------+--------+ +------------------+
|
||||
|
|
||||
v
|
||||
+------+---------------------+------+
|
||||
| 檢查任務狀態和依賴關係 |
|
||||
+------+---------------------+------+
|
||||
```
|
||||
|
||||
### 5.9 清除所有任務功能
|
||||
|
||||
```
|
||||
+------------------+ +----------------+ +------------------+
|
||||
| | | | | |
|
||||
| clearAllTasksSchema|---->| clearAllTasks |---->| modelClearAllTasks|
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+------------------+ +-------+--------+ +------------------+
|
||||
|
|
||||
v
|
||||
+------+---------------------+------+
|
||||
| 確認參數檢查和數據備份 |
|
||||
+------+---------------------+------+
|
||||
|
|
||||
v
|
||||
+------+---------------------+------+
|
||||
| 篩選和批量刪除未完成任務 |
|
||||
+------+---------------------+------+
|
||||
```
|
||||
|
||||
### 5.10 更新任務功能
|
||||
|
||||
```
|
||||
+------------------+ +----------------+ +------------------+
|
||||
| | | | | |
|
||||
| updateTaskSchema |---->| updateTask |---->| updateTask |
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+------------------+ +-------+--------+ +------------------+
|
||||
|
|
||||
v
|
||||
+------+---------------------+------+
|
||||
| 檢查任務狀態和更新參數有效性 |
|
||||
+------+---------------------+------+
|
||||
```
|
||||
|
||||
### 5.11 更新任務相關文件功能
|
||||
|
||||
```
|
||||
+----------------------+ +---------------------+ +----------------------+
|
||||
| | | | | |
|
||||
| updateTaskFilesSchema |---->| updateTaskRelatedFiles |---->| updateTaskRelatedFiles |
|
||||
| | | (taskTools.ts) | | (taskModel.ts) |
|
||||
+----------------------+ +-----------+---------+ +-----------+----------+
|
||||
| |
|
||||
v v
|
||||
+-------+-------------------------+------+
|
||||
| 驗證文件格式和路徑有效性 |
|
||||
+-------+-------------------------+------+
|
||||
|
|
||||
v
|
||||
+-------+-------------------------+------+
|
||||
| 更新任務相關文件列表 |
|
||||
+-------+-------------------------+------+
|
||||
```
|
||||
|
||||
## 6. 擴展性考慮
|
||||
|
||||
### 6.1 新功能擴展方式
|
||||
|
||||
蝦米任務管理器的模塊化設計使其易於擴展。要添加新功能,通常需要:
|
||||
|
||||
1. 在 `types/index.ts` 中定義相關數據類型
|
||||
2. 在相應的模型文件中實現核心邏輯
|
||||
3. 在工具層創建對應的工具函數
|
||||
4. 在 `index.ts` 中註冊新工具
|
||||
|
||||
### 6.2 目前的擴展點
|
||||
|
||||
系統當前提供以下擴展點:
|
||||
|
||||
- **任務處理流程擴展**:可通過修改 `executeTask`、`verifyTask` 等函數擴展任務處理流程
|
||||
- **複雜度評估擴展**:可在 `assessTaskComplexity` 中添加更多評估指標
|
||||
- **摘要生成擴展**:可增強 `summaryExtractor.ts` 中的算法
|
||||
- **文件處理擴展**:可在 `fileLoader.ts` 中支持更多文件類型的摘要格式化
|
||||
- **過濾條件擴展**:可在任務查詢中添加更多過濾條件選項
|
||||
|
||||
## 7. 系統限制與未來改進
|
||||
|
||||
### 7.1 當前限制
|
||||
|
||||
- 使用文件存儲,不適合多用戶並發場景
|
||||
- 缺乏用戶認證和權限控制
|
||||
- 摘要生成使用簡單規則,可進一步改進
|
||||
- 文件處理不讀取實際文件內容,僅生成摘要信息
|
||||
|
||||
### 7.2 未來可能的改進
|
||||
|
||||
- 遷移到數據庫存儲,提高並發處理能力
|
||||
- 添加用戶管理和訪問控制
|
||||
- 使用更先進的算法優化摘要生成
|
||||
- 添加任務優先級和時間規劃功能
|
||||
- 實現任務執行進度追蹤
|
||||
- 增強文件關聯系統,支持更複雜的關係類型
|
||||
- 實現自動識別相關文件的能力
|
||||
- 支持實際讀取文件內容,提供更詳細的上下文
|
||||
|
||||
## 8. 結論
|
||||
|
||||
蝦米任務管理器採用模塊化、分層設計,使系統具有良好的可維護性和擴展性。通過 12 個核心工具函數和完善的數據模型,系統能夠有效地管理複雜項目的任務流程,特別在需要長期上下文記憶的場景中表現出色。
|
||||
|
||||
系統的設計重點在於提供清晰的任務管理流程,同時增強 LLM 在執行任務時的上下文記憶能力,通過精確的文件關聯和智能上下文載入,有效解決了 LLM 在處理長期複雜任務時的記憶限制問題。
|
||||
|
||||
隨著系統的進一步發展,未來將著重改進數據存儲方式、優化摘要生成算法、增強文件處理能力和添加更多任務管理功能,使系統能夠應對更多複雜的任務管理場景。
|
@ -1,357 +0,0 @@
|
||||
[English](../en/functionality-checklist.md) | [中文](../zh/functionality-checklist.md)
|
||||
|
||||
# 蝦米任務管理器 - 功能實現清單
|
||||
|
||||
本文檔列出蝦米任務管理器系統中所有實際實現的工具函數、參數結構和功能。此清單作為文檔審查的基準參考。
|
||||
|
||||
## 類型定義與枚舉
|
||||
|
||||
### 任務狀態枚舉 (TaskStatus)
|
||||
|
||||
- `PENDING = "待處理"` - 已創建但尚未開始執行的任務
|
||||
- `IN_PROGRESS = "進行中"` - 當前正在執行的任務
|
||||
- `COMPLETED = "已完成"` - 已成功完成並通過驗證的任務
|
||||
- `BLOCKED = "被阻擋"` - 由於依賴關係而暫時無法執行的任務
|
||||
|
||||
### 任務依賴關係 (TaskDependency)
|
||||
|
||||
- `taskId: string` - 前置任務的唯一標識符,當前任務執行前必須完成此依賴任務
|
||||
|
||||
### 相關文件類型枚舉 (RelatedFileType)
|
||||
|
||||
- `TO_MODIFY = "待修改"` - 需要在任務中修改的文件
|
||||
- `REFERENCE = "參考資料"` - 任務的參考資料或相關文檔
|
||||
- `CREATE = "待建立"` - 需要在任務中建立的文件
|
||||
- `DEPENDENCY = "依賴文件"` - 任務依賴的組件或庫文件
|
||||
- `OTHER = "其他"` - 其他類型的相關文件
|
||||
|
||||
### 相關文件 (RelatedFile)
|
||||
|
||||
- `path: string` - 文件路徑,可以是相對於項目根目錄的路徑或絕對路徑
|
||||
- `type: RelatedFileType` - 文件與任務的關係類型
|
||||
- `description?: string` - 文件的補充描述,說明其與任務的具體關係或用途
|
||||
- `lineStart?: number` - 相關代碼區塊的起始行(選填)
|
||||
- `lineEnd?: number` - 相關代碼區塊的結束行(選填)
|
||||
|
||||
### 任務介面 (Task)
|
||||
|
||||
- `id: string` - 任務的唯一標識符
|
||||
- `name: string` - 簡潔明確的任務名稱
|
||||
- `description: string` - 詳細的任務描述,包含實施要點和驗收標準
|
||||
- `notes?: string` - 補充說明、特殊處理要求或實施建議(選填)
|
||||
- `status: TaskStatus` - 任務當前的執行狀態
|
||||
- `dependencies: TaskDependency[]` - 任務的前置依賴關係列表
|
||||
- `createdAt: Date` - 任務創建的時間戳
|
||||
- `updatedAt: Date` - 任務最後更新的時間戳
|
||||
- `completedAt?: Date` - 任務完成的時間戳(僅適用於已完成的任務)
|
||||
- `summary?: string` - 任務完成摘要,簡潔描述實施結果和重要決策(僅適用於已完成的任務)
|
||||
- `relatedFiles?: RelatedFile[]` - 與任務相關的文件列表(選填)
|
||||
|
||||
### 任務複雜度級別枚舉 (TaskComplexityLevel)
|
||||
|
||||
- `LOW = "低複雜度"` - 簡單且直接的任務,通常不需要特殊處理
|
||||
- `MEDIUM = "中等複雜度"` - 具有一定複雜性但仍可管理的任務
|
||||
- `HIGH = "高複雜度"` - 複雜且耗時的任務,需要特別關注
|
||||
- `VERY_HIGH = "極高複雜度"` - 極其複雜的任務,建議拆分處理
|
||||
|
||||
### 任務複雜度評估結果 (TaskComplexityAssessment)
|
||||
|
||||
- `level: TaskComplexityLevel` - 整體複雜度級別
|
||||
- `metrics: object` - 各項評估指標的詳細數據
|
||||
- `descriptionLength: number` - 描述長度
|
||||
- `dependenciesCount: number` - 依賴數量
|
||||
- `notesLength: number` - 注記長度
|
||||
- `hasNotes: boolean` - 是否有注記
|
||||
- `recommendations: string[]` - 處理建議列表
|
||||
|
||||
## 工具函數與參數
|
||||
|
||||
### 1. plan_task
|
||||
|
||||
**描述**:初始化並詳細規劃任務流程,建立明確的目標與成功標準
|
||||
|
||||
**參數**:
|
||||
|
||||
- `description: string` (必填) - 完整詳細的任務問題描述,應包含任務目標、背景及預期成果
|
||||
- 必須至少 10 個字符
|
||||
- `requirements?: string` (選填) - 任務的特定技術要求、業務約束條件或品質標準
|
||||
|
||||
**返回值**:
|
||||
|
||||
- 返回一個包含規劃提示的響應,用於引導用戶開始任務分析
|
||||
|
||||
### 2. analyze_task
|
||||
|
||||
**描述**:深入分析任務需求並系統性檢查代碼庫,評估技術可行性與潛在風險
|
||||
|
||||
**參數**:
|
||||
|
||||
- `summary: string` (必填) - 結構化的任務摘要,包含任務目標、範圍與關鍵技術挑戰
|
||||
- 必須至少 20 個字符
|
||||
- `initialConcept: string` (必填) - 初步解答構想,包含技術方案、架構設計和實施策略
|
||||
- 必須至少 50 個字符
|
||||
- `previousAnalysis?: string` (選填) - 前次迭代的分析結果,用於持續改進方案
|
||||
|
||||
**返回值**:
|
||||
|
||||
- 返回一個包含技術分析指引的響應,用於指導用戶進行深入分析
|
||||
|
||||
### 3. reflect_task
|
||||
|
||||
**描述**:批判性審查分析結果,評估方案完整性並識別優化機會,確保解決方案符合最佳實踐
|
||||
|
||||
**參數**:
|
||||
|
||||
- `summary: string` (必填) - 結構化的任務摘要,保持與分析階段一致以確保連續性
|
||||
- 必須至少 20 個字符
|
||||
- `analysis: string` (必填) - 完整詳盡的技術分析結果,包括所有技術細節、依賴組件和實施方案
|
||||
- 必須至少 100 個字符
|
||||
|
||||
**返回值**:
|
||||
|
||||
- 返回一個包含反思提示與實施建議的響應
|
||||
|
||||
### 4. split_tasks
|
||||
|
||||
**描述**:將複雜任務分解為獨立且可追蹤的子任務,建立明確的依賴關係和優先順序
|
||||
|
||||
**參數**:
|
||||
|
||||
- `updateMode: "append" | "overwrite" | "selective" | "clearAllTasks"` (必填) - 任務更新模式選擇:
|
||||
- `append`:保留所有現有任務並添加新任務
|
||||
- `overwrite`:清除所有未完成任務並完全替換
|
||||
- `selective`:根據任務名稱匹配更新現有任務,保留不在列表中的任務
|
||||
- `clearAllTasks`:清除所有任務並創建備份
|
||||
- `tasks: Array<object>` (必填) - 結構化的任務清單,每個任務應保持原子性且有明確的完成標準
|
||||
- `name: string` (必填) - 簡潔明確的任務名稱,應能清晰表達任務目的
|
||||
- 不超過 100 個字符
|
||||
- `description: string` (必填) - 詳細的任務描述,包含實施要點、技術細節和驗收標準
|
||||
- 必須至少 10 個字符
|
||||
- `notes?: string` (選填) - 補充說明、特殊處理要求或實施建議
|
||||
- `dependencies?: string[]` (選填) - 此任務依賴的前置任務 ID 或任務名稱列表
|
||||
- `relatedFiles?: RelatedFile[]` (選填) - 與任務相關的文件列表
|
||||
|
||||
**返回值**:
|
||||
|
||||
- 返回一個包含任務拆分結果的響應,包括成功創建的任務數量和任務 ID 列表
|
||||
|
||||
### 5. list_tasks
|
||||
|
||||
**描述**:生成結構化任務清單,包含完整狀態追蹤、優先級和依賴關係
|
||||
|
||||
**參數**:無
|
||||
|
||||
**返回值**:
|
||||
|
||||
- 返回一個包含任務清單的響應,按狀態分組顯示所有任務
|
||||
|
||||
### 6. execute_task
|
||||
|
||||
**描述**:按照預定義計劃執行特定任務,確保每個步驟的輸出符合質量標準
|
||||
|
||||
**參數**:
|
||||
|
||||
- `taskId: string` (必填) - 待執行任務的唯一標識符,必須是系統中存在的有效任務 ID
|
||||
|
||||
**返回值**:
|
||||
|
||||
- 返回一個包含任務執行指南的響應,包括任務詳情、複雜度評估和執行步驟建議
|
||||
|
||||
### 7. verify_task
|
||||
|
||||
**描述**:全面驗證任務完成度,確保所有需求與技術標準都已滿足,並無遺漏細節
|
||||
|
||||
**參數**:
|
||||
|
||||
- `taskId: string` (必填) - 待驗證任務的唯一標識符,必須是系統中存在的有效任務 ID
|
||||
|
||||
**返回值**:
|
||||
|
||||
- 返回一個包含任務驗證結果的響應,包括完成標準檢查和具體驗證項
|
||||
|
||||
### 8. complete_task
|
||||
|
||||
**描述**:正式標記任務為完成狀態,生成詳細的完成報告,並更新關聯任務的依賴狀態
|
||||
|
||||
**參數**:
|
||||
|
||||
- `taskId: string` (必填) - 待完成任務的唯一標識符,必須是系統中存在的有效任務 ID
|
||||
- `summary?: string` (選填) - 任務完成摘要,簡潔描述實施結果和重要決策
|
||||
|
||||
**返回值**:
|
||||
|
||||
- 返回一個包含任務完成確認的響應,包括完成時間和更新的依賴任務狀態
|
||||
|
||||
### 9. delete_task
|
||||
|
||||
**描述**:刪除未完成的任務,但不允許刪除已完成的任務,確保系統記錄的完整性
|
||||
|
||||
**參數**:
|
||||
|
||||
- `taskId: string` (必填) - 待刪除任務的唯一標識符,必須是系統中存在且未完成的任務 ID
|
||||
|
||||
**返回值**:
|
||||
|
||||
- 返回一個包含任務刪除結果的響應,包括成功或失敗的訊息
|
||||
|
||||
### 10. clear_all_tasks
|
||||
|
||||
**描述**:刪除系統中所有未完成的任務,該指令必須由用戶明確確認才能執行。同時將任務備份到 memory 子目錄,保存任務歷史記錄以供未來參考。
|
||||
|
||||
**參數**:
|
||||
|
||||
- `confirm: boolean` (必填) - 確認刪除所有未完成的任務(此操作不可逆)
|
||||
|
||||
**返回值**:
|
||||
|
||||
- 返回一個包含清除操作結果的響應,包括成功或失敗的訊息、備份文件名和備份位置
|
||||
|
||||
**重要細節**:
|
||||
|
||||
- 在刪除任務前,會自動將當前任務列表備份到 data/memory 子目錄
|
||||
- 備份文件使用時間戳命名,格式為 tasks_memory_YYYY-MM-DDThh-mm-ss.json
|
||||
- memory 子目錄作為長期記憶庫,用於存儲任務歷史記錄,供未來任務規劃參考
|
||||
|
||||
### 11. query_task
|
||||
|
||||
**描述**:根據關鍵字或 ID 搜尋任務,顯示省略版的任務資訊
|
||||
|
||||
**參數**:
|
||||
|
||||
- `query: string` (必填) - 搜尋查詢文字,可以是任務 ID 或多個關鍵字(空格分隔)
|
||||
- 必須至少 1 個字符
|
||||
- `isId: boolean` (選填) - 指定是否為 ID 查詢模式,默認為否(關鍵字模式)
|
||||
- `page: number` (選填) - 分頁頁碼,默認為第 1 頁
|
||||
- `pageSize: number` (選填) - 每頁顯示的任務數量,默認為 5 筆,最大 20 筆
|
||||
- 必須為正整數,範圍 1-20
|
||||
|
||||
**返回值**:
|
||||
|
||||
- 返回一個包含搜尋結果的響應,包括符合條件的任務列表、分頁資訊和總結果數量
|
||||
|
||||
**重要細節**:
|
||||
|
||||
- 當 `isId` 為 true 時,系統會精確查詢指定 ID 的任務
|
||||
- 當 `isId` 為 false 時,系統會在任務名稱、描述和摘要中搜尋指定關鍵字
|
||||
- 關鍵字模式支持多個關鍵字(以空格分隔),將返回符合任一關鍵字的任務
|
||||
- 結果會按任務狀態和更新時間排序,便於快速找到最相關的任務
|
||||
|
||||
### 12. update_task
|
||||
|
||||
**描述**:更新任務內容,包括名稱、描述和注記,但不允許修改已完成的任務
|
||||
|
||||
**參數**:
|
||||
|
||||
- `taskId: string` (必填) - 待更新任務的唯一標識符,必須是系統中存在且未完成的任務 ID
|
||||
- `name?: string` (選填) - 任務的新名稱
|
||||
- `description?: string` (選填) - 任務的新描述內容
|
||||
- `notes?: string` (選填) - 任務的新補充說明
|
||||
|
||||
**返回值**:
|
||||
|
||||
- 返回一個包含任務更新結果的響應,包括成功或失敗的訊息
|
||||
|
||||
### 13. get_task_detail
|
||||
|
||||
**描述**:根據任務 ID 獲取任務的完整詳細信息,包括未截斷的實現指南和驗證標準等
|
||||
|
||||
**參數**:
|
||||
|
||||
- `taskId: string` (必填) - 欲檢視詳情的任務 ID
|
||||
- 必須至少 1 個字符
|
||||
|
||||
**返回值**:
|
||||
|
||||
- 返回一個包含任務完整詳情的響應,包括所有任務屬性,特別是完整的實現指南和驗證標準
|
||||
|
||||
**重要細節**:
|
||||
|
||||
- 與 `list_tasks` 不同,此功能返回單個任務的完整詳情,沒有內容截斷
|
||||
- 適用於深入了解特定任務的要求和技術細節
|
||||
- 提供完整的相關文件列表和任務分析結果
|
||||
- 可用於檢視執行過程中可能被省略的長文本內容
|
||||
|
||||
### 14. update_task_files
|
||||
|
||||
**描述**:更新任務相關文件列表,用於記錄與任務相關的代碼文件、參考資料等
|
||||
|
||||
**參數**:
|
||||
|
||||
- `taskId: string` (必填) - 待更新任務的唯一標識符,必須是系統中存在且未完成的任務 ID
|
||||
- `relatedFiles: Array<RelatedFile>` (必填) - 與任務相關的文件列表
|
||||
- `path: string` (必填) - 文件路徑,可以是相對於項目根目錄的路徑或絕對路徑
|
||||
- `type: RelatedFileType` (必填) - 文件與任務的關係類型
|
||||
- `description?: string` (選填) - 文件的補充描述
|
||||
- `lineStart?: number` (選填) - 相關代碼區塊的起始行
|
||||
- `lineEnd?: number` (選填) - 相關代碼區塊的結束行
|
||||
|
||||
**返回值**:
|
||||
|
||||
- 返回一個包含文件更新結果的響應,包括成功或失敗的訊息
|
||||
|
||||
## 工具函數重要細節
|
||||
|
||||
### 依賴關係 (dependencies) 處理
|
||||
|
||||
- 在 `splitTasks` 和其他函數中,`dependencies` 參數允許接受任務名稱或任務 ID(UUID)
|
||||
- 系統會在任務創建或更新時將字串陣列轉換為 `TaskDependency` 物件陣列
|
||||
- 任務依賴關係形成有向無環圖(DAG),用於確定任務執行順序和阻塞狀態
|
||||
|
||||
### 任務複雜度評估
|
||||
|
||||
- 系統使用 `assessTaskComplexity` 函數評估任務的複雜度
|
||||
- 評估基於多個指標:描述長度、依賴數量、注記長度等
|
||||
- 根據 `TaskComplexityThresholds` 定義的閾值來判定複雜度級別
|
||||
- 複雜度評估結果用於生成適當的處理建議
|
||||
|
||||
### 文件處理功能
|
||||
|
||||
- `loadTaskRelatedFiles` 函數不實際讀取檔案內容,僅生成文件資訊摘要
|
||||
- 文件按類型優先級排序:待修改 > 參考資料 > 依賴文件 > 待建立 > 其他
|
||||
- 支持指定代碼區塊行號範圍,便於精確定位關鍵實現
|
||||
|
||||
## 實用工具函數
|
||||
|
||||
### 摘要提取 (summaryExtractor.ts)
|
||||
|
||||
- `extractSummary` - 從文本中提取簡短摘要,自動處理 Markdown 格式
|
||||
- `generateTaskSummary` - 基於任務名稱和描述生成任務完成摘要
|
||||
- `extractTitle` - 從內容中提取適合作為標題的文本
|
||||
|
||||
### 文件加載 (fileLoader.ts)
|
||||
|
||||
- `loadTaskRelatedFiles` - 生成任務相關文件的內容摘要
|
||||
- `generateFileInfo` - 生成文件基本資訊摘要
|
||||
|
||||
## 任務記憶功能
|
||||
|
||||
任務記憶功能是蝦米任務管理器的重要特性,它使系統具備長期記憶能力,能夠保存、查詢和利用過去的任務執行經驗。
|
||||
|
||||
### 核心實現
|
||||
|
||||
1. **自動備份機制**:
|
||||
|
||||
- 在 `clearAllTasks` 函數中實現雙重備份功能
|
||||
- 將任務備份同時保存在 data 目錄和 data/memory 子目錄
|
||||
- 使用時間戳命名備份文件,格式為 tasks_memory_YYYY-MM-DDThh-mm-ss.json
|
||||
|
||||
2. **智能提示指導**:
|
||||
- 在 `planTask` 函數的提示詞中添加任務記憶檢索指南
|
||||
- 指導 Agent 如何查找、分析和應用歷史任務記錄
|
||||
- 提供智能參考建議,促進知識重用
|
||||
|
||||
### 使用場景
|
||||
|
||||
- **任務規劃時**:參考類似任務的實施方案和最佳實踐
|
||||
- **問題解決時**:查閱過去遇到的類似問題及其解決方法
|
||||
- **代碼重用時**:識別過去實現的可重用組件或模式
|
||||
- **經驗學習時**:分析過去成功和失敗案例,持續優化工作方式
|
||||
|
||||
### 技術要點
|
||||
|
||||
- 使用相對路徑引用 memory 目錄,保持代碼的一致性和可維護性
|
||||
- 確保 memory 目錄存在,如不存在則自動創建
|
||||
- 保持原有的錯誤處理模式,確保系統穩定性
|
||||
- 備份過程透明無感,不影響用戶正常操作流程
|
||||
|
||||
此功能無需額外工具或配置,系統會自動在任務清除時保存歷史記錄,並在任務規劃時提供智能指導,使 Agent 能夠充分利用過去的經驗和知識。
|
@ -16,22 +16,64 @@
|
||||
|
||||
其中 `[FUNCTION_NAME]` 是工具函式的名稱,大寫形式。例如,對於任務規劃功能 `planTask`,相應的環境變數名稱為 `MCP_PROMPT_PLAN_TASK`。
|
||||
|
||||
## 多語言提示詞模板支持
|
||||
|
||||
蝦米任務管理器支持多種語言的提示詞模板,可通過 `TEMPLATES_USE` 環境變數設置:
|
||||
|
||||
- 當前支持的語言:`en`(英文)和 `zh`(繁體中文)
|
||||
- 默認為 `en`(英文)
|
||||
|
||||
### 切換語言
|
||||
|
||||
在 `mcp.json` 配置中設置:
|
||||
|
||||
```json
|
||||
"env": {
|
||||
"TEMPLATES_USE": "zh" // 使用繁體中文模板
|
||||
}
|
||||
```
|
||||
|
||||
或在 `.env` 文件中設置:
|
||||
|
||||
```
|
||||
TEMPLATES_USE=zh
|
||||
```
|
||||
|
||||
### 自定義模板
|
||||
|
||||
您可以創建自己的模板集:
|
||||
|
||||
1. 將現有模板集(如 `src/prompts/templates_en` 或 `src/prompts/templates_zh`)複製到 `DATA_DIR` 指定的目錄
|
||||
2. 重命名複製的目錄(例如:`my_templates`)
|
||||
3. 修改模板文件以符合您的需求
|
||||
4. 將 `TEMPLATES_USE` 環境變數設置為您的模板目錄名稱:
|
||||
|
||||
```json
|
||||
"env": {
|
||||
"DATA_DIR": "/path/to/project/data",
|
||||
"TEMPLATES_USE": "my_templates"
|
||||
}
|
||||
```
|
||||
|
||||
系統將優先使用您的自定義模板,如果找不到特定模板文件,會回退到內置的英文模板。
|
||||
|
||||
## 支援的工具函式
|
||||
|
||||
系統中的所有主要功能都支援透過環境變數自定義 prompt:
|
||||
|
||||
| 功能名稱 | 環境變數前綴 | 說明 |
|
||||
| --------------- | ---------------------------- | ------------ |
|
||||
| `planTask` | `MCP_PROMPT_PLAN_TASK` | 任務規劃 |
|
||||
| `analyzeTask` | `MCP_PROMPT_ANALYZE_TASK` | 任務分析 |
|
||||
| `reflectTask` | `MCP_PROMPT_REFLECT_TASK` | 方案評估 |
|
||||
| `splitTasks` | `MCP_PROMPT_SPLIT_TASKS` | 任務拆分 |
|
||||
| `executeTask` | `MCP_PROMPT_EXECUTE_TASK` | 任務執行 |
|
||||
| `verifyTask` | `MCP_PROMPT_VERIFY_TASK` | 任務驗證 |
|
||||
| `completeTask` | `MCP_PROMPT_COMPLETE_TASK` | 任務完成 |
|
||||
| `listTasks` | `MCP_PROMPT_LIST_TASKS` | 列出任務 |
|
||||
| `queryTask` | `MCP_PROMPT_QUERY_TASK` | 查詢任務 |
|
||||
| `getTaskDetail` | `MCP_PROMPT_GET_TASK_DETAIL` | 獲取任務詳情 |
|
||||
| 功能名稱 | 環境變數前綴 | 說明 |
|
||||
| ------------------ | ------------------------------- | -------------- |
|
||||
| `planTask` | `MCP_PROMPT_PLAN_TASK` | 任務規劃 |
|
||||
| `analyzeTask` | `MCP_PROMPT_ANALYZE_TASK` | 任務分析 |
|
||||
| `reflectTask` | `MCP_PROMPT_REFLECT_TASK` | 方案評估 |
|
||||
| `splitTasks` | `MCP_PROMPT_SPLIT_TASKS` | 任務拆分 |
|
||||
| `executeTask` | `MCP_PROMPT_EXECUTE_TASK` | 任務執行 |
|
||||
| `verifyTask` | `MCP_PROMPT_VERIFY_TASK` | 任務驗證 |
|
||||
| `listTasks` | `MCP_PROMPT_LIST_TASKS` | 列出任務 |
|
||||
| `queryTask` | `MCP_PROMPT_QUERY_TASK` | 查詢任務 |
|
||||
| `getTaskDetail` | `MCP_PROMPT_GET_TASK_DETAIL` | 獲取任務詳情 |
|
||||
| `processThought` | `MCP_PROMPT_PROCESS_THOUGHT` | 思維鏈處理 |
|
||||
| `initProjectRules` | `MCP_PROMPT_INIT_PROJECT_RULES` | 初始化專案規則 |
|
||||
|
||||
## 環境變數配置方法
|
||||
|
||||
@ -149,11 +191,6 @@ MCP_PROMPT_PLAN_TASK_APPEND=\n\n## 額外指導\n\n請特別注意以下事項
|
||||
|
||||
- `{task}` - 任務詳情
|
||||
|
||||
### completeTask 支援的參數
|
||||
|
||||
- `{task}` - 任務詳情
|
||||
- `{completionTime}` - 完成時間
|
||||
|
||||
### listTasks 支援的參數
|
||||
|
||||
- `{status}` - 任務狀態
|
||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "mcp-shrimp-task-manager",
|
||||
"version": "1.0.11",
|
||||
"version": "1.0.15",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "mcp-shrimp-task-manager",
|
||||
"version": "1.0.11",
|
||||
"version": "1.0.15",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.0.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mcp-shrimp-task-manager",
|
||||
"version": "1.0.14",
|
||||
"version": "1.0.21",
|
||||
"description": "Shrimp Task Manager is a task tool built for AI Agents, emphasizing chain-of-thought, reflection, and style consistency. It converts natural language into structured dev tasks with dependency tracking and iterative refinement, enabling agent-like developer behavior in reasoning AI systems",
|
||||
"main": "dist/index.js",
|
||||
"type": "module",
|
||||
@ -16,7 +16,7 @@
|
||||
"mcp-shrimp-task-manager": "./dist/index.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc && copyfiles -u 1 './src/**/*.md' dist && copyfiles -u 1 './src/public/**/*' dist && node scripts/add-shebang.js",
|
||||
"build": "tsc && copyfiles -u 1 \"src/**/*.md\" dist && copyfiles -u 1 \"src/public/**/*\" dist && node scripts/add-shebang.js",
|
||||
"dev": "ts-node src/index.ts",
|
||||
"start": "node dist/index.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
|
251
shrimp-rules.en.md
Normal file
251
shrimp-rules.en.md
Normal file
@ -0,0 +1,251 @@
|
||||
# Development Guidelines
|
||||
|
||||
This document provides the dedicated specifications for AI Agents performing development tasks in the `mcp-shrimp-task-manager` project.
|
||||
|
||||
## 1. Project Overview
|
||||
|
||||
- **Project Name**: `mcp-shrimp-task-manager`
|
||||
- **Purpose**: A task management tool designed for AI Agents, emphasizing chain-of-thought, reflection, and style consistency. It converts natural language into structured development tasks with dependency tracking and iterative refinement capabilities.
|
||||
- **Technology Stack**:
|
||||
- **Primary Language**: TypeScript
|
||||
- **Runtime Environment**: Node.js (ES Module)
|
||||
- **Main Frameworks/Libraries**: Express.js (for potential API or WebGUI), Zod (for data validation)
|
||||
- **Package Manager**: npm
|
||||
- **Core Features**:
|
||||
- Natural language task parsing
|
||||
- Structured task generation and management
|
||||
- Task dependency tracking
|
||||
- Task execution and verification assistance
|
||||
- Integration with AI Agent's thought processes
|
||||
|
||||
## 2. Project Architecture
|
||||
|
||||
- **Main Source Code Directory**: `src/`
|
||||
- `src/index.ts`: Main application entry point or module export point. **Modifications to this file require careful impact assessment.**
|
||||
- `src/utils/`: General-purpose utility functions.
|
||||
- `src/types/`: TypeScript type definitions. **When adding or modifying types, ensure consistency with Zod schemas (if applicable).**
|
||||
- `src/tools/`: Project-specific tools or modules for integration with external services.
|
||||
- `src/models/`: Data model definitions (potentially related to Zod schemas).
|
||||
- `src/prompts/`: Prompt templates related to AI interaction. **Modifying or adding prompts requires consideration of the potential impact on AI Agent behavior.**
|
||||
- `src/public/`: WebGUI or other static assets.
|
||||
- `src/tests/`: Unit and integration tests.
|
||||
- **Compiled Output Directory**: `dist/` (This directory is auto-generated by `tsc`. **Do not manually modify its contents.**).
|
||||
- **Configuration Files**:
|
||||
- `package.json`: Project dependencies and scripts. **After adding dependencies, you must run `npm install`.**
|
||||
- `tsconfig.json`: TypeScript compilation settings. **Do not modify the `"strict": true` setting unless absolutely necessary.**
|
||||
- `.env.example` & `.env`: Environment variable settings. **Sensitive information must not be committed to version control.**
|
||||
- **Documentation**:
|
||||
- `README.md`: Main project documentation.
|
||||
- `docs/`: May contain more detailed architecture, API documentation, etc.
|
||||
- `CHANGELOG.md`: Record of version changes. **Must be updated before releasing a new version.**
|
||||
- `data/WebGUI.md`: Contains the link to the Task Manager UI.
|
||||
|
||||
## 3. Code Specifications
|
||||
|
||||
### 3.1. Naming Conventions
|
||||
|
||||
- **Variables and Functions**: Use camelCase.
|
||||
- _Do_: `const taskName = "example"; function processTask() {}`
|
||||
- _Don't_: `const Task_Name = "example"; function Process_Task() {}`
|
||||
- **Classes and Interfaces**: Use PascalCase.
|
||||
- _Do_: `class TaskManager {}; interface ITaskOptions {}`
|
||||
- _Don't_: `class taskManager {}; interface iTaskOptions {}`
|
||||
- **File Names**: Use camelCase or kebab-case for `.ts` files.
|
||||
- _Do_: `taskProcessor.ts`, `task-utils.ts`
|
||||
- _Don't_: `TaskProcessor.ts`, `task_utils.ts`
|
||||
- **Constants**: Use UPPER_SNAKE_CASE.
|
||||
- _Do_: `const MAX_RETRIES = 3;`
|
||||
- _Don't_: `const maxRetries = 3;`
|
||||
|
||||
### 3.2. Formatting Requirements
|
||||
|
||||
- **Indentation**: Use 2 spaces for indentation. **Do not use Tab characters.**
|
||||
- **Semicolons**: Statements must end with a semicolon.
|
||||
- **Quotes**: Prefer single quotes (`'`) for strings, unless the string itself contains single quotes.
|
||||
- _Do_: `const message = 'Hello World'; const complex = "It\\'s complex";`
|
||||
- _Don't_: `const message = "Hello World";`
|
||||
- **Max Line Length**: Recommended not to exceed 120 characters.
|
||||
- **Comments**:
|
||||
- Use `//` for single-line comments.
|
||||
- Use `/* ... */` for multi-line comments.
|
||||
- Use JSDoc-style comments for public functions, classes, and methods.
|
||||
- _Do_:
|
||||
```typescript
|
||||
/**
|
||||
* Processes a given task.
|
||||
* @param taskId The ID of the task to process.
|
||||
* @returns True if successful, false otherwise.
|
||||
*/
|
||||
function processTaskById(taskId: string): boolean {
|
||||
// implementation
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3. TypeScript Specific Guidelines
|
||||
|
||||
- **Type Annotations**: All function parameters, return values, and variable declarations should have explicit type annotations. **The use of the `any` type is forbidden, except in very specific and unavoidable circumstances, which require a comment explaining the reason.**
|
||||
- _Do_: `function greet(name: string): string { return \`Hello, ${name}\`; }`
|
||||
- _Don't_: `function greet(name): any { return "Hello, " + name; }`
|
||||
- **Interfaces vs. Type Aliases**: Prefer Interfaces for defining object shapes and Type Aliases for defining union types, tuples, or other complex types.
|
||||
- **ES Modules**: Use `import` and `export` syntax.
|
||||
- _Do_: `import { Task } from './models/task'; export class TaskService {}`
|
||||
- _Don't_: `const Task = require('./models/task'); module.exports = TaskService;`
|
||||
- **Strict Mode**: The project has `"strict": true` enabled. All TypeScript strict mode errors must be resolved.
|
||||
|
||||
## 4. Feature Implementation Guidelines
|
||||
|
||||
### 4.1. General Principles
|
||||
|
||||
- **Single Responsibility Principle (SRP)**: Each function and class should be responsible for only one piece of functionality.
|
||||
- **Keep It Simple, Stupid (KISS)**: Avoid overly complex solutions.
|
||||
- **Don't Repeat Yourself (DRY)**: Extract common logic into reusable functions or classes, stored in `src/utils/` or relevant modules.
|
||||
- **Error Handling**:
|
||||
- Use `try...catch` to handle expected errors.
|
||||
- Provide clear error messages for critical operations.
|
||||
- Consider using custom error classes to provide richer error information.
|
||||
- **Logging**:
|
||||
- Add logging for critical operations, error handling, and important state changes.
|
||||
- Consider using structured logging.
|
||||
- **Do not log sensitive information (e.g., passwords, API Keys).**
|
||||
|
||||
### 4.2. Zod Usage
|
||||
|
||||
- Data structures defined in `src/models/` or `src/types/` should primarily use Zod schemas for definition and validation.
|
||||
- Zod schemas should be kept in sync with TypeScript types. You can use `z.infer<typeof schema>` to generate types.
|
||||
|
||||
- _Do_:
|
||||
|
||||
```typescript
|
||||
import { z } from "zod";
|
||||
|
||||
export const TaskSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
name: z.string().min(1),
|
||||
description: z.string().optional(),
|
||||
});
|
||||
|
||||
export type Task = z.infer<typeof TaskSchema>;
|
||||
```
|
||||
|
||||
### 4.3. Express.js Usage (if API/WebGUI exists)
|
||||
|
||||
- Route definitions should be clear and follow RESTful principles (for APIs).
|
||||
- Middleware should be effectively organized, e.g., error handling middleware, logging middleware.
|
||||
- All external input (request parameters, body, query) **must** be validated using Zod or a similar mechanism.
|
||||
|
||||
## 5. Framework/Plugin/Third-Party Library Usage Guidelines
|
||||
|
||||
- **Adding Dependencies**:
|
||||
- **Must** first evaluate the necessity, maintenance status, and security of the dependency.
|
||||
- Use `npm install <package-name>` (for runtime dependencies) or `npm install --save-dev <package-name>` (for development dependencies).
|
||||
- **Must** specify a clear version range in `package.json` (e.g., `^1.2.3` or `~1.2.3`), avoid using `*`.
|
||||
- **Updating Dependencies**: Regularly check and update dependencies to the latest stable version to get security patches and new features. Assess potential breaking changes before updating.
|
||||
- **Removing Dependencies**: If a dependency is no longer needed, remove it using `npm uninstall <package-name>` and remove related references from the code.
|
||||
|
||||
## 6. Workflow Guidelines
|
||||
|
||||
### 6.1. Development Process
|
||||
|
||||
1. **Understand the Task**: Carefully read the task description, requirements, and acceptance criteria.
|
||||
2. **Branch Management**: Create a new feature branch from the latest `main` (or `develop`) branch. Branch names should be concise and clear, e.g., `feature/add-task-editing` or `fix/login-bug`.
|
||||
3. **Coding and Testing**:
|
||||
- Code according to these guidelines.
|
||||
- **Must** write unit tests (stored in `src/tests/`) for new features or bug fixes.
|
||||
- Run `npm run build` to ensure the code compiles successfully.
|
||||
- Run `npm run dev` or `npm run start` locally for testing.
|
||||
4. **Code Committing**:
|
||||
- Git commit messages should follow the Conventional Commits specification (e.g., `feat: add user authentication`, `fix: resolve issue with task sorting`).
|
||||
- **Do not commit code with `console.log` or other debugging messages to the main branches.**
|
||||
5. **Pull Request (PR)**:
|
||||
- Push the feature branch to the remote repository and create a Pull Request to the `main` (or `develop`) branch.
|
||||
- The PR description should clearly explain the changes and their purpose.
|
||||
6. **Code Review**: Wait for other developers or AI Agents to conduct a code review.
|
||||
7. **Merge and Deploy**: After the code review is passed, merge the PR. The deployment process follows the project setup.
|
||||
|
||||
### 6.2. Version Control (Git)
|
||||
|
||||
- **Main Branches**:
|
||||
- `main`: Represents the stable and deployable product version.
|
||||
- `develop` (if used): Represents the latest in-development version.
|
||||
- **Commit Frequency**: Small, frequent, and meaningful commits are recommended.
|
||||
- **Resolving Conflicts**: When merging or rebasing branches, if conflicts occur, they **must** be resolved carefully to ensure the correctness and integrity of the code.
|
||||
|
||||
### 6.3. CHANGELOG Updates
|
||||
|
||||
- Before releasing a new version, `CHANGELOG.md` **must** be updated.
|
||||
- The log should include the version number, release date, and a list of new features, bug fixes, and breaking changes.
|
||||
|
||||
## 7. Key File Interaction Guidelines
|
||||
|
||||
- **Modifying `src/types/` or `src/models/` (especially Zod schemas)**:
|
||||
- **Must** check and update all files that reference these types or schemas to ensure type consistency.
|
||||
- **Must** re-run relevant tests.
|
||||
- **Modifying `src/index.ts`**:
|
||||
- If the module's exported API is changed, **must** check all dependent projects or files and make necessary adjustments.
|
||||
- **Modifying `package.json` (especially `dependencies` or `scripts`)**:
|
||||
- **Must** notify team members or relevant AI Agents to run `npm install`.
|
||||
- If `scripts` are modified, ensure the CI/CD process (if any) is updated accordingly.
|
||||
- **Modifying `.env.example`**:
|
||||
- **Must** synchronously update `.env` files in all development environments and notify team members.
|
||||
- **Modifying `README.md` or documents in `docs/`**:
|
||||
- If changes involve core features or usage, **must** ensure the accuracy and timeliness of the documentation.
|
||||
|
||||
## 8. AI Decision-Making Guidelines
|
||||
|
||||
### 8.1. Handling Vague Requests
|
||||
|
||||
- When receiving a vague development instruction (e.g., "optimize the task list display"):
|
||||
1. **Attempt to Clarify**: If possible, request more specific details or expected outcomes from the user or task initiator.
|
||||
2. **Analyze Context**: Check related code (`src/`), existing UI (if any), and relevant issues (if any) to infer intent.
|
||||
3. **Propose Solutions**: Based on the analysis, propose 1-2 concrete implementation plans, explaining their pros, cons, and estimated effort.
|
||||
4. **Wait for Confirmation**: Do not proceed with large-scale code modifications until clear instructions are received.
|
||||
|
||||
### 8.2. Error/Exception Handling Strategy
|
||||
|
||||
- **Priorities**:
|
||||
1. **User Experience**: Avoid program crashes and provide friendly error messages.
|
||||
2. **Data Integrity**: Ensure errors do not lead to data corruption or inconsistency.
|
||||
3. **System Stability**: Log detailed error information for troubleshooting.
|
||||
- **Choices**:
|
||||
- For predictable errors (e.g., invalid user input), handle them within the operation's context and provide feedback.
|
||||
- For unexpected system errors, catch, log, and potentially re-throw or trigger a global error handling mechanism.
|
||||
|
||||
### 8.3. Dependency Selection
|
||||
|
||||
- When needing to introduce a new third-party library:
|
||||
1. **Check Existing**: Verify if a similar library that meets the requirements already exists in the project.
|
||||
2. **Evaluate Options**:
|
||||
- **Activity and Community Support**: Choose well-maintained libraries with active communities.
|
||||
- **Lightweight**: Avoid introducing libraries that are too large or have redundant features.
|
||||
- **Security**: Check for known security vulnerabilities.
|
||||
- **License**: Ensure compatibility with the project's license.
|
||||
3. **Minimization Principle**: Only introduce libraries that are genuinely needed.
|
||||
|
||||
## 9. Prohibitions
|
||||
|
||||
- **Do not directly modify any files in the `dist/` directory.** This directory contains compiled output.
|
||||
- **Do not assume a new dependency is available without running `npm install`.**
|
||||
- **Do not commit untested or unfinished code directly to the main branches (`main` or `develop`).** Use feature branches.
|
||||
- **Do not commit code containing API Keys, passwords, or other sensitive information to the version control system.** Use the `.env` file for such information.
|
||||
- **Do not make major changes to the core architecture or public API without notification and approval.**
|
||||
- **Do not ignore TypeScript type errors.** All errors reported by `tsc` must be resolved.
|
||||
- **Do not use the `any` type without a very good reason and a corresponding comment.**
|
||||
- **Do not leave large amounts of `console.log` or other temporary debugging code in the codebase.**
|
||||
- **Do not release a new version without updating `CHANGELOG.md`.**
|
||||
- **Do not introduce third-party libraries incompatible with the project's MIT license.**
|
||||
|
||||
## 10. Updating This Guideline Document (`shrimp-rules.md`)
|
||||
|
||||
- When the project's tech stack, core architecture, main workflow, or important guidelines change, this document **must** be updated accordingly.
|
||||
- Update requests should clearly specify the sections and content to be changed.
|
||||
- If a vague "update rules" instruction is received, the AI Agent **must**:
|
||||
1. Autonomously analyze the current codebase for changes (e.g., `git diff`, recent commits).
|
||||
2. Compare the existing `shrimp-rules.md` with the project's current state to find inconsistent or outdated rules.
|
||||
3. List the inferred update points and their justifications in the `process_thought` stage.
|
||||
4. Propose specific modifications or directly edit this document.
|
||||
5. **Strictly prohibited** to seek clarification from the user on a vague request before performing an autonomous analysis.
|
||||
|
||||
---
|
||||
|
||||
This development guide aims to ensure that AI Agents can participate in the development of the `mcp-shrimp-task-manager` project efficiently, consistently, and securely.
|
251
shrimp-rules.md
Normal file
251
shrimp-rules.md
Normal file
@ -0,0 +1,251 @@
|
||||
# 開發守則
|
||||
|
||||
本文檔為 AI Agent 在 `mcp-shrimp-task-manager` 專案中執行開發任務的專用規範。
|
||||
|
||||
## 1. 專案概述
|
||||
|
||||
- **專案名稱**: `mcp-shrimp-task-manager`
|
||||
- **目的**: 一個為 AI Agents 設計的任務管理工具,強調思維鏈、反思和風格一致性。它將自然語言轉換為結構化的開發任務,並具有依賴追蹤和迭代優化功能。
|
||||
- **技術棧**:
|
||||
- 主要語言: TypeScript
|
||||
- 執行環境: Node.js (ES Module)
|
||||
- 主要框架/函式庫: Express.js (用於可能的 API 或 WebGUI), Zod (用於資料驗證)
|
||||
- 套件管理器: npm
|
||||
- **核心功能**:
|
||||
- 自然語言任務解析
|
||||
- 結構化任務生成與管理
|
||||
- 任務依賴關係追蹤
|
||||
- 任務執行與驗證輔助
|
||||
- 與 AI Agent 的思維流程整合
|
||||
|
||||
## 2. 專案架構
|
||||
|
||||
- **主要原始碼目錄**: `src/`
|
||||
- `src/index.ts`: 主要應用程式入口或模組匯出點。**修改此檔案需謹慎評估影響範圍。**
|
||||
- `src/utils/`: 通用工具函式。
|
||||
- `src/types/`: TypeScript 型別定義。**新增或修改型別時,務必確保與 Zod schema (如適用) 一致性。**
|
||||
- `src/tools/`: 專案特定工具或與外部服務整合的模組。
|
||||
- `src/models/`: 資料模型定義 (可能與 Zod schemas 相關)。
|
||||
- `src/prompts/`: AI 互動相關的提示詞模板。**修改或新增提示詞時,需考慮對 AI Agent 行為的潛在影響。**
|
||||
- `src/public/`: WebGUI 或其他靜態資源。
|
||||
- `src/tests/`: 單元測試和整合測試。
|
||||
- **編譯輸出目錄**: `dist/` (此目錄由 `tsc` 自動生成,**禁止手動修改此目錄內容**)。
|
||||
- **設定檔**:
|
||||
- `package.json`: 專案依賴和腳本。**新增依賴後,必須執行 `npm install`。**
|
||||
- `tsconfig.json`: TypeScript 編譯設定。**非必要情況下,禁止修改 `"strict": true` 設定。**
|
||||
- `.env.example` & `.env`: 環境變數設定。**敏感資訊不得提交至版本控制。**
|
||||
- **文件**:
|
||||
- `README.md`: 主要專案說明文件。
|
||||
- `docs/`: 可能包含更詳細的架構、API 文件等。
|
||||
- `CHANGELOG.md`: 版本變更紀錄。**每次發布新版本前必須更新。**
|
||||
- `data/WebGUI.md`: 包含 Task Manager UI 的連結。
|
||||
|
||||
## 3. 程式碼規範
|
||||
|
||||
### 3.1. 命名規範
|
||||
|
||||
- **變數與函式**: 使用小駝峰命名法 (camelCase)。
|
||||
- _範例 (可做)_: `const taskName = "example"; function processTask() {}`
|
||||
- _範例 (不可做)_: `const Task_Name = "example"; function Process_Task() {}`
|
||||
- **類別與介面**: 使用大駝峰命名法 (PascalCase)。
|
||||
- _範例 (可做)_: `class TaskManager {}; interface ITaskOptions {}`
|
||||
- _範例 (不可做)_: `class taskManager {}; interface iTaskOptions {}`
|
||||
- **檔案名稱**: 使用小駝峰命名法或橫線連接 (kebab-case) 的 `.ts` 檔案。
|
||||
- _範例 (可做)_: `taskProcessor.ts`, `task-utils.ts`
|
||||
- _範例 (不可做)_: `TaskProcessor.ts`, `task_utils.ts`
|
||||
- **常數**: 使用全大寫蛇形命名法 (UPPER_SNAKE_CASE)。
|
||||
- _範例 (可做)_: `const MAX_RETRIES = 3;`
|
||||
- _範例 (不可做)_: `const maxRetries = 3;`
|
||||
|
||||
### 3.2. 格式要求
|
||||
|
||||
- **縮排**: 使用 2 個空格進行縮排。**禁止使用 Tab 字元。**
|
||||
- **分號**: 每行敘述句尾必須加上分號。
|
||||
- **引號**: 字串優先使用單引號 (`'`),除非字串本身包含單引號。
|
||||
- _範例 (可做)_: `const message = 'Hello World'; const complex = "It\\'s complex";`
|
||||
- _範例 (不可做)_: `const message = "Hello World";`
|
||||
- **最大行長度**: 建議不超過 120 字元。
|
||||
- **註解**:
|
||||
- 單行註解使用 `//`。
|
||||
- 多行註解使用 `/* ... */`。
|
||||
- JSDoc 風格的註解應用於公開的函式、類別和方法。
|
||||
- _範例 (可做)_:
|
||||
```typescript
|
||||
/**
|
||||
* Processes a given task.
|
||||
* @param taskId The ID of the task to process.
|
||||
* @returns True if successful, false otherwise.
|
||||
*/
|
||||
function processTaskById(taskId: string): boolean {
|
||||
// implementation
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3. TypeScript 特定規範
|
||||
|
||||
- **型別註解**: 所有函式參數、回傳值和變數宣告都應有明確的型別註解。**禁止使用 `any` 型別,除非在極特殊且無法避免的情況下,並需加上註解說明原因。**
|
||||
- _範例 (可做)_: `function greet(name: string): string { return \`Hello, ${name}\`; }`
|
||||
- _範例 (不可做)_: `function greet(name): any { return "Hello, " + name; }`
|
||||
- **介面與型別別名**: 優先使用介面 (Interface) 定義物件的形狀,使用型別別名 (Type Alias) 定義聯合型別、元組或其他複雜型別。
|
||||
- **ES Module**: 使用 `import` 和 `export` 語法。
|
||||
- _範例 (可做)_: `import { Task } from './models/task'; export class TaskService {}`
|
||||
- _範例 (不可做)_: `const Task = require('./models/task'); module.exports = TaskService;`
|
||||
- **嚴格模式**: 專案已啟用 `"strict": true`。必須解決所有 TypeScript 的嚴格模式錯誤。
|
||||
|
||||
## 4. 功能實作規範
|
||||
|
||||
### 4.1. 通用原則
|
||||
|
||||
- **單一職責原則 (SRP)**: 每個函式和類別應只負責一項功能。
|
||||
- **保持簡潔 (KISS)**: 避免過度複雜的解決方案。
|
||||
- **重複利用**: 盡可能將通用邏輯抽取為可重用函式或類別,存放於 `src/utils/` 或相關模組。
|
||||
- **錯誤處理**:
|
||||
- 使用 `try...catch` 處理預期內的錯誤。
|
||||
- 對於關鍵操作,應提供清晰的錯誤訊息。
|
||||
- 考慮使用自定義錯誤類別以提供更豐富的錯誤資訊。
|
||||
- **日誌記錄**:
|
||||
- 在關鍵操作、錯誤處理和重要狀態變更時加入日誌記錄。
|
||||
- 考慮使用結構化日誌。
|
||||
- **禁止在日誌中記錄敏感資訊 (如密碼、API Keys)。**
|
||||
|
||||
### 4.2. Zod 使用
|
||||
|
||||
- 位於 `src/models/` 或 `src/types/` 的資料結構定義,應優先使用 Zod schema 進行定義和驗證。
|
||||
- Zod schema 應與 TypeScript 型別保持同步。可使用 `z.infer<typeof schema>` 生成型別。
|
||||
|
||||
- _範例 (可做)_:
|
||||
|
||||
```typescript
|
||||
import { z } from "zod";
|
||||
|
||||
export const TaskSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
name: z.string().min(1),
|
||||
description: z.string().optional(),
|
||||
});
|
||||
|
||||
export type Task = z.infer<typeof TaskSchema>;
|
||||
```
|
||||
|
||||
### 4.3. Express.js 使用 (若有 API/WebGUI)
|
||||
|
||||
- 路由定義應清晰且遵循 RESTful 原則 (若為 API)。
|
||||
- 中介軟體 (Middleware) 應有效組織,例如錯誤處理中介軟體、日誌中介軟體等。
|
||||
- 所有外部輸入 (request parameters, body, query) **必須**經過 Zod 或類似機制驗證。
|
||||
|
||||
## 5. 框架/外掛程式/第三方庫使用規範
|
||||
|
||||
- **新增依賴**:
|
||||
- **必須**先評估依賴的必要性、維護狀態和安全性。
|
||||
- 使用 `npm install <package-name>` (用於執行依賴) 或 `npm install --save-dev <package-name>` (用於開發依賴)。
|
||||
- **必須**在 `package.json` 中指定明確的版本範圍 (例如 `^1.2.3` 或 `~1.2.3`),避免使用 `*`。
|
||||
- **更新依賴**: 定期檢查並更新依賴至最新穩定版本,以獲取安全性修補和新功能。更新前需評估潛在的破壞性變更。
|
||||
- **移除依賴**: 若不再需要某個依賴,使用 `npm uninstall <package-name>` 將其移除,並從程式碼中移除相關引用。
|
||||
|
||||
## 6. 工作流程規範
|
||||
|
||||
### 6.1. 開發流程
|
||||
|
||||
1. **理解任務**: 仔細閱讀任務描述、需求和驗收標準。
|
||||
2. **分支管理**: 從最新的 `main` (或 `develop`) 分支建立新的特性分支 (feature branch)。分支名稱應簡潔明瞭,例如 `feature/add-task-editing` 或 `fix/login-bug`。
|
||||
3. **編碼與測試**:
|
||||
- 按照本規範進行編碼。
|
||||
- **必須**為新功能或修復的 bug 編寫單元測試 (存放於 `src/tests/`)。
|
||||
- 執行 `npm run build` 確保程式碼可以成功編譯。
|
||||
- 本地執行 `npm run dev` 或 `npm run start` 進行測試。
|
||||
4. **程式碼提交**:
|
||||
- Git commit message 應遵循 Conventional Commits 規範 (例如 `feat: add user authentication`, `fix: resolve issue with task sorting`)。
|
||||
- **禁止提交包含 `console.log` 或其他偵錯訊息的程式碼至主要分支。**
|
||||
5. **Pull Request (PR)**:
|
||||
- 將特性分支推送到遠端倉庫,並建立 Pull Request 至 `main` (或 `develop`) 分支。
|
||||
- PR 描述應清晰說明變更內容和原因。
|
||||
6. **Code Review**: 等待其他開發者或 AI Agent 進行 Code Review。
|
||||
7. **合併與部署**: Code Review 通過後,合併 PR。部署流程依專案設定。
|
||||
|
||||
### 6.2. 版本控制 (Git)
|
||||
|
||||
- **主要分支**:
|
||||
- `main`: 代表穩定且可部署的產品版本。
|
||||
- `develop` (若使用): 代表開發中的最新版本。
|
||||
- **提交頻率**: 建議小步快跑,頻繁提交有意義的變更。
|
||||
- **解決衝突**: 合併或 rebase 分支時,若發生衝突,**必須**仔細解決,確保程式碼的正確性和完整性。
|
||||
|
||||
### 6.3. CHANGELOG 更新
|
||||
|
||||
- 在發布新版本之前,**必須**更新 `CHANGELOG.md`。
|
||||
- 紀錄應包含版本號、發布日期以及新增功能、修復的錯誤和重大變更列表。
|
||||
|
||||
## 7. 關鍵檔案交互規範
|
||||
|
||||
- **修改 `src/types/` 或 `src/models/` (特別是 Zod schemas)**:
|
||||
- **必須**檢查並更新所有引用到這些型別或 schema 的檔案,確保型別一致性。
|
||||
- **必須**重新執行相關測試。
|
||||
- **修改 `src/index.ts`**:
|
||||
- 若修改了模組的匯出 API,**必須**檢查所有依賴此模組的專案或檔案,並進行相應調整。
|
||||
- **修改 `package.json` (特別是 `dependencies` 或 `scripts`)**:
|
||||
- **必須**通知團隊成員或相關 AI Agent 執行 `npm install`。
|
||||
- 若修改 `scripts`,需確保 CI/CD 流程 (若有) 也相應更新。
|
||||
- **修改 `.env.example`**:
|
||||
- **必須**同步更新所有開發環境的 `.env` 檔案,並通知團隊成員。
|
||||
- **修改 `README.md` 或 `docs/` 內的文檔**:
|
||||
- 若變更涉及核心功能或使用方式,**必須**確保文件內容的準確性和即時性。
|
||||
|
||||
## 8. AI 決策規範
|
||||
|
||||
### 8.1. 處理模糊請求
|
||||
|
||||
- 當收到模糊的開發指令時 (例如 "優化任務列表顯示"):
|
||||
1. **嘗試澄清**: 若可能,向用戶或任務發起者請求更具體的細節或預期結果。
|
||||
2. **分析上下文**: 檢查相關程式碼 (`src/`)、現有 UI (若有)、相關 issue (若有) 來推斷可能的意圖。
|
||||
3. **提出方案**: 基於分析,提出 1-2 個具體的實施方案,並說明各自的優缺點及預計工作量。
|
||||
4. **等待確認**: 在獲得明確指示前,不進行大規模程式碼修改。
|
||||
|
||||
### 8.2. 錯誤/異常處理策略
|
||||
|
||||
- **優先級**:
|
||||
1. **使用者體驗**: 避免程式崩潰,提供友好的錯誤提示。
|
||||
2. **資料完整性**: 確保錯誤不會導致資料損壞或不一致。
|
||||
3. **系統穩定性**: 記錄詳細錯誤資訊以供排查。
|
||||
- **選擇**:
|
||||
- 對於可預期的錯誤 (例如使用者輸入無效),應在該操作的上下文中處理並給予提示。
|
||||
- 對於意外的系統錯誤,應捕獲、記錄,並可能向上拋出或觸發全域錯誤處理機制。
|
||||
|
||||
### 8.3. 依賴選擇
|
||||
|
||||
- 當需要引入新的第三方函式庫時:
|
||||
1. **檢查現有**: 確認專案中是否已有可滿足需求的類似函式庫。
|
||||
2. **評估選項**:
|
||||
- **活躍度與社群支援**: 選擇維護良好、社群活躍的函式庫。
|
||||
- **輕量級**: 避免引入過於龐大或功能冗餘的函式庫。
|
||||
- **安全性**: 檢查是否有已知的安全漏洞。
|
||||
- **授權條款 (License)**: 確保與專案授權相容。
|
||||
3. **最小化原則**: 僅引入確實需要的函式庫。
|
||||
|
||||
## 9. 禁止事項
|
||||
|
||||
- **禁止直接修改 `dist/` 目錄下的任何檔案。** 該目錄為編譯產物。
|
||||
- **禁止在未執行 `npm install` 的情況下,假定新依賴可用。**
|
||||
- **禁止在主要分支 (`main` 或 `develop`) 直接提交未經測試或未完成的程式碼。** 必須使用特性分支。
|
||||
- **禁止提交包含 API Keys、密碼或其他敏感資訊的程式碼至版本控制系統。** 使用 `.env` 檔案管理此類資訊。
|
||||
- **禁止在未告知或未獲同意的情況下,大幅修改核心架構或公共 API。**
|
||||
- **禁止忽略 TypeScript 的型別錯誤。** 必須解決所有 `tsc` 報告的錯誤。
|
||||
- **禁止在沒有充分理由和註解的情況下使用 `any` 型別。**
|
||||
- **禁止在程式碼中留下大量的 `console.log` 或其他臨時偵錯程式碼。**
|
||||
- **禁止在未更新 `CHANGELOG.md` 的情況下發布新版本。**
|
||||
- **禁止引入與專案 MIT 授權條款不相容的第三方函式庫。**
|
||||
|
||||
## 10. 更新此規範文件 (`shrimp-rules.md`)
|
||||
|
||||
- 當專案的技術棧、核心架構、主要工作流程或重要規範發生變動時,**必須**同步更新此文件。
|
||||
- 更新請求應明確指出需要變更的章節和內容。
|
||||
- 若收到模糊的 "更新規則" 指令,AI Agent **必須**:
|
||||
1. 自主分析當前程式碼庫的變更 (例如 `git diff`、最近的 commit)。
|
||||
2. 比較現有的 `shrimp-rules.md` 與專案現狀,找出不一致或過時的規則。
|
||||
3. 在 `process_thought` 階段列出推斷的更新點及其理由。
|
||||
4. 提出具體的修改建議,或直接編輯此文件。
|
||||
5. **嚴格禁止**在執行自主分析前就模糊請求向用戶尋求澄清。
|
||||
|
||||
---
|
||||
|
||||
此開發守則旨在確保 AI Agent 能夠高效、一致且安全地參與 `mcp-shrimp-task-manager` 專案的開發。
|
200
src/index.ts
200
src/index.ts
@ -7,13 +7,10 @@ import {
|
||||
CallToolRequest,
|
||||
CallToolRequestSchema,
|
||||
ListToolsRequestSchema,
|
||||
InitializedNotificationSchema,
|
||||
} from "@modelcontextprotocol/sdk/types.js";
|
||||
import express, { Request, Response, NextFunction } from "express";
|
||||
import getPort from "get-port";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import fsPromises from "fs/promises";
|
||||
import { fileURLToPath } from "url";
|
||||
import { setGlobalServer } from "./utils/paths.js";
|
||||
import { createWebServer } from "./web/webServer.js";
|
||||
|
||||
// 導入所有工具函數和 schema
|
||||
import {
|
||||
@ -25,6 +22,8 @@ import {
|
||||
reflectTaskSchema,
|
||||
splitTasks,
|
||||
splitTasksSchema,
|
||||
splitTasksRaw,
|
||||
splitTasksRawSchema,
|
||||
listTasksSchema,
|
||||
listTasks,
|
||||
executeTask,
|
||||
@ -45,127 +44,15 @@ import {
|
||||
processThoughtSchema,
|
||||
initProjectRules,
|
||||
initProjectRulesSchema,
|
||||
researchMode,
|
||||
researchModeSchema,
|
||||
} from "./tools/index.js";
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
console.log("Starting Shrimp Task Manager service...");
|
||||
const ENABLE_GUI = process.env.ENABLE_GUI === "true";
|
||||
|
||||
if (ENABLE_GUI) {
|
||||
// 創建 Express 應用
|
||||
const app = express();
|
||||
|
||||
// 儲存 SSE 客戶端的列表
|
||||
let sseClients: Response[] = [];
|
||||
|
||||
// 發送 SSE 事件的輔助函數
|
||||
function sendSseUpdate() {
|
||||
sseClients.forEach((client) => {
|
||||
// 檢查客戶端是否仍然連接
|
||||
if (!client.writableEnded) {
|
||||
client.write(
|
||||
`event: update\ndata: ${JSON.stringify({
|
||||
timestamp: Date.now(),
|
||||
})}\n\n`
|
||||
);
|
||||
}
|
||||
});
|
||||
// 清理已斷開的客戶端 (可選,但建議)
|
||||
sseClients = sseClients.filter((client) => !client.writableEnded);
|
||||
}
|
||||
|
||||
// 設置靜態文件目錄
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const publicPath = path.join(__dirname, "public");
|
||||
const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, "data");
|
||||
const TASKS_FILE_PATH = path.join(DATA_DIR, "tasks.json"); // 提取檔案路徑
|
||||
|
||||
app.use(express.static(publicPath));
|
||||
|
||||
// 設置 API 路由
|
||||
app.get("/api/tasks", async (req: Request, res: Response) => {
|
||||
try {
|
||||
// 使用 fsPromises 保持異步讀取
|
||||
const tasksData = await fsPromises.readFile(TASKS_FILE_PATH, "utf-8");
|
||||
res.json(JSON.parse(tasksData));
|
||||
} catch (error) {
|
||||
// 確保檔案不存在時返回空任務列表
|
||||
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
||||
res.json({ tasks: [] });
|
||||
} else {
|
||||
res.status(500).json({ error: "Failed to read tasks data" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 新增:SSE 端點
|
||||
app.get("/api/tasks/stream", (req: Request, res: Response) => {
|
||||
res.writeHead(200, {
|
||||
"Content-Type": "text/event-stream",
|
||||
"Cache-Control": "no-cache",
|
||||
Connection: "keep-alive",
|
||||
// 可選: CORS 頭,如果前端和後端不在同一個 origin
|
||||
// "Access-Control-Allow-Origin": "*",
|
||||
});
|
||||
|
||||
// 發送一個初始事件或保持連接
|
||||
res.write("data: connected\n\n");
|
||||
|
||||
// 將客戶端添加到列表
|
||||
sseClients.push(res);
|
||||
|
||||
// 當客戶端斷開連接時,將其從列表中移除
|
||||
req.on("close", () => {
|
||||
sseClients = sseClients.filter((client) => client !== res);
|
||||
});
|
||||
});
|
||||
|
||||
// 獲取可用埠
|
||||
const port = await getPort();
|
||||
|
||||
// 啟動 HTTP 伺服器
|
||||
const httpServer = app.listen(port, () => {
|
||||
// 在伺服器啟動後開始監聽檔案變化
|
||||
try {
|
||||
// 檢查檔案是否存在,如果不存在則不監聽 (避免 watch 報錯)
|
||||
if (fs.existsSync(TASKS_FILE_PATH)) {
|
||||
fs.watch(TASKS_FILE_PATH, (eventType, filename) => {
|
||||
if (
|
||||
filename &&
|
||||
(eventType === "change" || eventType === "rename")
|
||||
) {
|
||||
// 稍微延遲發送,以防短時間內多次觸發 (例如編輯器保存)
|
||||
// debounce sendSseUpdate if needed
|
||||
sendSseUpdate();
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (watchError) {}
|
||||
});
|
||||
|
||||
// 將 URL 寫入 ebGUI.md
|
||||
try {
|
||||
const websiteUrl = `[Task Manager UI](http://localhost:${port})`;
|
||||
const websiteFilePath = path.join(DATA_DIR, "WebGUI.md");
|
||||
await fsPromises.writeFile(websiteFilePath, websiteUrl, "utf-8");
|
||||
} catch (error) {}
|
||||
|
||||
// 設置進程終止事件處理 (確保移除 watcher)
|
||||
const shutdownHandler = async () => {
|
||||
// 關閉所有 SSE 連接
|
||||
sseClients.forEach((client) => client.end());
|
||||
sseClients = [];
|
||||
|
||||
// 關閉 HTTP 伺服器
|
||||
await new Promise<void>((resolve) => httpServer.close(() => resolve()));
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
process.on("SIGINT", shutdownHandler);
|
||||
process.on("SIGTERM", shutdownHandler);
|
||||
}
|
||||
let webServerInstance: Awaited<ReturnType<typeof createWebServer>> | null =
|
||||
null;
|
||||
|
||||
// 創建MCP服務器
|
||||
const server = new Server(
|
||||
@ -176,109 +63,132 @@ async function main() {
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
logging: {},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// 設置全局 server 實例
|
||||
setGlobalServer(server);
|
||||
|
||||
// 監聽 initialized 通知來啟動 web 服務器
|
||||
if (ENABLE_GUI) {
|
||||
server.setNotificationHandler(InitializedNotificationSchema, async () => {
|
||||
try {
|
||||
webServerInstance = await createWebServer();
|
||||
await webServerInstance.startServer();
|
||||
} catch (error) {}
|
||||
});
|
||||
}
|
||||
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
return {
|
||||
tools: [
|
||||
{
|
||||
name: "plan_task",
|
||||
description: loadPromptFromTemplate("toolsDescription/planTask.md"),
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/planTask.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(planTaskSchema),
|
||||
},
|
||||
{
|
||||
name: "analyze_task",
|
||||
description: loadPromptFromTemplate(
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/analyzeTask.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(analyzeTaskSchema),
|
||||
},
|
||||
{
|
||||
name: "reflect_task",
|
||||
description: loadPromptFromTemplate(
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/reflectTask.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(reflectTaskSchema),
|
||||
},
|
||||
{
|
||||
name: "split_tasks",
|
||||
description: loadPromptFromTemplate(
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/splitTasks.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(splitTasksSchema),
|
||||
inputSchema: zodToJsonSchema(splitTasksRawSchema),
|
||||
},
|
||||
{
|
||||
name: "list_tasks",
|
||||
description: loadPromptFromTemplate(
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/listTasks.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(listTasksSchema),
|
||||
},
|
||||
{
|
||||
name: "execute_task",
|
||||
description: loadPromptFromTemplate(
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/executeTask.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(executeTaskSchema),
|
||||
},
|
||||
{
|
||||
name: "verify_task",
|
||||
description: loadPromptFromTemplate(
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/verifyTask.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(verifyTaskSchema),
|
||||
},
|
||||
{
|
||||
name: "delete_task",
|
||||
description: loadPromptFromTemplate(
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/deleteTask.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(deleteTaskSchema),
|
||||
},
|
||||
{
|
||||
name: "clear_all_tasks",
|
||||
description: loadPromptFromTemplate(
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/clearAllTasks.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(clearAllTasksSchema),
|
||||
},
|
||||
{
|
||||
name: "update_task",
|
||||
description: loadPromptFromTemplate(
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/updateTask.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(updateTaskContentSchema),
|
||||
},
|
||||
{
|
||||
name: "query_task",
|
||||
description: loadPromptFromTemplate(
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/queryTask.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(queryTaskSchema),
|
||||
},
|
||||
{
|
||||
name: "get_task_detail",
|
||||
description: loadPromptFromTemplate(
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/getTaskDetail.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(getTaskDetailSchema),
|
||||
},
|
||||
{
|
||||
name: "process_thought",
|
||||
description: loadPromptFromTemplate(
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/processThought.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(processThoughtSchema),
|
||||
},
|
||||
{
|
||||
name: "init_project_rules",
|
||||
description: loadPromptFromTemplate(
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/initProjectRules.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(initProjectRulesSchema),
|
||||
},
|
||||
{
|
||||
name: "research_mode",
|
||||
description: await loadPromptFromTemplate(
|
||||
"toolsDescription/researchMode.md"
|
||||
),
|
||||
inputSchema: zodToJsonSchema(researchModeSchema),
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
@ -324,7 +234,7 @@ async function main() {
|
||||
}
|
||||
return await reflectTask(parsedArgs.data);
|
||||
case "split_tasks":
|
||||
parsedArgs = await splitTasksSchema.safeParseAsync(
|
||||
parsedArgs = await splitTasksRawSchema.safeParseAsync(
|
||||
request.params.arguments
|
||||
);
|
||||
if (!parsedArgs.success) {
|
||||
@ -332,7 +242,7 @@ async function main() {
|
||||
`Invalid arguments for tool ${request.params.name}: ${parsedArgs.error.message}`
|
||||
);
|
||||
}
|
||||
return await splitTasks(parsedArgs.data);
|
||||
return await splitTasksRaw(parsedArgs.data);
|
||||
case "list_tasks":
|
||||
parsedArgs = await listTasksSchema.safeParseAsync(
|
||||
request.params.arguments
|
||||
@ -425,6 +335,16 @@ async function main() {
|
||||
return await processThought(parsedArgs.data);
|
||||
case "init_project_rules":
|
||||
return await initProjectRules();
|
||||
case "research_mode":
|
||||
parsedArgs = await researchModeSchema.safeParseAsync(
|
||||
request.params.arguments
|
||||
);
|
||||
if (!parsedArgs.success) {
|
||||
throw new Error(
|
||||
`Invalid arguments for tool ${request.params.name}: ${parsedArgs.error.message}`
|
||||
);
|
||||
}
|
||||
return await researchMode(parsedArgs.data);
|
||||
default:
|
||||
throw new Error(`Tool ${request.params.name} does not exist`);
|
||||
}
|
||||
@ -446,8 +366,6 @@ async function main() {
|
||||
// 建立連接
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
|
||||
console.log("Shrimp Task Manager service started");
|
||||
} catch (error) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
@ -13,21 +13,25 @@ import { v4 as uuidv4 } from "uuid";
|
||||
import { fileURLToPath } from "url";
|
||||
import { exec } from "child_process";
|
||||
import { promisify } from "util";
|
||||
import { getDataDir, getTasksFilePath, getMemoryDir } from "../utils/paths.js";
|
||||
|
||||
// 確保獲取專案資料夾路徑
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const PROJECT_ROOT = path.resolve(__dirname, "../..");
|
||||
|
||||
// 數據文件路徑
|
||||
const DATA_DIR = process.env.DATA_DIR || path.join(PROJECT_ROOT, "data");
|
||||
const TASKS_FILE = path.join(DATA_DIR, "tasks.json");
|
||||
// 數據文件路徑(改為異步獲取)
|
||||
// const DATA_DIR = getDataDir();
|
||||
// const TASKS_FILE = getTasksFilePath();
|
||||
|
||||
// 將exec轉換為Promise形式
|
||||
const execPromise = promisify(exec);
|
||||
|
||||
// 確保數據目錄存在
|
||||
async function ensureDataDir() {
|
||||
const DATA_DIR = await getDataDir();
|
||||
const TASKS_FILE = await getTasksFilePath();
|
||||
|
||||
try {
|
||||
await fs.access(DATA_DIR);
|
||||
} catch (error) {
|
||||
@ -44,6 +48,7 @@ async function ensureDataDir() {
|
||||
// 讀取所有任務
|
||||
async function readTasks(): Promise<Task[]> {
|
||||
await ensureDataDir();
|
||||
const TASKS_FILE = await getTasksFilePath();
|
||||
const data = await fs.readFile(TASKS_FILE, "utf-8");
|
||||
const tasks = JSON.parse(data).tasks;
|
||||
|
||||
@ -59,6 +64,7 @@ async function readTasks(): Promise<Task[]> {
|
||||
// 寫入所有任務
|
||||
async function writeTasks(tasks: Task[]): Promise<void> {
|
||||
await ensureDataDir();
|
||||
const TASKS_FILE = await getTasksFilePath();
|
||||
await fs.writeFile(TASKS_FILE, JSON.stringify({ tasks }, null, 2));
|
||||
}
|
||||
|
||||
@ -697,7 +703,7 @@ export async function clearAllTasks(): Promise<{
|
||||
const backupFileName = `tasks_memory_${timestamp}.json`;
|
||||
|
||||
// 確保 memory 目錄存在
|
||||
const MEMORY_DIR = path.join(DATA_DIR, "memory");
|
||||
const MEMORY_DIR = await getMemoryDir();
|
||||
try {
|
||||
await fs.access(MEMORY_DIR);
|
||||
} catch (error) {
|
||||
@ -751,7 +757,7 @@ export async function searchTasksWithCommand(
|
||||
let memoryTasks: Task[] = [];
|
||||
|
||||
// 搜尋記憶資料夾中的任務
|
||||
const MEMORY_DIR = path.join(DATA_DIR, "memory");
|
||||
const MEMORY_DIR = await getMemoryDir();
|
||||
|
||||
try {
|
||||
// 確保記憶資料夾存在
|
||||
|
@ -23,10 +23,14 @@ export interface AnalyzeTaskPromptParams {
|
||||
* @param params prompt 參數
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export function getAnalyzeTaskPrompt(params: AnalyzeTaskPromptParams): string {
|
||||
const indexTemplate = loadPromptFromTemplate("analyzeTask/index.md");
|
||||
export async function getAnalyzeTaskPrompt(
|
||||
params: AnalyzeTaskPromptParams
|
||||
): Promise<string> {
|
||||
const indexTemplate = await loadPromptFromTemplate("analyzeTask/index.md");
|
||||
|
||||
const iterationTemplate = loadPromptFromTemplate("analyzeTask/iteration.md");
|
||||
const iterationTemplate = await loadPromptFromTemplate(
|
||||
"analyzeTask/iteration.md"
|
||||
);
|
||||
|
||||
let iterationPrompt = "";
|
||||
if (params.previousAnalysis) {
|
||||
|
@ -25,20 +25,24 @@ export interface ClearAllTasksPromptParams {
|
||||
* @param params prompt 參數
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export function getClearAllTasksPrompt(
|
||||
export async function getClearAllTasksPrompt(
|
||||
params: ClearAllTasksPromptParams
|
||||
): string {
|
||||
): Promise<string> {
|
||||
const { confirm, success, message, backupFile, isEmpty } = params;
|
||||
|
||||
// 處理未確認的情況
|
||||
if (confirm === false) {
|
||||
const cancelTemplate = loadPromptFromTemplate("clearAllTasks/cancel.md");
|
||||
const cancelTemplate = await loadPromptFromTemplate(
|
||||
"clearAllTasks/cancel.md"
|
||||
);
|
||||
return generatePrompt(cancelTemplate, {});
|
||||
}
|
||||
|
||||
// 處理無任務需要清除的情況
|
||||
if (isEmpty) {
|
||||
const emptyTemplate = loadPromptFromTemplate("clearAllTasks/empty.md");
|
||||
const emptyTemplate = await loadPromptFromTemplate(
|
||||
"clearAllTasks/empty.md"
|
||||
);
|
||||
return generatePrompt(emptyTemplate, {});
|
||||
}
|
||||
|
||||
@ -47,12 +51,15 @@ export function getClearAllTasksPrompt(
|
||||
|
||||
// 使用模板生成 backupInfo
|
||||
const backupInfo = backupFile
|
||||
? generatePrompt(loadPromptFromTemplate("clearAllTasks/backupInfo.md"), {
|
||||
backupFile,
|
||||
})
|
||||
? generatePrompt(
|
||||
await loadPromptFromTemplate("clearAllTasks/backupInfo.md"),
|
||||
{
|
||||
backupFile,
|
||||
}
|
||||
)
|
||||
: "";
|
||||
|
||||
const indexTemplate = loadPromptFromTemplate("clearAllTasks/index.md");
|
||||
const indexTemplate = await loadPromptFromTemplate("clearAllTasks/index.md");
|
||||
const prompt = generatePrompt(indexTemplate, {
|
||||
responseTitle,
|
||||
message,
|
||||
|
@ -23,12 +23,12 @@ export interface CompleteTaskPromptParams {
|
||||
* @param params prompt 參數
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export function getCompleteTaskPrompt(
|
||||
export async function getCompleteTaskPrompt(
|
||||
params: CompleteTaskPromptParams
|
||||
): string {
|
||||
): Promise<string> {
|
||||
const { task, completionTime } = params;
|
||||
|
||||
const indexTemplate = loadPromptFromTemplate("completeTask/index.md");
|
||||
const indexTemplate = await loadPromptFromTemplate("completeTask/index.md");
|
||||
|
||||
// 開始構建基本 prompt
|
||||
let prompt = generatePrompt(indexTemplate, {
|
||||
|
@ -26,12 +26,16 @@ export interface DeleteTaskPromptParams {
|
||||
* @param params prompt 參數
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export function getDeleteTaskPrompt(params: DeleteTaskPromptParams): string {
|
||||
export async function getDeleteTaskPrompt(
|
||||
params: DeleteTaskPromptParams
|
||||
): Promise<string> {
|
||||
const { taskId, task, success, message, isTaskCompleted } = params;
|
||||
|
||||
// 處理任務不存在的情況
|
||||
if (!task) {
|
||||
const notFoundTemplate = loadPromptFromTemplate("deleteTask/notFound.md");
|
||||
const notFoundTemplate = await loadPromptFromTemplate(
|
||||
"deleteTask/notFound.md"
|
||||
);
|
||||
return generatePrompt(notFoundTemplate, {
|
||||
taskId,
|
||||
});
|
||||
@ -39,7 +43,9 @@ export function getDeleteTaskPrompt(params: DeleteTaskPromptParams): string {
|
||||
|
||||
// 處理任務已完成的情況
|
||||
if (isTaskCompleted) {
|
||||
const completedTemplate = loadPromptFromTemplate("deleteTask/completed.md");
|
||||
const completedTemplate = await loadPromptFromTemplate(
|
||||
"deleteTask/completed.md"
|
||||
);
|
||||
return generatePrompt(completedTemplate, {
|
||||
taskId: task.id,
|
||||
taskName: task.name,
|
||||
@ -48,7 +54,7 @@ export function getDeleteTaskPrompt(params: DeleteTaskPromptParams): string {
|
||||
|
||||
// 處理刪除成功或失敗的情況
|
||||
const responseTitle = success ? "Success" : "Failure";
|
||||
const indexTemplate = loadPromptFromTemplate("deleteTask/index.md");
|
||||
const indexTemplate = await loadPromptFromTemplate("deleteTask/index.md");
|
||||
const prompt = generatePrompt(indexTemplate, {
|
||||
responseTitle,
|
||||
message,
|
||||
|
@ -55,11 +55,13 @@ function getComplexityStyle(level: string): string {
|
||||
* @param params prompt 參數
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export function getExecuteTaskPrompt(params: ExecuteTaskPromptParams): string {
|
||||
export async function getExecuteTaskPrompt(
|
||||
params: ExecuteTaskPromptParams
|
||||
): Promise<string> {
|
||||
const { task, complexityAssessment, relatedFilesSummary, dependencyTasks } =
|
||||
params;
|
||||
|
||||
const notesTemplate = loadPromptFromTemplate("executeTask/notes.md");
|
||||
const notesTemplate = await loadPromptFromTemplate("executeTask/notes.md");
|
||||
let notesPrompt = "";
|
||||
if (task.notes) {
|
||||
notesPrompt = generatePrompt(notesTemplate, {
|
||||
@ -67,7 +69,7 @@ export function getExecuteTaskPrompt(params: ExecuteTaskPromptParams): string {
|
||||
});
|
||||
}
|
||||
|
||||
const implementationGuideTemplate = loadPromptFromTemplate(
|
||||
const implementationGuideTemplate = await loadPromptFromTemplate(
|
||||
"executeTask/implementationGuide.md"
|
||||
);
|
||||
let implementationGuidePrompt = "";
|
||||
@ -77,7 +79,7 @@ export function getExecuteTaskPrompt(params: ExecuteTaskPromptParams): string {
|
||||
});
|
||||
}
|
||||
|
||||
const verificationCriteriaTemplate = loadPromptFromTemplate(
|
||||
const verificationCriteriaTemplate = await loadPromptFromTemplate(
|
||||
"executeTask/verificationCriteria.md"
|
||||
);
|
||||
let verificationCriteriaPrompt = "";
|
||||
@ -87,7 +89,7 @@ export function getExecuteTaskPrompt(params: ExecuteTaskPromptParams): string {
|
||||
});
|
||||
}
|
||||
|
||||
const analysisResultTemplate = loadPromptFromTemplate(
|
||||
const analysisResultTemplate = await loadPromptFromTemplate(
|
||||
"executeTask/analysisResult.md"
|
||||
);
|
||||
let analysisResultPrompt = "";
|
||||
@ -97,7 +99,7 @@ export function getExecuteTaskPrompt(params: ExecuteTaskPromptParams): string {
|
||||
});
|
||||
}
|
||||
|
||||
const dependencyTasksTemplate = loadPromptFromTemplate(
|
||||
const dependencyTasksTemplate = await loadPromptFromTemplate(
|
||||
"executeTask/dependencyTasks.md"
|
||||
);
|
||||
let dependencyTasksPrompt = "";
|
||||
@ -119,7 +121,7 @@ export function getExecuteTaskPrompt(params: ExecuteTaskPromptParams): string {
|
||||
}
|
||||
}
|
||||
|
||||
const relatedFilesSummaryTemplate = loadPromptFromTemplate(
|
||||
const relatedFilesSummaryTemplate = await loadPromptFromTemplate(
|
||||
"executeTask/relatedFilesSummary.md"
|
||||
);
|
||||
let relatedFilesSummaryPrompt = "";
|
||||
@ -127,7 +129,7 @@ export function getExecuteTaskPrompt(params: ExecuteTaskPromptParams): string {
|
||||
relatedFilesSummary: relatedFilesSummary || "當前任務沒有關聯的文件。",
|
||||
});
|
||||
|
||||
const complexityTemplate = loadPromptFromTemplate(
|
||||
const complexityTemplate = await loadPromptFromTemplate(
|
||||
"executeTask/complexity.md"
|
||||
);
|
||||
let complexityPrompt = "";
|
||||
@ -151,7 +153,7 @@ export function getExecuteTaskPrompt(params: ExecuteTaskPromptParams): string {
|
||||
});
|
||||
}
|
||||
|
||||
const indexTemplate = loadPromptFromTemplate("executeTask/index.md");
|
||||
const indexTemplate = await loadPromptFromTemplate("executeTask/index.md");
|
||||
let prompt = generatePrompt(indexTemplate, {
|
||||
name: task.name,
|
||||
id: task.id,
|
||||
|
@ -24,14 +24,16 @@ export interface GetTaskDetailPromptParams {
|
||||
* @param params prompt 參數
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export function getGetTaskDetailPrompt(
|
||||
export async function getGetTaskDetailPrompt(
|
||||
params: GetTaskDetailPromptParams
|
||||
): string {
|
||||
): Promise<string> {
|
||||
const { taskId, task, error } = params;
|
||||
|
||||
// 如果有錯誤,顯示錯誤訊息
|
||||
if (error) {
|
||||
const errorTemplate = loadPromptFromTemplate("getTaskDetail/error.md");
|
||||
const errorTemplate = await loadPromptFromTemplate(
|
||||
"getTaskDetail/error.md"
|
||||
);
|
||||
return generatePrompt(errorTemplate, {
|
||||
errorMessage: error,
|
||||
});
|
||||
@ -39,7 +41,7 @@ export function getGetTaskDetailPrompt(
|
||||
|
||||
// 如果找不到任務,顯示找不到任務的訊息
|
||||
if (!task) {
|
||||
const notFoundTemplate = loadPromptFromTemplate(
|
||||
const notFoundTemplate = await loadPromptFromTemplate(
|
||||
"getTaskDetail/notFound.md"
|
||||
);
|
||||
return generatePrompt(notFoundTemplate, {
|
||||
@ -49,7 +51,9 @@ export function getGetTaskDetailPrompt(
|
||||
|
||||
let notesPrompt = "";
|
||||
if (task.notes) {
|
||||
const notesTemplate = loadPromptFromTemplate("getTaskDetail/notes.md");
|
||||
const notesTemplate = await loadPromptFromTemplate(
|
||||
"getTaskDetail/notes.md"
|
||||
);
|
||||
notesPrompt = generatePrompt(notesTemplate, {
|
||||
notes: task.notes,
|
||||
});
|
||||
@ -57,7 +61,7 @@ export function getGetTaskDetailPrompt(
|
||||
|
||||
let dependenciesPrompt = "";
|
||||
if (task.dependencies && task.dependencies.length > 0) {
|
||||
const dependenciesTemplate = loadPromptFromTemplate(
|
||||
const dependenciesTemplate = await loadPromptFromTemplate(
|
||||
"getTaskDetail/dependencies.md"
|
||||
);
|
||||
dependenciesPrompt = generatePrompt(dependenciesTemplate, {
|
||||
@ -69,7 +73,7 @@ export function getGetTaskDetailPrompt(
|
||||
|
||||
let implementationGuidePrompt = "";
|
||||
if (task.implementationGuide) {
|
||||
const implementationGuideTemplate = loadPromptFromTemplate(
|
||||
const implementationGuideTemplate = await loadPromptFromTemplate(
|
||||
"getTaskDetail/implementationGuide.md"
|
||||
);
|
||||
implementationGuidePrompt = generatePrompt(implementationGuideTemplate, {
|
||||
@ -79,7 +83,7 @@ export function getGetTaskDetailPrompt(
|
||||
|
||||
let verificationCriteriaPrompt = "";
|
||||
if (task.verificationCriteria) {
|
||||
const verificationCriteriaTemplate = loadPromptFromTemplate(
|
||||
const verificationCriteriaTemplate = await loadPromptFromTemplate(
|
||||
"getTaskDetail/verificationCriteria.md"
|
||||
);
|
||||
verificationCriteriaPrompt = generatePrompt(verificationCriteriaTemplate, {
|
||||
@ -89,7 +93,7 @@ export function getGetTaskDetailPrompt(
|
||||
|
||||
let relatedFilesPrompt = "";
|
||||
if (task.relatedFiles && task.relatedFiles.length > 0) {
|
||||
const relatedFilesTemplate = loadPromptFromTemplate(
|
||||
const relatedFilesTemplate = await loadPromptFromTemplate(
|
||||
"getTaskDetail/relatedFiles.md"
|
||||
);
|
||||
relatedFilesPrompt = generatePrompt(relatedFilesTemplate, {
|
||||
@ -106,7 +110,7 @@ export function getGetTaskDetailPrompt(
|
||||
|
||||
let complatedSummaryPrompt = "";
|
||||
if (task.completedAt) {
|
||||
const complatedSummaryTemplate = loadPromptFromTemplate(
|
||||
const complatedSummaryTemplate = await loadPromptFromTemplate(
|
||||
"getTaskDetail/complatedSummary.md"
|
||||
);
|
||||
complatedSummaryPrompt = generatePrompt(complatedSummaryTemplate, {
|
||||
@ -115,7 +119,7 @@ export function getGetTaskDetailPrompt(
|
||||
});
|
||||
}
|
||||
|
||||
const indexTemplate = loadPromptFromTemplate("getTaskDetail/index.md");
|
||||
const indexTemplate = await loadPromptFromTemplate("getTaskDetail/index.md");
|
||||
|
||||
// 開始構建基本 prompt
|
||||
let prompt = generatePrompt(indexTemplate, {
|
||||
|
@ -3,12 +3,7 @@
|
||||
* 負責將模板和參數組合成最終的 prompt
|
||||
*/
|
||||
|
||||
import {
|
||||
loadPrompt,
|
||||
generatePrompt,
|
||||
loadPromptFromTemplate,
|
||||
} from "../loader.js";
|
||||
import { getRulesFilePath } from "../../utils/pathUtils.js";
|
||||
import { loadPrompt, loadPromptFromTemplate } from "../loader.js";
|
||||
/**
|
||||
* initProjectRules prompt 參數介面
|
||||
*/
|
||||
@ -21,16 +16,13 @@ export interface InitProjectRulesPromptParams {
|
||||
* @param params prompt 參數(可選)
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export function getInitProjectRulesPrompt(
|
||||
export async function getInitProjectRulesPrompt(
|
||||
params?: InitProjectRulesPromptParams
|
||||
): string {
|
||||
// 使用基本模板
|
||||
const rulesPath = getRulesFilePath();
|
||||
const indexTemplate = loadPromptFromTemplate("initProjectRules/index.md");
|
||||
const basePrompt = generatePrompt(indexTemplate, {
|
||||
rulesPath,
|
||||
});
|
||||
): Promise<string> {
|
||||
const indexTemplate = await loadPromptFromTemplate(
|
||||
"initProjectRules/index.md"
|
||||
);
|
||||
|
||||
// 載入可能的自定義 prompt (通過環境變數覆蓋或追加)
|
||||
return loadPrompt(basePrompt, "INIT_PROJECT_RULES");
|
||||
return loadPrompt(indexTemplate, "INIT_PROJECT_RULES");
|
||||
}
|
||||
|
@ -24,12 +24,16 @@ export interface ListTasksPromptParams {
|
||||
* @param params prompt 參數
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export function getListTasksPrompt(params: ListTasksPromptParams): string {
|
||||
export async function getListTasksPrompt(
|
||||
params: ListTasksPromptParams
|
||||
): Promise<string> {
|
||||
const { status, tasks, allTasks } = params;
|
||||
|
||||
// 如果沒有任務,顯示通知
|
||||
if (allTasks.length === 0) {
|
||||
const notFoundTemplate = loadPromptFromTemplate("listTasks/notFound.md");
|
||||
const notFoundTemplate = await loadPromptFromTemplate(
|
||||
"listTasks/notFound.md"
|
||||
);
|
||||
const statusText = status === "all" ? "任何" : `任何 ${status} 的`;
|
||||
return generatePrompt(notFoundTemplate, {
|
||||
statusText: statusText,
|
||||
@ -58,7 +62,9 @@ export function getListTasksPrompt(params: ListTasksPromptParams): string {
|
||||
}
|
||||
|
||||
let taskDetails = "";
|
||||
let taskDetailsTemplate = loadPromptFromTemplate("listTasks/taskDetails.md");
|
||||
let taskDetailsTemplate = await loadPromptFromTemplate(
|
||||
"listTasks/taskDetails.md"
|
||||
);
|
||||
// 添加每個狀態下的詳細任務
|
||||
for (const statusType of Object.values(TaskStatus)) {
|
||||
const tasksWithStatus = tasks[statusType] || [];
|
||||
@ -88,7 +94,7 @@ export function getListTasksPrompt(params: ListTasksPromptParams): string {
|
||||
}
|
||||
}
|
||||
|
||||
const indexTemplate = loadPromptFromTemplate("listTasks/index.md");
|
||||
const indexTemplate = await loadPromptFromTemplate("listTasks/index.md");
|
||||
let prompt = generatePrompt(indexTemplate, {
|
||||
statusCount: statusCounts,
|
||||
taskDetailsTemplate: taskDetails,
|
||||
|
@ -8,7 +8,6 @@ import {
|
||||
generatePrompt,
|
||||
loadPromptFromTemplate,
|
||||
} from "../loader.js";
|
||||
import { getRulesFilePath } from "../../utils/pathUtils.js";
|
||||
import { Task, TaskDependency } from "../../types/index.js";
|
||||
|
||||
/**
|
||||
@ -28,7 +27,9 @@ export interface PlanTaskPromptParams {
|
||||
* @param params prompt 參數
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export function getPlanTaskPrompt(params: PlanTaskPromptParams): string {
|
||||
export async function getPlanTaskPrompt(
|
||||
params: PlanTaskPromptParams
|
||||
): Promise<string> {
|
||||
let tasksContent = "";
|
||||
if (
|
||||
params.existingTasksReference &&
|
||||
@ -102,7 +103,7 @@ export function getPlanTaskPrompt(params: PlanTaskPromptParams): string {
|
||||
});
|
||||
}
|
||||
|
||||
const tasksTemplate = loadPromptFromTemplate("planTask/tasks.md");
|
||||
const tasksTemplate = await loadPromptFromTemplate("planTask/tasks.md");
|
||||
tasksContent = generatePrompt(tasksTemplate, {
|
||||
completedTasks: completeTasksContent,
|
||||
unfinishedTasks: unfinishedTasksContent,
|
||||
@ -112,17 +113,16 @@ export function getPlanTaskPrompt(params: PlanTaskPromptParams): string {
|
||||
|
||||
let thoughtTemplate = "";
|
||||
if (process.env.ENABLE_THOUGHT_CHAIN !== "false") {
|
||||
thoughtTemplate = loadPromptFromTemplate("planTask/hasThought.md");
|
||||
thoughtTemplate = await loadPromptFromTemplate("planTask/hasThought.md");
|
||||
} else {
|
||||
thoughtTemplate = loadPromptFromTemplate("planTask/noThought.md");
|
||||
thoughtTemplate = await loadPromptFromTemplate("planTask/noThought.md");
|
||||
}
|
||||
const rulesPath = getRulesFilePath();
|
||||
const indexTemplate = loadPromptFromTemplate("planTask/index.md");
|
||||
const indexTemplate = await loadPromptFromTemplate("planTask/index.md");
|
||||
let prompt = generatePrompt(indexTemplate, {
|
||||
description: params.description,
|
||||
requirements: params.requirements || "No requirements",
|
||||
tasksTemplate: tasksContent,
|
||||
rulesPath: rulesPath,
|
||||
rulesPath: "shrimp-rules.md",
|
||||
memoryDir: params.memoryDir,
|
||||
thoughtTemplate: thoughtTemplate,
|
||||
});
|
||||
|
@ -15,19 +15,21 @@ export interface ProcessThoughtPromptParams {
|
||||
assumptions_challenged: string[];
|
||||
}
|
||||
|
||||
export function getProcessThoughtPrompt(
|
||||
export async function getProcessThoughtPrompt(
|
||||
param: ProcessThoughtPromptParams
|
||||
): string {
|
||||
): Promise<string> {
|
||||
let nextThoughtNeeded = "";
|
||||
if (param.nextThoughtNeeded) {
|
||||
nextThoughtNeeded = loadPromptFromTemplate("processThought/moreThought.md");
|
||||
nextThoughtNeeded = await loadPromptFromTemplate(
|
||||
"processThought/moreThought.md"
|
||||
);
|
||||
} else {
|
||||
nextThoughtNeeded = loadPromptFromTemplate(
|
||||
nextThoughtNeeded = await loadPromptFromTemplate(
|
||||
"processThought/complatedThought.md"
|
||||
);
|
||||
}
|
||||
|
||||
const indexTemplate = loadPromptFromTemplate("processThought/index.md");
|
||||
const indexTemplate = await loadPromptFromTemplate("processThought/index.md");
|
||||
|
||||
const prompt = generatePrompt(indexTemplate, {
|
||||
thought: param.thought,
|
||||
|
@ -28,17 +28,21 @@ export interface QueryTaskPromptParams {
|
||||
* @param params prompt 參數
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export function getQueryTaskPrompt(params: QueryTaskPromptParams): string {
|
||||
export async function getQueryTaskPrompt(
|
||||
params: QueryTaskPromptParams
|
||||
): Promise<string> {
|
||||
const { query, isId, tasks, totalTasks, page, pageSize, totalPages } = params;
|
||||
|
||||
if (tasks.length === 0) {
|
||||
const notFoundTemplate = loadPromptFromTemplate("queryTask/notFound.md");
|
||||
const notFoundTemplate = await loadPromptFromTemplate(
|
||||
"queryTask/notFound.md"
|
||||
);
|
||||
return generatePrompt(notFoundTemplate, {
|
||||
query,
|
||||
});
|
||||
}
|
||||
|
||||
const taskDetailsTemplate = loadPromptFromTemplate(
|
||||
const taskDetailsTemplate = await loadPromptFromTemplate(
|
||||
"queryTask/taskDetails.md"
|
||||
);
|
||||
let tasksContent = "";
|
||||
@ -55,7 +59,7 @@ export function getQueryTaskPrompt(params: QueryTaskPromptParams): string {
|
||||
});
|
||||
}
|
||||
|
||||
const indexTemplate = loadPromptFromTemplate("queryTask/index.md");
|
||||
const indexTemplate = await loadPromptFromTemplate("queryTask/index.md");
|
||||
const prompt = generatePrompt(indexTemplate, {
|
||||
tasksContent,
|
||||
page,
|
||||
|
@ -22,8 +22,10 @@ export interface ReflectTaskPromptParams {
|
||||
* @param params prompt 參數
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export function getReflectTaskPrompt(params: ReflectTaskPromptParams): string {
|
||||
const indexTemplate = loadPromptFromTemplate("reflectTask/index.md");
|
||||
export async function getReflectTaskPrompt(
|
||||
params: ReflectTaskPromptParams
|
||||
): Promise<string> {
|
||||
const indexTemplate = await loadPromptFromTemplate("reflectTask/index.md");
|
||||
const prompt = generatePrompt(indexTemplate, {
|
||||
summary: params.summary,
|
||||
analysis: params.analysis,
|
||||
|
57
src/prompts/generators/researchMode.ts
Normal file
57
src/prompts/generators/researchMode.ts
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* researchMode prompt 生成器
|
||||
* 負責將模板和參數組合成最終的 prompt
|
||||
*/
|
||||
|
||||
import {
|
||||
loadPrompt,
|
||||
generatePrompt,
|
||||
loadPromptFromTemplate,
|
||||
} from "../loader.js";
|
||||
|
||||
/**
|
||||
* researchMode prompt 參數介面
|
||||
*/
|
||||
export interface ResearchModePromptParams {
|
||||
topic: string;
|
||||
previousState: string;
|
||||
currentState: string;
|
||||
nextSteps: string;
|
||||
memoryDir: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 獲取 researchMode 的完整 prompt
|
||||
* @param params prompt 參數
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export async function getResearchModePrompt(
|
||||
params: ResearchModePromptParams
|
||||
): Promise<string> {
|
||||
// 處理之前的研究狀態
|
||||
let previousStateContent = "";
|
||||
if (params.previousState && params.previousState.trim() !== "") {
|
||||
const previousStateTemplate = await loadPromptFromTemplate(
|
||||
"researchMode/previousState.md"
|
||||
);
|
||||
previousStateContent = generatePrompt(previousStateTemplate, {
|
||||
previousState: params.previousState,
|
||||
});
|
||||
} else {
|
||||
previousStateContent = "這是第一次進行此主題的研究,沒有之前的研究狀態。";
|
||||
}
|
||||
|
||||
// 載入主要模板
|
||||
const indexTemplate = await loadPromptFromTemplate("researchMode/index.md");
|
||||
let prompt = generatePrompt(indexTemplate, {
|
||||
topic: params.topic,
|
||||
previousStateContent: previousStateContent,
|
||||
currentState: params.currentState,
|
||||
nextSteps: params.nextSteps,
|
||||
memoryDir: params.memoryDir,
|
||||
time: new Date().toLocaleString(),
|
||||
});
|
||||
|
||||
// 載入可能的自定義 prompt
|
||||
return loadPrompt(prompt, "RESEARCH_MODE");
|
||||
}
|
@ -24,8 +24,10 @@ export interface SplitTasksPromptParams {
|
||||
* @param params prompt 參數
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export function getSplitTasksPrompt(params: SplitTasksPromptParams): string {
|
||||
const taskDetailsTemplate = loadPromptFromTemplate(
|
||||
export async function getSplitTasksPrompt(
|
||||
params: SplitTasksPromptParams
|
||||
): Promise<string> {
|
||||
const taskDetailsTemplate = await loadPromptFromTemplate(
|
||||
"splitTasks/taskDetails.md"
|
||||
);
|
||||
|
||||
@ -72,7 +74,7 @@ export function getSplitTasksPrompt(params: SplitTasksPromptParams): string {
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
const indexTemplate = loadPromptFromTemplate("splitTasks/index.md");
|
||||
const indexTemplate = await loadPromptFromTemplate("splitTasks/index.md");
|
||||
const prompt = generatePrompt(indexTemplate, {
|
||||
updateMode: params.updateMode,
|
||||
tasksContent,
|
||||
|
@ -28,9 +28,9 @@ export interface UpdateTaskContentPromptParams {
|
||||
* @param params prompt 參數
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export function getUpdateTaskContentPrompt(
|
||||
export async function getUpdateTaskContentPrompt(
|
||||
params: UpdateTaskContentPromptParams
|
||||
): string {
|
||||
): Promise<string> {
|
||||
const {
|
||||
taskId,
|
||||
task,
|
||||
@ -43,7 +43,7 @@ export function getUpdateTaskContentPrompt(
|
||||
|
||||
// 處理任務不存在的情況
|
||||
if (!task) {
|
||||
const notFoundTemplate = loadPromptFromTemplate(
|
||||
const notFoundTemplate = await loadPromptFromTemplate(
|
||||
"updateTaskContent/notFound.md"
|
||||
);
|
||||
return generatePrompt(notFoundTemplate, {
|
||||
@ -53,7 +53,7 @@ export function getUpdateTaskContentPrompt(
|
||||
|
||||
// 處理驗證錯誤的情況
|
||||
if (validationError) {
|
||||
const validationTemplate = loadPromptFromTemplate(
|
||||
const validationTemplate = await loadPromptFromTemplate(
|
||||
"updateTaskContent/validation.md"
|
||||
);
|
||||
return generatePrompt(validationTemplate, {
|
||||
@ -63,7 +63,7 @@ export function getUpdateTaskContentPrompt(
|
||||
|
||||
// 處理空更新的情況
|
||||
if (emptyUpdate) {
|
||||
const emptyUpdateTemplate = loadPromptFromTemplate(
|
||||
const emptyUpdateTemplate = await loadPromptFromTemplate(
|
||||
"updateTaskContent/emptyUpdate.md"
|
||||
);
|
||||
return generatePrompt(emptyUpdateTemplate, {});
|
||||
@ -75,14 +75,14 @@ export function getUpdateTaskContentPrompt(
|
||||
|
||||
// 更新成功且有更新後的任務詳情
|
||||
if (success && updatedTask) {
|
||||
const successTemplate = loadPromptFromTemplate(
|
||||
const successTemplate = await loadPromptFromTemplate(
|
||||
"updateTaskContent/success.md"
|
||||
);
|
||||
|
||||
// 編合相關文件信息
|
||||
let filesContent = "";
|
||||
if (updatedTask.relatedFiles && updatedTask.relatedFiles.length > 0) {
|
||||
const fileDetailsTemplate = loadPromptFromTemplate(
|
||||
const fileDetailsTemplate = await loadPromptFromTemplate(
|
||||
"updateTaskContent/fileDetails.md"
|
||||
);
|
||||
|
||||
@ -130,7 +130,9 @@ export function getUpdateTaskContentPrompt(
|
||||
});
|
||||
}
|
||||
|
||||
const indexTemplate = loadPromptFromTemplate("updateTaskContent/index.md");
|
||||
const indexTemplate = await loadPromptFromTemplate(
|
||||
"updateTaskContent/index.md"
|
||||
);
|
||||
const prompt = generatePrompt(indexTemplate, {
|
||||
responseTitle,
|
||||
message: content,
|
||||
|
@ -44,10 +44,12 @@ function extractSummary(
|
||||
* @param params prompt 參數
|
||||
* @returns 生成的 prompt
|
||||
*/
|
||||
export function getVerifyTaskPrompt(params: VerifyTaskPromptParams): string {
|
||||
export async function getVerifyTaskPrompt(
|
||||
params: VerifyTaskPromptParams
|
||||
): Promise<string> {
|
||||
const { task, score, summary } = params;
|
||||
if (score < 80) {
|
||||
const noPassTemplate = loadPromptFromTemplate("verifyTask/noPass.md");
|
||||
const noPassTemplate = await loadPromptFromTemplate("verifyTask/noPass.md");
|
||||
const prompt = generatePrompt(noPassTemplate, {
|
||||
name: task.name,
|
||||
id: task.id,
|
||||
@ -55,7 +57,7 @@ export function getVerifyTaskPrompt(params: VerifyTaskPromptParams): string {
|
||||
});
|
||||
return prompt;
|
||||
}
|
||||
const indexTemplate = loadPromptFromTemplate("verifyTask/index.md");
|
||||
const indexTemplate = await loadPromptFromTemplate("verifyTask/index.md");
|
||||
const prompt = generatePrompt(indexTemplate, {
|
||||
name: task.name,
|
||||
id: task.id,
|
||||
|
@ -22,3 +22,4 @@ export { getInitProjectRulesPrompt } from "./generators/initProjectRules.js";
|
||||
export { getDeleteTaskPrompt } from "./generators/deleteTask.js";
|
||||
export { getClearAllTasksPrompt } from "./generators/clearAllTasks.js";
|
||||
export { getUpdateTaskContentPrompt } from "./generators/updateTaskContent.js";
|
||||
export { getResearchModePrompt } from "./generators/researchMode.js";
|
||||
|
@ -6,6 +6,7 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { getDataDir } from "../utils/paths.js";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
@ -79,22 +80,22 @@ export function generatePrompt(
|
||||
* @returns 模板內容
|
||||
* @throws Error 如果找不到模板文件
|
||||
*/
|
||||
export function loadPromptFromTemplate(templatePath: string): string {
|
||||
export async function loadPromptFromTemplate(
|
||||
templatePath: string
|
||||
): Promise<string> {
|
||||
const templateSetName = process.env.TEMPLATES_USE || "en";
|
||||
const dataDir = process.env.DATA_DIR;
|
||||
const dataDir = await getDataDir();
|
||||
const builtInTemplatesBaseDir = __dirname;
|
||||
|
||||
let finalPath = "";
|
||||
const checkedPaths: string[] = []; // 用於更詳細的錯誤報告
|
||||
|
||||
// 1. 檢查 DATA_DIR 中的自定義路徑
|
||||
if (dataDir) {
|
||||
// path.resolve 可以處理 templateSetName 是絕對路徑的情況
|
||||
const customFilePath = path.resolve(dataDir, templateSetName, templatePath);
|
||||
checkedPaths.push(`Custom: ${customFilePath}`);
|
||||
if (fs.existsSync(customFilePath)) {
|
||||
finalPath = customFilePath;
|
||||
}
|
||||
// path.resolve 可以處理 templateSetName 是絕對路徑的情況
|
||||
const customFilePath = path.resolve(dataDir, templateSetName, templatePath);
|
||||
checkedPaths.push(`Custom: ${customFilePath}`);
|
||||
if (fs.existsSync(customFilePath)) {
|
||||
finalPath = customFilePath;
|
||||
}
|
||||
|
||||
// 2. 如果未找到自定義路徑,檢查特定的內建模板目錄
|
||||
|
@ -35,4 +35,5 @@
|
||||
- **Code Quality** - Comply with coding standards, handle exceptions
|
||||
- **Performance Considerations** - Pay attention to algorithm efficiency and resource usage
|
||||
|
||||
Begin executing the task according to instructions, and use the "verify_task" tool for verification after completion.
|
||||
Begin executing the task according to the instructions. After completing the task, call the verify_task tool to perform verification.
|
||||
**Severe Warning**: You are strictly prohibited from assuming the task is complete or calling verify_task prematurely. You must use edit_file or any other available tools necessary to actually complete the task.
|
||||
|
@ -5,7 +5,7 @@ Please use the "process_thought" tool to consider the following issues
|
||||
## Purpose
|
||||
|
||||
**This document is specifically designed for AI Agents, not for general developer documentation.**
|
||||
**Must generate a project standards document (rules.md) exclusively for AI Agent operational use.**
|
||||
**Must generate a project standards document (shrimp-rules.md) exclusively for AI Agent operational use.**
|
||||
|
||||
**Must focus on the following key objectives:**
|
||||
|
||||
@ -72,10 +72,10 @@ The standards document should include but not be limited to the following:
|
||||
1. **Minimal Changes** - When users request updates to project rules, you should maintain existing rules unless necessary, with the principle of minimal changes
|
||||
2. **Timeliness** - You should check if existing rules are still beneficial or outdated, as users may have modified or removed relevant code, you must correct or remove corresponding rules
|
||||
3. **Completeness** - You should check all folders and file contents in the existing project, as users may have added or modified relevant code, you must supplement corresponding rules
|
||||
4. **Autonomous Handling of Ambiguous Requests**: When receiving ambiguous instructions such as "update rules" without specifying concrete content, the AI **must** first attempt to independently analyze the current codebase, recent changes (if available), and existing `rules.md` content to infer possible update points. List these inferred points and their rationale during the `process_thought` phase, then propose specific modification suggestions. **Strictly prohibited** from seeking clarification from users on ambiguous update requests before performing this autonomous analysis.
|
||||
4. **Autonomous Handling of Ambiguous Requests**: When receiving ambiguous instructions such as "update rules" without specifying concrete content, the AI **must** first attempt to independently analyze the current codebase, recent changes (if available), and existing `shrimp-rules.md` content to infer possible update points. List these inferred points and their rationale during the `process_thought` phase, then propose specific modification suggestions. **Strictly prohibited** from seeking clarification from users on ambiguous update requests before performing this autonomous analysis.
|
||||
|
||||
Based on the above guidelines, create a file named rules.md and store it at: {rulesPath}
|
||||
Based on the above guidelines, create a file named shrimp-rules.md and save it in the project root directory
|
||||
|
||||
**[AI Agent Action]** Now start calling the "process_thought" tool to think about how to write standards document that guides the Coding Agent
|
||||
**[AI Agent Action]** After completing the thought process, immediately edit the rules.md file, prohibited from calling the "analyze_task" tool
|
||||
**[AI Agent Action]** After completing the thought process, immediately edit the shrimp-rules.md file, prohibited from calling the "analyze_task" tool
|
||||
**[AI Agent Action]** Strictly forbidden not to call tools. The AI must independently complete the entire process from receiving instructions to implementing modifications, and should not interrupt the process to seek user input unless encountering technical errors or unresolvable dependency conflicts.
|
||||
|
@ -19,7 +19,7 @@ You must complete the following sub-steps in sequence, and at the end call the `
|
||||
|
||||
- View key configuration files and structures:
|
||||
- Examine root directory structure and important configuration files (package.json, tsconfig.json, etc.)
|
||||
- If {rulesPath} exists, please read and refer to it in detail
|
||||
- If shrimp-rules.md exists, please read and refer to it in detail
|
||||
- Analyze main directory organization and module divisions
|
||||
- Identify architectural patterns:
|
||||
- Identify core design patterns and architectural styles (MVC, MVVM, microservices, etc.)
|
||||
@ -86,6 +86,7 @@ You must complete the following sub-steps in sequence, and at the end call the `
|
||||
- Ensure the solution is consistent with the project's existing architectural patterns
|
||||
- Explain how to reuse existing components or follow existing patterns
|
||||
- The process must be thought through step by step and organize thoughts; if the problem is too complex, utilize `process_thought` to think
|
||||
- **Critical Warning**: All forms of `assumptions`, `guesses`, and `imagination` are strictly prohibited. You must use every `available tool` at your disposal to `gather real information`.
|
||||
- Call tool:
|
||||
```
|
||||
analyze_task({ summary: <Task Summary>, initialConcept: <Initial Concept> })
|
||||
|
@ -39,6 +39,9 @@ After receiving the solution and suggestions, conduct self-reflection and final
|
||||
- Ensure that the task group after splitting still maintains overall architectural consistency
|
||||
|
||||
7. **Submit Final Results**
|
||||
- **No Comments Allowed**: JSON does not support comments — Any use of `#` or `//` will cause parsing failures
|
||||
- **Proper Escaping Required**: All special characters (e.g., double quotes `\"`, backslashes `\\`) must be properly escaped, or they will be considered invalid.
|
||||
- **Line Breaks**: If you need line breaks, use escape sequences like \\n or \\r. Direct line breaks will cause parsing errors.
|
||||
- Adjusted final solution + reflection report
|
||||
- Call tool:
|
||||
```
|
||||
|
94
src/prompts/templates_en/researchMode/index.md
Normal file
94
src/prompts/templates_en/researchMode/index.md
Normal file
@ -0,0 +1,94 @@
|
||||
# Programming Research Mode
|
||||
|
||||
You are an AI research assistant equipped with web search, codebase file lookup, and library API query capabilities.
|
||||
You are now entering a specialized programming-focused **Research Mode**, similar to the research functions of ChatGPT or Perplexity, but focused on software development.
|
||||
Your mission is to conduct in-depth and comprehensive research and analysis on the **Research Topic**, and ultimately propose a final design solution.
|
||||
|
||||
In **Research Mode**, you should adopt an academic research mindset, maintaining **curiosity** and a **critical attitude** toward all retrieved information.
|
||||
You must **continually search and verify facts**, rather than trusting search results directly.
|
||||
Also, be mindful of the **timeliness** of the information — you are only interested in **the most up-to-date knowledge**.
|
||||
|
||||
Current time: **`{time}`**
|
||||
|
||||
## Research Topic
|
||||
|
||||
**{topic}**
|
||||
|
||||
## Research State Management
|
||||
|
||||
### Previous Research State
|
||||
|
||||
{previousStateContent}
|
||||
|
||||
### Current Execution State
|
||||
|
||||
**Current Task:** {currentState}
|
||||
|
||||
### Next Steps
|
||||
|
||||
**Next Directions:** {nextSteps}
|
||||
|
||||
## Research Guidelines
|
||||
|
||||
### 1. Depth and Breadth Requirements
|
||||
|
||||
- **Deep Exploration**: For every concept, technique, or solution found, use a **search strategy** to dig deeper into its principles, implementation details, pros and cons.
|
||||
- **Broad Exploration**: Use **search strategies** to explore alternatives, competing technologies, and related tools in the ecosystem.
|
||||
- **Continuous Exploration**: Every search result should trigger a desire to further explore, continuing until the topic is sufficiently covered.
|
||||
|
||||
### 2. Search Strategy
|
||||
|
||||
You have the following tools available:
|
||||
|
||||
When searching, keep your **keywords concise and precise**.
|
||||
**Avoid using too many keywords at once**. Limit each search to **2–4 keywords** to **prevent ineffective searches**.
|
||||
Use **multiple searches**, refining the keywords based on previous results.
|
||||
Whenever you feel **curious or uncertain about a search result**, you must **search again** multiple times to validate the content.
|
||||
|
||||
- **Web Search Tools**: For the latest technical info, documentation, tutorials, best practices, such as `web_search` or any web search tool.
|
||||
- **Browser Operation Tools**: For browsing recent documentation or sites, such as `use_browser` or any browser automation tool.
|
||||
- **Code Search Tools**: For searching implementations, patterns, and examples in the existing project, such as `codebase_search`, `read_file`, or any relevant tool.
|
||||
|
||||
### 3. Research Execution Flow
|
||||
|
||||
1. **Understand Current State**: Clearly identify the task at hand.
|
||||
2. **Perform Search**: Use appropriate search tools to collect information.
|
||||
3. **Deep Analysis**: Analyze the results thoroughly and extract key insights.
|
||||
4. **Expand Breadth**: Identify additional directions for exploration based on the analysis.
|
||||
5. **Iterative Exploration**: Repeat the search and analysis process until sufficient information is gathered. Ensure at least 3 rounds of research for quality.
|
||||
6. **Synthesize Summary**: Integrate all findings into a valuable research outcome.
|
||||
|
||||
### 4. Research Quality Standards
|
||||
|
||||
- **Accuracy**: All information must come from reliable sources, avoiding outdated or incorrect content.
|
||||
- **Practicality**: The outcome must be of practical value to software development.
|
||||
- **Completeness**: Cover all critical aspects of the topic without missing key information.
|
||||
- **Timeliness**: Prioritize the most recent technical advancements and best practices.
|
||||
|
||||
### 5. Avoiding Topic Deviation
|
||||
|
||||
- Always remember the **Research Topic**
|
||||
- Ensure all searches and analysis stay relevant to the topic
|
||||
- Refer to **Next Steps** to maintain correct direction
|
||||
|
||||
### 6. Final Report
|
||||
|
||||
When the research is complete, you must generate a detailed research report in **Markdown** format and wait for the user's next instruction.
|
||||
|
||||
## Execution Instructions
|
||||
|
||||
**Immediately begin executing the task described in the Current State**:
|
||||
{currentState}
|
||||
|
||||
Remember:
|
||||
|
||||
- Don’t settle for surface-level results — explore deeper.
|
||||
- After each search, reflect on what else might be worth exploring.
|
||||
- Maintain curiosity for new findings and expand the research scope.
|
||||
- Record important discoveries throughout the process for future state updates.
|
||||
- **Do not guess, hallucinate, or simulate** — all information **must be verified through web search tools**.
|
||||
- Throughout the process, continually call `research_mode` to log progress. **This is important!** You should call `research_mode` again after completing each stage to log detailed findings and determine the next direction.
|
||||
- When you feel the research is complete, generate the **Final Report**.
|
||||
|
||||
**Start the research task now.**
|
||||
**⚠️ Critical Warning: You are only responsible for research, so you are strictly prohibited from using `editing tools` or `plan task`. You must complete your research and provide a final report, then wait for the user's next instruction.**
|
9
src/prompts/templates_en/researchMode/previousState.md
Normal file
9
src/prompts/templates_en/researchMode/previousState.md
Normal file
@ -0,0 +1,9 @@
|
||||
**Previous Research Results Summary:**
|
||||
|
||||
{previousState}
|
||||
|
||||
**Based on previous research, please note:**
|
||||
|
||||
- Avoid repeating content that has already been explored
|
||||
- Deepen or expand based on previous research
|
||||
- If you find information that conflicts with previous research, pay special attention and verify
|
@ -1 +1 @@
|
||||
Execute specific tasks according to the predefined plan, ensuring the output of each step meets quality standards
|
||||
Retrieve the instructional guidance for a specific task. You will complete the programming task based on this guidance. You must strictly follow the feedback and instructions provided by the tool — it is designed to **guide you toward perfect task completion, not to execute the task for you**. Severe Warning: Calling the executeTask tool does not mean you have completed the task. You must follow the step-by-step guidance returned by the tool to complete the task properly.
|
||||
|
@ -1 +1,3 @@
|
||||
Initialize and plan task processes in detail, establish clear goals and success criteria, optionally reference existing tasks for continued planning
|
||||
When you need to plan tasks or construct complex features, you can use this tool to receive task planning guidance. You are expected to strictly follow the step-by-step instructions provided by the tool when organizing your tasks. You may optionally choose to reference existing tasks for extended planning.
|
||||
|
||||
**Critical Warning**: All forms of `assumptions`, `guesses`, and `imagination` are strictly prohibited. You must use every `available tool` at your disposal to `gather real information`.
|
||||
|
@ -0,0 +1 @@
|
||||
When you need to conduct in-depth research on programming-related topics, you can use this tool to enter a specialized research mode. This tool will guide you on how to use web search and code search tools to systematically research technical topics, ensuring research depth and breadth while avoiding topic deviation. Suitable for technical research, best practice exploration, solution comparison, and other scenarios.
|
@ -37,6 +37,15 @@ Break down complex tasks into independent subtasks, establishing dependencies an
|
||||
- Only outline high-level logic and key steps.
|
||||
- Avoid providing complete source code.
|
||||
- Check **dependencies** between subtasks and specify them in the `dependencies` field.
|
||||
- If the task involves interface design, always provide a complete and consistent definition, including:
|
||||
|
||||
- Function/class/schema definitions (including names, parameters, return values)
|
||||
- Data types, usage descriptions, and optional/required status for each item
|
||||
- Error handling methods and expected exception scenarios
|
||||
- Dependency and naming conventions (if any)
|
||||
- Sample data and usage examples
|
||||
|
||||
This ensures consistency, readability, and development precision between tasks.
|
||||
|
||||
## 3. **Dependencies and Prioritization**
|
||||
|
||||
@ -64,3 +73,11 @@ When you need to create a new task that is not related to the current task list,
|
||||
- ### **Proper Escaping Required**
|
||||
All special characters (e.g., double quotes `\"`, backslashes `\\`) must be properly escaped,
|
||||
or they will be considered invalid.
|
||||
|
||||
## 6. **Important Notes**
|
||||
|
||||
These tasks will be executed by low-intelligence models, so please follow the guidelines below:
|
||||
|
||||
- `Clear and Explicit Instructions`: This prevents the model from producing incorrect or inconsistent architecture/code styles. Provide clear commands or specifications.
|
||||
- `Encapsulated Interfaces`: Each task runs independently. Define the interfaces clearly — such as function names, parameters, return values — so that other task-executing models can easily understand how to interact with or integrate these functions.
|
||||
- `Dependencies`: If there are dependencies between tasks, define the interaction interfaces first. Tasks do not need to know each other's implementation, but must know how to interact with one another.
|
||||
|
@ -35,4 +35,5 @@
|
||||
- **代碼質量** - 符合編碼標準,處理異常情況
|
||||
- **效能考量** - 注意算法效率和資源使用
|
||||
|
||||
開始根據指示執行任務,執行完成後請直接使用「verify_task」工具進行驗證。
|
||||
現在開始根據指示執行任務,執行完成後調用「verify_task」工具來進行驗證。
|
||||
**嚴重警告**:禁止假設任務已完成與直接調用「verify_task」,你必須透過「edit_file」或其他一切可以幫助你完成任務的工具來完成任務
|
||||
|
@ -5,7 +5,7 @@
|
||||
## 目的
|
||||
|
||||
**此文件專為 AI Agent 設計,非一般開發者文檔。**
|
||||
**必須生成一個專屬於 AI Agent 操作使用的專案規範文件(rules.md)。**
|
||||
**必須生成一個專屬於 AI Agent 操作使用的專案規範文件(shrimp-rules.md)。**
|
||||
|
||||
**必須專注於以下關鍵目標:**
|
||||
|
||||
@ -72,10 +72,10 @@
|
||||
1. **最小變動** - 當用戶要求更新專案規則時,除非必要否則你應該雹持現有規則,以最小變更為原則的修改
|
||||
2. **時效性** - 你應該檢查有的規則的是否有還效益或過時,因為用戶可能已經修改或移除相關程式,你必須修正或移除相應規則
|
||||
3. **完整性** - 你應該檢查現有專案的所有資料夾及檔案內容,因為用戶可能已經有新增或修改相關程式,你必須補充相應的規則
|
||||
4. **自主處理模糊請求**:當收到如「更新規則」等未指定具體內容的模糊指令時,AI **必須**首先嘗試自主分析當前程式碼庫、近期變更(如果可用)以及現有的 `rules.md` 內容,以推斷可能的更新點。在 `process_thought` 階段列出這些推斷點及其理由,然後再提出具體修改建議。在執行此自主分析之前,**嚴格禁止**就模糊的更新請求向用戶尋求澄清。
|
||||
4. **自主處理模糊請求**:當收到如「更新規則」等未指定具體內容的模糊指令時,AI **必須**首先嘗試自主分析當前程式碼庫、近期變更(如果可用)以及現有的 `shrimp-rules.md` 內容,以推斷可能的更新點。在 `process_thought` 階段列出這些推斷點及其理由,然後再提出具體修改建議。在執行此自主分析之前,**嚴格禁止**就模糊的更新請求向用戶尋求澄清。
|
||||
|
||||
請根據以上指南,創建一個名為 rules.md 的文件並存放於: {rulesPath}
|
||||
請根據以上指南,創建一個名為 shrimp-rules.md 的文件並存放於專案根目錄
|
||||
|
||||
**[AI Agent Action]**現在開始呼叫 「process_thought」 工具思考如何撰寫出教導 Coding Agent 規範文件
|
||||
**[AI Agent Action]**思考完畢後請立即編輯 rules.md 文件,禁止呼叫「analyze_task」工具
|
||||
**[AI Agent Action]**思考完畢後請立即編輯 shrimp-rules.md 文件,禁止呼叫「analyze_task」工具
|
||||
**[AI Agent Action]**嚴禁不呼叫工具。AI 必須自主完成從接收指令到執行修改的完整流程,除非遇到技術錯誤或無法解決的依賴衝突,否則不應中斷流程尋求用戶輸入。
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
- 查看關鍵配置文件與結構:
|
||||
- 檢視根目錄結構和重要配置文件(package.json, tsconfig.json 等)
|
||||
- 如果 {rulesPath} 存在請詳細閱讀並參考
|
||||
- 如果 shrimp-rules.md 存在請詳細閱讀並參考
|
||||
- 分析主要的目錄組織和模組劃分
|
||||
- 辨識架構模式:
|
||||
- 識別核心設計模式和架構風格(MVC, MVVM, 微服務等)
|
||||
@ -86,6 +86,7 @@
|
||||
- 確保方案與專案既有架構模式一致
|
||||
- 說明如何重用現有組件或遵循現有模式
|
||||
- 過程必須一步一步思考並梳理思緒,如果問題過於複雜可以利用`process_thought`來思考
|
||||
- **嚴重警告**:禁止一切`假設`與`猜測`與`幻想`,你必須透過一切你`可以使用的工具`來`收集資訊`
|
||||
- 呼叫工具:
|
||||
```
|
||||
analyze_task({ summary: <任務摘要>, initialConcept: <初步構想> })
|
||||
|
@ -39,8 +39,13 @@
|
||||
- 確保拆分後的任務群組仍維持架構的整體一致性
|
||||
|
||||
7. **提交最終結果**
|
||||
|
||||
- **禁止註解**:JSON 本身不支援註解,任何 `#` 或 `//` 都會導致解析失敗
|
||||
- **注意轉義**:所有特殊字元(如雙引號 `\"`、反斜線 `\\`)必須正確轉義,否則視為非法字元
|
||||
- **換行符號**:如果需要換行請使用跳脫符號`\\n` 或 `\\r`,直接換行會導致解析失敗
|
||||
- 調整後的最終方案 + 反思報告
|
||||
- 呼叫工具:
|
||||
|
||||
```
|
||||
split_tasks( ... )
|
||||
```
|
||||
|
89
src/prompts/templates_zh/researchMode/index.md
Normal file
89
src/prompts/templates_zh/researchMode/index.md
Normal file
@ -0,0 +1,89 @@
|
||||
# 程式編程研究模式
|
||||
|
||||
你是一個擁有網頁搜尋、程式碼檔案查詢和程式庫 API 查詢功能的 AI 研究助理,
|
||||
你現在進入了專門的程式編程`研究模式`,類似於 ChatGPT 或 Perplexity 的研究功能,但專注於程式開發領域。
|
||||
你的任務是針對 【研究主題】 進行深入且全面的調研分析,並提出最終的設計方案。
|
||||
|
||||
在`研究模式`你應該專注於學術研究,必須對搜尋到的資訊保持`好奇心`與`質疑的態度`,你將透過`不斷地搜尋與研究來驗證事實`,而不是直接相信搜尋結果,同時你也要注意`資訊的時效性`,你只對`最新的資訊`有興趣。
|
||||
|
||||
現在時間是:`{time}`
|
||||
|
||||
## 研究主題
|
||||
|
||||
**{topic}**
|
||||
|
||||
## 研究狀態管理
|
||||
|
||||
### 之前的研究狀態
|
||||
|
||||
{previousStateContent}
|
||||
|
||||
### 當前執行狀態
|
||||
|
||||
**當前任務:** {currentState}
|
||||
|
||||
### 下一步計劃
|
||||
|
||||
**後續方向:** {nextSteps}
|
||||
|
||||
## 研究指導原則
|
||||
|
||||
### 1. 研究深度與廣度要求
|
||||
|
||||
- **深度探索**:對於找到的每個概念、技術或解決方案,必須使用 `搜尋策略` 繼續深入了解其原理、實作細節、優缺點
|
||||
- **廣度探索**:使用`搜尋策略`探索相關的替代方案、競爭技術、生態系統中的相關工具
|
||||
- **持續探索**:每次搜尋結果都應該觸發進一步的探索慾望,直到內容完善
|
||||
|
||||
### 2. 搜尋策略
|
||||
|
||||
你有以下工具可以使用:
|
||||
|
||||
在搜尋時提供的`關鍵字`需`簡潔`與`精準`,`切勿使用大量的關鍵字`再一次搜尋,每次搜尋應該勁量保持在`2~4個關鍵字`,這樣可以`避免太多關鍵字導致無效搜尋`,你應該使用`多次搜尋`並根據`搜尋結果修改關鍵字`慢慢地縮小範圍,當你對搜尋的`內容感到好奇或疑惑`你必須`再次使用搜尋工具`進行多次的搜尋來驗證內容
|
||||
|
||||
- **網路搜尋工具**:用於搜尋最新的技術資訊、文檔、教學、最佳實踐,例如 `web_search` 或其他任何網路搜尋工具
|
||||
- **瀏覽器操作工具**:用於搜尋最新的技術資訊、文檔、教學、最佳實踐,例如 `use_browser` 或其他任何瀏覽器操作工具
|
||||
- **程式碼搜尋工具**:用於在現有專案中搜尋相關實作、模式、範例,例如 `codebase_search`、`read_file` 或其他任何有幫助的工具
|
||||
|
||||
### 3. 研究執行流程
|
||||
|
||||
1. **理解當前狀態**:明確當前需要執行的具體任務
|
||||
2. **執行搜尋**:使用適當的搜尋工具收集資訊
|
||||
3. **深度分析**:對搜尋結果進行深入分析,提取關鍵資訊
|
||||
4. **廣度擴展**:基於分析結果,識別需要進一步探索的方向
|
||||
5. **持續探索**:重複執行搜尋和分析,直到獲得充分的資訊,確保至少經過三輪的研究來保證質量
|
||||
6. **整合總結**:將所有發現整合成有價值的研究成果
|
||||
|
||||
### 4. 研究品質標準
|
||||
|
||||
- **準確性**:所有資訊必須來自可靠來源,避免過時或錯誤的資訊
|
||||
- **實用性**:研究結果必須對程式開發有實際價值
|
||||
- **完整性**:涵蓋主題的各個重要面向,不遺漏關鍵資訊
|
||||
- **時效性**:優先關注最新的技術發展和最佳實踐
|
||||
|
||||
### 5. 避免偏離主題
|
||||
|
||||
- 始終記住`研究主題`
|
||||
- 確保所有搜尋和分析都與主題相關
|
||||
- 參考`下一步計劃`確保研究方向正確
|
||||
|
||||
### 6. 結論報告
|
||||
|
||||
當研究完畢時你必須使用 `markdown` 格式產生一份詳細的研究成果,並等待用戶的下一步指示
|
||||
|
||||
## 執行指示
|
||||
|
||||
**立即開始執行當前狀態中描述的任務**:
|
||||
{currentState}
|
||||
|
||||
記住:
|
||||
|
||||
- 不要滿足於表面的搜尋結果,要深入探索
|
||||
- 每次搜尋後都要思考還有什麼相關的內容需要探索
|
||||
- 保持對新發現的好奇心,持續擴展研究範圍
|
||||
- 將研究過程中的重要發現記錄下來,為後續狀態更新做準備
|
||||
- 禁止一切`猜測與幻覺與模擬`,所有資訊`必須透過網路搜尋工具`來驗證
|
||||
- 過程中你將持續的呼叫 `research_mode` 來記錄狀態,`注意這很重要`!你應該每研究完一個階段就重新互叫`research_mode`來記錄你的詳細研究結果並再次決定研究的方向
|
||||
- 當你覺得研究足夠完善時請產生`結論報告`
|
||||
|
||||
**現在開始執行研究任務**
|
||||
**嚴重警告:你只負責研究所以禁止使用`編輯工具`或`plan task`,你應該完善報告後提供`結論報告`並等待用戶下一步指示**
|
9
src/prompts/templates_zh/researchMode/previousState.md
Normal file
9
src/prompts/templates_zh/researchMode/previousState.md
Normal file
@ -0,0 +1,9 @@
|
||||
**之前的研究成果摘要:**
|
||||
|
||||
{previousState}
|
||||
|
||||
**基於之前的研究,請注意:**
|
||||
|
||||
- 避免重複已經探索過的內容
|
||||
- 在之前研究的基礎上進行深化或擴展
|
||||
- 如果發現與之前研究有衝突的資訊,請特別注意並進行驗證
|
@ -1 +1 @@
|
||||
按照預定義計劃執行特定任務,確保每個步驟的輸出符合質量標準
|
||||
取得特定任務的指導操作,你將根據任務指導來完成編程任務,你必須嚴格遵守工具的回饋指導內容,他將幫助你完美完成任務,**切記該工具不是幫你執行任務而是指導你如何完成任務**,嚴重警告:呼叫完 executeTask 工具不代表你已經完任務,你必須根據工具回傳的指導內容按照步驟來完成
|
||||
|
@ -1 +1 @@
|
||||
初始化並詳細規劃任務流程,建立明確的目標與成功標準,可選擇參考現有任務進行延續規劃
|
||||
當你需要規劃任務或處理複雜的功能建構時,可以使用該工具來取得任務規劃指導,你將依照工具反饋的指導內容嚴謹的按照步驟規劃任務,可選擇參考現有任務進行延續規劃,**嚴重警告**:禁止一切`假設`與`猜測`與`幻想`,你必須透過一切你`可以使用的工具`來`收集資訊`
|
||||
|
@ -0,0 +1 @@
|
||||
當你需要進行程式編程相關的深度研究時,可以使用該工具進入專門的研究模式。該工具會引導你如何使用網路搜尋和程式碼搜尋工具來系統性地研究技術主題,確保研究的深度與廣度,並避免偏離主題。適用於技術調研、最佳實踐探索、解決方案比較等場景。
|
@ -19,6 +19,15 @@
|
||||
- 在每個子任務下標註「輸入/輸出」與「驗收標準」
|
||||
- 如果需要請提供「pseudocode」,僅提供高級邏輯流程和關鍵步驟避免完整代碼
|
||||
- 檢查子任務間「前後依賴」,並在 `dependencies` 欄位標明
|
||||
- 若任務涉及介面設計,請務必提供完整且一致的定義,包括:
|
||||
|
||||
- function / class / schema 定義(含名稱、參數、回傳值)
|
||||
- 各項目之資料型別、用途描述、是否為選填
|
||||
- 錯誤處理方式與預期異常情境
|
||||
- 依賴關係與命名規範(如有)
|
||||
- 範例資料與使用方式
|
||||
|
||||
這將有助於任務之間的連貫性、可讀性與開發精確性。
|
||||
|
||||
3. **依賴與優先順序**
|
||||
|
||||
@ -35,5 +44,14 @@
|
||||
- `clearAllTasks`:清除所有任務並自動備份現有列表
|
||||
|
||||
5. **JSON 嚴謹規則**
|
||||
|
||||
- **禁止註解**:JSON 本身不支援註解,任何 `#` 或 `//` 都會導致解析失敗
|
||||
- **注意轉義**:所有特殊字元(如雙引號 `\"`、反斜線 `\\`)必須正確轉義,否則視為非法字元
|
||||
|
||||
6. **重要訊息**
|
||||
|
||||
這些任務將會分配給**低智能模型**執行,所以你必須參考以下幾點
|
||||
|
||||
- `明確且清楚的指導`:這將避免**低智能模型**設計出錯誤或架構風格不一致的程式碼,所以請給予明確的指令或規範
|
||||
- `封裝接口`:每個任務都會是獨立執行,所以需要定義好接口,例如你會暴露出什麼 function name 有什麼參數,會回傳什麼等等的資訊,方便其他任務執行模型可以快速的知道如何使用或穿接相關功能
|
||||
- `依賴性`:如果任務與任務之間有依賴性,那應該是先定義好交互的介面,任務之間不需要知道各自的實作,但需要知道如何與對方交互
|
||||
|
@ -46,6 +46,11 @@
|
||||
<div class="dependency-view">
|
||||
<div class="panel-header">
|
||||
<h2 data-i18n-key="dependency_view_title">Dependency View</h2>
|
||||
<button id="reset-view-btn" class="reset-view-btn" title="Reset View" data-i18n-key="reset_view_btn_title">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<path fill="currentColor" d="M12 5V2L8 6l4 4V7c3.31 0 6 2.69 6 6 0 2.97-2.17 5.43-5 5.91v2.02c3.95-.49 7-3.85 7-7.93 0-4.42-3.58-8-8-8zm-6 8c0-1.65.67-3.15 1.76-4.24L6.34 7.34C4.9 8.79 4 10.79 4 13c0 4.08 3.05 7.44 7 7.93v-2.02c-2.83-.48-5-2.94-5-5.91z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div id="dependency-graph" class="dependency-graph">
|
||||
<p class="placeholder"></p>
|
||||
|
@ -3,6 +3,7 @@
|
||||
"status_indicator_online": "ONLINE",
|
||||
"dependency_view_title": "Dependency View",
|
||||
"dependency_graph_placeholder": "Dependency relationship for all tasks",
|
||||
"reset_view_btn_title": "Reset View",
|
||||
"task_list_title": "Task List",
|
||||
"search_placeholder": "Search tasks...",
|
||||
"sort_option_date_desc": "Creation Time (New-Old)",
|
||||
|
@ -3,6 +3,7 @@
|
||||
"status_indicator_online": "在線",
|
||||
"dependency_view_title": "依賴關係",
|
||||
"dependency_graph_placeholder": "所有任務的依賴關係",
|
||||
"reset_view_btn_title": "重置視圖",
|
||||
"task_list_title": "任務列表",
|
||||
"search_placeholder": "搜索任務...",
|
||||
"sort_option_date_desc": "創建時間 (新-舊)",
|
||||
|
@ -4,7 +4,10 @@ let selectedTaskId = null;
|
||||
let searchTerm = "";
|
||||
let sortOption = "date-asc";
|
||||
let globalAnalysisResult = null; // 新增:儲存全局分析結果
|
||||
let svg, g, simulation; // << 修改:定義 D3 相關變量
|
||||
let svg, g, simulation;
|
||||
let width, height; // << 新增:將寬高定義為全局變量
|
||||
let isGraphInitialized = false; // << 新增:追蹤圖表是否已初始化
|
||||
let zoom; // << 新增:保存縮放行為對象
|
||||
|
||||
// 新增:i18n 全局變量
|
||||
let currentLang = "en"; // 預設語言
|
||||
@ -25,6 +28,7 @@ const globalAnalysisResultElement = document.getElementById(
|
||||
"global-analysis-result"
|
||||
); // 假設 HTML 中有這個元素
|
||||
const langSwitcher = document.getElementById("lang-switcher"); // << 新增:獲取切換器元素
|
||||
const resetViewBtn = document.getElementById("reset-view-btn"); // << 新增:獲取重置按鈕元素
|
||||
|
||||
// 初始化
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
@ -32,6 +36,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
initI18n(); // << 新增:初始化 i18n
|
||||
updateCurrentTime();
|
||||
setInterval(updateCurrentTime, 1000);
|
||||
updateDimensions(); // << 新增:初始化時更新尺寸
|
||||
|
||||
// 事件監聽器
|
||||
// statusFilter.addEventListener("change", renderTasks); // 將由 changeLanguage 觸發或在 applyTranslations 後觸發
|
||||
@ -39,6 +44,11 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
statusFilter.addEventListener("change", renderTasks);
|
||||
}
|
||||
|
||||
// 新增:重置視圖按鈕事件監聽
|
||||
if (resetViewBtn) {
|
||||
resetViewBtn.addEventListener("click", resetView);
|
||||
}
|
||||
|
||||
// 新增:搜索和排序事件監聽
|
||||
const searchInput = document.getElementById("search-input");
|
||||
const sortOptions = document.getElementById("sort-options");
|
||||
@ -66,24 +76,38 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
changeLanguage(e.target.value)
|
||||
);
|
||||
}
|
||||
|
||||
// 新增:視窗大小改變時更新尺寸
|
||||
window.addEventListener("resize", () => {
|
||||
updateDimensions();
|
||||
if (svg && simulation) {
|
||||
svg.attr("viewBox", [0, 0, width, height]);
|
||||
simulation.force("center", d3.forceCenter(width / 2, height / 2));
|
||||
simulation.alpha(0.3).restart();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 新增:i18n 核心函數
|
||||
// 1. 語言檢測 (localStorage > navigator.language > 'en')
|
||||
// 1. 語言檢測 (URL 參數 > navigator.language > 'en')
|
||||
function detectLanguage() {
|
||||
const savedLang = localStorage.getItem("lang");
|
||||
if (savedLang && ["en", "zh-TW"].includes(savedLang)) {
|
||||
// 確保保存的是有效語言
|
||||
return savedLang;
|
||||
// 1. 優先從 URL 參數讀取
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const urlLang = urlParams.get("lang");
|
||||
if (urlLang && ["en", "zh-TW"].includes(urlLang)) {
|
||||
return urlLang;
|
||||
}
|
||||
// 檢查瀏覽器語言
|
||||
|
||||
// 2. 檢查瀏覽器語言(移除 localStorage 檢查)
|
||||
const browserLang = navigator.language || navigator.userLanguage;
|
||||
if (browserLang) {
|
||||
if (browserLang.toLowerCase().startsWith("zh-tw")) return "zh-TW";
|
||||
if (browserLang.toLowerCase().startsWith("zh")) return "zh-TW"; // 簡體也先 fallback 到繁體
|
||||
if (browserLang.toLowerCase().startsWith("en")) return "en";
|
||||
}
|
||||
return "en"; // 預設
|
||||
|
||||
// 3. 預設值
|
||||
return "en";
|
||||
}
|
||||
|
||||
// 2. 異步加載翻譯文件
|
||||
@ -152,7 +176,6 @@ function applyTranslations() {
|
||||
async function initI18n() {
|
||||
currentLang = detectLanguage();
|
||||
console.log(`Initializing i18n with language: ${currentLang}`);
|
||||
localStorage.setItem("lang", currentLang); // 確保 lang 被保存
|
||||
// << 新增:設置切換器的初始值 >>
|
||||
if (langSwitcher) {
|
||||
langSwitcher.value = currentLang;
|
||||
@ -169,7 +192,6 @@ function changeLanguage(lang) {
|
||||
lang = "en";
|
||||
}
|
||||
currentLang = lang;
|
||||
localStorage.setItem("lang", lang);
|
||||
console.log(`Changing language to: ${currentLang}`);
|
||||
loadTranslations(currentLang)
|
||||
.then(() => {
|
||||
@ -468,6 +490,9 @@ function renderTasks() {
|
||||
);
|
||||
}
|
||||
|
||||
// 儲存篩選後的任務 ID 集合,用於圖形渲染
|
||||
const filteredTaskIds = new Set(filteredTasks.map(task => task.id));
|
||||
|
||||
filteredTasks.sort((a, b) => {
|
||||
switch (sortOption) {
|
||||
case "name-asc":
|
||||
@ -485,6 +510,9 @@ function renderTasks() {
|
||||
}
|
||||
});
|
||||
|
||||
// 更新圖形的顯示狀態
|
||||
updateGraphVisibility(filteredTaskIds);
|
||||
|
||||
// --- 簡單粗暴的替換 (會導致閃爍) ---
|
||||
// TODO: 實現 DOM Diffing 或更智慧的更新策略
|
||||
if (filteredTasks.length === 0) {
|
||||
@ -537,9 +565,77 @@ function renderTasks() {
|
||||
}
|
||||
}
|
||||
|
||||
// 選擇任務
|
||||
// 新增:更新图形可见性的函数
|
||||
function updateGraphVisibility(filteredTaskIds) {
|
||||
if (!g) return;
|
||||
|
||||
// 更新节点的样式
|
||||
g.select(".nodes")
|
||||
.selectAll("g.node-item")
|
||||
.style("opacity", d => filteredTaskIds.has(d.id) ? 1 : 0.2)
|
||||
.style("filter", d => filteredTaskIds.has(d.id) ? "none" : "grayscale(80%)");
|
||||
|
||||
// 更新连接的样式
|
||||
g.select(".links")
|
||||
.selectAll("line.link")
|
||||
.style("opacity", d => {
|
||||
const sourceVisible = filteredTaskIds.has(d.source.id || d.source);
|
||||
const targetVisible = filteredTaskIds.has(d.target.id || d.target);
|
||||
return (sourceVisible && targetVisible) ? 0.6 : 0.1;
|
||||
})
|
||||
.style("stroke", d => {
|
||||
const sourceVisible = filteredTaskIds.has(d.source.id || d.source);
|
||||
const targetVisible = filteredTaskIds.has(d.target.id || d.target);
|
||||
return (sourceVisible && targetVisible) ? "#999" : "#ccc";
|
||||
});
|
||||
|
||||
// 更新缩略图中的节点和连接样式
|
||||
const minimapContent = svg.select(".minimap-content");
|
||||
|
||||
minimapContent.selectAll(".minimap-node")
|
||||
.style("opacity", d => filteredTaskIds.has(d.id) ? 1 : 0.2)
|
||||
.style("filter", d => filteredTaskIds.has(d.id) ? "none" : "grayscale(80%)");
|
||||
|
||||
minimapContent.selectAll(".minimap-link")
|
||||
.style("opacity", d => {
|
||||
const sourceVisible = filteredTaskIds.has(d.source.id || d.source);
|
||||
const targetVisible = filteredTaskIds.has(d.target.id || d.target);
|
||||
return (sourceVisible && targetVisible) ? 0.6 : 0.1;
|
||||
})
|
||||
.style("stroke", d => {
|
||||
const sourceVisible = filteredTaskIds.has(d.source.id || d.source);
|
||||
const targetVisible = filteredTaskIds.has(d.target.id || d.target);
|
||||
return (sourceVisible && targetVisible) ? "#999" : "#ccc";
|
||||
});
|
||||
}
|
||||
|
||||
// 新增:将节点移动到视图中心的函数
|
||||
function centerNode(nodeId) {
|
||||
if (!svg || !g || !simulation) return;
|
||||
|
||||
const node = simulation.nodes().find(n => n.id === nodeId);
|
||||
if (!node) return;
|
||||
|
||||
// 获取当前视图的变换状态
|
||||
const transform = d3.zoomTransform(svg.node());
|
||||
|
||||
// 计算需要的变换以将节点居中
|
||||
const scale = transform.k; // 保持当前缩放级别
|
||||
const x = width / 2 - node.x * scale;
|
||||
const y = height / 2 - node.y * scale;
|
||||
|
||||
// 使用过渡动画平滑地移动到新位置
|
||||
svg.transition()
|
||||
.duration(750) // 750ms的过渡时间
|
||||
.call(zoom.transform, d3.zoomIdentity
|
||||
.translate(x, y)
|
||||
.scale(scale)
|
||||
);
|
||||
}
|
||||
|
||||
// 修改选择任务的函数
|
||||
function selectTask(taskId) {
|
||||
// 清除舊的選中狀態和高亮
|
||||
// 清除旧的选中状态和高亮
|
||||
if (selectedTaskId) {
|
||||
const previousElement = document.querySelector(
|
||||
`.task-item[data-id="${selectedTaskId}"]`
|
||||
@ -549,7 +645,7 @@ function selectTask(taskId) {
|
||||
}
|
||||
}
|
||||
|
||||
// 如果再次點擊同一個任務,則取消選中
|
||||
// 如果再次点击同一个任务,则取消选中
|
||||
if (selectedTaskId === taskId) {
|
||||
selectedTaskId = null;
|
||||
taskDetailsContent.innerHTML = `<p class="placeholder">${translate(
|
||||
@ -561,7 +657,7 @@ function selectTask(taskId) {
|
||||
|
||||
selectedTaskId = taskId;
|
||||
|
||||
// 添加新的選中狀態
|
||||
// 添加新的选中状态
|
||||
const selectedElement = document.querySelector(
|
||||
`.task-item[data-id="${taskId}"]`
|
||||
);
|
||||
@ -569,7 +665,7 @@ function selectTask(taskId) {
|
||||
selectedElement.classList.add("selected");
|
||||
}
|
||||
|
||||
// 獲取並顯示任務詳情
|
||||
// 获取并显示任务详情
|
||||
const task = tasks.find((t) => t.id === taskId);
|
||||
|
||||
if (!task) {
|
||||
@ -585,47 +681,49 @@ function selectTask(taskId) {
|
||||
<div class="task-details-header">
|
||||
<h3 id="detail-name"></h3>
|
||||
<div class="task-meta">
|
||||
<span>狀態: <span id="detail-status" class="task-status"></span></span>
|
||||
<span>${translate(
|
||||
"task_detail_status_label"
|
||||
)} <span id="detail-status" class="task-status"></span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 新增:條件顯示 Summary -->
|
||||
<div class="task-details-section" id="detail-summary-section" style="display: none;">
|
||||
<h4>完成摘要</h4>
|
||||
<h4>${translate("task_detail_summary_title")}</h4>
|
||||
<p id="detail-summary"></p>
|
||||
</div>
|
||||
|
||||
<div class="task-details-section">
|
||||
<h4>任務描述</h4>
|
||||
<h4>${translate("task_detail_description_title")}</h4>
|
||||
<p id="detail-description"></p>
|
||||
</div>
|
||||
|
||||
<div class="task-details-section">
|
||||
<h4>實現指南</h4>
|
||||
<h4>${translate("task_detail_implementation_guide_title")}</h4>
|
||||
<pre id="detail-implementation-guide"></pre>
|
||||
</div>
|
||||
|
||||
<div class="task-details-section">
|
||||
<h4>驗證標準</h4>
|
||||
<h4>${translate("task_detail_verification_criteria_title")}</h4>
|
||||
<p id="detail-verification-criteria"></p>
|
||||
</div>
|
||||
|
||||
<div class="task-details-section">
|
||||
<h4>依賴項 (前置任務)</h4>
|
||||
<h4>${translate("task_detail_dependencies_title")}</h4>
|
||||
<div class="dependencies" id="detail-dependencies">
|
||||
<!-- Dependencies will be populated by JS -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="task-details-section">
|
||||
<h4>相關文件</h4>
|
||||
<h4>${translate("task_detail_related_files_title")}</h4>
|
||||
<div class="related-files" id="detail-related-files">
|
||||
<!-- Related files will be populated by JS -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="task-details-section">
|
||||
<h4>備註</h4>
|
||||
<h4>${translate("task_detail_notes_title")}</h4>
|
||||
<p id="detail-notes"></p>
|
||||
</div>
|
||||
`;
|
||||
@ -733,8 +831,59 @@ function selectTask(taskId) {
|
||||
|
||||
// --- 原來的 innerHTML 賦值已移除 ---
|
||||
|
||||
// 只調用高亮函數
|
||||
highlightNode(taskId); // 只調用 highlightNode
|
||||
// 高亮节点并将其移动到中心
|
||||
highlightNode(taskId);
|
||||
centerNode(taskId);
|
||||
}
|
||||
|
||||
// 新增:重置視圖功能
|
||||
function resetView() {
|
||||
if (!svg || !simulation) return;
|
||||
|
||||
// 添加重置動畫效果
|
||||
resetViewBtn.classList.add("resetting");
|
||||
|
||||
// 計算視圖中心
|
||||
const centerX = width / 2;
|
||||
const centerY = height / 2;
|
||||
|
||||
// 重置縮放和平移(使用 transform 過渡)
|
||||
svg.transition()
|
||||
.duration(750)
|
||||
.call(zoom.transform, d3.zoomIdentity);
|
||||
|
||||
// 重置所有節點位置到中心附近
|
||||
simulation.nodes().forEach(node => {
|
||||
node.x = centerX + (Math.random() - 0.5) * 50; // 在中心點附近隨機分佈
|
||||
node.y = centerY + (Math.random() - 0.5) * 50;
|
||||
node.fx = null; // 清除固定位置
|
||||
node.fy = null;
|
||||
});
|
||||
|
||||
// 重置力導向模擬
|
||||
simulation
|
||||
.force("center", d3.forceCenter(centerX, centerY))
|
||||
.alpha(1) // 完全重啟模擬
|
||||
.restart();
|
||||
|
||||
// 750ms 後移除動畫類
|
||||
setTimeout(() => {
|
||||
resetViewBtn.classList.remove("resetting");
|
||||
}, 750);
|
||||
}
|
||||
|
||||
// 新增:初始化縮放行為
|
||||
function initZoom() {
|
||||
zoom = d3.zoom()
|
||||
.scaleExtent([0.1, 4]) // 設置縮放範圍
|
||||
.on("zoom", (event) => {
|
||||
g.attr("transform", event.transform);
|
||||
updateMinimap(); // 在縮放時更新縮略圖
|
||||
});
|
||||
|
||||
if (svg) {
|
||||
svg.call(zoom);
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染依賴關係圖 - 修改為全局視圖和 enter/update/exit 模式
|
||||
@ -742,22 +891,18 @@ function renderDependencyGraph() {
|
||||
if (!dependencyGraphElement || !window.d3) {
|
||||
console.warn("D3 or dependency graph element not found.");
|
||||
if (dependencyGraphElement) {
|
||||
// 首次或D3丟失時顯示提示,不清空已有的圖
|
||||
if (!dependencyGraphElement.querySelector("svg")) {
|
||||
dependencyGraphElement.innerHTML = `<p class="placeholder">${translate(
|
||||
"error_loading_graph_d3" // Use a specific key
|
||||
)}</p>`;
|
||||
dependencyGraphElement.innerHTML = `<p class="placeholder">${translate("error_loading_graph_d3")}</p>`;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
updateDimensions();
|
||||
|
||||
// 如果沒有任務,清空圖表並顯示提示
|
||||
if (tasks.length === 0) {
|
||||
dependencyGraphElement.innerHTML = `<p class="placeholder">${translate(
|
||||
"dependency_graph_placeholder_empty"
|
||||
)}</p>`;
|
||||
// 重置 SVG 和 simulation 變數,以便下次正確初始化
|
||||
dependencyGraphElement.innerHTML = `<p class="placeholder">${translate("dependency_graph_placeholder_empty")}</p>`;
|
||||
svg = null;
|
||||
g = null;
|
||||
simulation = null;
|
||||
@ -769,10 +914,9 @@ function renderDependencyGraph() {
|
||||
id: task.id,
|
||||
name: task.name,
|
||||
status: task.status,
|
||||
// 保留現有位置以便平滑過渡
|
||||
x: simulation?.nodes().find((n) => n.id === task.id)?.x,
|
||||
y: simulation?.nodes().find((n) => n.id === task.id)?.y,
|
||||
fx: simulation?.nodes().find((n) => n.id === task.id)?.fx, // 保留固定位置
|
||||
fx: simulation?.nodes().find((n) => n.id === task.id)?.fx,
|
||||
fy: simulation?.nodes().find((n) => n.id === task.id)?.fy,
|
||||
}));
|
||||
|
||||
@ -782,44 +926,56 @@ function renderDependencyGraph() {
|
||||
task.dependencies.forEach((dep) => {
|
||||
const sourceId = typeof dep === "object" ? dep.taskId : dep;
|
||||
const targetId = task.id;
|
||||
if (
|
||||
nodes.some((n) => n.id === sourceId) &&
|
||||
nodes.some((n) => n.id === targetId)
|
||||
) {
|
||||
// 確保 link 的 source/target 是 ID,以便力導向識別
|
||||
if (nodes.some((n) => n.id === sourceId) && nodes.some((n) => n.id === targetId)) {
|
||||
links.push({ source: sourceId, target: targetId });
|
||||
} else {
|
||||
console.warn(
|
||||
`Dependency link ignored: Task ${sourceId} or ${targetId} not found in task list.`
|
||||
);
|
||||
console.warn(`Dependency link ignored: Task ${sourceId} or ${targetId} not found in task list.`);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 2. D3 繪圖設置與更新
|
||||
const width = dependencyGraphElement.clientWidth;
|
||||
const height = dependencyGraphElement.clientHeight || 400;
|
||||
|
||||
if (!svg) {
|
||||
// --- 首次渲染 ---
|
||||
console.log("First render of dependency graph");
|
||||
dependencyGraphElement.innerHTML = ""; // 清空 placeholder
|
||||
dependencyGraphElement.innerHTML = "";
|
||||
|
||||
svg = d3
|
||||
.select(dependencyGraphElement)
|
||||
svg = d3.select(dependencyGraphElement)
|
||||
.append("svg")
|
||||
.attr("viewBox", [0, 0, width, height])
|
||||
.attr("preserveAspectRatio", "xMidYMid meet");
|
||||
|
||||
g = svg.append("g"); // 主要組,用於縮放和平移
|
||||
// 添加縮略圖背景
|
||||
const minimapSize = Math.min(width, height) * 0.2; // 縮略圖大小為主視圖的20%
|
||||
const minimapMargin = 40;
|
||||
|
||||
// 創建縮略圖容器
|
||||
const minimap = svg.append("g")
|
||||
.attr("class", "minimap")
|
||||
.attr("transform", `translate(${width - minimapSize - minimapMargin}, ${height - minimapSize - minimapMargin*(height/width)})`);
|
||||
|
||||
// 添加縮放和平移
|
||||
svg.call(
|
||||
d3.zoom().on("zoom", (event) => {
|
||||
g.attr("transform", event.transform);
|
||||
})
|
||||
);
|
||||
// 添加縮略圖背景
|
||||
minimap.append("rect")
|
||||
.attr("width", minimapSize)
|
||||
.attr("height", minimapSize)
|
||||
.attr("fill", "rgba(0, 0, 0, 0.2)")
|
||||
.attr("stroke", "#666")
|
||||
.attr("stroke-width", 1)
|
||||
.attr("rx", 4)
|
||||
.attr("ry", 4);
|
||||
|
||||
// 創建縮略圖內容組
|
||||
minimap.append("g")
|
||||
.attr("class", "minimap-content");
|
||||
|
||||
// 添加視口指示器
|
||||
minimap.append("rect")
|
||||
.attr("class", "minimap-viewport");
|
||||
|
||||
g = svg.append("g");
|
||||
|
||||
// 初始化並添加縮放行為
|
||||
initZoom();
|
||||
|
||||
// 添加箭頭定義
|
||||
g.append("defs")
|
||||
@ -836,32 +992,82 @@ function renderDependencyGraph() {
|
||||
.attr("fill", "#999");
|
||||
|
||||
// 初始化力導向模擬
|
||||
simulation = d3
|
||||
.forceSimulation() // 初始化時不傳入 nodes
|
||||
.force(
|
||||
"link",
|
||||
d3
|
||||
.forceLink()
|
||||
.id((d) => d.id)
|
||||
.distance(100) // 指定 id 訪問器
|
||||
)
|
||||
simulation = d3.forceSimulation()
|
||||
.force("link", d3.forceLink().id((d) => d.id).distance(100))
|
||||
.force("charge", d3.forceManyBody().strength(-300))
|
||||
.force("center", d3.forceCenter(width / 2, height / 2))
|
||||
.force("collide", d3.forceCollide().radius(30))
|
||||
.on("tick", ticked); // 綁定 tick 事件處理函數
|
||||
// 新增:水平分布力,用於優化節點在水平方向的分布,根據節點的入度和出度來決定節點的水平位置,入度為0的節點(起始節點)靠左,出度為0的節點(終止節點)靠右,其他節點則分布在中間位置
|
||||
.force("x", d3.forceX().x(d => {
|
||||
// 計算節點的入度和出度
|
||||
const inDegree = links.filter(l => (l.target.id || l.target) === d.id).length;
|
||||
const outDegree = links.filter(l => (l.source.id || l.source) === d.id).length;
|
||||
|
||||
if (inDegree === 0) {
|
||||
// 入度為0的節點(起始節點)靠左
|
||||
return width * 0.2;
|
||||
} else if (outDegree === 0) {
|
||||
// 出度為0的節點(終止節點)靠右
|
||||
return width * 0.8;
|
||||
} else {
|
||||
// 其他節點在中間
|
||||
return width * 0.5;
|
||||
}
|
||||
}).strength(0.2))
|
||||
// 新增:基于節點度數的垂直分布力
|
||||
.force("y", d3.forceY().y(height / 2).strength(d => {
|
||||
// 計算節點的總度數(入度+出度)
|
||||
const inDegree = links.filter(l => (l.target.id || l.target) === d.id).length;
|
||||
const outDegree = links.filter(l => (l.source.id || l.source) === d.id).length;
|
||||
const totalDegree = inDegree + outDegree;
|
||||
|
||||
// 度數越大,力越大(基礎力0.05,每個連接增加0.03,最大0.3)
|
||||
return Math.min(0.05 + totalDegree * 0.03, 0.3);
|
||||
}))
|
||||
.on("tick", ticked);
|
||||
|
||||
// 添加用於存放連結和節點的組
|
||||
g.append("g").attr("class", "links");
|
||||
g.append("g").attr("class", "nodes");
|
||||
} else {
|
||||
// --- 更新渲染 ---
|
||||
// --- 更新圖表渲染 ---
|
||||
console.log("Updating dependency graph");
|
||||
// 更新 SVG 尺寸和中心力 (如果窗口大小改變)
|
||||
svg.attr("viewBox", [0, 0, width, height]);
|
||||
simulation.force("center", d3.forceCenter(width / 2, height / 2));
|
||||
}
|
||||
|
||||
// 3. 更新連結
|
||||
// --- 預先運算穩定的節點位置 ---
|
||||
// 複製節點和連結以進行穩定化計算
|
||||
const stableNodes = [...nodes];
|
||||
const stableLinks = [...links];
|
||||
|
||||
// 暫時創建一個模擬器來計算穩定的位置
|
||||
const stableSim = d3
|
||||
.forceSimulation(stableNodes)
|
||||
.force("link", d3.forceLink(stableLinks).id(d => d.id).distance(100))
|
||||
.force("charge", d3.forceManyBody().strength(-300))
|
||||
.force("center", d3.forceCenter(width / 2, height / 2))
|
||||
.force("collide", d3.forceCollide().radius(30));
|
||||
|
||||
// 預熱模擬獲得穩定位置
|
||||
for (let i = 0; i < 10; i++) {
|
||||
stableSim.tick();
|
||||
}
|
||||
|
||||
// 將穩定位置複製回原始節點
|
||||
stableNodes.forEach((stableNode) => {
|
||||
const originalNode = nodes.find(n => n.id === stableNode.id);
|
||||
if (originalNode) {
|
||||
originalNode.x = stableNode.x;
|
||||
originalNode.y = stableNode.y;
|
||||
}
|
||||
});
|
||||
|
||||
// 停止臨時模擬器
|
||||
stableSim.stop();
|
||||
// --- 預先運算結束 ---
|
||||
|
||||
// 3. 更新連結 (無動畫)
|
||||
const linkSelection = g
|
||||
.select(".links") // 選擇放置連結的 g 元素
|
||||
.selectAll("line.link")
|
||||
@ -870,62 +1076,43 @@ function renderDependencyGraph() {
|
||||
(d) => `${d.source.id || d.source}-${d.target.id || d.target}`
|
||||
); // Key function 基於 source/target ID
|
||||
|
||||
// Exit - 移除舊連結
|
||||
linkSelection
|
||||
.exit()
|
||||
.transition("exit")
|
||||
.duration(300)
|
||||
.attr("stroke-opacity", 0)
|
||||
.remove();
|
||||
// Exit - 直接移除舊連結
|
||||
linkSelection.exit().remove();
|
||||
|
||||
// Enter - 添加新連結
|
||||
// Enter - 添加新連結 (無動畫)
|
||||
const linkEnter = linkSelection
|
||||
.enter()
|
||||
.append("line")
|
||||
.attr("class", "link")
|
||||
.attr("stroke", "#999")
|
||||
.attr("marker-end", "url(#arrowhead)")
|
||||
.attr("stroke-opacity", 0); // 初始透明
|
||||
|
||||
// Update + Enter - 更新所有連結的屬性 (合併 enter 和 update 選擇集)
|
||||
const linkUpdate = linkSelection.merge(linkEnter);
|
||||
|
||||
linkUpdate
|
||||
.transition("update")
|
||||
.duration(500)
|
||||
.attr("stroke-opacity", 0.6)
|
||||
.attr("stroke-width", 1.5);
|
||||
|
||||
// 4. 更新節點
|
||||
// 立即設置連結位置
|
||||
linkEnter
|
||||
.attr("x1", d => d.source.x || 0)
|
||||
.attr("y1", d => d.source.y || 0)
|
||||
.attr("x2", d => d.target.x || 0)
|
||||
.attr("y2", d => d.target.y || 0);
|
||||
|
||||
// 4. 更新節點 (無動畫)
|
||||
const nodeSelection = g
|
||||
.select(".nodes") // 選擇放置節點的 g 元素
|
||||
.selectAll("g.node-item")
|
||||
.data(nodes, (d) => d.id); // 使用 ID 作為 key
|
||||
|
||||
// Exit - 移除舊節點
|
||||
nodeSelection
|
||||
.exit()
|
||||
.transition("exit")
|
||||
.duration(300)
|
||||
.attr("transform", (d) => `translate(${d.x || 0}, ${d.y || 0}) scale(0)`) // 從當前位置縮放消失
|
||||
.attr("opacity", 0)
|
||||
.remove();
|
||||
// Exit - 直接移除舊節點
|
||||
nodeSelection.exit().remove();
|
||||
|
||||
// Enter - 添加新節點組
|
||||
// Enter - 添加新節點組 (無動畫,直接在最終位置創建)
|
||||
const nodeEnter = nodeSelection
|
||||
.enter()
|
||||
.append("g")
|
||||
.attr("class", (d) => `node-item status-${getStatusClass(d.status)}`) // 使用輔助函數設置 class
|
||||
.attr("data-id", (d) => d.id)
|
||||
// 初始位置:從模擬計算的位置(如果存在)或隨機位置出現,初始縮放為0
|
||||
.attr(
|
||||
"transform",
|
||||
(d) =>
|
||||
`translate(${d.x || Math.random() * width}, ${
|
||||
d.y || Math.random() * height
|
||||
}) scale(0)`
|
||||
)
|
||||
.attr("opacity", 0)
|
||||
// 直接使用預計算的位置,無需縮放或透明度過渡
|
||||
.attr("transform", (d) => `translate(${d.x || 0}, ${d.y || 0})`)
|
||||
.call(drag(simulation)); // 添加拖拽
|
||||
|
||||
// 添加圓形到 Enter 選擇集
|
||||
@ -933,8 +1120,8 @@ function renderDependencyGraph() {
|
||||
.append("circle")
|
||||
.attr("r", 10)
|
||||
.attr("stroke", "#fff")
|
||||
.attr("stroke-width", 1.5);
|
||||
// 顏色將在 merge 後通過 update 過渡設置
|
||||
.attr("stroke-width", 1.5)
|
||||
.attr("fill", getNodeColor); // 直接設置顏色
|
||||
|
||||
// 添加文字到 Enter 選擇集
|
||||
nodeEnter
|
||||
@ -956,28 +1143,14 @@ function renderDependencyGraph() {
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
// Update + Enter - 合併並更新所有節點
|
||||
const nodeUpdate = nodeSelection.merge(nodeEnter);
|
||||
// Update - 立即更新現有節點 (無動畫)
|
||||
nodeSelection
|
||||
.attr("transform", (d) => `translate(${d.x || 0}, ${d.y || 0})`)
|
||||
.attr("class", (d) => `node-item status-${getStatusClass(d.status)}`);
|
||||
|
||||
// 過渡到最終位置和狀態
|
||||
nodeUpdate
|
||||
.transition("update")
|
||||
.duration(500)
|
||||
.attr("transform", (d) => `translate(${d.x || 0}, ${d.y || 0}) scale(1)`) // 移動到模擬位置並恢復大小
|
||||
.attr("opacity", 1);
|
||||
|
||||
// 更新節點顏色 (單獨過渡)
|
||||
nodeUpdate
|
||||
nodeSelection
|
||||
.select("circle")
|
||||
.transition("color")
|
||||
.duration(500)
|
||||
.attr("fill", getNodeColor); // 使用已有的 getNodeColor 函數
|
||||
|
||||
// 更新節點狀態 Class (即時更新,無需過渡)
|
||||
nodeUpdate.attr(
|
||||
"class",
|
||||
(d) => `node-item status-${getStatusClass(d.status)}`
|
||||
);
|
||||
.attr("fill", getNodeColor);
|
||||
|
||||
// << 新增:重新定義 drag 函數 >>
|
||||
function drag(simulation) {
|
||||
@ -1008,10 +1181,24 @@ function renderDependencyGraph() {
|
||||
}
|
||||
// << drag 函數定義結束 >>
|
||||
|
||||
// 5. 更新力導向模擬
|
||||
simulation.nodes(nodes); // 在處理完 enter/exit 後更新模擬節點
|
||||
// 5. 更新力導向模擬,但不啟動
|
||||
simulation.nodes(nodes); // 更新模擬節點
|
||||
simulation.force("link").links(links); // 更新模擬連結
|
||||
simulation.alpha(0.3).restart(); // 重新激活模擬
|
||||
|
||||
// 更新水平分布力的目標位置
|
||||
simulation.force("x").x(d => {
|
||||
const inDegree = links.filter(l => (l.target.id || l.target) === d.id).length;
|
||||
const outDegree = links.filter(l => (l.source.id || l.source) === d.id).length;
|
||||
|
||||
if (inDegree === 0) {
|
||||
return width * 0.2;
|
||||
} else if (outDegree === 0) {
|
||||
return width * 0.8;
|
||||
} else {
|
||||
return width * 0.5;
|
||||
}
|
||||
});
|
||||
// 注意:移除了 restart() 調用,防止刷新時的動畫跳變
|
||||
}
|
||||
|
||||
// Tick 函數: 更新節點和連結位置
|
||||
@ -1031,16 +1218,22 @@ function ticked() {
|
||||
.selectAll("g.node-item")
|
||||
// << 修改:添加座標後備值 >>
|
||||
.attr("transform", (d) => `translate(${d.x || 0}, ${d.y || 0})`);
|
||||
|
||||
// 更新縮略圖
|
||||
updateMinimap();
|
||||
}
|
||||
|
||||
// 函數:根據節點數據返回顏色 (示例)
|
||||
function getNodeColor(nodeData) {
|
||||
switch (nodeData.status) {
|
||||
case "已完成":
|
||||
case "completed":
|
||||
return "var(--secondary-color)";
|
||||
case "進行中":
|
||||
case "in_progress":
|
||||
return "var(--primary-color)";
|
||||
case "待處理":
|
||||
case "pending":
|
||||
return "#f1c40f"; // 與進度條和狀態標籤一致
|
||||
default:
|
||||
return "#7f8c8d"; // 未知狀態
|
||||
@ -1085,12 +1278,14 @@ function updateProgressIndicator() {
|
||||
progressIndicator.style.display = "block"; // 確保顯示
|
||||
|
||||
const completedTasks = tasks.filter(
|
||||
(task) => task.status === "已完成"
|
||||
(task) => task.status === "completed" || task.status === "已完成"
|
||||
).length;
|
||||
const inProgressTasks = tasks.filter(
|
||||
(task) => task.status === "進行中"
|
||||
(task) => task.status === "in_progress" || task.status === "進行中"
|
||||
).length;
|
||||
const pendingTasks = tasks.filter(
|
||||
(task) => task.status === "pending" || task.status === "待處理"
|
||||
).length;
|
||||
const pendingTasks = tasks.filter((task) => task.status === "待處理").length;
|
||||
|
||||
const completedPercent =
|
||||
totalTasks > 0 ? (completedTasks / totalTasks) * 100 : 0;
|
||||
@ -1182,5 +1377,90 @@ function getStatusClass(status) {
|
||||
return status ? status.replace(/_/g, "-") : "unknown"; // 替換所有下劃線
|
||||
}
|
||||
|
||||
// 新增:更新寬高的函數
|
||||
function updateDimensions() {
|
||||
if (dependencyGraphElement) {
|
||||
width = dependencyGraphElement.clientWidth;
|
||||
height = dependencyGraphElement.clientHeight || 400;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加縮略圖更新函數
|
||||
function updateMinimap() {
|
||||
if (!svg || !simulation) return;
|
||||
|
||||
const minimapSize = Math.min(width, height) * 0.2;
|
||||
const nodes = simulation.nodes();
|
||||
const links = simulation.force("link").links();
|
||||
|
||||
// 計算當前圖的邊界(添加padding)
|
||||
const padding = 20; // 添加內邊距
|
||||
const xExtent = d3.extent(nodes, d => d.x);
|
||||
const yExtent = d3.extent(nodes, d => d.y);
|
||||
const graphWidth = (xExtent[1] - xExtent[0]) || width;
|
||||
const graphHeight = (yExtent[1] - yExtent[0]) || height;
|
||||
|
||||
// 計算縮放比例,確保考慮padding
|
||||
const scale = Math.min(
|
||||
minimapSize / (graphWidth + padding * 2),
|
||||
minimapSize / (graphHeight + padding * 2)
|
||||
) * 0.9; // 0.9作為安全係數
|
||||
|
||||
// 創建縮放函數,加入padding
|
||||
const minimapX = d3.scaleLinear()
|
||||
.domain([xExtent[0] - padding, xExtent[1] + padding])
|
||||
.range([0, minimapSize]);
|
||||
const minimapY = d3.scaleLinear()
|
||||
.domain([yExtent[0] - padding, yExtent[1] + padding])
|
||||
.range([0, minimapSize]);
|
||||
|
||||
// 更新縮略圖中的連接
|
||||
const minimapContent = svg.select(".minimap-content");
|
||||
const minimapLinks = minimapContent.selectAll(".minimap-link")
|
||||
.data(links);
|
||||
|
||||
minimapLinks.enter()
|
||||
.append("line")
|
||||
.attr("class", "minimap-link")
|
||||
.merge(minimapLinks)
|
||||
.attr("x1", d => minimapX(d.source.x))
|
||||
.attr("y1", d => minimapY(d.source.y))
|
||||
.attr("x2", d => minimapX(d.target.x))
|
||||
.attr("y2", d => minimapY(d.target.y))
|
||||
.attr("stroke", "#999")
|
||||
.attr("stroke-width", 0.5)
|
||||
.attr("stroke-opacity", 0.6);
|
||||
|
||||
minimapLinks.exit().remove();
|
||||
|
||||
// 更新縮略圖中的節點
|
||||
const minimapNodes = minimapContent.selectAll(".minimap-node")
|
||||
.data(nodes);
|
||||
|
||||
minimapNodes.enter()
|
||||
.append("circle")
|
||||
.attr("class", "minimap-node")
|
||||
.attr("r", 2)
|
||||
.merge(minimapNodes)
|
||||
.attr("cx", d => minimapX(d.x))
|
||||
.attr("cy", d => minimapY(d.y))
|
||||
.attr("fill", getNodeColor);
|
||||
|
||||
minimapNodes.exit().remove();
|
||||
|
||||
// 更新視口指示器
|
||||
const transform = d3.zoomTransform(svg.node());
|
||||
const viewportWidth = width / transform.k;
|
||||
const viewportHeight = height / transform.k;
|
||||
const viewportX = -transform.x / transform.k;
|
||||
const viewportY = -transform.y / transform.k;
|
||||
|
||||
svg.select(".minimap-viewport")
|
||||
.attr("x", minimapX(viewportX))
|
||||
.attr("y", minimapY(viewportY))
|
||||
.attr("width", minimapX(viewportX + viewportWidth) - minimapX(viewportX))
|
||||
.attr("height", minimapY(viewportY + viewportHeight) - minimapY(viewportY));
|
||||
}
|
||||
|
||||
// 函數:啟用節點拖拽 (保持不變)
|
||||
// ... drag ...
|
||||
|
@ -123,6 +123,32 @@ main {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.reset-view-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.reset-view-btn:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
transform: rotate(-30deg);
|
||||
}
|
||||
|
||||
.reset-view-btn svg {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.reset-view-btn.resetting svg {
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
@ -459,3 +485,11 @@ g.node-item.highlighted circle {
|
||||
flex-grow: 1; /* 讓搜索框佔據更多空間 */
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
/* 新增:缩略图视口指示器样式 */
|
||||
.minimap-viewport {
|
||||
fill: rgba(255, 255, 255, 0.025);
|
||||
stroke: rgba(255, 255, 255, 0.1);
|
||||
stroke-width: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
@ -6,3 +6,6 @@ export * from "./project/index.js";
|
||||
|
||||
// 導出所有思維鏈工具
|
||||
export * from "./thought/index.js";
|
||||
|
||||
// 導出所有研究工具
|
||||
export * from "./research/index.js";
|
||||
|
@ -1,9 +1,5 @@
|
||||
import { z } from "zod";
|
||||
import { getInitProjectRulesPrompt } from "../../prompts/index.js";
|
||||
import {
|
||||
getRulesFilePath,
|
||||
ensureRulesFileExists,
|
||||
} from "../../utils/pathUtils.js";
|
||||
|
||||
// 定義schema
|
||||
export const initProjectRulesSchema = z.object({});
|
||||
@ -15,20 +11,14 @@ export const initProjectRulesSchema = z.object({});
|
||||
export async function initProjectRules() {
|
||||
try {
|
||||
// 從生成器獲取提示詞
|
||||
const promptContent = getInitProjectRulesPrompt();
|
||||
|
||||
// 確保 DATA_DIR 目錄中存在 rules.md 文件
|
||||
await ensureRulesFileExists();
|
||||
|
||||
// 輸出規則文件的路徑,幫助用戶找到文件
|
||||
const rulesPath = getRulesFilePath();
|
||||
const promptContent = await getInitProjectRulesPrompt();
|
||||
|
||||
// 返回成功響應
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: promptContent + `\n\n規則文件將位於: ${rulesPath}`,
|
||||
text: promptContent,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
4
src/tools/research/index.ts
Normal file
4
src/tools/research/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
// 導出研究模式工具
|
||||
|
||||
// researchMode
|
||||
export { researchMode, researchModeSchema } from "./researchMode.js";
|
63
src/tools/research/researchMode.ts
Normal file
63
src/tools/research/researchMode.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import { z } from "zod";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { getResearchModePrompt } from "../../prompts/index.js";
|
||||
import { getMemoryDir } from "../../utils/paths.js";
|
||||
|
||||
// 研究模式工具
|
||||
export const researchModeSchema = z.object({
|
||||
topic: z
|
||||
.string()
|
||||
.min(5, {
|
||||
message: "研究主題不能少於5個字符,請提供明確的研究主題",
|
||||
})
|
||||
.describe("要研究的程式編程主題內容,應該明確且具體"),
|
||||
previousState: z
|
||||
.string()
|
||||
.optional()
|
||||
.default("")
|
||||
.describe(
|
||||
"之前的研究狀態和內容摘要,第一次執行時為空,後續會包含之前詳細且關鍵的研究成果,這將幫助後續的研究"
|
||||
),
|
||||
currentState: z
|
||||
.string()
|
||||
.describe(
|
||||
"當前 Agent 主要該執行的內容,例如使用網路工具搜尋某些關鍵字或分析特定程式碼,研究完畢後請呼叫 research_mode 來記錄狀態並與之前的`previousState`整合,這將幫助你更好的保存與執行研究內容"
|
||||
),
|
||||
nextSteps: z
|
||||
.string()
|
||||
.describe(
|
||||
"後續的計劃、步驟或研究方向,用來約束 Agent 不偏離主題或走錯方向,如果研究過程中發現需要調整研究方向,請更新此欄位"
|
||||
),
|
||||
});
|
||||
|
||||
export async function researchMode({
|
||||
topic,
|
||||
previousState = "",
|
||||
currentState,
|
||||
nextSteps,
|
||||
}: z.infer<typeof researchModeSchema>) {
|
||||
// 獲取基礎目錄路徑
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const PROJECT_ROOT = path.resolve(__dirname, "../../..");
|
||||
const MEMORY_DIR = await getMemoryDir();
|
||||
|
||||
// 使用prompt生成器獲取最終prompt
|
||||
const prompt = await getResearchModePrompt({
|
||||
topic,
|
||||
previousState,
|
||||
currentState,
|
||||
nextSteps,
|
||||
memoryDir: MEMORY_DIR,
|
||||
});
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: prompt,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
@ -32,7 +32,7 @@ export async function analyzeTask({
|
||||
previousAnalysis,
|
||||
}: z.infer<typeof analyzeTaskSchema>) {
|
||||
// 使用prompt生成器獲取最終prompt
|
||||
const prompt = getAnalyzeTaskPrompt({
|
||||
const prompt = await getAnalyzeTaskPrompt({
|
||||
summary,
|
||||
initialConcept,
|
||||
previousAnalysis,
|
||||
|
@ -25,7 +25,7 @@ export async function clearAllTasks({
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: getClearAllTasksPrompt({ confirm: false }),
|
||||
text: await getClearAllTasksPrompt({ confirm: false }),
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -38,7 +38,7 @@ export async function clearAllTasks({
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: getClearAllTasksPrompt({ isEmpty: true }),
|
||||
text: await getClearAllTasksPrompt({ isEmpty: true }),
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -51,7 +51,7 @@ export async function clearAllTasks({
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: getClearAllTasksPrompt({
|
||||
text: await getClearAllTasksPrompt({
|
||||
success: result.success,
|
||||
message: result.message,
|
||||
backupFile: result.backupFile,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { z } from "zod";
|
||||
import { UUID_V4_REGEX } from "../../utils/regex.js";
|
||||
import {
|
||||
getTaskById,
|
||||
deleteTask as modelDeleteTask,
|
||||
@ -10,7 +11,9 @@ import { getDeleteTaskPrompt } from "../../prompts/index.js";
|
||||
export const deleteTaskSchema = z.object({
|
||||
taskId: z
|
||||
.string()
|
||||
.uuid({ message: "任務ID格式無效,請提供有效的UUID格式" })
|
||||
.regex(UUID_V4_REGEX, {
|
||||
message: "任務ID格式無效,請提供有效的UUID v4格式",
|
||||
})
|
||||
.describe("待刪除任務的唯一標識符,必須是系統中存在且未完成的任務ID"),
|
||||
});
|
||||
|
||||
@ -22,7 +25,7 @@ export async function deleteTask({ taskId }: z.infer<typeof deleteTaskSchema>) {
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: getDeleteTaskPrompt({ taskId }),
|
||||
text: await getDeleteTaskPrompt({ taskId }),
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
@ -34,7 +37,11 @@ export async function deleteTask({ taskId }: z.infer<typeof deleteTaskSchema>) {
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: getDeleteTaskPrompt({ taskId, task, isTaskCompleted: true }),
|
||||
text: await getDeleteTaskPrompt({
|
||||
taskId,
|
||||
task,
|
||||
isTaskCompleted: true,
|
||||
}),
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
@ -47,7 +54,7 @@ export async function deleteTask({ taskId }: z.infer<typeof deleteTaskSchema>) {
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: getDeleteTaskPrompt({
|
||||
text: await getDeleteTaskPrompt({
|
||||
taskId,
|
||||
task,
|
||||
success: result.success,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { z } from "zod";
|
||||
import { UUID_V4_REGEX } from "../../utils/regex.js";
|
||||
import {
|
||||
getTaskById,
|
||||
updateTaskStatus,
|
||||
@ -13,8 +14,8 @@ import { loadTaskRelatedFiles } from "../../utils/fileLoader.js";
|
||||
export const executeTaskSchema = z.object({
|
||||
taskId: z
|
||||
.string()
|
||||
.uuid({
|
||||
message: "任務ID必須是有效的UUID格式",
|
||||
.regex(UUID_V4_REGEX, {
|
||||
message: "任務ID格式無效,請提供有效的UUID v4格式",
|
||||
})
|
||||
.describe("待執行任務的唯一標識符,必須是系統中存在的有效任務ID"),
|
||||
});
|
||||
@ -125,7 +126,7 @@ export async function executeTask({
|
||||
}
|
||||
|
||||
// 使用prompt生成器獲取最終prompt
|
||||
const prompt = getExecuteTaskPrompt({
|
||||
const prompt = await getExecuteTaskPrompt({
|
||||
task,
|
||||
complexityAssessment,
|
||||
relatedFilesSummary,
|
||||
|
@ -38,7 +38,7 @@ export async function getTaskDetail({
|
||||
const task = result.tasks[0];
|
||||
|
||||
// 使用prompt生成器獲取最終prompt
|
||||
const prompt = getGetTaskDetailPrompt({
|
||||
const prompt = await getGetTaskDetailPrompt({
|
||||
taskId,
|
||||
task,
|
||||
});
|
||||
@ -53,7 +53,7 @@ export async function getTaskDetail({
|
||||
};
|
||||
} catch (error) {
|
||||
// 使用prompt生成器獲取錯誤訊息
|
||||
const errorPrompt = getGetTaskDetailPrompt({
|
||||
const errorPrompt = await getGetTaskDetailPrompt({
|
||||
taskId,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
|
@ -35,3 +35,5 @@ export { queryTask, queryTaskSchema } from "./queryTask.js";
|
||||
|
||||
// getTaskDetail
|
||||
export { getTaskDetail, getTaskDetailSchema } from "./getTaskDetail.js";
|
||||
|
||||
export { splitTasksRaw, splitTasksRawSchema } from "./splitTasksRaw.js";
|
||||
|
@ -55,7 +55,7 @@ export async function listTasks({ status }: z.infer<typeof listTasksSchema>) {
|
||||
}, {} as Record<string, typeof tasks>);
|
||||
|
||||
// 使用prompt生成器獲取最終prompt
|
||||
const prompt = getListTasksPrompt({
|
||||
const prompt = await getListTasksPrompt({
|
||||
status,
|
||||
tasks: tasksByStatus,
|
||||
allTasks: filteredTasks,
|
||||
|
@ -4,6 +4,7 @@ import { fileURLToPath } from "url";
|
||||
import { getAllTasks } from "../../models/taskModel.js";
|
||||
import { TaskStatus, Task } from "../../types/index.js";
|
||||
import { getPlanTaskPrompt } from "../../prompts/index.js";
|
||||
import { getMemoryDir } from "../../utils/paths.js";
|
||||
|
||||
// 開始規劃工具
|
||||
export const planTaskSchema = z.object({
|
||||
@ -33,8 +34,7 @@ export async function planTask({
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const PROJECT_ROOT = path.resolve(__dirname, "../../..");
|
||||
const DATA_DIR = process.env.DATA_DIR || path.join(PROJECT_ROOT, "data");
|
||||
const MEMORY_DIR = path.join(DATA_DIR, "memory");
|
||||
const MEMORY_DIR = await getMemoryDir();
|
||||
|
||||
// 準備所需參數
|
||||
let completedTasks: Task[] = [];
|
||||
@ -56,7 +56,7 @@ export async function planTask({
|
||||
}
|
||||
|
||||
// 使用prompt生成器獲取最終prompt
|
||||
const prompt = getPlanTaskPrompt({
|
||||
const prompt = await getPlanTaskPrompt({
|
||||
description,
|
||||
requirements,
|
||||
existingTasksReference,
|
||||
|
@ -44,7 +44,7 @@ export async function queryTask({
|
||||
const results = await searchTasksWithCommand(query, isId, page, pageSize);
|
||||
|
||||
// 使用prompt生成器獲取最終prompt
|
||||
const prompt = getQueryTaskPrompt({
|
||||
const prompt = await getQueryTaskPrompt({
|
||||
query,
|
||||
isId,
|
||||
tasks: results.tasks,
|
||||
|
@ -24,7 +24,7 @@ export async function reflectTask({
|
||||
analysis,
|
||||
}: z.infer<typeof reflectTaskSchema>) {
|
||||
// 使用prompt生成器獲取最終prompt
|
||||
const prompt = getReflectTaskPrompt({
|
||||
const prompt = await getReflectTaskPrompt({
|
||||
summary,
|
||||
analysis,
|
||||
});
|
||||
|
@ -97,9 +97,7 @@ export const splitTasksSchema = z.object({
|
||||
globalAnalysisResult: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
"全局分析結果:來自 reflect_task 的完整分析結果,適用於所有任務的通用部分"
|
||||
),
|
||||
.describe("任務最終目標,來自之前分析適用於所有任務的通用部分"),
|
||||
});
|
||||
|
||||
export async function splitTasks({
|
||||
@ -211,7 +209,7 @@ export async function splitTasks({
|
||||
}
|
||||
|
||||
// 使用prompt生成器獲取最終prompt
|
||||
const prompt = getSplitTasksPrompt({
|
||||
const prompt = await getSplitTasksPrompt({
|
||||
updateMode,
|
||||
createdTasks,
|
||||
allTasks,
|
||||
|
283
src/tools/task/splitTasksRaw.ts
Normal file
283
src/tools/task/splitTasksRaw.ts
Normal file
@ -0,0 +1,283 @@
|
||||
import { z } from "zod";
|
||||
import {
|
||||
getAllTasks,
|
||||
batchCreateOrUpdateTasks,
|
||||
clearAllTasks as modelClearAllTasks,
|
||||
} from "../../models/taskModel.js";
|
||||
import { RelatedFileType, Task } from "../../types/index.js";
|
||||
import { getSplitTasksPrompt } from "../../prompts/index.js";
|
||||
|
||||
// 拆分任務工具
|
||||
export const splitTasksRawSchema = z.object({
|
||||
updateMode: z
|
||||
.enum(["append", "overwrite", "selective", "clearAllTasks"])
|
||||
.describe(
|
||||
"任務更新模式選擇:'append'(保留所有現有任務並添加新任務)、'overwrite'(清除所有未完成任務並完全替換,保留已完成任務)、'selective'(智能更新:根據任務名稱匹配更新現有任務,保留不在列表中的任務,推薦用於任務微調)、'clearAllTasks'(清除所有任務並創建備份)。\n預設為'clearAllTasks'模式,只有用戶要求變更或修改計劃內容才使用其他模式"
|
||||
),
|
||||
tasksRaw: z
|
||||
.string()
|
||||
.describe(
|
||||
"結構化的任務清單,每個任務應保持原子性且有明確的完成標準,避免過於簡單的任務,簡單修改可與其他任務整合,避免任務過多,範例:[{name: '簡潔明確的任務名稱,應能清晰表達任務目的', description: '詳細的任務描述,包含實施要點、技術細節和驗收標準', implementationGuide: '此特定任務的具體實現方法和步驟,請參考之前的分析結果提供精簡pseudocode', notes: '補充說明、特殊處理要求或實施建議(選填)', dependencies: ['此任務依賴的前置任務完整名稱'], relatedFiles: [{path: '文件路徑', type: '文件類型 (TO_MODIFY: 待修改, REFERENCE: 參考資料, CREATE: 待建立, DEPENDENCY: 依賴文件, OTHER: 其他)', description: '文件描述', lineStart: 1, lineEnd: 100}], verificationCriteria: '此特定任務的驗證標準和檢驗方法'}, {name: '任務2', description: '任務2描述', implementationGuide: '任務2實現方法', notes: '補充說明、特殊處理要求或實施建議(選填)', dependencies: ['任務1'], relatedFiles: [{path: '文件路徑', type: '文件類型 (TO_MODIFY: 待修改, REFERENCE: 參考資料, CREATE: 待建立, DEPENDENCY: 依賴文件, OTHER: 其他)', description: '文件描述', lineStart: 1, lineEnd: 100}], verificationCriteria: '此特定任務的驗證標準和檢驗方法'}]"
|
||||
),
|
||||
globalAnalysisResult: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("任務最終目標,來自之前分析適用於所有任務的通用部分"),
|
||||
});
|
||||
|
||||
const tasksSchema = z
|
||||
.array(
|
||||
z.object({
|
||||
name: z
|
||||
.string()
|
||||
.max(100, {
|
||||
message: "任務名稱過長,請限制在100個字符以內",
|
||||
})
|
||||
.describe("簡潔明確的任務名稱,應能清晰表達任務目的"),
|
||||
description: z
|
||||
.string()
|
||||
.min(10, {
|
||||
message: "任務描述過短,請提供更詳細的內容以確保理解",
|
||||
})
|
||||
.describe("詳細的任務描述,包含實施要點、技術細節和驗收標準"),
|
||||
implementationGuide: z
|
||||
.string()
|
||||
.describe(
|
||||
"此特定任務的具體實現方法和步驟,請參考之前的分析結果提供精簡pseudocode"
|
||||
),
|
||||
dependencies: z
|
||||
.array(z.string())
|
||||
.optional()
|
||||
.describe(
|
||||
"此任務依賴的前置任務ID或任務名稱列表,支持兩種引用方式,名稱引用更直觀,是一個字串陣列"
|
||||
),
|
||||
notes: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("補充說明、特殊處理要求或實施建議(選填)"),
|
||||
relatedFiles: z
|
||||
.array(
|
||||
z.object({
|
||||
path: z
|
||||
.string()
|
||||
.min(1, {
|
||||
message: "文件路徑不能為空",
|
||||
})
|
||||
.describe("文件路徑,可以是相對於項目根目錄的路徑或絕對路徑"),
|
||||
type: z
|
||||
.nativeEnum(RelatedFileType)
|
||||
.describe(
|
||||
"文件類型 (TO_MODIFY: 待修改, REFERENCE: 參考資料, CREATE: 待建立, DEPENDENCY: 依賴文件, OTHER: 其他)"
|
||||
),
|
||||
description: z
|
||||
.string()
|
||||
.min(1, {
|
||||
message: "文件描述不能為空",
|
||||
})
|
||||
.describe("文件描述,用於說明文件的用途和內容"),
|
||||
lineStart: z
|
||||
.number()
|
||||
.int()
|
||||
.positive()
|
||||
.optional()
|
||||
.describe("相關代碼區塊的起始行(選填)"),
|
||||
lineEnd: z
|
||||
.number()
|
||||
.int()
|
||||
.positive()
|
||||
.optional()
|
||||
.describe("相關代碼區塊的結束行(選填)"),
|
||||
})
|
||||
)
|
||||
.optional()
|
||||
.describe(
|
||||
"與任務相關的文件列表,用於記錄與任務相關的代碼文件、參考資料、要建立的文件等(選填)"
|
||||
),
|
||||
verificationCriteria: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("此特定任務的驗證標準和檢驗方法"),
|
||||
})
|
||||
)
|
||||
.min(1, {
|
||||
message: "請至少提供一個任務",
|
||||
})
|
||||
.describe(
|
||||
"結構化的任務清單,每個任務應保持原子性且有明確的完成標準,避免過於簡單的任務,簡單修改可與其他任務整合,避免任務過多"
|
||||
);
|
||||
|
||||
export async function splitTasksRaw({
|
||||
updateMode,
|
||||
tasksRaw,
|
||||
globalAnalysisResult,
|
||||
}: z.infer<typeof splitTasksRawSchema>) {
|
||||
let tasks: Task[] = [];
|
||||
try {
|
||||
tasks = JSON.parse(tasksRaw);
|
||||
} catch (error) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text:
|
||||
"tasksRaw 參數格式錯誤,請確保格式正確,請嘗試修正錯誤,如果文本太長無法順利修復請分批呼叫,這樣可以避免訊息過長導致不好修正問題,錯誤訊息:" +
|
||||
(error instanceof Error ? error.message : String(error)),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
// 使用 tasksSchema 驗證 tasks
|
||||
const tasksResult = tasksSchema.safeParse(tasks);
|
||||
if (!tasksResult.success) {
|
||||
// 返回錯誤訊息
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text:
|
||||
"tasks 參數格式錯誤,請確保格式正確,錯誤訊息:" +
|
||||
tasksResult.error.message,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
// 檢查 tasks 裡面的 name 是否有重複
|
||||
const nameSet = new Set();
|
||||
for (const task of tasks) {
|
||||
if (nameSet.has(task.name)) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: "tasks 參數中存在重複的任務名稱,請確保每個任務名稱是唯一的",
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
nameSet.add(task.name);
|
||||
}
|
||||
|
||||
// 根據不同的更新模式處理任務
|
||||
let message = "";
|
||||
let actionSuccess = true;
|
||||
let backupFile = null;
|
||||
let createdTasks: Task[] = [];
|
||||
let allTasks: Task[] = [];
|
||||
|
||||
// 將任務資料轉換為符合batchCreateOrUpdateTasks的格式
|
||||
const convertedTasks = tasks.map((task) => ({
|
||||
name: task.name,
|
||||
description: task.description,
|
||||
notes: task.notes,
|
||||
dependencies: task.dependencies as unknown as string[],
|
||||
implementationGuide: task.implementationGuide,
|
||||
verificationCriteria: task.verificationCriteria,
|
||||
relatedFiles: task.relatedFiles?.map((file) => ({
|
||||
path: file.path,
|
||||
type: file.type as RelatedFileType,
|
||||
description: file.description,
|
||||
lineStart: file.lineStart,
|
||||
lineEnd: file.lineEnd,
|
||||
})),
|
||||
}));
|
||||
|
||||
// 處理 clearAllTasks 模式
|
||||
if (updateMode === "clearAllTasks") {
|
||||
const clearResult = await modelClearAllTasks();
|
||||
|
||||
if (clearResult.success) {
|
||||
message = clearResult.message;
|
||||
backupFile = clearResult.backupFile;
|
||||
|
||||
try {
|
||||
// 清空任務後再創建新任務
|
||||
createdTasks = await batchCreateOrUpdateTasks(
|
||||
convertedTasks,
|
||||
"append",
|
||||
globalAnalysisResult
|
||||
);
|
||||
message += `\n成功創建了 ${createdTasks.length} 個新任務。`;
|
||||
} catch (error) {
|
||||
actionSuccess = false;
|
||||
message += `\n創建新任務時發生錯誤: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`;
|
||||
}
|
||||
} else {
|
||||
actionSuccess = false;
|
||||
message = clearResult.message;
|
||||
}
|
||||
} else {
|
||||
// 對於其他模式,直接使用 batchCreateOrUpdateTasks
|
||||
try {
|
||||
createdTasks = await batchCreateOrUpdateTasks(
|
||||
convertedTasks,
|
||||
updateMode,
|
||||
globalAnalysisResult
|
||||
);
|
||||
|
||||
// 根據不同的更新模式生成消息
|
||||
switch (updateMode) {
|
||||
case "append":
|
||||
message = `成功追加了 ${createdTasks.length} 個新任務。`;
|
||||
break;
|
||||
case "overwrite":
|
||||
message = `成功清除未完成任務並創建了 ${createdTasks.length} 個新任務。`;
|
||||
break;
|
||||
case "selective":
|
||||
message = `成功選擇性更新/創建了 ${createdTasks.length} 個任務。`;
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
actionSuccess = false;
|
||||
message = `任務創建失敗:${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 獲取所有任務用於顯示依賴關係
|
||||
try {
|
||||
allTasks = await getAllTasks();
|
||||
} catch (error) {
|
||||
allTasks = [...createdTasks]; // 如果獲取失敗,至少使用剛創建的任務
|
||||
}
|
||||
|
||||
// 使用prompt生成器獲取最終prompt
|
||||
const prompt = await getSplitTasksPrompt({
|
||||
updateMode,
|
||||
createdTasks,
|
||||
allTasks,
|
||||
});
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: prompt,
|
||||
},
|
||||
],
|
||||
ephemeral: {
|
||||
taskCreationResult: {
|
||||
success: actionSuccess,
|
||||
message,
|
||||
backupFilePath: backupFile,
|
||||
},
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text:
|
||||
"執行任務拆分時發生錯誤: " +
|
||||
(error instanceof Error ? error.message : String(error)),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import { z } from "zod";
|
||||
import { UUID_V4_REGEX } from "../../utils/regex.js";
|
||||
import {
|
||||
getTaskById,
|
||||
updateTaskContent as modelUpdateTaskContent,
|
||||
@ -10,7 +11,9 @@ import { getUpdateTaskContentPrompt } from "../../prompts/index.js";
|
||||
export const updateTaskContentSchema = z.object({
|
||||
taskId: z
|
||||
.string()
|
||||
.uuid({ message: "任務ID格式無效,請提供有效的UUID格式" })
|
||||
.regex(UUID_V4_REGEX, {
|
||||
message: "任務ID格式無效,請提供有效的UUID v4格式",
|
||||
})
|
||||
.describe("待更新任務的唯一標識符,必須是系統中存在且未完成的任務ID"),
|
||||
name: z.string().optional().describe("任務的新名稱(選填)"),
|
||||
description: z.string().optional().describe("任務的新描述內容(選填)"),
|
||||
@ -81,7 +84,7 @@ export async function updateTaskContent({
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: getUpdateTaskContentPrompt({
|
||||
text: await getUpdateTaskContentPrompt({
|
||||
taskId,
|
||||
validationError:
|
||||
"行號設置無效:必須同時設置起始行和結束行,且起始行必須小於結束行",
|
||||
@ -108,7 +111,7 @@ export async function updateTaskContent({
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: getUpdateTaskContentPrompt({
|
||||
text: await getUpdateTaskContentPrompt({
|
||||
taskId,
|
||||
emptyUpdate: true,
|
||||
}),
|
||||
@ -125,7 +128,7 @@ export async function updateTaskContent({
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: getUpdateTaskContentPrompt({
|
||||
text: await getUpdateTaskContentPrompt({
|
||||
taskId,
|
||||
}),
|
||||
},
|
||||
@ -161,7 +164,7 @@ export async function updateTaskContent({
|
||||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: getUpdateTaskContentPrompt({
|
||||
text: await getUpdateTaskContentPrompt({
|
||||
taskId,
|
||||
task,
|
||||
success: result.success,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { z } from "zod";
|
||||
import { UUID_V4_REGEX } from "../../utils/regex.js";
|
||||
import {
|
||||
getTaskById,
|
||||
updateTaskStatus,
|
||||
@ -11,7 +12,9 @@ import { getVerifyTaskPrompt } from "../../prompts/index.js";
|
||||
export const verifyTaskSchema = z.object({
|
||||
taskId: z
|
||||
.string()
|
||||
.uuid({ message: "任務ID格式無效,請提供有效的UUID格式" })
|
||||
.regex(UUID_V4_REGEX, {
|
||||
message: "任務ID格式無效,請提供有效的UUID v4格式",
|
||||
})
|
||||
.describe("待驗證任務的唯一標識符,必須是系統中存在的有效任務ID"),
|
||||
summary: z
|
||||
.string()
|
||||
@ -66,7 +69,7 @@ export async function verifyTask({
|
||||
}
|
||||
|
||||
// 使用prompt生成器獲取最終prompt
|
||||
const prompt = getVerifyTaskPrompt({ task, score, summary });
|
||||
const prompt = await getVerifyTaskPrompt({ task, score, summary });
|
||||
|
||||
return {
|
||||
content: [
|
||||
|
@ -35,7 +35,7 @@ export const processThoughtSchema = z.object({
|
||||
message: "思維階段不能為空,請提供有效的思考階段",
|
||||
})
|
||||
.describe(
|
||||
"思考階段,可以選擇的階段有:問題定義、收集資訊、研究、分析、綜合、結論、質疑、規劃"
|
||||
"Thinking stage. Available stages include: Problem Definition, Information Gathering, Research, Analysis, Synthesis, Conclusion, Critical Questioning, and Planning."
|
||||
),
|
||||
tags: z.array(z.string()).optional().describe("思維標籤,是一個陣列字串"),
|
||||
axioms_used: z
|
||||
@ -74,7 +74,7 @@ export async function processThought(
|
||||
}
|
||||
|
||||
// 格式化思維輸出
|
||||
const formattedThought = getProcessThoughtPrompt(thoughtData);
|
||||
const formattedThought = await getProcessThoughtPrompt(thoughtData);
|
||||
|
||||
// 返回成功響應
|
||||
return {
|
||||
|
@ -1,9 +1,9 @@
|
||||
// 任務狀態枚舉:定義任務在工作流程中的當前階段
|
||||
export enum TaskStatus {
|
||||
PENDING = "待處理", // 已創建但尚未開始執行的任務
|
||||
IN_PROGRESS = "進行中", // 當前正在執行的任務
|
||||
COMPLETED = "已完成", // 已成功完成並通過驗證的任務
|
||||
BLOCKED = "被阻擋", // 由於依賴關係而暫時無法執行的任務
|
||||
PENDING = "pending", // 已創建但尚未開始執行的任務
|
||||
IN_PROGRESS = "in_progress", // 當前正在執行的任務
|
||||
COMPLETED = "completed", // 已成功完成並通過驗證的任務
|
||||
BLOCKED = "blocked", // 由於依賴關係而暫時無法執行的任務
|
||||
}
|
||||
|
||||
// 任務依賴關係:定義任務之間的前置條件關係
|
||||
|
@ -1,40 +0,0 @@
|
||||
import fs from "fs/promises";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
// 獲取項目根目錄路徑
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const PROJECT_ROOT = path.resolve(__dirname, "../..");
|
||||
|
||||
// 獲取數據目錄路徑
|
||||
const DATA_DIR = process.env.DATA_DIR || path.join(PROJECT_ROOT, "data");
|
||||
|
||||
/**
|
||||
* 獲取規則文件路徑
|
||||
* @returns 規則文件的完整路徑
|
||||
*/
|
||||
export function getRulesFilePath(): string {
|
||||
return path.join(DATA_DIR, "rules.md");
|
||||
}
|
||||
|
||||
/**
|
||||
* 確保規則文件存在
|
||||
* 如果文件不存在,會嘗試從根目錄複製,或創建空文件
|
||||
*/
|
||||
export async function ensureRulesFileExists(): Promise<void> {
|
||||
const dataRulesPath = getRulesFilePath();
|
||||
|
||||
try {
|
||||
// 檢查 DATA_DIR 目錄中是否存在規則文件
|
||||
await fs.access(dataRulesPath);
|
||||
} catch (error) {
|
||||
// DATA_DIR 目錄中不存在規則文件
|
||||
await fs.mkdir(path.dirname(dataRulesPath), { recursive: true });
|
||||
await fs.writeFile(
|
||||
dataRulesPath,
|
||||
"# 開發守則\n\n請在此文件中定義專案規範。",
|
||||
"utf-8"
|
||||
);
|
||||
}
|
||||
}
|
116
src/utils/paths.ts
Normal file
116
src/utils/paths.ts
Normal file
@ -0,0 +1,116 @@
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
||||
import fs from "fs";
|
||||
|
||||
// 取得專案根目錄
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const PROJECT_ROOT = path.resolve(__dirname, "../..");
|
||||
|
||||
// 全局 server 實例
|
||||
let globalServer: Server | null = null;
|
||||
|
||||
/**
|
||||
* 設置全局 server 實例
|
||||
*/
|
||||
export function setGlobalServer(server: Server): void {
|
||||
globalServer = server;
|
||||
}
|
||||
|
||||
/**
|
||||
* 獲取全局 server 實例
|
||||
*/
|
||||
export function getGlobalServer(): Server | null {
|
||||
return globalServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取得 DATA_DIR 路徑
|
||||
* 如果有 server 且支援 listRoots,則使用第一筆 file:// 開頭的 root + "/data"
|
||||
* 否則使用環境變數或專案根目錄
|
||||
*/
|
||||
export async function getDataDir(): Promise<string> {
|
||||
const server = getGlobalServer();
|
||||
let rootPath: string | null = null;
|
||||
|
||||
if (server) {
|
||||
try {
|
||||
const roots = await server.listRoots();
|
||||
|
||||
// 找出第一筆 file:// 開頭的 root
|
||||
if (roots.roots && roots.roots.length > 0) {
|
||||
const firstFileRoot = roots.roots.find((root) =>
|
||||
root.uri.startsWith("file://")
|
||||
);
|
||||
if (firstFileRoot) {
|
||||
// 從 file:// URI 中提取實際路徑
|
||||
rootPath = firstFileRoot.uri.replace("file://", "");
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to get roots:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// 處理 process.env.DATA_DIR
|
||||
if (process.env.DATA_DIR) {
|
||||
if (path.isAbsolute(process.env.DATA_DIR)) {
|
||||
// 如果 DATA_DIR 是絕對路徑,返回 "DATA_DIR/rootPath最後一個資料夾名稱"
|
||||
if (rootPath) {
|
||||
const lastFolderName = path.basename(rootPath);
|
||||
return path.join(process.env.DATA_DIR, lastFolderName);
|
||||
} else {
|
||||
// 如果沒有 rootPath,直接返回 DATA_DIR
|
||||
return process.env.DATA_DIR;
|
||||
}
|
||||
} else {
|
||||
// 如果 DATA_DIR 是相對路徑,返回 "rootPath/DATA_DIR"
|
||||
if (rootPath) {
|
||||
return path.join(rootPath, process.env.DATA_DIR);
|
||||
} else {
|
||||
// 如果沒有 rootPath,使用 PROJECT_ROOT
|
||||
return path.join(PROJECT_ROOT, process.env.DATA_DIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果沒有 DATA_DIR,使用預設邏輯
|
||||
if (rootPath) {
|
||||
return path.join(rootPath, "data");
|
||||
}
|
||||
|
||||
// 最後回退到專案根目錄
|
||||
return path.join(PROJECT_ROOT, "data");
|
||||
}
|
||||
|
||||
/**
|
||||
* 取得任務檔案路徑
|
||||
*/
|
||||
export async function getTasksFilePath(): Promise<string> {
|
||||
const dataDir = await getDataDir();
|
||||
return path.join(dataDir, "tasks.json");
|
||||
}
|
||||
|
||||
/**
|
||||
* 取得記憶體資料夾路徑
|
||||
*/
|
||||
export async function getMemoryDir(): Promise<string> {
|
||||
const dataDir = await getDataDir();
|
||||
return path.join(dataDir, "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* 取得 WebGUI 檔案路徑
|
||||
*/
|
||||
export async function getWebGuiFilePath(): Promise<string> {
|
||||
const dataDir = await getDataDir();
|
||||
return path.join(dataDir, "WebGUI.md");
|
||||
}
|
||||
|
||||
/**
|
||||
* 取得專案根目錄
|
||||
*/
|
||||
export function getProjectRoot(): string {
|
||||
return PROJECT_ROOT;
|
||||
}
|
2
src/utils/regex.ts
Normal file
2
src/utils/regex.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const UUID_V4_REGEX =
|
||||
/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/;
|
153
src/web/webServer.ts
Normal file
153
src/web/webServer.ts
Normal file
@ -0,0 +1,153 @@
|
||||
import express, { Request, Response } from "express";
|
||||
import getPort from "get-port";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import fsPromises from "fs/promises";
|
||||
import { fileURLToPath } from "url";
|
||||
import {
|
||||
getDataDir,
|
||||
getTasksFilePath,
|
||||
getWebGuiFilePath,
|
||||
} from "../utils/paths.js";
|
||||
|
||||
export async function createWebServer() {
|
||||
// 創建 Express 應用
|
||||
const app = express();
|
||||
|
||||
// 儲存 SSE 客戶端的列表
|
||||
let sseClients: Response[] = [];
|
||||
|
||||
// 發送 SSE 事件的輔助函數
|
||||
function sendSseUpdate() {
|
||||
sseClients.forEach((client) => {
|
||||
// 檢查客戶端是否仍然連接
|
||||
if (!client.writableEnded) {
|
||||
client.write(
|
||||
`event: update\ndata: ${JSON.stringify({
|
||||
timestamp: Date.now(),
|
||||
})}\n\n`
|
||||
);
|
||||
}
|
||||
});
|
||||
// 清理已斷開的客戶端 (可選,但建議)
|
||||
sseClients = sseClients.filter((client) => !client.writableEnded);
|
||||
}
|
||||
|
||||
// 設置靜態文件目錄
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const publicPath = path.join(__dirname, "..", "..", "src", "public");
|
||||
const TASKS_FILE_PATH = await getTasksFilePath(); // 使用工具函數取得檔案路徑
|
||||
|
||||
app.use(express.static(publicPath));
|
||||
|
||||
// 設置 API 路由
|
||||
app.get("/api/tasks", async (req: Request, res: Response) => {
|
||||
try {
|
||||
// 使用 fsPromises 保持異步讀取
|
||||
const tasksData = await fsPromises.readFile(TASKS_FILE_PATH, "utf-8");
|
||||
res.json(JSON.parse(tasksData));
|
||||
} catch (error) {
|
||||
// 確保檔案不存在時返回空任務列表
|
||||
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
||||
res.json({ tasks: [] });
|
||||
} else {
|
||||
res.status(500).json({ error: "Failed to read tasks data" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 新增:SSE 端點
|
||||
app.get("/api/tasks/stream", (req: Request, res: Response) => {
|
||||
res.writeHead(200, {
|
||||
"Content-Type": "text/event-stream",
|
||||
"Cache-Control": "no-cache",
|
||||
Connection: "keep-alive",
|
||||
// 可選: CORS 頭,如果前端和後端不在同一個 origin
|
||||
// "Access-Control-Allow-Origin": "*",
|
||||
});
|
||||
|
||||
// 發送一個初始事件或保持連接
|
||||
res.write("data: connected\n\n");
|
||||
|
||||
// 將客戶端添加到列表
|
||||
sseClients.push(res);
|
||||
|
||||
// 當客戶端斷開連接時,將其從列表中移除
|
||||
req.on("close", () => {
|
||||
sseClients = sseClients.filter((client) => client !== res);
|
||||
});
|
||||
});
|
||||
|
||||
// 定義 writeWebGuiFile 函數
|
||||
async function writeWebGuiFile(port: number | string) {
|
||||
try {
|
||||
// 讀取 TEMPLATES_USE 環境變數並轉換為語言代碼
|
||||
const templatesUse = process.env.TEMPLATES_USE || "en";
|
||||
const getLanguageFromTemplate = (template: string): string => {
|
||||
if (template === "zh") return "zh-TW";
|
||||
if (template === "en") return "en";
|
||||
// 自訂範本預設使用英文
|
||||
return "en";
|
||||
};
|
||||
const language = getLanguageFromTemplate(templatesUse);
|
||||
|
||||
const websiteUrl = `[Task Manager UI](http://localhost:${port}?lang=${language})`;
|
||||
const websiteFilePath = await getWebGuiFilePath();
|
||||
const DATA_DIR = await getDataDir();
|
||||
try {
|
||||
await fsPromises.access(DATA_DIR);
|
||||
} catch (error) {
|
||||
await fsPromises.mkdir(DATA_DIR, { recursive: true });
|
||||
}
|
||||
await fsPromises.writeFile(websiteFilePath, websiteUrl, "utf-8");
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
return {
|
||||
app,
|
||||
sendSseUpdate,
|
||||
async startServer() {
|
||||
// 獲取可用埠
|
||||
const port = process.env.WEB_PORT || (await getPort());
|
||||
|
||||
// 啟動 HTTP 伺服器
|
||||
const httpServer = app.listen(port, () => {
|
||||
// 在伺服器啟動後開始監聽檔案變化
|
||||
try {
|
||||
// 檢查檔案是否存在,如果不存在則不監聽 (避免 watch 報錯)
|
||||
if (fs.existsSync(TASKS_FILE_PATH)) {
|
||||
fs.watch(TASKS_FILE_PATH, (eventType, filename) => {
|
||||
if (
|
||||
filename &&
|
||||
(eventType === "change" || eventType === "rename")
|
||||
) {
|
||||
// 稍微延遲發送,以防短時間內多次觸發 (例如編輯器保存)
|
||||
// debounce sendSseUpdate if needed
|
||||
sendSseUpdate();
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (watchError) {}
|
||||
|
||||
// 將 URL 寫入 WebGUI.md
|
||||
writeWebGuiFile(port).catch((error) => {});
|
||||
});
|
||||
|
||||
// 設置進程終止事件處理 (確保移除 watcher)
|
||||
const shutdownHandler = async () => {
|
||||
// 關閉所有 SSE 連接
|
||||
sseClients.forEach((client) => client.end());
|
||||
sseClients = [];
|
||||
|
||||
// 關閉 HTTP 伺服器
|
||||
await new Promise<void>((resolve) => httpServer.close(() => resolve()));
|
||||
};
|
||||
|
||||
process.on("SIGINT", shutdownHandler);
|
||||
process.on("SIGTERM", shutdownHandler);
|
||||
|
||||
return httpServer;
|
||||
},
|
||||
};
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user