已合并
feat(agents): tracked symlink 自动加载,兼容 Windows 客户端 #190
xieyajun创建于 6月25日
feat(agents): tracked symlink 自动加载,兼容 Windows 客户端 #190
已合并
共 20 个文件变更+155-278
| @@ -1,12 +1,17 @@ | |||
| 1 | -# amct 大模型量化 Agent Skills | 1 | +# amct Agent Skills |
| 2 | 2 | ||
| 3 | -面向昇腾 NPU 大模型量化压缩的 Agent Skills:封装 amct(`amct_pytorch`)的 LLM 量化全流程(`eval / extract_ptq_data / ptq / deploy` + blockwise PTQ),让你用自然语言完成「模型 → 量化方案 → 部署权重」。同时适配 Claude Code 与 OpenCode。 | 3 | +amct 仓的 Agent Skills 基础设施(`.agents/`),以 skill 为单元封装各类研发能力,自然语言触发、agent 自主执行,clone 即可用。 |
| 4 | + | ||
| 5 | +当前内置: | ||
| 6 | +- **quant-workflow**:LLM 量化全流程编排主入口(方案推荐 → PTQ → 部署导出,见下文) | ||
| 7 | +- **amct-ops-dev**:NPU 算子开发(编排外独立工具) | ||
| 8 | +- **gitcode-pr / gitcode-issue**:GitCode 仓库协作操作 | ||
| 9 | + | ||
| 10 | +后续按需扩充。适配 Claude Code 与 OpenCode。 | ||
| 4 | 11 | ||
| 5 | ## 快速开始 | 12 | ## 快速开始 |
| 6 | 13 | ||
| 7 | -```bash | 14 | +clone 本仓即可直接使用,Agent Skills 自动加载(机制见 [docs/architecture.md](docs/architecture.md) §3)。 |
| 8 | -bash scripts/init-agent.sh # 生成客户端视图;--claude / --opencode 可单装 | ||
| 9 | -``` | ||
| 10 | 15 | ||
| 11 | 装好后直接用自然语言描述任务,例如: | 16 | 装好后直接用自然语言描述任务,例如: |
| 12 | 17 | ||
| @@ -59,13 +64,13 @@ bash scripts/init-agent.sh # 生成客户端视图;--claude / --opencod | |||
| 59 | 64 | ||
| 60 | ## 仓内组织 | 65 | ## 仓内组织 |
| 61 | 66 | ||
| 62 | -`.agents/` 是唯一可信源(tracked): | 67 | +`.agents/` 是内容唯一可信源(tracked);客户端配置(`settings.json`/`opencode.json`)由各自视图目录直接持有: |
| 63 | 68 | ||
| 64 | ``` | 69 | ``` |
| 65 | .agents/ | 70 | .agents/ |
| 66 | ├── agents/ # 子代理:quant-analyzer / quant-implementer / quant-reviewer | 71 | ├── agents/ # 子代理:quant-analyzer / quant-implementer / quant-reviewer |
| 67 | ├── skills/ | 72 | ├── skills/ |
| 68 | -│ │ # LLM量化编排链路 | 73 | +│ │ # LLM 量化编排链路 |
| 69 | │ ├── quant-workflow/ # LLM 量化流程入口(调度) | 74 | │ ├── quant-workflow/ # LLM 量化流程入口(调度) |
| 70 | │ ├── quant-tools/ # 被调度的量化叶子技能(含 model-adapter + references 共享) | 75 | │ ├── quant-tools/ # 被调度的量化叶子技能(含 model-adapter + references 共享) |
| 71 | │ │ # 编排外的独立 skill(用户直接点名调用) | 76 | │ │ # 编排外的独立 skill(用户直接点名调用) |
| @@ -73,13 +78,42 @@ bash scripts/init-agent.sh # 生成客户端视图;--claude / --opencod | |||
| 73 | │ ├── gitcode-pr/ # PR 创建 / 评论 | 78 | │ ├── gitcode-pr/ # PR 创建 / 评论 |
| 74 | │ ├── gitcode-issue/ # issue 读取 | 79 | │ ├── gitcode-issue/ # issue 读取 |
| 75 | │ └── default-skills/ # 按需装通用 skill | 80 | │ └── default-skills/ # 按需装通用 skill |
| 76 | -├── docs/ # casebook(L1/L2/L3)/ architecture.md / repo-map.md / roadmap.md | 81 | +├── docs/ # casebook(L1/L2/L3)/ architecture.md / repo-map.md |
| 77 | -├── hooks/ # pre_tool_use / subagent_stop(Claude Code) | 82 | +└── hooks/ # pre_tool_use / subagent_stop(Claude Code) |
| 78 | -├── settings.json # Claude Code 配置(权限 + hooks) | ||
| 79 | -└── opencode.json # OpenCode 配置(plugins + 权限) | ||
| 80 | ``` | 83 | ``` |
| 81 | 84 | ||
| 82 | -`scripts/init-agent.sh` 据此生成 `.claude/`、`.opencode/` 客户端视图(均 gitignored、全量生成):`settings.json`→`.claude/`、`opencode.json`→`.opencode/`,skills/agents/hooks/docs 投影到两端。技能清单与规划见 [docs/roadmap.md](docs/roadmap.md),架构与设计见 [docs/architecture.md](docs/architecture.md)。 | 85 | +`.claude/`、`.opencode/` 是真实目录;其中 **配置文件**(`settings.json`、`opencode.json`)为真实文件,**内容目录**(skills/agents/hooks/docs)为 git-tracked symlink 指向 `.agents/`,随 clone 自动生效。架构与设计见 [docs/architecture.md](docs/architecture.md)。 |
| 86 | + | ||
| 87 | +> **Windows**:`settings.json`/`opencode.json` 为真实文件,客户端可正常启动。内容目录(skills/agents/hooks/docs)为 symlink,`core.symlinks=false` 下 clone 后退化为文本文件: | ||
| 88 | +> - **OpenCode**:原生将 `.agents/skills/` 列为发现路径,无需 symlink,clone 即可用 ✅ | ||
| 89 | +> - **Claude Code**:只扫 `.claude/skills/`,symlink 断裂后 skills 全部失效 ❌ → 修复如下: | ||
| 90 | + | ||
| 91 | +**修复方式(任选其一)**: | ||
| 92 | + | ||
| 93 | +1. **管理员终端**(推荐):右键 PowerShell / Git Bash,选「以管理员身份运行」,然后执行: | ||
| 94 | + ```bash | ||
| 95 | + git config core.symlinks true | ||
| 96 | + rm -rf .claude | ||
| 97 | + git checkout HEAD -- .claude | ||
| 98 | + ``` | ||
| 99 | + | ||
| 100 | +2. **开启开发者模式**(一劳永逸,之后普通终端也可用):打开「设置 → 系统 → 开发者选项 → 开发人员模式」,然后执行: | ||
| 101 | + ```bash | ||
| 102 | + git config core.symlinks true | ||
| 103 | + rm -rf .claude | ||
| 104 | + git checkout HEAD -- .claude | ||
| 105 | + ``` | ||
| 106 | + | ||
| 107 | +3. **手动建立目录联接**(无需管理员,但 git 不识别 junction,git 操作中可能报 warning): | ||
| 108 | + ```cmd | ||
| 109 | + rmdir .claude\skills .claude\agents .claude\docs .claude\hooks | ||
| 110 | + mklink /J .claude\skills .agents\skills | ||
| 111 | + mklink /J .claude\agents .agents\agents | ||
| 112 | + mklink /J .claude\docs .agents\docs | ||
| 113 | + mklink /J .claude\hooks .agents\hooks | ||
| 114 | + ``` | ||
| 115 | + | ||
| 116 | +如需同时修复 `.opencode/`,在上述 git checkout 命令中将 `-- .claude` 替换为 `-- .claude .opencode`;或手动对 `.opencode/` 重复执行 mklink /J 命令。 | ||
| 83 | 117 | ||
| 84 | ## 面向 agent 集成 | 118 | ## 面向 agent 集成 |
| 85 | 119 | ||
| @@ -8,8 +8,6 @@ | |||
| 8 | - 记录代码结构、关键模块和锚点文件 | 8 | - 记录代码结构、关键模块和锚点文件 |
| 9 | - `casebook/` | 9 | - `casebook/` |
| 10 | - 记录模型适配经验、量化经验和典型问题 | 10 | - 记录模型适配经验、量化经验和典型问题 |
| 11 | -- `roadmap.md` | ||
| 12 | - - skills 清单与演进规划(已实现 / 规划中) | ||
| 13 | 11 | ||
| 14 | ## 使用原则 | 12 | ## 使用原则 |
| 15 | 13 | ||
| @@ -33,12 +33,12 @@ docs/casebook/ + docs/repo-map.md 知识层(适配经验 / 仓内导航 | |||
| 33 | 33 | ||
| 34 | ## 3. 单一源投影机制(Single Source of Truth) | 34 | ## 3. 单一源投影机制(Single Source of Truth) |
| 35 | 35 | ||
| 36 | -`.agents/` 是**唯一源**(git tracked);`scripts/init-agent.sh` 把它投影成两套 runtime 视图,分两种方式: | 36 | +`.agents/` 是**内容唯一源**(git tracked);`.claude/`、`.opencode/` 下按类型分两种方式投影: |
| 37 | 37 | ||
| 38 | -- **符号链接**(源改即时生效):`skills` / `agents` / `hooks` / `docs`,及 `CLAUDE.md → AGENTS.md`。 | 38 | +- **git-tracked 符号链接**(源改即时生效):`skills` / `agents` / `hooks` / `docs` 目录 |
| 39 | -- **拷贝**(源改后须重跑 `init-agent.sh` 才同步):`settings.json → .claude/`、`opencode.json → .opencode/`。 | 39 | +- **git-tracked 真实文件**(各端独立持有,不在 `.agents/` 下):`settings.json`(`.claude/`)、`opencode.json`(`.opencode/`) |
| 40 | 40 | ||
| 41 | -视图分布:`.claude/{skills,agents,docs,settings.json}` + `CLAUDE.md`;`.opencode/{skills,agents,docs,opencode.json}`。两端视图 **全 gitignored、全量生成**,clone 后跑 `bash scripts/init-agent.sh` 生成。一处源、双端一致,不提交生成物、不双份维护。 | 41 | +视图分布:`.claude/{skills,agents,hooks,docs,settings.json}`;`.opencode/{skills,agents,docs,opencode.json}`。配置文件为真实文件(兼容 Windows),内容目录为 symlink(clone 自动还原)。系统提示统一由根目录 `AGENTS.md` 提供。一处源、双端一致,不双份维护。 |
| 42 | 42 | ||
| 43 | ## 4. 设计原则 | 43 | ## 4. 设计原则 |
| 44 | 44 | ||
| @@ -62,7 +62,7 @@ docs/casebook/ + docs/repo-map.md 知识层(适配经验 / 仓内导航 | |||
| 62 | 62 | ||
| 63 | ## 7. 运行与验证 | 63 | ## 7. 运行与验证 |
| 64 | 64 | ||
| 65 | -- 启动:`bash scripts/init-agent.sh` 生成视图后,在 Claude Code 或 OpenCode 中启动。 | 65 | +- 启动:clone 仓库后即可直接在 Claude Code 或 OpenCode 中启动(symlink 视图随 clone 自动生效)。 |
| 66 | - 已实测(OpenCode + glm-5):执行流(W8A8 直转)、分析流(方案推荐)、PTQ 流(extract → ptq → eval)三类端到端均由 agent 自主跑通且结果核实准确。 | 66 | - 已实测(OpenCode + glm-5):执行流(W8A8 直转)、分析流(方案推荐)、PTQ 流(extract → ptq → eval)三类端到端均由 agent 自主跑通且结果核实准确。 |
| 67 | 67 | ||
| 68 | ## 8. 面向 agent 集成(黑盒契约) | 68 | ## 8. 面向 agent 集成(黑盒契约) |
D.agents/docs/roadmap.md+0-124
| @@ -1,124 +0,0 @@ | |||
| 1 | -# AMCT 仓 Agent Skills 总览与规划 | ||
| 2 | - | ||
| 3 | -> 本仓 agent 的 skills 清单与演进规划。`[x]` 已实现、`[ ]` 规划中。 | ||
| 4 | -> 分发见下「单一源投影」;入口见根 `AGENTS.md` 与 [../README.md](../README.md),架构见 [architecture.md](architecture.md)。 | ||
| 5 | - | ||
| 6 | -## 已实现 —— 量化 agent(本仓主体) | ||
| 7 | - | ||
| 8 | -单编排入口 + 3 角色子代理 + 叶子技能: | ||
| 9 | - | ||
| 10 | -- [x] **quant-workflow** — 量化全生命周期唯一编排入口(判阶段 / 路由 / 交互门 / 汇总,零执行) | ||
| 11 | -- [x] **quant-tools/** 叶子: | ||
| 12 | - - [x] **scheme-recommendation** / **algorithm-recommendation** — 方案 / 算法推荐(规划) | ||
| 13 | - - [x] **quant-run** — 统一执行(直转评测 / 校准提取 / PTQ 训练 / 结果评测) | ||
| 14 | - - [x] **direct-quant-eval** / **algorithm-validation** — delta / 算法收益判读(只读结果) | ||
| 15 | - - [x] **deploy-export** — 部署权重导出 + `deploy_quantization.md` 交付 | ||
| 16 | - - [x] **model-adapter** — 新模型适配 | ||
| 17 | -- [x] **子代理**:`quant-analyzer`(规划/只读)· `quant-implementer`(执行)· `quant-reviewer`(判读) | ||
| 18 | -- [x] **hooks**:`pre_tool_use`(角色越界保护)· `subagent_stop`(自验证 + 重试上限) | ||
| 19 | - | ||
| 20 | -## 已实现 —— 通用协作 | ||
| 21 | - | ||
| 22 | -- [x] **gitcode-issue** — 读取 Issue、读/回评论 | ||
| 23 | -- [x] **gitcode-pr** — 创建 PR、行内检视、cherry-pick | ||
| 24 | -- [x] **default-skills** — 按需安装必备 skill | ||
| 25 | - | ||
| 26 | -## 规划中 —— 仓级 dev-workflow(未实现) | ||
| 27 | - | ||
| 28 | -面向「需求开发 / 问题单 / Issue → 设计 → 编码验证 → PR → 流水线」的完整研发流,待实现后接入: | ||
| 29 | - | ||
| 30 | -- [ ] **superpowers** — 需求开发(软件设计 / 编码 / 用例) | ||
| 31 | -- [ ] **amct-reviewer** — 按编码规范 / 军规 / 设计约束检视代码 | ||
| 32 | -- [ ] **amct-builder** — 编译 + 执行 UT/ST | ||
| 33 | -- [ ] **amct-tester** — 生成用例并在 NPU 环境执行 | ||
| 34 | -- [ ] **gitcode-pipeline** — 触发 / 查询流水线、获取失败任务日志 | ||
| 35 | -- [ ] **install-cann-toolkit** — 下载并安装最新 CANN toolkit | ||
| 36 | - | ||
| 37 | -规划流程:需求/问题单/Issue → (设计)→ 编码 → `amct-builder` UT/ST + `amct-reviewer` 检视 + `amct-tester` 真机验证 → `gitcode-pr` 提 PR → `gitcode-pipeline` 触发并轮询流水线 → 失败取日志、本地修、再提。 | ||
| 38 | - | ||
| 39 | -## 分发:单一源投影(Single Source of Truth) | ||
| 40 | - | ||
| 41 | -`.agents/` 为**唯一源**(git tracked,含 skills/agents/hooks/docs + `settings.json`/`opencode.json`);`scripts/init-agent.sh` 投影生成 `.claude/`(Claude Code)与 `.opencode/`(OpenCode)视图,**均 gitignored**,clone 后跑一次 `bash scripts/init-agent.sh` 生成。一处源、双端一致,不提交生成物、不双份维护。 | ||
| 42 | - | ||
| 43 | -## 附录:规划中 dev-workflow 流程图 | ||
| 44 | - | ||
| 45 | -> 下图为规划中的仓级研发流(需求/问题单/Issue → 编码 → 验证 → PR → 流水线);待 `amct-reviewer` / `amct-builder` / `amct-tester` / `gitcode-pipeline` 等 skill 实现后接入(当前仅 `gitcode-pr` / `gitcode-issue` 已实现)。 | ||
| 46 | - | ||
| 47 | -```mermaid | ||
| 48 | -flowchart TB | ||
| 49 | - subgraph 入口节点 | ||
| 50 | - A1[需求开发] | ||
| 51 | - A2[问题单修改] | ||
| 52 | - A3[Issue处理] | ||
| 53 | - end | ||
| 54 | - | ||
| 55 | - subgraph 判断 | ||
| 56 | - B1{是否需要<br/>代码修改?} | ||
| 57 | - B2{是否需要<br/>设计阶段?} | ||
| 58 | - end | ||
| 59 | - | ||
| 60 | - subgraph 设计阶段 | ||
| 61 | - C1[软件设计<br/>需求规格] | ||
| 62 | - end | ||
| 63 | - | ||
| 64 | - subgraph 编码验证阶段 | ||
| 65 | - D1[编写代码] | ||
| 66 | - D2[执行ut/st] | ||
| 67 | - D3[amct-reviewer<br/>agent检视代码] | ||
| 68 | - D4[amct-tester<br/>本地验证] | ||
| 69 | - end | ||
| 70 | - | ||
| 71 | - subgraph PR流程 | ||
| 72 | - E1[gitcode-pr<br/>创建PR] | ||
| 73 | - E2[个人代码检视] | ||
| 74 | - E3[gitcode-pipeline<br/>触发流水线] | ||
| 75 | - E4[gitcode-pipeline<br/>定时获取<br/>流水线结果] | ||
| 76 | - end | ||
| 77 | - | ||
| 78 | - subgraph 流水线结果处理 | ||
| 79 | - F1{gitcode-pipeline<br/>流水线<br/>是否通过?} | ||
| 80 | - F2[gitcode-pipeline<br/>获取失败<br/>任务日志] | ||
| 81 | - F3[Agent本地修复] | ||
| 82 | - end | ||
| 83 | - | ||
| 84 | - subgraph 推送代码 | ||
| 85 | - I1[gitcode-pr<br/>提交代码] | ||
| 86 | - end | ||
| 87 | - | ||
| 88 | - subgraph 完成 | ||
| 89 | - H1[流程结束] | ||
| 90 | - end | ||
| 91 | - | ||
| 92 | - %% 入口到判断 | ||
| 93 | - A1 --> B2 | ||
| 94 | - A2 --> B1 | ||
| 95 | - A3 --> B1 | ||
| 96 | - | ||
| 97 | - %% 设计判断 | ||
| 98 | - B2 -->|是| C1 | ||
| 99 | - B2 -->|否| D1 | ||
| 100 | - C1 --> D1 | ||
| 101 | - | ||
| 102 | - %% 编码判断 | ||
| 103 | - B1 -->|是| D1 | ||
| 104 | - B1 -->|否| H1 | ||
| 105 | - | ||
| 106 | - %% 编码到PR | ||
| 107 | - D1 --> D2 | ||
| 108 | - D2 --> D3 | ||
| 109 | - D3 --> D4 | ||
| 110 | - D4 --> E1 | ||
| 111 | - | ||
| 112 | - %% PR流程 | ||
| 113 | - E1 --> E2 | ||
| 114 | - E2 --> E3 | ||
| 115 | - E3 --> E4 | ||
| 116 | - E4 --> F1 | ||
| 117 | - | ||
| 118 | - %% 流水线结果处理 | ||
| 119 | - F1 -->|通过| H1 | ||
| 120 | - F1 -->|失败| F2 | ||
| 121 | - F2 --> F3 | ||
| 122 | - F3 --> I1 | ||
| 123 | - I1 --> E3 | ||
| 124 | -``` | ||
| @@ -1,4 +1,20 @@ | |||
| 1 | #!/usr/bin/env python3 | 1 | #!/usr/bin/env python3 |
| 2 | +# -*- coding: UTF-8 -*- | ||
| 3 | +# ---------------------------------------------------------------------------- | ||
| 4 | +# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved. | ||
| 5 | +# | ||
| 6 | +# Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 7 | +# you may not use this file except in compliance with the License. | ||
| 8 | +# You may obtain a copy of the License at | ||
| 9 | +# | ||
| 10 | +# http://www.apache.org/licenses/LICENSE-2.0 | ||
| 11 | +# | ||
| 12 | +# Unless required by applicable law or agreed to in writing, software | ||
| 13 | +# distributed under the License is distributed on an "AS IS" BASIS, | ||
| 14 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 15 | +# See the License for the specific language governing permissions and | ||
| 16 | +# limitations under the License. | ||
| 17 | +# ---------------------------------------------------------------------------- | ||
| 2 | """PreToolUse hook: 角色越界文件保护(analyzer/reviewer 不改 adapter/bit_config/CLI/算法)。amct 量化 agent。""" | 18 | """PreToolUse hook: 角色越界文件保护(analyzer/reviewer 不改 adapter/bit_config/CLI/算法)。amct 量化 agent。""" |
| 3 | 19 | ||
| 4 | import fnmatch | 20 | import fnmatch |
| @@ -1,11 +1,30 @@ | |||
| 1 | #!/usr/bin/env python3 | 1 | #!/usr/bin/env python3 |
| 2 | +# -*- coding: UTF-8 -*- | ||
| 3 | +# ---------------------------------------------------------------------------- | ||
| 4 | +# Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved. | ||
| 5 | +# | ||
| 6 | +# Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 7 | +# you may not use this file except in compliance with the License. | ||
| 8 | +# You may obtain a copy of the License at | ||
| 9 | +# | ||
| 10 | +# http://www.apache.org/licenses/LICENSE-2.0 | ||
| 11 | +# | ||
| 12 | +# Unless required by applicable law or agreed to in writing, software | ||
| 13 | +# distributed under the License is distributed on an "AS IS" BASIS, | ||
| 14 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 15 | +# See the License for the specific language governing permissions and | ||
| 16 | +# limitations under the License. | ||
| 17 | +# ---------------------------------------------------------------------------- | ||
| 2 | """SubagentStop hook: quant-implementer 自验证检查 + 外循环重试限制(amct 量化 agent)""" | 18 | """SubagentStop hook: quant-implementer 自验证检查 + 外循环重试限制(amct 量化 agent)""" |
| 3 | 19 | ||
F | |||
| 20 | +import glob | ||
| 4 | import json | 21 | import json |
| 5 | import logging | 22 | import logging |
| 6 | import os | 23 | import os |
| 7 | import re | 24 | import re |
| 8 | import sys | 25 | import sys |
| 26 | +import tempfile | ||
| 27 | +import time | ||
| 9 | 28 | ||
| 10 | logging.basicConfig(stream=sys.stderr, level=logging.WARNING, format="%(message)s") | 29 | logging.basicConfig(stream=sys.stderr, level=logging.WARNING, format="%(message)s") |
| 11 | logger = logging.getLogger(__name__) | 30 | logger = logging.getLogger(__name__) |
| @@ -26,6 +45,21 @@ RETRY_LIMIT_MSG = ("重试上限:当前阶段已执行 {n} 轮 implementer/rev | |||
| 26 | "请回退当前阶段改动,向用户报告阻塞点。") | 45 | "请回退当前阶段改动,向用户报告阻塞点。") |
| 27 | 46 | ||
| 28 | 47 | ||
| 48 | +COUNTER_TTL_SECONDS = 48 * 3600 | ||
| 49 | + | ||
| 50 | + | ||
| 51 | +def cleanup_stale_counters(): | ||
| 52 | + """删除临时目录下超过 48 小时的 hook_retry_*.count 文件(懒清理,静默失败)。""" | ||
| 53 | + cutoff = time.time() - COUNTER_TTL_SECONDS | ||
| 54 | + pattern = os.path.join(tempfile.gettempdir(), "hook_retry_*.count") | ||
| 55 | + for path in glob.glob(pattern): | ||
| 56 | + try: | ||
| 57 | + if os.path.getmtime(path) < cutoff: | ||
| 58 | + os.remove(path) | ||
| 59 | + except OSError: | ||
| 60 | + pass | ||
| 61 | + | ||
| 62 | + | ||
| 29 | def find_progress_md(cwd): | 63 | def find_progress_md(cwd): |
| 30 | candidates = [] | 64 | candidates = [] |
| 31 | try: | 65 | try: |
| @@ -80,7 +114,7 @@ def check_retry_limit(data, content): | |||
| 80 | # 无 session_id:跳过计数,不退化到共享 "unknown" key | 114 | # 无 session_id:跳过计数,不退化到共享 "unknown" key |
| 81 | # (否则不同会话/任务的重试计数互相累加,误触发上限阻断) | 115 | # (否则不同会话/任务的重试计数互相累加,误触发上限阻断) |
| 82 | return None | 116 | return None |
| 83 | - counter_file = f"/tmp/hook_retry_{session_id}_{stage}.count" | 117 | + counter_file = os.path.join(tempfile.gettempdir(), f"hook_retry_{session_id}_{stage}.count") |
| 84 | # flock 保护读-改-写原子性(防极端并发下计数丢失) | 118 | # flock 保护读-改-写原子性(防极端并发下计数丢失) |
| 85 | with open(counter_file, "a+") as f: | 119 | with open(counter_file, "a+") as f: |
| 86 | fcntl.flock(f, fcntl.LOCK_EX) | 120 | fcntl.flock(f, fcntl.LOCK_EX) |
| @@ -100,6 +134,7 @@ def check_retry_limit(data, content): | |||
| 100 | 134 | ||
| 101 | 135 | ||
| 102 | def main(): | 136 | def main(): |
| 137 | + cleanup_stale_counters() | ||
| 103 | data = json.load(sys.stdin) | 138 | data = json.load(sys.stdin) |
| 104 | cwd = data.get("cwd", ".") | 139 | cwd = data.get("cwd", ".") |
| 105 | progress_path = find_progress_md(cwd) | 140 | progress_path = find_progress_md(cwd) |
| @@ -1,13 +1,22 @@ | |||
| 1 | --- | 1 | --- |
| 2 | name: default-skills | 2 | name: default-skills |
| 3 | description: | | 3 | description: | |
| 4 | - **必须触发此 default-skills 的场景**(用户提到以下任何内容时使用):找不到/缺失/安装/更新 gitcode-pr, gitcode-issue skill时,或者安装必备/默认/必要/必须skills时; | 4 | + **必须触发此 default-skills 的场景**:① gitcode-pr 或 gitcode-issue skill 缺失/找不到时(补装缺失,不覆盖已有版本);② 用户明确要求更新/同步上游 skill 时(使用 --force 覆盖); |
| 5 | --- | 5 | --- |
| 6 | 6 | ||
| 7 | -## 安装默认skills步骤 | 7 | +## 执行步骤 |
| 8 | -1. 读取`.claude/skills/default-skills/scripts/install-default-skills.sh` 获取 `DEFAULT_SKILLS` | 8 | + |
| 9 | -2. 首先尝试使用 `.claude/skills/default-skills/scripts/install-default-skills.sh` 安装或更新skills,执行后检查 `.claude/skills/`目录有没有`DEFAULT_SKILLS`,如果有立即结束;如果没有,继续下一步 | 9 | +**第一步(必须)**:读取 `.claude/skills/default-skills/scripts/install-default-skills.sh` 获取 `DEFAULT_SKILLS` 列表 |
| 10 | -3. 使用git克隆`https://gitcode.com/cann-agent/skills.git` 到临时目录,要使用`--depth 1`参数,该仓下找到`DEFAULT_SKILLS`,拷贝到`.claude/skills/`目录下 | 10 | + |
| 11 | +**场景一:补装缺失(默认)** | ||
| 12 | +1. 执行 `.claude/skills/default-skills/scripts/install-default-skills.sh`(已存在的 skill 自动跳过) | ||
| 13 | +2. 检查 `.claude/skills/` 目录是否已有所有 `DEFAULT_SKILLS`,有则结束;若脚本执行失败,执行步骤 3 | ||
| 14 | +3. 兜底(脚本失败时手动复刻,与脚本逻辑等价):`git clone --depth 1 https://gitcode.com/cann-agent/skills.git` 到临时目录,将缺失的 `DEFAULT_SKILLS` 拷贝到 `.claude/skills/` | ||
| 15 | + | ||
| 16 | +**场景二:强制更新(用户明确要求更新/同步上游时)** | ||
| 17 | +1. 执行 `.claude/skills/default-skills/scripts/install-default-skills.sh --force`(从上游覆盖所有 skill) | ||
| 18 | +2. 若脚本失败,同场景一步骤 3 手动兜底(不做存在性检查,直接覆盖) | ||
| 19 | +3. 提示用户:本地对这些 skill 的定制改动已被上游版本覆盖 | ||
| 11 | 20 | ||
| 12 | ## 默认skills使用场景 | 21 | ## 默认skills使用场景 |
| 13 | 1. **必须触发 gitcode-issue 的场景**(用户提到以下任何内容时使用): | 22 | 1. **必须触发 gitcode-issue 的场景**(用户提到以下任何内容时使用): |
| @@ -16,19 +16,23 @@ | |||
| 16 | # ---------------------------------------------------------------------------- | 16 | # ---------------------------------------------------------------------------- |
| 17 | set -e | 17 | set -e |
| 18 | 18 | ||
| 19 | -# 脚本功能:安装项目必备的 skills | 19 | +# 脚本功能:补装或强制更新项目必备的 skills |
| 20 | -# 默认技能技能列表 | 20 | +# 用法:install-default-skills.sh [--force] |
| 21 | +# 默认:仅补装缺失的 skill,已存在的跳过 | ||
| 22 | +# --force:从上游强制覆盖所有 skill(用于主动更新) | ||
| 21 | DEFAULT_SKILLS=("gitcode-pr" "gitcode-issue") | 23 | DEFAULT_SKILLS=("gitcode-pr" "gitcode-issue") |
| 22 | 24 | ||
| 23 | -# 脚本所在目录的上上级目录为 .claude/skills/ | 25 | +FORCE=false |
| 26 | +for arg in "$@"; do | ||
| 27 | + [ "$arg" = "--force" ] && FORCE=true | ||
| 28 | +done | ||
| 29 | + | ||
| 24 | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | 30 | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" |
| 25 | SKILLS_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)" | 31 | SKILLS_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)" |
| 26 | 32 | ||
| 27 | -# 创建临时目录 | ||
| 28 | TEMP_DIR=$(mktemp -d) | 33 | TEMP_DIR=$(mktemp -d) |
| 29 | trap 'rm -rf "$TEMP_DIR"' EXIT | 34 | trap 'rm -rf "$TEMP_DIR"' EXIT |
| 30 | 35 | ||
| 31 | -# 克隆 skills 仓库 | ||
| 32 | echo "Cloning skills repository..." | 36 | echo "Cloning skills repository..." |
| 33 | git clone --depth 1 https://gitcode.com/cann-agent/skills.git "$TEMP_DIR/skills" | 37 | git clone --depth 1 https://gitcode.com/cann-agent/skills.git "$TEMP_DIR/skills" |
| 34 | if [ $? -ne 0 ]; then | 38 | if [ $? -ne 0 ]; then |
| @@ -36,21 +40,31 @@ if [ $? -ne 0 ]; then | |||
| 36 | exit 1 | 40 | exit 1 |
| 37 | fi | 41 | fi |
| 38 | 42 | ||
| 39 | -# 检查 skills 目录是否存在 | ||
| 40 | if [ ! -d "$TEMP_DIR/skills/skills" ]; then | 43 | if [ ! -d "$TEMP_DIR/skills/skills" ]; then |
| 41 | echo "Error: skills directory not found in repository" | 44 | echo "Error: skills directory not found in repository" |
| 42 | exit 1 | 45 | exit 1 |
| 43 | fi | 46 | fi |
| 44 | 47 | ||
| 45 | -# 拷贝技能到 .claude/skills/ 目录 | 48 | +installed=0 |
| 46 | -echo "Installing skills..." | 49 | +skipped=0 |
| 47 | for skill in "${DEFAULT_SKILLS[@]}"; do | 50 | for skill in "${DEFAULT_SKILLS[@]}"; do |
| 51 | + if [ -d "$SKILLS_DIR/$skill" ] && [ "$FORCE" = false ]; then | ||
| 52 | + echo "Skipped (already exists): $skill" | ||
| 53 | + skipped=$((skipped + 1)) | ||
| 54 | + continue | ||
| 55 | + fi | ||
| 48 | if [ -d "$TEMP_DIR/skills/skills/$skill" ]; then | 56 | if [ -d "$TEMP_DIR/skills/skills/$skill" ]; then |
| 57 | + rm -rf "$SKILLS_DIR/$skill" | ||
| 49 | cp -r "$TEMP_DIR/skills/skills/$skill" "$SKILLS_DIR/" | 58 | cp -r "$TEMP_DIR/skills/skills/$skill" "$SKILLS_DIR/" |
| 50 | echo "Installed skill: $skill" | 59 | echo "Installed skill: $skill" |
| 60 | + installed=$((installed + 1)) | ||
| 51 | else | 61 | else |
| 52 | echo "Warning: Skill '$skill' not found in repository" | 62 | echo "Warning: Skill '$skill' not found in repository" |
| 53 | fi | 63 | fi |
| 54 | done | 64 | done |
| 55 | 65 | ||
| 56 | -echo "All skills installed successfully." | 66 | +if [ "$installed" -eq 0 ]; then |
| 67 | + echo "All skills already present, nothing to install. Use --force to update." | ||
| 68 | +else | ||
| 69 | + echo "$installed skill(s) installed, $skipped skipped." | ||
| 70 | +fi | ||
| @@ -35,7 +35,3 @@ tmp/ | |||
| 35 | **/.claude/settings.local.json | 35 | **/.claude/settings.local.json |
| 36 | **/.claude/scheduled_tasks.lock | 36 | **/.claude/scheduled_tasks.lock |
| 37 | 37 | ||
| 38 | -# Generated agent views (source of truth: .agents/) | ||
| 39 | -/.claude/ | ||
| 40 | -/.opencode/ | ||
| 41 | -/CLAUDE.md | ||
| @@ -13,6 +13,10 @@ AMCT(Ascend Model Compression Toolkit)是一款昇腾 AI 处理器亲和的 | |||
| 13 | - **NPU 算子**:量化相关的昇腾 NPU 算子实现 | 13 | - **NPU 算子**:量化相关的昇腾 NPU 算子实现 |
| 14 | - **试验特性**:DeepSeekV3.2/V4 等前沿模型的量化支持 | 14 | - **试验特性**:DeepSeekV3.2/V4 等前沿模型的量化支持 |
| 15 | 15 | ||
| 16 | +## Agent Skills | ||
| 17 | + | ||
| 18 | +本仓内置 Agent Skills 基础设施(`.agents/`,经 git-tracked symlink 自动投影到各 AI 客户端,clone 即可用):以 skill 为单元封装特定领域能力,自然语言触发、agent 自主执行。当前内置 **quant-workflow**(LLM 量化全流程编排主入口)、**amct-ops-dev**(NPU 算子开发)与 `gitcode-pr`/`gitcode-issue`(仓库协作操作)等技能,后续按需扩充。详见 [.agents/README.md](.agents/README.md)(快速开始)与 [.agents/docs/architecture.md](.agents/docs/architecture.md)(架构设计)。 | ||
| 19 | + | ||
| 16 | ## 构建命令 | 20 | ## 构建命令 |
| 17 | 21 | ||
| 18 | ### 基础构建 | 22 | ### 基础构建 |
| @@ -110,7 +114,10 @@ python3 -c "import amct_pytorch as amct; print('successfully installed AMCT')" | |||
| 110 | ## 开发规范 | 114 | ## 开发规范 |
| 111 | 115 | ||
| 112 | ### gitcode pr/issue 操作 | 116 | ### gitcode pr/issue 操作 |
| 113 | -@.claude/skills/default-skills/SKILL.md | 117 | +@.claude/skills/gitcode-pr/SKILL.md |
| 118 | +@.claude/skills/gitcode-issue/SKILL.md | ||
| 119 | + | ||
| 120 | +若以上 skill 缺失,按 @.claude/skills/default-skills/SKILL.md 自动安装。 | ||
| 114 | 121 | ||
| 115 | ### 代码风格 | 122 | ### 代码风格 |
| 116 | - 遵循 Google 开源代码规范(基于 `.clang-format`) | 123 | - 遵循 Google 开源代码规范(基于 `.clang-format`) |
Dscripts/init-agent.sh+0-115
| @@ -1,115 +0,0 @@ | |||
| 1 | -#!/usr/bin/env bash | ||
| 2 | -# ---------------------------------------------------------------------------- | ||
| 3 | -# Copyright (c) Huawei Technologies Co., Ltd. 2025-2026. All rights reserved. | ||
| 4 | -# | ||
| 5 | -# Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 6 | -# you may not use this file except in compliance with the License. | ||
| 7 | -# You may obtain a copy of the License at | ||
| 8 | -# | ||
| 9 | -# http://www.apache.org/licenses/LICENSE-2.0 | ||
| 10 | -# | ||
| 11 | -# Unless required by applicable law or agreed to in writing, software | ||
| 12 | -# distributed under the License is distributed on an "AS IS" BASIS, | ||
| 13 | -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 14 | -# See the License for the specific language governing permissions and | ||
| 15 | -# limitations under the License. | ||
| 16 | -# ---------------------------------------------------------------------------- | ||
| 17 | -# init-agent.sh - Install amct_llm quant Agent Skills into Claude Code and/or OpenCode. | ||
| 18 | -# | ||
| 19 | -# Source of truth: .agents/ | ||
| 20 | -# .agents/skills/ - skill directories | ||
| 21 | -# .agents/agents/ - subagent markdown files | ||
| 22 | -# .agents/hooks/ - Claude Code hook scripts | ||
| 23 | -# .agents/settings.json - Claude Code settings (permissions + hook registration) | ||
| 24 | -# | ||
| 25 | -# Generated (gitignored): | ||
| 26 | -# .claude/{skills,agents,hooks,docs,settings.json} - Claude Code view | ||
| 27 | -# .opencode/{skills,agents,docs} - OpenCode view | ||
| 28 | -# ({claude,opencode}/docs symlink .agents/docs so skill→doc relative links resolve in both views) | ||
| 29 | -# CLAUDE.md -> AGENTS.md - Claude Code entry | ||
| 30 | -# | ||
| 31 | -# Usage: | ||
| 32 | -# bash scripts/init-agent.sh # both platforms (default) | ||
| 33 | -# bash scripts/init-agent.sh --claude # Claude Code only | ||
| 34 | -# bash scripts/init-agent.sh --opencode # OpenCode only | ||
| 35 | - | ||
| 36 | -set -euo pipefail | ||
| 37 | - | ||
| 38 | -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| 39 | -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" | ||
| 40 | -SRC="$REPO_ROOT/.agents" | ||
| 41 | - | ||
| 42 | -if [ ! -d "$SRC" ]; then | ||
| 43 | - echo "Error: source dir $SRC not found." >&2 | ||
| 44 | - exit 1 | ||
| 45 | -fi | ||
| 46 | - | ||
| 47 | -arg="${1:-}" | ||
| 48 | -case "$arg" in | ||
| 49 | - ""|--both|--all) target="both" ;; | ||
| 50 | - --claude) target="claude" ;; | ||
| 51 | - --opencode) target="opencode" ;; | ||
| 52 | - -h|--help) | ||
| 53 | - sed -n '2,21p' "$0" | sed 's/^# \{0,1\}//' | ||
| 54 | - exit 0 ;; | ||
| 55 | - *) | ||
| 56 | - echo "Unknown argument: $arg" >&2 | ||
| 57 | - echo "Usage: $0 [--claude|--opencode]" >&2 | ||
| 58 | - exit 1 ;; | ||
| 59 | -esac | ||
| 60 | - | ||
| 61 | -link_children() { | ||
| 62 | - # Create child symlinks in $2 for every entry in $1 (absolute paths). | ||
| 63 | - local src="$1" dst="$2" | ||
| 64 | - [ -d "$src" ] || return 0 | ||
| 65 | - mkdir -p "$dst" | ||
| 66 | - # Prune stale symlinks whose source entry no longer exists (renamed/removed skill etc.) | ||
| 67 | - for existing in "$dst"/*; do | ||
| 68 | - [ -L "$existing" ] || continue | ||
| 69 | - [ -e "$src/$(basename "$existing")" ] || { echo " - $existing pruned (source removed)" >&2; rm -f "$existing"; } | ||
| 70 | - done | ||
| 71 | - for entry in "$src"/*; do | ||
| 72 | - [ -e "$entry" ] || continue | ||
| 73 | - local target="$dst/$(basename "$entry")" | ||
| 74 | - if [ -e "$target" ] && [ ! -L "$target" ]; then | ||
| 75 | - # Non-symlink at a generated-view target: views are fully regenerable, | ||
| 76 | - # so warn loudly and replace (not silent, no .bak clutter). | ||
| 77 | - echo " ! $target was not a symlink; replaced (views are generated)" >&2 | ||
| 78 | - rm -rf "$target" | ||
| 79 | - fi | ||
| 80 | - ln -sfn "$(realpath "$entry")" "$target" | ||
| 81 | - done | ||
| 82 | -} | ||
| 83 | - | ||
| 84 | -install_claude() { | ||
| 85 | - local base="$REPO_ROOT/.claude" | ||
| 86 | - echo "Installing Claude Code -> $base/" | ||
| 87 | - link_children "$SRC/skills" "$base/skills" | ||
| 88 | - link_children "$SRC/agents" "$base/agents" | ||
| 89 | - link_children "$SRC/hooks" "$base/hooks" | ||
| 90 | - [ -d "$SRC/docs" ] && ln -sfn "$(realpath "$SRC/docs")" "$base/docs" | ||
| 91 | - if [ -f "$SRC/settings.json" ]; then | ||
| 92 | - cp "$SRC/settings.json" "$base/settings.json" | ||
| 93 | - fi | ||
| 94 | - ln -sfn AGENTS.md "$REPO_ROOT/CLAUDE.md" | ||
| 95 | - echo " + $base/{skills,agents,hooks,docs,settings.json}" | ||
| 96 | - echo " + $REPO_ROOT/CLAUDE.md -> AGENTS.md" | ||
| 97 | -} | ||
| 98 | - | ||
| 99 | -install_opencode() { | ||
| 100 | - local base="$REPO_ROOT/.opencode" | ||
| 101 | - echo "Installing OpenCode -> $base/" | ||
| 102 | - link_children "$SRC/skills" "$base/skills" | ||
| 103 | - link_children "$SRC/agents" "$base/agents" | ||
| 104 | - [ -d "$SRC/docs" ] && ln -sfn "$(realpath "$SRC/docs")" "$base/docs" | ||
| 105 | - [ -f "$SRC/opencode.json" ] && cp "$SRC/opencode.json" "$base/opencode.json" | ||
| 106 | - echo " + $base/{skills,agents,docs,opencode.json}" | ||
| 107 | -} | ||
| 108 | - | ||
| 109 | -case "$target" in | ||
| 110 | - claude) install_claude ;; | ||
| 111 | - opencode) install_opencode ;; | ||
| 112 | - both) install_claude; install_opencode ;; | ||
| 113 | -esac | ||
| 114 | - | ||
| 115 | -echo "Done." | ||


加下版权声明和UTF-8编码