@vocmarket/voc-skill 0.3.29 → 0.3.30
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-plugin/plugin.json +1 -1
- package/bin/claude-voc.js +25 -6
- package/mcp/src/core/activation.js +104 -0
- package/package.json +1 -1
- package/skill-package-manifest.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "voc-intelligence",
|
|
3
3
|
"description": "VOC intelligence skills for Claude Code: end-to-end VOC business workflows, Xiaohongshu and Douyin trend reports, live social VOC collection, Fmode Doubao image analysis, token/recharge checks, evidence-card outputs, prioritized issue pools, single-problem deep dives, competitor maps, 7-day content plans, VOC-backed speaking script co-creation, boss/operator action plans, and multi-turn memory.",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.30",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "nkkj-BrainHack"
|
|
7
7
|
}
|
package/bin/claude-voc.js
CHANGED
|
@@ -3,6 +3,7 @@ const fs = require('fs');
|
|
|
3
3
|
const os = require('os');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const { spawnSync } = require('child_process');
|
|
6
|
+
const { ensureActivated } = require('../mcp/src/core/activation');
|
|
6
7
|
|
|
7
8
|
const SOURCE_ROOT = path.resolve(__dirname, '..');
|
|
8
9
|
const WORKSPACE_ROOT = process.cwd();
|
|
@@ -34,6 +35,7 @@ function usage() {
|
|
|
34
35
|
'Usage:',
|
|
35
36
|
' claude-voc install',
|
|
36
37
|
' claude-voc workspace',
|
|
38
|
+
' claude-voc workspace --activate',
|
|
37
39
|
' claude-voc install --workspace --smoke',
|
|
38
40
|
' claude-voc check',
|
|
39
41
|
' claude-voc smoke',
|
|
@@ -43,6 +45,7 @@ function usage() {
|
|
|
43
45
|
'npx:',
|
|
44
46
|
' npx @vocmarket/voc-skill install',
|
|
45
47
|
' npx @vocmarket/voc-skill workspace --smoke',
|
|
48
|
+
' npx @vocmarket/voc-skill workspace --activate (其他 AI 编程器渠道专用:安装并按状态弹付费)',
|
|
46
49
|
'',
|
|
47
50
|
'Options:',
|
|
48
51
|
' --workspace Install into ./.claude/plugins/voc-intelligence',
|
|
@@ -50,6 +53,8 @@ function usage() {
|
|
|
50
53
|
' --force Allow overwriting an existing custom target',
|
|
51
54
|
' --skip-install Skip npm install after copying files',
|
|
52
55
|
' --smoke Run sample/preference/MCP smoke checks after install',
|
|
56
|
+
' --activate 安装后按 token 状态激活:无 token 弹付费/登录页,有 token 直接放行(外部 AI IDE 专用,不影响 --smoke)',
|
|
57
|
+
' --channel <name> 付费归因渠道名(claude-code/codex/workbuddy)',
|
|
53
58
|
' --help, -h Show help'
|
|
54
59
|
].join('\n');
|
|
55
60
|
}
|
|
@@ -65,6 +70,8 @@ function parseArgs(argv) {
|
|
|
65
70
|
target: DEFAULT_TARGET,
|
|
66
71
|
skipInstall: false,
|
|
67
72
|
smoke: false,
|
|
73
|
+
activate: false,
|
|
74
|
+
channel: 'external',
|
|
68
75
|
force: false,
|
|
69
76
|
help: false
|
|
70
77
|
};
|
|
@@ -88,6 +95,12 @@ function parseArgs(argv) {
|
|
|
88
95
|
opts.skipInstall = true;
|
|
89
96
|
} else if (token === '--smoke') {
|
|
90
97
|
opts.smoke = true;
|
|
98
|
+
} else if (token === '--activate') {
|
|
99
|
+
opts.activate = true;
|
|
100
|
+
} else if (token === '--channel') {
|
|
101
|
+
opts.channel = argv[++i];
|
|
102
|
+
} else if (token.startsWith('--channel=')) {
|
|
103
|
+
opts.channel = token.slice('--channel='.length);
|
|
91
104
|
} else if (token === '--help' || token === '-h') {
|
|
92
105
|
opts.help = true;
|
|
93
106
|
}
|
|
@@ -716,7 +729,7 @@ function printPath(opts) {
|
|
|
716
729
|
}
|
|
717
730
|
}
|
|
718
731
|
|
|
719
|
-
function main() {
|
|
732
|
+
async function main() {
|
|
720
733
|
const directCommand = process.argv[2];
|
|
721
734
|
if (directCommand === 'image' || directCommand === 'fmode-image') {
|
|
722
735
|
run(process.execPath, ['mcp/src/tools/fmode-image-analysis.js', ...process.argv.slice(3)], SOURCE_ROOT);
|
|
@@ -728,17 +741,23 @@ function main() {
|
|
|
728
741
|
console.log(usage());
|
|
729
742
|
return;
|
|
730
743
|
}
|
|
731
|
-
if (opts.command === 'install')
|
|
744
|
+
if (opts.command === 'install') {
|
|
745
|
+
install(opts);
|
|
746
|
+
if (opts.activate) {
|
|
747
|
+
await ensureActivated({ channel: opts.channel });
|
|
748
|
+
}
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
732
751
|
if (opts.command === 'check') return check(opts);
|
|
733
752
|
if (opts.command === 'smoke') return smoke(opts);
|
|
734
753
|
if (opts.command === 'path') return printPath(opts);
|
|
735
754
|
throw new Error(`Unknown command: ${opts.command}\n\n${usage()}`);
|
|
736
755
|
}
|
|
737
756
|
|
|
738
|
-
|
|
739
|
-
main();
|
|
740
|
-
} catch (error) {
|
|
757
|
+
main().catch((error) => {
|
|
741
758
|
console.error('');
|
|
742
759
|
console.error(`claude-voc failed: ${error.message}`);
|
|
743
760
|
process.exit(1);
|
|
744
|
-
}
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// 安装收尾激活检查(仅供外部 AI IDE 渠道的 `workspace --activate` 调用)。
|
|
4
|
+
//
|
|
5
|
+
// 设计要点(与 voc-api-catalog 计费链一致,复用同一套凭证解析,绝不另建路径):
|
|
6
|
+
// - 复用 credentials.js 的 readNewApiToken()(sk- 主链)/ readVocToken()(r: 会话回退)。
|
|
7
|
+
// - 按「是否已有可用 token」这一状态触发,而不是按命令触发:
|
|
8
|
+
// * 已检测到 token(飞马 UI 已写入,或 Claude Code 已配 sk-)→ 打印「✅ 已激活」,不弹浏览器。
|
|
9
|
+
// * 完全没有 token(现场新教练)→ 安装收尾立刻打开充值/登录页,避免进入取数流程后才弹、空耗 token。
|
|
10
|
+
// - 不主动发计费请求做探测(探测会真扣费);余额不足留给真实取数时由 catalog 的 402 分支处理。
|
|
11
|
+
// - VOC_OPEN_PAYMENT=0 可强制关闭弹窗(CI / 冒烟 / 无头环境)。
|
|
12
|
+
// - 始终把 URL 打印到终端兜底;并追加 &channel=&src=install 做渠道归因。
|
|
13
|
+
// - token 绝不回显到终端 / 日志。
|
|
14
|
+
|
|
15
|
+
const { spawn } = require('child_process');
|
|
16
|
+
const { readNewApiToken, readVocToken } = require('./credentials');
|
|
17
|
+
const { buildVocRechargeInfo } = require('./payment-links');
|
|
18
|
+
|
|
19
|
+
function appendAttribution(rawUrl, channel, src) {
|
|
20
|
+
try {
|
|
21
|
+
const url = new URL(rawUrl);
|
|
22
|
+
if (channel) url.searchParams.set('channel', String(channel));
|
|
23
|
+
if (src) url.searchParams.set('src', String(src));
|
|
24
|
+
return url.toString();
|
|
25
|
+
} catch {
|
|
26
|
+
return rawUrl;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function openBrowser(url) {
|
|
31
|
+
try {
|
|
32
|
+
let command;
|
|
33
|
+
let args;
|
|
34
|
+
if (process.platform === 'win32') {
|
|
35
|
+
command = 'cmd';
|
|
36
|
+
// 空字符串是 start 的窗口标题占位,避免带引号的 URL 被当成标题
|
|
37
|
+
args = ['/d', '/s', '/c', 'start', '', url];
|
|
38
|
+
} else if (process.platform === 'darwin') {
|
|
39
|
+
command = 'open';
|
|
40
|
+
args = [url];
|
|
41
|
+
} else {
|
|
42
|
+
command = 'xdg-open';
|
|
43
|
+
args = [url];
|
|
44
|
+
}
|
|
45
|
+
const child = spawn(command, args, { stdio: 'ignore', detached: true });
|
|
46
|
+
child.on('error', () => {});
|
|
47
|
+
child.unref();
|
|
48
|
+
return true;
|
|
49
|
+
} catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// channel: 渠道名(claude-code / codex / workbuddy),用于付费归因
|
|
55
|
+
// src: 来源标记,默认 install
|
|
56
|
+
async function ensureActivated({ channel = 'external', src = 'install' } = {}) {
|
|
57
|
+
if (process.env.VOC_OPEN_PAYMENT === '0') {
|
|
58
|
+
console.log('');
|
|
59
|
+
console.log('VOC_OPEN_PAYMENT=0:已跳过激活弹窗(CI/无头环境)。');
|
|
60
|
+
return { status: 'skipped' };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const newApiToken = readNewApiToken();
|
|
64
|
+
const vocToken = readVocToken();
|
|
65
|
+
|
|
66
|
+
if (newApiToken || vocToken) {
|
|
67
|
+
console.log('');
|
|
68
|
+
console.log('✅ 已激活:检测到 VOC 计费/会话 token,可直接开始取数,无需充值。');
|
|
69
|
+
console.log('(若取数时返回 402 余额不足,再按工具提示充值即可。)');
|
|
70
|
+
return { status: 'activated' };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 完全没有 token:现场新用户。打开充值/登录页,引导先付费再进流程。
|
|
74
|
+
// 无 token 时 buildVocRechargeInfo 不会发起网络请求(resolveVocUserId 对空 token 直接返回)。
|
|
75
|
+
let recharge;
|
|
76
|
+
try {
|
|
77
|
+
recharge = await buildVocRechargeInfo({ token: '' });
|
|
78
|
+
} catch {
|
|
79
|
+
recharge = {};
|
|
80
|
+
}
|
|
81
|
+
const primaryUrl = appendAttribution(
|
|
82
|
+
recharge.recommendedPackageUrl || recharge.paymentUrl || 'https://app.fmode.cn/dev/apig-pay/',
|
|
83
|
+
channel,
|
|
84
|
+
src
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
console.log('');
|
|
88
|
+
console.log('⚠️ 尚未检测到 VOC token —— 你还没有激活。');
|
|
89
|
+
console.log('为避免进入取数流程后才发现需要付费、白白消耗 token,请先在浏览器完成登录并充值/开通:');
|
|
90
|
+
console.log(` ${primaryUrl}`);
|
|
91
|
+
if (recharge.paymentUrl) {
|
|
92
|
+
console.log(` (充值入口:${appendAttribution(recharge.paymentUrl, channel, src)})`);
|
|
93
|
+
}
|
|
94
|
+
console.log('完成付费后,再让 AI 进入取数/报告流程。');
|
|
95
|
+
console.log('如本机无法自动打开浏览器,请手动复制上面的链接到浏览器打开。');
|
|
96
|
+
|
|
97
|
+
const opened = openBrowser(primaryUrl);
|
|
98
|
+
if (!opened) {
|
|
99
|
+
console.log('(自动打开浏览器失败,请手动打开上面的链接。)');
|
|
100
|
+
}
|
|
101
|
+
return { status: 'needs_activation', url: primaryUrl };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = { ensureActivated, openBrowser, appendAttribution };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vocmarket/voc-skill",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.30",
|
|
4
4
|
"description": "Claude Code VOC intelligence skills for Xiaohongshu and Douyin trend reports, live social VOC collection, Fmode image analysis, single-issue deep dives, boss/operator action plans, and multi-turn memory.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"bin": {
|