@optima-chat/optima-agent 0.9.1 → 0.9.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.
Files changed (87) hide show
  1. package/.claude/settings.local.json +166 -0
  2. package/.claude/skills/ads/SKILL.md +6 -4
  3. package/.claude/skills/ads/template/user/ADS.md +1 -1
  4. package/.claude/skills/channels/SKILL.md +16 -0
  5. package/dist/bin/bi-cli.js +0 -0
  6. package/dist/bin/browser-cli.js +0 -0
  7. package/dist/bin/comfy.d.ts +3 -0
  8. package/dist/bin/comfy.d.ts.map +1 -0
  9. package/dist/bin/comfy.js +3 -0
  10. package/dist/bin/comfy.js.map +1 -0
  11. package/dist/bin/commerce.js +0 -0
  12. package/dist/bin/gen.js +0 -0
  13. package/dist/bin/google-ads.js +0 -0
  14. package/dist/bin/growth.d.ts +3 -0
  15. package/dist/bin/growth.d.ts.map +1 -0
  16. package/dist/bin/growth.js +3 -0
  17. package/dist/bin/growth.js.map +1 -0
  18. package/dist/bin/logistics.js +0 -0
  19. package/dist/bin/optima.js +0 -0
  20. package/dist/bin/scout.js +0 -0
  21. package/dist/bin/sentinel.js +0 -0
  22. package/dist/bin/shopify.js +0 -0
  23. package/dist/src/hooks-loader.d.ts +6 -0
  24. package/dist/src/hooks-loader.d.ts.map +1 -0
  25. package/dist/src/hooks-loader.js +215 -0
  26. package/dist/src/hooks-loader.js.map +1 -0
  27. package/dist/src/ui/App.d.ts +6 -0
  28. package/dist/src/ui/App.d.ts.map +1 -0
  29. package/dist/src/ui/App.js +164 -0
  30. package/dist/src/ui/App.js.map +1 -0
  31. package/dist/src/ui/components/Composer.d.ts +10 -0
  32. package/dist/src/ui/components/Composer.d.ts.map +1 -0
  33. package/dist/src/ui/components/Composer.js +13 -0
  34. package/dist/src/ui/components/Composer.js.map +1 -0
  35. package/dist/src/ui/components/Header.d.ts +7 -0
  36. package/dist/src/ui/components/Header.d.ts.map +1 -0
  37. package/dist/src/ui/components/Header.js +7 -0
  38. package/dist/src/ui/components/Header.js.map +1 -0
  39. package/dist/src/ui/components/Message.d.ts +12 -0
  40. package/dist/src/ui/components/Message.d.ts.map +1 -0
  41. package/dist/src/ui/components/Message.js +21 -0
  42. package/dist/src/ui/components/Message.js.map +1 -0
  43. package/dist/src/ui/components/MessageList.d.ts +9 -0
  44. package/dist/src/ui/components/MessageList.d.ts.map +1 -0
  45. package/dist/src/ui/components/MessageList.js +18 -0
  46. package/dist/src/ui/components/MessageList.js.map +1 -0
  47. package/dist/src/ui/components/Spinner.d.ts +6 -0
  48. package/dist/src/ui/components/Spinner.d.ts.map +1 -0
  49. package/dist/src/ui/components/Spinner.js +7 -0
  50. package/dist/src/ui/components/Spinner.js.map +1 -0
  51. package/dist/src/ui/components/StatusBar.d.ts +11 -0
  52. package/dist/src/ui/components/StatusBar.d.ts.map +1 -0
  53. package/dist/src/ui/components/StatusBar.js +7 -0
  54. package/dist/src/ui/components/StatusBar.js.map +1 -0
  55. package/dist/src/ui/components/index.d.ts +7 -0
  56. package/dist/src/ui/components/index.d.ts.map +1 -0
  57. package/dist/src/ui/components/index.js +7 -0
  58. package/dist/src/ui/components/index.js.map +1 -0
  59. package/dist/src/validation/error-formatter.d.ts +21 -0
  60. package/dist/src/validation/error-formatter.d.ts.map +1 -0
  61. package/dist/src/validation/error-formatter.js +98 -0
  62. package/dist/src/validation/error-formatter.js.map +1 -0
  63. package/dist/src/validation/index.d.ts +10 -0
  64. package/dist/src/validation/index.d.ts.map +1 -0
  65. package/dist/src/validation/index.js +10 -0
  66. package/dist/src/validation/index.js.map +1 -0
  67. package/dist/src/validation/json-validator.d.ts +25 -0
  68. package/dist/src/validation/json-validator.d.ts.map +1 -0
  69. package/dist/src/validation/json-validator.js +173 -0
  70. package/dist/src/validation/json-validator.js.map +1 -0
  71. package/dist/src/validation/schema.d.ts +353 -0
  72. package/dist/src/validation/schema.d.ts.map +1 -0
  73. package/dist/src/validation/schema.js +57 -0
  74. package/dist/src/validation/schema.js.map +1 -0
  75. package/dist/src/validation/suggestions.d.ts +25 -0
  76. package/dist/src/validation/suggestions.d.ts.map +1 -0
  77. package/dist/src/validation/suggestions.js +144 -0
  78. package/dist/src/validation/suggestions.js.map +1 -0
  79. package/dist/src/validation/types.d.ts +40 -0
  80. package/dist/src/validation/types.d.ts.map +1 -0
  81. package/dist/src/validation/types.js +5 -0
  82. package/dist/src/validation/types.js.map +1 -0
  83. package/dist/src/validation/yaml-validator.d.ts +25 -0
  84. package/dist/src/validation/yaml-validator.d.ts.map +1 -0
  85. package/dist/src/validation/yaml-validator.js +177 -0
  86. package/dist/src/validation/yaml-validator.js.map +1 -0
  87. package/package.json +1 -1
