@blod-nm/1kuan-act-01-cli 0.1.0 → 0.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blod-nm/1kuan-act-01-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "description": "Internal operations CLI: invoke preset database functions via a gateway. Zero dependencies, MCP (stdio) support.",
6
6
  "license": "MIT",
@@ -37,4 +37,4 @@
37
37
  "access": "public",
38
38
  "registry": "https://registry.npmjs.org"
39
39
  }
40
- }
40
+ }
package/src/main.js CHANGED
@@ -3,9 +3,11 @@
3
3
  */
4
4
 
5
5
  import { parseArgs } from 'node:util'
6
- import { configPath, loadConfig, saveConfig, decodeConfigString, encryptConfig } from './store.js'
6
+ import { join } from 'node:path'
7
+ import { configPath, expandPath, loadConfig, saveConfig, decodeConfigString, encryptConfig } from './store.js'
7
8
  import { ACCOUNT_SQL, execPgsql, resolveApikey, gatewayBase } from './tcb.js'
8
9
  import { buildCreateSql, confirmSummary, normalizeCreateRedpacket } from './redpacket.js'
10
+ import { SKILL_MD, SKILL_NAME } from './skill.js'
9
11
  import { startMcp } from './mcp.js'
10
12
 
11
13
  const VERSION = '0.1.0'
@@ -22,6 +24,7 @@ const USAGE = `act-01 —— operations CLI(invoke preset database functions)
22
24
  config export 导出加密配置串(口令交互输入或 ACT01_EXPORT_PASS)
23
25
  config import <串|--stdin> 导入配置串(自动识别 加密/明文/网页格式)
24
26
  mcp 启动 MCP 服务(stdio;接入 Claude 等 AI 客户端)
27
+ skill 输出 agent 技能文档(--install <dir> 写入)
25
28
  balance account balance
26
29
  redpacket create create a record(pre-flight balance check, atomic deduct)
27
30
  redpacket check validate params(side-effect free)
@@ -306,6 +309,37 @@ function normalizeFromValues(values) {
306
309
  })
307
310
  }
308
311
 
312
+ /* ---------- skill ---------- */
313
+
314
+ async function cmdSkill(argv) {
315
+ const { values, positionals } = parseArgs({
316
+ strict: false,
317
+ allowPositionals: true,
318
+ args: argv,
319
+ options: { install: { type: 'string' } },
320
+ })
321
+ const sub = positionals[0] ?? SKILL_NAME
322
+ if (sub !== SKILL_NAME) {
323
+ const err = new Error(`未知 skill: ${sub}(可用: ${SKILL_NAME})`)
324
+ err.exitCode = 2
325
+ throw err
326
+ }
327
+
328
+ if (values.install) {
329
+ const { mkdirSync, writeFileSync } = await import('node:fs')
330
+ const dir = expandPath(values.install)
331
+ mkdirSync(dir, { recursive: true, mode: 0o755 })
332
+ const file = join(dir, 'SKILL.md')
333
+ writeFileSync(file, SKILL_MD)
334
+ console.log(`SKILL.md 已写入: ${file}`)
335
+ console.error('hint: 把该目录加入你的 agent 技能路径')
336
+ return 0
337
+ }
338
+
339
+ console.log(SKILL_MD)
340
+ return 0
341
+ }
342
+
309
343
  /* ---------- redpacket check(零副作用参数校验) ---------- */
310
344
 
311
345
  async function cmdCheck(argv) {
@@ -486,6 +520,7 @@ export async function main(argv) {
486
520
  if (cmd === 'config') return await cmdConfig(argv.slice(1))
487
521
  if (cmd === 'balance') return await cmdBalance(argv.slice(1))
488
522
  if (cmd === 'mcp') return await startMcp()
523
+ if (cmd === 'skill') return await cmdSkill(argv.slice(1))
489
524
  if (cmd === 'redpacket') {
490
525
  const sub = argv[1]
491
526
  if (sub === 'create') return await cmdCreate(argv.slice(2))
package/src/skill.js ADDED
@@ -0,0 +1,83 @@
1
+ /**
2
+ * 内置 agent skill:给 AI 客户端的完整操作技能文档。
3
+ * act-01 skill → 打印 SKILL.md(agent 抓 stdout 即可)
4
+ * act-01 skill --install <dir> → 写入 <dir>/SKILL.md
5
+ */
6
+
7
+ const B = '`' // 模板串内的反引号统一用变量拼接,避免转义地狱
8
+
9
+ const BODY = [
10
+ '---',
11
+ 'name: act-01-ops',
12
+ 'description: act-01 运营操作技能——通过 act-01 CLI / MCP 工具安全地创建 packet、查询余额。资金操作,遵守三道闸门。',
13
+ '---',
14
+ '',
15
+ '# act-01 运营操作',
16
+ '',
17
+ '通过云开发网关调用预置数据库函数(原子操作)。',
18
+ '',
19
+ '## 运行方式(二选一)',
20
+ '',
21
+ '- 已全局安装:' + B + 'act-01 <命令>' + B,
22
+ '- 未安装:每条命令前加 ' + B + 'npx -y @blod-nm/1kuan-act-01-cli' + B + ',如 ' + B + 'npx -y @blod-nm/1kuan-act-01-cli balance' + B,
23
+ '',
24
+ '所有命令零依赖,Node >= 18。',
25
+ '',
26
+ '## 工具面',
27
+ '',
28
+ '| 途径 | 命令 / MCP 工具 | 副作用 |',
29
+ '|---|---|---|',
30
+ '| 参数校验 | ' + B + 'act-01 redpacket check <flags>' + B + ' / ' + B + 'redpacket_check' + B + ' | 零副作用,优先用 |',
31
+ '| 余额查询 | ' + B + 'act-01 balance' + B + ' / ' + B + 'balance' + B + ' | 只读 |',
32
+ '| 创建 packet | ' + B + 'act-01 redpacket create <flags>' + B + ' / ' + B + 'redpacket_create' + B + ' | **有副作用:账户原子扣减** |',
33
+ '',
34
+ '## create 参数规格',
35
+ '',
36
+ '| 参数 | 规则 |',
37
+ '|---|---|',
38
+ '| mode | random(随机)/ equal(均分) |',
39
+ '| total_points | 正整数(内部单位,不换算) |',
40
+ '| count | 正整数(份数) |',
41
+ '| per_user_limit | 正整数,≤ count |',
42
+ '| min_points / max_points(仅 random) | max ≥ min;total ∈ [min×count, max×count];total % count === 0 |',
43
+ '| share_title / note | 可选,≤60 / ≤20 字 |',
44
+ '| require_group | 布尔,默认 false |',
45
+ '',
46
+ 'equal 模式自动 min = floor(total/count),max = ceil(total/count)。',
47
+ '',
48
+ '## 安全三道闸门',
49
+ '',
50
+ '1. **CLI 预检**:balance < total_points 时直接拒绝(不触数据库写)',
51
+ '2. **确认卡**:执行前列出全部参数,等用户确认',
52
+ '3. **库函数原子扣减**:并发/余额竞争由数据库兜底,不会扣穿',
53
+ '',
54
+ '## Agent 行为规则',
55
+ '',
56
+ '1. **先 check 后 create**:参数没把握时,先调 redpacket_check,拿到校验报告再执行',
57
+ '2. **create 前必须向用户确认参数**(mode/total/count/区间/群归属),MCP 客户端会弹审批',
58
+ '3. **结果转述只给摘要**:packet_no、余额变化;不要猜测或编造未返回的字段',
59
+ '4. **失败处理**:错误信息是人话(余额不足/区间错误/整除错误),原样转告用户并给出修正建议;不要重试同参数的 create',
60
+ '5. **金额单位**:内部整数单位,不要做 ×100 或 ÷100 的换算,除非用户明确要求',
61
+ '',
62
+ '## 失败速查',
63
+ '',
64
+ '| 错误含 | 含义 | 修正 |',
65
+ '|---|---|---|',
66
+ '| 可分配区间 | total 不在 min×count ~ max×count | 调整 min/max 或 total |',
67
+ '| 整除 | total % count ≠ 0(random) | 调整 total 或 count |',
68
+ '| 不能超过份数 | per_user_limit > count | 降低 per_user_limit |',
69
+ '| at least count | equal 模式 total < count | 提高 total |',
70
+ '| 余额不足 / insufficient | 账户余额 < total | 先充值或调低 total |',
71
+ '',
72
+ '## 配置前置',
73
+ '',
74
+ '目标机器需要云开发配置(envId + apiKey)。没有配置文件时,让用户用配套网页',
75
+ '(config-helper.html)生成加密配置串,然后:',
76
+ '',
77
+ B + 'act-01 config import "配置串"' + B + '(会提示输入生成时的口令)',
78
+ '',
79
+ ].join('\n')
80
+
81
+ export const SKILL_MD = BODY
82
+
83
+ export const SKILL_NAME = 'act-01-ops'
package/src/tcb.js CHANGED
@@ -3,13 +3,15 @@
3
3
  *
