claxcode 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claxcode-0.1.1/.env.example +11 -0
- claxcode-0.1.1/.github/workflows/publish.yml +43 -0
- claxcode-0.1.1/.gitignore +31 -0
- claxcode-0.1.1/AGENTS.md +282 -0
- claxcode-0.1.1/CLAUDE.md +24 -0
- claxcode-0.1.1/LICENSE +201 -0
- claxcode-0.1.1/PKG-INFO +359 -0
- claxcode-0.1.1/README.md +327 -0
- claxcode-0.1.1/claxcode/__init__.py +3 -0
- claxcode-0.1.1/claxcode/api/__init__.py +1 -0
- claxcode-0.1.1/claxcode/api/chat.py +51 -0
- claxcode-0.1.1/claxcode/api/session.py +66 -0
- claxcode-0.1.1/claxcode/api/subagents.py +82 -0
- claxcode-0.1.1/claxcode/api/tools.py +38 -0
- claxcode-0.1.1/claxcode/cli.py +1214 -0
- claxcode-0.1.1/claxcode/cli_completion.py +174 -0
- claxcode-0.1.1/claxcode/config.py +54 -0
- claxcode-0.1.1/claxcode/core/__init__.py +1 -0
- claxcode-0.1.1/claxcode/core/agent.py +327 -0
- claxcode-0.1.1/claxcode/core/checkpoint.py +100 -0
- claxcode-0.1.1/claxcode/core/context.py +114 -0
- claxcode-0.1.1/claxcode/core/models.py +446 -0
- claxcode-0.1.1/claxcode/extensions/__init__.py +1 -0
- claxcode-0.1.1/claxcode/extensions/hooks.py +131 -0
- claxcode-0.1.1/claxcode/extensions/mcp.py +13 -0
- claxcode-0.1.1/claxcode/extensions/plugins.py +10 -0
- claxcode-0.1.1/claxcode/extensions/skills.py +205 -0
- claxcode-0.1.1/claxcode/main.py +55 -0
- claxcode-0.1.1/claxcode/memory/__init__.py +23 -0
- claxcode-0.1.1/claxcode/memory/auto_memory.py +68 -0
- claxcode-0.1.1/claxcode/memory/long_term.py +196 -0
- claxcode-0.1.1/claxcode/memory/project_context.py +20 -0
- claxcode-0.1.1/claxcode/memory/project_memory.py +194 -0
- claxcode-0.1.1/claxcode/memory/session_store.py +206 -0
- claxcode-0.1.1/claxcode/models/__init__.py +1 -0
- claxcode-0.1.1/claxcode/models/session.py +25 -0
- claxcode-0.1.1/claxcode/models/subagent.py +25 -0
- claxcode-0.1.1/claxcode/models/tool.py +24 -0
- claxcode-0.1.1/claxcode/security/__init__.py +1 -0
- claxcode-0.1.1/claxcode/security/audit.py +54 -0
- claxcode-0.1.1/claxcode/security/permissions.py +29 -0
- claxcode-0.1.1/claxcode/skills/bug-fix/SKILL.md +33 -0
- claxcode-0.1.1/claxcode/skills/code-review/SKILL.md +35 -0
- claxcode-0.1.1/claxcode/skills/python-refactor/SKILL.md +22 -0
- claxcode-0.1.1/claxcode/skills/task-workflow/SKILL.md +38 -0
- claxcode-0.1.1/claxcode/subagents/__init__.py +1 -0
- claxcode-0.1.1/claxcode/subagents/base.py +108 -0
- claxcode-0.1.1/claxcode/subagents/executor.py +16 -0
- claxcode-0.1.1/claxcode/subagents/explore.py +25 -0
- claxcode-0.1.1/claxcode/subagents/planner.py +25 -0
- claxcode-0.1.1/claxcode/tools/__init__.py +14 -0
- claxcode-0.1.1/claxcode/tools/admin.py +170 -0
- claxcode-0.1.1/claxcode/tools/base.py +19 -0
- claxcode-0.1.1/claxcode/tools/browser.py +499 -0
- claxcode-0.1.1/claxcode/tools/code_intelligence.py +68 -0
- claxcode-0.1.1/claxcode/tools/custom_example.py +76 -0
- claxcode-0.1.1/claxcode/tools/execution.py +114 -0
- claxcode-0.1.1/claxcode/tools/file_operations.py +287 -0
- claxcode-0.1.1/claxcode/tools/memory_tool.py +29 -0
- claxcode-0.1.1/claxcode/tools/registry.py +35 -0
- claxcode-0.1.1/claxcode/tools/search.py +157 -0
- claxcode-0.1.1/claxcode/tools/ssh.py +534 -0
- claxcode-0.1.1/claxcode/tools/web.py +83 -0
- claxcode-0.1.1/pyproject.toml +65 -0
- claxcode-0.1.1/tests/__init__.py +1 -0
- claxcode-0.1.1/tests/conftest.py +16 -0
- claxcode-0.1.1/tests/test_api/test_health.py +10 -0
- claxcode-0.1.1/tests/test_api/test_session.py +22 -0
- claxcode-0.1.1/tests/test_api/test_tools_api.py +26 -0
- claxcode-0.1.1/tests/test_core/test_agent_hooks.py +59 -0
- claxcode-0.1.1/tests/test_core/test_agent_memory.py +65 -0
- claxcode-0.1.1/tests/test_core/test_agent_permissions.py +170 -0
- claxcode-0.1.1/tests/test_core/test_checkpoint_rollback.py +71 -0
- claxcode-0.1.1/tests/test_core/test_cli_commands.py +453 -0
- claxcode-0.1.1/tests/test_core/test_cli_completion.py +131 -0
- claxcode-0.1.1/tests/test_core/test_cli_env.py +47 -0
- claxcode-0.1.1/tests/test_core/test_context.py +94 -0
- claxcode-0.1.1/tests/test_core/test_models.py +84 -0
- claxcode-0.1.1/tests/test_core/test_subagent_store.py +42 -0
- claxcode-0.1.1/tests/test_extensions/__init__.py +1 -0
- claxcode-0.1.1/tests/test_extensions/test_hooks.py +67 -0
- claxcode-0.1.1/tests/test_extensions/test_skill_tools.py +101 -0
- claxcode-0.1.1/tests/test_extensions/test_skills.py +65 -0
- claxcode-0.1.1/tests/test_extensions/test_skills_loading.py +88 -0
- claxcode-0.1.1/tests/test_memory/__init__.py +0 -0
- claxcode-0.1.1/tests/test_memory/test_auto_memory.py +45 -0
- claxcode-0.1.1/tests/test_memory/test_long_term.py +104 -0
- claxcode-0.1.1/tests/test_memory/test_project_memory.py +13 -0
- claxcode-0.1.1/tests/test_memory/test_session_messages.py +30 -0
- claxcode-0.1.1/tests/test_security/__init__.py +1 -0
- claxcode-0.1.1/tests/test_security/test_audit.py +44 -0
- claxcode-0.1.1/tests/test_security/test_permissions.py +47 -0
- claxcode-0.1.1/tests/test_tools/test_admin.py +81 -0
- claxcode-0.1.1/tests/test_tools/test_browser.py +120 -0
- claxcode-0.1.1/tests/test_tools/test_calculate.py +30 -0
- claxcode-0.1.1/tests/test_tools/test_execution.py +42 -0
- claxcode-0.1.1/tests/test_tools/test_file_operations.py +187 -0
- claxcode-0.1.1/tests/test_tools/test_memory_tool.py +15 -0
- claxcode-0.1.1/tests/test_tools/test_registry.py +35 -0
- claxcode-0.1.1/tests/test_tools/test_search.py +59 -0
- claxcode-0.1.1/tests/test_tools/test_ssh_execute.py +119 -0
- claxcode-0.1.1/tests/test_tools/test_web_tools.py +50 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
LLM_PROVIDER=openai
|
|
2
|
+
LLM_API_KEY=your-api-key-here
|
|
3
|
+
LLM_BASE_URL=
|
|
4
|
+
LLM_MODEL=gpt-4o
|
|
5
|
+
LLM_TEMPERATURE=0.2
|
|
6
|
+
LLM_MAX_TOKENS=4096
|
|
7
|
+
# JSON config for custom/ollama providers
|
|
8
|
+
LLM_CUSTOM_CONFIG={}
|
|
9
|
+
|
|
10
|
+
DATABASE_URL=sqlite+aiosqlite:///./.claxcode/claxcode.db
|
|
11
|
+
PERMISSION_MODE=ask
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
environment:
|
|
16
|
+
name: pypi
|
|
17
|
+
url: https://pypi.org/project/claxcode/
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
id-token: write
|
|
21
|
+
steps:
|
|
22
|
+
- name: Check out repository
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: Set up Python
|
|
26
|
+
uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.11"
|
|
29
|
+
|
|
30
|
+
- name: Install build and test tools
|
|
31
|
+
run: python -m pip install -e ".[dev]" build twine
|
|
32
|
+
|
|
33
|
+
- name: Run tests
|
|
34
|
+
run: python -m pytest -q
|
|
35
|
+
|
|
36
|
+
- name: Build distributions
|
|
37
|
+
run: python -m build
|
|
38
|
+
|
|
39
|
+
- name: Check distributions
|
|
40
|
+
run: python -m twine check dist/*
|
|
41
|
+
|
|
42
|
+
- name: Publish to PyPI
|
|
43
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Secrets — never commit real keys
|
|
2
|
+
.env
|
|
3
|
+
.env.*
|
|
4
|
+
!.env.example
|
|
5
|
+
|
|
6
|
+
# Python
|
|
7
|
+
__pycache__/
|
|
8
|
+
*.py[cod]
|
|
9
|
+
*.egg-info/
|
|
10
|
+
.venv/
|
|
11
|
+
build/
|
|
12
|
+
dist/
|
|
13
|
+
|
|
14
|
+
# Tool caches
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
.mypy_cache/
|
|
18
|
+
|
|
19
|
+
# IDE
|
|
20
|
+
.idea/
|
|
21
|
+
.vscode/
|
|
22
|
+
|
|
23
|
+
# ClaxCode runtime state (DB, snapshots, audit log)
|
|
24
|
+
.claxcode/
|
|
25
|
+
|
|
26
|
+
# Backups and stray logs
|
|
27
|
+
*.bak
|
|
28
|
+
|
|
29
|
+
# OS
|
|
30
|
+
.DS_Store
|
|
31
|
+
Thumbs.db
|
claxcode-0.1.1/AGENTS.md
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# AGENTS.md — ClaxCode
|
|
2
|
+
|
|
3
|
+
本文面向首次接触本仓库的 AI 编程代理,说明当前实现、开发命令和修改约定。阅读代码时以实际实现为准;`README.md` 是主要的人类可读说明,本文侧重开发与架构细节。
|
|
4
|
+
|
|
5
|
+
## 项目概览
|
|
6
|
+
|
|
7
|
+
ClaxCode 是一个用 Python 编写的开源、自托管 Agentic 编程助手,灵感来自 Claude Code。两个前端共享同一套 Agent、LLM Provider、工具、权限和记忆系统:
|
|
8
|
+
|
|
9
|
+
- **交互式 CLI**(`claxcode-cli`):REPL 终端助手,也支持 `--print/-P` 单发模式。斜杠命令集中定义在 `claxcode/cli.py` 的 `_build_commands()` 中,`/help` 由该表生成。
|
|
10
|
+
- **HTTP API**(`claxcode`):FastAPI 应用,通过 SSE 流式返回聊天事件。
|
|
11
|
+
|
|
12
|
+
核心循环位于 `claxcode/core/agent.py`:收集上下文 → 流式调用 LLM → 执行工具 → 发出验证标记并进入下一轮。每条用户消息最多迭代 10 次;没有工具调用时结束。主 Agent 会把系统提示、项目上下文、Skills、自动记忆、项目记忆及相关长期记忆组合进上下文。
|
|
13
|
+
|
|
14
|
+
当前版本**不支持图片/视觉输入**;CLI 的 `@path` 会跳过常见图片扩展名。
|
|
15
|
+
|
|
16
|
+
## 技术栈与关键配置
|
|
17
|
+
|
|
18
|
+
- Python **>= 3.11**;`pyproject.toml` 使用 **hatchling** 构建 wheel,包名为 `claxcode`,版本为 `0.1.0`。
|
|
19
|
+
- **FastAPI + Uvicorn**:HTTP API 与 SSE(`StreamingResponse`)。
|
|
20
|
+
- **Pydantic v2 + pydantic-settings**:配置和 API 数据模型。
|
|
21
|
+
- **SQLAlchemy 2.0 异步 API + aiosqlite**:默认使用本地 SQLite。
|
|
22
|
+
- **httpx**:OpenAI 兼容、Ollama、自定义 HTTP Provider 以及 Web 工具的 HTTP 请求;OpenAI Provider 不依赖 `openai` SDK。
|
|
23
|
+
- **prompt-toolkit**:CLI 的 `@` 文件模糊补全和 `/` 命令补全。
|
|
24
|
+
- **paramiko**:SSH 工具。
|
|
25
|
+
- **Playwright**:可选浏览器工具,延迟导入,通过 `browser` extra 安装。
|
|
26
|
+
- **pytest + pytest-asyncio + pytest-httpx**:测试;**ruff** 和 **mypy**:静态检查。
|
|
27
|
+
|
|
28
|
+
关键文件:
|
|
29
|
+
|
|
30
|
+
| 文件/目录 | 作用 |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `pyproject.toml` | 构建、依赖、console scripts、pytest、ruff、mypy 的唯一主要配置 |
|
|
33
|
+
| `.env.example` | 最小环境变量模板;复制为 `.env` 后填写 Provider 和密钥 |
|
|
34
|
+
| `claxcode/config.py` | 全部环境驱动设置;`.env` 中未知变量会被忽略 |
|
|
35
|
+
| `README.md` | 中文使用说明、功能介绍和示例 |
|
|
36
|
+
| `CLAUDE.md` | 注入 Agent 的项目上下文;当前是 `/init` 生成的基本模板 |
|
|
37
|
+
| `.claxcode/` | 本地运行时状态:数据库、快照、审计日志、CLI 会话指针等,不应提交 |
|
|
38
|
+
|
|
39
|
+
仓库没有 `package.json`、锁文件、Makefile 或 Dockerfile。`.github/workflows/publish.yml` 提供 PyPI 发布 CI:推送 `v*` 标签或手动触发,运行测试和构建后通过 OIDC 发布,使用 GitHub 环境 `pypi`。
|
|
40
|
+
|
|
41
|
+
## 安装、构建与运行
|
|
42
|
+
|
|
43
|
+
在仓库根目录执行。 editable 安装不需要单独的构建步骤。
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
python -m venv .venv
|
|
47
|
+
# Windows cmd / PowerShell:
|
|
48
|
+
.\.venv\Scripts\activate
|
|
49
|
+
# Unix shells:
|
|
50
|
+
source .venv/bin/activate
|
|
51
|
+
|
|
52
|
+
pip install -e ".[dev]"
|
|
53
|
+
cp .env.example .env # 然后编辑 .env
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
可选依赖:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install -e ".[anthropic]" # AnthropicProvider 需要 anthropic SDK
|
|
60
|
+
pip install -e ".[browser]" # 浏览器工具需要 Playwright;还需可用的 Chromium
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`pyproject.toml` 也声明了 `openai` extra,但当前 OpenAI/OpenAI 兼容 Provider 直接使用 httpx,不导入该 SDK。
|
|
64
|
+
|
|
65
|
+
启动方式:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# FastAPI 服务,默认 http://127.0.0.1:8000;GET /health 返回纯文本 ok
|
|
69
|
+
claxcode
|
|
70
|
+
# 等价:python -m claxcode.main
|
|
71
|
+
|
|
72
|
+
# 交互式 CLI
|
|
73
|
+
claxcode-cli --project . --mode ask
|
|
74
|
+
# 等价:python -m claxcode.cli --project . --mode ask
|
|
75
|
+
|
|
76
|
+
# 非交互单发模式;正文走 stdout,工具事件走 stderr
|
|
77
|
+
claxcode-cli --print "总结这个项目的结构"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`claxcode` 和 `claxcode-cli` 分别映射到 `claxcode.main:run`、`claxcode.cli:main`。Uvicorn 的 host、port 和 reload 由环境设置控制。
|
|
81
|
+
|
|
82
|
+
## 运行时架构
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
CLI / FastAPI API
|
|
86
|
+
│
|
|
87
|
+
▼
|
|
88
|
+
Agent(上下文组装、最多 10 轮循环)
|
|
89
|
+
├── LLMProvider(流式文本与工具调用)
|
|
90
|
+
├── ToolRegistry(内置及 Skill 工具)
|
|
91
|
+
│ └── 权限 → PreToolUse → 写前快照 → 工具 → PostToolUse → 审计
|
|
92
|
+
└── ContextManager(历史恢复、估算、压缩)
|
|
93
|
+
│
|
|
94
|
+
▼
|
|
95
|
+
SQLite 会话/子代理/长期记忆/项目记忆 + 本地 JSON 自动记忆
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### CLI 行为
|
|
99
|
+
|
|
100
|
+
- `!cmd`:直接调用 `run_shell`,Ctrl+C 会终止子进程并返回提示;`@path` 或 `@"带 空格的路径"`:把项目内 UTF-8 文本文件内容(最多 8000 字符)附加到提示,重复引用只内联一次,加载失败会在 stderr 给出原因;`#text`:写入自动记忆。
|
|
101
|
+
- prompt_toolkit 不可用或没有真实控制台时退回普通 `input()`。文件索引最多缓存 5000 个路径,30 秒过期,并排除依赖/缓存目录。`@` 支持模糊文件补全,`/` 支持命令和常用参数补全;输入历史存于 `.claxcode/cli_history`,Enter 提交、Alt+Enter 换行、Ctrl+C 清空非空输入。
|
|
102
|
+
- 每个项目的 `.claxcode/cli_session` 保存最近会话 UUID;每轮结束后保存消息,下次启动自动恢复,`/clear` 清空上下文。`/project switch` 会保存旧会话,重建项目 Agent、Skills、Hooks 和补全,再恢复目标项目会话;命令参数支持成对引号和 Windows 路径。`/init` 覆盖已有 `CLAUDE.md` 前需要确认。
|
|
103
|
+
- `ask` 模式的交互审批支持 `y`(允许一次)、`a`(本会话始终允许该工具)、`N`(拒绝);切换 `/mode` 会清空自动批准集合。
|
|
104
|
+
- Ctrl+C 设置全局工具取消标记;长任务(例如 SSH)轮询该标记,Agent 在处理下一条用户消息前重置它。
|
|
105
|
+
|
|
106
|
+
### API 表面
|
|
107
|
+
|
|
108
|
+
- `POST /sessions`、`GET /sessions`、`GET /sessions/{id}`、`DELETE /sessions/{id}`:会话管理。
|
|
109
|
+
- `POST /sessions/{id}/chat`:SSE 聊天;事件包括 `thinking`、`message_delta`、`tool_call`、`tool_result_start`、`tool_result`、可选 `debug`、`done`。
|
|
110
|
+
- `GET /tools`、`POST /tools/invoke`:列出工具、直接调用工具。
|
|
111
|
+
- `POST /subagents`、`GET /subagents/{task_id}`、`POST /subagents/{task_id}/stream`:创建、查询和流式运行子代理任务。
|
|
112
|
+
- `GET /health`:健康检查。
|
|
113
|
+
|
|
114
|
+
每次 API 聊天请求都会新建 Agent、从数据库恢复该会话消息,并在流结束后重新保存。FastAPI lifespan 启动时初始化数据库。
|
|
115
|
+
|
|
116
|
+
## 代码组织
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
claxcode/
|
|
120
|
+
├── main.py # FastAPI app、路由注册、/health、Uvicorn 启动
|
|
121
|
+
├── cli.py # REPL、单发模式、斜杠命令、审批与 CLI 持久化
|
|
122
|
+
├── cli_completion.py # @ 文件和 / 命令补全
|
|
123
|
+
├── config.py # pydantic-settings 全局 settings
|
|
124
|
+
├── api/ # session、chat、tools、subagents 路由
|
|
125
|
+
├── models/ # API 的 Pydantic 请求/响应模型
|
|
126
|
+
├── core/
|
|
127
|
+
│ ├── agent.py # 主 Agent 循环及工具执行管线
|
|
128
|
+
│ ├── models.py # LLMProvider 抽象和各 Provider
|
|
129
|
+
│ ├── context.py # 消息历史、Token 粗估、摘要压缩、恢复清理
|
|
130
|
+
│ └── checkpoint.py # 写前文件快照、manifest、列表与回滚
|
|
131
|
+
├── tools/ # Tool 基类、注册表及自动发现的内置工具
|
|
132
|
+
├── memory/
|
|
133
|
+
│ ├── session_store.py # SQLAlchemy ORM、init_db、会话和子代理持久化
|
|
134
|
+
│ ├── long_term.py # 长期记忆检索、导入导出等
|
|
135
|
+
│ ├── project_memory.py # 项目记录与摘要
|
|
136
|
+
│ ├── project_context.py # CLAUDE.md / .claxcode/context.md 加载
|
|
137
|
+
│ └── auto_memory.py # ~/.claxcode/auto_memory.json,最多 50 条
|
|
138
|
+
├── extensions/
|
|
139
|
+
│ ├── skills.py # Skill 加载、覆盖、命令和 tools.py 动态注册
|
|
140
|
+
│ ├── hooks.py # PreToolUse / PostToolUse shell hooks
|
|
141
|
+
│ ├── mcp.py # 占位实现,仅返回空工具列表
|
|
142
|
+
│ └── plugins.py # 占位实现
|
|
143
|
+
├── security/
|
|
144
|
+
│ ├── permissions.py # 五种权限模式
|
|
145
|
+
│ └── audit.py # .claxcode/audit.jsonl 审计日志
|
|
146
|
+
├── subagents/ # explore、planner、executor 及独立上下文基类
|
|
147
|
+
└── skills/ # task-workflow、bug-fix、code-review、python-refactor
|
|
148
|
+
|
|
149
|
+
tests/ # 按 api/core/tools/memory/security/extensions 分组的 pytest 套件
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 工具系统
|
|
153
|
+
|
|
154
|
+
- 工具继承 `claxcode/tools/base.py` 的 `Tool`,定义 `name`、`description`、JSON Schema `input_schema`、`category`、`required_permissions`,实现 `async execute(**kwargs) -> str`。
|
|
155
|
+
- `@tool` 在 `claxcode/tools/registry.py` 中把实例注册进全局 `registry`。
|
|
156
|
+
- `claxcode/tools/__init__.py` 使用 `pkgutil` 自动导入包内模块(排除 base、registry 和 `__init__`);新增工具模块通常不需要手工登记。两个入口都导入 `claxcode.tools` 以触发发现。
|
|
157
|
+
- 当前有 **35 个内置工具**:文件操作 7、搜索 3、执行 3、Web 2、浏览器 9、SSH 5、代码智能 3,以及 `remember_fact`、`admin_add_tool`、`calculate`。
|
|
158
|
+
- 浏览器工具共享 actor 式持久会话,同一页面可跨工具调用和对话轮次连续使用。Playwright 或 Chromium 不可用时,相应测试会跳过。
|
|
159
|
+
- 工具结果保持普通字符串;新增工具应把预期异常转换成错误字符串,不让 `execute()` 直接向调用方抛出异常。
|
|
160
|
+
|
|
161
|
+
### LLM Provider
|
|
162
|
+
|
|
163
|
+
`claxcode/core/models.py` 定义 `LLMProvider.stream_chat(messages, tools)`,以异步迭代器产生文本块或工具调用字典。`get_provider()` 支持:
|
|
164
|
+
|
|
165
|
+
- `openai`:OpenAI API,httpx 实现。
|
|
166
|
+
- `generic_openai`:vLLM、LM Studio、DashScope 等 OpenAI 兼容端点。
|
|
167
|
+
- `anthropic`:Anthropic SDK;未安装依赖时退回 `DummyProvider`。
|
|
168
|
+
- `ollama`:原生 `/api/chat`,`LLM_CUSTOM_CONFIG` 可传 `ollama_options`。
|
|
169
|
+
- `custom_http`:通过 `request_template` 和 `response_parser` 适配自定义流式 HTTP API。
|
|
170
|
+
- 运行时通过 `register_custom_provider(name, cls)` 注册的其他 Provider。
|
|
171
|
+
|
|
172
|
+
未知名称会退回 `DummyProvider`,使应用仍能启动并报告配置问题。
|
|
173
|
+
|
|
174
|
+
### 上下文与持久化
|
|
175
|
+
|
|
176
|
+
- `init_db()` 用 `Base.metadata.create_all` 创建 `sessions`、`subagent_tasks`、`long_term_memories`、`project_memories`;**没有数据库迁移系统**。
|
|
177
|
+
- 默认数据库为 `./.claxcode/claxcode.db`。会话消息以 JSON 存在 `sessions.messages`,系统提示不持久化。
|
|
178
|
+
- `ContextManager.restore()` 会清理不完整的工具调用/结果配对,避免 Provider 拒绝孤立消息。
|
|
179
|
+
- Token 数是粗略字符估算(`len(text) // 3 + 1`)。超过阈值时,主 Agent 调用 LLM 总结最旧的一半消息;新增消息时的硬上限保护会直接丢弃最旧消息。
|
|
180
|
+
- 系统提示可由 `~/.claxcode/system_prompt.md` 覆盖;项目上下文依次尝试 `CLAUDE.md`、`.claxcode/context.md`。
|
|
181
|
+
- 记忆职责分层:`~/.claxcode/auto_memory.json` 只保存稳定的全局用户偏好/事实;长期记忆保存项目或全局历史事件;项目记忆保存滚动状态摘要。自动记忆和长期记忆每轮动态刷新,避免当前会话写入后不生效或重复注入。
|
|
182
|
+
- 长期记忆检索使用“当前项目 + 全局”作用域,支持中文词语与二字片段相关性排序,无匹配时退回少量近期记忆;项目路径在写入和查询时统一标准化。
|
|
183
|
+
- `/compact` 分别生成本次总结与融合旧状态的项目滚动摘要,写入长期记忆和项目记忆后立即持久化清空后的会话;项目未 `/init` 时也会自动创建摘要记录。
|
|
184
|
+
|
|
185
|
+
## 环境变量
|
|
186
|
+
|
|
187
|
+
所有设置见 `claxcode/config.py`;下表默认值来自代码,而不是仅来自 `.env.example`。
|
|
188
|
+
|
|
189
|
+
| 变量 | 默认值 | 说明 |
|
|
190
|
+
|---|---|---|
|
|
191
|
+
| `LLM_PROVIDER` | `openai` | Provider 名称或运行时注册的自定义名称 |
|
|
192
|
+
| `LLM_API_KEY` / `LLM_BASE_URL` | 空字符串 | API 密钥 / 端点 |
|
|
193
|
+
| `LLM_MODEL` | `gpt-4o` | 模型名 |
|
|
194
|
+
| `LLM_TEMPERATURE` / `LLM_MAX_TOKENS` | `0.2` / `4096` | 生成参数 |
|
|
195
|
+
| `LLM_CUSTOM_CONFIG` | 空字符串 | JSON;用于 Ollama 选项或自定义 HTTP 模板 |
|
|
196
|
+
| `DATABASE_URL` | `sqlite+aiosqlite:///./.claxcode/claxcode.db` | SQLAlchemy 异步连接串 |
|
|
197
|
+
| `SNAPSHOTS_DIR` | `./.claxcode/snapshots` | 写前快照目录 |
|
|
198
|
+
| `PROJECT_CONTEXT_FILE` | `CLAUDE.md` | 项目上下文文件名 |
|
|
199
|
+
| `PERMISSION_MODE` | `ask` | `ask` / `auto_edit` / `plan` / `auto_safe` / `yolo` |
|
|
200
|
+
| `MAX_CONTEXT_TOKENS` | `128000` | 粗略上下文预算 |
|
|
201
|
+
| `CONTEXT_COMPRESSION_THRESHOLD` | `0.85` | 触发压缩的预算比例 |
|
|
202
|
+
| `HOST` / `PORT` | `127.0.0.1` / `8000` | API 监听地址 |
|
|
203
|
+
| `CLAXCODE_DEBUG` | `false` | 调试事件、SQL echo、Uvicorn reload |
|
|
204
|
+
| `TOOL_TIMEOUT` | `60` | 工具相关默认超时配置 |
|
|
205
|
+
| `BROWSER_HEADLESS` | `true` | 新浏览器会话的默认模式 |
|
|
206
|
+
|
|
207
|
+
CLI 在导入项目模块前加载模型配置,优先级为 `--env` 指定文件 > 当前目录 `.env` > `~/.claxcode/.env`;修改 CLI 的导入顺序时保留这一约束(ruff 对 `cli.py` 特意忽略 E402)。根级命令 `claxcode-cli init` 可交互创建全局配置,API Key 使用隐藏输入,覆盖已有文件前需确认;它与交互式 `/init` 的项目初始化不同。版本可通过 `/version` 或 `claxcode-cli --version/-v` 查看。
|
|
208
|
+
|
|
209
|
+
## 扩展点
|
|
210
|
+
|
|
211
|
+
- **新工具**:在 `claxcode/tools/` 新增模块,继承 `Tool` 并使用 `@tool`;为文件、Shell、Web 等能力准确声明权限。
|
|
212
|
+
- **新 Provider**:继承 `LLMProvider`,在 `get_provider()` 加分支,或在运行时调用 `register_custom_provider()`。
|
|
213
|
+
- **新 Skill**:目录中放置 `SKILL.md`(`# Name`、`## Description`、`## Instructions`,可选 `## Commands`)和可选 `tools.py`。加载顺序为内置 `claxcode/skills/` → 用户 `~/.claxcode/skills/`、`~/.agent/skills/` → 项目 `.claxcode/skills/`、`.agent/skills/`、`skills/`;同名后者覆盖前者。CLI 支持 `/skills create` 和 `/skills reload`。
|
|
214
|
+
- **Hooks**:在 `~/.claxcode/hooks.json` 或项目 `.claxcode/hooks.json` 配置 `PreToolUse`/`PostToolUse`。`match` 是工具名正则;命令从 stdin 收到 JSON,并获得 `CLAXCODE_TOOL_NAME`、`CLAXCODE_TOOL_ARGS`。Pre hook 非零退出会阻止工具;启动失败或 30 秒超时不阻塞主流程。
|
|
215
|
+
- **子代理**:`explore` 和 `planner` 仅开放六个只读搜索/读取工具,分别最多 8 和 5 轮;`executor` 开放全部工具,最多 10 轮。子代理拥有独立上下文。
|
|
216
|
+
|
|
217
|
+
## 开发约定与代码风格
|
|
218
|
+
|
|
219
|
+
遵循 README 中的原则:**最少代码、最简单实现**。
|
|
220
|
+
|
|
221
|
+
1. 只实现当前需求,不做顺手重构或投机性配置。
|
|
222
|
+
2. 扁平优于嵌套,优先提前返回;三行相似代码优于过早抽象。
|
|
223
|
+
3. 在根因处修复问题,及时删除死代码。
|
|
224
|
+
4. 新功能和缺陷修复应附快速、无需真实 LLM 或外部网络的测试。
|
|
225
|
+
5. 使用现有 async/await、类型标注、`pathlib.Path` 和绝对导入风格,避免引入未在 `pyproject.toml` 声明的新依赖。
|
|
226
|
+
|
|
227
|
+
语言约定:`README.md`、CLI 输出、错误信息和多数 LLM 提示使用中文;模块 docstring 多数为英文,代码内注释中英混合。编辑时匹配所在文件,新增用户-facing 文本通常使用中文。
|
|
228
|
+
|
|
229
|
+
静态检查命令:
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
ruff check claxcode tests
|
|
233
|
+
mypy claxcode
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
ruff 配置为行宽 100、Python 3.11,规则 `E,F,I,N,W,UP,B,C4,SIM`;mypy 为 strict。**当前全量静态检查基线并不干净**:本次验证 ruff 报告 36 项、mypy 报告 104 项(含缺失可选依赖/类型 stub 等问题)。修改时不要新增告警,并区分存量问题与自己的改动。
|
|
237
|
+
|
|
238
|
+
## 测试策略
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
pytest # 全量
|
|
242
|
+
pytest tests/test_core/test_agent_permissions.py
|
|
243
|
+
pytest tests/test_tools/test_file_operations.py -k write
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
`pyproject.toml` 设置 `testpaths = ["tests"]`、`asyncio_mode = "auto"` 和 `asyncio_default_fixture_loop_scope = "function"`,异步测试无需统一额外装饰器(部分旧测试仍显式使用 `@pytest.mark.asyncio`)。
|
|
247
|
+
|
|
248
|
+
- `tests/conftest.py` 的 `client` fixture 调用 `init_db()`,再用 httpx `ASGITransport` 和 `AsyncClient` 直接测试 FastAPI,不启动真实端口。
|
|
249
|
+
- 测试目录按被测模块分组。新工具、Provider、权限或扩展功能应在相邻测试目录添加同风格测试。
|
|
250
|
+
- 使用 `monkeypatch`、临时目录和假 Provider/会话隔离外部依赖;`pytest-httpx` 可用于出站 HTTP mock。测试不得要求真实 LLM 密钥或公网。
|
|
251
|
+
- 浏览器集成测试只使用本地 `data:` URL;Playwright/Chromium 不可用时跳过。
|
|
252
|
+
- 本次实际验证结果:**200 个测试全部通过**(`200 passed in 8.87s`)。README 内其他测试数量是历史值,以 pytest 实际收集结果为准。
|
|
253
|
+
|
|
254
|
+
## 安全注意事项
|
|
255
|
+
|
|
256
|
+
主 Agent 的权限模式:
|
|
257
|
+
|
|
258
|
+
| 模式 | 行为 |
|
|
259
|
+
|---|---|
|
|
260
|
+
| `ask` | 仅声明 `read` 的工具自动放行;其他工具需要审批。API 聊天没有审批回调,因此这些工具会被阻止 |
|
|
261
|
+
| `plan` | 阻止需要 `write` 或 `execute` 的工具 |
|
|
262
|
+
| `auto_safe` | 阻止需要 `execute` 的工具,允许读、写和 Web 工具 |
|
|
263
|
+
| `auto_edit` / `yolo` | 当前实现均放行全部工具;`yolo` 应视为完全无沙箱 |
|
|
264
|
+
|
|
265
|
+
主 Agent 的 `_execute_tool()` 顺序为:权限检查 → Pre hook → 对带 `path` 参数的写工具创建快照 → 执行 → Post hook → 审计。快照只覆盖执行前已存在的文件,位于 `.claxcode/snapshots/<session>/<timestamp>/`,原始路径记录在 `manifest.json`;CLI `/rollback` 使用这些 manifest 恢复。允许和被阻止的主 Agent 工具调用都会尝试写入 `.claxcode/audit.jsonl`。
|
|
266
|
+
|
|
267
|
+
必须注意以下边界:
|
|
268
|
+
|
|
269
|
+
- `POST /tools/invoke` 直接执行工具,**不经过**主 Agent 的权限、hooks、快照和审计管线。
|
|
270
|
+
- 子代理基类也直接执行其允许列表中的工具;`executor` 的全部工具调用不经过主 Agent 管线。
|
|
271
|
+
- CLI 的 `!cmd` 是直接 Shell 执行入口,不经过交互审批。
|
|
272
|
+
- `run_shell`、`git_command` 可执行任意命令;`admin_add_tool` 会写入工具代码;Skill 的 `tools.py` 通过 `exec()` 加载;Hooks 本身也是 Shell 命令。不要加载不可信配置或 Skill。
|
|
273
|
+
- API 未实现身份认证,默认仅绑定 `127.0.0.1`。不要在不可信网络中直接暴露,尤其不要与直接工具调用或 executor 组合暴露。
|
|
274
|
+
- `.env`、`.claxcode/`、虚拟环境和缓存均由 `.gitignore` 排除。`.env` 虽未在当前索引中跟踪,但曾出现在 Git 历史中;其中曾使用的真实密钥必须轮换,不能仅依赖删除文件。
|
|
275
|
+
|
|
276
|
+
## 部署与已知限制
|
|
277
|
+
|
|
278
|
+
- 应用部署仍是本地 editable 安装后用 console script 启动 Uvicorn 或 CLI;没有容器、进程管理或生产部署工具。PyPI 发布由 GitHub Actions 负责。
|
|
279
|
+
- 数据库仅自动建表,没有 Alembic 等迁移机制;修改 ORM 时需考虑既有本地数据库。
|
|
280
|
+
- MCP 和插件系统仍是 stub,不能当作已可用能力。
|
|
281
|
+
- 无视觉输入、无 `/resume` 会话选择器;CLI 只自动恢复项目最近一次会话。
|
|
282
|
+
- `.claxcode/` 是本地状态,不是源码;调试问题时可检查数据库、快照和审计日志,但不要提交这些文件。
|
claxcode-0.1.1/CLAUDE.md
ADDED
claxcode-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|