helloagents 3.0.2-beta.1 → 3.0.7

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.
Files changed (72) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/README.md +147 -45
  5. package/README_CN.md +148 -46
  6. package/bootstrap-lite.md +104 -46
  7. package/bootstrap.md +143 -112
  8. package/cli.mjs +80 -427
  9. package/gemini-extension.json +1 -1
  10. package/hooks/hooks-claude.json +10 -0
  11. package/hooks/hooks.json +10 -0
  12. package/package.json +2 -12
  13. package/scripts/advisor-state.mjs +222 -0
  14. package/scripts/capability-registry.mjs +59 -0
  15. package/scripts/cli-codex-backup.mjs +59 -0
  16. package/scripts/cli-codex-config.mjs +100 -0
  17. package/scripts/cli-codex.mjs +34 -156
  18. package/scripts/cli-config.mjs +1 -0
  19. package/scripts/cli-doctor-render.mjs +28 -0
  20. package/scripts/cli-doctor.mjs +367 -0
  21. package/scripts/cli-host-detect.mjs +94 -0
  22. package/scripts/cli-lifecycle-hosts.mjs +123 -0
  23. package/scripts/cli-lifecycle.mjs +213 -0
  24. package/scripts/cli-messages.mjs +76 -52
  25. package/scripts/closeout-state.mjs +213 -0
  26. package/scripts/delivery-gate.mjs +256 -0
  27. package/scripts/guard-rules.mjs +122 -0
  28. package/scripts/guard.mjs +190 -168
  29. package/scripts/notify-context.mjs +77 -17
  30. package/scripts/notify-events.mjs +5 -1
  31. package/scripts/notify-route.mjs +111 -0
  32. package/scripts/notify-shared.mjs +0 -2
  33. package/scripts/notify-source.mjs +113 -0
  34. package/scripts/notify-ui.mjs +40 -6
  35. package/scripts/notify.mjs +120 -59
  36. package/scripts/plan-contract.mjs +210 -0
  37. package/scripts/project-storage.mjs +235 -0
  38. package/scripts/ralph-loop.mjs +9 -58
  39. package/scripts/replay-state.mjs +210 -0
  40. package/scripts/review-state.mjs +220 -0
  41. package/scripts/runtime-context.mjs +74 -0
  42. package/scripts/verify-state.mjs +226 -0
  43. package/scripts/visual-state.mjs +244 -0
  44. package/scripts/workflow-core.mjs +165 -0
  45. package/scripts/workflow-plan-files.mjs +249 -0
  46. package/scripts/workflow-recommendation.mjs +335 -0
  47. package/scripts/workflow-state.mjs +113 -0
  48. package/skills/commands/auto/SKILL.md +37 -71
  49. package/skills/commands/build/SKILL.md +67 -0
  50. package/skills/commands/clean/SKILL.md +10 -8
  51. package/skills/commands/commit/SKILL.md +8 -4
  52. package/skills/commands/help/SKILL.md +19 -11
  53. package/skills/commands/idea/SKILL.md +55 -0
  54. package/skills/commands/init/SKILL.md +6 -3
  55. package/skills/commands/loop/SKILL.md +6 -5
  56. package/skills/commands/plan/SKILL.md +116 -0
  57. package/skills/commands/prd/SKILL.md +20 -15
  58. package/skills/commands/verify/SKILL.md +32 -9
  59. package/skills/commands/wiki/SKILL.md +59 -0
  60. package/skills/hello-review/SKILL.md +9 -0
  61. package/skills/hello-subagent/SKILL.md +4 -3
  62. package/skills/hello-ui/SKILL.md +36 -8
  63. package/skills/hello-verify/SKILL.md +10 -2
  64. package/skills/helloagents/SKILL.md +24 -13
  65. package/templates/DESIGN.md +25 -4
  66. package/templates/STATE.md +3 -0
  67. package/templates/plans/contract.json +48 -0
  68. package/templates/plans/plan.md +23 -0
  69. package/templates/plans/tasks.md +3 -3
  70. package/skills/commands/design/SKILL.md +0 -108
  71. package/skills/commands/review/SKILL.md +0 -16
  72. package/templates/plans/design.md +0 -14