@@ -0,0 +1,166 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(gh api:*)",
5
+ "WebFetch(domain:platform.claude.com)",
6
+ "Bash(git init:*)",
7
+ "Bash(mkdir:*)",
8
+ "Bash(npm run typecheck:*)",
9
+ "Bash(npm view:*)",
10
+ "WebSearch",
11
+ "Bash(commerce --help)",
12
+ "Bash(done)",
13
+ "Bash(commerce product:*)",
14
+ "Bash(commerce order:*)",
15
+ "Bash(commerce i18n:*)",
16
+ "Bash(google-ads:*)",
17
+ "Bash(scout --help:*)",
18
+ "Bash(tree:*)",
19
+ "Bash(cloc:*)",
20
+ "Bash(npm run build:*)",
21
+ "Bash(git restore:*)",
22
+ "Bash(gh repo view:*)",
23
+ "Bash(mv:*)",
24
+ "Bash(rmdir:*)",
25
+ "Bash(git add:*)",
26
+ "Bash(git commit:*)",
27
+ "Bash(git push)",
28
+ "Bash(timeout 5 npm run optima:*)",
29
+ "Bash(npm install:*)",
30
+ "Bash(cat:*)",
31
+ "Bash(gh issue create:*)",
32
+ "Bash(npx tsx:*)",
33
+ "Bash(timeout 30 npx tsx:*)",
34
+ "Bash(git push origin feature/ask-user-question)",
35
+ "Bash(node:*)",
36
+ "Bash(npm version:*)",
37
+ "Bash(git push:*)",
38
+ "Bash(npm publish:*)",
39
+ "Bash(pkill:*)",
40
+ "Bash(git -C /Users/verypro/optima-agent log --oneline --all -- \".claude/\")",
41
+ "Bash(wc:*)",
42
+ "Bash(grep:*)",
43
+ "Bash(find:*)",
44
+ "Bash(commerce collection --help:*)",
45
+ "Bash(commerce collection update --help:*)",
46
+ "Bash(commerce collection set-cover:*)",
47
+ "Bash(commerce collection get --help:*)",
48
+ "Bash(commerce collection list --help:*)",
49
+ "Bash(commerce collection create --help:*)",
50
+ "Bash(commerce collection remove-products:*)",
51
+ "Bash(commerce collection list-products:*)",
52
+ "Bash(commerce --version:*)",
53
+ "Bash(bi-cli --version:*)",
54
+ "Bash(commerce homepage create --help:*)",
55
+ "Bash(commerce homepage reorder --help:*)",
56
+ "Bash(commerce homepage delete --help:*)",
57
+ "Bash(commerce homepage update-images:*)",
58
+ "Bash(commerce homepage update-collections:*)",
59
+ "Bash(commerce homepage update-target:*)",
60
+ "Bash(commerce homepage switch-template:*)",
61
+ "Bash(commerce inventory:*)",
62
+ "Bash(commerce merchant:*)",
63
+ "Bash(commerce review:*)",
64
+ "Bash(commerce product-page:*)",
65
+ "Bash(bi-cli:*)",
66
+ "Bash(comfy:*)",
67
+ "Bash(scout search:*)",
68
+ "Bash(scout product:*)",
69
+ "Bash(commerce homepage create-collections:*)",
70
+ "Bash(commerce homepage create-featured:*)",
71
+ "Bash(commerce homepage create-collection-products:*)",
72
+ "Bash(commerce homepage create-banner:*)",
73
+ "Bash(xargs -I {} sh -c 'echo \"\"\"\"=== {} ===\"\"\"\"; head -3 /Users/verypro/optima-agent/.claude/skills/{}/SKILL.md | grep \"\"\"\"name:\"\"\"\"')",
74
+ "Bash(ls:*)",
75
+ "Bash(gh issue view:*)",
76
+ "Bash(npx markdownlint-cli:*)",
77
+ "Bash(chmod:*)",
78
+ "Bash(npm whoami:*)",
79
+ "Bash(tsx test-scripts/test-headless-progress.ts:*)",
80
+ "Bash(DEBUG_STREAM=1 node dist/bin/optima.js:*)",
81
+ "Bash(git describe:*)",
82
+ "WebFetch(domain:github.com)",
83
+ "Bash(./scripts/test-headless.sh:*)",
84
+ "Bash(./scripts/test-headless-simple.sh:*)",
85
+ "Bash(env)",
86
+ "Bash(gh pr list:*)",
87
+ "Bash(gh pr view:*)",
88
+ "Bash(gh pr diff:*)",
89
+ "Bash(optima --version:*)",
90
+ "Bash(optima agent headless:*)",
91
+ "Bash(optima headless:*)",
92
+ "Bash(/Users/verypro/optima-agent/scripts/test-headless.sh:*)",
93
+ "Bash(/Users/verypro/optima-agent/scripts/test-headless-simple.sh:*)",
94
+ "Bash(tee:*)",
95
+ "Bash(CONV_ID=\"conv-1\":*)",
96
+ "Bash(echo:*)",
97
+ "Bash(scout tiktok trending --help:*)",
98
+ "Bash(scout tiktok trending:*)",
99
+ "Bash(git checkout:*)",
100
+ "Bash(npm test:*)",
101
+ "Bash(git tag:*)",
102
+ "Bash(/private/tmp/claude/-Users-verypro-optima-agent/68a9ac2c-def2-44e1-b42b-e53bd9022ab6/scratchpad/test-canUseTool.sh)",
103
+ "Bash(optima --help:*)",
104
+ "Bash(npx @optima-chat/ads-cli:*)",
105
+ "Bash(head:*)",
106
+ "Bash(git pull:*)",
107
+ "Bash(pnpm build:*)",
108
+ "Skill(read-code)",
109
+ "Bash(npm run cli:*)",
110
+ "Bash(scout:*)",
111
+ "WebFetch(domain:docs.scrapecreators.com)",
112
+ "WebFetch(domain:scrapecreators.com)",
113
+ "Bash(gh auth status:*)",
114
+ "Bash(optima-agent:*)",
115
+ "Bash(python3:*)",
116
+ "Bash(python3 -c \" import sys content = sys.stdin.read\\(\\) # Find flushMessageQueueSync idx = content.find\\(''flushMessageQueueSync''\\) # Get context around it lines = content.split\\(''\\\\n''\\) for i, line in enumerate\\(lines\\): if ''flushMessageQueueSync'' in line and ''private'' in line: for j in range\\(i, min\\(i+20, len\\(lines\\)\\)\\): print\\(f''{j+1}: {lines[j]}''\\) break \")",
117
+ "Bash(optima:*)",
118
+ "WebFetch(domain:www.npmjs.com)",
119
+ "WebFetch(domain:registry.npmjs.org)",
120
+ "WebFetch(domain:zod.dev)",
121
+ "Bash(npm ls:*)",
122
+ "Bash(NODE_DEBUG=child_process npx tsx:*)",
123
+ "Bash(DEBUG_CLAUDE_AGENT_SDK=1 npx tsx:*)",
124
+ "Bash(CLAUDECODE= npx tsx:*)",
125
+ "Bash(env:*)",
126
+ "Bash(gh release:*)",
127
+ "Bash(npm info:*)",
128
+ "Bash(gh run:*)",
129
+ "Bash(gtimeout 90:*)",
130
+ "Bash(sentinel:*)",
131
+ "Bash(gh pr:*)",
132
+ "Bash(git fetch:*)",
133
+ "Bash(git log:*)",
134
+ "Bash(npm bin:*)",
135
+ "Bash(git status:*)",
136
+ "Bash(browser-cli --version && browser-cli --help)",
137
+ "Bash(browser-cli status:*)",
138
+ "Bash(browser-cli launch:*)",
139
+ "Bash(browser-cli screenshot:*)",
140
+ "Bash(browser-cli --version)",
141
+ "Bash(browser-cli close:*)",
142
+ "Bash(npm update:*)",
143
+ "Bash(node -e \"console.log\\(require\\('./node_modules/@optima-chat/browser-cli/package.json'\\).version\\)\")",
144
+ "WebFetch(domain:raw.githubusercontent.com)",
145
+ "Bash(aws ecs:*)",
146
+ "Bash(aws ecr:*)",
147
+ "Bash(gh search:*)",
148
+ "Bash(npx tsc:*)",
149
+ "Bash(find /Users/verypro/optima-agent -path */node_modules -prune -o -type f \\\\\\(-name *comfy* -o -name *gen* \\\\\\) -print)",
150
+ "Bash(export PATH=\"/usr/local/bin:$PATH\")",
151
+ "Bash(pnpm add:*)",
152
+ "Bash(cp -r ~/optima-agent/test/skills/kol-outreach/fixtures/one-active-campaign ~/optima-agent/test/skills/kol-outreach/fixtures/max-rounds-hit)",
153
+ "Bash(cp -r ~/optima-agent/test/skills/kol-outreach/fixtures/one-active-campaign ~/optima-agent/test/skills/kol-outreach/fixtures/budget-almost-spent)",
154
+ "Bash(cp -r ~/optima-agent/test/skills/kol-outreach/fixtures/one-active-campaign ~/optima-agent/test/skills/kol-outreach/fixtures/two-active-campaigns)",
155
+ "Bash(cp -r ~/optima-agent/test/skills/kol-outreach/fixtures/one-active-campaign ~/optima-agent/test/skills/kol-outreach/fixtures/brand-only)",
156
+ "Bash(pnpm vitest:*)",
157
+ "Bash(pnpm test:*)",
158
+ "Bash(pnpm --filter @optima-scout/backend test --reporter=verbose backend/src/routes/outreach/__tests__/lock.test.ts backend/src/routes/outreach/__tests__/inbound.test.ts)",
159
+ "Bash(npx vitest:*)",
160
+ "Bash(DATABASE_URL=postgres://optima_scout:optima_scout_dev@localhost:7293/optima_scout pnpm --filter @optima-scout/backend test)",
161
+ "Bash(pnpm --filter @optima-scout/backend exec vitest run src/routes/outreach/__tests__/inbound.test.ts)"
162
+ ],
163
+ "deny": [],
164
+ "ask": []
165
+ }
166
+ }
@@ -40,7 +40,8 @@ AI 广告官:通过 `~/ads/` 工作目录持续运营用户的付费广告投放
40
40
  3. `git -C ~/ads log --oneline -5` — 最近变更
