helloagents 1.0.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/Claude/Skills/CN/CLAUDE.md +998 -0
- package/Claude/Skills/CN/skills/helloagents/analyze/SKILL.md +187 -0
- package/Claude/Skills/CN/skills/helloagents/design/SKILL.md +261 -0
- package/Claude/Skills/CN/skills/helloagents/develop/SKILL.md +352 -0
- package/Claude/Skills/CN/skills/helloagents/kb/SKILL.md +249 -0
- package/Claude/Skills/CN/skills/helloagents/templates/SKILL.md +451 -0
- package/Claude/Skills/EN/CLAUDE.md +998 -0
- package/Claude/Skills/EN/skills/helloagents/analyze/SKILL.md +187 -0
- package/Claude/Skills/EN/skills/helloagents/design/SKILL.md +261 -0
- package/Claude/Skills/EN/skills/helloagents/develop/SKILL.md +352 -0
- package/Claude/Skills/EN/skills/helloagents/kb/SKILL.md +249 -0
- package/Claude/Skills/EN/skills/helloagents/templates/SKILL.md +451 -0
- package/Codex/Skills/CN/AGENTS.md +998 -0
- package/Codex/Skills/CN/skills/helloagents/analyze/SKILL.md +187 -0
- package/Codex/Skills/CN/skills/helloagents/design/SKILL.md +261 -0
- package/Codex/Skills/CN/skills/helloagents/develop/SKILL.md +352 -0
- package/Codex/Skills/CN/skills/helloagents/kb/SKILL.md +249 -0
- package/Codex/Skills/CN/skills/helloagents/templates/SKILL.md +451 -0
- package/Codex/Skills/EN/AGENTS.md +998 -0
- package/Codex/Skills/EN/skills/helloagents/analyze/SKILL.md +187 -0
- package/Codex/Skills/EN/skills/helloagents/design/SKILL.md +261 -0
- package/Codex/Skills/EN/skills/helloagents/develop/SKILL.md +352 -0
- package/Codex/Skills/EN/skills/helloagents/kb/SKILL.md +249 -0
- package/Codex/Skills/EN/skills/helloagents/templates/SKILL.md +451 -0
- package/README.md +840 -0
- package/bin/cli.js +85 -0
- package/lib/args.js +106 -0
- package/lib/backup.js +81 -0
- package/lib/conflict.js +118 -0
- package/lib/copy.js +125 -0
- package/lib/defaults.js +47 -0
- package/lib/index.js +297 -0
- package/lib/output.js +220 -0
- package/lib/prompts.js +173 -0
- package/lib/utils.js +225 -0
- package/package.json +38 -0
package/lib/utils.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utils - Utility functions with dependency injection support
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const fsPromises = require('fs').promises;
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const os = require('os');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get home directory (injectable for testing)
|
|
14
|
+
* @param {Object} deps - Dependencies
|
|
15
|
+
* @returns {string} Home directory path
|
|
16
|
+
*/
|
|
17
|
+
function getHomeDir(deps = {}) {
|
|
18
|
+
if (deps.homeDir) {
|
|
19
|
+
return deps.homeDir;
|
|
20
|
+
}
|
|
21
|
+
return os.homedir();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get timestamp string (injectable for testing)
|
|
26
|
+
* @param {Object} deps - Dependencies
|
|
27
|
+
* @returns {string} Timestamp in YYYYMMDD-HHmmss format
|
|
28
|
+
*/
|
|
29
|
+
function getTimestamp(deps = {}) {
|
|
30
|
+
const now = deps.now ? deps.now() : new Date();
|
|
31
|
+
const year = now.getFullYear();
|
|
32
|
+
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
33
|
+
const day = String(now.getDate()).padStart(2, '0');
|
|
34
|
+
const hours = String(now.getHours()).padStart(2, '0');
|
|
35
|
+
const minutes = String(now.getMinutes()).padStart(2, '0');
|
|
36
|
+
const seconds = String(now.getSeconds()).padStart(2, '0');
|
|
37
|
+
return `${year}${month}${day}-${hours}${minutes}${seconds}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Generate random suffix (injectable for testing)
|
|
42
|
+
* @param {Object} deps - Dependencies
|
|
43
|
+
* @returns {string} Random 6-character string
|
|
44
|
+
*/
|
|
45
|
+
function randomSuffix(deps = {}) {
|
|
46
|
+
if (deps.randomSuffix) {
|
|
47
|
+
return deps.randomSuffix();
|
|
48
|
+
}
|
|
49
|
+
return Math.random().toString(36).slice(2, 8);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Check if file exists
|
|
54
|
+
* @param {string} filePath - Path to check
|
|
55
|
+
* @param {Object} deps - Dependencies
|
|
56
|
+
* @returns {Promise<boolean>}
|
|
57
|
+
*/
|
|
58
|
+
async function fileExists(filePath, deps = {}) {
|
|
59
|
+
const fsModule = deps.fs || fsPromises;
|
|
60
|
+
try {
|
|
61
|
+
const stat = await fsModule.stat(filePath);
|
|
62
|
+
return stat.isFile();
|
|
63
|
+
} catch (err) {
|
|
64
|
+
if (err.code === 'ENOENT') {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
throw err;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Check if directory exists
|
|
73
|
+
* @param {string} dirPath - Path to check
|
|
74
|
+
* @param {Object} deps - Dependencies
|
|
75
|
+
* @returns {Promise<boolean>}
|
|
76
|
+
*/
|
|
77
|
+
async function dirExists(dirPath, deps = {}) {
|
|
78
|
+
const fsModule = deps.fs || fsPromises;
|
|
79
|
+
try {
|
|
80
|
+
const stat = await fsModule.stat(dirPath);
|
|
81
|
+
return stat.isDirectory();
|
|
82
|
+
} catch (err) {
|
|
83
|
+
if (err.code === 'ENOENT') {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Read file content
|
|
92
|
+
* @param {string} filePath - Path to read
|
|
93
|
+
* @param {Object} deps - Dependencies
|
|
94
|
+
* @returns {Promise<string>}
|
|
95
|
+
*/
|
|
96
|
+
async function readFileContent(filePath, deps = {}) {
|
|
97
|
+
const fsModule = deps.fs || fsPromises;
|
|
98
|
+
return fsModule.readFile(filePath, 'utf8');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Recursive delete (compatible with Node 14)
|
|
103
|
+
* @param {string} targetPath - Path to delete
|
|
104
|
+
* @param {Object} deps - Dependencies
|
|
105
|
+
* @returns {Promise<void>}
|
|
106
|
+
*/
|
|
107
|
+
async function rmrf(targetPath, deps = {}) {
|
|
108
|
+
const fsModule = deps.fs || fsPromises;
|
|
109
|
+
|
|
110
|
+
// Check if path exists
|
|
111
|
+
try {
|
|
112
|
+
await fsModule.stat(targetPath);
|
|
113
|
+
} catch (err) {
|
|
114
|
+
if (err.code === 'ENOENT') {
|
|
115
|
+
return; // Already doesn't exist
|
|
116
|
+
}
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Try fs.rm first (Node 14.14+)
|
|
121
|
+
if (fsModule.rm) {
|
|
122
|
+
try {
|
|
123
|
+
await fsModule.rm(targetPath, { recursive: true, force: true });
|
|
124
|
+
return;
|
|
125
|
+
} catch (err) {
|
|
126
|
+
// Fall through to rmdir
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Fallback to fs.rmdir with recursive (Node 14.0+)
|
|
131
|
+
if (fsModule.rmdir) {
|
|
132
|
+
await fsModule.rmdir(targetPath, { recursive: true });
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Manual recursive delete as last resort
|
|
137
|
+
const stat = await fsModule.stat(targetPath);
|
|
138
|
+
if (stat.isDirectory()) {
|
|
139
|
+
const entries = await fsModule.readdir(targetPath);
|
|
140
|
+
for (const entry of entries) {
|
|
141
|
+
await rmrf(path.join(targetPath, entry), deps);
|
|
142
|
+
}
|
|
143
|
+
await fsModule.rmdir(targetPath);
|
|
144
|
+
} else {
|
|
145
|
+
await fsModule.unlink(targetPath);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Ensure directory exists (create if not)
|
|
151
|
+
* @param {string} dirPath - Directory path
|
|
152
|
+
* @param {Object} deps - Dependencies
|
|
153
|
+
* @returns {Promise<void>}
|
|
154
|
+
*/
|
|
155
|
+
async function ensureDir(dirPath, deps = {}) {
|
|
156
|
+
const fsModule = deps.fs || fsPromises;
|
|
157
|
+
try {
|
|
158
|
+
await fsModule.mkdir(dirPath, { recursive: true });
|
|
159
|
+
} catch (err) {
|
|
160
|
+
if (err.code !== 'EEXIST') {
|
|
161
|
+
throw err;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Get package root directory (where package.json is)
|
|
168
|
+
* @returns {string}
|
|
169
|
+
*/
|
|
170
|
+
function getPackageRoot() {
|
|
171
|
+
return path.resolve(__dirname, '..');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Get source path for platform and language
|
|
176
|
+
* @param {string} platform - 'claude' or 'codex'
|
|
177
|
+
* @param {string} lang - 'cn' or 'en'
|
|
178
|
+
* @returns {Object} { configFile, skillsDir }
|
|
179
|
+
*/
|
|
180
|
+
function getSourcePaths(platform, lang) {
|
|
181
|
+
const root = getPackageRoot();
|
|
182
|
+
const platformDir = platform === 'claude' ? 'Claude' : 'Codex';
|
|
183
|
+
const langDir = lang === 'cn' ? 'CN' : 'EN';
|
|
184
|
+
const configFileName = platform === 'claude' ? 'CLAUDE.md' : 'AGENTS.md';
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
configFile: path.join(root, platformDir, 'Skills', langDir, configFileName),
|
|
188
|
+
skillsDir: path.join(root, platformDir, 'Skills', langDir, 'skills', 'helloagents'),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Get target path for platform
|
|
194
|
+
* @param {string} platform - 'claude' or 'codex'
|
|
195
|
+
* @param {Object} deps - Dependencies
|
|
196
|
+
* @returns {Object} { targetDir, configFile, skillsDir, newFile }
|
|
197
|
+
*/
|
|
198
|
+
function getTargetPaths(platform, deps = {}) {
|
|
199
|
+
const homeDir = getHomeDir(deps);
|
|
200
|
+
const targetDir = platform === 'claude'
|
|
201
|
+
? path.join(homeDir, '.claude')
|
|
202
|
+
: path.join(homeDir, '.codex');
|
|
203
|
+
const configFileName = platform === 'claude' ? 'CLAUDE.md' : 'AGENTS.md';
|
|
204
|
+
|
|
205
|
+
return {
|
|
206
|
+
targetDir,
|
|
207
|
+
configFile: path.join(targetDir, configFileName),
|
|
208
|
+
skillsDir: path.join(targetDir, 'skills', 'helloagents'),
|
|
209
|
+
newFile: path.join(targetDir, '.helloagents.new'),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
module.exports = {
|
|
214
|
+
getHomeDir,
|
|
215
|
+
getTimestamp,
|
|
216
|
+
randomSuffix,
|
|
217
|
+
fileExists,
|
|
218
|
+
dirExists,
|
|
219
|
+
readFileContent,
|
|
220
|
+
rmrf,
|
|
221
|
+
ensureDir,
|
|
222
|
+
getPackageRoot,
|
|
223
|
+
getSourcePaths,
|
|
224
|
+
getTargetPaths,
|
|
225
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "helloagents",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI tool to configure HelloAGENTS for Claude Code and Codex",
|
|
5
|
+
"bin": {
|
|
6
|
+
"helloagents": "bin/cli.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin/",
|
|
10
|
+
"lib/",
|
|
11
|
+
"Claude/",
|
|
12
|
+
"Codex/"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"test": "node test/run.js"
|
|
16
|
+
},
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=14.0.0"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"cli",
|
|
22
|
+
"claude",
|
|
23
|
+
"codex",
|
|
24
|
+
"ai",
|
|
25
|
+
"agents",
|
|
26
|
+
"helloagents"
|
|
27
|
+
],
|
|
28
|
+
"author": "",
|
|
29
|
+
"license": "Apache-2.0",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/hellowind777/helloagents.git"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/hellowind777/helloagents#readme",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/hellowind777/helloagents/issues"
|
|
37
|
+
}
|
|
38
|
+
}
|