package/cli.mjs CHANGED
@@ -3,451 +3,104 @@
3
3
  * HelloAGENTS CLI — Quality-driven orchestration kernel for AI CLIs.
4
4
  * Runs as npm lifecycle script (postinstall/preuninstall). Zero external dependencies.
5
5
  */
6
- 'use strict';
6
+ 'use strict'
7
7
 
8
- import { homedir } from 'node:os';
9
- import { join, resolve, dirname } from 'node:path';
10
- import { fileURLToPath } from 'node:url';
11
- import { existsSync, writeFileSync } from 'node:fs';
12
- import { safeRead, safeWrite, safeJson, ensureDir } from './scripts/cli-utils.mjs';
13
- import {
14
- installCodexStandby,
15
- uninstallCodexStandby,
16
- installCodexGlobal,
17
- uninstallCodexGlobal,
18
- CODEX_MARKETPLACE_NAME,
19
- CODEX_PLUGIN_KEY,
20
- CODEX_PLUGIN_NAME,
21
- } from './scripts/cli-codex.mjs';
22
- import { installClaudeStandby, uninstallClaudeStandby, installGeminiStandby, uninstallGeminiStandby } from './scripts/cli-hosts.mjs';
23
- import { DEFAULTS, ensureConfig, loadPackageVersion } from './scripts/cli-config.mjs';
24
- import { createMessageHelpers, createInstallMessagePrinter } from './scripts/cli-messages.mjs';
8
+ import { homedir } from 'node:os'
9
+ import { dirname, join, resolve } from 'node:path'
10
+ import { fileURLToPath } from 'node:url'
25
11
 
26
- const HOME = homedir();
27
- const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)));
28
- const HELLOAGENTS_HOME = join(HOME, '.helloagents');
29
- const CONFIG_FILE = join(HELLOAGENTS_HOME, 'helloagents.json');
30
- const pkg = loadPackageVersion(PKG_ROOT);
12
+ import { DEFAULTS, ensureConfig, loadPackageVersion } from './scripts/cli-config.mjs'
13
+ import { safeJson, ensureDir } from './scripts/cli-utils.mjs'
14
+ import {
15
+ detectHostMode,
16
+ getHostLabel,
17
+ getTrackedHostMode,
18
+ initCliLifecycle,
19
+ normalizeHost,
20
+ readSettings,
21
+ runScopedLifecycle,
22
+ switchMode,
23
+ syncVersion,
24
+ } from './scripts/cli-lifecycle.mjs'
25
+ import { initCliDoctor, runDoctor } from './scripts/cli-doctor.mjs'
26
+ import { createMessageHelpers, createInstallMessagePrinter } from './scripts/cli-messages.mjs'
27
+
28
+ const HOME = homedir()
29
+ const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)))
30
+ const HELLOAGENTS_HOME = join(HOME, '.helloagents')
31
+ const CONFIG_FILE = join(HELLOAGENTS_HOME, 'helloagents.json')
32
+ const pkg = loadPackageVersion(PKG_ROOT)
31
33
 