41
41
  4. `ls ~/ads/campaigns/` — 列出本地登记的 campaign
42
42
  5. `ads status` — 从后端拉事实(默认 JSON 输出,加 `--pretty` 可读格式): 在跑的 campaign 列表 + 7 天花费 + 钱包 + 月度 cap
43
- - 如果钱包余额 < 阈值,第一时间告诉用户
43
+ - 钱包分为付费余额(`balanceUsd`)和赠送余额(`grantedBalanceUsd`),**赠送余额不能用于广告投放**
44
+ - 如果付费余额 < 阈值,第一时间告诉用户
44
45
  - 如果月度 cap 使用率 > 80%,同样提示
45
46
  - 如果后端 campaign 和本地目录对不齐,视为需要修复
46
47
  6. → 决定本次要做的**一个**动作
@@ -60,8 +61,9 @@ AI 广告官:通过 `~/ads/` 工作目录持续运营用户的付费广告投放
60
61
  4. `ads init --total-monthly-budget <X>` — 后端创建 user_ads 记录 + 确保 Google Ads label 存在 + 查 USD wallet
61
62
  5. 把后端返回的 ID 自动填进 ADS.md 的"后端登记"段,`git commit -m "register backend"`
62
63
  6. 提示用户:
63
- - 钱包余额为 0 → "需要先充值. 说 'ads budget topup --amount 100' 可充 $100"
64
- - 有余额 → "可以现在 launch 第一个 campaign,或者下次会话再开始"
64
+ - 注意区分 `wallet_balance_usd`(付费余额)和 `wallet_granted_usd`(赠送余额)。**赠送余额不能用于广告投放**,只有付费余额可以。
65
+ - 付费余额为 0 → "需要先充值. 'ads budget topup --amount 100' 可充 $100"
66
+ - 有付费余额 → "可以现在 launch 第一个 campaign,或者下次会话再开始"
65
67
 
