@blod-nm/1kuan-act-01-cli 0.1.3 → 0.1.4
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/README.md +13 -1
- package/package.json +1 -1
- package/src/main.js +98 -7
- package/src/skill.js +6 -1
- package/src/version.js +1 -1
package/README.md
CHANGED
|
@@ -30,15 +30,27 @@ act-01 config import "act01w.v1.xxxx" # prompts for the passphrase used at gen
|
|
|
30
30
|
|
|
31
31
|
Transfer strings are AES-256-GCM encrypted; the passphrase never travels with the string.
|
|
32
32
|
|
|
33
|
+
## One-shot setup
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
ACT01_EXPORT_PASS="<passphrase>" act-01 setup --install ~/.claude/skills "<config-string>"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Installs the skill doc, imports the config, and prints the balance in one command
|
|
40
|
+
(passphrase via env; config string also accepted on stdin or `ACT01_IMPORT_STRING`).
|
|
41
|
+
`--install <dir>` writes `<dir>/act-01-ops/SKILL.md`.
|
|
42
|
+
|
|
33
43
|
## Operations
|
|
34
44
|
|
|
35
45
|
```bash
|
|
36
|
-
act-01
|
|
46
|
+
act-01 redpacket check --mode random --total 10000 --count 50 --per-user 2 --min 100 --max 500
|
|
47
|
+
act-01 redpacket create --mode random --total 10000 --count 50 --per-user 2 --min 100 --max 500 --yes
|
|
37
48
|
```
|
|
38
49
|
|
|
39
50
|
- Amounts are integer units, no conversion
|
|
40
51
|
- Pre-flight balance check runs before execution; insufficient balance is rejected locally
|
|
41
52
|
- Interactive confirm card lists every parameter before the atomic database function call
|
|
53
|
+
- `create` is non-interactive only with `--yes` (otherwise it asks for confirmation)
|
|
42
54
|
- `--dry-run` prints the function call without executing; `--json` for machine output
|
|
43
55
|
|
|
44
56
|
## MCP (AI client integration)
|
package/package.json
CHANGED
package/src/main.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { parseArgs } from 'node:util'
|
|
6
|
+
import { mkdirSync, writeFileSync } from 'node:fs'
|
|
6
7
|
import { VERSION } from './version.js'
|
|
7
8
|
import { join } from 'node:path'
|
|
8
9
|
import { configPath, expandPath, loadConfig, saveConfig, decodeConfigString, encryptConfig } from './store.js'
|
|
@@ -23,8 +24,9 @@ const USAGE = `act-01 —— operations CLI(invoke preset database functions)
|
|
|
23
24
|
config test 连接测试(SELECT 1,验证 envId/apiKey)
|
|
24
25
|
config export 导出加密配置串(口令交互输入或 ACT01_EXPORT_PASS)
|
|
25
26
|
config import <串|--stdin> [--pass <口令>] 导入配置串(加密串需口令;自动识别 三种格式)
|
|
27
|
+
setup <串|--stdin> [--install <技能根目录>] 一条命令:装技能 + 导配置 + 查余额
|
|
26
28
|
mcp 启动 MCP 服务(stdio;接入 Claude 等 AI 客户端)
|
|
27
|
-
skill 输出 agent 技能文档(--install <
|
|
29
|
+
skill 输出 agent 技能文档(--install <技能根目录> 装成 <root>/act-01-ops/SKILL.md)
|
|
28
30
|
balance account balance
|
|
29
31
|
redpacket create create a record(pre-flight balance check, atomic deduct)
|
|
30
32
|
redpacket check validate params(side-effect free)
|
|
@@ -150,6 +152,23 @@ async function cmdConfig(argv) {
|
|
|
150
152
|
throw err
|
|
151
153
|
}
|
|
152
154
|
|
|
155
|
+
if (sub === 'test') {
|
|
156
|
+
const config = loadConfig()
|
|
157
|
+
const apikey = resolveApikey(config, undefined)
|
|
158
|
+
if (!config.envId || !apikey) {
|
|
159
|
+
const err = new Error('配置不完整:先 config set envId 和 apiKey')
|
|
160
|
+
err.exitCode = 2
|
|
161
|
+
throw err
|
|
162
|
+
}
|
|
163
|
+
const r = await execPgsql(config, apikey, 'SELECT 1 AS ok')
|
|
164
|
+
if (!r.ok) {
|
|
165
|
+
console.error(`error: 连接测试失败 (${r.message})`)
|
|
166
|
+
return 1
|
|
167
|
+
}
|
|
168
|
+
console.log('连接测试通过(SELECT 1)')
|
|
169
|
+
return 0
|
|
170
|
+
}
|
|
171
|
+
|
|
153
172
|
if (sub === 'export') {
|
|
154
173
|
const config = loadConfig()
|
|
155
174
|
if (!config.envId || !config.apiKey) {
|
|
@@ -317,6 +336,15 @@ function normalizeFromValues(values) {
|
|
|
317
336
|
|
|
318
337
|
/* ---------- skill ---------- */
|
|
319
338
|
|
|
339
|
+
/** 把 SKILL.md 装到 <root>/<SKILL_NAME>/SKILL.md(目录式,匹配主流 agent 技能布局) */
|
|
340
|
+
function installSkill(root) {
|
|
341
|
+
const dir = join(expandPath(root), SKILL_NAME)
|
|
342
|
+
mkdirSync(dir, { recursive: true, mode: 0o755 })
|
|
343
|
+
const file = join(dir, 'SKILL.md')
|
|
344
|
+
writeFileSync(file, SKILL_MD)
|
|
345
|
+
return file
|
|
346
|
+
}
|
|
347
|
+
|
|
320
348
|
async function cmdSkill(argv) {
|
|
321
349
|
const { values, positionals } = parseArgs({
|
|
322
350
|
strict: false,
|
|
@@ -332,13 +360,9 @@ async function cmdSkill(argv) {
|
|
|
332
360
|
}
|
|
333
361
|
|
|
334
362
|
if (values.install) {
|
|
335
|
-
const
|
|
336
|
-
const dir = expandPath(values.install)
|
|
337
|
-
mkdirSync(dir, { recursive: true, mode: 0o755 })
|
|
338
|
-
const file = join(dir, 'SKILL.md')
|
|
339
|
-
writeFileSync(file, SKILL_MD)
|
|
363
|
+
const file = installSkill(values.install)
|
|
340
364
|
console.log(`SKILL.md 已写入: ${file}`)
|
|
341
|
-
console.error(
|
|
365
|
+
console.error(`hint: 已装成 <技能根目录>/${SKILL_NAME}/SKILL.md;根目录指你的 agent 扫描的那个 skills 目录`)
|
|
342
366
|
return 0
|
|
343
367
|
}
|
|
344
368
|
|
|
@@ -346,6 +370,72 @@ async function cmdSkill(argv) {
|
|
|
346
370
|
return 0
|
|
347
371
|
}
|
|
348
372
|
|
|
373
|
+
/* ---------- setup(一条命令:装技能 + 导配置 + 查余额) ---------- */
|
|
374
|
+
|
|
375
|
+
/** 解析配置串(明文/加密)、写盘;返回 { envId, apiKey } */
|
|
376
|
+
function importConfig(body, passFlag) {
|
|
377
|
+
const decoded = decodeConfigString(body)
|
|
378
|
+
let cfg = decoded.config
|
|
379
|
+
if (decoded.encrypted) {
|
|
380
|
+
const pass = passFlag ?? process.env.ACT01_EXPORT_PASS
|
|
381
|
+
if (!pass) {
|
|
382
|
+
const err = new Error('加密串需要口令:用 ACT01_EXPORT_PASS 环境变量或 --pass 传入')
|
|
383
|
+
err.exitCode = 2
|
|
384
|
+
throw err
|
|
385
|
+
}
|
|
386
|
+
cfg = decoded.decode(pass)
|
|
387
|
+
}
|
|
388
|
+
if (!cfg.envId || !cfg.apiKey) {
|
|
389
|
+
const err = new Error('配置串内容不完整(缺 envId 或 apiKey)')
|
|
390
|
+
err.exitCode = 2
|
|
391
|
+
throw err
|
|
392
|
+
}
|
|
393
|
+
saveConfig({ envId: cfg.envId, apiKey: cfg.apiKey })
|
|
394
|
+
return cfg
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
async function cmdSetup(argv) {
|
|
398
|
+
const { values, positionals } = parseArgs({
|
|
399
|
+
strict: false,
|
|
400
|
+
allowPositionals: true,
|
|
401
|
+
args: argv,
|
|
402
|
+
options: { install: { type: 'string' }, pass: { type: 'string' }, json: { type: 'boolean', short: 'j' } },
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
let body = positionals[0] ?? process.env.ACT01_IMPORT_STRING
|
|
406
|
+
if (!body && !process.stdin.isTTY) body = await readStdinText()
|
|
407
|
+
if (!body) {
|
|
408
|
+
const err = new Error('setup 需要 <配置串>(位置参数 / stdin / ACT01_IMPORT_STRING)')
|
|
409
|
+
err.exitCode = 2
|
|
410
|
+
throw err
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const cfg = importConfig(body, str(values, 'pass'))
|
|
414
|
+
const skillPath = values.install ? installSkill(values.install) : null
|
|
415
|
+
|
|
416
|
+
const account = await execPgsql(cfg, resolveApikey(cfg, undefined), ACCOUNT_SQL)
|
|
417
|
+
const wallet =
|
|
418
|
+
account.ok && account.rows?.[0]?.data?.wallet && typeof account.rows[0].data.wallet === 'object'
|
|
419
|
+
? account.rows[0].data.wallet
|
|
420
|
+
: {}
|
|
421
|
+
const points = account.ok ? Number(wallet.points || 0) : null
|
|
422
|
+
const label = account.ok ? String(wallet.label || 'account') : null
|
|
423
|
+
|
|
424
|
+
if (values.json === true) {
|
|
425
|
+
printJson({ ok: account.ok, envId: cfg.envId, apiKeySet: true, skillPath, balance: points, account: label, error: account.ok ? null : account.message })
|
|
426
|
+
} else {
|
|
427
|
+
console.log('setup 完成:')
|
|
428
|
+
console.log(skillPath ? ` 技能: SKILL.md → ${skillPath}` : ' 技能: (未装;加 --install <技能根目录>)')
|
|
429
|
+
console.log(` 配置: envId ${cfg.envId},apiKey 已打码写入 0600`)
|
|
430
|
+
if (account.ok) console.log(` 余额: ${points}(${label})`)
|
|
431
|
+
else {
|
|
432
|
+
console.error(` 余额: 查询失败 (${account.message})`)
|
|
433
|
+
return 1
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return 0
|
|
437
|
+
}
|
|
438
|
+
|
|
349
439
|
/* ---------- redpacket check(零副作用参数校验) ---------- */
|
|
350
440
|
|
|
351
441
|
async function cmdCheck(argv) {
|
|
@@ -527,6 +617,7 @@ export async function main(argv) {
|
|
|
527
617
|
if (cmd === 'balance') return await cmdBalance(argv.slice(1))
|
|
528
618
|
if (cmd === 'mcp') return await startMcp()
|
|
529
619
|
if (cmd === 'skill') return await cmdSkill(argv.slice(1))
|
|
620
|
+
if (cmd === 'setup') return await cmdSetup(argv.slice(1))
|
|
530
621
|
if (cmd === 'redpacket') {
|
|
531
622
|
const sub = argv[1]
|
|
532
623
|
if (sub === 'create') return await cmdCreate(argv.slice(2))
|
package/src/skill.js
CHANGED
|
@@ -23,6 +23,11 @@ const BODY = [
|
|
|
23
23
|
'',
|
|
24
24
|
'所有命令零依赖,Node >= 18。',
|
|
25
25
|
'',
|
|
26
|
+
'## 一条命令装好(推荐)',
|
|
27
|
+
'',
|
|
28
|
+
B + 'act-01 setup "<配置串>" --install <技能根目录>' + B + ' —— 一次完成:装技能 + 导配置 + 查余额,',
|
|
29
|
+
'口令走 ' + B + 'ACT01_EXPORT_PASS' + B + ' 环境变量;配置串也可走 stdin 或 ' + B + 'ACT01_IMPORT_STRING' + B + '。',
|
|
30
|
+
'',
|
|
26
31
|
'## 工具面',
|
|
27
32
|
'',
|
|
28
33
|
'| 途径 | 命令 / MCP 工具 | 副作用 |',
|
|
@@ -54,7 +59,7 @@ const BODY = [
|
|
|
54
59
|
'## Agent 行为规则',
|
|
55
60
|
'',
|
|
56
61
|
'1. **先 check 后 create**:参数没把握时,先调 redpacket_check,拿到校验报告再执行',
|
|
57
|
-
'2. **create 前必须向用户确认参数**(mode/total/count/区间/群归属)
|
|
62
|
+
'2. **create 前必须向用户确认参数**(mode/total/count/区间/群归属);确认后执行时,**非交互(非 TTY)必须带 --yes**,否则 CLI 会拒绝(MCP 客户端则弹审批)',
|
|
58
63
|
'3. **结果转述只给摘要**:packet_no、余额变化;不要猜测或编造未返回的字段',
|
|
59
64
|
'4. **失败处理**:错误信息是人话(余额不足/区间错误/整除错误),原样转告用户并给出修正建议;不要重试同参数的 create',
|
|
60
65
|
'5. **金额单位**:内部整数单位,不要做 ×100 或 ÷100 的换算,除非用户明确要求',
|
package/src/version.js
CHANGED