32
34
  const isCN = (() => {
33
- const lang = (process.env.LANG || process.env.LANGUAGE || process.env.LC_ALL || '').toLowerCase();
34
- return lang.includes('zh') || lang.includes('cn');
35
- })();
36
- const { msg, ok } = createMessageHelpers(isCN);
35
+ const lang = (process.env.LANG || process.env.LANGUAGE || process.env.LC_ALL || '').toLowerCase()
36
+ return lang.includes('zh') || lang.includes('cn')
37
+ })()
38
+
39
+ const { msg, ok } = createMessageHelpers(isCN)
37
40
  const { printHelp, printInstallMsg } = createInstallMessagePrinter({
38
41
  home: HOME,
39
42
  pkgVersion: pkg.version,
40
43
  msg,
41
- });
42
- const HOSTS = ['claude', 'gemini', 'codex'];
43
- const HOST_ALIASES = new Map([
44
- ['all', 'all'],
45
- ['*', 'all'],
46
- ['claude', 'claude'],
47
- ['claude-code', 'claude'],
48
- ['gemini', 'gemini'],
49
- ['gemini-cli', 'gemini'],
50
- ['codex', 'codex'],
51
- ['codex-cli', 'codex'],
52
- ]);
53
-
54
- function readSettings(shouldEnsure = false) {
55
- if (shouldEnsure) ensureConfig(HELLOAGENTS_HOME, CONFIG_FILE, safeJson, ensureDir);
56
- return safeJson(CONFIG_FILE) || {};
57
- }
58
-
59
- function writeSettings(settings) {
60
- ensureDir(HELLOAGENTS_HOME);
61
- writeFileSync(CONFIG_FILE, JSON.stringify(settings, null, 2), 'utf-8');
62
- }
63
-
64
- function hasTrackedHostModes(settings) {
65
- return !!settings
66
- && typeof settings.host_install_modes === 'object'
67
- && !Array.isArray(settings.host_install_modes);
68
- }
69
-
70
- function getTrackedHostMode(settings, host) {
71
- return hasTrackedHostModes(settings) ? settings.host_install_modes[host] || '' : '';
72
- }
73
-
74
- function setTrackedHostMode(settings, host, mode) {
75
- if (!hasTrackedHostModes(settings)) settings.host_install_modes = {};
76
- settings.host_install_modes[host] = mode;
77
- }
78
-
79
- function clearTrackedHostMode(settings, host) {
80
- if (!hasTrackedHostModes(settings)) {
81
- settings.host_install_modes = {};
82
- return;
83
- }
84
- delete settings.host_install_modes[host];
85
- }
86
-
87
- function setAllTrackedHostModes(settings, mode) {
88
- settings.host_install_modes = Object.fromEntries(HOSTS.map((host) => [host, mode]));
89
- }
90
-
91
- function clearAllTrackedHostModes(settings) {
92
- settings.host_install_modes = {};
93
- }
94
-
95
- function normalizeHost(value = '') {
96
- return HOST_ALIASES.get(String(value || '').toLowerCase()) || '';
97
- }
98
-
99
- function parseModeFlag(args) {
100
- const hasGlobal = args.includes('--global');
101
- const hasStandby = args.includes('--standby');
102
- if (hasGlobal && hasStandby) {
103
- throw new Error(msg('不能同时指定 --global 和 --standby', 'Cannot use --global and --standby together'));
104
- }
105
- if (hasGlobal) return 'global';
106
- if (hasStandby) return 'standby';
107
- return '';
108
- }
109
-
110
- function parseLifecycleArgs(args) {
111
- const explicitMode = parseModeFlag(args);
112
- const wantsAll = args.includes('--all');
113
- const positionals = args.filter((arg) => !arg.startsWith('--'));
114
- const unknownFlags = args.filter((arg) =>
115
- arg.startsWith('--')
116
- && arg !== '--global'
117
- && arg !== '--standby'
118
- && arg !== '--all');
119
- if (unknownFlags.length) {
120
- throw new Error(msg(`未知参数: ${unknownFlags.join(', ')}`, `Unknown flags: ${unknownFlags.join(', ')}`));
121
- }
122
- if (wantsAll && positionals.length) {
123
- throw new Error(msg('`--all` 不能与具体 CLI 同时使用', '`--all` cannot be combined with a specific CLI'));
124
- }
125
- if (positionals.length > 1) {
126
- throw new Error(msg(`参数过多: ${positionals.join(' ')}`, `Too many arguments: ${positionals.join(' ')}`));
127
- }
128
- const host = normalizeHost(wantsAll ? 'all' : (positionals[0] || 'all'));
129
- if (!host) {
130
- throw new Error(msg(`不支持的 CLI: ${positionals[0]}`, `Unsupported CLI: ${positionals[0]}`));
131
- }
132
- return { host, explicitMode };
133
- }
134
-
135
- function hasHelloagentsMarker(filePath) {
136
- return (safeRead(filePath) || '').includes('HELLOAGENTS_START');
137
- }
138
-
139
- function hasHelloagentsSettings(filePath) {
140
- return JSON.stringify(safeJson(filePath) || {}).includes('helloagents');
141
- }
142
-
143
- function detectClaudeMode() {
144
- const claudeDir = join(HOME, '.claude');
145
- if (
146
- existsSync(join(claudeDir, 'helloagents'))
147
- || hasHelloagentsMarker(join(claudeDir, 'CLAUDE.md'))
148
- || hasHelloagentsSettings(join(claudeDir, 'settings.json'))
149
- ) {
150
- return 'standby';
151
- }
152
- return '';
153
- }
154
-
155
- function detectGeminiMode() {
156
- const geminiDir = join(HOME, '.gemini');
157
- if (
158
- existsSync(join(geminiDir, 'helloagents'))
159
- || hasHelloagentsMarker(join(geminiDir, 'GEMINI.md'))
160
- || hasHelloagentsSettings(join(geminiDir, 'settings.json'))
161
- ) {
162
- return 'standby';
163
- }
164
- return '';
165
- }
166
-
167
- function detectCodexMode() {
168
- const codexDir = join(HOME, '.codex');
169
- const codexConfig = safeRead(join(codexDir, 'config.toml')) || '';
170
- const marketplace = safeRead(join(HOME, '.agents', 'plugins', 'marketplace.json')) || '';
171
- if (
172
- existsSync(join(HOME, 'plugins', CODEX_PLUGIN_NAME))
173
- || existsSync(join(codexDir, 'plugins', 'cache', CODEX_MARKETPLACE_NAME, CODEX_PLUGIN_NAME))
174
- || marketplace.includes(`"name": "${CODEX_PLUGIN_NAME}"`)
175
- || codexConfig.includes(CODEX_PLUGIN_KEY)
176
- || codexConfig.includes(`/plugins/${CODEX_PLUGIN_NAME}/scripts/notify.mjs`)
177
- ) {
178
- return 'global';
179
- }
180
- if (
181
- existsSync(join(codexDir, 'helloagents'))
182
- || hasHelloagentsMarker(join(codexDir, 'AGENTS.md'))
183
- || codexConfig.includes('codex-notify')
184
- || codexConfig.includes('HelloAGENTS')
185
- ) {
186
- return 'standby';
187
- }
188
- return '';
189
- }
190
-
191
- function detectHostMode(host) {
192
- if (host === 'claude') return detectClaudeMode();
193
- if (host === 'gemini') return detectGeminiMode();
194
- if (host === 'codex') return detectCodexMode();
195
- return '';
196
- }
197
-
198
- function resolveHostMode(host, explicitMode, settings) {
199
- if (explicitMode) return explicitMode;
200
- return detectHostMode(host)
201
- || getTrackedHostMode(settings, host)
202
- || (!hasTrackedHostModes(settings) ? (settings.install_mode || '') : '')
203
- || DEFAULTS.install_mode;
204
- }
205
-
206
- function resolveInstallMode(explicitMode, settings) {
207
- return explicitMode || settings.install_mode || DEFAULTS.install_mode;
208
- }
209
-
210
- function getHostLabel(host) {
211
- if (host === 'claude') return 'Claude Code';
212
- if (host === 'gemini') return 'Gemini CLI';
213
- if (host === 'codex') return 'Codex CLI';
214
- return 'All CLIs';
215
- }
216
-
217
- function reportHostAction(action, host, mode, result = {}) {
218
- const label = getHostLabel(host);
219
- const isCleanup = action === 'cleanup' || action === 'uninstall';
220
- if (result.skipped) {
221
- console.log(msg(` - ${label} 未检测到,跳过`, ` - ${label} not detected, skipped`));
222
- } else if (isCleanup) {
223
- ok(msg(`${label} 已清理(${mode} 模式)`, `${label} cleaned (${mode} mode)`));
224
- } else if (mode === 'standby') {
225
- ok(msg(`${label} 已配置(standby 模式)`, `${label} configured (standby mode)`));
226
- } else if (host === 'codex') {
227
- ok(msg(`${label} 已安装原生本地插件(global 模式)`, `${label} native local plugin installed (global mode)`));
228
- } else {
229
- ok(msg(`${label} 已切到 global 模式`, `${label} switched to global mode`));
230
- }
231
-
232
- if (result.noteCN || result.noteEN) {
233
- console.log(msg(` ℹ ${result.noteCN}`, ` ℹ ${result.noteEN}`));
234
- }
235
- }
236
-
237
- function installHostStandby(host) {
238
- if (host === 'claude') {
239
- installClaudeStandby(HOME, PKG_ROOT);
240
- return {};
241
- }
242
- if (host === 'gemini') {
243
- installGeminiStandby(HOME, PKG_ROOT);
244
- return {};
245
- }
246
- uninstallCodexGlobal(HOME);
247
- if (!installCodexStandby(HOME, PKG_ROOT)) return { skipped: true };
248
- return {};
249
- }
250
-
251
- function installHostGlobal(host) {
252
- if (host === 'claude') {
253
- uninstallClaudeStandby(HOME);
254
- return {
255
- noteCN: 'Claude Code 的 global 模式需手动安装插件: /plugin marketplace add hellowind777/helloagents',
256
- noteEN: 'Claude Code global mode still needs a manual plugin install: /plugin marketplace add hellowind777/helloagents',
257
- };
258
- }
259
- if (host === 'gemini') {
260
- uninstallGeminiStandby(HOME);
261
- return {
262
- noteCN: 'Gemini CLI 的 global 模式需手动安装扩展: gemini extensions install https://github.com/hellowind777/helloagents',
263
- noteEN: 'Gemini CLI global mode still needs a manual extension install: gemini extensions install https://github.com/hellowind777/helloagents',
264
- };
265
- }
266
- uninstallCodexStandby(HOME);
267
- if (!installCodexGlobal(HOME, PKG_ROOT)) return { skipped: true };
268
- return {};
269
- }
270
-
271
- function cleanupHostStandby(host) {
272
- if (host === 'claude') return { skipped: !uninstallClaudeStandby(HOME) };
273
- if (host === 'gemini') return { skipped: !uninstallGeminiStandby(HOME) };
274
- const standbyCleaned = uninstallCodexStandby(HOME);
275
- const globalResidueCleaned = uninstallCodexGlobal(HOME);
276
- return { skipped: !(standbyCleaned || globalResidueCleaned) };
277
- }
278
-
279
- function cleanupHostGlobal(host) {
280
- if (host === 'claude') {
281
- uninstallClaudeStandby(HOME);
282
- return {
283
- noteCN: '如已安装 Claude Code 插件,请手动执行: /plugin remove helloagents',
284
- noteEN: 'If the Claude Code plugin is installed, remove it manually: /plugin remove helloagents',
285
- };
286
- }
287
- if (host === 'gemini') {
288
- uninstallGeminiStandby(HOME);
289
- return {
290
- noteCN: '如已安装 Gemini CLI 扩展,请手动执行: gemini extensions uninstall helloagents',
291
- noteEN: 'If the Gemini CLI extension is installed, remove it manually: gemini extensions uninstall helloagents',
292
- };
293
- }
294
- return { skipped: !uninstallCodexGlobal(HOME) };
295
- }
296
-
297
- function runHostInstall(host, mode) {
298
- return mode === 'global' ? installHostGlobal(host) : installHostStandby(host);
299
- }
300
-
301
- function runHostCleanup(host, mode) {
302
- return mode === 'global' ? cleanupHostGlobal(host) : cleanupHostStandby(host);
303
- }
304
-
305
- function installStandby() {
306
- uninstallCodexGlobal(HOME);
307
- if (installClaudeStandby(HOME, PKG_ROOT)) ok(msg('Claude Code 已配置(standby 模式)', 'Claude Code configured (standby mode)'));
308
- if (installGeminiStandby(HOME, PKG_ROOT)) ok(msg('Gemini CLI 已配置(standby 模式)', 'Gemini CLI configured (standby mode)'));
309
- if (installCodexStandby(HOME, PKG_ROOT)) ok(msg('Codex CLI 已配置(standby 模式)', 'Codex CLI configured (standby mode)'));
310
- else console.log(msg(' - Codex CLI 未检测到,跳过', ' - Codex CLI not detected, skipped'));
311
- }
312
-
313
- function installGlobal() {
314
- uninstallClaudeStandby(HOME);
315
- uninstallGeminiStandby(HOME);
316
- uninstallCodexStandby(HOME);
317
- if (installCodexGlobal(HOME, PKG_ROOT)) ok(msg('Codex CLI 已安装原生本地插件(global 模式)', 'Codex CLI native local plugin installed (global mode)'));
318
- else console.log(msg(' - Codex CLI 未检测到,跳过', ' - Codex CLI not detected, skipped'));
319
- }
320
-
321
- function uninstallAll() {
322
- uninstallClaudeStandby(HOME);
323
- uninstallGeminiStandby(HOME);
324
- uninstallCodexStandby(HOME);
325
- uninstallCodexGlobal(HOME);
326
- }
327
-
328
- function syncVersion() {
329
- const ver = pkg.version;
330
- const targets = [
331
- join(PKG_ROOT, '.claude-plugin', 'plugin.json'),
332
- join(PKG_ROOT, '.codex-plugin', 'plugin.json'),
333
- join(PKG_ROOT, 'gemini-extension.json'),
334
- ];
335
- for (const path of targets) {
336
- const obj = safeJson(path);
337
- if (obj) {
338
- obj.version = ver;
339
- safeWrite(path, JSON.stringify(obj, null, 2) + '\n');
340
- }
341
- }
342
- const marketPath = join(PKG_ROOT, '.claude-plugin', 'marketplace.json');
343
- const market = safeJson(marketPath);
344
- if (market?.plugins?.[0]) {
345
- market.plugins[0].version = ver;
346
- safeWrite(marketPath, JSON.stringify(market, null, 2) + '\n');
347
- }
348
- ok(`Version synced to ${ver}`);
349
- }
350
-
351
- function switchMode(newMode) {
352
- const config = readSettings(true);
353
- const oldMode = config.install_mode || DEFAULTS.install_mode;
354
-
355
- const isRefresh = oldMode === newMode;
356
- if (!isRefresh) {
357
- config.install_mode = newMode;
358
- ok(msg(`模式已切换为: ${newMode}`, `Mode switched to: ${newMode}`));
359
- } else {
360
- ok(msg(`当前已是 ${newMode} 模式,正在刷新安装`, `Already in ${newMode} mode, refreshing installation`));
361
- }
362
-
363
- if (newMode === 'global') installGlobal();
364
- else installStandby();
365
- setAllTrackedHostModes(config, newMode);
366
- writeSettings(config);
367
- printInstallMsg(newMode, isRefresh ? 'refresh' : 'switch');
44
+ })
45
+ initCliLifecycle({
46
+ home: HOME,
47
+ pkgRoot: PKG_ROOT,
48
+ helloagentsHome: HELLOAGENTS_HOME,
49
+ configFile: CONFIG_FILE,
50
+ pkgVersion: pkg.version,
51
+ msg,
52
+ ok,
53
+ printInstallMsg,
54
+ })
55
+ initCliDoctor({
56
+ home: HOME,
57
+ pkgRoot: PKG_ROOT,
58
+ pkgVersion: pkg.version,
59
+ msg,
60
+ readSettings,
61
+ getTrackedHostMode,
62
+ normalizeHost,
63
+ detectHostMode,
64
+ getHostLabel,
65
+ })
66
+
67
+ function printPostinstallMessage() {
68
+ console.log(`\n HelloAGENTS v${pkg.version}\n`)
69
+ ensureConfig(HELLOAGENTS_HOME, CONFIG_FILE, safeJson, ensureDir)
70
+ ok('~/.helloagents/helloagents.json')
71
+
72
+ const settings = readSettings()
73
+ const mode = settings.install_mode || DEFAULTS.install_mode
74
+ console.log(msg(
75
+ ` HelloAGENTS 包已安装,尚未自动部署到任何 CLI。\n 使用显式命令部署:\n helloagents install codex --${mode}\n helloagents install --all --${mode}\n`,
76
+ ` HelloAGENTS package installed. No CLI targets were configured automatically.\n Deploy explicitly with:\n helloagents install codex --${mode}\n helloagents install --all --${mode}\n`,
77
+ ))
368
78
  }