66
68
  **不会自动 launch 任何 campaign.** 第一次 launch 必须由用户明确要求。
67
69
 
@@ -146,7 +148,7 @@ AI 广告官:通过 `~/ads/` 工作目录持续运营用户的付费广告投放
146
148
  - "加到 $20/天" → `ads budget set --campaign <id> --daily 20000000 --reason "..."`
147
149
  - "月度上限改 $500" → `ads budget set --total-monthly 500000000 --reason "..."`
148
150
  - "充 $100" → `ads budget topup --amount 100` → 把返回的 `checkout_url` 作为 markdown 链接输出给用户(topup 用 USD)
149
- - "看下预算" → `ads budget show`
151
+ - "看下预算" → `ads budget show`(注意区分付费余额和赠送余额,赠送余额不可用于广告)
150
152
 
151
153
  改完之后相应更新 `ADS.md`(月度 cap 变化)或 `campaigns/<slug>/STRATEGY.md`(campaign 日预算变化),commit。
152
154
 
@@ -16,7 +16,7 @@
16
16
 
17
17
  ## 月度总预算 (软性, 超出后所有 campaign 自动暂停到下月 1 日)
18
18
  - 月度上限: $___
19
- - 钱包余额低于 $___ 时自动暂停
19
+ - 付费余额低于 $___ 时自动暂停(赠送余额不可用于广告)
20
20
 
