From bb4672c08bd44ee108ea27e7346be72c3f7a3a9a Mon Sep 17 00:00:00 2001 From: lwmacct Date: Thu, 4 Dec 2025 22:45:32 +0800 Subject: [PATCH] style: configure prettier and format codebase - Add .prettierrc configuration with 2-space indentation - Format TypeScript/JavaScript files in client-sdks and ui directories - Format Vue components and configuration files - Update pre-commit configuration for prettier - Fix check-yaml to allow multi-document YAML files - Remove deprecated .githooks/pre-commit in favor of pre-commit framework --- .githooks/pre-commit | 54 -- .github/workflows/go-ci.yml | 6 +- .gitignore | 5 + .golangci.yml | 2 +- .pre-commit-config.yaml | 3 +- .prettierrc | 4 + CHANGELOG.md | 5 + CLAUDE.md | 7 - README_EN.md | 54 +- client-sdks/client-js/README.md | 40 +- client-sdks/client-js/docs/API.md | 42 +- client-sdks/client-js/docs/QUICKSTART.md | 5 +- client-sdks/client-js/examples/agent-usage.ts | 40 +- .../client-js/examples/complete-usage.ts | 69 +- client-sdks/client-js/examples/eval-usage.ts | 86 +- .../client-js/examples/event-subscription.ts | 35 +- .../client-js/examples/mcp-middleware-tool.ts | 48 +- .../client-js/examples/memory-usage.ts | 32 +- .../client-js/examples/session-workflow.ts | 41 +- .../client-js/src/events/subscription.ts | 25 +- client-sdks/client-js/src/events/types.ts | 25 +- client-sdks/client-js/src/index.ts | 6 +- client-sdks/client-js/src/resources/agent.ts | 77 +- client-sdks/client-js/src/resources/base.ts | 43 +- client-sdks/client-js/src/resources/eval.ts | 100 +-- client-sdks/client-js/src/resources/mcp.ts | 73 +- client-sdks/client-js/src/resources/memory.ts | 77 +- .../client-js/src/resources/middleware.ts | 40 +- .../client-js/src/resources/session.ts | 68 +- .../client-js/src/resources/telemetry.ts | 99 +-- client-sdks/client-js/src/resources/tool.ts | 61 +- .../client-js/src/resources/workflow.ts | 66 +- .../client-js/src/transport/websocket.ts | 30 +- client-sdks/client-js/src/types/agent.ts | 7 +- client-sdks/client-js/src/types/mcp.ts | 7 +- client-sdks/client-js/src/types/memory.ts | 6 +- client-sdks/client-js/src/types/middleware.ts | 4 +- client-sdks/client-js/src/types/workflow.ts | 5 +- .../tests/integration/client.test.ts | 5 +- .../client-js/tests/resources/memory.test.ts | 20 +- client-sdks/client-js/vitest.config.ts | 8 +- docs/components/AppHeader.vue | 6 +- docs/content/05.tools/2.builtin/1.builtin.md | 23 +- docs/content/11.evals/1.overview/index.md | 8 +- docs/content/16.whitepaper/1.whitepaper.md | 3 +- docs/content/18.architecture/4.client-sdk.md | 31 +- docs/tailwind.config.js | 20 +- examples/actor/README.md | 28 +- examples/agent-working-memory/README.md | 37 +- examples/agent/README.md | 3 + examples/cloud-sandbox/README.md | 38 +- examples/human-in-the-loop/README.md | 9 +- examples/mcp/README.md | 6 + examples/memory-working/README.md | 23 +- examples/model-fallback/README.md | 36 +- examples/openrouter/README.md | 12 +- examples/plan-explore-ui/static/index.html | 5 +- examples/plan-explore-ui/static/main.js | 14 +- examples/ptc/README.md | 15 + examples/skills/README.md | 3 + examples/tool-cache/README.md | 69 +- pkg/asteros/README.md | 22 +- server/README.md | 45 +- server/deploy/docker/docker-compose.yml | 2 +- server/deploy/k8s/deployment.yaml | 106 +-- server/deploy/k8s/service.yaml | 24 +- ui/README.md | 16 +- ui/eslint.config.js | 31 +- ui/index.html | 20 +- ui/postcss.config.js | 2 +- .../__tests__/composables/useDarkMode.spec.ts | 24 +- ui/src/__tests__/utils/format.spec.ts | 34 +- ui/src/components/Agent/AgentCard.vue | 69 +- ui/src/components/Agent/AgentChatSession.vue | 46 +- ui/src/components/Agent/AgentDashboard.vue | 70 +- ui/src/components/Agent/AgentForm.vue | 139 ++-- ui/src/components/Agent/AgentList.vue | 49 +- ui/src/components/Agent/AgentLoopDemo.vue | 104 +-- ui/src/components/Agent/ThinkingBlock.vue | 77 +- ui/src/components/Agent/index.ts | 12 +- ui/src/components/AsterChat.vue | 167 ++-- ui/src/components/Chat/Chat.vue | 79 +- ui/src/components/Chat/Composer.vue | 83 +- ui/src/components/Chat/MessageBubble.vue | 99 +-- ui/src/components/Chat/MessageList.vue | 95 +-- ui/src/components/Chat/QuickReplies.vue | 15 +- ui/src/components/Chat/index.ts | 10 +- ui/src/components/ChatUI/Avatar.vue | 36 +- ui/src/components/ChatUI/Bubble.vue | 27 +- ui/src/components/ChatUI/Button.vue | 36 +- ui/src/components/ChatUI/Card.vue | 7 +- ui/src/components/ChatUI/Carousel.vue | 29 +- ui/src/components/ChatUI/Chat.vue | 151 ++-- ui/src/components/ChatUI/Checkbox.vue | 12 +- ui/src/components/ChatUI/Divider.vue | 10 +- ui/src/components/ChatUI/Dropdown.vue | 33 +- ui/src/components/ChatUI/FileCard.vue | 11 +- ui/src/components/ChatUI/Flex.vue | 48 +- ui/src/components/ChatUI/Icon.vue | 173 +++- ui/src/components/ChatUI/Image.vue | 37 +- ui/src/components/ChatUI/Input.vue | 19 +- ui/src/components/ChatUI/List.vue | 7 +- ui/src/components/ChatUI/MessageStatus.vue | 12 +- ui/src/components/ChatUI/Modal.vue | 36 +- ui/src/components/ChatUI/MultimodalInput.vue | 88 +- ui/src/components/ChatUI/Navbar.vue | 8 +- ui/src/components/ChatUI/Notice.vue | 24 +- ui/src/components/ChatUI/Popover.vue | 14 +- ui/src/components/ChatUI/Progress.vue | 17 +- ui/src/components/ChatUI/README.md | 82 +- ui/src/components/ChatUI/Radio.vue | 14 +- ui/src/components/ChatUI/RichText.vue | 4 +- ui/src/components/ChatUI/ScrollView.vue | 32 +- ui/src/components/ChatUI/Search.vue | 44 +- ui/src/components/ChatUI/Sidebar.vue | 16 +- ui/src/components/ChatUI/Tabs.vue | 24 +- ui/src/components/ChatUI/Tag.vue | 28 +- ui/src/components/ChatUI/ThinkBubble.vue | 7 +- ui/src/components/ChatUI/Tooltip.vue | 14 +- ui/src/components/ChatUI/Typing.vue | 6 +- ui/src/components/ChatUI/TypingBubble.vue | 4 +- ui/src/components/ChatUI/index.ts | 68 +- ui/src/components/Common/EmptyState.vue | 11 +- ui/src/components/Common/ErrorBoundary.vue | 30 +- ui/src/components/Common/LoadingSpinner.vue | 51 +- ui/src/components/Common/Modal.vue | 6 +- .../Common/NotificationContainer.vue | 18 +- ui/src/components/Common/index.ts | 2 +- ui/src/components/DocViewer.vue | 37 +- ui/src/components/Editor/EditorPanel.vue | 90 +-- ui/src/components/Editor/MarkdownEditor.vue | 128 ++- ui/src/components/Editor/MarkdownPreview.vue | 21 +- ui/src/components/Editor/index.ts | 6 +- ui/src/components/Message/CardMessage.vue | 38 +- ui/src/components/Message/ImageMessage.vue | 30 +- ui/src/components/Message/ListMessage.vue | 40 +- ui/src/components/Message/SystemMessage.vue | 12 +- ui/src/components/Message/ThinkingMessage.vue | 79 +- ui/src/components/Message/index.ts | 10 +- ui/src/components/MessageItem.vue | 74 +- ui/src/components/Planning/PlanModeView.vue | 6 +- ui/src/components/Project/ProjectCard.vue | 83 +- ui/src/components/Project/ProjectList.vue | 75 +- ui/src/components/Project/index.ts | 4 +- ui/src/components/Room/RoomList.vue | 59 +- ui/src/components/Room/index.ts | 2 +- .../components/Settings/ProviderSelector.vue | 50 +- ui/src/components/Thinking/ApprovalCard.vue | 60 +- .../Thinking/AskUserQuestionCard.vue | 82 +- ui/src/components/Thinking/ThinkingBlock.vue | 63 +- ui/src/components/Thinking/ThinkingStep.vue | 148 +--- .../components/Thinking/ThinkingTimeline.vue | 17 +- ui/src/components/Thinking/index.ts | 8 +- ui/src/components/ThinkingBlock.vue | 90 +-- ui/src/components/Tools/AskUserTool.vue | 94 +-- ui/src/components/Tools/BashOutputTool.vue | 357 ++++----- ui/src/components/Tools/BashTool.vue | 294 ++++--- ui/src/components/Tools/EditTool.vue | 756 +++++++----------- ui/src/components/Tools/ExploreTool.vue | 321 +++----- ui/src/components/Tools/GlobTool.vue | 137 +--- ui/src/components/Tools/GrepTool.vue | 152 +--- ui/src/components/Tools/HTTPRequestTool.vue | 703 ++++++---------- ui/src/components/Tools/KillShellTool.vue | 623 +++++++-------- ui/src/components/Tools/PlanTool.vue | 321 ++++---- ui/src/components/Tools/ReadTool.vue | 282 +++---- .../components/Tools/SemanticSearchTool.vue | 406 ++++------ ui/src/components/Tools/SkillCallTool.vue | 658 +++++++-------- ui/src/components/Tools/TaskTool.vue | 248 +++--- ui/src/components/Tools/TodoTool.vue | 304 +++---- ui/src/components/Tools/WebSearchTool.vue | 383 ++++----- ui/src/components/Tools/WriteTool.vue | 555 +++++-------- ui/src/components/Workflow/WorkflowCard.vue | 78 +- ui/src/components/Workflow/WorkflowList.vue | 49 +- .../components/Workflow/WorkflowProgress.vue | 29 +- .../Workflow/WorkflowProgressView.vue | 50 +- ui/src/components/Workflow/WorkflowStep.vue | 128 +-- .../components/Workflow/WorkflowTimeline.vue | 84 +- ui/src/components/Workflow/index.ts | 12 +- ui/src/composables/index.ts | 28 +- ui/src/composables/useAgentLoop.ts | 150 ++-- ui/src/composables/useAsterClient.ts | 77 +- ui/src/composables/useChat.ts | 324 ++++---- ui/src/composables/useChatV2.ts | 220 +++-- ui/src/composables/useClipboard.ts | 8 +- ui/src/composables/useDarkMode.ts | 46 +- ui/src/composables/useDebounce.ts | 12 +- ui/src/composables/useLocalStorage.ts | 13 +- ui/src/composables/useMessage.ts | 60 +- ui/src/composables/useNotification.ts | 18 +- ui/src/composables/useScroll.ts | 10 +- ui/src/composables/useThrottle.ts | 16 +- ui/src/composables/useWebSocket.ts | 26 +- ui/src/config/demoData.ts | 148 ++-- ui/src/docs/README.md | 108 ++- ui/src/docs/components/AgentCard.md | 96 +-- ui/src/docs/components/Avatar.md | 20 +- ui/src/docs/components/Bubble.md | 31 +- ui/src/docs/components/Button.md | 22 +- ui/src/docs/components/Card.md | 45 +- ui/src/docs/components/Carousel.md | 79 +- ui/src/docs/components/Chat.md | 133 ++- ui/src/docs/components/Checkbox.md | 72 +- ui/src/docs/components/Divider.md | 12 +- ui/src/docs/components/Dropdown.md | 55 +- ui/src/docs/components/FileCard.md | 50 +- ui/src/docs/components/Flex.md | 30 +- ui/src/docs/components/Icon.md | 28 +- ui/src/docs/components/Image.md | 48 +- ui/src/docs/components/Input.md | 48 +- ui/src/docs/components/List.md | 44 +- ui/src/docs/components/MessageStatus.md | 88 +- ui/src/docs/components/Modal.md | 74 +- ui/src/docs/components/MultimodalInput.md | 124 ++- ui/src/docs/components/Navbar.md | 26 +- ui/src/docs/components/Notice.md | 33 +- ui/src/docs/components/Popover.md | 59 +- ui/src/docs/components/Progress.md | 46 +- ui/src/docs/components/ProjectCard.md | 131 +-- ui/src/docs/components/Radio.md | 56 +- ui/src/docs/components/RichText.md | 6 +- ui/src/docs/components/RoomCard.md | 87 +- ui/src/docs/components/ScrollView.md | 75 +- ui/src/docs/components/Search.md | 68 +- ui/src/docs/components/Sidebar.md | 65 +- ui/src/docs/components/SystemMessage.md | 46 +- ui/src/docs/components/Tabs.md | 75 +- ui/src/docs/components/Tag.md | 43 +- ui/src/docs/components/ThinkBubble.md | 16 +- ui/src/docs/components/ThinkingBlock.md | 133 ++- ui/src/docs/components/Tooltip.md | 20 +- ui/src/docs/components/Typing.md | 120 +-- ui/src/docs/components/TypingBubble.md | 63 +- ui/src/docs/components/WorkflowCard.md | 88 +- ui/src/docs/components/WorkflowTimeline.md | 203 ++--- ui/src/index.ts | 88 +- ui/src/main.ts | 12 +- ui/src/router.ts | 64 +- ui/src/stores/approval.ts | 26 +- ui/src/stores/chat.ts | 62 +- ui/src/stores/index.ts | 12 +- ui/src/stores/thinking.ts | 26 +- ui/src/stores/todos.ts | 70 +- ui/src/stores/tools.ts | 49 +- ui/src/stores/workflow.ts | 54 +- ui/src/style.css | 26 +- ui/src/types/approval.ts | 4 +- ui/src/types/chat.ts | 6 +- ui/src/types/index.ts | 30 +- ui/src/types/message.ts | 125 ++- ui/src/types/thinking.ts | 8 +- ui/src/types/workflow.ts | 6 +- ui/src/utils/format.ts | 44 +- ui/src/utils/markdown.ts | 28 +- ui/src/utils/performance.ts | 43 +- ui/src/views/AgentChatUIDemo.vue | 720 ++++++++--------- ui/src/views/AgentManagement.vue | 13 +- ui/src/views/ChatUIComponents.vue | 433 ++++------ ui/src/views/ComponentDocs.vue | 286 +++---- ui/src/views/Home.vue | 88 +- ui/src/views/LandingPage.vue | 243 +++--- ui/src/views/ProjectManagement.vue | 128 +-- ui/src/views/RoomManagement.vue | 125 +-- ui/src/views/WorkflowManagement.vue | 181 ++--- ui/tailwind.config.js | 65 +- ui/vite.config.ts | 34 +- ui/vitest.config.ts | 29 +- ui/vitest.setup.ts | 6 +- 267 files changed, 7900 insertions(+), 11947 deletions(-) delete mode 100755 .githooks/pre-commit create mode 100644 .prettierrc diff --git a/.githooks/pre-commit b/.githooks/pre-commit deleted file mode 100755 index 53fac73..0000000 --- a/.githooks/pre-commit +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -# Pre-commit hook for Go projects -# Runs go fmt, go vet, and golangci-lint before commit - -set -e - -echo "Running pre-commit checks..." - -# 1. Format check -echo "→ Running go fmt..." -UNFORMATTED=$(gofmt -l .) -if [ -n "$UNFORMATTED" ]; then - echo "❌ The following files need formatting:" - echo "$UNFORMATTED" - echo "" - echo "Run: gofmt -w ." - exit 1 -fi -echo "✓ go fmt passed" - -# 2. Go vet -echo "→ Running go vet..." -if ! go vet ./...; then - echo "❌ go vet failed" - exit 1 -fi -echo "✓ go vet passed" - -# 3. golangci-lint (if available) -if command -v golangci-lint &> /dev/null; then - echo "→ Running golangci-lint..." - if ! golangci-lint run --timeout=5m; then - echo "❌ golangci-lint failed" - echo "" - echo "Fix the issues or run: git commit --no-verify (not recommended)" - exit 1 - fi - echo "✓ golangci-lint passed" -else - echo "⚠️ golangci-lint not found, skipping..." - echo " Install: https://golangci-lint.run/usage/install/" -fi - -# 4. Run tests (optional, can be slow) -# Uncomment if you want to run tests before every commit -# echo "→ Running tests..." -# if ! go test ./... -short; then -# echo "❌ Tests failed" -# exit 1 -# fi -# echo "✓ Tests passed" - -echo "" -echo "✅ All pre-commit checks passed!" diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index b636b69..01e01d3 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -40,7 +40,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: '1.24' + go-version: "1.24" cache: true - name: golangci-lint @@ -57,7 +57,7 @@ jobs: timeout-minutes: 10 strategy: matrix: - go-version: ['1.24'] + go-version: ["1.24"] steps: - name: Checkout code uses: actions/checkout@v4 @@ -94,7 +94,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: '1.24' + go-version: "1.24" cache: true - name: Run tests diff --git a/.gitignore b/.gitignore index b35f4f4..def2609 100644 --- a/.gitignore +++ b/.gitignore @@ -207,3 +207,8 @@ article-writer-web-service/ # claude .claude/ *_PLAN.md + +# lwmacct conventions +.local/ +.taskfile/ +Taskfile.yml diff --git a/.golangci.yml b/.golangci.yml index 8f765a7..53621b2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -4,7 +4,7 @@ version: "2" run: timeout: 5m tests: true - go: '1.21' + go: "1.21" linters: enable: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 46f3ed0..3197335 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,6 +14,7 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml + args: [--allow-multiple-documents] - id: check-added-large-files - args: ['--maxkb=1000'] + args: ["--maxkb=1000"] - id: check-merge-conflict diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..1ef6e5e --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "tabWidth": 2, + "printWidth": 256 +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b1c31f..3d62ef5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,14 +3,17 @@ ## [v0.15.0] - 2025-11-24 ### Added + - 完成15个工具的全面测试验证 - 添加工具测试文档和报告 ### Fixed + - **WebSearch工具**: 修复search_depth参数问题,从"general"改为"basic"以符合Tavily API规范 - 验证多轮推理功能正常工作(streaming.go) ### Tested + - 网络工具: HttpRequest ✅, WebSearch ✅ - 文件工具: Read ✅, Write ✅, Edit ✅, Glob ✅, Grep ✅ - 执行工具: Bash ✅, BashOutput ✅, KillShell ✅ @@ -18,10 +21,12 @@ - 高级工具: DemoLongTask ✅, Skill ⚠️, SemanticSearch ⚠️ ### Notes + - Skill和SemanticSearch工具需要额外配置才能完整使用 - 所有核心工具调用功能已验证正常 - 系统可投入实际使用 ## [v0.14.0] - Previous Release + - 基础工具实现 - 多轮推理支持 diff --git a/CLAUDE.md b/CLAUDE.md index 001e04b..441ad01 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -68,44 +68,37 @@ Aster is an event-driven AI Agent framework built with Go, implementing the Goog ### Key Components 1. **Agent System** (`pkg/agent/`) - - Core agent implementation with event-driven architecture - Three event channels: Progress (real-time output), Control (human interaction), Monitor (governance) - Dependencies injection pattern with Registry pattern for tools and templates 2. **Workflow Engine** (`pkg/workflow/`) - - Sequential, Parallel, and Loop workflow agents - 8-step types with Router for dynamic routing - Stream-based execution with Go 1.23 iter.Seq2 3. **Memory Management** (`pkg/memory/`) - - Three-tier system: Text Memory, Working Memory, Semantic Memory - Advanced features: Provenance (source tracking), Consolidation (LLM-driven merging), PII Auto-Redaction - Vector store integration with confidence scoring 4. **Middleware System** (`pkg/middleware/`) - - Onion-model architecture with priority-based layers - Built-in middlewares: filesystem, summarization, agent memory, working memory - Custom middleware support via WrapModelCall/WrapToolCall interfaces 5. **Tools System** (`pkg/tools/`) - - Registry pattern for tool discovery and management - Built-in tools: filesystem operations, bash execution, HTTP requests, web search, todo management - MCP (Model Context Protocol) support for external tool integration - Long-running tools with async execution and progress tracking 6. **Session & Persistence** (`pkg/session/`) - - PostgreSQL and MySQL support with JSONB/JSON columns - Event sourcing with append-only storage - 7-point recovery mechanism for fault tolerance 7. **Multi-Agent Collaboration** (`pkg/stars/`) - - Stars pattern for agent collaboration - Scheduler for intelligent task distribution - Permission management system diff --git a/README_EN.md b/README_EN.md index b40bb20..7b6a31c 100644 --- a/README_EN.md +++ b/README_EN.md @@ -21,6 +21,7 @@ **Aster** (星尘云枢) is a production-ready AI Agent development framework built with Go, designed to run agents safely and efficiently in enterprise environments. Like stardust converging to form a celestial hub, Aster brings together: + - **High Performance**: Go's concurrency model supports 100+ concurrent agents - **Native Script Execution**: Run Python, TypeScript, and Bash natively with full sandbox isolation - **Event-Driven Architecture**: Progress/Control/Monitor tri-channel design for clear separation of concerns @@ -29,33 +30,39 @@ Like stardust converging to form a celestial hub, Aster brings together: ## 🎯 Core Features ### 🚀 Multi-Language Script Execution + - **Python**: Execute data processing, ML workflows, and analytics scripts -- **TypeScript**: Run modern JavaScript/TypeScript for web automation and API interactions +- **TypeScript**: Run modern JavaScript/TypeScript for web automation and API interactions - **Bash**: Shell commands for system operations and DevOps tasks - All with **native performance** and **isolated sandbox environments** ### 🎪 Event-Driven Architecture + - **Progress Channel**: Real-time text streaming, tool execution progress - **Control Channel**: Tool approval requests, human-in-the-loop interactions - **Monitor Channel**: Governance events, error tracking, audit logs ### 🧅 Middleware Onion Model + - **Layered Processing**: Requests and responses flow through middleware layers - **Built-in Middlewares**: Auto-summarization, PII redaction, tool interception - **Extensible**: Create custom middleware for your specific needs ### 🔒 Enterprise-Grade Security + - **Cloud Sandbox**: Native integration with Aliyun AgentBay, Volcengine - **PII Auto-Redaction**: Detect and redact 10+ types of sensitive data - **Permission System**: Fine-grained tool-level access control - **Audit Logging**: Complete tool call tracking and state management ### 🧠 Three-Layer Memory System + - **Text Memory**: File-based short-term memory for conversation context - **Working Memory**: Persistent state across sessions with TTL and JSON schema - **Semantic Memory**: Vector-based long-term memory with provenance tracking ### 🔄 Advanced Capabilities + - **Streaming API**: iter.Seq2-based streaming with 80%+ memory reduction - **Long-Running Tools**: Async task management with progress tracking - **Multi-Agent Orchestration**: Pool/Room/Workflow collaboration patterns @@ -91,7 +98,7 @@ func main() { // 1. Setup dependencies toolRegistry := tools.NewRegistry() builtin.RegisterAll(toolRegistry) - + jsonStore, _ := store.NewJSONStore("./.aster") deps := &agent.Dependencies{ Store: jsonStore, @@ -162,6 +169,7 @@ func main() { ![Middleware Onion](https://raw.githubusercontent.com/astercloud/aster/main/docs/public/images/middleware-onion.svg) The middleware architecture processes each request/response through multiple layers: + - Higher priority middleware sits in outer layers - Handles requests first, processes responses last - Clean separation of concerns and easy extensibility @@ -169,6 +177,7 @@ The middleware architecture processes each request/response through multiple lay ## 🌐 Multi-Language Execution ### Python Script Example + ```python # agent can execute this directly import pandas as pd @@ -179,6 +188,7 @@ print(result.to_json()) ``` ### TypeScript Example + ```typescript // Native TypeScript execution interface User { @@ -186,11 +196,12 @@ interface User { email: string; } -const users: User[] = await fetch('/api/users').then(r => r.json()); -console.log(users.map(u => u.name)); +const users: User[] = await fetch("/api/users").then((r) => r.json()); +console.log(users.map((u) => u.name)); ``` ### Bash Example + ```bash # System operations find . -name "*.log" -mtime +7 -delete @@ -203,15 +214,16 @@ docker ps | grep running ### Completed Phases -✅ **Phase 1**: Foundation (Event system, Sandbox abstraction, Storage) -✅ **Phase 2**: Agent Runtime (Message processing, Tool system, Streaming) -✅ **Phase 3**: Cloud Integration (MCP, Aliyun, Volcengine) -✅ **Phase 4**: Multi-Agent (Pool, Room, Scheduler, Permissions) -✅ **Phase 5**: MCP Support (Protocol, Servers, Tools) -✅ **Phase 6**: Advanced Features (Commands, Skills, Middleware, Multi-provider) +✅ **Phase 1**: Foundation (Event system, Sandbox abstraction, Storage) +✅ **Phase 2**: Agent Runtime (Message processing, Tool system, Streaming) +✅ **Phase 3**: Cloud Integration (MCP, Aliyun, Volcengine) +✅ **Phase 4**: Multi-Agent (Pool, Room, Scheduler, Permissions) +✅ **Phase 5**: MCP Support (Protocol, Servers, Tools) +✅ **Phase 6**: Advanced Features (Commands, Skills, Middleware, Multi-provider) ✅ **Phase 7**: ADK Alignment (Streaming, OpenTelemetry, Persistence, Workflows) **Current Stats**: + - ~18,000+ LOC - 25+ new modules - 80%+ test coverage @@ -221,16 +233,16 @@ docker ps | grep running Aster fully implements the **Google Context Engineering** whitepaper's 8 core capabilities: -| Capability | Status | Description | -|------------|--------|-------------| -| Sessions & Memory | ✅ | Three-layer memory system (Text/Working/Semantic) | -| Memory Provenance | ✅ | Source tracking with confidence scoring | -| Memory Consolidation | ✅ | LLM-driven intelligent memory merging | -| PII Auto-Redaction | ✅ | Automated privacy data protection | -| Event-Driven Architecture | ✅ | Progress/Control/Monitor tri-channel | -| Streaming & Backpressure | ✅ | iter.Seq2 streaming interface | -| Multi-Agent Orchestration | ✅ | Pool/Room/Workflow patterns | -| Observability | ✅ | Complete OpenTelemetry integration | +| Capability | Status | Description | +| ------------------------- | ------ | ------------------------------------------------- | +| Sessions & Memory | ✅ | Three-layer memory system (Text/Working/Semantic) | +| Memory Provenance | ✅ | Source tracking with confidence scoring | +| Memory Consolidation | ✅ | LLM-driven intelligent memory merging | +| PII Auto-Redaction | ✅ | Automated privacy data protection | +| Event-Driven Architecture | ✅ | Progress/Control/Monitor tri-channel | +| Streaming & Backpressure | ✅ | iter.Seq2 streaming interface | +| Multi-Agent Orchestration | ✅ | Pool/Room/Workflow patterns | +| Observability | ✅ | Complete OpenTelemetry integration | **100% Implementation** - First Go framework to fully implement the standard. @@ -239,11 +251,13 @@ Aster fully implements the **Google Context Engineering** whitepaper's 8 core ca Aster builds upon the excellent work of the open-source community: ### Frameworks + - **[LangChain](https://github.com/langchain-ai/langchain)**: Pioneering agent framework - **[Google ADK](https://github.com/google/genkit)**: Enterprise-grade agent toolkit - **[Claude Agent SDK](https://github.com/anthropics/anthropic-sdk-python)**: Computer Use & MCP reference ### Research + Special thanks to the **[Google Context Engineering Whitepaper](https://cloud.google.com/blog/products/ai-machine-learning/context-engineering-for-ai-agents)** for defining agent capabilities and best practices. ## 📄 License diff --git a/client-sdks/client-js/README.md b/client-sdks/client-js/README.md index 3ad28a9..ed8f54d 100644 --- a/client-sdks/client-js/README.md +++ b/client-sdks/client-js/README.md @@ -242,13 +242,10 @@ await client.skill.deleteVersion('my-skill', 'v1.0'); ```typescript // 订阅事件(三通道) -const subscription = await client.agent.subscribe( - ["progress", "control", "monitor"], - { - agentId: "agent-123", - eventTypes: ["thinking", "text_chunk", "tool_start"], - }, -); +const subscription = await client.agent.subscribe(["progress", "control", "monitor"], { + agentId: "agent-123", + eventTypes: ["thinking", "text_chunk", "tool_start"], +}); // 处理事件 for await (const event of subscription) { @@ -367,23 +364,17 @@ await client.memory.working.delete("user_preference", "thread"); ```typescript // 存储记忆 -const chunkId = await client.memory.semantic.store( - "Paris is the capital of France.", - { - source: "wikipedia", - category: "geography", - }, -); +const chunkId = await client.memory.semantic.store("Paris is the capital of France.", { + source: "wikipedia", + category: "geography", +}); // 语义搜索 -const results = await client.memory.semantic.search( - "What is the capital of France?", - { - limit: 10, - threshold: 0.8, - filter: { category: "geography" }, - }, -); +const results = await client.memory.semantic.search("What is the capital of France?", { + limit: 10, + threshold: 0.8, + filter: { category: "geography" }, +}); console.log(results); // [ @@ -495,10 +486,7 @@ await client.workflow.resume(parallelWorkflow.id, run.id); // 获取执行历史 const runs = await client.workflow.getRuns(parallelWorkflow.id); -const runDetails = await client.workflow.getRunDetails( - parallelWorkflow.id, - run.id, -); +const runDetails = await client.workflow.getRunDetails(parallelWorkflow.id, run.id); ``` --- diff --git a/client-sdks/client-js/docs/API.md b/client-sdks/client-js/docs/API.md index c63373a..873a023 100644 --- a/client-sdks/client-js/docs/API.md +++ b/client-sdks/client-js/docs/API.md @@ -123,14 +123,11 @@ const items = await client.memory.working.list({ #### store() - 存储语义记忆 ```typescript -await client.memory.semantic.store( - "aster is a powerful framework for building AI agents", - { - source: "documentation", - category: "introduction", - timestamp: new Date().toISOString(), - }, -); +await client.memory.semantic.store("aster is a powerful framework for building AI agents", { + source: "documentation", + category: "introduction", + timestamp: new Date().toISOString(), +}); ``` #### search() - 语义搜索 @@ -249,10 +246,7 @@ const messages = await client.sessions.getMessages("session-id", { ```typescript // 创建手动断点 -const checkpoint = await client.sessions.createCheckpoint( - "session-id", - "before-important-action", -); +const checkpoint = await client.sessions.createCheckpoint("session-id", "before-important-action"); // 获取所有断点 const checkpoints = await client.sessions.getCheckpoints("session-id"); @@ -369,14 +363,10 @@ await client.workflows.cancel("workflow-id", { ### 等待完成 ```typescript -const result = await client.workflows.waitForCompletion( - "workflow-id", - "run-id", - { - pollInterval: 2000, - timeout: 60000, - }, -); +const result = await client.workflows.waitForCompletion("workflow-id", "run-id", { + pollInterval: 2000, + timeout: 60000, +}); ``` --- @@ -435,9 +425,7 @@ await client.mcp.removeServer("server-id"); const middlewares = await client.middleware.list(); middlewares.forEach((mw) => { - console.log( - `[P${mw.priority}] ${mw.displayName} - ${mw.enabled ? "ON" : "OFF"}`, - ); + console.log(`[P${mw.priority}] ${mw.displayName} - ${mw.enabled ? "ON" : "OFF"}`); }); ``` @@ -490,13 +478,7 @@ await client.middleware.updateConfig("cost_tracker", { const order = await client.middleware.getExecutionOrder(); // 设置执行顺序 -await client.middleware.setExecutionOrder([ - "logging", - "telemetry", - "cost_tracker", - "token_limiter", - "summarization", -]); +await client.middleware.setExecutionOrder(["logging", "telemetry", "cost_tracker", "token_limiter", "summarization"]); // 重置为默认顺序 await client.middleware.resetExecutionOrder(); diff --git a/client-sdks/client-js/docs/QUICKSTART.md b/client-sdks/client-js/docs/QUICKSTART.md index e66d5ea..55dbe92 100644 --- a/client-sdks/client-js/docs/QUICKSTART.md +++ b/client-sdks/client-js/docs/QUICKSTART.md @@ -67,10 +67,7 @@ console.log(item?.value); // { theme: 'dark', language: 'zh-CN' } ```typescript // 存储 -await client.memory.semantic.store( - "aster is a powerful framework for building AI agents", - { category: "introduction" }, -); +await client.memory.semantic.store("aster is a powerful framework for building AI agents", { category: "introduction" }); // 搜索 const results = await client.memory.semantic.search("What is aster?", { diff --git a/client-sdks/client-js/examples/agent-usage.ts b/client-sdks/client-js/examples/agent-usage.ts index 09ce515..7b1df3b 100644 --- a/client-sdks/client-js/examples/agent-usage.ts +++ b/client-sdks/client-js/examples/agent-usage.ts @@ -60,8 +60,7 @@ async function main() { templateId: "researcher", llmProvider: "openai", llmModel: "gpt-4-turbo", - systemPrompt: - "You are an expert AI researcher. Provide detailed, accurate information.", + systemPrompt: "You are an expert AI researcher. Provide detailed, accurate information.", tools: ["http_request", "web_scraper"], middlewares: ["summarization", "cost_tracker"], }); @@ -81,14 +80,10 @@ async function main() { sortBy: "createdAt", sortOrder: "desc", }); - console.log( - `📋 总共 ${agents.total} 个 Agents (显示 ${agents.items.length} 个):`, - ); + console.log(`📋 总共 ${agents.total} 个 Agents (显示 ${agents.items.length} 个):`); agents.items.forEach((agent, i) => { console.log(` ${i + 1}. ${agent.name} (${agent.id})`); - console.log( - ` 状态: ${agent.status} | LLM: ${agent.llmProvider}/${agent.llmModel}`, - ); + console.log(` 状态: ${agent.status} | LLM: ${agent.llmProvider}/${agent.llmModel}`); }); // 获取 Agent 详情 @@ -133,9 +128,7 @@ async function main() { } if (chatResponse.cost) { - console.log( - ` 成本: ${chatResponse.cost.currency} ${chatResponse.cost.amount.toFixed(4)}`, - ); + console.log(` 成本: ${chatResponse.cost.currency} ${chatResponse.cost.amount.toFixed(4)}`); } console.log(` 执行时间: ${chatResponse.executionTime}ms`); @@ -200,16 +193,10 @@ async function main() { console.log("Agent 统计(过去7天):"); console.log(` 总请求数: ${stats.totalRequests}`); - console.log( - ` 成功率: ${((stats.successfulRequests / stats.totalRequests) * 100).toFixed(1)}%`, - ); + console.log(` 成功率: ${((stats.successfulRequests / stats.totalRequests) * 100).toFixed(1)}%`); console.log(` 平均响应时间: ${stats.avgResponseTime.toFixed(2)}ms`); - console.log( - ` Token 使用: ${stats.tokenUsage.totalTokens.toLocaleString()}`, - ); - console.log( - ` 总成本: ${stats.cost.currency} ${stats.cost.total.toFixed(4)}`, - ); + console.log(` Token 使用: ${stats.tokenUsage.totalTokens.toLocaleString()}`); + console.log(` 总成本: ${stats.cost.currency} ${stats.cost.total.toFixed(4)}`); if (stats.toolCalls) { console.log(` 工具调用: ${stats.toolCalls.total} 次`); @@ -230,14 +217,10 @@ async function main() { end: new Date().toISOString(), }); console.log("\n📈 所有 Agents 汇总(过去24小时):"); - console.log( - ` 总 Agents: ${aggregated.totalAgents} | 活跃: ${aggregated.activeAgents}`, - ); + console.log(` 总 Agents: ${aggregated.totalAgents} | 活跃: ${aggregated.activeAgents}`); console.log(` 总请求数: ${aggregated.totalRequests.toLocaleString()}`); console.log(` 总 Tokens: ${aggregated.totalTokens.toLocaleString()}`); - console.log( - ` 总成本: ${aggregated.currency} ${aggregated.totalCost.toFixed(2)}`, - ); + console.log(` 总成本: ${aggregated.currency} ${aggregated.totalCost.toFixed(2)}`); // ======================================================================== // 7. Agent 克隆 @@ -245,10 +228,7 @@ async function main() { console.log("\n📋 7. Agent 克隆"); console.log("-".repeat(70)); - const cloned = await client.agents.clone( - assistant.id, - "My Assistant (Clone)", - ); + const cloned = await client.agents.clone(assistant.id, "My Assistant (Clone)"); console.log("✅ Agent 已克隆:", cloned.id); console.log(" 原始 Agent:", assistant.id); console.log(" 克隆 Agent:", cloned.id); diff --git a/client-sdks/client-js/examples/complete-usage.ts b/client-sdks/client-js/examples/complete-usage.ts index 4669823..a5448e2 100644 --- a/client-sdks/client-js/examples/complete-usage.ts +++ b/client-sdks/client-js/examples/complete-usage.ts @@ -67,18 +67,12 @@ async function main() { console.log("📝 获取 Working Memory:", preference?.value); // Semantic Memory - await client.memory.semantic.store( - "AsterClient is a powerful framework for building AI agents", - { source: "documentation", category: "introduction" }, - ); + await client.memory.semantic.store("AsterClient is a powerful framework for building AI agents", { source: "documentation", category: "introduction" }); console.log("✅ Semantic Memory 已添加"); - const searchResults = await client.memory.semantic.search( - "What is AsterClient?", - { - limit: 3, - }, - ); + const searchResults = await client.memory.semantic.search("What is AsterClient?", { + limit: 3, + }); console.log(`🔍 搜索结果: ${searchResults.length} 条`); // ======================================================================== @@ -235,39 +229,16 @@ async function main() { }); console.log("📈 性能指标(过去24小时):"); console.log(" 总请求数:", performance.requests.total); - console.log( - " 成功率:", - ( - (performance.requests.successful / performance.requests.total) * - 100 - ).toFixed(1), - "%", - ); - console.log( - " 平均延迟:", - performance.requests.avgLatency.toFixed(2), - "ms", - ); - console.log( - " P95 延迟:", - performance.requests.p95Latency.toFixed(2), - "ms", - ); - console.log( - " P99 延迟:", - performance.requests.p99Latency.toFixed(2), - "ms", - ); + console.log(" 成功率:", ((performance.requests.successful / performance.requests.total) * 100).toFixed(1), "%"); + console.log(" 平均延迟:", performance.requests.avgLatency.toFixed(2), "ms"); + console.log(" P95 延迟:", performance.requests.p95Latency.toFixed(2), "ms"); + console.log(" P99 延迟:", performance.requests.p99Latency.toFixed(2), "ms"); if (performance.tokens) { console.log(" 总 Tokens:", performance.tokens.total.toLocaleString()); } if (performance.cost) { - console.log( - " 总成本:", - performance.cost.currency, - performance.cost.total.toFixed(2), - ); + console.log(" 总成本:", performance.cost.currency, performance.cost.total.toFixed(2)); } // 获取使用统计 @@ -277,21 +248,11 @@ async function main() { }); console.log("\n📊 使用统计(过去7天):"); if (usage.sessions) { - console.log( - " Sessions: 总计", - usage.sessions.total, - "| 活跃", - usage.sessions.active, - ); + console.log(" Sessions: 总计", usage.sessions.total, "| 活跃", usage.sessions.active); console.log(" 平均时长:", usage.sessions.avgDuration.toFixed(0), "秒"); } if (usage.workflows) { - console.log( - " Workflows: 成功", - usage.workflows.successful, - "| 失败", - usage.workflows.failed, - ); + console.log(" Workflows: 成功", usage.workflows.successful, "| 失败", usage.workflows.failed); } if (usage.tools) { console.log(" 工具调用:", usage.tools.total, "次"); @@ -307,9 +268,7 @@ async function main() { const metrics = await client.telemetry.listMetrics(); console.log(`\n📊 Metrics: ${metrics.length} 个`); metrics.slice(0, 5).forEach((metric, i) => { - console.log( - ` ${i + 1}. ${metric.name} (${metric.type}): ${metric.value} ${metric.unit || ""}`, - ); + console.log(` ${i + 1}. ${metric.name} (${metric.type}): ${metric.value} ${metric.unit || ""}`); }); // 查询 Traces @@ -322,9 +281,7 @@ async function main() { }); console.log(`\n🔍 Traces(过去1小时): ${traces.length} 个`); traces.forEach((trace, i) => { - console.log( - ` ${i + 1}. ${trace.operationName} - ${trace.duration}ms (${trace.status})`, - ); + console.log(` ${i + 1}. ${trace.operationName} - ${trace.duration}ms (${trace.status})`); }); } catch (error: any) { console.log("⚠️ Telemetry 查询失败:", error.message); diff --git a/client-sdks/client-js/examples/eval-usage.ts b/client-sdks/client-js/examples/eval-usage.ts index 1cc6703..2c46148 100644 --- a/client-sdks/client-js/examples/eval-usage.ts +++ b/client-sdks/client-js/examples/eval-usage.ts @@ -36,16 +36,14 @@ async function main() { id: "test-2", name: "Technical Question", input: "What is the difference between HTTP and HTTPS?", - expectedOutput: - "HTTPS is the secure version of HTTP. It uses SSL/TLS encryption to protect data in transit.", + expectedOutput: "HTTPS is the secure version of HTTP. It uses SSL/TLS encryption to protect data in transit.", tags: ["technical", "security"], }, { id: "test-3", name: "Complex Query", input: "Explain how machine learning models are trained", - expectedOutput: - "Machine learning models are trained by feeding them data and adjusting their parameters to minimize prediction errors.", + expectedOutput: "Machine learning models are trained by feeding them data and adjusting their parameters to minimize prediction errors.", tags: ["ml", "complex"], }, ], @@ -71,16 +69,11 @@ async function main() { console.log("✅ 测试 Agent 已创建:", agent.id); // 执行快速评估 - const quickResult = await client.evals.quickEval( - agent.id, - "What is AI?", - "Artificial Intelligence (AI) refers to computer systems that can perform tasks requiring human intelligence.", - [ - { type: "semantic_similarity", weight: 0.5, params: { threshold: 0.7 } }, - { type: "keyword_coverage", weight: 0.3 }, - { type: "coherence", weight: 0.2 }, - ], - ); + const quickResult = await client.evals.quickEval(agent.id, "What is AI?", "Artificial Intelligence (AI) refers to computer systems that can perform tasks requiring human intelligence.", [ + { type: "semantic_similarity", weight: 0.5, params: { threshold: 0.7 } }, + { type: "keyword_coverage", weight: 0.3 }, + { type: "coherence", weight: 0.2 }, + ]); console.log("\n📊 快速评估结果:"); console.log(` 状态: ${quickResult.status}`); @@ -122,40 +115,28 @@ async function main() { console.log("\n📊 批量评估结果:"); console.log(` 总测试用例: ${batchResult.summary.totalTestCases}`); - console.log( - ` 通过: ${batchResult.summary.passed} | 失败: ${batchResult.summary.failed}`, - ); + console.log(` 通过: ${batchResult.summary.passed} | 失败: ${batchResult.summary.failed}`); console.log(` 通过率: ${(batchResult.summary.passRate * 100).toFixed(1)}%`); console.log(` 平均分数: ${batchResult.summary.avgScore.toFixed(2)}`); - console.log( - ` 平均执行时间: ${batchResult.summary.avgExecutionTime.toFixed(0)}ms`, - ); + console.log(` 平均执行时间: ${batchResult.summary.avgExecutionTime.toFixed(0)}ms`); if (batchResult.summary.totalTokenUsage) { - console.log( - ` 总 Tokens: ${batchResult.summary.totalTokenUsage.totalTokens.toLocaleString()}`, - ); + console.log(` 总 Tokens: ${batchResult.summary.totalTokenUsage.totalTokens.toLocaleString()}`); } if (batchResult.summary.totalCost) { - console.log( - ` 总成本: ${batchResult.summary.totalCost.currency} ${batchResult.summary.totalCost.amount.toFixed(4)}`, - ); + console.log(` 总成本: ${batchResult.summary.totalCost.currency} ${batchResult.summary.totalCost.amount.toFixed(4)}`); } console.log("\n 各 Scorer 平均分:"); - Object.entries(batchResult.summary.avgScoresByScorer).forEach( - ([scorer, score]) => { - console.log(` ${scorer}: ${score.toFixed(2)}`); - }, - ); + Object.entries(batchResult.summary.avgScoresByScorer).forEach(([scorer, score]) => { + console.log(` ${scorer}: ${score.toFixed(2)}`); + }); console.log("\n 各测试用例结果:"); batchResult.testCaseResults.forEach((result, i) => { const icon = result.passed ? "✅" : "❌"; - console.log( - ` ${icon} ${result.testCaseName}: ${result.overallScore.toFixed(2)}`, - ); + console.log(` ${icon} ${result.testCaseName}: ${result.overallScore.toFixed(2)}`); }); // ======================================================================== @@ -188,9 +169,7 @@ async function main() { }); // 等待 Benchmark 完成 - const benchmarkResult = await client.evals.waitForBenchmarkCompletion( - benchmark.id, - ); + const benchmarkResult = await client.evals.waitForBenchmarkCompletion(benchmark.id); console.log("\n📊 Benchmark 结果:"); console.log(` 状态: ${benchmarkResult.status}`); @@ -210,15 +189,10 @@ async function main() { console.log("-".repeat(70)); console.log("开始 A/B 测试..."); - const abTestResult = await client.evals.compareAgents( - agent.id, - agent2.id, - testCaseSet.id, - [ - { type: "semantic_similarity", weight: 0.5 }, - { type: "keyword_coverage", weight: 0.5 }, - ], - ); + const abTestResult = await client.evals.compareAgents(agent.id, agent2.id, testCaseSet.id, [ + { type: "semantic_similarity", weight: 0.5 }, + { type: "keyword_coverage", weight: 0.5 }, + ]); console.log("\n📊 A/B 测试结果:"); console.log(` 状态: ${abTestResult.status}`); @@ -227,15 +201,12 @@ async function main() { console.log("\n 统计分析:"); console.log(` Agent A 平均分: ${stats.agentAAvgScore.toFixed(2)}`); console.log(` Agent B 平均分: ${stats.agentBAvgScore.toFixed(2)}`); - console.log( - ` 差异: ${stats.difference > 0 ? "+" : ""}${stats.difference.toFixed(2)} (${stats.differencePercent > 0 ? "+" : ""}${stats.differencePercent.toFixed(1)}%)`, - ); + console.log(` 差异: ${stats.difference > 0 ? "+" : ""}${stats.difference.toFixed(2)} (${stats.differencePercent > 0 ? "+" : ""}${stats.differencePercent.toFixed(1)}%)`); console.log(` p-value: ${stats.pValue.toFixed(4)}`); console.log(` 显著性: ${stats.isSignificant ? "✅ 显著" : "❌ 不显著"}`); if (stats.winner) { - const winnerIcon = - stats.winner === "A" ? "🏆" : stats.winner === "B" ? "🏆" : "🤝"; + const winnerIcon = stats.winner === "A" ? "🏆" : stats.winner === "B" ? "🏆" : "🤝"; console.log(` 胜者: ${winnerIcon} Agent ${stats.winner}`); } @@ -268,10 +239,7 @@ async function main() { console.log(mdReport.content.substring(0, 200) + "..."); // 导出 JSON - const jsonExport = await client.evals.exportResult( - batchResult.evalId, - "json", - ); + const jsonExport = await client.evals.exportResult(batchResult.evalId, "json"); console.log("\n✅ JSON 导出已完成"); console.log(` 大小: ${jsonExport.length} 字符`); @@ -291,15 +259,11 @@ async function main() { sortOrder: "desc", }); - console.log( - `📋 找到 ${evals.total} 个 Evals (显示 ${evals.items.length} 个):`, - ); + console.log(`📋 找到 ${evals.total} 个 Evals (显示 ${evals.items.length} 个):`); evals.items.forEach((evalInfo, i) => { console.log(` ${i + 1}. ${evalInfo.name} (${evalInfo.type})`); console.log(` 状态: ${evalInfo.status} | 进度: ${evalInfo.progress}%`); - console.log( - ` 测试用例: ${evalInfo.completedTestCases}/${evalInfo.totalTestCases}`, - ); + console.log(` 测试用例: ${evalInfo.completedTestCases}/${evalInfo.totalTestCases}`); }); // 获取 Eval 详情 diff --git a/client-sdks/client-js/examples/event-subscription.ts b/client-sdks/client-js/examples/event-subscription.ts index 3afb322..b1d102d 100644 --- a/client-sdks/client-js/examples/event-subscription.ts +++ b/client-sdks/client-js/examples/event-subscription.ts @@ -3,14 +3,7 @@ * 展示如何使用 aster 的三通道事件系统 */ -import { - WebSocketClient, - SubscriptionManager, - isProgressEvent, - isControlEvent, - isMonitorEvent, - isEventType, -} from "@aster/client-js"; +import { WebSocketClient, SubscriptionManager, isProgressEvent, isControlEvent, isMonitorEvent, isEventType } from "@aster/client-js"; async function main() { // 1. 创建 WebSocket 客户端 @@ -34,13 +27,10 @@ async function main() { const subscriptionManager = new SubscriptionManager(ws); // 4. 订阅所有三个通道 - const subscription = subscriptionManager.subscribe( - ["progress", "control", "monitor"], - { - agentId: "agent-123", - eventTypes: ["thinking", "text_chunk", "tool_start", "token_usage"], - }, - ); + const subscription = subscriptionManager.subscribe(["progress", "control", "monitor"], { + agentId: "agent-123", + eventTypes: ["thinking", "text_chunk", "tool_start", "token_usage"], + }); // 5. 处理事件 try { @@ -76,12 +66,7 @@ function handleProgressEvent(event: any) { } else if (isEventType(event, "tool_start")) { console.log("🔧 调用工具:", event.data.toolName); } else if (isEventType(event, "tool_end")) { - console.log( - "✅ 工具完成:", - event.data.toolName, - "结果:", - event.data.result, - ); + console.log("✅ 工具完成:", event.data.toolName, "结果:", event.data.result); } else if (isEventType(event, "done")) { console.log("\n\n✅ 任务完成:", event.data.text); } else if (isEventType(event, "error")) { @@ -116,13 +101,7 @@ function handleMonitorEvent(event: any) { total: event.data.totalTokens, }); } else if (isEventType(event, "latency")) { - console.log( - "⏱️ 延迟:", - event.data.latencyMs, - "ms", - "操作:", - event.data.operation, - ); + console.log("⏱️ 延迟:", event.data.latencyMs, "ms", "操作:", event.data.operation); } else if (isEventType(event, "cost")) { console.log("💰 成本:", event.data.cost, event.data.currency); } else if (isEventType(event, "compliance")) { diff --git a/client-sdks/client-js/examples/mcp-middleware-tool.ts b/client-sdks/client-js/examples/mcp-middleware-tool.ts index 19fc8cc..f930436 100644 --- a/client-sdks/client-js/examples/mcp-middleware-tool.ts +++ b/client-sdks/client-js/examples/mcp-middleware-tool.ts @@ -2,11 +2,7 @@ * MCP + Middleware + Tool 使用示例 */ -import { - MCPResource, - MiddlewareResource, - ToolResource, -} from "@aster/client-js"; +import { MCPResource, MiddlewareResource, ToolResource } from "@aster/client-js"; async function main() { console.log("=".repeat(60)); @@ -78,10 +74,7 @@ async function main() { console.log(" 成功:", result.success); console.log(" 耗时:", result.executionTime, "ms"); if (result.result) { - console.log( - " 结果:", - JSON.stringify(result.result).substring(0, 100), - ); + console.log(" 结果:", JSON.stringify(result.result).substring(0, 100)); } } } catch (error: any) { @@ -92,19 +85,10 @@ async function main() { try { const stats = await mcp.getStats(); console.log("📊 MCP 统计:"); - console.log( - " 连接的 Servers:", - stats.connectedServers, - "/", - stats.totalServers, - ); + console.log(" 连接的 Servers:", stats.connectedServers, "/", stats.totalServers); console.log(" 总工具数:", stats.totalTools); console.log(" 总调用次数:", stats.totalCalls); - console.log( - " 成功率:", - ((stats.successfulCalls / stats.totalCalls) * 100).toFixed(1), - "%", - ); + console.log(" 成功率:", ((stats.successfulCalls / stats.totalCalls) * 100).toFixed(1), "%"); } catch (error: any) { console.log("⚠️ 获取统计失败:", error.message); } @@ -120,9 +104,7 @@ async function main() { console.log(`📋 总共 ${middlewares.length} 个 Middlewares:`); middlewares.forEach((mw, index) => { const status = mw.enabled ? "✅" : "⏸️ "; - console.log( - ` ${status} ${index + 1}. [P${mw.priority}] ${mw.displayName} - ${mw.description}`, - ); + console.log(` ${status} ${index + 1}. [P${mw.priority}] ${mw.displayName} - ${mw.description}`); }); // 配置 Summarization Middleware(上下文压缩) @@ -191,9 +173,7 @@ async function main() { allStats.slice(0, 3).forEach((stat) => { console.log(` ${stat.name}:`); console.log(` 执行: ${stat.executionCount} 次`); - console.log( - ` 成功率: ${((stat.successCount / stat.executionCount) * 100).toFixed(1)}%`, - ); + console.log(` 成功率: ${((stat.successCount / stat.executionCount) * 100).toFixed(1)}%`); console.log(` 平均耗时: ${stat.avgExecutionTime.toFixed(2)} ms`); }); } catch (error: any) { @@ -225,9 +205,7 @@ async function main() { builtinTools.forEach((t, index) => { const status = t.enabled ? "✅" : "⏸️ "; const approval = t.requiresApproval ? "🔒" : ""; - console.log( - ` ${status}${approval} ${index + 1}. ${t.name} - ${t.description}`, - ); + console.log(` ${status}${approval} ${index + 1}. ${t.name} - ${t.description}`); }); // 执行 Bash 工具(同步) @@ -295,9 +273,7 @@ async function main() { }); console.log(`\n📊 运行中的任务: ${tasks.length} 个`); tasks.forEach((t, index) => { - console.log( - ` ${index + 1}. [${t.toolName}] ${t.status} - ${t.progress}%`, - ); + console.log(` ${index + 1}. [${t.toolName}] ${t.status} - ${t.progress}%`); }); } catch (error: any) { console.log("⚠️ 获取任务列表失败:", error.message); @@ -313,9 +289,7 @@ async function main() { .forEach((stat, index) => { console.log(` ${index + 1}. ${stat.toolName}:`); console.log(` 调用: ${stat.totalCalls} 次`); - console.log( - ` 成功率: ${((stat.successCount / stat.totalCalls) * 100).toFixed(1)}%`, - ); + console.log(` 成功率: ${((stat.successCount / stat.totalCalls) * 100).toFixed(1)}%`); console.log(` 平均耗时: ${stat.avgExecutionTime.toFixed(2)} ms`); }); } catch (error: any) { @@ -332,9 +306,7 @@ async function main() { console.log(" 总调用次数:", report.totalCalls); console.log(" 最常用工具:"); report.topTools.slice(0, 3).forEach((t, index) => { - console.log( - ` ${index + 1}. ${t.toolName} - ${t.callCount} 次 (${t.percentage.toFixed(1)}%)`, - ); + console.log(` ${index + 1}. ${t.toolName} - ${t.callCount} 次 (${t.percentage.toFixed(1)}%)`); }); } catch (error: any) { console.log("⚠️ 获取报告失败:", error.message); diff --git a/client-sdks/client-js/examples/memory-usage.ts b/client-sdks/client-js/examples/memory-usage.ts index 38cdf19..651a4bc 100644 --- a/client-sdks/client-js/examples/memory-usage.ts +++ b/client-sdks/client-js/examples/memory-usage.ts @@ -85,39 +85,25 @@ async function main() { console.log("-".repeat(60)); // 存储知识 - const chunk1 = await memory.semantic.store( - "Paris is the capital of France.", - { source: "wikipedia", category: "geography", language: "en" }, - ); + const chunk1 = await memory.semantic.store("Paris is the capital of France.", { source: "wikipedia", category: "geography", language: "en" }); console.log("✅ 存储记忆块 1:", chunk1); - const chunk2 = await memory.semantic.store( - "The Eiffel Tower is located in Paris.", - { source: "wikipedia", category: "landmarks", language: "en" }, - ); + const chunk2 = await memory.semantic.store("The Eiffel Tower is located in Paris.", { source: "wikipedia", category: "landmarks", language: "en" }); console.log("✅ 存储记忆块 2:", chunk2); - const chunk3 = await memory.semantic.store( - "France is a country in Western Europe.", - { source: "wikipedia", category: "geography", language: "en" }, - ); + const chunk3 = await memory.semantic.store("France is a country in Western Europe.", { source: "wikipedia", category: "geography", language: "en" }); console.log("✅ 存储记忆块 3:", chunk3); // 语义搜索 console.log('\n🔎 搜索: "What is the capital of France?"'); - const results = await memory.semantic.search( - "What is the capital of France?", - { - limit: 5, - threshold: 0.7, - filter: { category: "geography" }, - }, - ); + const results = await memory.semantic.search("What is the capital of France?", { + limit: 5, + threshold: 0.7, + filter: { category: "geography" }, + }); results.forEach((chunk, index) => { - console.log( - ` ${index + 1}. [Score: ${chunk.score?.toFixed(2)}] ${chunk.content}`, - ); + console.log(` ${index + 1}. [Score: ${chunk.score?.toFixed(2)}] ${chunk.content}`); console.log(` Metadata:`, chunk.metadata); }); diff --git a/client-sdks/client-js/examples/session-workflow.ts b/client-sdks/client-js/examples/session-workflow.ts index c20b3a5..7ec0079 100644 --- a/client-sdks/client-js/examples/session-workflow.ts +++ b/client-sdks/client-js/examples/session-workflow.ts @@ -2,13 +2,7 @@ * Session 和 Workflow 使用示例 */ -import { - SessionResource, - WorkflowResource, - ParallelWorkflowDefinition, - SequentialWorkflowDefinition, - LoopWorkflowDefinition, -} from "@aster/client-js"; +import { SessionResource, WorkflowResource, ParallelWorkflowDefinition, SequentialWorkflowDefinition, LoopWorkflowDefinition } from "@aster/client-js"; async function main() { console.log("=".repeat(60)); @@ -55,8 +49,7 @@ async function main() { await session.addMessage(newSession.id, { role: "assistant", - content: - "Of course! I'd be happy to help. What do you need assistance with?", + content: "Of course! I'd be happy to help. What do you need assistance with?", }); console.log("✅ 添加助手消息"); @@ -75,19 +68,14 @@ async function main() { console.log("-".repeat(60)); // 创建手动 checkpoint - const checkpoint = await session.createCheckpoint( - newSession.id, - "before-important-action", - ); + const checkpoint = await session.createCheckpoint(newSession.id, "before-important-action"); console.log("✅ 创建 Checkpoint:", checkpoint.id); // 获取所有 checkpoints const checkpoints = await session.getCheckpoints(newSession.id); console.log(`📊 总共 ${checkpoints.length} 个 Checkpoints:`); checkpoints.forEach((cp, index) => { - console.log( - ` ${index + 1}. [${cp.type}] Sequence: ${cp.sequence}, Time: ${cp.timestamp}`, - ); + console.log(` ${index + 1}. [${cp.type}] Sequence: ${cp.sequence}, Time: ${cp.timestamp}`); }); // 从 checkpoint 恢复 @@ -146,14 +134,10 @@ async function main() { // 等待完成(模拟) try { - const finalRun = await workflow.waitForCompletion( - parallelWf.id, - parallelRun.id, - { - pollInterval: 2000, - timeout: 60000, - }, - ); + const finalRun = await workflow.waitForCompletion(parallelWf.id, parallelRun.id, { + pollInterval: 2000, + timeout: 60000, + }); console.log("✅ Workflow 完成:", finalRun.status); } catch (error: any) { console.log("⚠️ 等待超时或失败:", error.message); @@ -237,10 +221,7 @@ async function main() { console.log("-".repeat(60)); // 获取执行详情 - const runDetails = await workflow.getRunDetails( - parallelWf.id, - parallelRun.id, - ); + const runDetails = await workflow.getRunDetails(parallelWf.id, parallelRun.id); console.log("📊 执行详情:"); console.log(` - 状态: ${runDetails.status}`); console.log(` - 进度: ${runDetails.progress}%`); @@ -275,9 +256,7 @@ async function main() { }); console.log(`📋 执行历史: 共 ${runs.total} 次执行`); runs.items.forEach((run, index) => { - console.log( - ` ${index + 1}. [${run.status}] ${run.startedAt} - Progress: ${run.progress}%`, - ); + console.log(` ${index + 1}. [${run.status}] ${run.startedAt} - Progress: ${run.progress}%`); }); // ======================================================================== diff --git a/client-sdks/client-js/src/events/subscription.ts b/client-sdks/client-js/src/events/subscription.ts index b3c2aa4..991af09 100644 --- a/client-sdks/client-js/src/events/subscription.ts +++ b/client-sdks/client-js/src/events/subscription.ts @@ -47,16 +47,14 @@ export class EventSubscription { } // 等待新事件 - const result = await new Promise>( - (resolve) => { - if (!this.isActive) { - resolve({ done: true, value: undefined }); - return; - } + const result = await new Promise>((resolve) => { + if (!this.isActive) { + resolve({ done: true, value: undefined }); + return; + } - this.resolvers.push(resolve); - }, - ); + this.resolvers.push(resolve); + }); if (result.done) { break; @@ -116,10 +114,7 @@ export class EventSubscription { } // 事件类型过滤 - if ( - this.filter.eventTypes && - !this.filter.eventTypes.includes(envelope.event.type) - ) { + if (this.filter.eventTypes && !this.filter.eventTypes.includes(envelope.event.type)) { return; } } @@ -134,9 +129,7 @@ export class EventSubscription { // 防止队列过大 if (this.eventQueue.length > 1000) { - console.warn( - "[EventSubscription] Event queue overflow, dropping oldest events", - ); + console.warn("[EventSubscription] Event queue overflow, dropping oldest events"); this.eventQueue = this.eventQueue.slice(-500); // 保留最新的 500 个 } } diff --git a/client-sdks/client-js/src/events/types.ts b/client-sdks/client-js/src/events/types.ts index 0ade3e8..a1c5601 100644 --- a/client-sdks/client-js/src/events/types.ts +++ b/client-sdks/client-js/src/events/types.ts @@ -117,13 +117,7 @@ export interface ProgressErrorEvent { /** * Progress Channel 所有事件的联合类型 */ -export type ProgressEvent = - | ProgressThinkingEvent - | ProgressTextChunkEvent - | ProgressToolStartEvent - | ProgressToolEndEvent - | ProgressDoneEvent - | ProgressErrorEvent; +export type ProgressEvent = ProgressThinkingEvent | ProgressTextChunkEvent | ProgressToolStartEvent | ProgressToolEndEvent | ProgressDoneEvent | ProgressErrorEvent; // ============================================================================ // Control Channel Events (审批流) @@ -190,11 +184,7 @@ export interface ControlResumeEvent { /** * Control Channel 所有事件的联合类型 */ -export type ControlEvent = - | ControlToolApprovalRequestEvent - | ControlToolApprovalResponseEvent - | ControlPauseEvent - | ControlResumeEvent; +export type ControlEvent = ControlToolApprovalRequestEvent | ControlToolApprovalResponseEvent | ControlPauseEvent | ControlResumeEvent; // ============================================================================ // Monitor Channel Events (治理流) @@ -265,11 +255,7 @@ export interface MonitorComplianceEvent { /** * Monitor Channel 所有事件的联合类型 */ -export type MonitorEvent = - | MonitorTokenUsageEvent - | MonitorLatencyEvent - | MonitorCostEvent - | MonitorComplianceEvent; +export type MonitorEvent = MonitorTokenUsageEvent | MonitorLatencyEvent | MonitorCostEvent | MonitorComplianceEvent; // ============================================================================ // 事件联合类型 @@ -324,9 +310,6 @@ export function isMonitorEvent(event: StreamEvent): event is MonitorEvent { /** * 类型守卫:检查具体事件类型 */ -export function isEventType( - event: StreamEvent, - type: T, -): event is Extract { +export function isEventType(event: StreamEvent, type: T): event is Extract { return event.type === type; } diff --git a/client-sdks/client-js/src/index.ts b/client-sdks/client-js/src/index.ts index 62b001c..4f069ca 100644 --- a/client-sdks/client-js/src/index.ts +++ b/client-sdks/client-js/src/index.ts @@ -41,11 +41,7 @@ export * from "./types/eval"; // 资源类 export { BaseResource } from "./resources/base"; -export type { - ClientOptions, - RequestOptions, - RetryOptions, -} from "./resources/base"; +export type { ClientOptions, RequestOptions, RetryOptions } from "./resources/base"; export { AgentResource } from "./resources/agent"; export { MemoryResource } from "./resources/memory"; export { SessionResource } from "./resources/session"; diff --git a/client-sdks/client-js/src/resources/agent.ts b/client-sdks/client-js/src/resources/agent.ts index ed48f61..405ca79 100644 --- a/client-sdks/client-js/src/resources/agent.ts +++ b/client-sdks/client-js/src/resources/agent.ts @@ -4,20 +4,7 @@ */ import { BaseResource, ClientOptions } from "./base"; -import { - AgentInfo, - AgentFilter, - PaginatedAgentResponse, - CreateAgentRequest, - UpdateAgentRequest, - ChatRequest, - ChatResponse, - StreamChatEvent, - AgentTemplate, - AgentStats, - AgentValidationResult, - AgentStatus, -} from "../types/agent"; +import { AgentInfo, AgentFilter, PaginatedAgentResponse, CreateAgentRequest, UpdateAgentRequest, ChatRequest, ChatResponse, StreamChatEvent, AgentTemplate, AgentStats, AgentValidationResult, AgentStatus } from "../types/agent"; /** * Agent 资源类 @@ -69,10 +56,7 @@ export class AgentResource extends BaseResource { * @param updates 更新内容 * @returns 更新后的 Agent */ - async update( - agentId: string, - updates: UpdateAgentRequest, - ): Promise { + async update(agentId: string, updates: UpdateAgentRequest): Promise { return this.request(`/v1/agents/${agentId}`, { method: "PATCH", body: updates, @@ -126,10 +110,7 @@ export class AgentResource extends BaseResource { * @param status 新状态 * @returns 更新后的 Agent */ - private async updateStatus( - agentId: string, - status: AgentStatus, - ): Promise { + private async updateStatus(agentId: string, status: AgentStatus): Promise { return this.update(agentId, { status }); } @@ -156,23 +137,17 @@ export class AgentResource extends BaseResource { * @param request Chat 请求 * @returns AsyncIterable 流式事件 */ - async *chatStream( - agentId: string, - request: ChatRequest, - ): AsyncIterable { - const response = await fetch( - `${this.options.baseUrl}/v1/agents/${agentId}/chat/stream`, - { - method: "POST", - headers: { - "Content-Type": "application/json", - ...(this.options.apiKey && { - Authorization: `Bearer ${this.options.apiKey}`, - }), - }, - body: JSON.stringify(request), + async *chatStream(agentId: string, request: ChatRequest): AsyncIterable { + const response = await fetch(`${this.options.baseUrl}/v1/agents/${agentId}/chat/stream`, { + method: "POST", + headers: { + "Content-Type": "application/json", + ...(this.options.apiKey && { + Authorization: `Bearer ${this.options.apiKey}`, + }), }, - ); + body: JSON.stringify(request), + }); if (!response.ok) { throw new Error(`Chat stream failed: ${response.statusText}`); @@ -224,9 +199,7 @@ export class AgentResource extends BaseResource { * @returns 模板列表 */ async listTemplates(): Promise { - const result = await this.request<{ templates: AgentTemplate[] }>( - "/v1/agents/templates", - ); + const result = await this.request<{ templates: AgentTemplate[] }>("/v1/agents/templates"); return result.templates; } @@ -245,17 +218,13 @@ export class AgentResource extends BaseResource { * @param overrides 覆盖配置 * @returns 创建的 Agent */ - async createFromTemplate( - templateId: string, - overrides: Partial, - ): Promise { + async createFromTemplate(templateId: string, overrides: Partial): Promise { const template = await this.getTemplate(templateId); const request: CreateAgentRequest = { name: overrides.name || `Agent from ${template.name}`, templateId, - llmProvider: - overrides.llmProvider || template.recommendedProvider || "openai", + llmProvider: overrides.llmProvider || template.recommendedProvider || "openai", llmModel: overrides.llmModel || template.recommendedModel || "gpt-4", systemPrompt: overrides.systemPrompt || template.defaultSystemPrompt, tools: overrides.tools || template.defaultTools, @@ -278,10 +247,7 @@ export class AgentResource extends BaseResource { * @param timeRange 时间范围(可选) * @returns 统计数据 */ - async getStats( - agentId: string, - timeRange?: { start: string; end: string }, - ): Promise { + async getStats(agentId: string, timeRange?: { start: string; end: string }): Promise { return this.request(`/v1/agents/${agentId}/stats`, { params: timeRange, }); @@ -292,10 +258,7 @@ export class AgentResource extends BaseResource { * @param timeRange 时间范围(可选) * @returns 汇总统计数据 */ - async getAggregatedStats(timeRange?: { - start: string; - end: string; - }): Promise<{ + async getAggregatedStats(timeRange?: { start: string; end: string }): Promise<{ totalAgents: number; activeAgents: number; totalRequests: number; @@ -317,9 +280,7 @@ export class AgentResource extends BaseResource { * @param config Agent 配置 * @returns 验证结果 */ - async validate( - config: CreateAgentRequest | UpdateAgentRequest, - ): Promise { + async validate(config: CreateAgentRequest | UpdateAgentRequest): Promise { return this.request("/v1/agents/validate", { method: "POST", body: config, diff --git a/client-sdks/client-js/src/resources/base.ts b/client-sdks/client-js/src/resources/base.ts index 204d067..41b6215 100644 --- a/client-sdks/client-js/src/resources/base.ts +++ b/client-sdks/client-js/src/resources/base.ts @@ -86,10 +86,7 @@ export class BaseResource { * 发送 HTTP 请求 * 自动处理重试、超时、错误 */ - protected async request( - path: string, - options: RequestOptions = {}, - ): Promise { + protected async request(path: string, options: RequestOptions = {}): Promise { const url = this.buildUrl(path, options.params); const timeout = options.timeout ?? this.options.timeout; @@ -114,14 +111,8 @@ export class BaseResource { clearTimeout(timeoutId); // 检查是否需要重试 - if ( - !response.ok && - this.shouldRetry(response.status) && - attempt < maxRetries - ) { - lastError = new Error( - `HTTP ${response.status}: ${response.statusText}`, - ); + if (!response.ok && this.shouldRetry(response.status) && attempt < maxRetries) { + lastError = new Error(`HTTP ${response.status}: ${response.statusText}`); await this.delay(this.getBackoffDelay(attempt)); continue; } @@ -177,9 +168,7 @@ export class BaseResource { /** * 构建请求 headers */ - private buildHeaders( - customHeaders?: Record, - ): Record { + private buildHeaders(customHeaders?: Record): Record { const headers: Record = { "Content-Type": "application/json", ...this.options.headers, @@ -212,9 +201,7 @@ export class BaseResource { } catch (error) { // 不是有效的 JSON if (!response.ok) { - throw new Error( - `HTTP ${response.status}: ${text || response.statusText}`, - ); + throw new Error(`HTTP ${response.status}: ${text || response.statusText}`); } return text as T; } @@ -226,12 +213,7 @@ export class BaseResource { } // 解包 {success: true, data: {...}} 格式的响应 - if ( - data && - typeof data === "object" && - "success" in data && - "data" in data - ) { + if (data && typeof data === "object" && "success" in data && "data" in data) { return data.data as T; } @@ -250,13 +232,7 @@ export class BaseResource { */ private isRetryableError(error: any): boolean { // 超时、网络错误等 - return ( - error.name === "AbortError" || - error.name === "TimeoutError" || - error.message?.includes("fetch failed") || - error.message?.includes("network") || - error.message?.includes("ECONNREFUSED") - ); + return error.name === "AbortError" || error.name === "TimeoutError" || error.message?.includes("fetch failed") || error.message?.includes("network") || error.message?.includes("ECONNREFUSED"); } /** @@ -265,10 +241,7 @@ export class BaseResource { */ private getBackoffDelay(attempt: number): number { const { backoffMultiplier, maxBackoffTime } = this.options.retry!; - const delay = Math.min( - 1000 * Math.pow(backoffMultiplier!, attempt), - maxBackoffTime!, - ); + const delay = Math.min(1000 * Math.pow(backoffMultiplier!, attempt), maxBackoffTime!); // 添加随机抖动(±25%) const jitter = delay * (0.75 + Math.random() * 0.5); return Math.floor(jitter); diff --git a/client-sdks/client-js/src/resources/eval.ts b/client-sdks/client-js/src/resources/eval.ts index 38da85d..dde206e 100644 --- a/client-sdks/client-js/src/resources/eval.ts +++ b/client-sdks/client-js/src/resources/eval.ts @@ -4,22 +4,7 @@ */ import { BaseResource, ClientOptions } from "./base"; -import { - EvalRequest, - EvalInfo, - EvalResult, - EvalFilter, - PaginatedEvalResponse, - TestCase, - TestCaseSet, - BenchmarkConfig, - BenchmarkResult, - ABTestConfig, - ABTestResult, - EvalReportRequest, - EvalReportResult, - ScorerConfig, -} from "../types/eval"; +import { EvalRequest, EvalInfo, EvalResult, EvalFilter, PaginatedEvalResponse, TestCase, TestCaseSet, BenchmarkConfig, BenchmarkResult, ABTestConfig, ABTestResult, EvalReportRequest, EvalReportResult, ScorerConfig } from "../types/eval"; /** * Eval 资源类 @@ -50,12 +35,7 @@ export class EvalResource extends BaseResource { * @param request 文本评估请求 * @returns Eval 结果 */ - async runTextEval(request: { - prompt: string; - expected?: string; - scorer?: string; - [key: string]: any; - }): Promise { + async runTextEval(request: { prompt: string; expected?: string; scorer?: string; [key: string]: any }): Promise { const evalInfo = await this.create({ type: "text", ...request, @@ -68,11 +48,7 @@ export class EvalResource extends BaseResource { * @param request 批量评估请求 * @returns Eval 结果 */ - async runBatchEval(request: { - items: Array<{ prompt: string; expected?: string; [key: string]: any }>; - scorer?: string; - [key: string]: any; - }): Promise { + async runBatchEval(request: { items: Array<{ prompt: string; expected?: string; [key: string]: any }>; scorer?: string; [key: string]: any }): Promise { const evalInfo = await this.create({ type: "batch", ...request, @@ -141,11 +117,7 @@ export class EvalResource extends BaseResource { * @param maxWaitTime 最大等待时间(毫秒),默认 300000 (5分钟) * @returns Eval 结果 */ - async waitForCompletion( - evalId: string, - pollInterval: number = 1000, - maxWaitTime: number = 300000, - ): Promise { + async waitForCompletion(evalId: string, pollInterval: number = 1000, maxWaitTime: number = 300000): Promise { const startTime = Date.now(); while (Date.now() - startTime < maxWaitTime) { @@ -156,9 +128,7 @@ export class EvalResource extends BaseResource { } if (evalInfo.status === "failed" || evalInfo.status === "cancelled") { - throw new Error( - `Eval ${evalId} ${evalInfo.status}${evalInfo.error ? `: ${evalInfo.error}` : ""}`, - ); + throw new Error(`Eval ${evalId} ${evalInfo.status}${evalInfo.error ? `: ${evalInfo.error}` : ""}`); } // 等待下次轮询 @@ -179,11 +149,7 @@ export class EvalResource extends BaseResource { * @param description 描述 * @returns 测试用例集 */ - async createTestCaseSet( - name: string, - testCases: TestCase[], - description?: string, - ): Promise { + async createTestCaseSet(name: string, testCases: TestCase[], description?: string): Promise { return this.request("/v1/evals/test-cases", { method: "POST", body: { name, testCases, description }, @@ -204,9 +170,7 @@ export class EvalResource extends BaseResource { * @returns 测试用例集列表 */ async listTestCaseSets(): Promise { - const result = await this.request<{ items: TestCaseSet[] }>( - "/v1/evals/test-cases", - ); + const result = await this.request<{ items: TestCaseSet[] }>("/v1/evals/test-cases"); return result.items; } @@ -282,11 +246,7 @@ export class EvalResource extends BaseResource { * @param maxWaitTime 最大等待时间(毫秒),默认 600000 (10分钟) * @returns Benchmark 结果 */ - async waitForBenchmarkCompletion( - benchmarkId: string, - pollInterval: number = 2000, - maxWaitTime: number = 600000, - ): Promise { + async waitForBenchmarkCompletion(benchmarkId: string, pollInterval: number = 2000, maxWaitTime: number = 600000): Promise { const startTime = Date.now(); while (Date.now() - startTime < maxWaitTime) { @@ -303,9 +263,7 @@ export class EvalResource extends BaseResource { await new Promise((resolve) => setTimeout(resolve, pollInterval)); } - throw new Error( - `Benchmark ${benchmarkId} did not complete within ${maxWaitTime}ms`, - ); + throw new Error(`Benchmark ${benchmarkId} did not complete within ${maxWaitTime}ms`); } // ========================================================================== @@ -340,11 +298,7 @@ export class EvalResource extends BaseResource { * @param maxWaitTime 最大等待时间(毫秒),默认 600000 (10分钟) * @returns A/B 测试结果 */ - async waitForABTestCompletion( - abTestId: string, - pollInterval: number = 2000, - maxWaitTime: number = 600000, - ): Promise { + async waitForABTestCompletion(abTestId: string, pollInterval: number = 2000, maxWaitTime: number = 600000): Promise { const startTime = Date.now(); while (Date.now() - startTime < maxWaitTime) { @@ -361,9 +315,7 @@ export class EvalResource extends BaseResource { await new Promise((resolve) => setTimeout(resolve, pollInterval)); } - throw new Error( - `A/B Test ${abTestId} did not complete within ${maxWaitTime}ms`, - ); + throw new Error(`A/B Test ${abTestId} did not complete within ${maxWaitTime}ms`); } // ========================================================================== @@ -389,12 +341,9 @@ export class EvalResource extends BaseResource { * @returns 导出内容 */ async exportResult(evalId: string, format: "json" | "csv"): Promise { - const result = await this.request<{ content: string }>( - `/v1/evals/${evalId}/export`, - { - params: { format }, - }, - ); + const result = await this.request<{ content: string }>(`/v1/evals/${evalId}/export`, { + params: { format }, + }); return result.content; } @@ -410,12 +359,7 @@ export class EvalResource extends BaseResource { * @param scorers Scorer 配置列表 * @returns Eval 结果 */ - async quickEval( - agentId: string, - input: string, - expectedOutput: string, - scorers: ScorerConfig[], - ): Promise { + async quickEval(agentId: string, input: string, expectedOutput: string, scorers: ScorerConfig[]): Promise { const evalInfo = await this.create({ name: `Quick Eval - ${new Date().toISOString()}`, type: "single", @@ -442,12 +386,7 @@ export class EvalResource extends BaseResource { * @param concurrency 并发数 * @returns Eval 结果 */ - async batchEval( - agentId: string, - testCases: TestCase[], - scorers: ScorerConfig[], - concurrency?: number, - ): Promise { + async batchEval(agentId: string, testCases: TestCase[], scorers: ScorerConfig[], concurrency?: number): Promise { const evalInfo = await this.create({ name: `Batch Eval - ${new Date().toISOString()}`, type: "batch", @@ -468,12 +407,7 @@ export class EvalResource extends BaseResource { * @param scorers Scorer 配置列表 * @returns A/B 测试结果 */ - async compareAgents( - agentAId: string, - agentBId: string, - testCaseSetId: string, - scorers: ScorerConfig[], - ): Promise { + async compareAgents(agentAId: string, agentBId: string, testCaseSetId: string, scorers: ScorerConfig[]): Promise { const abTest = await this.createABTest({ name: `Compare ${agentAId} vs ${agentBId}`, agentAId, diff --git a/client-sdks/client-js/src/resources/mcp.ts b/client-sdks/client-js/src/resources/mcp.ts index ebca3da..97a1f9f 100644 --- a/client-sdks/client-js/src/resources/mcp.ts +++ b/client-sdks/client-js/src/resources/mcp.ts @@ -4,18 +4,7 @@ */ import { BaseResource, ClientOptions } from "./base"; -import { - MCPServerConfig, - MCPServerInfo, - MCPTool, - MCPToolCallRequest, - MCPToolCallResponse, - MCPResource as MCPResourceData, - MCPResourceContent, - MCPPrompt, - MCPPromptResult, - MCPStats, -} from "../types/mcp"; +import { MCPServerConfig, MCPServerInfo, MCPTool, MCPToolCallRequest, MCPToolCallResponse, MCPResource as MCPResourceData, MCPResourceContent, MCPPrompt, MCPPromptResult, MCPStats } from "../types/mcp"; /** * MCP 资源类 @@ -55,9 +44,7 @@ export class MCPResource extends BaseResource { * @returns Server 列表 */ async listServers(): Promise { - const result = await this.request<{ servers: MCPServerInfo[] }>( - "/v1/mcp/servers", - ); + const result = await this.request<{ servers: MCPServerInfo[] }>("/v1/mcp/servers"); return result.servers; } @@ -76,10 +63,7 @@ export class MCPResource extends BaseResource { * @param updates 更新内容 * @returns 更新后的 Server 信息 */ - async updateServer( - serverId: string, - updates: Partial, - ): Promise { + async updateServer(serverId: string, updates: Partial): Promise { return this.request(`/v1/mcp/servers/${serverId}`, { method: "PATCH", body: updates, @@ -152,9 +136,7 @@ export class MCPResource extends BaseResource { * @returns 工具列表 */ async getServerTools(serverId: string): Promise { - const result = await this.request<{ tools: MCPTool[] }>( - `/v1/mcp/servers/${serverId}/tools`, - ); + const result = await this.request<{ tools: MCPTool[] }>(`/v1/mcp/servers/${serverId}/tools`); return result.tools; } @@ -187,11 +169,7 @@ export class MCPResource extends BaseResource { * @param params 参数 * @returns 调用响应 */ - async call( - serverId: string, - toolName: string, - params: Record, - ): Promise { + async call(serverId: string, toolName: string, params: Record): Promise { return this.callTool({ serverId, toolName, params }); } @@ -205,9 +183,7 @@ export class MCPResource extends BaseResource { * @returns 资源列表 */ async listResources(serverId: string): Promise { - const result = await this.request<{ resources: MCPResourceData[] }>( - `/v1/mcp/servers/${serverId}/resources`, - ); + const result = await this.request<{ resources: MCPResourceData[] }>(`/v1/mcp/servers/${serverId}/resources`); return result.resources; } @@ -217,17 +193,11 @@ export class MCPResource extends BaseResource { * @param uri 资源 URI * @returns 资源内容 */ - async readResource( - serverId: string, - uri: string, - ): Promise { - return this.request( - `/v1/mcp/servers/${serverId}/resources/read`, - { - method: "POST", - body: { uri }, - }, - ); + async readResource(serverId: string, uri: string): Promise { + return this.request(`/v1/mcp/servers/${serverId}/resources/read`, { + method: "POST", + body: { uri }, + }); } // ========================================================================== @@ -240,9 +210,7 @@ export class MCPResource extends BaseResource { * @returns Prompt 列表 */ async listPrompts(serverId: string): Promise { - const result = await this.request<{ prompts: MCPPrompt[] }>( - `/v1/mcp/servers/${serverId}/prompts`, - ); + const result = await this.request<{ prompts: MCPPrompt[] }>(`/v1/mcp/servers/${serverId}/prompts`); return result.prompts; } @@ -253,18 +221,11 @@ export class MCPResource extends BaseResource { * @param args Prompt 参数 * @returns Prompt 结果 */ - async getPrompt( - serverId: string, - name: string, - args?: Record, - ): Promise { - return this.request( - `/v1/mcp/servers/${serverId}/prompts/${name}`, - { - method: "POST", - body: { arguments: args }, - }, - ); + async getPrompt(serverId: string, name: string, args?: Record): Promise { + return this.request(`/v1/mcp/servers/${serverId}/prompts/${name}`, { + method: "POST", + body: { arguments: args }, + }); } // ========================================================================== diff --git a/client-sdks/client-js/src/resources/memory.ts b/client-sdks/client-js/src/resources/memory.ts index b1f6f95..e45e16c 100644 --- a/client-sdks/client-js/src/resources/memory.ts +++ b/client-sdks/client-js/src/resources/memory.ts @@ -4,19 +4,7 @@ */ import { BaseResource, ClientOptions } from "./base"; -import { - WorkingMemoryScope, - WorkingMemorySetOptions, - WorkingMemoryItem, - MemoryChunk, - SearchOptions, - SearchResult, - Provenance, - ProvenanceResponse, - ConsolidateOptions, - ConsolidationResult, - JobStatus, -} from "../types/memory"; +import { WorkingMemoryScope, WorkingMemorySetOptions, WorkingMemoryItem, MemoryChunk, SearchOptions, SearchResult, Provenance, ProvenanceResponse, ConsolidateOptions, ConsolidationResult, JobStatus } from "../types/memory"; /** * Memory 资源类 @@ -57,11 +45,7 @@ export class MemoryResource extends BaseResource { * @param value 值 * @param options 选项(作用域、TTL、Schema) */ - set: async ( - key: string, - value: any, - options?: WorkingMemorySetOptions, - ): Promise => { + set: async (key: string, value: any, options?: WorkingMemorySetOptions): Promise => { await this.request("/v1/memory/working", { method: "POST", body: { @@ -94,10 +78,7 @@ export class MemoryResource extends BaseResource { */ list: async (scope?: WorkingMemoryScope): Promise> => { const params = scope ? { scope } : undefined; - const result = await this.request( - "/v1/memory/working", - { params }, - ); + const result = await this.request("/v1/memory/working", { params }); // 转换为键值对对象 const items: Record = {}; @@ -137,22 +118,16 @@ export class MemoryResource extends BaseResource { * @param options 搜索选项 * @returns 搜索结果 */ - search: async ( - query: string, - options?: SearchOptions, - ): Promise => { - const result = await this.request( - "/v1/memory/semantic/search", - { - method: "POST", - body: { - query, - limit: options?.limit ?? 10, - threshold: options?.threshold, - filter: options?.filter, - }, + search: async (query: string, options?: SearchOptions): Promise => { + const result = await this.request("/v1/memory/semantic/search", { + method: "POST", + body: { + query, + limit: options?.limit ?? 10, + threshold: options?.threshold, + filter: options?.filter, }, - ); + }); return result.chunks; }, @@ -162,10 +137,7 @@ export class MemoryResource extends BaseResource { * @param metadata 元数据(可选) * @returns 记忆块 ID */ - store: async ( - content: string, - metadata?: Record, - ): Promise => { + store: async (content: string, metadata?: Record): Promise => { const result = await this.request<{ id: string }>("/v1/memory/semantic", { method: "POST", body: { content, ...metadata }, @@ -178,11 +150,7 @@ export class MemoryResource extends BaseResource { * @param data 记忆数据 * @returns 记忆信息 */ - create: async (data: { - content: string; - tags?: string[]; - metadata?: Record; - }): Promise<{ id: string; content: string; [key: string]: any }> => { + create: async (data: { content: string; tags?: string[]; metadata?: Record }): Promise<{ id: string; content: string; [key: string]: any }> => { const chunkId = await this.semantic.store(data.content, { ...data.metadata, tags: data.tags, @@ -195,10 +163,7 @@ export class MemoryResource extends BaseResource { * @param options 查询选项 * @returns 记忆列表 */ - list: async (options?: { - limit?: number; - filter?: Record; - }): Promise => { + list: async (options?: { limit?: number; filter?: Record }): Promise => { // 使用空查询返回所有记忆 return this.semantic.search("", options); }, @@ -237,9 +202,7 @@ export class MemoryResource extends BaseResource { * @returns 溯源信息 */ async getProvenance(memoryId: string): Promise { - return this.request( - `/v1/memory/provenance/${memoryId}`, - ); + return this.request(`/v1/memory/provenance/${memoryId}`); } /** @@ -250,9 +213,7 @@ export class MemoryResource extends BaseResource { * @returns 谱系链 */ async getLineage(memoryId: string): Promise { - const result = await this.request<{ lineage: Provenance[] }>( - `/v1/memory/lineage/${memoryId}`, - ); + const result = await this.request<{ lineage: Provenance[] }>(`/v1/memory/lineage/${memoryId}`); return result.lineage; } @@ -267,9 +228,7 @@ export class MemoryResource extends BaseResource { * @param options 合并选项 * @returns 合并任务结果 */ - async consolidate( - options?: ConsolidateOptions, - ): Promise { + async consolidate(options?: ConsolidateOptions): Promise { return this.request("/v1/memory/consolidate", { method: "POST", body: options, diff --git a/client-sdks/client-js/src/resources/middleware.ts b/client-sdks/client-js/src/resources/middleware.ts index 2f222a8..f6f4c76 100644 --- a/client-sdks/client-js/src/resources/middleware.ts +++ b/client-sdks/client-js/src/resources/middleware.ts @@ -4,11 +4,7 @@ */ import { BaseResource, ClientOptions } from "./base"; -import { - MiddlewareInfo, - UpdateMiddlewareRequest, - MiddlewareStats, -} from "../types/middleware"; +import { MiddlewareInfo, UpdateMiddlewareRequest, MiddlewareStats } from "../types/middleware"; /** * Middleware 资源类 @@ -27,12 +23,7 @@ export class MiddlewareResource extends BaseResource { * @param middleware Middleware 定义 * @returns Middleware 信息 */ - async create(middleware: { - name: string; - type: string; - priority: number; - config?: Record; - }): Promise { + async create(middleware: { name: string; type: string; priority: number; config?: Record }): Promise { return this.request("/v1/middlewares", { method: "POST", body: middleware, @@ -44,9 +35,7 @@ export class MiddlewareResource extends BaseResource { * @returns Middleware 列表 */ async list(): Promise { - const result = await this.request<{ middlewares: MiddlewareInfo[] }>( - "/v1/middlewares", - ); + const result = await this.request<{ middlewares: MiddlewareInfo[] }>("/v1/middlewares"); return result.middlewares; } @@ -65,10 +54,7 @@ export class MiddlewareResource extends BaseResource { * @param updates 更新内容 * @returns 更新后的 Middleware 信息 */ - async update( - name: string, - updates: UpdateMiddlewareRequest, - ): Promise { + async update(name: string, updates: UpdateMiddlewareRequest): Promise { return this.request(`/v1/middlewares/${name}`, { method: "PATCH", body: updates, @@ -106,10 +92,7 @@ export class MiddlewareResource extends BaseResource { * @param name Middleware 名称 * @param config 配置 */ - async updateConfig( - name: string, - config: Record, - ): Promise { + async updateConfig(name: string, config: Record): Promise { return this.update(name, { config }); } @@ -118,10 +101,7 @@ export class MiddlewareResource extends BaseResource { * @param name Middleware 名称 * @param priority 优先级(数字越小越早执行) */ - async updatePriority( - name: string, - priority: number, - ): Promise { + async updatePriority(name: string, priority: number): Promise { return this.update(name, { priority }); } @@ -143,9 +123,7 @@ export class MiddlewareResource extends BaseResource { * @returns 统计数据列表 */ async getAllStats(): Promise { - const result = await this.request<{ stats: MiddlewareStats[] }>( - "/v1/middlewares/stats", - ); + const result = await this.request<{ stats: MiddlewareStats[] }>("/v1/middlewares/stats"); return result.stats; } @@ -184,9 +162,7 @@ export class MiddlewareResource extends BaseResource { * @returns Middleware 名称列表(按执行顺序) */ async getExecutionOrder(): Promise { - const result = await this.request<{ order: string[] }>( - "/v1/middlewares/execution-order", - ); + const result = await this.request<{ order: string[] }>("/v1/middlewares/execution-order"); return result.order; } diff --git a/client-sdks/client-js/src/resources/session.ts b/client-sdks/client-js/src/resources/session.ts index 3b36ed1..6e913c5 100644 --- a/client-sdks/client-js/src/resources/session.ts +++ b/client-sdks/client-js/src/resources/session.ts @@ -4,21 +4,7 @@ */ import { BaseResource, ClientOptions } from "./base"; -import { - SessionConfig, - SessionInfo, - SessionFilter, - SessionStatus, - Message, - Pagination, - PaginatedResponse, - Checkpoint, - ResumeOptions, - SessionStats, - UpdateSessionRequest, - ExportOptions, - ExportResult, -} from "../types/session"; +import { SessionConfig, SessionInfo, SessionFilter, SessionStatus, Message, Pagination, PaginatedResponse, Checkpoint, ResumeOptions, SessionStats, UpdateSessionRequest, ExportOptions, ExportResult } from "../types/session"; /** * Session 资源类 @@ -69,10 +55,7 @@ export class SessionResource extends BaseResource { * @param sessionId Session ID * @param updates 更新内容 */ - async update( - sessionId: string, - updates: UpdateSessionRequest, - ): Promise { + async update(sessionId: string, updates: UpdateSessionRequest): Promise { return this.request(`/v1/sessions/${sessionId}`, { method: "PATCH", body: updates, @@ -99,14 +82,8 @@ export class SessionResource extends BaseResource { * @param pagination 分页参数 * @returns 消息列表 */ - async getMessages( - sessionId: string, - pagination?: Pagination, - ): Promise> { - return this.request>( - `/v1/sessions/${sessionId}/messages`, - { params: pagination }, - ); + async getMessages(sessionId: string, pagination?: Pagination): Promise> { + return this.request>(`/v1/sessions/${sessionId}/messages`, { params: pagination }); } /** @@ -115,10 +92,7 @@ export class SessionResource extends BaseResource { * @param message 消息内容 * @returns 创建的消息 */ - async addMessage( - sessionId: string, - message: Omit, - ): Promise { + async addMessage(sessionId: string, message: Omit): Promise { return this.request(`/v1/sessions/${sessionId}/messages`, { method: "POST", body: message, @@ -132,9 +106,7 @@ export class SessionResource extends BaseResource { * @returns 消息详情 */ async getMessage(sessionId: string, messageId: string): Promise { - return this.request( - `/v1/sessions/${sessionId}/messages/${messageId}`, - ); + return this.request(`/v1/sessions/${sessionId}/messages/${messageId}`); } /** @@ -158,9 +130,7 @@ export class SessionResource extends BaseResource { * @returns Checkpoint 列表 */ async getCheckpoints(sessionId: string): Promise { - const result = await this.request<{ checkpoints: Checkpoint[] }>( - `/v1/sessions/${sessionId}/checkpoints`, - ); + const result = await this.request<{ checkpoints: Checkpoint[] }>(`/v1/sessions/${sessionId}/checkpoints`); return result.checkpoints; } @@ -170,13 +140,8 @@ export class SessionResource extends BaseResource { * @param checkpointId Checkpoint ID * @returns Checkpoint 详情 */ - async getCheckpoint( - sessionId: string, - checkpointId: string, - ): Promise { - return this.request( - `/v1/sessions/${sessionId}/checkpoints/${checkpointId}`, - ); + async getCheckpoint(sessionId: string, checkpointId: string): Promise { + return this.request(`/v1/sessions/${sessionId}/checkpoints/${checkpointId}`); } /** @@ -184,10 +149,7 @@ export class SessionResource extends BaseResource { * @param sessionId Session ID * @param options 恢复选项 */ - async resume( - sessionId: string, - options?: ResumeOptions, - ): Promise { + async resume(sessionId: string, options?: ResumeOptions): Promise { return this.request(`/v1/sessions/${sessionId}/resume`, { method: "POST", body: options, @@ -200,10 +162,7 @@ export class SessionResource extends BaseResource { * @param label Checkpoint 标签(可选) * @returns 创建的 Checkpoint */ - async createCheckpoint( - sessionId: string, - label?: string, - ): Promise { + async createCheckpoint(sessionId: string, label?: string): Promise { return this.request(`/v1/sessions/${sessionId}/checkpoints`, { method: "POST", body: { label }, @@ -269,10 +228,7 @@ export class SessionResource extends BaseResource { * @param options 导出选项 * @returns 导出结果 */ - async export( - sessionId: string, - options: ExportOptions, - ): Promise { + async export(sessionId: string, options: ExportOptions): Promise { return this.request(`/v1/sessions/${sessionId}/export`, { method: "POST", body: options, diff --git a/client-sdks/client-js/src/resources/telemetry.ts b/client-sdks/client-js/src/resources/telemetry.ts index cfea8ff..39dd66d 100644 --- a/client-sdks/client-js/src/resources/telemetry.ts +++ b/client-sdks/client-js/src/resources/telemetry.ts @@ -45,9 +45,7 @@ export class TelemetryResource extends BaseResource { * @param config 配置更新 * @returns 更新后的配置 */ - async updateConfig( - config: Partial, - ): Promise { + async updateConfig(config: Partial): Promise { return this.request("/v1/telemetry/config", { method: "PATCH", body: config, @@ -63,9 +61,7 @@ export class TelemetryResource extends BaseResource { * @returns Metric 列表 */ async listMetrics(): Promise { - const result = await this.request<{ metrics: MetricInfo[] }>( - "/v1/telemetry/metrics", - ); + const result = await this.request<{ metrics: MetricInfo[] }>("/v1/telemetry/metrics"); return result.metrics; } @@ -84,13 +80,10 @@ export class TelemetryResource extends BaseResource { * @returns 数据点列表 */ async queryMetrics(options: MetricQueryOptions): Promise { - const result = await this.request<{ dataPoints: MetricDataPoint[] }>( - "/v1/telemetry/metrics/query", - { - method: "POST", - body: options, - }, - ); + const result = await this.request<{ dataPoints: MetricDataPoint[] }>("/v1/telemetry/metrics/query", { + method: "POST", + body: options, + }); return result.dataPoints; } @@ -100,17 +93,8 @@ export class TelemetryResource extends BaseResource { * @param value 值 * @param labels 标签(可选) */ - async recordMetric( - name: string, - value: number, - labels?: Record, - ): Promise; - async recordMetric(data: { - name: string; - type?: string; - value: number; - labels?: Record; - }): Promise; + async recordMetric(name: string, value: number, labels?: Record): Promise; + async recordMetric(data: { name: string; type?: string; value: number; labels?: Record }): Promise; async recordMetric( nameOrData: | string @@ -144,13 +128,7 @@ export class TelemetryResource extends BaseResource { * @param trace Trace 数据 * @returns Trace 信息 */ - async recordTrace(trace: { - name: string; - span_id: string; - trace_id?: string; - parent_id?: string; - [key: string]: any; - }): Promise { + async recordTrace(trace: { name: string; span_id: string; trace_id?: string; parent_id?: string; [key: string]: any }): Promise { return this.request("/v1/telemetry/traces", { method: "POST", body: trace, @@ -163,13 +141,10 @@ export class TelemetryResource extends BaseResource { * @returns Trace 列表 */ async queryTraces(options?: TraceQueryOptions): Promise { - const result = await this.request<{ traces: TraceInfo[] }>( - "/v1/telemetry/traces/query", - { - method: "POST", - body: options || {}, - }, - ); + const result = await this.request<{ traces: TraceInfo[] }>("/v1/telemetry/traces/query", { + method: "POST", + body: options || {}, + }); return result.traces; } @@ -197,9 +172,7 @@ export class TelemetryResource extends BaseResource { * @returns Span 列表 */ async getTraceSpans(traceId: string): Promise { - const result = await this.request<{ spans: TraceInfo[] }>( - `/v1/telemetry/traces/${traceId}/spans`, - ); + const result = await this.request<{ spans: TraceInfo[] }>(`/v1/telemetry/traces/${traceId}/spans`); return result.spans; } @@ -213,13 +186,10 @@ export class TelemetryResource extends BaseResource { * @returns 日志列表 */ async queryLogs(options: LogQueryOptions): Promise { - const result = await this.request<{ logs: LogEntry[] }>( - "/v1/telemetry/logs/query", - { - method: "POST", - body: options, - }, - ); + const result = await this.request<{ logs: LogEntry[] }>("/v1/telemetry/logs/query", { + method: "POST", + body: options, + }); return result.logs; } @@ -240,9 +210,7 @@ export class TelemetryResource extends BaseResource { * @returns 日志列表 */ async getTraceLogs(traceId: string): Promise { - const result = await this.request<{ logs: LogEntry[] }>( - `/v1/telemetry/traces/${traceId}/logs`, - ); + const result = await this.request<{ logs: LogEntry[] }>(`/v1/telemetry/traces/${traceId}/logs`); return result.logs; } @@ -280,10 +248,7 @@ export class TelemetryResource extends BaseResource { * @param timeRange 时间范围 * @returns 性能指标 */ - async getPerformanceMetrics(timeRange?: { - start: string; - end: string; - }): Promise { + async getPerformanceMetrics(timeRange?: { start: string; end: string }): Promise { return this.request("/v1/telemetry/performance", { params: timeRange, }); @@ -294,10 +259,7 @@ export class TelemetryResource extends BaseResource { * @param timeRange 时间范围 * @returns 使用统计 */ - async getUsageStatistics(timeRange?: { - start: string; - end: string; - }): Promise { + async getUsageStatistics(timeRange?: { start: string; end: string }): Promise { return this.request("/v1/telemetry/usage", { params: timeRange, }); @@ -312,9 +274,7 @@ export class TelemetryResource extends BaseResource { * @param request 导出请求 * @returns 导出结果 */ - async export( - request: ExportTelemetryRequest, - ): Promise { + async export(request: ExportTelemetryRequest): Promise { return this.request("/v1/telemetry/export", { method: "POST", body: request, @@ -327,10 +287,7 @@ export class TelemetryResource extends BaseResource { * @param timeRange 时间范围 * @returns 导出结果 */ - async exportMetrics( - format: "json" | "csv" | "prometheus", - timeRange?: { start: string; end: string }, - ): Promise { + async exportMetrics(format: "json" | "csv" | "prometheus", timeRange?: { start: string; end: string }): Promise { return this.export({ type: "metrics", format, @@ -344,10 +301,7 @@ export class TelemetryResource extends BaseResource { * @param timeRange 时间范围 * @returns 导出结果 */ - async exportTraces( - format: "json" | "opentelemetry", - timeRange?: { start: string; end: string }, - ): Promise { + async exportTraces(format: "json" | "opentelemetry", timeRange?: { start: string; end: string }): Promise { return this.export({ type: "traces", format, @@ -361,10 +315,7 @@ export class TelemetryResource extends BaseResource { * @param timeRange 时间范围 * @returns 导出结果 */ - async exportLogs( - format: "json" | "csv", - timeRange?: { start: string; end: string }, - ): Promise { + async exportLogs(format: "json" | "csv", timeRange?: { start: string; end: string }): Promise { return this.export({ type: "logs", format, diff --git a/client-sdks/client-js/src/resources/tool.ts b/client-sdks/client-js/src/resources/tool.ts index 9288938..30cdeea 100644 --- a/client-sdks/client-js/src/resources/tool.ts +++ b/client-sdks/client-js/src/resources/tool.ts @@ -4,15 +4,7 @@ */ import { BaseResource, ClientOptions } from "./base"; -import { - ToolInfo, - ToolExecutionRequest, - ToolExecutionResponse, - AsyncToolExecutionResponse, - TaskProgress, - ToolStats, - ToolUsageReport, -} from "../types/tool"; +import { ToolInfo, ToolExecutionRequest, ToolExecutionResponse, AsyncToolExecutionResponse, TaskProgress, ToolStats, ToolUsageReport } from "../types/tool"; /** * Tool 资源类 @@ -31,12 +23,7 @@ export class ToolResource extends BaseResource { * @param tool 工具定义 * @returns 工具信息 */ - async create(tool: { - name: string; - type: string; - schema: Record; - description?: string; - }): Promise { + async create(tool: { name: string; type: string; schema: Record; description?: string }): Promise { return this.request("/v1/tools", { method: "POST", body: tool, @@ -48,11 +35,7 @@ export class ToolResource extends BaseResource { * @param filter 过滤条件 * @returns 工具列表 */ - async list(filter?: { - type?: "builtin" | "custom" | "mcp"; - category?: string; - enabled?: boolean; - }): Promise { + async list(filter?: { type?: "builtin" | "custom" | "mcp"; category?: string; enabled?: boolean }): Promise { const result = await this.request<{ tools: ToolInfo[] }>("/v1/tools", { params: filter, }); @@ -121,10 +104,7 @@ export class ToolResource extends BaseResource { * @param params 参数 * @returns 任务信息 */ - async executeAsync( - toolName: string, - params: Record, - ): Promise { + async executeAsync(toolName: string, params: Record): Promise { return this.request("/v1/tools/execute", { method: "POST", body: { @@ -140,9 +120,7 @@ export class ToolResource extends BaseResource { * @param request 执行请求 * @returns 执行结果或任务信息 */ - async executeWithOptions( - request: ToolExecutionRequest, - ): Promise { + async executeWithOptions(request: ToolExecutionRequest): Promise { return this.request("/v1/tools/execute", { method: "POST", body: request, @@ -168,14 +146,8 @@ export class ToolResource extends BaseResource { * @param filter 过滤条件 * @returns 任务列表 */ - async listTasks(filter?: { - status?: "pending" | "running" | "completed" | "failed" | "cancelled"; - toolName?: string; - }): Promise { - const result = await this.request<{ tasks: TaskProgress[] }>( - "/v1/tools/tasks", - { params: filter }, - ); + async listTasks(filter?: { status?: "pending" | "running" | "completed" | "failed" | "cancelled"; toolName?: string }): Promise { + const result = await this.request<{ tasks: TaskProgress[] }>("/v1/tools/tasks", { params: filter }); return result.tasks; } @@ -210,19 +182,13 @@ export class ToolResource extends BaseResource { const task = await this.getTaskProgress(taskId); // 检查是否完成 - if ( - task.status === "completed" || - task.status === "failed" || - task.status === "cancelled" - ) { + if (task.status === "completed" || task.status === "failed" || task.status === "cancelled") { return task; } // 检查超时 if (Date.now() - startTime > timeout) { - throw new Error( - `Task timeout after ${timeout}ms. Current status: ${task.status}`, - ); + throw new Error(`Task timeout after ${timeout}ms. Current status: ${task.status}`); } // 等待后继续轮询 @@ -248,9 +214,7 @@ export class ToolResource extends BaseResource { * @returns 统计数据列表 */ async getAllStats(): Promise { - const result = await this.request<{ stats: ToolStats[] }>( - "/v1/tools/stats", - ); + const result = await this.request<{ stats: ToolStats[] }>("/v1/tools/stats"); return result.stats; } @@ -259,10 +223,7 @@ export class ToolResource extends BaseResource { * @param timeRange 时间范围 * @returns 使用报告 */ - async getUsageReport(timeRange?: { - start: string; - end: string; - }): Promise { + async getUsageReport(timeRange?: { start: string; end: string }): Promise { return this.request("/v1/tools/usage-report", { params: timeRange, }); diff --git a/client-sdks/client-js/src/resources/workflow.ts b/client-sdks/client-js/src/resources/workflow.ts index 6d5b280..2db4a71 100644 --- a/client-sdks/client-js/src/resources/workflow.ts +++ b/client-sdks/client-js/src/resources/workflow.ts @@ -58,9 +58,7 @@ export class WorkflowResource extends BaseResource { * @param filter 过滤条件 * @returns Workflow 列表 */ - async list( - filter?: WorkflowFilter, - ): Promise> { + async list(filter?: WorkflowFilter): Promise> { return this.request>("/v1/workflows", { params: filter, }); @@ -72,10 +70,7 @@ export class WorkflowResource extends BaseResource { * @param updates 更新内容 * @returns 更新后的 Workflow */ - async update( - workflowId: string, - updates: UpdateWorkflowRequest, - ): Promise { + async update(workflowId: string, updates: UpdateWorkflowRequest): Promise { return this.request(`/v1/workflows/${workflowId}`, { method: "PATCH", body: updates, @@ -102,10 +97,7 @@ export class WorkflowResource extends BaseResource { * @param request 执行请求 * @returns Workflow 执行记录 */ - async execute( - workflowId: string, - request: ExecuteWorkflowRequest, - ): Promise { + async execute(workflowId: string, request: ExecuteWorkflowRequest): Promise { return this.request(`/v1/workflows/${workflowId}/execute`, { method: "POST", body: request, @@ -117,10 +109,7 @@ export class WorkflowResource extends BaseResource { * @param workflowId Workflow ID * @param request 暂停请求 */ - async suspend( - workflowId: string, - request: SuspendWorkflowRequest, - ): Promise { + async suspend(workflowId: string, request: SuspendWorkflowRequest): Promise { await this.request(`/v1/workflows/${workflowId}/suspend`, { method: "POST", body: request, @@ -132,10 +121,7 @@ export class WorkflowResource extends BaseResource { * @param workflowId Workflow ID * @param request 恢复请求 */ - async resume( - workflowId: string, - request: ResumeWorkflowRequest, - ): Promise { + async resume(workflowId: string, request: ResumeWorkflowRequest): Promise { await this.request(`/v1/workflows/${workflowId}/resume`, { method: "POST", body: request, @@ -147,10 +133,7 @@ export class WorkflowResource extends BaseResource { * @param workflowId Workflow ID * @param request 取消请求 */ - async cancel( - workflowId: string, - request: CancelWorkflowRequest, - ): Promise { + async cancel(workflowId: string, request: CancelWorkflowRequest): Promise { await this.request(`/v1/workflows/${workflowId}/cancel`, { method: "POST", body: request, @@ -167,14 +150,8 @@ export class WorkflowResource extends BaseResource { * @param filter 过滤条件 * @returns 执行记录列表 */ - async getRuns( - workflowId: string, - filter?: WorkflowRunFilter, - ): Promise> { - return this.request>( - `/v1/workflows/${workflowId}/executions`, - { params: filter }, - ); + async getRuns(workflowId: string, filter?: WorkflowRunFilter): Promise> { + return this.request>(`/v1/workflows/${workflowId}/executions`, { params: filter }); } /** @@ -183,10 +160,7 @@ export class WorkflowResource extends BaseResource { * @param filter 过滤条件 * @returns 执行记录数组 */ - async listExecutions( - workflowId: string, - filter?: WorkflowRunFilter, - ): Promise { + async listExecutions(workflowId: string, filter?: WorkflowRunFilter): Promise { const result = await this.getRuns(workflowId, filter); return result.items || []; } @@ -198,9 +172,7 @@ export class WorkflowResource extends BaseResource { * @returns 执行详情 */ async getRunDetails(workflowId: string, runId: string): Promise { - return this.request( - `/v1/workflows/${workflowId}/runs/${runId}`, - ); + return this.request(`/v1/workflows/${workflowId}/runs/${runId}`); } /** @@ -210,9 +182,7 @@ export class WorkflowResource extends BaseResource { * @returns 执行状态 */ async getRunStatus(workflowId: string, runId: string): Promise { - return this.request( - `/v1/workflows/${workflowId}/runs/${runId}/status`, - ); + return this.request(`/v1/workflows/${workflowId}/runs/${runId}/status`); } // ========================================================================== @@ -224,9 +194,7 @@ export class WorkflowResource extends BaseResource { * @param definition Workflow 定义 * @returns 验证结果 */ - async validate( - definition: WorkflowDefinition, - ): Promise { + async validate(definition: WorkflowDefinition): Promise { return this.request("/v1/workflows/validate", { method: "POST", body: definition, @@ -286,19 +254,13 @@ export class WorkflowResource extends BaseResource { const run = await this.getRunStatus(workflowId, runId); // 检查是否完成 - if ( - run.status === "completed" || - run.status === "failed" || - run.status === "cancelled" - ) { + if (run.status === "completed" || run.status === "failed" || run.status === "cancelled") { return run; } // 检查超时 if (Date.now() - startTime > timeout) { - throw new Error( - `Workflow execution timeout after ${timeout}ms. Current status: ${run.status}`, - ); + throw new Error(`Workflow execution timeout after ${timeout}ms. Current status: ${run.status}`); } // 等待后继续轮询 diff --git a/client-sdks/client-js/src/transport/websocket.ts b/client-sdks/client-js/src/transport/websocket.ts index 4dcb85b..def6218 100644 --- a/client-sdks/client-js/src/transport/websocket.ts +++ b/client-sdks/client-js/src/transport/websocket.ts @@ -70,10 +70,7 @@ export class WebSocketClient { * 连接到 WebSocket 服务器 */ async connect(url: string): Promise { - if ( - this.state === WebSocketState.CONNECTED || - this.state === WebSocketState.CONNECTING - ) { + if (this.state === WebSocketState.CONNECTED || this.state === WebSocketState.CONNECTING) { console.warn("[WebSocket] Already connected or connecting"); return; } @@ -84,8 +81,7 @@ export class WebSocketClient { return new Promise((resolve, reject) => { try { // 在浏览器和 Node.js 中使用不同的 WebSocket - const WebSocketImpl = - typeof window !== "undefined" ? window.WebSocket : require("ws"); + const WebSocketImpl = typeof window !== "undefined" ? window.WebSocket : require("ws"); this.ws = new WebSocketImpl(url); @@ -131,10 +127,7 @@ export class WebSocketClient { * 断开连接 */ disconnect(): void { - if ( - this.state === WebSocketState.DISCONNECTED || - this.state === WebSocketState.DISCONNECTING - ) { + if (this.state === WebSocketState.DISCONNECTED || this.state === WebSocketState.DISCONNECTING) { return; } @@ -153,8 +146,7 @@ export class WebSocketClient { * 发送消息 */ send(message: any): void { - const data = - typeof message === "string" ? message : JSON.stringify(message); + const data = typeof message === "string" ? message : JSON.stringify(message); if (this.state === WebSocketState.CONNECTED && this.ws) { try { @@ -204,10 +196,7 @@ export class WebSocketClient { */ private handleMessage(data: string | Buffer): void { try { - const message = - typeof data === "string" - ? JSON.parse(data) - : JSON.parse(data.toString()); + const message = typeof data === "string" ? JSON.parse(data) : JSON.parse(data.toString()); // 检查是否为心跳响应 if (message.type === "pong") { @@ -232,10 +221,7 @@ export class WebSocketClient { * 刷新消息队列 */ private flushMessageQueue(): void { - while ( - this.messageQueue.length > 0 && - this.state === WebSocketState.CONNECTED - ) { + while (this.messageQueue.length > 0 && this.state === WebSocketState.CONNECTED) { const message = this.messageQueue.shift(); this.send(message); } @@ -256,9 +242,7 @@ export class WebSocketClient { // 指数退避 const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1); - console.log( - `[WebSocket] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`, - ); + console.log(`[WebSocket] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`); await new Promise((resolve) => setTimeout(resolve, delay)); diff --git a/client-sdks/client-js/src/types/agent.ts b/client-sdks/client-js/src/types/agent.ts index 7106a07..87a7b82 100644 --- a/client-sdks/client-js/src/types/agent.ts +++ b/client-sdks/client-js/src/types/agent.ts @@ -236,12 +236,7 @@ export interface ToolCall { /** * 流式 Chat 事件 */ -export type StreamChatEvent = - | { type: "start"; sessionId: string } - | { type: "token"; token: string } - | { type: "tool_call"; toolCall: ToolCall } - | { type: "end"; response: ChatResponse } - | { type: "error"; error: string }; +export type StreamChatEvent = { type: "start"; sessionId: string } | { type: "token"; token: string } | { type: "tool_call"; toolCall: ToolCall } | { type: "end"; response: ChatResponse } | { type: "error"; error: string }; // ============================================================================ // Agent Statistics diff --git a/client-sdks/client-js/src/types/mcp.ts b/client-sdks/client-js/src/types/mcp.ts index 78566a9..3fa05d6 100644 --- a/client-sdks/client-js/src/types/mcp.ts +++ b/client-sdks/client-js/src/types/mcp.ts @@ -228,12 +228,7 @@ export interface MCPStats { /** * MCP 事件类型 */ -export type MCPEventType = - | "server_connected" - | "server_disconnected" - | "tool_called" - | "tool_completed" - | "error"; +export type MCPEventType = "server_connected" | "server_disconnected" | "tool_called" | "tool_completed" | "error"; /** * MCP 事件 diff --git a/client-sdks/client-js/src/types/memory.ts b/client-sdks/client-js/src/types/memory.ts index df922cf..3e2fea9 100644 --- a/client-sdks/client-js/src/types/memory.ts +++ b/client-sdks/client-js/src/types/memory.ts @@ -111,11 +111,7 @@ export interface SearchResult { /** * 记忆来源类型 */ -export type MemorySource = - | "user_input" - | "tool_output" - | "inference" - | "external"; +export type MemorySource = "user_input" | "tool_output" | "inference" | "external"; /** * 记忆溯源信息 diff --git a/client-sdks/client-js/src/types/middleware.ts b/client-sdks/client-js/src/types/middleware.ts index 0a16911..0381b8c 100644 --- a/client-sdks/client-js/src/types/middleware.ts +++ b/client-sdks/client-js/src/types/middleware.ts @@ -106,9 +106,7 @@ export interface ToolApprovalConfig { */ export interface PIIRedactionConfig { /** 启用的 PII 类型 */ - enabledTypes: Array< - "email" | "phone" | "ssn" | "credit_card" | "ip_address" | "name" - >; + enabledTypes: Array<"email" | "phone" | "ssn" | "credit_card" | "ip_address" | "name">; /** 脱敏策略 */ strategy: "mask" | "remove" | "replace"; /** 替换文本(strategy=replace 时使用) */ diff --git a/client-sdks/client-js/src/types/workflow.ts b/client-sdks/client-js/src/types/workflow.ts index e23d476..95602f7 100644 --- a/client-sdks/client-js/src/types/workflow.ts +++ b/client-sdks/client-js/src/types/workflow.ts @@ -95,10 +95,7 @@ export interface LoopWorkflowDefinition extends BaseWorkflowDefinition { /** * Workflow 定义联合类型 */ -export type WorkflowDefinition = - | ParallelWorkflowDefinition - | SequentialWorkflowDefinition - | LoopWorkflowDefinition; +export type WorkflowDefinition = ParallelWorkflowDefinition | SequentialWorkflowDefinition | LoopWorkflowDefinition; // ============================================================================ // Workflow Info diff --git a/client-sdks/client-js/tests/integration/client.test.ts b/client-sdks/client-js/tests/integration/client.test.ts index b35644a..79a5b4b 100644 --- a/client-sdks/client-js/tests/integration/client.test.ts +++ b/client-sdks/client-js/tests/integration/client.test.ts @@ -120,10 +120,7 @@ describe("AsterClient Client Integration", () => { }), ); - const results = await client.memory.semantic.search( - "What is the user preference?", - { limit: 5 }, - ); + const results = await client.memory.semantic.search("What is the user preference?", { limit: 5 }); expect(results.length).toBeGreaterThan(0); expect(global.fetch).toHaveBeenCalledTimes(2); diff --git a/client-sdks/client-js/tests/resources/memory.test.ts b/client-sdks/client-js/tests/resources/memory.test.ts index f9e1469..cb3665d 100644 --- a/client-sdks/client-js/tests/resources/memory.test.ts +++ b/client-sdks/client-js/tests/resources/memory.test.ts @@ -141,10 +141,7 @@ describe("MemoryResource", () => { await memory.working.get("global_config", "resource"); - expect(mockFetch).toHaveBeenCalledWith( - "http://localhost:8080/v1/memory/working/global_config?scope=resource", - expect.any(Object), - ); + expect(mockFetch).toHaveBeenCalledWith("http://localhost:8080/v1/memory/working/global_config?scope=resource", expect.any(Object)); }); }); @@ -175,10 +172,7 @@ describe("MemoryResource", () => { await memory.working.delete("global_config", "resource"); - expect(mockFetch).toHaveBeenCalledWith( - "http://localhost:8080/v1/memory/working/global_config?scope=resource", - expect.any(Object), - ); + expect(mockFetch).toHaveBeenCalledWith("http://localhost:8080/v1/memory/working/global_config?scope=resource", expect.any(Object)); }); }); @@ -233,10 +227,7 @@ describe("MemoryResource", () => { await memory.working.list("resource"); - expect(mockFetch).toHaveBeenCalledWith( - "http://localhost:8080/v1/memory/working?scope=resource", - expect.any(Object), - ); + expect(mockFetch).toHaveBeenCalledWith("http://localhost:8080/v1/memory/working?scope=resource", expect.any(Object)); }); }); @@ -316,10 +307,7 @@ describe("MemoryResource", () => { text: async () => JSON.stringify({ chunkId: "chunk-123" }), }); - const chunkId = await memory.semantic.store( - "Paris is the capital of France", - { source: "wikipedia", category: "geography" }, - ); + const chunkId = await memory.semantic.store("Paris is the capital of France", { source: "wikipedia", category: "geography" }); expect(chunkId).toBe("chunk-123"); diff --git a/client-sdks/client-js/vitest.config.ts b/client-sdks/client-js/vitest.config.ts index f09e89b..83f5f24 100644 --- a/client-sdks/client-js/vitest.config.ts +++ b/client-sdks/client-js/vitest.config.ts @@ -7,13 +7,7 @@ export default defineConfig({ coverage: { provider: "v8", reporter: ["text", "json", "html"], - exclude: [ - "node_modules/", - "dist/", - "tests/", - "**/*.test.ts", - "**/*.config.ts", - ], + exclude: ["node_modules/", "dist/", "tests/", "**/*.test.ts", "**/*.config.ts"], }, }, }); diff --git a/docs/components/AppHeader.vue b/docs/components/AppHeader.vue index 51ca3bf..cc4321a 100644 --- a/docs/components/AppHeader.vue +++ b/docs/components/AppHeader.vue @@ -5,11 +5,7 @@ Aster Logo
- - Aster · 星尘云枢 - + Aster · 星尘云枢 星尘汇聚,智能成枢
diff --git a/docs/content/05.tools/2.builtin/1.builtin.md b/docs/content/05.tools/2.builtin/1.builtin.md index dbc5846..e5ed427 100644 --- a/docs/content/05.tools/2.builtin/1.builtin.md +++ b/docs/content/05.tools/2.builtin/1.builtin.md @@ -625,23 +625,10 @@ result, err := ag.Chat(ctx, "这个任务比较复杂,我需要先规划一下 "ok": true, "plan_file_path": ".aster/plans/sunny-singing-nygaard.md", "plan_id": "sunny-singing-nygaard", - "allowed_tools": [ - "Read", - "Glob", - "Grep", - "WebFetch", - "WebSearch", - "AskUserQuestion", - "Write" - ], + "allowed_tools": ["Read", "Glob", "Grep", "WebFetch", "WebSearch", "AskUserQuestion", "Write"], "workflow": "## Plan Mode Workflow\n...", "message": "Plan mode activated. You can now explore the codebase and create your plan.", - "next_steps": [ - "1. Read the codebase to understand existing patterns", - "2. Ask user questions to clarify requirements", - "3. Update the plan file with your findings", - "4. Call ExitPlanMode when ready for user approval" - ], + "next_steps": ["1. Read the codebase to understand existing patterns", "2. Ask user questions to clarify requirements", "3. Update the plan file with your findings", "4. Call ExitPlanMode when ready for user approval"], "constraints": { "read_only": true, "plan_file_writable": ".aster/plans/sunny-singing-nygaard.md", @@ -698,11 +685,7 @@ result, err := ag.Chat(ctx, "规划完成,请用户审批") "confirmation_required": true, "duration_ms": 5, "message": "Plan is ready for user review. The user will see the plan content and can approve or request changes.", - "next_steps": [ - "User needs to review the plan", - "After approval, implementation can begin", - "User can request modifications if needed" - ] + "next_steps": ["User needs to review the plan", "After approval, implementation can begin", "User can request modifications if needed"] } ``` diff --git a/docs/content/11.evals/1.overview/index.md b/docs/content/11.evals/1.overview/index.md index 66c5f25..8f1f013 100644 --- a/docs/content/11.evals/1.overview/index.md +++ b/docs/content/11.evals/1.overview/index.md @@ -511,13 +511,7 @@ func main() { "reference": "伦敦是英国的首都。" } ], - "scorers": [ - "keyword_coverage", - "lexical_similarity", - "faithfulness", - "hallucination", - "answer_relevancy" - ], + "scorers": ["keyword_coverage", "lexical_similarity", "faithfulness", "hallucination", "answer_relevancy"], "concurrency": 5, "keywords": ["首都"], "provider_config": { diff --git a/docs/content/16.whitepaper/1.whitepaper.md b/docs/content/16.whitepaper/1.whitepaper.md index 6b02fb5..9a9bcf9 100644 --- a/docs/content/16.whitepaper/1.whitepaper.md +++ b/docs/content/16.whitepaper/1.whitepaper.md @@ -3829,8 +3829,7 @@ Agent配置文件中声明MCP Servers: mcp_servers: filesystem: command: "npx" - args: - ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/workspace"] + args: ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/workspace"] github: command: "npx" diff --git a/docs/content/18.architecture/4.client-sdk.md b/docs/content/18.architecture/4.client-sdk.md index ef7ce66..34f72e8 100644 --- a/docs/content/18.architecture/4.client-sdk.md +++ b/docs/content/18.architecture/4.client-sdk.md @@ -79,13 +79,10 @@ class AgentsdkClient { ```typescript // 订阅事件 -const subscription = await client.agents.subscribe( - [Channel.Progress, Channel.Control, Channel.Monitor], - { - agentId: "agent-123", - eventTypes: ["thinking", "text_chunk", "tool_start"], - }, -); +const subscription = await client.agents.subscribe([Channel.Progress, Channel.Control, Channel.Monitor], { + agentId: "agent-123", + eventTypes: ["thinking", "text_chunk", "tool_start"], +}); // 处理事件 for await (const event of subscription) { @@ -152,10 +149,7 @@ class BaseResource { } // 统一的请求方法 - protected async request( - path: string, - options?: RequestOptions, - ): Promise { + protected async request(path: string, options?: RequestOptions): Promise { // 1. Retry 机制(exponential backoff) // 2. 错误处理和恢复 // 3. Request Context 传递 @@ -165,18 +159,12 @@ class BaseResource { } // 流式请求 - protected async *streamRequest( - path: string, - options?: RequestOptions, - ): AsyncGenerator { + protected async *streamRequest(path: string, options?: RequestOptions): AsyncGenerator { // SSE 解析和 AsyncGenerator } // 事件订阅 - protected subscribe( - path: string, - options?: SubscribeOptions, - ): EventSubscription { + protected subscribe(path: string, options?: SubscribeOptions): EventSubscription { // WebSocket 长连接 } } @@ -526,10 +514,7 @@ for await (const event of client.agents.stream({ ```typescript // 订阅所有通道 -const subscription = await client.agents.subscribe( - ["progress", "control", "monitor"], - { agentId: "agent-123" }, -); +const subscription = await client.agents.subscribe(["progress", "control", "monitor"], { agentId: "agent-123" }); for await (const event of subscription) { console.log(event.channel, event.type, event.data); diff --git a/docs/tailwind.config.js b/docs/tailwind.config.js index e8111de..26c4422 100644 --- a/docs/tailwind.config.js +++ b/docs/tailwind.config.js @@ -2,28 +2,12 @@ import defaultTheme from "tailwindcss/defaultTheme"; /** @type {import('tailwindcss').Config} */ export default { - content: [ - "./components/**/*.{js,vue,ts}", - "./layouts/**/*.vue", - "./pages/**/*.vue", - "./plugins/**/*.{js,ts}", - "./app.vue", - "./content/**/*.md", - ], + content: ["./components/**/*.{js,vue,ts}", "./layouts/**/*.vue", "./pages/**/*.vue", "./plugins/**/*.{js,ts}", "./app.vue", "./content/**/*.md"], darkMode: "class", theme: { extend: { fontFamily: { - mono: [ - "ui-monospace", - "SFMono-Regular", - "Menlo", - "Monaco", - "Consolas", - '"Liberation Mono"', - '"Courier New"', - ...defaultTheme.fontFamily.mono, - ], + mono: ["ui-monospace", "SFMono-Regular", "Menlo", "Monaco", "Consolas", '"Liberation Mono"', '"Courier New"', ...defaultTheme.fontFamily.mono], }, colors: { primary: { diff --git a/examples/actor/README.md b/examples/actor/README.md index d6498ae..87a7422 100644 --- a/examples/actor/README.md +++ b/examples/actor/README.md @@ -33,13 +33,13 @@ Actor 模型是一种并发计算模型,每个 Actor 是独立的计算单元 ## 演示命令 -| 命令 | 说明 | -|------|------| -| `go run . basic` | 基础 Ping-Pong 消息传递 | -| `go run . counter` | 并发安全计数器 | -| `go run . supervisor` | 监督者故障恢复策略 | -| `go run . pipeline` | 流水线处理模式 | -| `go run . broadcast` | 广播消息给多个订阅者 | +| 命令 | 说明 | +| --------------------- | ----------------------- | +| `go run . basic` | 基础 Ping-Pong 消息传递 | +| `go run . counter` | 并发安全计数器 | +| `go run . supervisor` | 监督者故障恢复策略 | +| `go run . pipeline` | 流水线处理模式 | +| `go run . broadcast` | 广播消息给多个订阅者 | ## 运行示例 @@ -158,13 +158,13 @@ pid.Tell(&agent.ChatMsg{ ## 使用场景 -| 场景 | 适用度 | 说明 | -|------|--------|------| -| 多 Agent 协作 | ⭐⭐⭐⭐⭐ | 每个 Agent 是独立 Actor | -| 并发任务处理 | ⭐⭐⭐⭐⭐ | 消息驱动,无锁并发 | -| 故障隔离 | ⭐⭐⭐⭐⭐ | Actor 故障不影响其他 Actor | -| 流水线处理 | ⭐⭐⭐⭐ | 多阶段异步处理 | -| 发布订阅 | ⭐⭐⭐⭐ | 广播消息给多个订阅者 | +| 场景 | 适用度 | 说明 | +| ------------- | ---------- | -------------------------- | +| 多 Agent 协作 | ⭐⭐⭐⭐⭐ | 每个 Agent 是独立 Actor | +| 并发任务处理 | ⭐⭐⭐⭐⭐ | 消息驱动,无锁并发 | +| 故障隔离 | ⭐⭐⭐⭐⭐ | Actor 故障不影响其他 Actor | +| 流水线处理 | ⭐⭐⭐⭐ | 多阶段异步处理 | +| 发布订阅 | ⭐⭐⭐⭐ | 广播消息给多个订阅者 | ## 性能特点 diff --git a/examples/agent-working-memory/README.md b/examples/agent-working-memory/README.md index 611cdeb..287189b 100644 --- a/examples/agent-working-memory/README.md +++ b/examples/agent-working-memory/README.md @@ -5,6 +5,7 @@ ## 什么是 Working Memory? Working Memory 是一个持久化的、结构化的状态管理系统,它能够: + - **自动加载**:每轮对话开始时自动加载到 system prompt - **LLM 控制**:Agent 可以通过 `update_working_memory` 工具主动更新 - **作用域隔离**:支持 thread 和 resource 两种作用域 @@ -12,17 +13,18 @@ Working Memory 是一个持久化的、结构化的状态管理系统,它能 ## 与普通记忆的区别 -| 特性 | Working Memory | 文本记忆 (agent_memory) | -|------|---------------|------------------------| -| **自动加载** | ✅ 每轮对话自动加载 | ❌ 需要 LLM 主动读取 | -| **更新方式** | 完全覆盖 | 追加或覆盖 | -| **大小** | 小(< 500 words)| 大(无限制)| -| **结构** | 结构化(可选 Schema)| 自由文本 | -| **用途** | 会话状态管理 | 长期知识库 | +| 特性 | Working Memory | 文本记忆 (agent_memory) | +| ------------ | --------------------- | ----------------------- | +| **自动加载** | ✅ 每轮对话自动加载 | ❌ 需要 LLM 主动读取 | +| **更新方式** | 完全覆盖 | 追加或覆盖 | +| **大小** | 小(< 500 words) | 大(无限制) | +| **结构** | 结构化(可选 Schema) | 自由文本 | +| **用途** | 会话状态管理 | 长期知识库 | ## 示例场景 本示例模拟一个**任务助手 Agent**,它能够: + 1. 记住用户的偏好和设置 2. 跟踪当前任务的进度 3. 在多轮对话间保持状态 @@ -44,7 +46,7 @@ examples/agent-working-memory/ memory: working_memory: enabled: true - scope: "thread" # 每个会话独立的状态 + scope: "thread" # 每个会话独立的状态 base_path: "/working_memory/" # 可选:定义 Schema 确保数据一致性 @@ -56,14 +58,14 @@ memory: preferences: type: object properties: - language: {type: string} - verbosity: {type: string} + language: { type: string } + verbosity: { type: string } current_task: type: object properties: - name: {type: string} - status: {type: string} - progress: {type: integer} + name: { type: string } + status: { type: string } + progress: { type: integer } required: ["user_name"] ``` @@ -249,7 +251,7 @@ working_memory: schema: type: object properties: - user_name: {type: string} + user_name: { type: string } task_status: type: string enum: ["pending", "in_progress", "completed"] @@ -278,6 +280,7 @@ manager.Update(ctx, threadID, resourceID, `{ - 只存储当前会话相关的状态 2. **使用清晰的结构** + ```json { "user_info": {...}, @@ -331,6 +334,7 @@ Working Memory(当前状态): ``` **策略:** + - **Working Memory**:存储当前会话需要的最小状态 - **文本记忆**:存储详细的历史记录和知识 - **定期归档**:将 Working Memory 中完成的任务归档到文本记忆 @@ -342,6 +346,7 @@ Working Memory(当前状态): **症状**:Agent 没有记住之前的信息 **解决**: + 1. 检查 `agentsdk.yaml` 中 `working_memory.enabled` 是否为 `true` 2. 确认 Middlewares 包含 `"working_memory"` 3. 检查 threadID/resourceID 是否正确传递 @@ -351,6 +356,7 @@ Working Memory(当前状态): **症状**:更新 Working Memory 时报错 **解决**: + 1. 确保内容是有效的 JSON 2. 检查是否包含所有 `required` 字段 3. 验证字段类型是否匹配 @@ -362,6 +368,7 @@ Working Memory(当前状态): **原因**:`update_working_memory` 是完全覆盖模式 **解决**: + ```json // ❌ 错误:只更新部分,其他内容会丢失 {"user_name": "Alice"} @@ -389,4 +396,4 @@ Working Memory 让 Agent 拥有了真正的"记忆"能力: - ✅ **持久化** - 跨会话保持状态 - ✅ **结构化** - Schema 验证确保一致性 -通过合理使用 Working Memory,Agent 可以提供更加个性化、连贯的体验! \ No newline at end of file +通过合理使用 Working Memory,Agent 可以提供更加个性化、连贯的体验! diff --git a/examples/agent/README.md b/examples/agent/README.md index 5cae199..b9bf421 100644 --- a/examples/agent/README.md +++ b/examples/agent/README.md @@ -55,12 +55,14 @@ main() ## 事件处理 ### Progress Events + - `ProgressTextChunkEvent` - 流式文本增量 - `ProgressToolStartEvent` - 工具开始执行 - `ProgressToolEndEvent` - 工具执行完成 - `ProgressDoneEvent` - 步骤完成 ### Monitor Events + - `MonitorStateChangedEvent` - Agent状态变化 - `MonitorBreakpointChangedEvent` - 断点状态变化 - `MonitorTokenUsageEvent` - Token使用统计 @@ -69,6 +71,7 @@ main() ## 工作空间 Agent 在 `./workspace` 目录下执行所有文件操作,该目录会: + - 自动创建(如果不存在) - 作为沙箱边界 - 隔离文件系统访问 diff --git a/examples/cloud-sandbox/README.md b/examples/cloud-sandbox/README.md index bb4629b..6caf9dc 100644 --- a/examples/cloud-sandbox/README.md +++ b/examples/cloud-sandbox/README.md @@ -71,29 +71,29 @@ go run main.go ### 阿里云 AgentBay -| 功能 | MCP 工具 | -|------|---------| -| 执行命令 | `shell` | -| 读取文件 | `read_file` | -| 写入文件 | `write_file` | +| 功能 | MCP 工具 | +| -------- | ---------------- | +| 执行命令 | `shell` | +| 读取文件 | `read_file` | +| 写入文件 | `write_file` | | 列出文件 | `list_directory` | -| 文件信息 | `get_file_info` | -| 删除文件 | `delete_file` | -| 搜索文件 | `search_files` | +| 文件信息 | `get_file_info` | +| 删除文件 | `delete_file` | +| 搜索文件 | `search_files` | ### 火山引擎 -| 功能 | MCP 工具 | -|------|---------| -| 初始化会话 | `computer_init` | -| 执行命令 | `computer_exec` | -| 读取文件 | `computer_read_file` | -| 写入文件 | `computer_write_file` | -| 列出文件 | `computer_list_files` | -| 文件信息 | `computer_stat_file` | -| 删除文件 | `computer_delete_file` | -| Glob 匹配 | `computer_glob` | -| 终止会话 | `computer_terminate` | +| 功能 | MCP 工具 | +| ---------- | ---------------------- | +| 初始化会话 | `computer_init` | +| 执行命令 | `computer_exec` | +| 读取文件 | `computer_read_file` | +| 写入文件 | `computer_write_file` | +| 列出文件 | `computer_list_files` | +| 文件信息 | `computer_stat_file` | +| 删除文件 | `computer_delete_file` | +| Glob 匹配 | `computer_glob` | +| 终止会话 | `computer_terminate` | ## 注意事项 diff --git a/examples/human-in-the-loop/README.md b/examples/human-in-the-loop/README.md index 0f7145c..25bd60b 100644 --- a/examples/human-in-the-loop/README.md +++ b/examples/human-in-the-loop/README.md @@ -61,16 +61,19 @@ go run main.go ## 风险评估规则 ### 低风险 (🟢) + - 读取操作:`ls`, `cat`, `grep` - 查询命令:`ps`, `top`, `df` - 无副作用的操作 ### 中风险 (🟡) + - 文件操作:`rm`, `mv`, `chmod` - 进程控制:`kill`, `pkill` - 配置文件修改 ### 高风险 (🔴) + - 批量删除:`rm -rf` - 磁盘操作:`mkfs`, `dd` - 系统路径操作:`/etc`, `/usr`, `/bin` @@ -119,7 +122,7 @@ InterruptOn: map[string]interface{}{ ApprovalHandler: func(ctx context.Context, req *middleware.ReviewRequest) ([]middleware.Decision, error) { // 1. 评估风险 risk := assessRisk(req.ActionRequests[0]) - + // 2. 根据风险决定策略 switch risk { case RiskLow: @@ -181,11 +184,11 @@ ApprovalHandler: webApprovalSystem.CreateHandler() ```go func roleBasedApprovalHandler(ctx context.Context, req *middleware.ReviewRequest) ([]middleware.Decision, error) { user := getUserFromContext(ctx) - + if hasPermission(user, req.ActionRequests[0].ToolName) { return autoApprove() } - + return requestSupervisorApproval(req) } ``` diff --git a/examples/mcp/README.md b/examples/mcp/README.md index 4da3af1..dc62f23 100644 --- a/examples/mcp/README.md +++ b/examples/mcp/README.md @@ -103,6 +103,7 @@ err := mcpManager.ConnectAll(ctx) ### 4. 使用 MCP 工具 MCP 工具会被自动注册到 Tool Registry,工具名称格式为 `{server_id}:{tool_name}`,例如: + - `my-server:calculator` - `my-server:WebSearch` - `my-server:database_query` @@ -202,6 +203,7 @@ if __name__ == '__main__': ``` 运行: + ```bash python simple_mcp_server.py ``` @@ -232,6 +234,7 @@ python simple_mcp_server.py ### MCPToolAdapter 实现 `tools.Tool` 接口: + - `Name()` - 工具名称 - `Description()` - 工具描述 - `InputSchema()` - 输入 Schema @@ -247,6 +250,7 @@ python simple_mcp_server.py ``` **解决方案:** + - 确保 MCP Server 正在运行 - 检查 `MCP_ENDPOINT` 环境变量是否正确 - 验证网络连接和防火墙设置 @@ -258,12 +262,14 @@ python simple_mcp_server.py ``` **解决方案:** + - 检查 `MCP_ACCESS_KEY` 和 `MCP_SECRET_KEY` - 确认 MCP Server 的认证配置 ### 工具未找到 如果 Agent 无法找到 MCP 工具: + 1. 检查工具是否已注册: `toolRegistry.List()` 2. 确认工具名称格式: `{server_id}:{tool_name}` 3. 查看 MCP Server 返回的工具列表: `server.ListTools()` diff --git a/examples/memory-working/README.md b/examples/memory-working/README.md index a97f709..a2300fd 100644 --- a/examples/memory-working/README.md +++ b/examples/memory-working/README.md @@ -5,6 +5,7 @@ ## Working Memory 简介 Working Memory 是一个持久化的、结构化的状态管理系统,用于: + - 跟踪当前会话状态 - 存储用户偏好和上下文 - 管理多步骤任务的进度 @@ -12,13 +13,13 @@ Working Memory 是一个持久化的、结构化的状态管理系统,用于 ### 与文本记忆的区别 -| 特性 | Working Memory | 文本记忆 | -|------|---------------|---------| -| **用途** | 会话状态管理 | 长期知识库 | -| **大小** | 小(< 500 words)| 大(无限制)| -| **更新方式** | 完全覆盖 | 追加或覆盖 | -| **自动加载** | 是 | 否 | -| **Schema 验证** | 支持 | 不支持 | +| 特性 | Working Memory | 文本记忆 | +| --------------- | ----------------- | ------------ | +| **用途** | 会话状态管理 | 长期知识库 | +| **大小** | 小(< 500 words) | 大(无限制) | +| **更新方式** | 完全覆盖 | 追加或覆盖 | +| **自动加载** | 是 | 否 | +| **Schema 验证** | 支持 | 不支持 | ## 示例内容 @@ -37,6 +38,7 @@ manager.Update(ctx, "thread-002", "resource", bobProfile) ``` **适用场景:** + - 独立的用户会话 - 不同上下文的对话 - 需要隔离状态的情况 @@ -57,6 +59,7 @@ manager.Update(ctx, "edit-002", "article-123", updatedState) ``` **适用场景:** + - 多轮协作编辑 - 团队共享的项目状态 - 长期追踪的资源 @@ -212,15 +215,15 @@ Role: Product Manager memory: working_memory: enabled: true - scope: "thread" # "thread" | "resource" + scope: "thread" # "thread" | "resource" base_path: "/working_memory/" - ttl: 0 # 过期时间(秒),0表示不过期 + ttl: 0 # 过期时间(秒),0表示不过期 # 可选:JSON Schema schema: type: object properties: - user_name: {type: string} + user_name: { type: string } task_status: type: string enum: ["not_started", "in_progress", "completed"] diff --git a/examples/model-fallback/README.md b/examples/model-fallback/README.md index df6b3ea..77ea8d2 100644 --- a/examples/model-fallback/README.md +++ b/examples/model-fallback/README.md @@ -5,23 +5,29 @@ ## 功能特性 ### 1. 自动模型降级 + 当主模型失败时,自动切换到备用模型,确保服务可用性。 ### 2. 智能重试机制 + 每个模型可以配置独立的重试次数,支持指数退避策略。 ### 3. 优先级管理 + 通过优先级控制模型的使用顺序,优先使用性能更好或成本更低的模型。 ### 4. 动态模型管理 + 运行时动态启用/禁用模型,无需重启服务。 ### 5. 统计和监控 + 实时统计模型使用情况、成功率、降级次数等指标。 ## 使用场景 ### 场景 1: 高可用性保障 + ```go fallbacks := []*agent.ModelFallback{ { @@ -44,6 +50,7 @@ fallbacks := []*agent.ModelFallback{ ``` ### 场景 2: 成本优化 + ```go fallbacks := []*agent.ModelFallback{ { @@ -66,6 +73,7 @@ fallbacks := []*agent.ModelFallback{ ``` ### 场景 3: 区域容灾 + ```go fallbacks := []*agent.ModelFallback{ { @@ -93,12 +101,12 @@ fallbacks := []*agent.ModelFallback{ ### ModelFallback 配置 -| 字段 | 类型 | 说明 | -|------|------|------| -| Config | *types.ModelConfig | 模型配置 | -| MaxRetries | int | 最大重试次数 | -| Enabled | bool | 是否启用 | -| Priority | int | 优先级(数字越小优先级越高) | +| 字段 | 类型 | 说明 | +| ---------- | ------------------- | ---------------------------- | +| Config | \*types.ModelConfig | 模型配置 | +| MaxRetries | int | 最大重试次数 | +| Enabled | bool | 是否启用 | +| Priority | int | 优先级(数字越小优先级越高) | ### 重试策略 @@ -172,15 +180,18 @@ go run main.go ## 最佳实践 ### 1. 合理配置重试次数 + - 主模型: 2-3 次重试 - 备用模型: 1-2 次重试 - 最后备用: 0-1 次重试 ### 2. 优先级设置 + - 按性能/成本/可用性综合考虑 - 定期评估和调整优先级 ### 3. 监控和告警 + ```go stats := manager.GetStats() if stats.FallbackCount > threshold { @@ -190,6 +201,7 @@ if stats.FallbackCount > threshold { ``` ### 4. 动态调整 + ```go // 根据监控指标动态调整 if modelHealth["claude"] < 0.9 { @@ -198,6 +210,7 @@ if modelHealth["claude"] < 0.9 { ``` ### 5. 错误处理 + ```go resp, err := manager.Complete(ctx, messages, opts) if err != nil { @@ -211,45 +224,54 @@ if err != nil { ## 性能考虑 ### 1. 重试开销 -- 每次重试增加 500ms * retry 的延迟 + +- 每次重试增加 500ms \* retry 的延迟 - 建议设置合理的超时时间 ### 2. 模型切换 + - 模型切换几乎无开销(已预初始化) - 建议预热所有模型的连接 ### 3. 统计开销 + - 统计信息使用原子操作,开销极小 - 可以安全地在高并发场景使用 ## 故障排查 ### 问题 1: 所有模型都失败 + ``` Error: all models failed, last error: ... ``` **解决方案**: + 1. 检查 API Keys 是否正确 2. 检查网络连接 3. 查看详细的错误日志 ### 问题 2: 频繁降级 + ``` FallbackCount: 100 ``` **解决方案**: + 1. 检查主模型的健康状态 2. 增加主模型的重试次数 3. 考虑更换主模型 ### 问题 3: 响应延迟高 + ``` Average latency: 5s ``` **解决方案**: + 1. 减少重试次数 2. 设置合理的超时时间 3. 使用更快的模型作为主模型 diff --git a/examples/openrouter/README.md b/examples/openrouter/README.md index 67b2253..496c42e 100644 --- a/examples/openrouter/README.md +++ b/examples/openrouter/README.md @@ -18,12 +18,12 @@ OpenRouter 是一个统一的 API 网关,可通过单一端点访问多个 LLM ## 命令行参数 -| 参数 | 简写 | 说明 | -|------|------|------| -| --print | -p | 非交互模式,执行指定提示词后退出 | -| --stream | -s | 启用流式模式,实时输出响应 | -| --model | -m | 指定使用的模型,默认 anthropic/claude-haiku-4.5 | -| --help | -h | 显示帮助信息 | +| 参数 | 简写 | 说明 | +| -------- | ---- | ----------------------------------------------- | +| --print | -p | 非交互模式,执行指定提示词后退出 | +| --stream | -s | 启用流式模式,实时输出响应 | +| --model | -m | 指定使用的模型,默认 anthropic/claude-haiku-4.5 | +| --help | -h | 显示帮助信息 | ## 运行方式 diff --git a/examples/plan-explore-ui/static/index.html b/examples/plan-explore-ui/static/index.html index 31a1bc5..37d8b16 100644 --- a/examples/plan-explore-ui/static/index.html +++ b/examples/plan-explore-ui/static/index.html @@ -1,4 +1,4 @@ - + @@ -164,5 +164,4 @@

AgentSDK Plan / Explore UI Demo

- - + diff --git a/examples/plan-explore-ui/static/main.js b/examples/plan-explore-ui/static/main.js index efb8048..a024463 100644 --- a/examples/plan-explore-ui/static/main.js +++ b/examples/plan-explore-ui/static/main.js @@ -160,18 +160,12 @@ case "tool:error": if (ev.payload && ev.payload.call) { uiState.textStarted = false; // 重置文本状态 - appendPhaseLine( - `[Tool Error] ${ev.payload.call.name}: ${ev.payload.error || ""}`, - "error" - ); + appendPhaseLine(`[Tool Error] ${ev.payload.call.name}: ${ev.payload.error || ""}`, "error"); } break; case "done": uiState.textStarted = false; // 重置文本状态 - appendPhaseLine( - `[Done] ${ev.payload && ev.payload.reason ? ev.payload.reason : ""}`, - "tool" - ); + appendPhaseLine(`[Done] ${ev.payload && ev.payload.reason ? ev.payload.reason : ""}`, "tool"); break; } } else if (ev.channel === "monitor") { @@ -197,8 +191,7 @@ const subType = getStringArgWeb(args, "subagent_type"); const prompt = getStringArgWeb(args, "prompt") || "子代理任务"; const labelType = subType || "Task"; - const className = - labelType === "Explore" ? "explore" : labelType === "Plan" ? "plan" : "tool"; + const className = labelType === "Explore" ? "explore" : labelType === "Plan" ? "plan" : "tool"; appendPhaseLine(`${labelType}(${prompt})`, className); uiState.currentPhase = { kind: labelType, title: prompt, count: 0 }; return; @@ -278,4 +271,3 @@ } } })(); - diff --git a/examples/ptc/README.md b/examples/ptc/README.md index 5bd9aca..88bb388 100644 --- a/examples/ptc/README.md +++ b/examples/ptc/README.md @@ -5,6 +5,7 @@ ## 前置条件 1. **Anthropic API Key** + ```bash export ANTHROPIC_API_KEY="your-api-key-here" ``` @@ -22,17 +23,20 @@ 最简单的 PTC 示例,演示如何让 LLM 生成 Python 代码并调用 Aster 工具。 **运行:** + ```bash cd basic go run main.go ``` **功能:** + - 使用 Glob 查找所有 .go 文件 - 使用 Read 读取文件内容 - 统计代码行数和字符数 **预期输出:** + ``` 正在调用 LLM 生成 Python 代码... @@ -53,12 +57,14 @@ go run main.go 演示如何使用 PTC 进行批量文件处理。 **运行:** + ```bash cd file-processor go run main.go ``` **功能:** + - 批量读取多个文件 - 数据转换和处理 - 并发执行提升性能 @@ -68,12 +74,14 @@ go run main.go 演示复杂的代码分析任务。 **运行:** + ```bash cd code-analyzer go run main.go ``` **功能:** + - 使用 Grep 搜索特定模式 - 统计代码复杂度 - 生成分析报告 @@ -147,6 +155,7 @@ toolSchemas := []provider.ToolSchema{ ``` 可选值: + - `"direct"`: LLM 直接调用 - `"code_execution_20250825"`: Python 代码中调用 @@ -187,6 +196,7 @@ log.SetFlags(log.LstdFlags | log.Lshortfile) ``` 会输出: + - HTTP 桥接服务器启动信息 - 工具调用详情 - Provider API 请求详情 @@ -211,6 +221,7 @@ curl "http://localhost:8080/tools/schema?name=Read" ### Q: 报错 "aiohttp is required" A: 安装 Python 依赖: + ```bash pip install aiohttp ``` @@ -218,11 +229,13 @@ pip install aiohttp ### Q: HTTP 桥接服务器启动失败 A: 检查端口占用: + ```bash lsof -i :8080 ``` 修改端口: + ```go codeExecTool.SetBridgeURL("http://localhost:9000") ``` @@ -230,6 +243,7 @@ codeExecTool.SetBridgeURL("http://localhost:9000") ### Q: Python 代码执行超时 A: 增加超时时间: + ```go config := &bridge.RuntimeConfig{ Timeout: 60 * time.Second, @@ -240,6 +254,7 @@ runtime := bridge.NewPythonRuntime(config) ### Q: 如何限制可调用的工具? A: 只为需要的工具设置 `AllowedCallers`: + ```go // 仅允许 Read 和 Glob 在 Python 中调用 toolSchemas := []provider.ToolSchema{ diff --git a/examples/skills/README.md b/examples/skills/README.md index 90c28b7..e512650 100644 --- a/examples/skills/README.md +++ b/examples/skills/README.md @@ -7,6 +7,7 @@ ### 1. 多模型支持 支持任何 LLM 模型,包括: + - ✅ Claude (Anthropic) - ✅ GPT-4 (OpenAI) - ✅ 通义千问 (Qwen) @@ -25,6 +26,7 @@ agent.Send(ctx, "/plan") ``` **工作流程:** + 1. 检测到 `/` 开头的消息 2. 从 `commands/` 目录加载命令定义(.md 文件) 3. 执行前置脚本(如果有) @@ -42,6 +44,7 @@ agent.Send(ctx, "帮我检查一致性问题") ``` **工作流程:** + 1. Agent 根据配置加载 `workspace/skills/**/SKILL.md`,解析其中 YAML frontmatter 2. 所有启用的 skills 只将 **元数据**(`name` + `description` + SKILL.md 路径)注入 SystemPrompt / UserMessage 3. 当模型认为某个 skill 相关时,会先用 `Read` 或 `Bash` 工具主动打开对应的 `SKILL.md` diff --git a/examples/tool-cache/README.md b/examples/tool-cache/README.md index 8e8318d..9b07c03 100644 --- a/examples/tool-cache/README.md +++ b/examples/tool-cache/README.md @@ -5,25 +5,31 @@ ## 功能特性 ### 1. 多种缓存策略 + - **内存缓存**: 最快,适合短期缓存 - **文件缓存**: 持久化,适合长期缓存 - **双层缓存**: 内存+文件,兼顾速度和持久化 ### 2. 智能缓存键生成 + 基于工具名称和输入参数自动生成唯一的缓存键。 ### 3. 灵活的 TTL 配置 + 每个缓存条目可以配置独立的过期时间。 ### 4. 自动清理机制 + 后台定期清理过期的缓存条目。 ### 5. 详细的统计信息 + 实时统计命中率、未命中率、驱逐次数等指标。 ## 使用场景 ### 场景 1: API 调用缓存 + ```go // 缓存 API 调用结果 config := &tools.CacheConfig{ @@ -37,6 +43,7 @@ cachedTool := tools.NewCachedTool(apiTool, cache) ``` ### 场景 2: 数据库查询缓存 + ```go // 缓存数据库查询结果 config := &tools.CacheConfig{ @@ -51,6 +58,7 @@ cachedTool := tools.NewCachedTool(dbQueryTool, cache) ``` ### 场景 3: 计算密集型任务缓存 + ```go // 缓存计算结果 config := &tools.CacheConfig{ @@ -68,22 +76,22 @@ cachedTool := tools.NewCachedTool(computeTool, cache) ### CacheConfig 配置 -| 字段 | 类型 | 说明 | -|------|------|------| -| Enabled | bool | 是否启用缓存 | -| Strategy | CacheStrategy | 缓存策略(memory/file/both) | -| TTL | time.Duration | 缓存过期时间 | -| CacheDir | string | 文件缓存目录 | -| MaxMemoryItems | int | 内存缓存最大条目数(0=无限制) | -| MaxFileSize | int64 | 单个缓存文件最大大小(字节) | +| 字段 | 类型 | 说明 | +| -------------- | ------------- | ------------------------------ | +| Enabled | bool | 是否启用缓存 | +| Strategy | CacheStrategy | 缓存策略(memory/file/both) | +| TTL | time.Duration | 缓存过期时间 | +| CacheDir | string | 文件缓存目录 | +| MaxMemoryItems | int | 内存缓存最大条目数(0=无限制) | +| MaxFileSize | int64 | 单个缓存文件最大大小(字节) | ### 缓存策略对比 -| 策略 | 速度 | 持久化 | 内存占用 | 适用场景 | -|------|------|--------|----------|----------| -| Memory | 极快 | ❌ | 高 | 短期、高频访问 | -| File | 快 | ✅ | 低 | 长期、大数据 | -| Both | 极快 | ✅ | 中 | 兼顾速度和持久化 | +| 策略 | 速度 | 持久化 | 内存占用 | 适用场景 | +| ------ | ---- | ------ | -------- | ---------------- | +| Memory | 极快 | ❌ | 高 | 短期、高频访问 | +| File | 快 | ✅ | 低 | 长期、大数据 | +| Both | 极快 | ✅ | 中 | 兼顾速度和持久化 | ## 运行示例 @@ -194,27 +202,28 @@ go run main.go ### 无缓存 vs 有缓存 -| 操作 | 无缓存 | 内存缓存 | 文件缓存 | 双层缓存 | -|------|--------|----------|----------|----------| -| 第一次调用 | 2000ms | 2000ms | 2000ms | 2000ms | -| 第二次调用 | 2000ms | 0.05ms | 1.2ms | 0.03ms | -| 性能提升 | 1x | 40000x | 1667x | 66667x | +| 操作 | 无缓存 | 内存缓存 | 文件缓存 | 双层缓存 | +| ---------- | ------ | -------- | -------- | -------- | +| 第一次调用 | 2000ms | 2000ms | 2000ms | 2000ms | +| 第二次调用 | 2000ms | 0.05ms | 1.2ms | 0.03ms | +| 性能提升 | 1x | 40000x | 1667x | 66667x | ### 缓存命中率影响 | 命中率 | 平均响应时间 | 性能提升 | -|--------|--------------|----------| -| 0% | 2000ms | 1x | -| 50% | 1000ms | 2x | -| 80% | 400ms | 5x | -| 95% | 100ms | 20x | -| 99% | 20ms | 100x | +| ------ | ------------ | -------- | +| 0% | 2000ms | 1x | +| 50% | 1000ms | 2x | +| 80% | 400ms | 5x | +| 95% | 100ms | 20x | +| 99% | 20ms | 100x | ## 最佳实践 ### 1. 选择合适的缓存策略 **内存缓存**: + - ✅ 高频访问的数据 - ✅ 数据量小 - ✅ 不需要持久化 @@ -222,6 +231,7 @@ go run main.go - ❌ 需要跨进程共享 **文件缓存**: + - ✅ 大数据集 - ✅ 需要持久化 - ✅ 低频访问 @@ -229,6 +239,7 @@ go run main.go - ❌ 对延迟敏感 **双层缓存**: + - ✅ 兼顾速度和持久化 - ✅ 中等数据量 - ✅ 混合访问模式 @@ -280,51 +291,61 @@ cache.Delete(key) ## 注意事项 ### 1. 缓存一致性 + - 缓存的数据可能过时 - 对实时性要求高的数据慎用缓存 - 考虑使用较短的 TTL ### 2. 内存管理 + - 设置 `MaxMemoryItems` 防止内存溢出 - 监控 `TotalSize` 指标 - 大数据优先使用文件缓存 ### 3. 并发安全 + - 缓存实现是并发安全的 - 可以在多个 goroutine 中安全使用 ### 4. 错误处理 + - 缓存失败不影响工具执行 - 缓存错误会被记录但不会抛出 ## 故障排查 ### 问题 1: 缓存未命中 + ``` Misses: 100, Hits: 0 ``` **解决方案**: + 1. 检查输入参数是否完全相同 2. 检查 TTL 是否过短 3. 检查缓存是否被清空 ### 问题 2: 内存占用过高 + ``` TotalSize: 1GB ``` **解决方案**: + 1. 设置 `MaxMemoryItems` 2. 使用文件缓存 3. 减少 TTL ### 问题 3: 文件缓存失败 + ``` Error: failed to write cache file ``` **解决方案**: + 1. 检查 `CacheDir` 权限 2. 检查磁盘空间 3. 检查 `MaxFileSize` 限制 diff --git a/pkg/asteros/README.md b/pkg/asteros/README.md index be2aada..5b546b9 100644 --- a/pkg/asteros/README.md +++ b/pkg/asteros/README.md @@ -5,18 +5,21 @@ AsterOS 是 Aster 框架的统一运行时系统,提供多智能体协作的 ## 🌟 核心特性 ### **统一资源管理** + - **Cosmos**: 智能体生命周期管理器,替代原有的 Pool 概念 - **Stars**: 多智能体协作单元,替代原有的 Room 概念 - **Workflows**: 工作流管理和执行 - **自动发现**: 自动注册和发现所有资源 ### **多接口支持** + - **HTTP Interface**: RESTful API 接口 - **A2A Interface**: Agent-to-Agent 通信接口 - **AGUI Interface**: 控制平面 UI 集成接口 - **插件化**: 支持自定义 Interface 扩展 ### **自动 API 生成** + - 为所有注册的 Agents 自动生成 REST 端点 - 为所有 Stars 自动生成协作管理 API - 为所有 Workflows 自动生成执行 API @@ -132,6 +135,7 @@ os.AddInterface(aguiIface) AsterOS 自动生成以下 REST API 端点: ### Agent 管理 + ``` GET /api/agents # 列出所有 Agent POST /api/agents/{id}/run # 运行指定 Agent @@ -139,6 +143,7 @@ GET /api/agents/{id}/status # 获取 Agent 状态 ``` ### Stars 协作 + ``` GET /api/stars # 列出所有 Stars POST /api/stars/{id}/run # 运行 Stars 协作 @@ -148,12 +153,14 @@ GET /api/stars/{id}/members # 获取成员列表 ``` ### Workflow 执行 + ``` GET /api/workflows # 列出所有 Workflow POST /api/workflows/{id}/execute # 执行 Workflow ``` ### 系统 + ``` GET /health # 健康检查 GET /metrics # Prometheus 指标 @@ -230,16 +237,19 @@ type Interface interface { ## 🌌 与 Cosmos 和 Stars 的关系 ### Cosmos (宇宙) + - **职责**: Agent 生命周期管理 - **功能**: 创建、销毁、监控 Agent - **类似**: Kubernetes 的 Pod Manager ### Stars (星座) + - **职责**: 多 Agent 协作管理 - **功能**: 编组、通信、协作调度 - **类似**: Kubernetes 的 Service/Deployment ### AsterOS (星系操作系统) + - **职责**: 统一运行时和 API 网关 - **功能**: 资源注册、API 生成、接口管理 - **类似**: Kubernetes API Server + Ingress Controller @@ -275,17 +285,21 @@ os.Router().Use(myMiddleware) ## 📊 监控和观测 ### 健康检查 + ```bash curl http://localhost:8080/health ``` ### Prometheus 指标 + ```bash curl http://localhost:8080/metrics ``` ### 日志输出 + AsterOS 使用结构化日志,支持不同级别: + ``` 🌟 AsterOS 'MyAsterOS' is running on http://localhost:8080 [Agent Create] Total tools loaded: 5 @@ -295,6 +309,7 @@ AsterOS 使用结构化日志,支持不同级别: ## 🛡️ 安全特性 ### 认证授权 + ```go // 启用认证 os, err := asteros.New(&asteros.Options{ @@ -304,6 +319,7 @@ os, err := asteros.New(&asteros.Options{ ``` ### CORS 支持 + ```go // 启用 CORS (默认已启用) os, err := asteros.New(&asteros.Options{ @@ -315,7 +331,7 @@ os, err := asteros.New(&asteros.Options{ ### 常见问题 -1. **"cosmos is required" 错误 +1. \*\*"cosmos is required" 错误 - 确保在创建 AsterOS 时提供了有效的 Cosmos 实例 2. **端口占用** @@ -327,6 +343,7 @@ os, err := asteros.New(&asteros.Options{ - 确保 Cosmos 中有足够的 Agent 容量 ### 调试模式 + ```go os, err := asteros.New(&asteros.Options{ LogLevel: "debug", // 启用详细日志 @@ -336,6 +353,7 @@ os, err := asteros.New(&asteros.Options{ ## 📚 示例项目 查看 `examples/asteros/` 目录下的完整示例: + - `basic/`: 基本 AsterOS 使用 - `interfaces/`: 多种 Interface 使用示例 - `collaboration/`: Stars 协作示例 @@ -346,4 +364,4 @@ os, err := asteros.New(&asteros.Options{ ## 📄 许可证 -本项目采用 Apache 2.0 许可证。 \ No newline at end of file +本项目采用 Apache 2.0 许可证。 diff --git a/server/README.md b/server/README.md index 037daef..b1a749b 100644 --- a/server/README.md +++ b/server/README.md @@ -35,18 +35,18 @@ import ( func main() { // 创建存储 st, _ := store.NewJSONStore(".data") - + // 创建依赖 deps := &server.Dependencies{ Store: st, } - + // 创建服务器(使用默认配置) srv, err := server.New(server.DefaultConfig(), deps) if err != nil { log.Fatal(err) } - + // 启动服务器 srv.Start() } @@ -59,7 +59,7 @@ config := &server.Config{ Host: "0.0.0.0", Port: 8080, Mode: "production", - + // 认证配置 Auth: server.AuthConfig{ APIKey: server.APIKeyConfig{ @@ -68,14 +68,14 @@ config := &server.Config{ Keys: []string{"your-secure-api-key"}, }, }, - + // CORS 配置 CORS: server.CORSConfig{ Enabled: true, AllowOrigins: []string{"https://yourdomain.com"}, AllowMethods: []string{"GET", "POST", "PUT", "DELETE"}, }, - + // 速率限制 RateLimit: server.RateLimitConfig{ Enabled: true, @@ -147,12 +147,12 @@ kubectl scale deployment agentsdk-server --replicas=5 ## 📝 环境变量 -| 变量 | 描述 | 默认值 | -|------|------|--------| -| `HOST` | 服务器监听地址 | `0.0.0.0` | -| `PORT` | 服务器端口 | `8080` | -| `MODE` | 运行模式 (`development`/`production`) | `development` | -| `API_KEY` | API 密钥 | `dev-key-12345` | +| 变量 | 描述 | 默认值 | +| --------- | ------------------------------------- | --------------- | +| `HOST` | 服务器监听地址 | `0.0.0.0` | +| `PORT` | 服务器端口 | `8080` | +| `MODE` | 运行模式 (`development`/`production`) | `development` | +| `API_KEY` | API 密钥 | `dev-key-12345` | --- @@ -183,6 +183,7 @@ curl http://localhost:8080/health ``` 响应: + ```json { "status": "healthy", @@ -427,16 +428,16 @@ Logging: server.LoggingConfig{ ## 🔄 与 cmd/agentsdk 的对比 -| 特性 | cmd/agentsdk | server/ | -|------|--------------|---------| -| **定位** | 演示/开发 | 生产部署 | -| **认证** | ❌ | ✅ API Key + JWT | -| **速率限制** | ❌ | ✅ | -| **CORS** | 基础 | 完整配置 | -| **日志** | 简单 | 结构化 | -| **监控** | ❌ | ✅ Health + Metrics | -| **部署** | 手动 | Docker + K8s | -| **生产就绪** | ❌ | ✅ | +| 特性 | cmd/agentsdk | server/ | +| ------------ | ------------ | ------------------- | +| **定位** | 演示/开发 | 生产部署 | +| **认证** | ❌ | ✅ API Key + JWT | +| **速率限制** | ❌ | ✅ | +| **CORS** | 基础 | 完整配置 | +| **日志** | 简单 | 结构化 | +| **监控** | ❌ | ✅ Health + Metrics | +| **部署** | 手动 | Docker + K8s | +| **生产就绪** | ❌ | ✅ | --- diff --git a/server/deploy/docker/docker-compose.yml b/server/deploy/docker/docker-compose.yml index 8aadc26..3d80d6c 100644 --- a/server/deploy/docker/docker-compose.yml +++ b/server/deploy/docker/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.8' +version: "3.8" services: aster-server: diff --git a/server/deploy/k8s/deployment.yaml b/server/deploy/k8s/deployment.yaml index 9eb5e04..9c18de9 100644 --- a/server/deploy/k8s/deployment.yaml +++ b/server/deploy/k8s/deployment.yaml @@ -18,60 +18,60 @@ spec: component: server spec: containers: - - name: aster-server - image: aster/server:latest - imagePullPolicy: Always - ports: - - name: http - containerPort: 8080 - protocol: TCP - - name: metrics - containerPort: 9090 - protocol: TCP - env: - - name: HOST - value: "0.0.0.0" - - name: PORT - value: "8080" - - name: MODE - value: "production" - - name: API_KEY - valueFrom: - secretKeyRef: - name: aster-secrets - key: api-key - resources: - requests: - memory: "256Mi" - cpu: "250m" - limits: - memory: "512Mi" - cpu: "500m" - livenessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 15 - periodSeconds: 20 - timeoutSeconds: 3 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 3 - successThreshold: 1 - failureThreshold: 3 - volumeMounts: - - name: data - mountPath: /app/.data + - name: aster-server + image: aster/server:latest + imagePullPolicy: Always + ports: + - name: http + containerPort: 8080 + protocol: TCP + - name: metrics + containerPort: 9090 + protocol: TCP + env: + - name: HOST + value: "0.0.0.0" + - name: PORT + value: "8080" + - name: MODE + value: "production" + - name: API_KEY + valueFrom: + secretKeyRef: + name: aster-secrets + key: api-key + resources: + requests: + memory: "256Mi" + cpu: "250m" + limits: + memory: "512Mi" + cpu: "500m" + livenessProbe: + httpGet: + path: /health + port: http + initialDelaySeconds: 15 + periodSeconds: 20 + timeoutSeconds: 3 + successThreshold: 1 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: http + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 3 + successThreshold: 1 + failureThreshold: 3 + volumeMounts: + - name: data + mountPath: /app/.data volumes: - - name: data - persistentVolumeClaim: - claimName: aster-data + - name: data + persistentVolumeClaim: + claimName: aster-data --- apiVersion: v1 kind: PersistentVolumeClaim diff --git a/server/deploy/k8s/service.yaml b/server/deploy/k8s/service.yaml index 7b1efbe..dd4e555 100644 --- a/server/deploy/k8s/service.yaml +++ b/server/deploy/k8s/service.yaml @@ -8,14 +8,14 @@ metadata: spec: type: ClusterIP ports: - - name: http - port: 80 - targetPort: http - protocol: TCP - - name: metrics - port: 9090 - targetPort: metrics - protocol: TCP + - name: http + port: 80 + targetPort: http + protocol: TCP + - name: metrics + port: 9090 + targetPort: metrics + protocol: TCP selector: app: aster component: server @@ -30,10 +30,10 @@ metadata: spec: type: LoadBalancer ports: - - name: http - port: 80 - targetPort: http - protocol: TCP + - name: http + port: 80 + targetPort: http + protocol: TCP selector: app: aster component: server diff --git a/ui/README.md b/ui/README.md index d81aa33..12408a4 100644 --- a/ui/README.md +++ b/ui/README.md @@ -9,7 +9,7 @@ Aster Agent UI 是一个专门为 AI Agent 应用设计的组件库,提供了 ## ✨ 核心特性 - 🤖 **67 个组件** - 包含 46 个 ChatUI 组件 + 21 个 Agent 专属组件 -- 💬 **对话界面** - 完整的 Agent 对话体验 +- 💬 **对话界面** - 完整的 Agent 对话体验 - 🔄 **工作流** - Agent 工作流可视化 - 👥 **多 Agent** - 支持多 Agent 协作 - 🧠 **思考过程** - Agent 推理过程可视化 @@ -21,7 +21,7 @@ Aster Agent UI 是一个专门为 AI Agent 应用设计的组件库,提供了 ### 前提条件 -- Node.js 16+ +- Node.js 16+ - Go 1.21+(如果需要运行后端) ### 1. 启动后端服务器 @@ -74,6 +74,7 @@ npm run build ## 📦 组件分类 ### 🤖 Agent 组件 + - **AgentCard** - Agent 信息卡片 - **AgentDashboard** - Agent 管理仪表板 - **AgentChatSession** - Agent 对话会话 @@ -81,19 +82,23 @@ npm run build - **WorkflowTimeline** - 工作流时间线(含快捷操作) ### 📁 项目组件 + - **ProjectCard** - 项目信息卡片 - **ProjectList** - 项目列表(含筛选) ### ✏️ 编辑器组件 + - **EditorPanel** - Markdown 编辑器(含预览) ### 💬 对话组件 + - **Chat** - 聊天容器 - **Bubble** - 消息气泡 - **MultimodalInput** - 多模态输入 - **MessageStatus** - 消息状态 ### 🎨 基础组件 + - **Button** - 按钮 - **Avatar** - 头像 - **Icon** - 图标 @@ -102,6 +107,7 @@ npm run build ## 📖 文档资源 ### 🚀 快速开始 + - [状态更新](./STATUS_UPDATE.md) - 最新状态和问题解决 🆕 - [配置指南](./SETUP_GUIDE.md) - 完整的环境配置和启动说明 ⭐ - [快速测试](./QUICK_TEST.md) - 验证系统是否正常工作 ⭐ @@ -109,11 +115,13 @@ npm run build - [故障排除](./TROUBLESHOOTING.md) - 常见问题解决方案 ### 📚 学习资源 + - [完整使用示例](./COMPLETE_EXAMPLE.md) - 构建 AI 写作助手 - [组件文档](./src/docs/README.md) - 完整的组件 API - [ChatUI 组件指南](./CHATUI_GUIDE.md) - 对话组件使用 ### 📊 项目状态 + - [最终完成报告](./FINAL_REPORT.md) - 项目总览和成就 🎉 - [开发进度报告](./PROGRESS_REPORT.md) - 87.5% 完成 - [实现总结](./IMPLEMENTATION_SUMMARY.md) - 技术细节 @@ -123,7 +131,7 @@ npm run build ```vue diff --git a/ui/eslint.config.js b/ui/eslint.config.js index 6872994..bc8d70c 100644 --- a/ui/eslint.config.js +++ b/ui/eslint.config.js @@ -1,4 +1,4 @@ -import antfu from '@antfu/eslint-config'; +import antfu from "@antfu/eslint-config"; export default antfu({ // 启用 Vue 支持 @@ -15,32 +15,27 @@ export default antfu({ }, // 忽略的文件 - ignores: [ - 'dist', - 'node_modules', - '*.min.js', - 'coverage', - ], + ignores: ["dist", "node_modules", "*.min.js", "coverage"], // 自定义规则 rules: { // Vue 相关 - 'vue/block-order': ['error', { order: ['template', 'script', 'style'] }], - 'vue/define-macros-order': ['error', { order: ['defineProps', 'defineEmits'] }], - 'vue/no-unused-refs': 'warn', + "vue/block-order": ["error", { order: ["template", "script", "style"] }], + "vue/define-macros-order": ["error", { order: ["defineProps", "defineEmits"] }], + "vue/no-unused-refs": "warn", // TypeScript 相关 - 'ts/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], - 'ts/consistent-type-imports': ['error', { prefer: 'type-imports' }], + "ts/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }], + "ts/consistent-type-imports": ["error", { prefer: "type-imports" }], // 通用规则 - 'no-console': ['warn', { allow: ['warn', 'error'] }], - 'curly': ['error', 'multi-line'], - 'antfu/if-newline': 'off', + "no-console": ["warn", { allow: ["warn", "error"] }], + curly: ["error", "multi-line"], + "antfu/if-newline": "off", // 样式规则 - 'style/semi': ['error', 'always'], - 'style/quotes': ['error', 'single'], - 'style/comma-dangle': ['error', 'always-multiline'], + "style/semi": ["error", "always"], + "style/quotes": ["error", "single"], + "style/comma-dangle": ["error", "always-multiline"], }, }); diff --git a/ui/index.html b/ui/index.html index 6a4141f..d2365c1 100644 --- a/ui/index.html +++ b/ui/index.html @@ -1,12 +1,12 @@ - + - - - - AsterUI - Universal AI Agent Interface - - -
- - + + + + AsterUI - Universal AI Agent Interface + + +
+ + diff --git a/ui/postcss.config.js b/ui/postcss.config.js index 2e7af2b..2aa7205 100644 --- a/ui/postcss.config.js +++ b/ui/postcss.config.js @@ -3,4 +3,4 @@ export default { tailwindcss: {}, autoprefixer: {}, }, -} +}; diff --git a/ui/src/__tests__/composables/useDarkMode.spec.ts b/ui/src/__tests__/composables/useDarkMode.spec.ts index 86d4809..31da364 100644 --- a/ui/src/__tests__/composables/useDarkMode.spec.ts +++ b/ui/src/__tests__/composables/useDarkMode.spec.ts @@ -1,15 +1,15 @@ -import { describe, expect, it, vi } from 'vitest'; -import { useDarkMode } from '@/composables/useDarkMode'; +import { describe, expect, it, vi } from "vitest"; +import { useDarkMode } from "@/composables/useDarkMode"; -describe('useDarkMode', () => { - it('should initialize with auto theme', () => { +describe("useDarkMode", () => { + it("should initialize with auto theme", () => { const { theme, isDark } = useDarkMode(); - expect(theme.value).toBe('auto'); - expect(typeof isDark.value).toBe('boolean'); + expect(theme.value).toBe("auto"); + expect(typeof isDark.value).toBe("boolean"); }); - it('should toggle theme', () => { + it("should toggle theme", () => { const { isDark, toggleTheme } = useDarkMode(); const initialDark = isDark.value; @@ -18,15 +18,15 @@ describe('useDarkMode', () => { expect(isDark.value).toBe(!initialDark); }); - it('should set specific theme', () => { + it("should set specific theme", () => { const { theme, isDark, setTheme } = useDarkMode(); - setTheme('dark'); - expect(theme.value).toBe('dark'); + setTheme("dark"); + expect(theme.value).toBe("dark"); expect(isDark.value).toBe(true); - setTheme('light'); - expect(theme.value).toBe('light'); + setTheme("light"); + expect(theme.value).toBe("light"); expect(isDark.value).toBe(false); }); }); diff --git a/ui/src/__tests__/utils/format.spec.ts b/ui/src/__tests__/utils/format.spec.ts index 9bd9b7d..f1d1efd 100644 --- a/ui/src/__tests__/utils/format.spec.ts +++ b/ui/src/__tests__/utils/format.spec.ts @@ -1,32 +1,32 @@ -import { describe, expect, it } from 'vitest'; -import { formatFileSize, formatTime, truncate } from '@/utils/format'; +import { describe, expect, it } from "vitest"; +import { formatFileSize, formatTime, truncate } from "@/utils/format"; -describe('format utils', () => { - describe('truncate', () => { - it('should return original string if shorter than max length', () => { - expect(truncate('hello', 10)).toBe('hello'); +describe("format utils", () => { + describe("truncate", () => { + it("should return original string if shorter than max length", () => { + expect(truncate("hello", 10)).toBe("hello"); }); - it('should truncate string and add ellipsis', () => { - expect(truncate('hello world', 8)).toBe('hello...'); + it("should truncate string and add ellipsis", () => { + expect(truncate("hello world", 8)).toBe("hello..."); }); - it('should handle empty string', () => { - expect(truncate('', 10)).toBe(''); + it("should handle empty string", () => { + expect(truncate("", 10)).toBe(""); }); }); - describe('formatFileSize', () => { - it('should format bytes', () => { - expect(formatFileSize(500)).toBe('500.00 B'); + describe("formatFileSize", () => { + it("should format bytes", () => { + expect(formatFileSize(500)).toBe("500.00 B"); }); - it('should format kilobytes', () => { - expect(formatFileSize(1024)).toBe('1.00 KB'); + it("should format kilobytes", () => { + expect(formatFileSize(1024)).toBe("1.00 KB"); }); - it('should format megabytes', () => { - expect(formatFileSize(1024 * 1024)).toBe('1.00 MB'); + it("should format megabytes", () => { + expect(formatFileSize(1024 * 1024)).toBe("1.00 MB"); }); }); }); diff --git a/ui/src/components/Agent/AgentCard.vue b/ui/src/components/Agent/AgentCard.vue index a81c8dd..75def7d 100644 --- a/ui/src/components/Agent/AgentCard.vue +++ b/ui/src/components/Agent/AgentCard.vue @@ -6,7 +6,12 @@
- +
@@ -26,11 +31,7 @@
- - -
@@ -70,31 +58,19 @@
@@ -119,23 +95,14 @@
- +
-
+
@@ -156,34 +123,16 @@
- - - -
@@ -199,12 +148,12 @@
CPU: - {{ process.cpuUsage || 'N/A' }}% + {{ process.cpuUsage || "N/A" }}%
内存: - {{ process.memoryUsage || 'N/A' }} + {{ process.memoryUsage || "N/A" }}
@@ -214,56 +163,29 @@
-
+
进程输出 {{ process.output.length }} 行
- - - -
-
-
+
+
{{ formatTimestamp(line.timestamp) }} @@ -279,9 +201,7 @@

暂无后台任务

-

- 没有运行中的后台进程,所有进程都已正常完成 -

+

没有运行中的后台进程,所有进程都已正常完成

@@ -323,22 +237,14 @@

{{ selectedProcess.command }}

-
-
+
{{ formatTimestamp(line.timestamp) }} @@ -351,13 +257,13 @@ \ No newline at end of file + diff --git a/ui/src/components/Tools/ExploreTool.vue b/ui/src/components/Tools/ExploreTool.vue index 657484b..df629af 100644 --- a/ui/src/components/Tools/ExploreTool.vue +++ b/ui/src/components/Tools/ExploreTool.vue @@ -7,34 +7,16 @@ 文件浏览器
- - - -
@@ -43,36 +25,19 @@
- - @@ -88,29 +53,20 @@ -
{{ sortedItems.length }} 项 - - 已选择 {{ selectedItems.length }} 项 - + 已选择 {{ selectedItems.length }} 项
-
+
@@ -130,26 +86,18 @@ 'file-item', { 'directory-item': item.isDirectory, - 'file-selected': selectedItems.includes(item.path) - } + 'file-selected': selectedItems.includes(item.path), + }, ]" @click="handleItemClick(item)" @contextmenu.prevent="showContextMenu(item, $event)" >
- +
- +
@@ -158,14 +106,12 @@ {{ getFileExtension(item.name) }} - - {{ item.children?.length || 0 }} 项 - + {{ item.children?.length || 0 }} 项
- {{ item.isDirectory ? '-' : formatFileSize(item.size) }} + {{ item.isDirectory ? "-" : formatFileSize(item.size) }}
@@ -173,34 +119,16 @@
- - - -
@@ -220,31 +148,16 @@ 总大小: {{ formatTotalSize() }}
- - +
-
+
复制 @@ -258,11 +171,7 @@ 粘贴
-
+
重命名
@@ -284,18 +193,10 @@ - @@ -96,31 +66,17 @@
@@ -158,12 +114,8 @@
{{ process.name }} - - PID: {{ process.pid }} - - - PPID: {{ process.ppid }} - + PID: {{ process.pid }} + PPID: {{ process.ppid }} {{ process.user }} @@ -186,7 +138,7 @@ - 端口: {{ process.ports.join(', ') }} + 端口: {{ process.ports.join(", ") }}
@@ -198,11 +150,7 @@
- + + +
- +
系统负载
-
{{ systemInfo.loadAverage || 'N/A' }}
+
{{ systemInfo.loadAverage || "N/A" }}
内存使用
-
{{ systemInfo.memoryUsage || 'N/A' }}
+
{{ systemInfo.memoryUsage || "N/A" }}
CPU 使用
-
{{ systemInfo.cpuUsage || 'N/A' }}
+
{{ systemInfo.cpuUsage || "N/A" }}
运行时间
-
{{ systemInfo.uptime || 'N/A' }}
+
{{ systemInfo.uptime || "N/A" }}
@@ -307,10 +234,7 @@

进程详情 - {{ selectedProcess.name }} ({{ selectedProcess.pid }})

-
父进程ID
-
{{ selectedProcess.ppid || 'N/A' }}
+
{{ selectedProcess.ppid || "N/A" }}
用户
-
{{ selectedProcess.user || 'N/A' }}
+
{{ selectedProcess.user || "N/A" }}
状态
@@ -345,18 +269,18 @@
启动时间
-
{{ selectedProcess.startTime || 'N/A' }}
+
{{ selectedProcess.startTime || "N/A" }}
运行时长
-
{{ selectedProcess.duration || 'N/A' }}
+
{{ selectedProcess.duration || "N/A" }}
命令行
- {{ selectedProcess.command || 'N/A' }} + {{ selectedProcess.command || "N/A" }}
@@ -390,19 +314,8 @@
- - + +
@@ -433,24 +346,27 @@
-
-
+
@@ -466,403 +382,399 @@ \ No newline at end of file + diff --git a/ui/src/components/Tools/PlanTool.vue b/ui/src/components/Tools/PlanTool.vue index 44a31e9..7d16211 100644 --- a/ui/src/components/Tools/PlanTool.vue +++ b/ui/src/components/Tools/PlanTool.vue @@ -7,25 +7,13 @@ 计划管理
- - -
@@ -34,21 +22,8 @@
- - + +
- - + + @@ -89,13 +57,8 @@
- @@ -106,11 +69,14 @@
@@ -130,26 +96,13 @@
- - -
@@ -166,10 +119,13 @@
{{ index + 1 }}
@@ -199,12 +155,8 @@