helloagents 3.0.12 → 3.0.16-beta.1
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/marketplace.json +6 -4
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +182 -35
- package/README_CN.md +184 -37
- package/bootstrap-lite.md +32 -26
- package/bootstrap.md +35 -29
- package/cli.mjs +119 -11
- package/gemini-extension.json +1 -1
- package/install.ps1 +128 -0
- package/install.sh +121 -0
- package/package.json +23 -4
- package/scripts/advisor-state.mjs +36 -63
- package/scripts/capability-registry.mjs +4 -4
- package/scripts/cli-branch.mjs +84 -0
- package/scripts/cli-codex-config.mjs +14 -20
- package/scripts/cli-codex.mjs +32 -38
- package/scripts/cli-doctor-render.mjs +4 -0
- package/scripts/cli-doctor.mjs +40 -30
- package/scripts/cli-host-detect.mjs +0 -1
- package/scripts/cli-hosts.mjs +16 -8
- package/scripts/cli-lifecycle-hosts.mjs +119 -32
- package/scripts/cli-lifecycle.mjs +24 -13
- package/scripts/cli-messages.mjs +34 -16
- package/scripts/cli-runtime-carrier.mjs +15 -0
- package/scripts/cli-runtime-root.mjs +72 -0
- package/scripts/cli-toml.mjs +0 -79
- package/scripts/cli-utils.mjs +30 -4
- package/scripts/closeout-state.mjs +35 -62
- package/scripts/delivery-gate-messages.mjs +70 -0
- package/scripts/delivery-gate.mjs +9 -75
- package/scripts/guard-rules.mjs +42 -42
- package/scripts/guard.mjs +44 -24
- package/scripts/notify-context.mjs +19 -28
- package/scripts/notify-events.mjs +3 -1
- package/scripts/notify-gates.mjs +2 -0
- package/scripts/notify-route.mjs +9 -7
- package/scripts/notify-ui.mjs +42 -32
- package/scripts/notify.mjs +72 -36
- package/scripts/project-storage.mjs +35 -66
- package/scripts/ralph-loop.mjs +36 -31
- package/scripts/replay-state.mjs +31 -128
- package/scripts/review-state.mjs +34 -61
- package/scripts/runtime-artifacts.mjs +95 -0
- package/scripts/runtime-context.mjs +35 -29
- package/scripts/runtime-scope.mjs +313 -0
- package/scripts/session-capsule.mjs +202 -0
- package/scripts/turn-state-cli.mjs +17 -0
- package/scripts/turn-state.mjs +185 -66
- package/scripts/turn-stop-gate.mjs +24 -6
- package/scripts/verify-state.mjs +34 -85
- package/scripts/visual-state.mjs +38 -65
- package/scripts/workflow-core.mjs +3 -3
- package/scripts/workflow-plan-files.mjs +1 -1
- package/scripts/workflow-recommendation.mjs +17 -13
- package/scripts/workflow-state.mjs +5 -5
- package/skills/commands/build/SKILL.md +1 -1
- package/skills/commands/commit/SKILL.md +1 -1
- package/skills/commands/help/SKILL.md +5 -3
- package/skills/commands/loop/SKILL.md +1 -1
- package/skills/commands/plan/SKILL.md +8 -6
- package/skills/commands/prd/SKILL.md +5 -3
- package/skills/commands/verify/SKILL.md +5 -5
- package/skills/hello-debug/SKILL.md +20 -3
- package/skills/hello-review/SKILL.md +2 -2
- package/skills/hello-subagent/SKILL.md +2 -2
- package/skills/hello-test/SKILL.md +6 -2
- package/skills/hello-ui/SKILL.md +7 -7
- package/skills/hello-verify/SKILL.md +10 -7
- package/skills/helloagents/SKILL.md +14 -9
- package/templates/context.md +6 -0
- package/templates/plans/plan.md +3 -0
- package/templates/plans/tasks.md +8 -3
package/bootstrap.md
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
## 配置
|
|
6
6
|
配置文件: ~/.helloagents/helloagents.json
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
`output_language` 非空时,所有用户可见文本使用该语言;为空则跟随用户当前语言。
|
|
8
|
+
会话级缓存优先:当前上下文已有"当前用户设置"、原始 JSON 或读取摘要,且覆盖所需配置项时,直接复用。
|
|
9
|
+
仅在缺少所需项、用户要求刷新,或本轮修改后需要核验时读取;输出格式只在缺少 `output_format` 已知值时触发读取。
|
|
10
|
+
同一会话内,同一路径的配置文件、模块、SKILL、模板只读一次并跨轮复用;读取失败必须明示,并按默认值或已知设置执行。
|
|
11
11
|
|
|
12
12
|
## 编码原则
|
|
13
13
|
- 代码是唯一判断依据,文档与代码不一致时以代码为准
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
- 项目已有技术栈、设计系统或方案包时必须遵循既有决策
|
|
55
55
|
|
|
56
56
|
### UI 质量基线(涉及视觉/交互任务时,全阶段生效)
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
任务涉及界面视觉、交互体验、页面结构、组件外观、信息呈现或设计需求时,统一遵循以下基线;适用于标准模式未激活项目、标准模式已激活项目与全局模式。
|
|
58
|
+
纯逻辑修复、纯文案修改、纯数据处理、纯后端实现等不涉及视觉/交互变化的任务,不触发本节。本基线是最低质量线;已有 `plan.md` / PRD、`DESIGN.md` 或 `hello-ui` 约束时,与其共同生效,不覆盖上层决策。
|
|
59
59
|
|
|
60
60
|
- 先判断本次视觉变更是延续既有风格、演进式优化还是探索性方案,再形成简短但明确的内部设计简报:界面目的、目标用户与场景、主要视口、情绪方向、记忆点;不得直接滑入泛化风格标签或模型默认审美
|
|
61
61
|
- 已有项目优先复用现有组件、token、品牌资产、内容语气与交互模式;先建立最小设计系统:至少明确背景/表面/正文/弱化/强调/语义色,以及 display/headline/body/caption 等排版角色;缺少关键设计上下文时明确说明,不凭空发明视觉语言
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
|
|
98
98
|
## 输出格式
|
|
99
99
|
适用条件:
|
|
100
|
-
- 当 `helloagents.json` 的 `output_format` 为 `true`
|
|
100
|
+
- 当 `helloagents.json` 的 `output_format` 为 `true` 时,主代理必须在本轮最后一条、且确认**不再继续调用工具、不再继续执行**的**收尾消息**中使用输出格式。
|
|
101
101
|
- 若某个 skill 在本轮明确要求输出停顿、确认或总结,也仅当该消息同时是**本轮最终收尾消息**时,才可使用输出格式。
|
|
102
102
|
|
|
103
103
|
排除条件:
|
|
@@ -116,16 +116,18 @@
|
|
|
116
116
|
图标:💡直接响应 | ⚡快速执行 | 🔵规划流程 | ✅完成 | ❓等待输入 | ⚠️警告 | ❌错误
|
|
117
117
|
|
|
118
118
|
使用约束:
|
|
119
|
-
-
|
|
120
|
-
- `🔄 下一步`
|
|
121
|
-
- `🔄 下一步` 只写真实下一步,不改写成条件式能力表述或询问句。
|
|
119
|
+
- 状态图标与收尾内容必须一致。正文仍在等待用户输入、确认、授权或补充信息(含确认是否执行已给出的方案)时,只能使用 `❓等待输入`;仅在本轮执行已完成且不存在待确认动作时,才能使用 `✅完成`。
|
|
120
|
+
- `🔄 下一步` 必须写真实下一步,不改写成条件式能力表述或空泛询问。若正在等待确认,写清待确认动作;若存在自然后续动作,直接给出明确引导;若当前任务已完整结束且确无合理后续,可填写“当前任务已完成;无后续动作。”
|
|
122
121
|
|
|
123
122
|
### 收尾状态信号
|
|
124
|
-
-
|
|
125
|
-
-
|
|
126
|
-
-
|
|
123
|
+
- `turn-state` 只在运行时必须识别本轮“完成 / 等待输入 / 阻塞”时写入;普通问候、普通问答、T0 只读分析和一次性解释不调用
|
|
124
|
+
- 必须调用场景:显式 `~auto` / `~loop`;非只读任务完成验证并进入收尾;需要 delivery gate / Ralph Loop / closeout evidence;需要等待或阻塞且运行时必须识别状态;已进入项目连续流程或方案包闭环
|
|
125
|
+
- 首选参数式调用,保证一次完成:`helloagents-turn-state write --kind complete --role main`;也可用 stdin JSON。不要查找、读取或拼接 `turn-state.mjs` 源码路径
|
|
126
|
+
- 本轮已完成且不再等待用户输入 → `helloagents-turn-state write --kind complete --role main`
|
|
127
|
+
- 因阻塞判定等待用户输入、确认、授权或补充信息(含未授权的外部副作用确认) → 写 `kind=waiting`、`role=main`,并同时写 `reasonCategory` 与 `reason`
|
|
127
128
|
- 因错误、缺少前置条件或外部依赖而本轮停下 → 写 `kind=blocked`、`role=main`,并同时写 `reasonCategory` 与 `reason`
|
|
128
129
|
- `reasonCategory` 只允许:`ambiguity`、`missing-input`、`missing-file`、`missing-credential`、`unauthorized-side-effect`、`high-risk-confirmation`、`external-dependency`、`error`
|
|
130
|
+
- 显式 `~auto` / `~loop` 下,`waiting` / `blocked` 还必须写入 `blocker.target`、`blocker.evidence`、`blocker.requiredAction`;阶段汇报、单轮 probe 完成、内部路线调整或“下一步建议”不构成停下理由
|
|
129
131
|
- 子代理不得写 turn-state;子代理结束只直接返回结果,不为主代理代写完成态
|
|
130
132
|
|
|
131
133
|
## 交互规则
|
|
@@ -163,7 +165,7 @@
|
|
|
163
165
|
以下情况才构成中途停下并请求用户输入的正当理由:
|
|
164
166
|
- 需求存在影响执行结果的真实歧义
|
|
165
167
|
- 缺少继续执行所必需的信息、文件、路径或凭据
|
|
166
|
-
-
|
|
168
|
+
- 将产生外部副作用,但本轮尚未获得对应授权(含等待确认是否实施已给方案)
|
|
167
169
|
- 操作属于高风险或不可逆,按安全规则必须确认
|
|
168
170
|
除上述情况外,默认继续执行,不以“建议下一步”替代实际推进。
|
|
169
171
|
|
|
@@ -205,13 +207,16 @@
|
|
|
205
207
|
|
|
206
208
|
### 3. PLAN — 规划与上下文准备
|
|
207
209
|
根据 skills/ 目录下各 hello-* 技能的 SKILL.md frontmatter(name + description),标记本次任务可能需要的技能(不读取文件内容,仅记录名称)。
|
|
208
|
-
路径定义:`{HELLOAGENTS_READ_ROOT}` = 本轮已确定的 HelloAGENTS
|
|
210
|
+
路径定义:`{HELLOAGENTS_READ_ROOT}` = 本轮已确定的 HelloAGENTS 读取根目录,统一用于读取 `skills/` 与 `templates/`
|
|
209
211
|
先确定当前技能根目录:
|
|
210
212
|
- 优先使用当前上下文中已注入的“本轮 HelloAGENTS 读取根目录”
|
|
211
|
-
-
|
|
213
|
+
- 若当前上下文未注入,则使用稳定运行根目录 `~/.helloagents/helloagents`
|
|
214
|
+
- 宿主固定链接(Codex `~/.codex/helloagents`、Claude `~/.claude/helloagents`、Gemini `~/.gemini/helloagents`)只作为兼容别名,不作为优先探测路径
|
|
215
|
+
- 仍无法确定时,明确说明缺少 HelloAGENTS 读取根目录;不要递归扫描 `$HOME`、`Downloads`、项目目录或旧版本目录
|
|
212
216
|
- 已激活项目或全局模式下,技能是否需要使用由当前已加载 AGENTS 规则决定;不要因此额外探测项目目录里的 HelloAGENTS skills 路径
|
|
213
217
|
路径确定一次即可,不预读、不扫描整个目录,也不重复探测同一路径。
|
|
214
218
|
hello-* 技能读取路径:`{HELLOAGENTS_READ_ROOT}/skills/{技能名}/SKILL.md`
|
|
219
|
+
包内脚本优先使用稳定命令入口;需要写收尾状态时优先调用 `helloagents-turn-state write --kind complete --role main`,不要拼接 `turn-state.mjs` 路径。
|
|
215
220
|
|
|
216
221
|
命令职责:
|
|
217
222
|
- `~plan` 生成 `requirements.md`、`plan.md`、`tasks.md`、`contract.json`
|
|
@@ -235,7 +240,7 @@ hello-* 技能读取路径:`{HELLOAGENTS_READ_ROOT}/skills/{技能名}/SKILL.m
|
|
|
235
240
|
### 5. VERIFY — 审查与验证
|
|
236
241
|
编码任务:
|
|
237
242
|
- 读取 `skills/hello-verify/SKILL.md`,执行完整验证循环(Ralph Loop)→ 失败则修复 → 循环直到通过
|
|
238
|
-
- 审查优先或显式使用 `~review` 时,先读取 `skills/hello-review/SKILL.md` 做范围审查;审查完成后调用 `scripts/review-state.mjs write`
|
|
243
|
+
- 审查优先或显式使用 `~review` 时,先读取 `skills/hello-review/SKILL.md` 做范围审查;审查完成后调用 `scripts/review-state.mjs write` 写当前会话 `artifacts/review.json`,再进入验证
|
|
239
244
|
- 通过后收集已读取技能的交付检查清单,逐项附带证据确认,并确认用户目标已达成
|
|
240
245
|
|
|
241
246
|
非编码任务(文档 / 方案 / 审查等):
|
|
@@ -243,14 +248,15 @@ hello-* 技能读取路径:`{HELLOAGENTS_READ_ROOT}/skills/{技能名}/SKILL.m
|
|
|
243
248
|
|
|
244
249
|
### 6. CONSOLIDATE — 状态、资料与归档
|
|
245
250
|
所有任务:
|
|
246
|
-
- 有方案包且准备报告完成 → 优先调用 `scripts/closeout-state.mjs write`
|
|
251
|
+
- 有方案包且准备报告完成 → 优先调用 `scripts/closeout-state.mjs write` 写当前会话 `artifacts/closeout.json`,记录“需求覆盖”和“交付清单”;每项写明 `PASS` / `BLOCKED` 与简要摘要,再进入最终交付
|
|
247
252
|
- 状态文件维护:按上文“流程状态”中的适用范围执行。属于“强制创建并持续更新”范围时,重写 `state_path` 指向的文件(“正在做什么”更新为已完成,清空关键上下文 / 下一步 / 阻塞项);属于“已有则更新”范围时,仅在文件已存在时重写;属于“不创建”范围时不生成此文件
|
|
248
|
-
- 有方案包且任务已完成 → 将整个 `plans/{feature}/` 目录归档到 `.helloagents/archive/YYYY-MM/`,并更新 `archive/_index.md
|
|
253
|
+
- 有方案包且任务已完成 → 将整个 `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`)
|
|
249
254
|
- 按 `kb_create_mode` 同步知识库(0=关闭 / 1=已激活项目或全局模式中编码自动 / 2=已激活项目或全局模式中始终):
|
|
250
255
|
- `.helloagents/` 不存在则按 templates/ 创建知识库文件(`context.md`、`guidelines.md`、`verify.yaml`、`CHANGELOG.md`、`modules/`)
|
|
251
256
|
- 已存在但不完整(缺少上述核心文件)→ 按 templates/ 补全缺失文件,不覆盖已有文件
|
|
252
257
|
- 已存在且完整则按模板格式更新 `CHANGELOG.md`、相关 `modules/*.md`、增量经验 delta 追加
|
|
253
258
|
- 符合条件时触发 `hello-reflect`(详见 `hello-reflect` SKILL.md)
|
|
259
|
+
- 本地版本检查点:非只读任务完成验证且产生工作区变更时,最终收尾前自动执行本地提交。先检查 `git status --short`;若不是 git 仓库或无变更则跳过。若发现 `.env`、密钥、凭据、明显不应提交的大文件或二进制产物,停止提交并说明风险;否则执行 `git add -A`,使用当前回复语言生成简洁 conventional commit message 后执行 `git commit`。不自动远程 `git push`,除非用户明确要求
|
|
254
260
|
|
|
255
261
|
## 完成约束
|
|
256
262
|
- 未进入 VERIFY / CONSOLIDATE 的路径,声称完成前必须完成与任务类型匹配的必要检查;无法执行的检查必须明确说明,不得直接宣称完成
|
|
@@ -269,8 +275,8 @@ hello-* 技能读取路径:`{HELLOAGENTS_READ_ROOT}/skills/{技能名}/SKILL.m
|
|
|
269
275
|
路径: {CWD}/.helloagents/
|
|
270
276
|
所有文件的创建和更新必须按 templates/ 目录中对应模板的格式执行,不可自由发挥格式。
|
|
271
277
|
说明:
|
|
272
|
-
- `.helloagents/`
|
|
273
|
-
- `state_path`
|
|
278
|
+
- `.helloagents/` 表示项目级存储路径,也是标准模式的项目激活信号
|
|
279
|
+
- `state_path` 指向的状态文件、当前会话 `capsule.json`、`events.jsonl`、`artifacts/*.json`、`artifacts/loop-results.tsv` 等运行态文件始终保留在项目本地 `.helloagents/sessions/{branch}/{session}/`
|
|
274
280
|
- `state_path` 是状态文件的唯一位置。宿主提供会话标识时,写入 `.helloagents/sessions/{branch}/{session}/STATE.md`;没有稳定会话标识时,写入 `.helloagents/sessions/{branch}/default/STATE.md`
|
|
275
281
|
- 若 helloagents.json 中 `project_store_mode = "repo-shared"`,`context.md`、`guidelines.md`、`CHANGELOG.md`、`verify.yaml`、`DESIGN.md`、`modules/`、`plans/`、`archive/` 改按当前上下文中已注入的“当前项目存储”/“项目知识/方案目录”解析;未注入具体路径时,按当前存储模式自行解析,不要假定这些文件一定实际位于当前工作树中
|
|
276
282
|
templates/ 查找路径(按优先级;首次确定模板根目录后,本轮复用):
|
|
@@ -296,7 +302,7 @@ templates/ 查找路径(按优先级;首次确定模板根目录后,本轮
|
|
|
296
302
|
- “关键上下文”只保留恢复所需的信息,已不再相关的决策和变更移除
|
|
297
303
|
- DESIGN.md — 项目级稳定 UI 契约(仅 UI 项目),`~plan` / `~auto` / `~prd` 创建或更新;不存在且当前任务涉及 UI → 按 templates/DESIGN.md 创建;不替代单次需求的 `plan.md`
|
|
298
304
|
- plans/{feature}/ — 活跃方案包。`~plan` / `~auto` 生成:`requirements.md` + `plan.md` + `tasks.md` + `contract.json`;`~prd` 生成:`prd/` 目录(多维度文档)+ `tasks.md` + `decisions.md` + `contract.json`
|
|
299
|
-
-
|
|
305
|
+
- artifacts/advisor.json — 当前会话的可选 advisor 证据;仅当 `contract.json` 明确要求独立 advisor 时写入,记录 reason / focus / consultedSources / outcome
|
|
300
306
|
- archive/YYYY-MM/ — 已归档的方案包(整个 plans/{feature}/ 目录移入)
|
|
301
307
|
- archive/_index.md — 归档索引
|
|
302
308
|
|
|
@@ -308,11 +314,11 @@ templates/ 查找路径(按优先级;首次确定模板根目录后,本轮
|
|
|
308
314
|
- modules/*.md — 模块文档和经验
|
|
309
315
|
|
|
310
316
|
### 临时文件(流程产物,~clean 时清理)
|
|
311
|
-
- loop-results.tsv — ~loop 迭代记录
|
|
312
|
-
-
|
|
313
|
-
-
|
|
314
|
-
-
|
|
315
|
-
-
|
|
317
|
+
- artifacts/loop-results.tsv — 当前会话的 ~loop 迭代记录
|
|
318
|
+
- artifacts/loop-breaker.json — 当前会话的 hello-verify 断路器状态,仅在 `~loop` 或自动验证触发时写入
|
|
319
|
+
- artifacts/verify.json — 当前会话最近一次成功验证的证据快照
|
|
320
|
+
- artifacts/review.json — 当前会话最近一次成功审查的证据快照
|
|
321
|
+
- artifacts/closeout.json — 当前会话最近一次成功收尾的交付证据快照
|
|
316
322
|
|
|
317
323
|
## 项目上下文
|
|
318
324
|
|
|
@@ -325,11 +331,11 @@ templates/ 查找路径(按优先级;首次确定模板根目录后,本轮
|
|
|
325
331
|
### .helloagents/ 文件读取优先级
|
|
326
332
|
以下文件在任务需要时按需读取,按优先级分层:
|
|
327
333
|
说明:
|
|
328
|
-
- Tier 1
|
|
334
|
+
- Tier 1 在恢复、压缩、连续流程或活跃方案包场景读取当前 `state_path`;普通问答和一次性只读任务不强制读取
|
|
329
335
|
- Tier 2 / Tier 3 中的 `.helloagents/...` 路径默认按项目级存储路径解析;`project_store_mode=repo-shared` 时按共享知识/方案目录解析
|
|
330
336
|
|
|
331
337
|
Tier 1 — 恢复当前任务时优先读取:
|
|
332
|
-
- 当前状态文件(`state_path`)→
|
|
338
|
+
- 当前状态文件(`state_path`)→ 仅在恢复、压缩、连续流程或活跃方案包场景读取;先确认当前消息仍是同一任务,再用它找回最近进度
|
|
333
339
|
|
|
334
340
|
Tier 2 — 理解项目时读取:
|
|
335
341
|
- .helloagents/context.md → 项目架构、技术栈、目录结构、模块索引
|
package/cli.mjs
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
8
|
import { homedir } from 'node:os'
|
|
9
|
+
import { existsSync } from 'node:fs'
|
|
10
|
+
import { spawnSync } from 'node:child_process'
|
|
9
11
|
import { dirname, join, resolve } from 'node:path'
|
|
10
12
|
import { fileURLToPath } from 'node:url'
|
|
11
13
|
|
|
@@ -23,11 +25,14 @@ import {
|
|
|
23
25
|
syncVersion,
|
|
24
26
|
} from './scripts/cli-lifecycle.mjs'
|
|
25
27
|
import { initCliDoctor, runDoctor } from './scripts/cli-doctor.mjs'
|
|
28
|
+
import { runBranchSwitch } from './scripts/cli-branch.mjs'
|
|
26
29
|
import { createMessageHelpers, createInstallMessagePrinter } from './scripts/cli-messages.mjs'
|
|
30
|
+
import { getStableRuntimeRoot, removeRuntimeRoot, syncRuntimeRoot } from './scripts/cli-runtime-root.mjs'
|
|
27
31
|
|
|
28
32
|
const HOME = homedir()
|
|
29
33
|
const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)))
|
|
30
34
|
const HELLOAGENTS_HOME = join(HOME, '.helloagents')
|
|
35
|
+
const RUNTIME_ROOT = getStableRuntimeRoot(HOME)
|
|
31
36
|
const CONFIG_FILE = join(HELLOAGENTS_HOME, 'helloagents.json')
|
|
32
37
|
const pkg = loadPackageVersion(PKG_ROOT)
|
|
33
38
|
|
|
@@ -44,7 +49,8 @@ const { printHelp, printInstallMsg } = createInstallMessagePrinter({
|
|
|
44
49
|
})
|
|
45
50
|
initCliLifecycle({
|
|
46
51
|
home: HOME,
|
|
47
|
-
pkgRoot:
|
|
52
|
+
pkgRoot: RUNTIME_ROOT,
|
|
53
|
+
sourceRoot: PKG_ROOT,
|
|
48
54
|
helloagentsHome: HELLOAGENTS_HOME,
|
|
49
55
|
configFile: CONFIG_FILE,
|
|
50
56
|
pkgVersion: pkg.version,
|
|
@@ -54,7 +60,8 @@ initCliLifecycle({
|
|
|
54
60
|
})
|
|
55
61
|
initCliDoctor({
|
|
56
62
|
home: HOME,
|
|
57
|
-
pkgRoot:
|
|
63
|
+
pkgRoot: RUNTIME_ROOT,
|
|
64
|
+
sourceRoot: PKG_ROOT,
|
|
58
65
|
pkgVersion: pkg.version,
|
|
59
66
|
msg,
|
|
60
67
|
readSettings,
|
|
@@ -64,17 +71,29 @@ initCliDoctor({
|
|
|
64
71
|
getHostLabel,
|
|
65
72
|
})
|
|
66
73
|
|
|
74
|
+
function ensureRuntimeRoot() {
|
|
75
|
+
syncRuntimeRoot(PKG_ROOT, RUNTIME_ROOT)
|
|
76
|
+
}
|
|
77
|
+
|
|
67
78
|
function printPostinstallMessage() {
|
|
68
79
|
console.log(`\n HelloAGENTS v${pkg.version}\n`)
|
|
69
80
|
ensureConfig(HELLOAGENTS_HOME, CONFIG_FILE, safeJson, ensureDir)
|
|
81
|
+
ensureRuntimeRoot()
|
|
70
82
|
ok('~/.helloagents/helloagents.json')
|
|
83
|
+
ok('~/.helloagents/helloagents')
|
|
71
84
|
|
|
72
85
|
const settings = readSettings()
|
|
73
86
|
const mode = settings.install_mode || DEFAULTS.install_mode
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
87
|
+
const deployMessage = shouldDeployFromEnv()
|
|
88
|
+
? msg(
|
|
89
|
+
' HelloAGENTS 包已安装,正在按环境变量部署。\n',
|
|
90
|
+
' HelloAGENTS package installed; deploying from environment variables.\n',
|
|
91
|
+
)
|
|
92
|
+
: msg(
|
|
93
|
+
` HelloAGENTS 包已安装,尚未自动部署到任何 CLI。\n 使用显式命令部署:\n helloagents install codex --${mode}\n helloagents install --all --${mode}\n`,
|
|
94
|
+
` HelloAGENTS package installed. No CLI targets were configured automatically.\n Deploy explicitly with:\n helloagents install codex --${mode}\n helloagents install --all --${mode}\n`,
|
|
95
|
+
)
|
|
96
|
+
console.log(deployMessage)
|
|
78
97
|
}
|
|
79
98
|
|
|
80
99
|
function runSafely(handler) {
|
|
@@ -86,21 +105,110 @@ function runSafely(handler) {
|
|
|
86
105
|
}
|
|
87
106
|
}
|
|
88
107
|
|
|
108
|
+
function resolveRuntimeScript(scriptName) {
|
|
109
|
+
const runtimeScript = join(RUNTIME_ROOT, 'scripts', scriptName)
|
|
110
|
+
if (existsSync(runtimeScript)) return runtimeScript
|
|
111
|
+
return join(PKG_ROOT, 'scripts', scriptName)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function runRuntimeScript(scriptName, scriptArgs) {
|
|
115
|
+
const result = spawnSync(process.execPath, [resolveRuntimeScript(scriptName), ...scriptArgs], {
|
|
116
|
+
stdio: 'inherit',
|
|
117
|
+
windowsHide: true,
|
|
118
|
+
})
|
|
119
|
+
if (result.error) {
|
|
120
|
+
console.error(`\n ✗ ${result.error.message}\n`)
|
|
121
|
+
process.exitCode = 1
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
process.exitCode = typeof result.status === 'number' ? result.status : 1
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function envFlag(name) {
|
|
128
|
+
return ['1', 'true', 'yes', 'on'].includes(String(process.env[name] || '').toLowerCase())
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function parseCompactLifecycleSpec() {
|
|
132
|
+
const raw = String(process.env.HELLOAGENTS || '').trim()
|
|
133
|
+
if (!raw) return null
|
|
134
|
+
|
|
135
|
+
const parts = raw.split(':')
|
|
136
|
+
if (parts.length > 2 || !parts[0]) {
|
|
137
|
+
throw new Error(msg('HELLOAGENTS 必须是 target[:mode],例如 codex:global', 'HELLOAGENTS must be target[:mode], for example codex:global'))
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const target = normalizeHost(parts[0].trim().toLowerCase())
|
|
141
|
+
const mode = (parts[1] || '').trim().toLowerCase()
|
|
142
|
+
if (!target) throw new Error(msg(`不支持的 HELLOAGENTS 目标:${parts[0]}`, `Unsupported HELLOAGENTS target: ${parts[0]}`))
|
|
143
|
+
if (mode && !['standby', 'global'].includes(mode)) {
|
|
144
|
+
throw new Error(msg(`不支持的 HELLOAGENTS 模式:${mode}`, `Unsupported HELLOAGENTS mode: ${mode}`))
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return { target, mode }
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function lifecycleArgsFromEnv(defaultTarget = 'all') {
|
|
151
|
+
const compact = parseCompactLifecycleSpec()
|
|
152
|
+
const target = (
|
|
153
|
+
process.env.HELLOAGENTS_TARGET
|
|
154
|
+
|| process.env.HELLOAGENTS_HOST
|
|
155
|
+
|| compact?.target
|
|
156
|
+
|| defaultTarget
|
|
157
|
+
).trim()
|
|
158
|
+
const mode = (process.env.HELLOAGENTS_MODE || compact?.mode || '').trim().toLowerCase()
|
|
159
|
+
const args = [target === 'all' ? '--all' : target]
|
|
160
|
+
if (mode) args.push(`--${mode}`)
|
|
161
|
+
return args
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function shouldDeployFromEnv() {
|
|
165
|
+
return envFlag('HELLOAGENTS_DEPLOY') || Boolean(String(process.env.HELLOAGENTS || '').trim())
|
|
166
|
+
}
|
|
167
|
+
|
|
89
168
|
const argv = process.argv.slice(2)
|
|
90
169
|
const cmd = argv[0] || ''
|
|
91
170
|
|
|
92
|
-
if (cmd === '
|
|
171
|
+
if (cmd === 'codex-notify') {
|
|
172
|
+
runRuntimeScript('notify.mjs', ['codex-notify', ...argv.slice(1)])
|
|
173
|
+
} else if (cmd === 'notify') {
|
|
174
|
+
runRuntimeScript('notify.mjs', argv.slice(1))
|
|
175
|
+
} else if (cmd === 'guard') {
|
|
176
|
+
runRuntimeScript('guard.mjs', argv.slice(1))
|
|
177
|
+
} else if (cmd === 'ralph-loop') {
|
|
178
|
+
runRuntimeScript('ralph-loop.mjs', argv.slice(1))
|
|
179
|
+
} else if (cmd === 'postinstall') {
|
|
93
180
|
printPostinstallMessage()
|
|
181
|
+
if (shouldDeployFromEnv()) {
|
|
182
|
+
runSafely(() => runScopedLifecycle('install', lifecycleArgsFromEnv()))
|
|
183
|
+
}
|
|
94
184
|
} else if (cmd === 'preuninstall') {
|
|
95
|
-
|
|
185
|
+
runSafely(() => {
|
|
186
|
+
const cleanupArgs = argv.length > 1 ? argv.slice(1) : lifecycleArgsFromEnv('all')
|
|
187
|
+
runScopedLifecycle('cleanup', cleanupArgs)
|
|
188
|
+
if (cleanupArgs.includes('--all')) removeRuntimeRoot(RUNTIME_ROOT)
|
|
189
|
+
})
|
|
96
190
|
} else if (cmd === 'sync-version') {
|
|
97
191
|
syncVersion()
|
|
98
192
|
} else if (cmd === 'doctor') {
|
|
99
193
|
runSafely(() => runDoctor(argv.slice(1)))
|
|
100
194
|
} else if (cmd === '--global' || cmd === '--standby') {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
195
|
+
runSafely(() => {
|
|
196
|
+
ensureRuntimeRoot()
|
|
197
|
+
switchMode(cmd === '--global' ? 'global' : 'standby')
|
|
198
|
+
})
|
|
199
|
+
} else if (cmd === 'branch' || cmd === 'switch-branch') {
|
|
200
|
+
runSafely(() => runBranchSwitch(argv.slice(1)))
|
|
201
|
+
} else if (['install', 'update', 'uninstall', 'cleanup'].includes(cmd)) {
|
|
202
|
+
runSafely(() => {
|
|
203
|
+
const action = cmd
|
|
204
|
+
const lifecycleArgs = argv.slice(1)
|
|
205
|
+
if (cmd === 'install' || cmd === 'update') ensureRuntimeRoot()
|
|
206
|
+
runScopedLifecycle(action, lifecycleArgs)
|
|
207
|
+
const positionals = lifecycleArgs.filter((arg) => !arg.startsWith('--'))
|
|
208
|
+
if (action === 'uninstall' && (lifecycleArgs.includes('--all') || positionals.length === 0)) {
|
|
209
|
+
removeRuntimeRoot(RUNTIME_ROOT)
|
|
210
|
+
}
|
|
211
|
+
})
|
|
104
212
|
} else {
|
|
105
213
|
printHelp()
|
|
106
214
|
}
|
package/gemini-extension.json
CHANGED
package/install.ps1
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# HelloAGENTS one-shot installer.
|
|
2
|
+
#
|
|
3
|
+
# Environment:
|
|
4
|
+
# HELLOAGENTS=all|claude|gemini|codex[:standby|global]
|
|
5
|
+
# HELLOAGENTS_ACTION=install|update|cleanup|uninstall|switch-branch|branch
|
|
6
|
+
# HELLOAGENTS_TARGET=all|claude|gemini|codex
|
|
7
|
+
# HELLOAGENTS_MODE=standby|global
|
|
8
|
+
# HELLOAGENTS_BRANCH=main|beta|...
|
|
9
|
+
# HELLOAGENTS_PACKAGE=helloagents|github:owner/repo#ref|...
|
|
10
|
+
|
|
11
|
+
$ErrorActionPreference = "Stop"
|
|
12
|
+
|
|
13
|
+
$Action = if ($env:HELLOAGENTS_ACTION) { $env:HELLOAGENTS_ACTION } else { "install" }
|
|
14
|
+
$Target = if ($env:HELLOAGENTS_TARGET) { $env:HELLOAGENTS_TARGET } else { "" }
|
|
15
|
+
$Mode = if ($env:HELLOAGENTS_MODE) { $env:HELLOAGENTS_MODE } else { "" }
|
|
16
|
+
$Branch = if ($env:HELLOAGENTS_BRANCH) { $env:HELLOAGENTS_BRANCH } else { "" }
|
|
17
|
+
$Package = if ($env:HELLOAGENTS_PACKAGE) { $env:HELLOAGENTS_PACKAGE } else { "" }
|
|
18
|
+
|
|
19
|
+
if ($env:HELLOAGENTS) {
|
|
20
|
+
$Parts = $env:HELLOAGENTS.Split(":", 2)
|
|
21
|
+
if (-not $Parts[0]) {
|
|
22
|
+
throw "HELLOAGENTS must be target[:mode], for example codex:global"
|
|
23
|
+
}
|
|
24
|
+
if (-not $Target) { $Target = $Parts[0] }
|
|
25
|
+
if (-not $Mode -and $Parts.Count -gt 1) { $Mode = $Parts[1] }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (-not $Target) { $Target = "all" }
|
|
29
|
+
if (-not $Mode) { $Mode = "standby" }
|
|
30
|
+
$Target = $Target.ToLowerInvariant()
|
|
31
|
+
$Mode = $Mode.ToLowerInvariant()
|
|
32
|
+
|
|
33
|
+
if (@("all", "claude", "gemini", "codex") -notcontains $Target) {
|
|
34
|
+
throw "Unsupported HELLOAGENTS target: $Target"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (@("standby", "global") -notcontains $Mode) {
|
|
38
|
+
throw "Unsupported HELLOAGENTS mode: $Mode"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (-not $Package) {
|
|
42
|
+
if ($Branch) {
|
|
43
|
+
$Package = "github:hellowind777/helloagents#$Branch"
|
|
44
|
+
} else {
|
|
45
|
+
$Package = "helloagents"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function Invoke-Npm {
|
|
50
|
+
param([string[]]$Args)
|
|
51
|
+
& npm @Args
|
|
52
|
+
if ($LASTEXITCODE -ne 0) {
|
|
53
|
+
throw "npm $($Args -join ' ') failed with exit code $LASTEXITCODE"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function Enable-PostinstallDeploy {
|
|
58
|
+
$env:HELLOAGENTS_DEPLOY = "1"
|
|
59
|
+
$env:HELLOAGENTS_TARGET = $Target
|
|
60
|
+
$env:HELLOAGENTS_MODE = $Mode
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function Invoke-HostScript {
|
|
64
|
+
param([string]$ScriptName)
|
|
65
|
+
if ($Target -eq "all") {
|
|
66
|
+
Invoke-Npm @("explore", "-g", "helloagents", "--", "npm", "run", $ScriptName, "--", "--all", "--$Mode")
|
|
67
|
+
} else {
|
|
68
|
+
Invoke-Npm @("explore", "-g", "helloagents", "--", "npm", "run", $ScriptName, "--", $Target, "--$Mode")
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function Sync-Hosts {
|
|
73
|
+
Invoke-HostScript "sync-hosts"
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function Cleanup-Hosts {
|
|
77
|
+
Invoke-HostScript "cleanup-hosts"
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function Uninstall-Hosts {
|
|
81
|
+
Invoke-HostScript "uninstall"
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
switch ($Action) {
|
|
85
|
+
"install" {
|
|
86
|
+
Enable-PostinstallDeploy
|
|
87
|
+
Invoke-Npm @("install", "-g", $Package)
|
|
88
|
+
}
|
|
89
|
+
"update" {
|
|
90
|
+
if ($Branch -or $env:HELLOAGENTS_PACKAGE) {
|
|
91
|
+
Invoke-Npm @("install", "-g", $Package)
|
|
92
|
+
} else {
|
|
93
|
+
& npm update -g helloagents
|
|
94
|
+
if ($LASTEXITCODE -ne 0) {
|
|
95
|
+
Invoke-Npm @("install", "-g", "helloagents")
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
Sync-Hosts
|
|
99
|
+
}
|
|
100
|
+
"cleanup" {
|
|
101
|
+
Cleanup-Hosts
|
|
102
|
+
}
|
|
103
|
+
"switch-branch" {
|
|
104
|
+
if (-not $Branch -and -not $env:HELLOAGENTS_PACKAGE) {
|
|
105
|
+
throw "HELLOAGENTS_BRANCH or HELLOAGENTS_PACKAGE is required for switch-branch"
|
|
106
|
+
}
|
|
107
|
+
Invoke-Npm @("install", "-g", $Package)
|
|
108
|
+
Sync-Hosts
|
|
109
|
+
}
|
|
110
|
+
"branch" {
|
|
111
|
+
if (-not $Branch -and -not $env:HELLOAGENTS_PACKAGE) {
|
|
112
|
+
throw "HELLOAGENTS_BRANCH or HELLOAGENTS_PACKAGE is required for branch"
|
|
113
|
+
}
|
|
114
|
+
Invoke-Npm @("install", "-g", $Package)
|
|
115
|
+
Sync-Hosts
|
|
116
|
+
}
|
|
117
|
+
"uninstall" {
|
|
118
|
+
try {
|
|
119
|
+
Uninstall-Hosts
|
|
120
|
+
} catch {
|
|
121
|
+
Write-Warning "Failed to cleanup HelloAGENTS host integrations before uninstall: $_"
|
|
122
|
+
}
|
|
123
|
+
Invoke-Npm @("uninstall", "-g", "helloagents")
|
|
124
|
+
}
|
|
125
|
+
default {
|
|
126
|
+
throw "Unsupported HELLOAGENTS_ACTION: $Action"
|
|
127
|
+
}
|
|
128
|
+
}
|
package/install.sh
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
set -eu
|
|
3
|
+
|
|
4
|
+
# HelloAGENTS one-shot installer.
|
|
5
|
+
#
|
|
6
|
+
# Environment:
|
|
7
|
+
# HELLOAGENTS=all|claude|gemini|codex[:standby|global]
|
|
8
|
+
# HELLOAGENTS_ACTION=install|update|cleanup|uninstall|switch-branch|branch
|
|
9
|
+
# HELLOAGENTS_TARGET=all|claude|gemini|codex
|
|
10
|
+
# HELLOAGENTS_MODE=standby|global
|
|
11
|
+
# HELLOAGENTS_BRANCH=main|beta|...
|
|
12
|
+
# HELLOAGENTS_PACKAGE=helloagents|github:owner/repo#ref|...
|
|
13
|
+
|
|
14
|
+
ACTION="${HELLOAGENTS_ACTION:-install}"
|
|
15
|
+
TARGET="${HELLOAGENTS_TARGET:-}"
|
|
16
|
+
MODE="${HELLOAGENTS_MODE:-}"
|
|
17
|
+
BRANCH="${HELLOAGENTS_BRANCH:-}"
|
|
18
|
+
PACKAGE="${HELLOAGENTS_PACKAGE:-}"
|
|
19
|
+
|
|
20
|
+
if [ -n "${HELLOAGENTS:-}" ]; then
|
|
21
|
+
SPEC_TARGET="${HELLOAGENTS%%:*}"
|
|
22
|
+
SPEC_MODE=""
|
|
23
|
+
if [ -z "$SPEC_TARGET" ]; then
|
|
24
|
+
echo "HELLOAGENTS must be target[:mode], for example codex:global" >&2
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
if [ "$SPEC_TARGET" != "$HELLOAGENTS" ]; then
|
|
28
|
+
SPEC_MODE="${HELLOAGENTS#*:}"
|
|
29
|
+
fi
|
|
30
|
+
TARGET="${TARGET:-$SPEC_TARGET}"
|
|
31
|
+
MODE="${MODE:-$SPEC_MODE}"
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
TARGET="${TARGET:-all}"
|
|
35
|
+
MODE="${MODE:-standby}"
|
|
36
|
+
TARGET="$(printf '%s' "$TARGET" | tr '[:upper:]' '[:lower:]')"
|
|
37
|
+
MODE="$(printf '%s' "$MODE" | tr '[:upper:]' '[:lower:]')"
|
|
38
|
+
|
|
39
|
+
case "$TARGET" in
|
|
40
|
+
all|claude|gemini|codex) ;;
|
|
41
|
+
*) echo "Unsupported HELLOAGENTS target: $TARGET" >&2; exit 1 ;;
|
|
42
|
+
esac
|
|
43
|
+
|
|
44
|
+
case "$MODE" in
|
|
45
|
+
standby|global) ;;
|
|
46
|
+
*) echo "Unsupported HELLOAGENTS mode: $MODE" >&2; exit 1 ;;
|
|
47
|
+
esac
|
|
48
|
+
|
|
49
|
+
if [ -z "$PACKAGE" ]; then
|
|
50
|
+
if [ -n "$BRANCH" ]; then
|
|
51
|
+
PACKAGE="github:hellowind777/helloagents#$BRANCH"
|
|
52
|
+
else
|
|
53
|
+
PACKAGE="helloagents"
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
sync_hosts() {
|
|
58
|
+
if [ "$TARGET" = "all" ]; then
|
|
59
|
+
npm explore -g helloagents -- npm run sync-hosts -- --all "--$MODE"
|
|
60
|
+
else
|
|
61
|
+
npm explore -g helloagents -- npm run sync-hosts -- "$TARGET" "--$MODE"
|
|
62
|
+
fi
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
cleanup_hosts() {
|
|
66
|
+
if [ "$TARGET" = "all" ]; then
|
|
67
|
+
npm explore -g helloagents -- npm run cleanup-hosts -- --all "--$MODE"
|
|
68
|
+
else
|
|
69
|
+
npm explore -g helloagents -- npm run cleanup-hosts -- "$TARGET" "--$MODE"
|
|
70
|
+
fi
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
uninstall_hosts() {
|
|
74
|
+
if [ "$TARGET" = "all" ]; then
|
|
75
|
+
npm explore -g helloagents -- npm run uninstall -- --all "--$MODE"
|
|
76
|
+
else
|
|
77
|
+
npm explore -g helloagents -- npm run uninstall -- "$TARGET" "--$MODE"
|
|
78
|
+
fi
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
enable_postinstall_deploy() {
|
|
82
|
+
export HELLOAGENTS_DEPLOY=1
|
|
83
|
+
export HELLOAGENTS_TARGET="$TARGET"
|
|
84
|
+
export HELLOAGENTS_MODE="$MODE"
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
case "$ACTION" in
|
|
88
|
+
install)
|
|
89
|
+
enable_postinstall_deploy
|
|
90
|
+
npm install -g "$PACKAGE"
|
|
91
|
+
;;
|
|
92
|
+
update)
|
|
93
|
+
if [ -n "$BRANCH" ] || [ -n "${HELLOAGENTS_PACKAGE:-}" ]; then
|
|
94
|
+
npm install -g "$PACKAGE"
|
|
95
|
+
else
|
|
96
|
+
npm update -g helloagents || npm install -g helloagents
|
|
97
|
+
fi
|
|
98
|
+
sync_hosts
|
|
99
|
+
;;
|
|
100
|
+
cleanup)
|
|
101
|
+
cleanup_hosts
|
|
102
|
+
;;
|
|
103
|
+
switch-branch|branch)
|
|
104
|
+
if [ -z "$BRANCH" ] && [ -z "${HELLOAGENTS_PACKAGE:-}" ]; then
|
|
105
|
+
echo "HELLOAGENTS_BRANCH or HELLOAGENTS_PACKAGE is required for switch-branch" >&2
|
|
106
|
+
exit 1
|
|
107
|
+
fi
|
|
108
|
+
npm install -g "$PACKAGE"
|
|
109
|
+
sync_hosts
|
|
110
|
+
;;
|
|
111
|
+
uninstall)
|
|
112
|
+
if ! uninstall_hosts; then
|
|
113
|
+
echo "Warning: failed to cleanup HelloAGENTS host integrations before uninstall" >&2
|
|
114
|
+
fi
|
|
115
|
+
npm uninstall -g helloagents
|
|
116
|
+
;;
|
|
117
|
+
*)
|
|
118
|
+
echo "Unsupported HELLOAGENTS_ACTION: $ACTION" >&2
|
|
119
|
+
exit 1
|
|
120
|
+
;;
|
|
121
|
+
esac
|