@house365/comate 0.9.19 → 0.9.22

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 (2) hide show
  1. package/bin/cli.mjs +70 -16
  2. package/package.json +1 -1
package/bin/cli.mjs CHANGED
@@ -8,10 +8,13 @@ import { dirname } from 'node:path';
8
8
  import { readFileSync } from 'node:fs';
9
9
  import { get } from 'node:https';
10
10
 
11
- import { run, skillsInvocation, SKILLS_TIMEOUT_MS } from './init.mjs';
11
+ import { run, skillsInvocation, SKILLS_TIMEOUT_MS, atLeast } from './init.mjs';
12
12
 
13
13
  // Check npm registry for the latest version and notify if an update is available.
14
14
  async function checkForUpdates(currentVersion) {
15
+ // Escape hatch: skip the network round-trip entirely. Keeps `--version`
16
+ // deterministic and offline-safe in tests and CI.
17
+ if (process.env.COMATE_NO_UPDATE_CHECK) return;
15
18
  return new Promise((resolve) => {
16
19
  const req = get('https://registry.npmjs.org/@house365/comate/latest', { timeout: 3000 }, (res) => {
17
20
  if (res.statusCode !== 200) {
@@ -24,7 +27,11 @@ async function checkForUpdates(currentVersion) {
24
27
  try {
25
28
  const pkg = JSON.parse(data);
26
29
  const latestVersion = pkg.version;
27
- if (latestVersion && latestVersion !== currentVersion) {
30
+ // Notify only when the registry is strictly newer. A plain `!==` also
31
+ // fired when local was ahead of the registry (e.g. mid-release, before
32
+ // publish lands), printing a bogus "update available" for an older
33
+ // version and polluting `--version` stdout.
34
+ if (latestVersion && atLeast(latestVersion, currentVersion) && latestVersion !== currentVersion) {
28
35
  console.log('');
29
36
  console.log(`\x1b[33m🔔 有新版本可用:${latestVersion} (当前版本:${currentVersion})\x1b[0m`);
30
37
  console.log(`\x1b[36m更新命令:npm install -g @house365/comate@latest\x1b[0m`);
@@ -44,14 +51,57 @@ async function checkForUpdates(currentVersion) {
44
51
  });
45
52
  }
46
53
 
54
+ // comate 自身的子命令(在下方被先取处理,不会透传给 skills CLI)。
55
+ const COMATE_COMMANDS = ['init', 'doctor', 'update', 'usage'];
56
+
57
+ // 允许透传给 skills CLI 的子命令(含别名)。留在这里的都是 skills CLI 真实存在
58
+ // 的命令,未列入的一律视为未知命令并命中 --help。init/update 已被 comate 先取,
59
+ // 故不在此列。
60
+ const SKILLS_PASSTHROUGH = new Set([
61
+ 'add', 'a',
62
+ 'use',
63
+ 'remove', 'rm',
64
+ 'list', 'ls',
65
+ 'find',
66
+ 'upgrade',
67
+ 'experimental_install',
68
+ 'experimental_sync',
69
+ ]);
70
+
71
+ const HELP_TEXT = `comate — SDD (规约驱动开发) 的 AI 开发编排器
72
+
73
+ 用法:
74
+ comate 安装/更新本包全部 comate skill 到当前 agent
75
+ comate init 安装 comate 和依赖到用户级,并在当前项目创建 openspec/
76
+ comate doctor 健康检查
77
+ comate update 更新 comate 到最新版本
78
+ comate usage 查看本项目 token 用量(--global 看全部;参数透传给 ccusage)
79
+ comate --help, -h 显示本帮助
80
+ comate --version, -v 显示版本号
81
+
82
+ 管理 skill(透传给 skills CLI):
83
+ comate add <包> 添加 skill 包
84
+ comate remove [名] 移除已装 skill(别名 rm)
85
+ comate list 列出已装 skill(别名 ls)
86
+ comate find [关键词] 搜索 skill
87
+
88
+ 装好后在 agent 中输入 /comate 开始使用。`;
89
+
90
+ function printHelp(stream = console.log) {
91
+ stream(HELP_TEXT);
92
+ }
93
+
47
94
  const pkgRoot = dirname(dirname(fileURLToPath(import.meta.url)));
48
95
  const args = process.argv.slice(2);
49
96
  const packageVersion = JSON.parse(readFileSync(`${pkgRoot}/package.json`, 'utf8')).version;
50
97
 
51
98
  if (args[0] === '--version' || args[0] === '-v') {
52
99
  console.log(packageVersion);
53
- // Check for updates in the background, non-blocking
54
- checkForUpdates(packageVersion).catch(() => {
100
+ // Await the check: without it, process.exit(0) fires synchronously and the
101
+ // process dies before the registry request resolves, so the update notice
102
+ // never prints. The check has its own 3s timeout, so a dead network stalls
103
+ // this by at most 3s.
104
+ await checkForUpdates(packageVersion).catch(() => {
55
105
  // Silently ignore network errors
56
106
  });
57
107
  process.exit(0);
@@ -77,22 +127,26 @@ if (args[0] === 'usage') {
77
127
  process.exit(await usage(args.slice(1), { pkgRoot }));
78
128
  }
79
129
 
80
- if (args[0] === '--help' || args[0] === '-h') {
81
- console.log(`comate — SDD (规约驱动开发) 的 AI 开发编排器
82
-
83
- 用法:
84
- comate init 安装 comate 和依赖到用户级,并在当前项目创建 openspec/
85
- comate doctor 健康检查
86
- comate update 更新 comate 到最新版本
87
- comate usage 查看本项目 token 用量(--global 看全部;参数透传给 ccusage)
88
-
89
- 装好后在 agent 中输入 /comate 开始使用。`);
130
+ if (args[0] === '--help' || args[0] === '-h' || args[0] === 'help') {
131
+ printHelp();
90
132
  process.exit(0);
91
133
  }
92
134
 
135
+ // A leading token that is neither a flag, a comate command, nor a known skills
136
+ // passthrough command is an unknown command. Print help to stderr and exit 1 so
137
+ // typos surface as usage guidance instead of an opaque skills CLI error.
138
+ if (args.length && !args[0].startsWith('-')) {
139
+ const cmd = args[0];
140
+ if (!COMATE_COMMANDS.includes(cmd) && !SKILLS_PASSTHROUGH.has(cmd)) {
141
+ console.error(`comate: 未知命令 '${cmd}'\n`);
142
+ printHelp(console.error);
143
+ process.exit(1);
144
+ }
145
+ }
146
+
93
147
  // No args, or only flags (-g, --list, …) = install every comate skill from this
94
- // package, forwarding the flags. A leading subcommand passes straight through,
95
- // so remove/list/update all still work.
148
+ // package, forwarding the flags. A leading passthrough subcommand goes straight
149
+ // through, so add/remove/list all still work.
96
150
  const argv =
97
151
  args.length && !args[0].startsWith('-') ? args : ['add', pkgRoot, '--skill', '*', ...args];
98
152
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@house365/comate",
3
- "version": "0.9.19",
3
+ "version": "0.9.22",
4
4
  "description": "comate —— SDD (规约驱动开发) 的 AI 开发编排器(Agent Skills)",
5
5
  "type": "module",
6
6
  "license": "MIT",