@house365/comate 0.4.0 → 0.5.0
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/bin/init-run.mjs +29 -6
- package/bin/postinstall.mjs +36 -0
- package/package.json +2 -1
package/bin/init-run.mjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
3
|
import { existsSync, readFileSync } from 'node:fs';
|
|
4
4
|
import { join, resolve } from 'node:path';
|
|
5
|
+
import { createInterface } from 'node:readline';
|
|
5
6
|
|
|
6
7
|
import { findBash } from './doctor.mjs';
|
|
7
8
|
import {
|
|
@@ -50,12 +51,19 @@ export async function init(pkgRoot) {
|
|
|
50
51
|
|
|
51
52
|
const target = inspectTarget(cwd, home);
|
|
52
53
|
if (target.kind !== 'project') {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
// Home directory is always refused
|
|
55
|
+
if (target.kind === 'home') {
|
|
56
|
+
console.error('\n这是主目录,请在项目目录下运行 comate init。');
|
|
57
|
+
return 1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Bare directory: ask user if they want to create a project here
|
|
61
|
+
console.log('\n当前目录不像项目(无 .git / package.json 等)。');
|
|
62
|
+
const confirmed = await askConfirm('要在这里初始化新项目吗?');
|
|
63
|
+
if (!confirmed) {
|
|
64
|
+
console.log('已取消。');
|
|
65
|
+
return 1;
|
|
66
|
+
}
|
|
59
67
|
}
|
|
60
68
|
|
|
61
69
|
// comate's skills are bash scripts needing associative arrays (bash 4+), and
|
|
@@ -167,6 +175,21 @@ export async function init(pkgRoot) {
|
|
|
167
175
|
return report(results);
|
|
168
176
|
}
|
|
169
177
|
|
|
178
|
+
// A yes/no prompt. Defaults to "no" so a piped/non-interactive run (CI, an
|
|
179
|
+
// unattended npx) never silently scaffolds a project into whatever directory it
|
|
180
|
+
// happened to land in — those callers should point at a real project instead.
|
|
181
|
+
// [y/N]: empty input, EOF (Ctrl-D / closed stdin), or anything but y/yes = no.
|
|
182
|
+
export function askConfirm(question, { input = process.stdin, output = process.stdout } = {}) {
|
|
183
|
+
if (!input.isTTY) return Promise.resolve(false);
|
|
184
|
+
const rl = createInterface({ input, output });
|
|
185
|
+
return new Promise((done) => {
|
|
186
|
+
rl.question(`${question} [y/N] `, (answer) => {
|
|
187
|
+
rl.close();
|
|
188
|
+
done(/^\s*y(es)?\s*$/i.test(answer));
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
170
193
|
// The spinner runs in its own process because every step above is a synchronous
|
|
171
194
|
// spawnSync — an interval on this thread would never fire. In a pipe \r does not
|
|
172
195
|
// overwrite, so animating there would leave every frame on screen; print one
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Postinstall hook: show the wordmark and next steps after npm install finishes.
|
|
3
|
+
// Skipped in CI (where the logo wouldn't render anyway) and local dev installs
|
|
4
|
+
// (where the developer already knows what they installed).
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { dirname, resolve } from 'node:path';
|
|
7
|
+
|
|
8
|
+
const pkgRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
9
|
+
|
|
10
|
+
// Skip in CI, or when installing the package's own dependencies during dev.
|
|
11
|
+
if (isCI() || isDevInstall()) {
|
|
12
|
+
process.exit(0);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { banner, pkgVersion } = await import('./init-run.mjs');
|
|
16
|
+
|
|
17
|
+
console.log(banner(pkgVersion(pkgRoot)));
|
|
18
|
+
console.log(` 🎉 Congratulations! comate 已成功安装。\n`);
|
|
19
|
+
console.log(' 下一步:');
|
|
20
|
+
console.log(' 在你的项目目录下运行 comate init 开始使用');
|
|
21
|
+
console.log(' 或运行 comate doctor 健康检查');
|
|
22
|
+
console.log(' 更多帮助 comate --help\n');
|
|
23
|
+
|
|
24
|
+
function isCI() {
|
|
25
|
+
return Boolean(process.env.CI || process.env.GITHUB_ACTIONS);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// When npm installs a package's own dependencies (npm i in the repo itself),
|
|
29
|
+
// INIT_CWD points to the package root. A user installing comate globally or as
|
|
30
|
+
// a dependency has INIT_CWD pointing elsewhere.
|
|
31
|
+
function isDevInstall() {
|
|
32
|
+
const initCwd = process.env.INIT_CWD;
|
|
33
|
+
if (!initCwd) return false;
|
|
34
|
+
const normalise = (p) => resolve(p).replace(/[\\/]+$/, '').toLowerCase();
|
|
35
|
+
return normalise(initCwd) === normalise(pkgRoot);
|
|
36
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@house365/comate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "comate —— OpenSpec + Superpowers 规约驱动的 AI 开发编排器(Agent Skills)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"skills": "^1.5.21"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
|
+
"postinstall": "node bin/postinstall.mjs",
|
|
47
48
|
"test": "node bin/init.test.mjs && bash skills/comate/tests/run.sh",
|
|
48
49
|
"doctor": "cd skills && bash comate/scripts/comate.sh doctor",
|
|
49
50
|
"prepublish-check": "node scripts/prepublish-check.mjs",
|