369
79
 
370
- function runScopedLifecycle(action, rawArgs) {
371
- const { host, explicitMode } = parseLifecycleArgs(rawArgs);
372
-
373
- if (host === 'all') {
374
- if (action === 'cleanup' || action === 'uninstall') {
375
- console.log(`\n HelloAGENTS ${msg('正在清理', 'Cleaning up')}\n`);
376
- uninstallAll();
377
- if (existsSync(CONFIG_FILE)) {
378
- const settings = readSettings();
379
- clearAllTrackedHostModes(settings);
380
- writeSettings(settings);
381
- }
382
- ok(msg('所有 CLI 配置已清理', 'All CLI configurations cleaned'));
383
- console.log(msg(
384
- ' ℹ ~/.helloagents/ 已保留(如需彻底清理请手动删除)\n ℹ 如已安装 Claude Code 插件,请手动执行: /plugin remove helloagents\n ℹ 如已安装 Gemini CLI 扩展,请手动执行: gemini extensions uninstall helloagents',
385
- ' ℹ ~/.helloagents/ preserved (delete manually if desired)\n ℹ If Claude Code plugin installed, run: /plugin remove helloagents\n ℹ If Gemini CLI extension installed, run: gemini extensions uninstall helloagents',
386
- ));
387
- console.log();
388
- return;
389
- }
390
-
391
- const settings = readSettings(true);
392
- const mode = resolveInstallMode(explicitMode, settings);
393
- if (explicitMode) settings.install_mode = explicitMode;
394
- if (mode === 'global') installGlobal();
395
- else installStandby();
396
- setAllTrackedHostModes(settings, mode);
397
- writeSettings(settings);
398
- printInstallMsg(mode, action === 'update' ? 'refresh' : 'install');
399
- return;
400
- }
401
-
402
- const shouldEnsure = action === 'install' || action === 'update';
403
- const settings = readSettings(shouldEnsure);
404
- const mode = resolveHostMode(host, explicitMode, settings);
405
- const result = (action === 'cleanup' || action === 'uninstall')
406
- ? runHostCleanup(host, mode)
407
- : runHostInstall(host, mode);
408
-
409
- if (action === 'cleanup' || action === 'uninstall') {
410
- if (existsSync(CONFIG_FILE)) {
411
- clearTrackedHostMode(settings, host);
412
- writeSettings(settings);
413
- }
414
- } else {
415
- if (!result.skipped) {
416
- setTrackedHostMode(settings, host, mode);
417
- writeSettings(settings);
418
- }
80
+ function runSafely(handler) {
81
+ try {
82
+ handler()
83
+ } catch (error) {
84
+ console.error(`\n ✗ ${error.message}\n`)
85
+ process.exitCode = 1
419
86
  }
420
-
421
- reportHostAction(action, host, mode, result);
422
87
  }
423
88
 
424
- const argv = process.argv.slice(2);
425
- const cmd = argv[0] || '';
89
+ const argv = process.argv.slice(2)
90
+ const cmd = argv[0] || ''
426
91
 
427
92
  if (cmd === 'postinstall') {
428
- console.log(`\n HelloAGENTS v${pkg.version}\n`);
429
- ensureConfig(HELLOAGENTS_HOME, CONFIG_FILE, safeJson, ensureDir);
430
- ok('~/.helloagents/helloagents.json');
431
-
432
- const settings = readSettings();
433
- const mode = settings.install_mode || DEFAULTS.install_mode;
434
- console.log(msg(
435
- ` HelloAGENTS 包已安装,尚未自动部署到任何 CLI。\n 使用显式命令部署:\n helloagents install codex --${mode}\n helloagents install --all --${mode}\n`,
436
- ` HelloAGENTS package installed. No CLI targets were configured automatically.\n Deploy explicitly with:\n helloagents install codex --${mode}\n helloagents install --all --${mode}\n`,
437
- ));
93
+ printPostinstallMessage()
438
94
  } else if (cmd === 'preuninstall') {
439
- runScopedLifecycle('cleanup', []);
95
+ runScopedLifecycle('cleanup', [])
440
96
  } else if (cmd === 'sync-version') {
441
- syncVersion();
97
+ syncVersion()
98
+ } else if (cmd === 'doctor') {
99
+ runSafely(() => runDoctor(argv.slice(1)))
442
100
  } else if (cmd === '--global' || cmd === '--standby') {
443
- switchMode(cmd === '--global' ? 'global' : 'standby');
101
+ switchMode(cmd === '--global' ? 'global' : 'standby')
444
102
  } else if (['install', 'update', 'uninstall', 'cleanup', '--cleanup'].includes(cmd)) {
445
- try {
446
- runScopedLifecycle(cmd === '--cleanup' ? 'cleanup' : cmd, argv.slice(1));
447
- } catch (error) {
448
- console.error(`\n ✗ ${error.message}\n`);
449
- process.exitCode = 1;
450
- }
103
+ runSafely(() => runScopedLifecycle(cmd === '--cleanup' ? 'cleanup' : cmd, argv.slice(1)))
451
104
  } else {
452
- printHelp();
105
+ printHelp()
453
106
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helloagents",
3
- "version": "3.0.2-beta.1",
3
+ "version": "3.0.7",
4
4
  "description": "Quality-driven orchestration kernel for AI CLIs",
5
5
  "contextFileName": "bootstrap.md",
6
6
  "author": "HelloWind",
@@ -34,6 +34,16 @@
34
34
  "timeout": 5
35
35
  }
36
36
  ]
37
+ },
38
+ {
39
+ "matcher": "Write|Edit|NotebookEdit",
40
+ "hooks": [
41
+ {
42
+ "type": "command",
43
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/guard.mjs\" pre-write",
44
+ "timeout": 5
45
+ }
46
+ ]
37
47
  }