21
21
  ## 渠道偏好
22
22
  - [x] google_ads
@@ -7,9 +7,25 @@ description: "社交渠道管理。接入/管理 Telegram、WhatsApp、Discord
7
7
 
8
8
  管理社交渠道接入、用户绑定和消息推送。支持 Telegram、WhatsApp、Discord、Slack、飞书、LINE、Zalo。
9
9
 
10
+ ## 社交渠道环境注意事项
11
+
12
+ 当消息来自社交渠道(metadata.source === "channel_bridge")时:
13
+
14
+ 1. **无浏览器环境** — 用户在 Telegram/WhatsApp 等社交 App 中,无法自动打开浏览器。所有需要浏览器的操作(如 OAuth 登录),必须把 URL 发给用户让他们手动打开。
15
+
16
+ 2. **登录流程** — 当用户需要登录(如操作商品、订单等需要认证的功能):
17
+ - 运行 `commerce auth login`
18
+ - 命令会输出一个授权 URL 和验证码
19
+ - **把 URL 和验证码发给用户**,告诉他们在手机浏览器中打开
20
+ - 命令会自动等待用户完成授权
21
+ - 不要说"浏览器已自动打开"——社交渠道里没有浏览器
22
+
23
+ 3. **回复简洁** — 社交渠道消息应比 Web Chat 更简洁。避免长段落,用要点列表。
24
+
10
25
  ## 典型场景