4
4
  * 端点:POST https://{envId}.api.tcloudbasegateway.com/v1/rdb/exec-pgsql
5
5
  * 鉴权:Authorization: Bearer <apiKey>
6
- * 请求体:{ sql } —— exec-pgsql 只收一整条 SQL(无 parameters 通道),
6
+ * 请求体:{ sql, role } —— exec-pgsql 只收一整条 SQL(无 parameters 通道),
7
7
  * $1..$11 由客户端绑定成带类型的字面量(文本单引号翻倍,数值/布尔直书)。
8
+ * 角色:固定 cloudbase_postgres(管理可读写)——网关默认是只读,不显式升权写语句会被 42501 拒。
8
9
  */
9
10
 
10
11
  import { loadConfig } from './store.js'
11
12
 
12
13
  export const GATEWAY_DOMAIN = 'api.tcloudbasegateway.com'
14
+ export const PG_ROLE = 'cloudbase_postgres'
13
15
 
14
16
  export function resolveApikey(config, flagValue) {
15
17
  const raw = flagValue ?? process.env.ACT01_API_KEY ?? config.apiKey
@@ -44,7 +46,7 @@ export async function execPgsql(config, apikey, sql) {
44
46
  'Content-Type': 'application/json',
45
47
  Authorization: `Bearer ${apikey}`,
46
48
  },
47
- body: JSON.stringify({ sql }),
49
+ body: JSON.stringify({ sql, role: PG_ROLE }),
48
50
  })
49
51
  } catch (err) {
50
52
  throw new Error(`网关连接失败:${err instanceof Error ? err.message : String(err)}`)