38
48
  ],
39
49
  "PostToolUse": [
package/hooks/hooks.json CHANGED
@@ -34,6 +34,16 @@
34
34
  "timeout": 5000
35
35
  }
36
36
  ]
37
+ },
38
+ {
39
+ "matcher": "write_file|edit_file",
40
+ "hooks": [
41
+ {
42
+ "type": "command",
43
+ "command": "node \"${extensionPath}/scripts/guard.mjs\" pre-write --gemini",
44
+ "timeout": 5000
45
+ }
46
+ ]
37
47
  }
38
48
  ],
39
49
  "AfterModel": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helloagents",
3
- "version": "3.0.2-beta.1",
3
+ "version": "3.0.7",
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",
@@ -36,17 +36,7 @@
36
36
  ".claude-plugin/",
37
37
  ".codex-plugin/"
38
38
  ],
39
- "keywords": [
40
- "ai",
41
- "agent",
42
- "claude",
43
- "codex",
44
- "cli",
45
- "orchestration",
46
- "subagent",
47
- "hooks",
48
- "skills"
49
- ],
39
+ "keywords": ["ai", "agent", "claude", "codex", "cli", "orchestration", "subagent", "hooks", "skills"],
50
40
  "engines": {
51
41
  "node": ">=18"
52
42
  }