11
26
 
12
27
  当用户说:
28
+ - "登录" → 运行 `commerce auth login`,把输出中的 URL 和验证码发给用户
13
29
  - "帮我接入 Telegram" → 引导创建 bot → `channels accounts add telegram --account-id store --token <token>`
14
30
  - "查看我的渠道" → `channels accounts list`
15
31
  - "关掉 Telegram" → `channels accounts disable telegram store`
File without changes
File without changes
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import "@optima-chat/comfy-cli";
3
+ //# sourceMappingURL=comfy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comfy.d.ts","sourceRoot":"","sources":["../../bin/comfy.ts"],"names":[],"mappings":";AACA,OAAO,wBAAwB,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import "@optima-chat/comfy-cli";
3
+ //# sourceMappingURL=comfy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comfy.js","sourceRoot":"","sources":["../../bin/comfy.ts"],"names":[],"mappings":";AACA,OAAO,wBAAwB,CAAC"}
File without changes
package/dist/bin/gen.js CHANGED
File without changes
File without changes
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import "@optima-chat/growth-cli";
3
+ //# sourceMappingURL=growth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"growth.d.ts","sourceRoot":"","sources":["../../bin/growth.ts"],"names":[],"mappings":";AACA,OAAO,yBAAyB,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import "@optima-chat/growth-cli";
3
+ //# sourceMappingURL=growth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"growth.js","sourceRoot":"","sources":["../../bin/growth.ts"],"names":[],"mappings":";AACA,OAAO,yBAAyB,CAAC"}
File without changes
File without changes
package/dist/bin/scout.js CHANGED
File without changes
File without changes
File without changes
@@ -0,0 +1,6 @@
1
+ import type { HooksConfig } from "./types.js";
2
+ /**
3
+ * 从 skills 目录加载所有 skill 的 hooks
4
+ */
5
+ export declare function loadSkillHooks(skillsDir: string, cwd: string, getSessionId: () => string | undefined): HooksConfig;
6
+ //# sourceMappingURL=hooks-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks-loader.d.ts","sourceRoot":"","sources":["../../src/hooks-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAgB,MAAM,YAAY,CAAC;AAwL5D;;GAEG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,MAAM,GAAG,SAAS,GACrC,WAAW,CAiFb"}
@@ -0,0 +1,215 @@
1
+ import { readFileSync, readdirSync, existsSync, writeFileSync, mkdirSync } from "fs";
2
+ import { join, dirname } from "path";
3
+ import yaml from "js-yaml";
4
+ import { execSync } from "child_process";
5
+ import { YamlValidator, formatValidationErrors, formatValidationWarning } from "./validation/index.js";
6
+ /**
7
+ * 从 SKILL.md 提取 YAML frontmatter
8
+ */
9
+ function extractYamlFrontmatter(content) {
10
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
11
+ if (!match)
12
+ return null;
13
+ try {
14
+ return yaml.load(match[1]);
15
+ }
16
+ catch (error) {
17
+ console.error("Failed to parse YAML frontmatter:", error);
18
+ return null;
19
+ }
20
+ }
21
+ /**
22
+ * 执行 shell 命令并返回结果
23
+ */
24
+ function executeCommand(command, cwd, skillDir, sessionId) {
25
+ try {
26
+ // 替换环境变量
27
+ const expandedCommand = command
28
+ .replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, skillDir)
29
+ .replace(/\$\{SESSION_ID\}/g, sessionId || 'default');
30
+ const result = execSync(expandedCommand, {
31
+ cwd,
32
+ encoding: "utf-8",
33
+ stdio: ["pipe", "pipe", "pipe"],
34
+ });
35
+ return result.trim();
36
+ }
37
+ catch (error) {
38
+ // 命令失败不阻塞,返回错误信息
39
+ return error.stdout || error.message || "";
40
+ }
41
+ }
42
+ /**
43
+ * 转换 skill hooks 为 SDK hooks 格式
44
+ */
45
+ function convertSkillHooksToSdkHooks(skillHooks, skillDir, cwd, getSessionId, hookType) {
46
+ return skillHooks.map((hookConfig) => ({
47
+ matcher: hookConfig.matcher,
48
+ hooks: hookConfig.hooks.map((hook) => {
49
+ // SDK HookCallback 签名: (input, toolUseID, options) => Promise<HookJSONOutput>
50
+ return async (input, toolUseID, options) => {
51
+ // PreToolUse: 拦截并重定向 planning 文件操作
52
+ if (hookType === "PreToolUse" && input.tool_name && input.tool_input) {
53
+ const toolName = input.tool_name;
54
+ const toolInput = input.tool_input;
55
+ // 处理文件操作工具的路径重定向
56
+ if ((toolName === "Write" || toolName === "Read" || toolName === "Edit") && toolInput.file_path) {
57
+ const filePath = toolInput.file_path;
58
+ if (filePath.includes(".planning/default/")) {
59
+ const sessionId = getSessionId() || "default";
60
+ const updatedPath = filePath.replace(".planning/default/", `.planning/${sessionId}/`);
61
+ console.log(`[hooks-loader] Intercepting and redirecting: ${filePath} -> ${updatedPath}`);
62
+ // 手动执行文件操作并 return,不要继续到 command 部分
63
+ try {
64
+ console.log(`[hooks-loader] Inside try block, toolName=${toolName}`);
65
+ if (toolName === "Write") {
66
+ console.log(`[hooks-loader] Handling Write operation`);
67
+ // 创建目录
68
+ const dir = dirname(updatedPath);
69
+ if (!existsSync(dir)) {
70
+ mkdirSync(dir, { recursive: true });
71
+ }
72
+ // 写入文件
73
+ writeFileSync(updatedPath, toolInput.content || "", "utf-8");
74
+ console.log(`[hooks-loader] File written to ${updatedPath}`);
75
+ // Block 原始工具执行
76
+ return {
77
+ decision: "block",
78
+ systemMessage: `File written to session-specific directory`,
79
+ };
80
+ }
81
+ else if (toolName === "Read") {
82
+ // 读取文件
83
+ if (existsSync(updatedPath)) {
84
+ const content = readFileSync(updatedPath, "utf-8");
85
+ console.log(`[hooks-loader] File read from ${updatedPath}`);
86
+ // Block 原始工具,返回文件内容
87
+ return {
88
+ decision: "block",
89
+ systemMessage: `File content:\n\n${content}`,
90
+ };
91
+ }
92
+ else {
93
+ return {
94
+ decision: "block",
95
+ systemMessage: `File not found: ${updatedPath}`,
96
+ };
97
+ }
98
+ }
99
+ else if (toolName === "Edit") {
100
+ // Edit 需要读取、修改、写入
101
+ if (existsSync(updatedPath)) {
102
+ let content = readFileSync(updatedPath, "utf-8");
103
+ // 执行替换
104
+ if (toolInput.old_string && toolInput.new_string) {
105
+ if (toolInput.replace_all) {
106
+ content = content.split(toolInput.old_string).join(toolInput.new_string);
107
+ }
108
+ else {
109
+ content = content.replace(toolInput.old_string, toolInput.new_string);
110
+ }
111
+ writeFileSync(updatedPath, content, "utf-8");
112
+ console.log(`[hooks-loader] File edited at ${updatedPath}`);
113
+ }
114
+ return {
115
+ decision: "block",
116
+ systemMessage: `File edited successfully`,
117
+ };
118
+ }
119
+ else {
120
+ return {
121
+ decision: "block",
122
+ systemMessage: `File not found: ${updatedPath}`,
123
+ };
124
+ }
125
+ }
126
+ }
127
+ catch (error) {
128
+ console.error(`[hooks-loader] Error:`, error);
129
+ return {
130
+ decision: "block",
131
+ systemMessage: `Error: ${error.message}`,
132
+ };
133
+ }
134
+ }
135
+ }
136
+ }
137
+ if (hook.type === "command") {
138
+ const sessionId = getSessionId();
139
+ const result = executeCommand(hook.command, cwd, skillDir, sessionId);
140
+ // 如果有输出,作为系统消息返回
141
+ if (result) {
142
+ return {
143
+ continue: true,
144
+ systemMessage: result,
145
+ };
146
+ }
147
+ }
148
+ return { continue: true };
149
+ };
150
+ }),
151
+ }));
152
+ }
153
+ /**
154
+ * 从 skills 目录加载所有 skill 的 hooks
155
+ */
156
+ export function loadSkillHooks(skillsDir, cwd, getSessionId) {
157
+ const hooks = {};
158
+ if (!existsSync(skillsDir)) {
159
+ return hooks;
160
+ }
161
+ const skillDirs = readdirSync(skillsDir, { withFileTypes: true })
162
+ .filter((dirent) => dirent.isDirectory())
163
+ .map((dirent) => dirent.name);
164
+ for (const skillName of skillDirs) {
165
+ const skillDir = join(skillsDir, skillName);
166
+ const skillMdPath = join(skillDir, "SKILL.md");
167
+ if (!existsSync(skillMdPath)) {
168
+ continue;
169
+ }
170
+ try {
171
+ const content = readFileSync(skillMdPath, "utf-8");
172
+ // 验证配置文件
173
+ const validator = new YamlValidator();
174
+ const validationResult = validator.validate(content, skillMdPath);
175
+ // 显示错误
176
+ if (!validationResult.valid) {
177
+ console.error(formatValidationErrors(validationResult.errors));
178
+ continue;
179
+ }
180
+ // 显示警告
181
+ if (validationResult.warnings && validationResult.warnings.length > 0) {
182
+ for (const warning of validationResult.warnings) {
183
+ console.warn(formatValidationWarning(warning));
184
+ }
185
+ }
186
+ const frontmatter = extractYamlFrontmatter(content);
187
+ if (!frontmatter?.hooks) {
188
+ continue;
189
+ }
190
+ // 转换各个 hook 事件
191
+ if (frontmatter.hooks.SessionStart) {
192
+ hooks.SessionStart = hooks.SessionStart || [];
193
+ hooks.SessionStart.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.SessionStart, skillDir, cwd, getSessionId, "SessionStart"));
194
+ }
195
+ if (frontmatter.hooks.PreToolUse) {
196
+ hooks.PreToolUse = hooks.PreToolUse || [];
197
+ hooks.PreToolUse.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.PreToolUse, skillDir, cwd, getSessionId, "PreToolUse"));
198
+ }
199
+ if (frontmatter.hooks.PostToolUse) {
200
+ hooks.PostToolUse = hooks.PostToolUse || [];
201
+ hooks.PostToolUse.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.PostToolUse, skillDir, cwd, getSessionId, "PostToolUse"));
202
+ }
203
+ if (frontmatter.hooks.Stop) {
204
+ hooks.Stop = hooks.Stop || [];
205
+ hooks.Stop.push(...convertSkillHooksToSdkHooks(frontmatter.hooks.Stop, skillDir, cwd, getSessionId, "Stop"));
206
+ }
207
+ console.log(`[hooks-loader] Loaded hooks from skill: ${skillName}`);
208
+ }
209
+ catch (error) {
210
+ console.error(`[hooks-loader] Failed to load hooks from ${skillName}:`, error);
211
+ }
212
+ }
213
+ return hooks;
214
+ }
215
+ //# sourceMappingURL=hooks-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks-loader.js","sourceRoot":"","sources":["../../src/hooks-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ interface AppProps {
2
+ cwd?: string;
3
+ }
4
+ export declare function App({ cwd }: AppProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
6
+ //# sourceMappingURL=App.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../../src/ui/App.tsx"],"names":[],"mappings":"AAcA,UAAU,QAAQ;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,QAAQ,2CAqMpC"}