@scorehub/creator-outreach 1.2.0 → 1.2.1
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/.codebuddy-plugin/plugin.json +1 -1
- package/README.en.md +2 -2
- package/README.md +2 -2
- package/install.js +80 -29
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tiktok-creator-outreach",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "ScoreHub AI's TikTok creator marketing expert for building clear creator profiles and validating focused collaboration shortlists across Southeast Asia.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Ben",
|
package/README.en.md
CHANGED
|
@@ -23,7 +23,7 @@ For the public release, end users only need to:
|
|
|
23
23
|
|
|
24
24
|
Tiky uses `npx -y @scorehub/creator-outreach@latest` to run a bootstrap check before every new conversation. When the machine is uninitialized, Tiky explains that the ScoreHub local component is required and waits for explicit confirmation. It then prefetches and self-checks `@scorehub/mcp-server@latest` before updating Tiky's files and the WorkBuddy `scorehub` MCP configuration. WorkBuddy must be fully restarted after the initial installation.
|
|
25
25
|
|
|
26
|
-
That first confirmation also authorizes future silent creator-outreach updates, so Tiky does not ask again for every release. The MCP
|
|
26
|
+
That first confirmation also authorizes future silent creator-outreach updates, so Tiky does not ask again for every release. The MCP launcher always resolves `@scorehub/mcp-server@latest`; it is never pinned to a specific version.
|
|
27
27
|
|
|
28
28
|
The share link only installs Tiky into WorkBuddy. In the normal public path, users do not need to install `@scorehub/mcp-server` manually or edit `mcp.json` themselves.
|
|
29
29
|
|
|
@@ -41,7 +41,7 @@ The installer configures WorkBuddy only. If it does not find WorkBuddy, it exits
|
|
|
41
41
|
|---|---|---|---|
|
|
42
42
|
| WorkBuddy | `~/.workbuddy/` exists | Plugin files in `~/.workbuddy/plugins/.../`; MCP configuration merged into `~/.workbuddy/mcp.json` | Restart, then select “ScoreHub AI TikTok Creator Marketing Expert” from the Agent list |
|
|
43
43
|
|
|
44
|
-
Before writing the configuration, Tiky verifies the MCP server with `--self-check --json
|
|
44
|
+
Before writing the configuration, Tiky verifies the MCP server with `--self-check --json`, then WorkBuddy starts it automatically. macOS and Linux use `npx -y @scorehub/mcp-server@latest`. Windows reuses WorkBuddy's managed `node.exe` to load the matching npm `npx-cli.js` directly, avoiding `.cmd` / `.bat` process-launch compatibility problems. Tiky only guides users to the official Node.js LTS installer when the managed runtime is explicitly missing or too old.
|
|
45
45
|
|
|
46
46
|
## First Use and Authorization
|
|
47
47
|
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ English version: [README.en.md](./README.en.md)
|
|
|
23
23
|
|
|
24
24
|
Tiky 每个新会话都会通过 `npx -y @scorehub/creator-outreach@latest` 执行 bootstrap 检查。未初始化时,她会说明需要安装 ScoreHub 本地组件,并等待你明确确认;确认后预拉取并自检 `@scorehub/mcp-server@latest`,再更新 Tiky 本地文件和 WorkBuddy 的 `scorehub` MCP 配置。安装完成后需要完全重启 WorkBuddy。
|
|
25
25
|
|
|
26
|
-
首次确认同时授权后续静默更新 creator-outreach,不会对每个新版本重复询问。MCP
|
|
26
|
+
首次确认同时授权后续静默更新 creator-outreach,不会对每个新版本重复询问。MCP 始终运行 `@scorehub/mcp-server@latest`,不固定具体版本。
|
|
27
27
|
|
|
28
28
|
分享链接只负责把 Tiky 放进 WorkBuddy。默认情况下,你不需要手工安装 `@scorehub/mcp-server`,也不需要自己编辑 `mcp.json`。
|
|
29
29
|
|
|
@@ -41,7 +41,7 @@ npx -y @scorehub/creator-outreach
|
|
|
41
41
|
|---|---|---|---|
|
|
42
42
|
| WorkBuddy | `~/.workbuddy/` 存在 | 插件文件写入 `~/.workbuddy/plugins/.../`;MCP 配置合并到 `~/.workbuddy/mcp.json` | 重启后在 Agent 列表选择“ScoreHub AI TikTok达人营销专家” |
|
|
43
43
|
|
|
44
|
-
MCP Server(`@scorehub/mcp-server`)在写入配置前会先通过 `--self-check --json` 验证可执行性,之后由 `npx -y @scorehub/mcp-server@latest
|
|
44
|
+
MCP Server(`@scorehub/mcp-server`)在写入配置前会先通过 `--self-check --json` 验证可执行性,之后由 WorkBuddy 自动拉起。macOS / Linux 使用 `npx -y @scorehub/mcp-server@latest`;Windows 复用 WorkBuddy 托管的 `node.exe` 直接加载同版本 npm 的 `npx-cli.js`,避免 `.cmd` / `.bat` 的进程启动兼容问题。只有在托管运行时明确缺失或版本过低时,Tiky 才会引导你安装官方 Node.js LTS。
|
|
45
45
|
|
|
46
46
|
## 首次使用与授权
|
|
47
47
|
|
package/install.js
CHANGED
|
@@ -48,23 +48,33 @@ function getPaths(homeDir) {
|
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
function
|
|
51
|
+
function resolveWorkBuddyLauncher(workBuddyDir, platform = process.platform) {
|
|
52
52
|
const versionsDir = path.join(workBuddyDir, 'binaries', 'node', 'versions');
|
|
53
|
-
const npxExecutable = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
54
53
|
try {
|
|
55
|
-
const versions = fs.readdirSync(versionsDir)
|
|
54
|
+
const versions = fs.readdirSync(versionsDir)
|
|
55
|
+
.sort((left, right) => right.localeCompare(left, undefined, { numeric: true }));
|
|
56
56
|
for (const version of versions) {
|
|
57
57
|
const versionDir = path.join(versionsDir, version);
|
|
58
|
+
if (platform === 'win32') {
|
|
59
|
+
const command = path.join(versionDir, 'node.exe');
|
|
60
|
+
const npxCli = path.join(versionDir, 'node_modules', 'npm', 'bin', 'npx-cli.js');
|
|
61
|
+
if (fs.existsSync(command) && fs.existsSync(npxCli)) {
|
|
62
|
+
return { command, argsPrefix: [npxCli], binDir: versionDir };
|
|
63
|
+
}
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
58
67
|
const binDirs = [path.join(versionDir, 'bin'), versionDir];
|
|
59
68
|
for (const binDir of binDirs) {
|
|
60
|
-
const
|
|
61
|
-
if (fs.existsSync(
|
|
69
|
+
const command = path.join(binDir, 'npx');
|
|
70
|
+
if (fs.existsSync(command)) return { command, argsPrefix: [], binDir };
|
|
62
71
|
}
|
|
63
72
|
}
|
|
64
73
|
} catch {
|
|
65
74
|
// WorkBuddy or its bundled Node.js is not available at this path.
|
|
66
75
|
}
|
|
67
|
-
|
|
76
|
+
if (platform === 'win32') return null;
|
|
77
|
+
return { command: 'npx', argsPrefix: [], binDir: null };
|
|
68
78
|
}
|
|
69
79
|
|
|
70
80
|
function readJson(filePath) {
|
|
@@ -144,11 +154,11 @@ function buildMcpEnvironment(version, binDir) {
|
|
|
144
154
|
});
|
|
145
155
|
}
|
|
146
156
|
|
|
147
|
-
function buildMcpConfig(version,
|
|
157
|
+
function buildMcpConfig(version, launcher) {
|
|
148
158
|
return {
|
|
149
|
-
command:
|
|
150
|
-
args: MCP_CONFIG.args
|
|
151
|
-
env: buildMcpEnvironment(version, binDir),
|
|
159
|
+
command: launcher.command,
|
|
160
|
+
args: launcher.argsPrefix.concat(MCP_CONFIG.args),
|
|
161
|
+
env: buildMcpEnvironment(version, launcher.binDir),
|
|
152
162
|
};
|
|
153
163
|
}
|
|
154
164
|
|
|
@@ -172,6 +182,17 @@ function isManagedMcpConfig(config) {
|
|
|
172
182
|
&& server.env.SCOREHUB_CLIENT_HOST === 'workbuddy';
|
|
173
183
|
}
|
|
174
184
|
|
|
185
|
+
function needsMcpLauncherMigration(config, platform = process.platform, expectedLauncher) {
|
|
186
|
+
if (platform !== 'win32' || !isManagedMcpConfig(config)) return false;
|
|
187
|
+
const server = config.mcpServers.scorehub;
|
|
188
|
+
const npxCli = server.args.find((arg) => /(?:^|[\\/])npx-cli\.js$/i.test(arg));
|
|
189
|
+
if (!/(?:^|[\\/])node\.exe$/i.test(server.command || '') || !npxCli) return true;
|
|
190
|
+
if (expectedLauncher === undefined) return false;
|
|
191
|
+
if (expectedLauncher === null) return true;
|
|
192
|
+
return server.command.toLowerCase() !== expectedLauncher.command.toLowerCase()
|
|
193
|
+
|| npxCli.toLowerCase() !== expectedLauncher.argsPrefix[0].toLowerCase();
|
|
194
|
+
}
|
|
195
|
+
|
|
175
196
|
function mergeMcpConfig(configPath, serverConfig) {
|
|
176
197
|
const current = readMcpConfig(configPath);
|
|
177
198
|
if (current.config === null) throw new Error(current.error);
|
|
@@ -228,18 +249,22 @@ function parseSelfCheckOutput(output) {
|
|
|
228
249
|
throw new Error('mcp-server self-check did not return a valid JSON payload');
|
|
229
250
|
}
|
|
230
251
|
|
|
231
|
-
function runMcpSelfCheck({
|
|
232
|
-
return selfCheck({
|
|
252
|
+
function runMcpSelfCheck({ launcher, env, selfCheck = defaultMcpSelfCheck } = {}) {
|
|
253
|
+
return selfCheck({ launcher, env });
|
|
233
254
|
}
|
|
234
255
|
|
|
235
|
-
function defaultMcpSelfCheck({
|
|
256
|
+
function defaultMcpSelfCheck({ launcher, env, execFile = execFileSync }) {
|
|
236
257
|
try {
|
|
237
|
-
const output =
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
258
|
+
const output = execFile(
|
|
259
|
+
launcher.command,
|
|
260
|
+
launcher.argsPrefix.concat(['-y', '@scorehub/mcp-server@latest', '--self-check', '--json']),
|
|
261
|
+
{
|
|
262
|
+
encoding: 'utf8',
|
|
263
|
+
env,
|
|
264
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
265
|
+
timeout: 30000,
|
|
266
|
+
},
|
|
267
|
+
);
|
|
243
268
|
const payload = parseSelfCheckOutput(output);
|
|
244
269
|
if (!payload.ok) throw new Error(`mcp-server self-check failed for Node.js ${payload.node_version}`);
|
|
245
270
|
return payload;
|
|
@@ -268,13 +293,24 @@ function detectStatus({ paths, state, nodeVersion }) {
|
|
|
268
293
|
return { status: 'ready', reason: null };
|
|
269
294
|
}
|
|
270
295
|
|
|
271
|
-
function check({
|
|
296
|
+
function check({
|
|
297
|
+
homeDir = os.homedir(),
|
|
298
|
+
nodeVersion = process.versions.node,
|
|
299
|
+
now = Date.now(),
|
|
300
|
+
platform = process.platform,
|
|
301
|
+
} = {}) {
|
|
272
302
|
const paths = getPaths(homeDir);
|
|
273
303
|
const state = loadState(paths.bootstrapState);
|
|
274
304
|
const detected = detectStatus({ paths, state, nodeVersion });
|
|
275
305
|
const lastCheckAt = state.last_check_at ? Date.parse(state.last_check_at) : Number.NaN;
|
|
306
|
+
const mcp = readMcpConfig(paths.workBuddyMcpJson);
|
|
307
|
+
const expectedLauncher = platform === 'win32'
|
|
308
|
+
? resolveWorkBuddyLauncher(paths.workBuddyDir, platform)
|
|
309
|
+
: undefined;
|
|
310
|
+
const launcherMigrationDue = mcp.config !== null
|
|
311
|
+
&& needsMcpLauncherMigration(mcp.config, platform, expectedLauncher);
|
|
276
312
|
const updateDue = detected.status === 'ready'
|
|
277
|
-
&& (!Number.isFinite(lastCheckAt) || now - lastCheckAt >= UPDATE_INTERVAL_MS);
|
|
313
|
+
&& (launcherMigrationDue || !Number.isFinite(lastCheckAt) || now - lastCheckAt >= UPDATE_INTERVAL_MS);
|
|
278
314
|
return {
|
|
279
315
|
schema_version: STATE_SCHEMA_VERSION,
|
|
280
316
|
status: detected.status,
|
|
@@ -287,11 +323,15 @@ function check({ homeDir = os.homedir(), nodeVersion = process.versions.node, no
|
|
|
287
323
|
};
|
|
288
324
|
}
|
|
289
325
|
|
|
290
|
-
function assertInstallable({ homeDir, nodeVersion }) {
|
|
326
|
+
function assertInstallable({ homeDir, nodeVersion, platform }) {
|
|
291
327
|
const paths = getPaths(homeDir);
|
|
292
328
|
if (!isSupportedNode(nodeVersion)) throw new Error(`Node.js ${MIN_NODE_MAJOR}+ is required. Detected ${nodeVersion}.`);
|
|
293
329
|
if (!fs.existsSync(paths.workBuddyDir)) throw new Error('No supported client was found. Launch WorkBuddy once, then retry.');
|
|
294
|
-
|
|
330
|
+
const launcher = resolveWorkBuddyLauncher(paths.workBuddyDir, platform);
|
|
331
|
+
if (!launcher) {
|
|
332
|
+
throw new Error('WorkBuddy managed Node.js/npm runtime is incomplete: expected node.exe and node_modules/npm/bin/npx-cli.js in the same version directory.');
|
|
333
|
+
}
|
|
334
|
+
return { paths, launcher };
|
|
295
335
|
}
|
|
296
336
|
|
|
297
337
|
function install({
|
|
@@ -300,16 +340,17 @@ function install({
|
|
|
300
340
|
selfCheck = defaultMcpSelfCheck,
|
|
301
341
|
markConsent = true,
|
|
302
342
|
replacePlugin = replacePluginAtomic,
|
|
343
|
+
platform = process.platform,
|
|
303
344
|
} = {}) {
|
|
304
|
-
const { paths,
|
|
305
|
-
const env = buildMcpEnvironment(pkg.version,
|
|
306
|
-
const mcpCheck = runMcpSelfCheck({
|
|
345
|
+
const { paths, launcher } = assertInstallable({ homeDir, nodeVersion, platform });
|
|
346
|
+
const env = buildMcpEnvironment(pkg.version, launcher.binDir);
|
|
347
|
+
const mcpCheck = runMcpSelfCheck({ launcher, env, selfCheck });
|
|
307
348
|
const mcpSnapshot = snapshotFile(paths.workBuddyMcpJson);
|
|
308
349
|
const stateSnapshot = snapshotFile(paths.bootstrapState);
|
|
309
350
|
let pluginBackup = null;
|
|
310
351
|
let pluginReplaced = false;
|
|
311
352
|
try {
|
|
312
|
-
mergeMcpConfig(paths.workBuddyMcpJson, buildMcpConfig(pkg.version,
|
|
353
|
+
mergeMcpConfig(paths.workBuddyMcpJson, buildMcpConfig(pkg.version, launcher));
|
|
313
354
|
pluginBackup = replacePlugin(paths.workBuddyPluginDir);
|
|
314
355
|
pluginReplaced = true;
|
|
315
356
|
|
|
@@ -348,6 +389,7 @@ function update({
|
|
|
348
389
|
homeDir = os.homedir(),
|
|
349
390
|
nodeVersion = process.versions.node,
|
|
350
391
|
selfCheck = defaultMcpSelfCheck,
|
|
392
|
+
platform = process.platform,
|
|
351
393
|
} = {}) {
|
|
352
394
|
const paths = getPaths(homeDir);
|
|
353
395
|
const state = loadState(paths.bootstrapState);
|
|
@@ -357,7 +399,13 @@ function update({
|
|
|
357
399
|
return { status: detected.status, reason: detected.reason };
|
|
358
400
|
}
|
|
359
401
|
if (state.restart_required) return { status: 'restart_required', reason: 'WorkBuddy must be restarted to load the updated plugin and MCP configuration.' };
|
|
360
|
-
|
|
402
|
+
const mcp = readMcpConfig(paths.workBuddyMcpJson);
|
|
403
|
+
const expectedLauncher = platform === 'win32'
|
|
404
|
+
? resolveWorkBuddyLauncher(paths.workBuddyDir, platform)
|
|
405
|
+
: undefined;
|
|
406
|
+
const launcherMigrationDue = mcp.config !== null
|
|
407
|
+
&& needsMcpLauncherMigration(mcp.config, platform, expectedLauncher);
|
|
408
|
+
if (readInstalledPluginVersion(paths.workBuddyPluginDir) === pkg.version && !launcherMigrationDue) {
|
|
361
409
|
state.status = 'ready';
|
|
362
410
|
state.creator_outreach_version = pkg.version;
|
|
363
411
|
state.last_check_at = new Date().toISOString();
|
|
@@ -365,7 +413,7 @@ function update({
|
|
|
365
413
|
writeJsonAtomic(paths.bootstrapState, state);
|
|
366
414
|
return { status: 'ready', creator_outreach_version: pkg.version };
|
|
367
415
|
}
|
|
368
|
-
return install({ homeDir, nodeVersion, selfCheck, markConsent: false });
|
|
416
|
+
return install({ homeDir, nodeVersion, selfCheck, markConsent: false, platform });
|
|
369
417
|
}
|
|
370
418
|
|
|
371
419
|
function printJson(value) {
|
|
@@ -403,6 +451,7 @@ module.exports = {
|
|
|
403
451
|
UPDATE_INTERVAL_MS,
|
|
404
452
|
WORKBUDDY_SHARE_URL,
|
|
405
453
|
check,
|
|
454
|
+
defaultMcpSelfCheck,
|
|
406
455
|
detectStatus,
|
|
407
456
|
getNodeMajorVersion,
|
|
408
457
|
getPaths,
|
|
@@ -410,6 +459,8 @@ module.exports = {
|
|
|
410
459
|
isManagedMcpConfig,
|
|
411
460
|
isSupportedNode,
|
|
412
461
|
markReady,
|
|
462
|
+
needsMcpLauncherMigration,
|
|
463
|
+
resolveWorkBuddyLauncher,
|
|
413
464
|
runCli,
|
|
414
465
|
update,
|
|
415
466
|
};
|