diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..cb77662 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,172 @@ +# AGENTS.md - Engineering and Agent Governance for ACI + +This file defines mandatory engineering rules for this repository. + +Applies to: +- Human contributors +- AI coding agents + +## 1. Purpose and Scope + +This document is the single governance contract for: +- Requirements +- Design +- Programming +- Testing +- CI/CD +- Git workflow +- AI safety constraints +- AI commit discipline + +If a change conflicts with this document, this document takes precedence unless a maintainer explicitly overrides it in the task context. + +## 2. Roles and Audience + +- Humans MUST follow these standards when planning, coding, testing, and reviewing. +- AI agents MUST follow these standards when proposing, editing, validating, and reporting changes. + +## 3. Requirement Engineering Standards + +- Every non-trivial task MUST define: + - Objective + - In-scope + - Out-of-scope + - Acceptance criteria +- Bugfixes MUST include: + - Reproducible symptom + - Expected behavior +- If acceptance criteria are undefined, implementation MUST NOT start. + +## 4. Design Standards + +- Non-trivial changes MUST include a brief design rationale in PR/task notes. +- Design rationale MUST state: + - Selected approach + - Alternatives considered + - Tradeoffs +- Layering MUST be respected: + - `core`: domain logic and cross-cutting primitives + - `infrastructure`: external systems and adapters + - `services`: orchestration and business workflows + - `cli` / `http` / `mcp`: entrypoint adapters only + +## 5. Programming Standards + +- New code MUST include type annotations. +- Error handling and logs MUST preserve root causes and actionable context. +- Security-sensitive data MUST NOT be hardcoded or logged. +- Changes SHOULD minimize diff surface; avoid opportunistic refactors. +- Existing repository conventions MUST be preserved unless the task explicitly requests a redesign. + +## 6. Testing Standards + +- Logic changes MUST include tests appropriate to the change: + - Unit tests + - Property tests + - Integration tests +- Flaky or non-deterministic tests MUST NOT be merged. +- Minimum local validation before PR: + - `uv run ruff check src tests` + - `uv run pytest tests/ -v --tb=short -q --durations=10` +- Type checking SHOULD be run and reviewed: + - `uv run mypy src --ignore-missing-imports --no-error-summary` + +## 7. CI/CD Standards + +- CI source of truth: + - `.github/workflows/test.yml` + - `.github/workflows/release.yml` +- Required CI commands are: + - `uv run ruff check src tests` + - `uv run pytest tests/ -v --tb=short -q --durations=10` +- Current mypy execution in CI is informational/non-blocking: + - `uv run mypy src --ignore-missing-imports --no-error-summary || true` +- Release tags MUST follow `v*`. +- A release is marked prerelease when tag name contains `-`. +- PRs MUST NOT merge with failing required checks. + +## 8. Git Workflow and PR Standards + +- Workflow MUST be Trunk-based development + PR. +- Commit messages MUST follow Conventional Commits with scope: + - `type(scope): short imperative summary` +- Allowed types: + - `feat`, `fix`, `refactor`, `test`, `docs`, `chore`, `ci`, `perf` +- Branch naming SHOULD use: + - `feat/` + - `fix/` + - `chore/` + - `docs/` +- Every PR MUST include: + - What changed + - Why + - Test evidence (commands + outcomes) + - Risk/rollback notes for non-trivial changes + +## 9. AI Safety and Dangerous-Command Policy + +### 9.1 Strict Blocking Rules + +AI MUST NOT run destructive or high-risk commands. + +Default prohibited patterns: +- `rm -rf` +- `del /s /q` +- `format` +- `mkfs` +- `dd` +- shutdown/reboot commands +- recursive permission/ownership changes outside task scope +- `git reset --hard` +- `git clean -fdx` +- `git checkout -- .` +- force push to protected branches + +### 9.2 Additional Safety Constraints + +- AI MUST NOT modify files outside repository task scope without explicit user instruction. +- AI MUST explicitly call out risk before any potentially destructive operation. +- AI MUST prefer reversible operations. +- AI MUST preserve unrelated local changes. + +## 10. AI Commit Discipline and Commit Message Standard + +### 10.1 Milestone-Based Commit Discipline + +- AI MUST commit at each verifiable milestone, not only at final completion. +- A milestone is: + - A complete logical subtask + - With relevant checks passing + - With coherent rollback boundaries +- AI MUST avoid oversized mixed-purpose commits. +- AI SHOULD keep one intent per commit. + +### 10.2 AI Commit Message Template + +Header (required): +- `type(scope): short imperative summary` + +Body (required): +- `Why:` context/problem +- `What:` key changes +- `Test:` commands executed and outcomes + +Optional footer: +- `BREAKING CHANGE:` when applicable + +Example: +- `fix(indexing): retry qdrant upsert on transient timeout` + +## 11. Definition of Done (DoD) Checklist + +Before marking work complete, ALL applicable items MUST be satisfied: + +- Requirements are explicit and testable +- Design rationale is captured for non-trivial changes +- Code is scoped and consistent with project architecture +- Tests are added/updated and passing +- Lint checks are passing +- CI/CD impact is considered +- Documentation is updated when behavior changes +- Commit/PR metadata follows policy + diff --git a/README.md b/README.md index f797550..1aaf422 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Project ACI - Augmented Codebase Indexer Language: **English** | [简体中文](doc/README.zh-CN.md) +Development governance: see [AGENTS.md](AGENTS.md) A Python tool for semantic code search with precise line-level location results. diff --git a/doc/CHUNKING_ALGORITHM.zh-CN.md b/doc/CHUNKING_ALGORITHM.zh-CN.md new file mode 100644 index 0000000..ff8dc4a --- /dev/null +++ b/doc/CHUNKING_ALGORITHM.zh-CN.md @@ -0,0 +1,109 @@ +# Chunking 算法原理(当前实现) + +本文基于 `src/aci/core/chunker` 的当前代码实现,说明 ACI 在索引阶段如何把源码切分为可检索片段(chunks)。 + +## 1. 总体流程 + +`Chunker.chunk(file, ast_nodes)` 的主流程: + +1. 先按语言抽取 import 列表(写入每个 chunk 的 metadata)。 +2. 若存在 AST 节点:走 **语义切分(AST-based)**。 +3. 若无 AST 节点:走 **固定行数切分(fixed-size fallback)**。 +4. 若配置了 `summary_generator`,并行产出 function/class/file summary artifact。 + +## 2. AST 语义切分(优先路径) + +当解析器能产出 AST 节点时: + +- 每个 AST 节点(`function/class/method`)默认作为一个 chunk 候选。 +- metadata 会补充结构化信息: + - `function_name` + - `class_name` + - `parent_class`(method 场景) + - `imports`、`file_hash`、`language` +- 若节点有 docstring,会先规范化,再以分隔符拼到 chunk 内容前缀,提高语义可检索性。 + +### Token 上限控制 + +对每个候选节点: + +- `token_count <= max_tokens`:直接生成单个 chunk。 +- `token_count > max_tokens`:交给 `SmartChunkSplitter` 做智能拆分。 + +## 3. SmartChunkSplitter 智能拆分策略 + +目标:在 token 约束下尽量不破坏代码语法/语义边界。 + +### 3.1 拆分优先级 + +在一个超大节点内部,优先在这些位置切分: + +1. 空行 +2. 语句边界(`def/class/if/for/while/try/except/return/...` 模式) +3. 缩进较低的行(块边界) +4. 实在不行按可容纳最大范围切 + +### 3.2 如何找“可容纳最大范围” + +- 通过二分法 `_find_max_end_index` 找从 `start_idx` 开始,token 不超限的最远 `end_idx`。 +- 再在 `[start_idx, end_idx]` 区间回溯挑“最佳切点”。 + +### 3.3 上下文补偿 + +拆分后会给后续子块加上下文前缀,避免脱离语境: + +- 方法:`# Context: class ` +- 函数:`# Context: function ` +- 类:`# Context: class ` + +此外: + +- docstring 前缀只附加在首个子块。 +- metadata 里标记 `is_partial / part_index / total_parts` 等字段。 + +## 4. 固定行数切分(fallback) + +当某语言暂不支持 AST(或 AST 为空)时: + +- 以 `fixed_chunk_lines`(默认 50 行)分块。 +- 相邻块保留 `overlap_lines`(默认 5 行)重叠,降低跨块语义断裂。 +- 每块仍会做 token 校验;若超限,持续从块尾减行直到不超限(至少保留 1 行)。 +- chunk 类型标记为 `fixed`。 + +## 5. Import 抽取策略 + +chunking 前会先提取 import,并写入 metadata: + +- Python:识别 `import ...` / `from ...` +- JS/TS:识别 `import ...` 和 `const ... require(...)` +- Go:支持 `import (...)` 块和单行 import +- 其他语言:空实现(返回空列表) + +这让检索和后续总结模型可利用依赖上下文。 + +## 6. 输出数据形态 + +最终 `ChunkingResult` 包含两类产物: + +- `chunks: list[CodeChunk]` +- `summaries: list[SummaryArtifact]` + +其中 `CodeChunk` 是索引主对象,带有: + +- 行号范围(1-based,含结束行) +- 原始/拆分后的内容 +- chunk 类型(`function/class/method/fixed`) +- metadata(含 imports、符号名、分片标记等) + +## 7. 设计取舍总结 + +当前算法是“**语义优先 + token 兜底 + 行切分回退**”的混合方案: + +- 优点: + - 尽量对齐语言结构(函数/类/方法),检索粒度更自然。 + - 超大节点可智能拆分,并保留上下文,降低语义损失。 + - 对不支持 AST 的语言仍可工作(工程可用性高)。 +- 潜在限制: + - 语句边界模式目前偏 Python 风格正则,对其他语言并非完全精确。 + - 固定切分路径主要靠行数和重叠,语义一致性弱于 AST 路径。 + diff --git a/scripts/start-http.ps1 b/scripts/start-http.ps1 new file mode 100644 index 0000000..ccb7123 --- /dev/null +++ b/scripts/start-http.ps1 @@ -0,0 +1,134 @@ +#Requires -Version 5.1 +<# +.SYNOPSIS + 自动配置 ACI 环境并启动 HTTP 服务器 (FastAPI / uvicorn) + +.DESCRIPTION + 1. 检查并安装 uv 包管理器 + 2. 检查 .env 配置文件(不存在则从 .env.example 复制并提示填写) + 3. 验证必填环境变量 + 4. 执行 uv sync 同步依赖 + 5. 启动 ACI HTTP 服务器 + +.PARAMETER Host + 监听地址,默认 0.0.0.0 + +.PARAMETER Port + 监听端口,默认 8000 + +.EXAMPLE + .\scripts\start-http.ps1 + .\scripts\start-http.ps1 -Port 9000 +#> +param( + [string]$HostAddr = "", + [int]$Port = 0 +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +# ---------- 路径 ---------- +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$ProjectRoot = Split-Path -Parent $ScriptDir +Set-Location $ProjectRoot + +# ---------- 颜色辅助函数 ---------- +function Write-Info { param($Msg) Write-Host "[ACI] $Msg" -ForegroundColor Cyan } +function Write-Success { param($Msg) Write-Host "[ACI] $Msg" -ForegroundColor Green } +function Write-Warn { param($Msg) Write-Host "[ACI] $Msg" -ForegroundColor Yellow } +function Write-Err { param($Msg) Write-Host "[ACI] $Msg" -ForegroundColor Red } + +Write-Host "" +Write-Host "================================================" -ForegroundColor Cyan +Write-Host " ACI — HTTP 服务器启动脚本" -ForegroundColor Cyan +Write-Host "================================================" -ForegroundColor Cyan +Write-Host "" + +# ---------- 检查 uv ---------- +$uvCmd = Get-Command uv -ErrorAction SilentlyContinue +if (-not $uvCmd) { + Write-Warn "未检测到 uv,正在安装..." + try { + Invoke-RestMethod https://astral.sh/uv/install.ps1 | Invoke-Expression + # 刷新 PATH + $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "User") + ";" + $env:PATH + $uvCmd = Get-Command uv -ErrorAction SilentlyContinue + if (-not $uvCmd) { throw "安装后仍未找到 uv" } + Write-Success "uv 安装成功" + } catch { + Write-Err "uv 安装失败: $_" + Write-Err "请手动安装: https://docs.astral.sh/uv/" + exit 1 + } +} else { + Write-Info "uv 已就绪: $(uv --version)" +} + +# ---------- 检查 .env ---------- +if (-not (Test-Path ".env")) { + Write-Warn ".env 文件不存在,从 .env.example 复制..." + if (Test-Path ".env.example") { + Copy-Item ".env.example" ".env" + Write-Host "" + Write-Warn "==========================================================" + Write-Warn " 请编辑 .env 文件,填写以下必填项后重新运行本脚本:" + Write-Warn " - ACI_EMBEDDING_API_URL" + Write-Warn " - ACI_EMBEDDING_API_KEY" + Write-Warn " - ACI_EMBEDDING_MODEL" + Write-Warn "==========================================================" + Write-Host "" + # 尝试用记事本打开 .env + Start-Process notepad.exe -ArgumentList (Resolve-Path ".env").Path -Wait + } else { + Write-Err ".env.example 不存在,请手动创建 .env 文件" + exit 1 + } +} else { + Write-Info ".env 已存在" +} + +# ---------- 加载 .env 并验证必填项 ---------- +$envContent = Get-Content ".env" -ErrorAction SilentlyContinue +$envVars = @{} +foreach ($line in $envContent) { + if ($line -match '^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$') { + $envVars[$Matches[1]] = $Matches[2].Trim('"').Trim("'") + } +} + +$missing = @() +if (-not $envVars["ACI_EMBEDDING_API_KEY"] -or $envVars["ACI_EMBEDDING_API_KEY"] -eq "your_embedding_api_key") { + $missing += "ACI_EMBEDDING_API_KEY" +} +if (-not $envVars["ACI_EMBEDDING_API_URL"]) { + $missing += "ACI_EMBEDDING_API_URL" +} +if ($missing.Count -gt 0) { + Write-Err "以下环境变量未配置: $($missing -join ', ')" + Write-Err "请编辑 .env 文件后重试" + exit 1 +} + +# ---------- 确定 host / port ---------- +if (-not $HostAddr) { + $HostAddr = if ($envVars["ACI_SERVER_HOST"]) { $envVars["ACI_SERVER_HOST"] } else { "0.0.0.0" } +} +if ($Port -eq 0) { + $Port = if ($envVars["ACI_SERVER_PORT"]) { [int]$envVars["ACI_SERVER_PORT"] } else { 8000 } +} + +# ---------- 同步依赖 ---------- +Write-Info "同步依赖(uv sync)..." +uv sync --quiet +if ($LASTEXITCODE -ne 0) { Write-Err "依赖同步失败"; exit 1 } +Write-Success "依赖同步完成" + +# ---------- 启动 HTTP 服务器 ---------- +Write-Host "" +Write-Success "启动 ACI HTTP 服务器 → http://${HostAddr}:${Port}" +Write-Info "API 文档: http://${HostAddr}:${Port}/docs" +Write-Info "按 Ctrl+C 停止服务" +Write-Host "" + +uv run aci serve --host $HostAddr --port $Port diff --git a/scripts/start-http.sh b/scripts/start-http.sh new file mode 100644 index 0000000..5e4399f --- /dev/null +++ b/scripts/start-http.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash +# start-http.sh — 自动配置环境并启动 ACI HTTP 服务器 (FastAPI / uvicorn) +# 用法:bash scripts/start-http.sh [--host HOST] [--port PORT] +set -euo pipefail + +# ---------- 路径 ---------- +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +cd "$PROJECT_ROOT" + +# ---------- 颜色输出 ---------- +RED='\033[0;31m'; YELLOW='\033[1;33m'; GREEN='\033[0;32m'; CYAN='\033[0;36m'; NC='\033[0m' +info() { echo -e "${CYAN}[ACI]${NC} $*"; } +success() { echo -e "${GREEN}[ACI]${NC} $*"; } +warn() { echo -e "${YELLOW}[ACI]${NC} $*"; } +error() { echo -e "${RED}[ACI]${NC} $*" >&2; } + +# ---------- 参数默认值 ---------- +HOST="${ACI_SERVER_HOST:-0.0.0.0}" +PORT="${ACI_SERVER_PORT:-8000}" + +# 解析命令行参数 +while [[ $# -gt 0 ]]; do + case $1 in + --host) HOST="$2"; shift 2 ;; + --port) PORT="$2"; shift 2 ;; + *) warn "未知参数 '$1',已忽略"; shift ;; + esac +done + +echo "" +echo -e "${CYAN}================================================${NC}" +echo -e "${CYAN} ACI — HTTP 服务器启动脚本${NC}" +echo -e "${CYAN}================================================${NC}" +echo "" + +# ---------- 检查 uv ---------- +if ! command -v uv &>/dev/null; then + warn "未检测到 uv,正在安装..." + curl -LsSf https://astral.sh/uv/install.sh | sh + export PATH="$HOME/.cargo/bin:$PATH" + if ! command -v uv &>/dev/null; then + error "uv 安装失败,请手动安装: https://docs.astral.sh/uv/" + exit 1 + fi + success "uv 安装成功" +else + info "uv 已就绪: $(uv --version)" +fi + +# ---------- 检查 .env ---------- +if [[ ! -f ".env" ]]; then + warn ".env 文件不存在,从 .env.example 复制..." + if [[ -f ".env.example" ]]; then + cp ".env.example" ".env" + echo "" + warn "==========================================================" + warn " 请编辑 .env 文件,填写以下必填项后重新运行本脚本:" + warn " - ACI_EMBEDDING_API_URL" + warn " - ACI_EMBEDDING_API_KEY" + warn " - ACI_EMBEDDING_MODEL" + warn "==========================================================" + echo "" + read -rp "已打开 .env,配置完成后按 [Enter] 继续,或 Ctrl+C 退出..." _ + else + error ".env.example 不存在,请手动创建 .env 文件" + exit 1 + fi +else + info ".env 已存在" +fi + +# ---------- 检查必填环境变量 ---------- +# shellcheck source=/dev/null +set -a; source ".env"; set +a +MISSING=() +[[ -z "${ACI_EMBEDDING_API_KEY:-}" || "${ACI_EMBEDDING_API_KEY}" == "your_embedding_api_key" ]] && MISSING+=("ACI_EMBEDDING_API_KEY") +[[ -z "${ACI_EMBEDDING_API_URL:-}" ]] && MISSING+=("ACI_EMBEDDING_API_URL") +if [[ ${#MISSING[@]} -gt 0 ]]; then + error "以下环境变量未配置: ${MISSING[*]}" + error "请编辑 .env 文件后重试" + exit 1 +fi + +# ---------- 同步依赖 ---------- +info "同步依赖(uv sync)..." +uv sync --quiet +success "依赖同步完成" + +# ---------- 启动 HTTP 服务器 ---------- +echo "" +success "启动 ACI HTTP 服务器 → http://${HOST}:${PORT}" +info "API 文档: http://${HOST}:${PORT}/docs" +info "按 Ctrl+C 停止服务" +echo "" +exec uv run aci serve --host "$HOST" --port "$PORT" diff --git a/scripts/start-mcp.ps1 b/scripts/start-mcp.ps1 new file mode 100644 index 0000000..ddb41f6 --- /dev/null +++ b/scripts/start-mcp.ps1 @@ -0,0 +1,129 @@ +#Requires -Version 5.1 +<# +.SYNOPSIS + 自动配置 ACI 环境并启动 MCP 服务器(供 LLM 客户端接入) + +.DESCRIPTION + 1. 检查并安装 uv 包管理器 + 2. 检查 .env 配置文件(不存在则从 .env.example 复制并提示填写) + 3. 验证必填环境变量 + 4. 执行 uv sync 同步依赖 + 5. 打印 MCP 客户端配置示例 + 6. 启动 ACI MCP 服务器(stdio 传输) + +.EXAMPLE + .\scripts\start-mcp.ps1 +#> +param() + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +# ---------- 路径 ---------- +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$ProjectRoot = Split-Path -Parent $ScriptDir +Set-Location $ProjectRoot + +# ---------- 颜色辅助函数 ---------- +function Write-Info { param($Msg) Write-Host "[ACI] $Msg" -ForegroundColor Cyan } +function Write-Success { param($Msg) Write-Host "[ACI] $Msg" -ForegroundColor Green } +function Write-Warn { param($Msg) Write-Host "[ACI] $Msg" -ForegroundColor Yellow } +function Write-Err { param($Msg) Write-Host "[ACI] $Msg" -ForegroundColor Red } + +Write-Host "" +Write-Host "================================================" -ForegroundColor Cyan +Write-Host " ACI — MCP 服务器启动脚本" -ForegroundColor Cyan +Write-Host "================================================" -ForegroundColor Cyan +Write-Host "" + +# ---------- 检查 uv ---------- +$uvCmd = Get-Command uv -ErrorAction SilentlyContinue +if (-not $uvCmd) { + Write-Warn "未检测到 uv,正在安装..." + try { + Invoke-RestMethod https://astral.sh/uv/install.ps1 | Invoke-Expression + $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "User") + ";" + $env:PATH + $uvCmd = Get-Command uv -ErrorAction SilentlyContinue + if (-not $uvCmd) { throw "安装后仍未找到 uv" } + Write-Success "uv 安装成功" + } catch { + Write-Err "uv 安装失败: $_" + Write-Err "请手动安装: https://docs.astral.sh/uv/" + exit 1 + } +} else { + Write-Info "uv 已就绪: $(uv --version)" +} + +# ---------- 检查 .env ---------- +if (-not (Test-Path ".env")) { + Write-Warn ".env 文件不存在,从 .env.example 复制..." + if (Test-Path ".env.example") { + Copy-Item ".env.example" ".env" + Write-Host "" + Write-Warn "==========================================================" + Write-Warn " 请编辑 .env 文件,填写以下必填项后重新运行本脚本:" + Write-Warn " - ACI_EMBEDDING_API_URL" + Write-Warn " - ACI_EMBEDDING_API_KEY" + Write-Warn " - ACI_EMBEDDING_MODEL" + Write-Warn "==========================================================" + Write-Host "" + Start-Process notepad.exe -ArgumentList (Resolve-Path ".env").Path -Wait + } else { + Write-Err ".env.example 不存在,请手动创建 .env 文件" + exit 1 + } +} else { + Write-Info ".env 已存在" +} + +# ---------- 加载 .env 并验证必填项 ---------- +$envContent = Get-Content ".env" -ErrorAction SilentlyContinue +$envVars = @{} +foreach ($line in $envContent) { + if ($line -match '^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$') { + $envVars[$Matches[1]] = $Matches[2].Trim('"').Trim("'") + } +} + +$missing = @() +if (-not $envVars["ACI_EMBEDDING_API_KEY"] -or $envVars["ACI_EMBEDDING_API_KEY"] -eq "your_embedding_api_key") { + $missing += "ACI_EMBEDDING_API_KEY" +} +if (-not $envVars["ACI_EMBEDDING_API_URL"]) { + $missing += "ACI_EMBEDDING_API_URL" +} +if ($missing.Count -gt 0) { + Write-Err "以下环境变量未配置: $($missing -join ', ')" + Write-Err "请编辑 .env 文件后重试" + exit 1 +} + +# ---------- 同步依赖 ---------- +Write-Info "同步依赖(uv sync)..." +uv sync --quiet +if ($LASTEXITCODE -ne 0) { Write-Err "依赖同步失败"; exit 1 } +Write-Success "依赖同步完成" + +# ---------- 打印 MCP 客户端配置示例 ---------- +Write-Host "" +Write-Info "MCP 客户端配置参考(粘贴到 Kiro / Claude Desktop / Cursor 等 MCP 客户端):" +Write-Host @" +{ + "mcpServers": { + "aci": { + "command": "uv", + "args": ["run", "aci-mcp"], + "cwd": "$($ProjectRoot.Replace('\','\\'))" + } + } +} +"@ -ForegroundColor DarkGray +Write-Host "" + +# ---------- 启动 MCP 服务器 ---------- +Write-Success "启动 ACI MCP 服务器(stdio 传输模式)..." +Write-Info "按 Ctrl+C 停止服务" +Write-Host "" + +uv run aci-mcp diff --git a/scripts/start-mcp.sh b/scripts/start-mcp.sh new file mode 100644 index 0000000..22d54ca --- /dev/null +++ b/scripts/start-mcp.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +# start-mcp.sh — 自动配置环境并启动 ACI MCP 服务器(供 LLM 客户端接入) +# 用法:bash scripts/start-mcp.sh +set -euo pipefail + +# ---------- 路径 ---------- +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +cd "$PROJECT_ROOT" + +# ---------- 颜色输出 ---------- +RED='\033[0;31m'; YELLOW='\033[1;33m'; GREEN='\033[0;32m'; CYAN='\033[0;36m'; NC='\033[0m' +info() { echo -e "${CYAN}[ACI]${NC} $*"; } +success() { echo -e "${GREEN}[ACI]${NC} $*"; } +warn() { echo -e "${YELLOW}[ACI]${NC} $*"; } +error() { echo -e "${RED}[ACI]${NC} $*" >&2; } + +echo "" +echo -e "${CYAN}================================================${NC}" +echo -e "${CYAN} ACI — MCP 服务器启动脚本${NC}" +echo -e "${CYAN}================================================${NC}" +echo "" + +# ---------- 检查 uv ---------- +if ! command -v uv &>/dev/null; then + warn "未检测到 uv,正在安装..." + curl -LsSf https://astral.sh/uv/install.sh | sh + export PATH="$HOME/.cargo/bin:$PATH" + if ! command -v uv &>/dev/null; then + error "uv 安装失败,请手动安装: https://docs.astral.sh/uv/" + exit 1 + fi + success "uv 安装成功" +else + info "uv 已就绪: $(uv --version)" +fi + +# ---------- 检查 .env ---------- +if [[ ! -f ".env" ]]; then + warn ".env 文件不存在,从 .env.example 复制..." + if [[ -f ".env.example" ]]; then + cp ".env.example" ".env" + echo "" + warn "==========================================================" + warn " 请编辑 .env 文件,填写以下必填项后重新运行本脚本:" + warn " - ACI_EMBEDDING_API_URL" + warn " - ACI_EMBEDDING_API_KEY" + warn " - ACI_EMBEDDING_MODEL" + warn "==========================================================" + echo "" + read -rp "配置完成后按 [Enter] 继续,或 Ctrl+C 退出..." _ + else + error ".env.example 不存在,请手动创建 .env 文件" + exit 1 + fi +else + info ".env 已存在" +fi + +# ---------- 检查必填环境变量 ---------- +# shellcheck source=/dev/null +set -a; source ".env"; set +a +MISSING=() +[[ -z "${ACI_EMBEDDING_API_KEY:-}" || "${ACI_EMBEDDING_API_KEY}" == "your_embedding_api_key" ]] && MISSING+=("ACI_EMBEDDING_API_KEY") +[[ -z "${ACI_EMBEDDING_API_URL:-}" ]] && MISSING+=("ACI_EMBEDDING_API_URL") +if [[ ${#MISSING[@]} -gt 0 ]]; then + error "以下环境变量未配置: ${MISSING[*]}" + error "请编辑 .env 文件后重试" + exit 1 +fi + +# ---------- 同步依赖 ---------- +info "同步依赖(uv sync)..." +uv sync --quiet +success "依赖同步完成" + +# ---------- 打印 MCP 客户端配置示例 ---------- +echo "" +info "MCP 客户端配置参考(JSON):" +cat < +param() + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +# ---------- 路径 ---------- +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$ProjectRoot = Split-Path -Parent $ScriptDir +Set-Location $ProjectRoot + +# ---------- 颜色辅助函数 ---------- +function Write-Info { param($Msg) Write-Host "[ACI] $Msg" -ForegroundColor Cyan } +function Write-Success { param($Msg) Write-Host "[ACI] $Msg" -ForegroundColor Green } +function Write-Warn { param($Msg) Write-Host "[ACI] $Msg" -ForegroundColor Yellow } +function Write-Err { param($Msg) Write-Host "[ACI] $Msg" -ForegroundColor Red } + +Write-Host "" +Write-Host "================================================" -ForegroundColor Cyan +Write-Host " ACI — 交互式 REPL 启动脚本" -ForegroundColor Cyan +Write-Host "================================================" -ForegroundColor Cyan +Write-Host "" + +# ---------- 检查 uv ---------- +$uvCmd = Get-Command uv -ErrorAction SilentlyContinue +if (-not $uvCmd) { + Write-Warn "未检测到 uv,正在安装..." + try { + Invoke-RestMethod https://astral.sh/uv/install.ps1 | Invoke-Expression + $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "User") + ";" + $env:PATH + $uvCmd = Get-Command uv -ErrorAction SilentlyContinue + if (-not $uvCmd) { throw "安装后仍未找到 uv" } + Write-Success "uv 安装成功" + } catch { + Write-Err "uv 安装失败: $_" + Write-Err "请手动安装: https://docs.astral.sh/uv/" + exit 1 + } +} else { + Write-Info "uv 已就绪: $(uv --version)" +} + +# ---------- 检查 .env ---------- +if (-not (Test-Path ".env")) { + Write-Warn ".env 文件不存在,从 .env.example 复制..." + if (Test-Path ".env.example") { + Copy-Item ".env.example" ".env" + Write-Host "" + Write-Warn "==========================================================" + Write-Warn " 请编辑 .env 文件,填写以下必填项后重新运行本脚本:" + Write-Warn " - ACI_EMBEDDING_API_URL" + Write-Warn " - ACI_EMBEDDING_API_KEY" + Write-Warn " - ACI_EMBEDDING_MODEL" + Write-Warn "==========================================================" + Write-Host "" + Start-Process notepad.exe -ArgumentList (Resolve-Path ".env").Path -Wait + } else { + Write-Err ".env.example 不存在,请手动创建 .env 文件" + exit 1 + } +} else { + Write-Info ".env 已存在" +} + +# ---------- 加载 .env 并验证必填项 ---------- +$envContent = Get-Content ".env" -ErrorAction SilentlyContinue +$envVars = @{} +foreach ($line in $envContent) { + if ($line -match '^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$') { + $envVars[$Matches[1]] = $Matches[2].Trim('"').Trim("'") + } +} + +$missing = @() +if (-not $envVars["ACI_EMBEDDING_API_KEY"] -or $envVars["ACI_EMBEDDING_API_KEY"] -eq "your_embedding_api_key") { + $missing += "ACI_EMBEDDING_API_KEY" +} +if (-not $envVars["ACI_EMBEDDING_API_URL"]) { + $missing += "ACI_EMBEDDING_API_URL" +} +if ($missing.Count -gt 0) { + Write-Err "以下环境变量未配置: $($missing -join ', ')" + Write-Err "请编辑 .env 文件后重试" + exit 1 +} + +# ---------- 同步依赖 ---------- +Write-Info "同步依赖(uv sync)..." +uv sync --quiet +if ($LASTEXITCODE -ne 0) { Write-Err "依赖同步失败"; exit 1 } +Write-Success "依赖同步完成" + +# ---------- 打印 REPL 命令提示 ---------- +Write-Host "" +Write-Info "REPL 常用命令:" +Write-Host " index " -NoNewline; Write-Host "— 索引目录" -ForegroundColor DarkGray +Write-Host " search " -NoNewline; Write-Host "— 语义搜索" -ForegroundColor DarkGray +Write-Host " status " -NoNewline; Write-Host "— 查看索引状态" -ForegroundColor DarkGray +Write-Host " update " -NoNewline; Write-Host "— 增量更新索引" -ForegroundColor DarkGray +Write-Host " reset " -NoNewline; Write-Host "— 清空索引" -ForegroundColor DarkGray +Write-Host " help / ? " -NoNewline; Write-Host "— 查看帮助" -ForegroundColor DarkGray +Write-Host " exit / q " -NoNewline; Write-Host "— 退出" -ForegroundColor DarkGray +Write-Host "" + +# ---------- 启动 REPL ---------- +Write-Success "进入 ACI 交互式 Shell..." +Write-Host "" + +uv run aci shell diff --git a/scripts/start-repl.sh b/scripts/start-repl.sh new file mode 100644 index 0000000..07f3493 --- /dev/null +++ b/scripts/start-repl.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +# start-repl.sh — 自动配置环境并启动 ACI 交互式 REPL(shell 模式) +# 用法:bash scripts/start-repl.sh +set -euo pipefail + +# ---------- 路径 ---------- +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +cd "$PROJECT_ROOT" + +# ---------- 颜色输出 ---------- +RED='\033[0;31m'; YELLOW='\033[1;33m'; GREEN='\033[0;32m'; CYAN='\033[0;36m'; NC='\033[0m' +info() { echo -e "${CYAN}[ACI]${NC} $*"; } +success() { echo -e "${GREEN}[ACI]${NC} $*"; } +warn() { echo -e "${YELLOW}[ACI]${NC} $*"; } +error() { echo -e "${RED}[ACI]${NC} $*" >&2; } + +echo "" +echo -e "${CYAN}================================================${NC}" +echo -e "${CYAN} ACI — 交互式 REPL 启动脚本${NC}" +echo -e "${CYAN}================================================${NC}" +echo "" + +# ---------- 检查 uv ---------- +if ! command -v uv &>/dev/null; then + warn "未检测到 uv,正在安装..." + curl -LsSf https://astral.sh/uv/install.sh | sh + export PATH="$HOME/.cargo/bin:$PATH" + if ! command -v uv &>/dev/null; then + error "uv 安装失败,请手动安装: https://docs.astral.sh/uv/" + exit 1 + fi + success "uv 安装成功" +else + info "uv 已就绪: $(uv --version)" +fi + +# ---------- 检查 .env ---------- +if [[ ! -f ".env" ]]; then + warn ".env 文件不存在,从 .env.example 复制..." + if [[ -f ".env.example" ]]; then + cp ".env.example" ".env" + echo "" + warn "==========================================================" + warn " 请编辑 .env 文件,填写以下必填项后重新运行本脚本:" + warn " - ACI_EMBEDDING_API_URL" + warn " - ACI_EMBEDDING_API_KEY" + warn " - ACI_EMBEDDING_MODEL" + warn "==========================================================" + echo "" + read -rp "配置完成后按 [Enter] 继续,或 Ctrl+C 退出..." _ + else + error ".env.example 不存在,请手动创建 .env 文件" + exit 1 + fi +else + info ".env 已存在" +fi + +# ---------- 检查必填环境变量 ---------- +# shellcheck source=/dev/null +set -a; source ".env"; set +a +MISSING=() +[[ -z "${ACI_EMBEDDING_API_KEY:-}" || "${ACI_EMBEDDING_API_KEY}" == "your_embedding_api_key" ]] && MISSING+=("ACI_EMBEDDING_API_KEY") +[[ -z "${ACI_EMBEDDING_API_URL:-}" ]] && MISSING+=("ACI_EMBEDDING_API_URL") +if [[ ${#MISSING[@]} -gt 0 ]]; then + error "以下环境变量未配置: ${MISSING[*]}" + error "请编辑 .env 文件后重试" + exit 1 +fi + +# ---------- 同步依赖 ---------- +info "同步依赖(uv sync)..." +uv sync --quiet +success "依赖同步完成" + +# ---------- 提示 ---------- +echo "" +info "REPL 常用命令:" +info " index — 索引目录" +info " search — 语义搜索" +info " status — 查看索引状态" +info " update — 增量更新索引" +info " reset — 清空索引" +info " help / ? — 查看帮助" +info " exit / q — 退出" +echo "" + +# ---------- 启动 REPL ---------- +success "进入 ACI 交互式 Shell..." +echo "" +exec uv run aci shell