helloagents 3.0.29 → 3.0.31
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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +34 -34
- package/README_CN.md +36 -34
- package/bootstrap-lite.md +20 -20
- package/bootstrap.md +23 -21
- package/gemini-extension.json +1 -1
- package/install.ps1 +2 -2
- package/install.sh +2 -2
- package/package.json +1 -1
- package/scripts/cli-branch.mjs +7 -3
- package/scripts/cli-codex.mjs +6 -5
- package/scripts/cli-config.mjs +8 -0
- package/scripts/cli-doctor-codex.mjs +10 -5
- package/scripts/cli-doctor-render.mjs +16 -0
- package/scripts/cli-doctor.mjs +2 -3
- package/scripts/cli-lifecycle-hosts.mjs +6 -1
- package/scripts/cli-lifecycle.mjs +16 -2
- package/scripts/cli-messages.mjs +8 -7
- package/scripts/cli-runtime-carrier.mjs +3 -3
- package/scripts/cli-utils.mjs +9 -0
- package/scripts/guard.mjs +1 -1
- package/scripts/notify-context.mjs +1 -1
- package/scripts/notify-route.mjs +3 -4
- package/scripts/notify.mjs +6 -1
- package/scripts/project-storage.mjs +4 -4
- package/scripts/replay-state.mjs +22 -4
- package/scripts/runtime-context.mjs +14 -2
- package/scripts/runtime-scope.mjs +144 -2
- package/scripts/session-capsule.mjs +14 -0
- package/scripts/turn-state.mjs +7 -0
- package/scripts/turn-stop-gate.mjs +5 -5
- package/skills/commands/auto/SKILL.md +2 -2
- package/skills/commands/build/SKILL.md +4 -4
- package/skills/commands/commit/SKILL.md +2 -2
- package/skills/commands/global/SKILL.md +71 -0
- package/skills/commands/help/SKILL.md +8 -7
- package/skills/commands/init/SKILL.md +14 -31
- package/skills/commands/loop/SKILL.md +1 -1
- package/skills/commands/plan/SKILL.md +1 -1
- package/skills/commands/prd/SKILL.md +1 -1
- package/skills/commands/test/SKILL.md +1 -1
- package/skills/commands/verify/SKILL.md +5 -5
- package/skills/commands/wiki/SKILL.md +1 -1
- package/skills/hello-review/SKILL.md +1 -1
- package/skills/hello-subagent/SKILL.md +1 -1
- package/skills/hello-ui/SKILL.md +6 -6
- package/skills/hello-verify/SKILL.md +7 -7
- package/skills/helloagents/SKILL.md +9 -8
package/bootstrap.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
配置文件: ~/.helloagents/helloagents.json
|
|
7
7
|
`output_language` 非空时,所有用户可见文本使用该语言;为空则跟随用户当前语言。
|
|
8
8
|
会话级缓存优先:当前上下文已有"当前用户设置"、原始 JSON 或读取摘要,且覆盖所需配置项时,直接复用。
|
|
9
|
-
|
|
9
|
+
仅在缺少所需项、用户要求刷新,或本次修改后需要核验时读取;对 Codex 来说,首次对话前若当前上下文仍缺少所需配置项,必须先读取一次 `~/.helloagents/helloagents.json`,压缩/恢复后的首次对话同样先重读一次;输出格式只在缺少 `output_format` 已知值时触发读取。
|
|
10
10
|
同一会话内,同一路径的配置文件、模块、SKILL、模板只读一次并跨轮复用;读取失败必须明示,并按默认值或已知设置执行。
|
|
11
11
|
|
|
12
12
|
## 通用交付规则(强制)
|
|
@@ -107,8 +107,8 @@
|
|
|
107
107
|
## 交互、停顿与收尾
|
|
108
108
|
### 输出格式
|
|
109
109
|
适用条件:
|
|
110
|
-
- 当 `helloagents.json` 的 `output_format` 为 `true`
|
|
111
|
-
- 若某个 skill
|
|
110
|
+
- 当 `helloagents.json` 的 `output_format` 为 `true` 时,主代理必须在每轮对话最后一条、且确认**不再继续调用工具、不再继续执行**的**最终回复**中使用输出格式。
|
|
111
|
+
- 若某个 skill 在当前对话明确要求输出停顿、确认或总结,也仅当该消息同时是**当前对话的最终回复**时,才可使用输出格式。
|
|
112
112
|
|
|
113
113
|
排除条件:
|
|
114
114
|
- 当 `output_format` 为 `false` 时,所有回复保持自然输出,不得使用输出格式。
|
|
@@ -126,16 +126,16 @@
|
|
|
126
126
|
图标:💡直接响应(一次性答复 / 只读分析) | ⚡快速执行(低风险直接执行) | 🔵规划流程(方案 / 规划产出) | ✅完成(已完成且无待确认动作) | ❓等待输入(等待用户输入 / 授权) | ⚠️警告(存在重要风险或限制) | ❌错误(发生错误或已阻塞)
|
|
127
127
|
|
|
128
128
|
使用约束:
|
|
129
|
-
- 首行必须保留 `【HelloAGENTS】` 和连字符 `-`,不得省略;状态图标与收尾内容必须一致。正文仍在等待用户输入、确认、授权或补充信息(含确认是否执行已给出的方案或修改)时,只能使用
|
|
129
|
+
- 首行必须保留 `【HelloAGENTS】` 和连字符 `-`,不得省略;状态图标与收尾内容必须一致。正文仍在等待用户输入、确认、授权或补充信息(含确认是否执行已给出的方案或修改)时,只能使用 `❓等待输入`;仅在当前对话执行已完成且不存在待确认动作时,才能使用 `✅完成`。同一条最终回复只使用一次该格式;若主体需要分段,在同一个外层块内分节,不得在正文中再次输出 `【HelloAGENTS】` 或第二个 `🔄 下一步`。
|
|
130
130
|
- `🔄 下一步` 必须写真正的下一步动作,不写单纯当前状态或条件式能力表述。若正在等待确认,写清待确认动作;若仍有已授权且可继续执行的动作,不得收尾,必须继续执行;若当前任务已完整结束且确无合理后续,可明确写出任务已结束、无后续动作,不补条件式邀约。
|
|
131
131
|
|
|
132
132
|
### 收尾状态信号
|
|
133
|
-
- `turn-state`
|
|
134
|
-
- 必须调用场景:显式 `~auto` / `~loop
|
|
133
|
+
- `turn-state` 只在运行时必须识别当前对话“完成 / 等待输入 / 阻塞”时写入;普通问候、普通问答、T0 只读分析和一次性解释不调用
|
|
134
|
+
- 必须调用场景:显式 `~auto` / `~loop`;非只读任务完成验证并进入收尾;需要让运行时识别当前对话已完成、等待输入或已阻塞时;已进入项目连续流程或方案包闭环
|
|
135
135
|
- 首选参数式调用,保证一次完成:`helloagents-turn-state write --kind complete --role main`;也可用 stdin JSON。不要查找、读取或拼接 `turn-state.mjs` 源码路径
|
|
136
|
-
-
|
|
136
|
+
- 当前对话已完成且不再等待用户输入 → `helloagents-turn-state write --kind complete --role main`
|
|
137
137
|
- 因阻塞判定等待用户输入、确认、授权或补充信息(含未授权的外部副作用确认) → 写 `kind=waiting`、`role=main`,并同时写 `reasonCategory` 与 `reason`
|
|
138
|
-
-
|
|
138
|
+
- 因错误、缺少前置条件或外部依赖而当前对话停下 → 写 `kind=blocked`、`role=main`,并同时写 `reasonCategory` 与 `reason`
|
|
139
139
|
- `reasonCategory` 只允许:`ambiguity`、`missing-input`、`missing-file`、`missing-credential`、`unauthorized-side-effect`、`high-risk-confirmation`、`external-dependency`、`error`
|
|
140
140
|
- 显式 `~auto` / `~loop` 下,`waiting` / `blocked` 还必须写入 `blocker.target`、`blocker.evidence`、`blocker.requiredAction`;阶段汇报、单轮探测完成、路线调整或“下一步建议”不构成停下理由
|
|
141
141
|
- 子代理不得写 turn-state;子代理结束只直接返回结果,不为主代理代写完成态
|
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
以下情况才构成中途停下并请求用户输入的正当理由:
|
|
174
174
|
- 需求存在影响执行结果的真实歧义
|
|
175
175
|
- 缺少继续执行所必需的信息、文件、路径或凭据
|
|
176
|
-
-
|
|
176
|
+
- 将产生外部副作用,但当前任务尚未获得对应授权(含等待确认是否实施已给方案)
|
|
177
177
|
- 操作属于高风险或不可逆,按安全规则必须确认
|
|
178
178
|
除上述情况外,默认继续执行。
|
|
179
179
|
|
|
@@ -209,7 +209,7 @@
|
|
|
209
209
|
- 审查 / 执行验证 → `~verify`
|
|
210
210
|
- 不确定或希望端到端自动推进时使用 `~auto`
|
|
211
211
|
|
|
212
|
-
|
|
212
|
+
当前项目只要已初始化(例如执行过 `~global`,或当前项目级规则文件已包含 `<!-- HELLOAGENTS_PROFILE: full -->`),就按项目级完整流程执行。
|
|
213
213
|
|
|
214
214
|
#### 2. SPEC — 澄清目标与验收
|
|
215
215
|
根据任务需要,按需读取项目上下文(知识库文件和项目文件),明确:
|
|
@@ -221,13 +221,13 @@
|
|
|
221
221
|
|
|
222
222
|
#### 3. PLAN — 规划与上下文准备
|
|
223
223
|
根据 skills/ 目录下各 hello-* 技能的 SKILL.md frontmatter(name + description),标记本次任务可能需要的技能(不读取文件内容,仅记录名称)。
|
|
224
|
-
路径定义:`{HELLOAGENTS_READ_ROOT}` =
|
|
224
|
+
路径定义:`{HELLOAGENTS_READ_ROOT}` = 当前对话已确定的 HelloAGENTS 读取根目录,统一用于读取 `skills/` 与 `templates/`
|
|
225
225
|
先确定当前技能根目录:
|
|
226
|
-
-
|
|
226
|
+
- 优先使用当前上下文中已注入的“当前对话 HelloAGENTS 读取根目录”
|
|
227
227
|
- 若当前上下文未注入,则使用稳定运行根目录 `~/.helloagents/helloagents`
|
|
228
228
|
- 宿主固定链接(Codex `~/.codex/helloagents`、Claude `~/.claude/helloagents`、Gemini `~/.gemini/helloagents`)只作为兼容别名,不作为优先探测路径
|
|
229
229
|
- 仍无法确定时,明确说明缺少 HelloAGENTS 读取根目录;不要递归扫描 `$HOME`、`Downloads`、项目目录或旧版本目录
|
|
230
|
-
-
|
|
230
|
+
- 全局模式或已初始化项目时,技能是否需要使用由当前已加载 AGENTS 规则决定;不要因此额外探测项目目录里的 HelloAGENTS skills 路径
|
|
231
231
|
路径确定一次即可,不预读、不扫描整个目录,也不重复探测同一路径。
|
|
232
232
|
hello-* 技能读取路径:`{HELLOAGENTS_READ_ROOT}/skills/{技能名}/SKILL.md`
|
|
233
233
|
包内脚本优先使用稳定命令入口;涉及 turn-state 时按“收尾状态信号”执行。
|
|
@@ -265,12 +265,14 @@ hello-* 技能读取路径:`{HELLOAGENTS_READ_ROOT}/skills/{技能名}/SKILL.m
|
|
|
265
265
|
- 有方案包且准备报告完成 → 优先调用 `scripts/closeout-state.mjs write` 写当前会话 `artifacts/closeout.json`,记录“需求覆盖”和“交付清单”;每项写明 `PASS` / `BLOCKED` 与简要摘要,再进入最终交付
|
|
266
266
|
- 状态文件维护:按上文“流程状态”中的适用范围执行。属于“强制创建并持续更新”范围时,重写 `state_path` 指向的文件(“正在做什么”更新为已完成,清空关键上下文 / 下一步 / 阻塞项);属于“已有则更新”范围时,仅在文件已存在时重写;属于“不创建”范围时不生成此文件
|
|
267
267
|
- 有方案包且任务已完成 → 将整个 `plans/{feature}/` 目录归档到 `.helloagents/archive/YYYY-MM/`,并更新 `archive/_index.md`。清理当前会话临时文件(`artifacts/loop-results.tsv`、`capsule.json`、`events.jsonl`、`artifacts/loop-breaker.json`、`artifacts/verify.json`、`artifacts/review.json`、`artifacts/closeout.json`)
|
|
268
|
-
- 按 `kb_create_mode` 同步知识库(0=关闭 / 1
|
|
269
|
-
-
|
|
268
|
+
- 按 `kb_create_mode` 同步知识库(0=关闭 / 1=知识库已存在时自动同步,未创建则不自动补建 / 2=编码任务在知识库已存在或全局模式下自动创建或同步):
|
|
269
|
+
- `0` → 跳过
|
|
270
|
+
- `1` → 仅在知识库已存在时按模板增量同步;未创建则不自动补建
|
|
271
|
+
- `2` → 仅在编码任务中生效;知识库已存在时按模板增量同步;若知识库不存在但当前项目已处于全局模式,则按 templates/ 创建或补全 `context.md`、`guidelines.md`、`verify.yaml`、`CHANGELOG.md`、`modules/`
|
|
270
272
|
- 已存在但不完整(缺少上述核心文件)→ 按 templates/ 补全缺失文件,不覆盖已有文件
|
|
271
273
|
- 已存在且完整则按模板格式更新 `CHANGELOG.md`、相关 `modules/*.md`、增量经验 delta 追加
|
|
272
274
|
- 符合条件时触发 `hello-reflect`(详见 `hello-reflect` SKILL.md)
|
|
273
|
-
- 本地版本检查点:非只读任务完成验证且产生工作区变更时,若 `auto_commit_enabled=true
|
|
275
|
+
- 本地版本检查点:非只读任务完成验证且产生工作区变更时,若 `auto_commit_enabled=true`,最终回复前自动执行本地提交;若 `auto_commit_enabled=false`,跳过这一步。先检查 `git status --short`;若不是 git 仓库或无变更则跳过。若发现 `.env`、密钥、凭据、明显不应提交的大文件或二进制产物,停止提交并说明风险;否则执行 `git add -A`,使用当前回复语言生成简洁 conventional commit message 后执行 `git commit`。显式 `~commit` 不受这个开关影响。不自动远程 `git push`,除非用户明确要求
|
|
274
276
|
|
|
275
277
|
### 完成判定
|
|
276
278
|
- 未进入 VERIFY / CONSOLIDATE 的路径,声称完成前必须完成与任务类型匹配的必要检查;无法执行的检查必须明确说明,不得直接宣称完成
|
|
@@ -287,19 +289,19 @@ hello-* 技能读取路径:`{HELLOAGENTS_READ_ROOT}/skills/{技能名}/SKILL.m
|
|
|
287
289
|
### .helloagents/ 目录
|
|
288
290
|
路径: {CWD}/.helloagents/
|
|
289
291
|
所有文件的创建和更新必须按 templates/ 目录中对应模板的格式执行,不可自由发挥格式。
|
|
290
|
-
- `.helloagents/`
|
|
292
|
+
- `.helloagents/` 表示项目本地存储路径,负责知识、方案、状态与运行态;它不再作为项目是否已初始化的判定信号
|
|
291
293
|
- `state_path` 指向的状态文件、当前会话 `capsule.json`、`events.jsonl`、`artifacts/*.json`、`artifacts/loop-results.tsv` 等运行态文件始终保留在项目本地 `.helloagents/sessions/{workspace}/{session}/`
|
|
292
294
|
- `state_path` 是状态文件的唯一位置。宿主提供会话标识时,写入 `.helloagents/sessions/{workspace}/{session}/STATE.md`;没有稳定会话标识时,写入 `.helloagents/sessions/{workspace}/default/STATE.md`
|
|
293
295
|
- `{workspace}` 为当前 Git 分支、`detached-{sha}` 或非 Git 项目的 `workspace`;`.helloagents/sessions/active.json` 只记录当前活跃会话索引,避免同一会话被拆成多个目录
|
|
294
296
|
- 若 helloagents.json 中 `project_store_mode = "repo-shared"`,`context.md`、`guidelines.md`、`CHANGELOG.md`、`verify.yaml`、`DESIGN.md`、`modules/`、`plans/`、`archive/` 改按当前上下文中已注入的“当前项目存储”/“项目知识/方案目录”解析;未注入具体路径时,按当前存储模式自行解析,不要假定这些文件一定实际位于当前工作树中
|
|
295
|
-
templates/
|
|
297
|
+
templates/ 查找路径(按优先级;首次确定模板根目录后,本会话复用):
|
|
296
298
|
按上文相同的技能根目录规则确定;确定根目录后读取其中的 `templates/`。
|
|
297
299
|
|
|
298
300
|
### 流程状态(不受 `kb_create_mode` 控制,始终可写)
|
|
299
301
|
- 状态文件(`state_path`)— ≤70 行,用来记录“上次做到哪里”。判断当前任务时,当前用户消息、显式命令、活跃方案包 / PRD、代码与验证证据优先于状态文件
|
|
300
302
|
内容:主线目标、正在做什么、关键上下文(决策/变更/假设)、下一步(具体可执行动作含文件路径)、阻塞项
|
|
301
303
|
适用边界:
|
|
302
|
-
- 强制创建并持续更新:`~wiki`、`~init`、`~plan`、`~build`、`~auto`、`~prd`、`~loop
|
|
304
|
+
- 强制创建并持续更新:`~wiki`、`~init`、`~global`、`~plan`、`~build`、`~auto`、`~prd`、`~loop`,以及进入工作流阶段、已初始化项目的连续任务,或任何会创建/修改本地文件、会在当前工作区留下实际输出或操作记录的非只读任务
|
|
303
305
|
- 强制更新,不要求首次创建:`~clean`,主代理汇总子代理结果后
|
|
304
306
|
- 已有则更新:`~verify`、`~review`(兼容别名)、`~test`、`~commit`
|
|
305
307
|
- 不创建:`~help`、`~idea`、普通问答、一次性只读任务、子代理自身执行过程、压缩/恢复钩子
|
|
@@ -320,7 +322,7 @@ templates/ 查找路径(按优先级;首次确定模板根目录后,本轮
|
|
|
320
322
|
- archive/_index.md — 归档索引
|
|
321
323
|
|
|
322
324
|
### 知识记录(受 `kb_create_mode` 控制)
|
|
323
|
-
- 0=关闭;1
|
|
325
|
+
- 0=关闭;1=知识库已存在时自动同步;2=编码任务在知识库已存在或全局模式下自动创建或同步
|
|
324
326
|
- context.md — 项目架构、技术栈、目录结构、模块索引
|
|
325
327
|
- guidelines.md — 编码约定(仅含非显而易见的约定)
|
|
326
328
|
- CHANGELOG.md — 变更历史
|
|
@@ -335,7 +337,7 @@ templates/ 查找路径(按优先级;首次确定模板根目录后,本轮
|
|
|
335
337
|
- artifacts/closeout.json — 当前会话最近一次成功收尾的交付证据快照
|
|
336
338
|
|
|
337
339
|
### 主线判断依据
|
|
338
|
-
1. 当前用户最新消息、显式 `~command
|
|
340
|
+
1. 当前用户最新消息、显式 `~command`、当前对话已确认的范围与结论
|
|
339
341
|
2. 当前活跃方案包 / PRD、代码与验证证据
|
|
340
342
|
3. 当前状态文件(`state_path`,只用于补齐最近进度)
|
|
341
343
|
4. 其他知识记录与历史归档
|
package/gemini-extension.json
CHANGED
package/install.ps1
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# HELLOAGENTS_TARGET=all|claude|gemini|codex
|
|
7
7
|
# HELLOAGENTS_MODE=standby|global
|
|
8
8
|
# HELLOAGENTS_BRANCH=main|beta|...
|
|
9
|
-
# HELLOAGENTS_PACKAGE=helloagents|github
|
|
9
|
+
# HELLOAGENTS_PACKAGE=helloagents|https://github.com/owner/repo/archive/refs/heads/ref.tar.gz|...
|
|
10
10
|
|
|
11
11
|
$ErrorActionPreference = "Stop"
|
|
12
12
|
|
|
@@ -39,7 +39,7 @@ if ($Mode -and @("standby", "global") -notcontains $Mode) {
|
|
|
39
39
|
|
|
40
40
|
if (-not $Package) {
|
|
41
41
|
if ($Branch) {
|
|
42
|
-
$Package = "github
|
|
42
|
+
$Package = "https://github.com/hellowind777/helloagents/archive/refs/heads/$Branch.tar.gz"
|
|
43
43
|
} else {
|
|
44
44
|
$Package = "helloagents"
|
|
45
45
|
}
|
package/install.sh
CHANGED
|
@@ -9,7 +9,7 @@ set -eu
|
|
|
9
9
|
# HELLOAGENTS_TARGET=all|claude|gemini|codex
|
|
10
10
|
# HELLOAGENTS_MODE=standby|global
|
|
11
11
|
# HELLOAGENTS_BRANCH=main|beta|...
|
|
12
|
-
# HELLOAGENTS_PACKAGE=helloagents|github
|
|
12
|
+
# HELLOAGENTS_PACKAGE=helloagents|https://github.com/owner/repo/archive/refs/heads/ref.tar.gz|...
|
|
13
13
|
|
|
14
14
|
ACTION="${HELLOAGENTS_ACTION:-install}"
|
|
15
15
|
TARGET="${HELLOAGENTS_TARGET:-}"
|
|
@@ -49,7 +49,7 @@ fi
|
|
|
49
49
|
|
|
50
50
|
if [ -z "$PACKAGE" ]; then
|
|
51
51
|
if [ -n "$BRANCH" ]; then
|
|
52
|
-
PACKAGE="github
|
|
52
|
+
PACKAGE="https://github.com/hellowind777/helloagents/archive/refs/heads/$BRANCH.tar.gz"
|
|
53
53
|
else
|
|
54
54
|
PACKAGE="helloagents"
|
|
55
55
|
fi
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "helloagents",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.31",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "HelloAGENTS — The orchestration kernel that makes any AI CLI smarter. Adds intelligent routing, quality verification (Ralph Loop), safety guards, and notifications.",
|
|
6
6
|
"author": "HelloWind",
|
package/scripts/cli-branch.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { spawnSync } from 'node:child_process'
|
|
|
2
2
|
|
|
3
3
|
import { normalizeHost } from './cli-lifecycle.mjs'
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const DEFAULT_REPO_ARCHIVE_BASE = 'https://github.com/hellowind777/helloagents/archive/refs/heads'
|
|
6
6
|
|
|
7
7
|
function runCommand(command, args) {
|
|
8
8
|
const needsShell = process.platform === 'win32' && /\.cmd$/i.test(command)
|
|
@@ -19,6 +19,10 @@ function runCommand(command, args) {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
function getDefaultNpmCommand() {
|
|
23
|
+
return process.platform === 'win32' ? 'npm.cmd' : 'npm'
|
|
24
|
+
}
|
|
25
|
+
|
|
22
26
|
function parseModeFlag(args) {
|
|
23
27
|
const hasGlobal = args.includes('--global')
|
|
24
28
|
const hasStandby = args.includes('--standby')
|
|
@@ -56,7 +60,7 @@ function parseBranchArgs(args) {
|
|
|
56
60
|
|
|
57
61
|
function buildPackageSpec(ref) {
|
|
58
62
|
if (/^(github:|git\+|https?:|file:)/i.test(ref)) return ref
|
|
59
|
-
return `${
|
|
63
|
+
return `${DEFAULT_REPO_ARCHIVE_BASE}/${ref}.tar.gz`
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
function buildSyncArgs({ host, mode }) {
|
|
@@ -76,7 +80,7 @@ function buildSyncArgs({ host, mode }) {
|
|
|
76
80
|
|
|
77
81
|
export function runBranchSwitch(args, options = {}) {
|
|
78
82
|
const parsed = parseBranchArgs(args)
|
|
79
|
-
const npmCommand = options.npmCommand || process.env.HELLOAGENTS_NPM_CMD ||
|
|
83
|
+
const npmCommand = options.npmCommand || process.env.HELLOAGENTS_NPM_CMD || getDefaultNpmCommand()
|
|
80
84
|
|
|
81
85
|
const packageSpec = buildPackageSpec(parsed.branch)
|
|
82
86
|
runCommand(npmCommand, ['install', '-g', packageSpec])
|
package/scripts/cli-codex.mjs
CHANGED
|
@@ -121,17 +121,17 @@ function removeCodexMarketplaceEntry(marketplaceFile) {
|
|
|
121
121
|
return true;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
function injectCodexRuntimeCarrier(filePath, bootstrapPath, settings) {
|
|
124
|
+
function injectCodexRuntimeCarrier(filePath, bootstrapPath, settings, options = {}) {
|
|
125
125
|
const bootstrapContent = safeRead(bootstrapPath);
|
|
126
126
|
if (!bootstrapContent) return false;
|
|
127
|
-
injectMarkedContent(filePath, buildRuntimeCarrier(bootstrapContent, settings).trimEnd());
|
|
127
|
+
injectMarkedContent(filePath, buildRuntimeCarrier(bootstrapContent, settings, options).trimEnd());
|
|
128
128
|
return true;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
function writeCodexRuntimeCarrier(filePath, bootstrapPath, settings) {
|
|
131
|
+
function writeCodexRuntimeCarrier(filePath, bootstrapPath, settings, options = {}) {
|
|
132
132
|
const bootstrapContent = safeRead(bootstrapPath);
|
|
133
133
|
if (!bootstrapContent) return false;
|
|
134
|
-
safeWrite(filePath, buildRuntimeCarrier(bootstrapContent, settings));
|
|
134
|
+
safeWrite(filePath, buildRuntimeCarrier(bootstrapContent, settings, options));
|
|
135
135
|
return true;
|
|
136
136
|
}
|
|
137
137
|
|
|
@@ -298,9 +298,10 @@ export function installCodexGlobal(home, pkgRoot) {
|
|
|
298
298
|
join(pkgRoot, CODEX_RUNTIME_CARRIER),
|
|
299
299
|
join(pkgRoot, 'bootstrap.md'),
|
|
300
300
|
settings,
|
|
301
|
+
{ profile: 'full' },
|
|
301
302
|
);
|
|
302
303
|
const homeCarrierPath = join(codexDir, CODEX_RUNTIME_CARRIER);
|
|
303
|
-
injectCodexRuntimeCarrier(homeCarrierPath, join(pkgRoot, 'bootstrap.md'), settings);
|
|
304
|
+
injectCodexRuntimeCarrier(homeCarrierPath, join(pkgRoot, 'bootstrap.md'), settings, { profile: 'full' });
|
|
304
305
|
|
|
305
306
|
ensureDir(join(home, '.agents', 'plugins'));
|
|
306
307
|
updateCodexMarketplace(marketplaceFile);
|
package/scripts/cli-config.mjs
CHANGED
|
@@ -34,6 +34,14 @@ export function ensureConfig(helloagentsHome, configFile, safeJson, ensureDir) {
|
|
|
34
34
|
for (const [key, val] of Object.entries(DEFAULTS)) {
|
|
35
35
|
if (!(key in reconciled)) reconciled[key] = val;
|
|
36
36
|
}
|
|
37
|
+
if (!reconciled.host_install_modes || typeof reconciled.host_install_modes !== 'object' || Array.isArray(reconciled.host_install_modes)) {
|
|
38
|
+
reconciled.host_install_modes = {};
|
|
39
|
+
} else {
|
|
40
|
+
reconciled.host_install_modes = Object.fromEntries(
|
|
41
|
+
Object.entries(reconciled.host_install_modes)
|
|
42
|
+
.filter(([host, mode]) => ['claude', 'gemini', 'codex'].includes(host) && typeof mode === 'string' && mode),
|
|
43
|
+
);
|
|
44
|
+
}
|
|
37
45
|
if (JSON.stringify(reconciled) !== JSON.stringify(existing)) {
|
|
38
46
|
writeFileSync(configFile, JSON.stringify(reconciled, null, 2), 'utf-8');
|
|
39
47
|
}
|
|
@@ -64,9 +64,9 @@ function readExpectedHooks(runtime, hooksFile, pathVar) {
|
|
|
64
64
|
return pickManagedHooks(loadHooksWithCliEntry(runtime.pkgRoot, hooksFile, pathVar)?.hooks || {})
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
function readExpectedCarrierContent(runtime, fileName, settings) {
|
|
67
|
+
function readExpectedCarrierContent(runtime, fileName, settings, options = {}) {
|
|
68
68
|
const bootstrap = safeRead(join(runtime.pkgRoot, fileName)) || ''
|
|
69
|
-
return normalizeText(buildRuntimeCarrier(bootstrap, settings))
|
|
69
|
+
return normalizeText(buildRuntimeCarrier(bootstrap, settings, options))
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
function buildDoctorIssue(runtime, code, cn, en) {
|
|
@@ -168,7 +168,12 @@ function buildCodexChecks(runtime, settings, trackedMode, detectedMode) {
|
|
|
168
168
|
checks: {
|
|
169
169
|
carrierMarker: (safeRead(join(codexDir, 'AGENTS.md')) || '').includes('HELLOAGENTS_START'),
|
|
170
170
|
carrierContentMatch: normalizeText((safeRead(join(codexDir, 'AGENTS.md')) || '').match(/<!-- HELLOAGENTS_START -->([\s\S]*?)<!-- HELLOAGENTS_END -->/)?.[1] || '')
|
|
171
|
-
=== readExpectedCarrierContent(
|
|
171
|
+
=== readExpectedCarrierContent(
|
|
172
|
+
runtime,
|
|
173
|
+
expectedHomeCarrier,
|
|
174
|
+
settings,
|
|
175
|
+
expectedHomeCarrier === 'bootstrap.md' ? { profile: 'full' } : {},
|
|
176
|
+
),
|
|
172
177
|
homeLink: homeLinkTarget === (safeRealTarget(runtime.pkgRoot) || normalizePath(runtime.pkgRoot)),
|
|
173
178
|
globalHomeLink: homeLinkTarget === runtimeRoot,
|
|
174
179
|
modelInstructionsFile: !!modelInstructionsLine,
|
|
@@ -187,8 +192,8 @@ function buildCodexChecks(runtime, settings, trackedMode, detectedMode) {
|
|
|
187
192
|
pluginCache: existsSync(pluginCacheRoot),
|
|
188
193
|
pluginRootLink: pluginRootTarget === runtimeRoot,
|
|
189
194
|
pluginCacheLink: pluginCacheTarget === runtimeRoot,
|
|
190
|
-
pluginCarrierMatch: normalizeText(safeRead(join(pluginRoot, 'AGENTS.md')) || '') === readExpectedCarrierContent(runtime, 'bootstrap.md', settings),
|
|
191
|
-
pluginCacheCarrierMatch: normalizeText(safeRead(join(pluginCacheRoot, 'AGENTS.md')) || '') === readExpectedCarrierContent(runtime, 'bootstrap.md', settings),
|
|
195
|
+
pluginCarrierMatch: normalizeText(safeRead(join(pluginRoot, 'AGENTS.md')) || '') === readExpectedCarrierContent(runtime, 'bootstrap.md', settings, { profile: 'full' }),
|
|
196
|
+
pluginCacheCarrierMatch: normalizeText(safeRead(join(pluginCacheRoot, 'AGENTS.md')) || '') === readExpectedCarrierContent(runtime, 'bootstrap.md', settings, { profile: 'full' }),
|
|
192
197
|
marketplaceEntry: Array.isArray(marketplace.plugins) && marketplace.plugins.some((plugin) => plugin?.name === CODEX_PLUGIN_NAME),
|
|
193
198
|
pluginEnabled: codexConfig.includes(CODEX_PLUGIN_CONFIG_HEADER) && codexConfig.includes('enabled = true'),
|
|
194
199
|
globalNotifyPathMatch: codexConfig.includes(CODEX_MANAGED_NOTIFY_VALUE),
|
|
@@ -17,6 +17,22 @@ export function printDoctorText(runtime, report) {
|
|
|
17
17
|
for (const [key, value] of Object.entries(entry.checks)) {
|
|
18
18
|
console.log(` ${key}: ${value ? 'ok' : 'missing'}`)
|
|
19
19
|
}
|
|
20
|
+
if (entry.nativeDoctor) {
|
|
21
|
+
console.log(` native_doctor.available: ${entry.nativeDoctor.available ? 'ok' : 'missing'}`)
|
|
22
|
+
if (entry.nativeDoctor.available) {
|
|
23
|
+
console.log(` native_doctor.ok: ${entry.nativeDoctor.ok ? 'ok' : 'missing'}`)
|
|
24
|
+
}
|
|
25
|
+
if (entry.nativeDoctor.summary) {
|
|
26
|
+
if (entry.nativeDoctor.summary.version) console.log(` native_doctor.version: ${entry.nativeDoctor.summary.version}`)
|
|
27
|
+
if (entry.nativeDoctor.summary.configPath) console.log(` native_doctor.config_path: ${entry.nativeDoctor.summary.configPath}`)
|
|
28
|
+
if (entry.nativeDoctor.summary.resolvedProvider) console.log(` native_doctor.resolved_provider: ${entry.nativeDoctor.summary.resolvedProvider}`)
|
|
29
|
+
if (entry.nativeDoctor.summary.resolvedModel) console.log(` native_doctor.resolved_model: ${entry.nativeDoctor.summary.resolvedModel}`)
|
|
30
|
+
if (entry.nativeDoctor.summary.sandboxAvailable !== null) console.log(` native_doctor.sandbox_available: ${entry.nativeDoctor.summary.sandboxAvailable}`)
|
|
31
|
+
console.log(` native_doctor.mcp_present: ${entry.nativeDoctor.summary.mcpPresent ? 'ok' : 'missing'}`)
|
|
32
|
+
console.log(` native_doctor.skills_selected: ${entry.nativeDoctor.summary.skillsSelected.join(', ') || '(none)'}`)
|
|
33
|
+
}
|
|
34
|
+
if (entry.nativeDoctor.output) console.log(` native_doctor.output: ${entry.nativeDoctor.output}`)
|
|
35
|
+
}
|
|
20
36
|
for (const note of entry.notes) {
|
|
21
37
|
console.log(` note: ${note}`)
|
|
22
38
|
}
|
package/scripts/cli-doctor.mjs
CHANGED
|
@@ -5,7 +5,6 @@ import { DEFAULTS } from './cli-config.mjs'
|
|
|
5
5
|
import { inspectCodexDoctor as inspectCodexDoctorImpl } from './cli-doctor-codex.mjs'
|
|
6
6
|
import { printDoctorText } from './cli-doctor-render.mjs'
|
|
7
7
|
import { buildRuntimeCarrier } from './cli-runtime-carrier.mjs'
|
|
8
|
-
import { readTopLevelTomlLine } from './cli-toml.mjs'
|
|
9
8
|
import { loadHooksWithCliEntry, safeJson, safeRead } from './cli-utils.mjs'
|
|
10
9
|
|
|
11
10
|
const runtime = {
|
|
@@ -78,9 +77,9 @@ function managedHooksMatch(actualHooks, expectedHooks) {
|
|
|
78
77
|
return stringifySorted(pickManagedHooks(actualHooks || {})) === stringifySorted(expectedHooks || {})
|
|
79
78
|
}
|
|
80
79
|
|
|
81
|
-
function readExpectedCarrierContent(fileName, settings) {
|
|
80
|
+
function readExpectedCarrierContent(fileName, settings, options = {}) {
|
|
82
81
|
const bootstrap = safeRead(join(runtime.pkgRoot, fileName)) || ''
|
|
83
|
-
return normalizeText(buildRuntimeCarrier(bootstrap, settings))
|
|
82
|
+
return normalizeText(buildRuntimeCarrier(bootstrap, settings, options))
|
|
84
83
|
}
|
|
85
84
|
|
|
86
85
|
function buildDoctorIssue(code, cn, en) {
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
installClaudeStandby,
|
|
5
|
+
installGeminiStandby,
|
|
6
|
+
uninstallClaudeStandby,
|
|
7
|
+
uninstallGeminiStandby,
|
|
8
|
+
} from './cli-hosts.mjs'
|
|
4
9
|
import {
|
|
5
10
|
cleanupCodexGlobalResidueForStandby,
|
|
6
11
|
installCodexGlobal,
|
|
@@ -28,14 +28,28 @@ export function initCliLifecycle(options) {
|
|
|
28
28
|
Object.assign(runtime, options)
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
function sanitizeSettings(settings = {}) {
|
|
32
|
+
const next = settings && typeof settings === 'object' ? { ...settings } : {}
|
|
33
|
+
const tracked = next.host_install_modes
|
|
34
|
+
if (!tracked || typeof tracked !== 'object' || Array.isArray(tracked)) {
|
|
35
|
+
next.host_install_modes = {}
|
|
36
|
+
return next
|
|
37
|
+
}
|
|
38
|
+
next.host_install_modes = Object.fromEntries(
|
|
39
|
+
Object.entries(tracked).filter(([host, mode]) => HOSTS.includes(host) && typeof mode === 'string' && mode),
|
|
40
|
+
)
|
|
41
|
+
return next
|
|
42
|
+
}
|
|
43
|
+
|
|
31
44
|
export function readSettings(shouldEnsure = false) {
|
|
32
45
|
if (shouldEnsure) ensureConfig(runtime.helloagentsHome, runtime.configFile, safeJson, ensureDir)
|
|
33
|
-
return safeJson(runtime.configFile) || {}
|
|
46
|
+
return sanitizeSettings(safeJson(runtime.configFile) || {})
|
|
34
47
|
}
|
|
35
48
|
|
|
36
49
|
function writeSettings(settings) {
|
|
50
|
+
const sanitized = sanitizeSettings(settings)
|
|
37
51
|
ensureDir(runtime.helloagentsHome)
|
|
38
|
-
writeFileSync(runtime.configFile, JSON.stringify(
|
|
52
|
+
writeFileSync(runtime.configFile, JSON.stringify(sanitized, null, 2), 'utf-8')
|
|
39
53
|
}
|
|
40
54
|
|
|
41
55
|
function hasTrackedHostModes(settings) {
|
package/scripts/cli-messages.mjs
CHANGED
|
@@ -65,18 +65,18 @@ function renderInstallMessage(context, mode, state) {
|
|
|
65
65
|
|
|
66
66
|
if (install) {
|
|
67
67
|
return msg(
|
|
68
|
-
`\n ✅ HelloAGENTS 已安装(standby 模式)!\n\n Claude Code: 已自动配置(~/.claude/CLAUDE.md + hooks)\n Gemini CLI: 已自动配置(~/.gemini/GEMINI.md)\n Codex: ${codexStandbyStatus(context)}\n\n ${restartHint(msg)}\n\n standby 模式下,hello-* 技能不会自动触发。\n 在项目中使用 ~wiki
|
|
69
|
-
`\n ✅ HelloAGENTS installed (standby mode)!\n\n Claude Code: Auto-configured (~/.claude/CLAUDE.md + hooks)\n Gemini CLI: Auto-configured (~/.gemini/GEMINI.md)\n Codex: ${codexStandbyStatus(context)}\n\n ${restartHint(msg)}\n\n In standby mode, hello-* skills won't auto-trigger.\n Use ~wiki to create or sync the KB only
|
|
68
|
+
`\n ✅ HelloAGENTS 已安装(standby 模式)!\n\n Claude Code: 已自动配置(~/.claude/CLAUDE.md + hooks)\n Gemini CLI: 已自动配置(~/.gemini/GEMINI.md)\n Codex: ${codexStandbyStatus(context)}\n\n ${restartHint(msg)}\n\n standby 模式下,hello-* 技能不会自动触发。\n 在项目中使用 ~wiki 或 ~init 仅创建/同步知识库;用 ~global 初始化项目级全局模式;也可用 ~command 按需调用。\n\n 切换模式:\n helloagents --global 项目级全局模式(自动尝试 Claude/Gemini 插件或扩展;Codex 自动装原生本地插件)`,
|
|
69
|
+
`\n ✅ HelloAGENTS installed (standby mode)!\n\n Claude Code: Auto-configured (~/.claude/CLAUDE.md + hooks)\n Gemini CLI: Auto-configured (~/.gemini/GEMINI.md)\n Codex: ${codexStandbyStatus(context)}\n\n ${restartHint(msg)}\n\n In standby mode, hello-* skills won't auto-trigger.\n Use ~wiki or ~init to create or sync the KB only; use ~global to initialize project-level global mode; ~command stays available on demand.\n\n Switch modes:\n helloagents --global Project-level global mode (auto-attempts Claude/Gemini plugins or extensions; native local plugin auto-install for Codex)`,
|
|
70
70
|
)
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
return msg(
|
|
74
74
|
refresh
|
|
75
75
|
? ` standby 模式已刷新,CLI 注入与链接已同步最新文件。\n ${restartHint(msg)}\n ${removeHint(msg)}`
|
|
76
|
-
: ` 项目可通过 ~wiki
|
|
76
|
+
: ` 项目可通过 ~wiki 或 ~init 创建/同步知识库;用 ~global 初始化项目级全局模式;未初始化时仅注入轻量规则。\n ${restartHint(msg)}\n ${removeHint(msg)}`,
|
|
77
77
|
refresh
|
|
78
78
|
? ` Standby mode refreshed; injected files and links were synchronized.\n ${restartHint(msg)}\n ${removeHint(msg)}`
|
|
79
|
-
: ` Projects can use ~wiki
|
|
79
|
+
: ` Projects can use ~wiki or ~init to create/sync the KB; use ~global to initialize project-level global mode. Projects that are not initialized get lite rules only.\n ${restartHint(msg)}\n ${removeHint(msg)}`,
|
|
80
80
|
)
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -84,17 +84,18 @@ function renderHelp({ pkgVersion, msg }) {
|
|
|
84
84
|
return `
|
|
85
85
|
HelloAGENTS v${pkgVersion} — The orchestration kernel for AI CLIs
|
|
86
86
|
|
|
87
|
-
${msg('安装', 'Install')}:
|
|
87
|
+
${msg('安装', 'Install')}:
|
|
88
88
|
npm install -g helloagents ${msg('(安装命令并同步稳定运行根目录;CLI 部署需显式执行 helloagents install ...)', '(installs the command and syncs the stable runtime root; deploy to CLIs explicitly with helloagents install ...)')}
|
|
89
89
|
HELLOAGENTS=codex:global npm install -g helloagents
|
|
90
90
|
helloagents-js ${msg('(受管宿主配置的跨平台稳定入口)', '(cross-platform stable entrypoint for managed host configs)')}
|
|
91
91
|
|
|
92
92
|
${msg('模式切换', 'Mode switching')}:
|
|
93
|
-
helloagents --global ${msg('
|
|
93
|
+
helloagents --global ${msg('项目级全局模式(自动尝试 Claude/Gemini 插件或扩展;Codex 自动装原生本地插件)', 'Project-level global mode (auto-attempts Claude/Gemini plugins or extensions; native local plugin auto-install for Codex)')}
|
|
94
94
|
helloagents --standby ${msg('标准模式(非插件安装,hello-* 不自动触发,默认)', "Standby mode (non-plugin install, hello-* won't auto-trigger, default)")}
|
|
95
95
|
|
|
96
96
|
${msg('单 CLI 管理', 'Scoped CLI management')}:
|
|
97
97
|
helloagents install codex --standby
|
|
98
|
+
helloagents install gemini --standby
|
|
98
99
|
helloagents install --all --global
|
|
99
100
|
helloagents update codex
|
|
100
101
|
helloagents cleanup claude --global
|
|
@@ -104,7 +105,7 @@ ${msg('单 CLI 管理', 'Scoped CLI management')}:
|
|
|
104
105
|
${msg('分支切换', 'Branch switching')}:
|
|
105
106
|
helloagents switch-branch beta
|
|
106
107
|
helloagents switch-branch beta claude --global
|
|
107
|
-
helloagents branch
|
|
108
|
+
helloagents branch beta --all --standby
|
|
108
109
|
${msg('先通过 npm 安装指定 ref,再通过 npm 脚本同步宿主 CLI', 'Installs the requested ref with npm first, then syncs host CLIs through npm scripts')}
|
|
109
110
|
|
|
110
111
|
${msg('诊断', 'Diagnostics')}:
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { join } from 'node:path'
|
|
2
2
|
|
|
3
|
-
import { safeJson } from './cli-utils.mjs'
|
|
3
|
+
import { safeJson, withCarrierProfile } from './cli-utils.mjs'
|
|
4
4
|
|
|
5
5
|
export function readCarrierSettings(home) {
|
|
6
6
|
return safeJson(join(home, '.helloagents', 'helloagents.json')) || {}
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export function buildRuntimeCarrier(bootstrapContent, settings = {}) {
|
|
9
|
+
export function buildRuntimeCarrier(bootstrapContent, settings = {}, options = {}) {
|
|
10
10
|
void settings
|
|
11
11
|
const normalized = String(bootstrapContent || '').trim()
|
|
12
12
|
if (!normalized) return ''
|
|
13
13
|
|
|
14
|
-
return
|
|
14
|
+
return withCarrierProfile(normalized, options.profile || '')
|
|
15
15
|
}
|
package/scripts/cli-utils.mjs
CHANGED
|
@@ -54,8 +54,17 @@ export function removeLink(p) {
|
|
|
54
54
|
|
|
55
55
|
const MARKER = '<!-- HELLOAGENTS_START -->';
|
|
56
56
|
const MARKER_END = '<!-- HELLOAGENTS_END -->';
|
|
57
|
+
export const FULL_CARRIER_PROFILE_MARKER = '<!-- HELLOAGENTS_PROFILE: full -->';
|
|
57
58
|
const MARKER_RE = new RegExp(`\\n*${MARKER}[\\s\\S]*?${MARKER_END}\\n*`, 'g');
|
|
58
59
|
|
|
60
|
+
export function withCarrierProfile(content, profile = '') {
|
|
61
|
+
const normalized = String(content || '').trim();
|
|
62
|
+
if (!normalized) return '';
|
|
63
|
+
if (profile !== 'full') return `${normalized}\n`;
|
|
64
|
+
if (normalized.includes(FULL_CARRIER_PROFILE_MARKER)) return `${normalized}\n`;
|
|
65
|
+
return `${FULL_CARRIER_PROFILE_MARKER}\n${normalized}\n`;
|
|
66
|
+
}
|
|
67
|
+
|
|
59
68
|
/** Inject content wrapped in markers, preserving existing content outside markers. */
|
|
60
69
|
export function injectMarkedContent(filePath, content) {
|
|
61
70
|
const existing = safeRead(filePath) || '';
|
package/scripts/guard.mjs
CHANGED
|
@@ -133,7 +133,7 @@ function buildPostWriteWarnings(data) {
|
|
|
133
133
|
const filePath = data.tool_input?.file_path || ''
|
|
134
134
|
return [
|
|
135
135
|
...(detectIdeaBoundaryContext(data)?.zeroSideEffect
|
|
136
|
-
? ['~idea
|
|
136
|
+
? ['~idea 当前任务要求只读探索;检测到写入文件的工具调用,请回到探索输出,或升级到 ~plan / ~build / ~prd / ~auto 后再修改文件']
|
|
137
137
|
: []),
|
|
138
138
|
...scanUnrequestedFiles(filePath, data.tool_name),
|
|
139
139
|
...(content ? [...scanForSecrets(content), ...scanDangerousPackages(content, filePath)] : []),
|
|
@@ -34,7 +34,7 @@ function buildReadRootBlock(readRoot) {
|
|
|
34
34
|
turnStateCommand: 'helloagents-turn-state write --kind complete --role main',
|
|
35
35
|
turnStateUsage: '仅在运行时需要识别完成、等待或阻塞时调用;普通问答不调用',
|
|
36
36
|
};
|
|
37
|
-
return `##
|
|
37
|
+
return `## 当前对话 HelloAGENTS 读取根目录\n\`\`\`json\n${JSON.stringify(block, null, 2)}\n\`\`\``;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export function resolveCanonicalCommandSkill(skillName) {
|
package/scripts/notify-route.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { hasProjectFullCarrier } from './runtime-scope.mjs'
|
|
2
2
|
|
|
3
3
|
export function resolveRuntimeInstallMode(settings = {}, host = '') {
|
|
4
4
|
if (!settings || typeof settings !== 'object') return 'standby'
|
|
@@ -13,8 +13,7 @@ export function resolveBootstrapFile(cwd, settings = {}, host = '') {
|
|
|
13
13
|
const installMode = typeof settings === 'string'
|
|
14
14
|
? settings
|
|
15
15
|
: resolveRuntimeInstallMode(settings, host)
|
|
16
|
-
|
|
17
|
-
return (installMode === 'global' || isActivated) ? 'bootstrap.md' : 'bootstrap-lite.md'
|
|
16
|
+
return (installMode === 'global' || hasProjectFullCarrier(cwd, host)) ? 'bootstrap.md' : 'bootstrap-lite.md'
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
function shouldBypassRoute(prompt) {
|
|
@@ -23,7 +22,7 @@ function shouldBypassRoute(prompt) {
|
|
|
23
22
|
|
|
24
23
|
function buildHelpExtraRules(skillName) {
|
|
25
24
|
if (skillName !== 'help') return ''
|
|
26
|
-
return ' 这是 HelloAGENTS 的帮助命令,不是宿主 CLI 的内置帮助。仅显示 HelloAGENTS 的帮助和当前设置;优先使用当前会话上下文中已注入的“当前用户设置”、配置文件原始 JSON 或此前读取结果摘要,上下文不存在或缺少要展示的配置项时才读取一次 ~/.helloagents/helloagents.json
|
|
25
|
+
return ' 这是 HelloAGENTS 的帮助命令,不是宿主 CLI 的内置帮助。仅显示 HelloAGENTS 的帮助和当前设置;优先使用当前会话上下文中已注入的“当前用户设置”、配置文件原始 JSON 或此前读取结果摘要,上下文不存在或缺少要展示的配置项时才读取一次 ~/.helloagents/helloagents.json;自动激活技能说明仅在全局模式或已初始化项目时生效。不要调用宿主 CLI 的帮助工具(如 cli_help 或 /help),不要使用子代理,不要读取项目文件;若受工作区限制无法读取配置,必须明确说明并按已知默认值或已注入设置展示。'
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
function routeExplicitCommand({
|
package/scripts/notify.mjs
CHANGED
|
@@ -391,6 +391,7 @@ function cmdInject() {
|
|
|
391
391
|
const cwd = payload.cwd || process.cwd();
|
|
392
392
|
const settings = getSettings();
|
|
393
393
|
const bootstrapFile = resolveBootstrapFile(cwd, settings, HOST);
|
|
394
|
+
const shouldEnsureProjectLocal = bootstrapFile === 'bootstrap.md' || source === 'resume' || source === 'compact';
|
|
394
395
|
|
|
395
396
|
startReplaySession(cwd, {
|
|
396
397
|
host: HOST,
|
|
@@ -398,6 +399,7 @@ function cmdInject() {
|
|
|
398
399
|
bootstrapFile,
|
|
399
400
|
installMode: settings.install_mode || '',
|
|
400
401
|
payload,
|
|
402
|
+
ensureProjectLocal: shouldEnsureProjectLocal,
|
|
401
403
|
});
|
|
402
404
|
if (!IS_SILENT) {
|
|
403
405
|
appendReplayEvent(cwd, {
|
|
@@ -413,7 +415,10 @@ function cmdInject() {
|
|
|
413
415
|
});
|
|
414
416
|
}
|
|
415
417
|
clearRouteContext({ cwd, payload });
|
|
416
|
-
clearTurnState(cwd, {
|
|
418
|
+
clearTurnState(cwd, {
|
|
419
|
+
payload,
|
|
420
|
+
ensureProjectLocal: shouldEnsureProjectLocal,
|
|
421
|
+
});
|
|
417
422
|
cleanupProjectSessions(cwd, {
|
|
418
423
|
minIntervalMs: IS_SILENT ? PROJECT_SESSION_CLEANUP_COOLDOWN_MS : 0,
|
|
419
424
|
});
|
|
@@ -250,7 +250,7 @@ export function buildProjectStorageHint(cwd, options = {}) {
|
|
|
250
250
|
hints.push(`当前宿主未提供稳定会话标识,因此使用工作区默认位置 \`${summary.stateSessionToken}\``)
|
|
251
251
|
}
|
|
252
252
|
if (summary.usesSharedStore) {
|
|
253
|
-
hints.push(`项目存储:\`project_store_mode=repo-shared
|
|
253
|
+
hints.push(`项目存储:\`project_store_mode=repo-shared\`;项目本地存储/会话运行态目录仍是 \`${summary.promptActivationDir}\`,知识库/方案目录改为 \`${summary.promptStoreDir}\``)
|
|
254
254
|
}
|
|
255
255
|
return hints.join('。') + (hints.length > 0 ? '。' : '')
|
|
256
256
|
}
|
|
@@ -263,7 +263,7 @@ export function buildProjectStorageBlock(cwd, options = {}) {
|
|
|
263
263
|
|
|
264
264
|
const details = {
|
|
265
265
|
project_store_mode: summary.projectStoreMode,
|
|
266
|
-
|
|
266
|
+
project_local_dir: summary.promptActivationDir,
|
|
267
267
|
state_scope: summary.stateScope,
|
|
268
268
|
state_path: summary.promptStatePath,
|
|
269
269
|
state_workspace: summary.stateWorkspace,
|
|
@@ -281,9 +281,9 @@ export function buildProjectStorageBlock(cwd, options = {}) {
|
|
|
281
281
|
explanations.push('说明:当前宿主未提供稳定会话标识,因此使用工作区默认位置。')
|
|
282
282
|
}
|
|
283
283
|
if (summary.usesSharedStore) {
|
|
284
|
-
explanations.push('
|
|
284
|
+
explanations.push('说明:状态文件与会话产物写项目本地存储目录;`context.md`、`guidelines.md`、`DESIGN.md`、`verify.yaml`、`modules/`、`plans/`、`archive/` 写知识库/方案目录。')
|
|
285
285
|
} else {
|
|
286
|
-
explanations.push('说明:当前使用项目本地 `.helloagents/`
|
|
286
|
+
explanations.push('说明:当前使用项目本地 `.helloagents/` 作为知识、方案、状态和运行态目录。')
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
return [
|