@taptap/instant-games-open-mcp 1.22.0-beta.5 → 1.22.0-beta.6
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 +4 -0
- package/dist/maker.js +689 -100
- package/dist/proxy.js +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -72,17 +72,21 @@ maker_push_current_directory
|
|
|
72
72
|
- 保存 PAT 后会自动列出 app;`maker_status` 如果发现本地已有 PAT 且当前目录未绑定,也会自动列出 app,无需用户额外要求。
|
|
73
73
|
- 保存 PAT 后会自动调用 `GET /api/v1/user/taptap-token` 获取并保存 TapTap MAC token;Tap OAuth 登录只作为 legacy fallback。
|
|
74
74
|
- `maker_list_apps` 和 `maker_clone_to_current_directory` 不再要求先完成 Tap 登录。
|
|
75
|
+
- `maker_clone_to_current_directory` 不要求当前目录为空;clone 前会检查本地目录,忽略 `.claude`、`.mcp`、`.skill`、`.config`、`.ini` 等点开头配置项,只对普通本地文件输出提醒。clone 最终结果固定包含 `Pre-clone local directory check` 区块;已有本地文件会保留,若与 Maker 项目文件同路径冲突则失败并列出冲突文件。
|
|
76
|
+
- `maker_list_apps` 会解析 Maker `/apps` 返回的创建时间、最近会话时间、游戏类型、阶段、图标、置顶/归档/删除时间等字段,并保留原始 `raw` 数据。
|
|
75
77
|
- Maker Tap 登录只需要 client id;`rnd` 环境或 npm `@beta` 包会使用内置 Maker client id 兜底,不要求产品配置 `TAPTAP_MCP_CLIENT_SECRET`。
|
|
76
78
|
- PAT 会保存到 `~/.taptap-maker/pat.json`,并兼容旧的 `~/.maker-pat`、`PAT` / `MAKER_PAT` 环境变量。
|
|
77
79
|
- JWT 仅作为 legacy fallback 保留:`maker_exchange_jwt(manual_jwt)`、`JWT` / `MAKER_JWT` 仍可用于旧后端或创建新 PAT。
|
|
78
80
|
- Maker app 必须先通过 `maker_list_apps` 展示给用户选择,再调用 clone。
|
|
79
81
|
- Maker 后端地址按 `TAPTAP_MCP_ENV` 从 `src/maker/config.ts` 的环境配置表读取,本地 MCP 配置只需要切 `rnd` / `production`。
|
|
80
82
|
- 如果用户直接说“构建 / build / 重新构建游戏”,本地 Maker MCP 应调用 `maker_build_current_directory` 转发到远端 `build` tool。
|
|
83
|
+
- 构建转发会从 MCP 包自身定位 `dist/proxy.js`;`cwd` / `target_dir` 只用于识别 Maker 游戏项目,不要求游戏目录存在 MCP 的 `dist/proxy.js`。
|
|
81
84
|
- 如需在当前游戏项目里直接暴露远端全量 `taptap-proxy` tools,再使用 `maker_configure_remote_proxy` 写入 `.mcp.json` 并重启 MCP 会话。
|
|
82
85
|
- 用户说“帮我提交/提交代码”时使用 `maker_submit_current_directory`,会对当前 Maker 项目执行 commit + push。
|
|
83
86
|
- “帮我提交代码到maker / taptap制造 / tap制造 / tap”也应触发 `maker_submit_current_directory`。
|
|
84
87
|
- Maker 项目提交不走通用 Git skill 的任务号、新分支规则;冲突时先和用户确认 pull/rebase 流程。
|
|
85
88
|
- 如果 commit 已完成但 push 失败,Maker MCP 会返回 commit hash、ahead 状态、exit code、stderr/stdout 和下一步建议,便于开发期排查。
|
|
89
|
+
- clone/fetch、push 和远端 build 属于慢操作;工具会尽量发送 MCP progress notification,Git 阶段会解析 stderr 百分比,最终返回会包含耗时和最近进度。
|
|
86
90
|
|
|
87
91
|
Git 引导:
|
|
88
92
|
|
package/dist/maker.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// TapTap Maker MCP - Standalone Bundle
|
|
3
3
|
import { createRequire } from 'node:module';
|
|
4
4
|
const require = createRequire(import.meta.url);
|
|
5
|
+
const __MAKER_BUNDLE_URL__ = import.meta.url;
|
|
5
6
|
|
|
6
7
|
var __create = Object.create;
|
|
7
8
|
var __defProp = Object.defineProperty;
|
|
@@ -25750,7 +25751,7 @@ function requireMakerJwt(manualJwt) {
|
|
|
25750
25751
|
var BUILT_IN_MAKER_CLIENT_ID = "m2dnabebip3fpardnm";
|
|
25751
25752
|
var MAKER_CLIENT_ID_ENV = "TAPTAP_MAKER_CLIENT_ID";
|
|
25752
25753
|
var TAPTAP_CLIENT_ID_ENV = "TAPTAP_MCP_CLIENT_ID";
|
|
25753
|
-
var MAKER_VERSION = true ? "1.22.0-beta.
|
|
25754
|
+
var MAKER_VERSION = true ? "1.22.0-beta.6" : "dev";
|
|
25754
25755
|
async function startTapDeviceLogin() {
|
|
25755
25756
|
ensureMakerClientId();
|
|
25756
25757
|
const environment = EnvConfig.environment;
|
|
@@ -26158,17 +26159,59 @@ function getMakerApiBase() {
|
|
|
26158
26159
|
function getMakerGitBase() {
|
|
26159
26160
|
return requireMakerEndpoint("gitBase", getConfiguredMakerGitBase()).replace(/\/$/, "");
|
|
26160
26161
|
}
|
|
26162
|
+
function stringField(item, ...keys) {
|
|
26163
|
+
for (const key of keys) {
|
|
26164
|
+
const value = item[key];
|
|
26165
|
+
if (typeof value === "string") {
|
|
26166
|
+
return value;
|
|
26167
|
+
}
|
|
26168
|
+
}
|
|
26169
|
+
return void 0;
|
|
26170
|
+
}
|
|
26171
|
+
function nullableStringField(item, ...keys) {
|
|
26172
|
+
for (const key of keys) {
|
|
26173
|
+
const value = item[key];
|
|
26174
|
+
if (typeof value === "string" || value === null) {
|
|
26175
|
+
return value;
|
|
26176
|
+
}
|
|
26177
|
+
}
|
|
26178
|
+
return void 0;
|
|
26179
|
+
}
|
|
26180
|
+
function numberField(item, ...keys) {
|
|
26181
|
+
for (const key of keys) {
|
|
26182
|
+
const value = item[key];
|
|
26183
|
+
if (typeof value === "number") {
|
|
26184
|
+
return value;
|
|
26185
|
+
}
|
|
26186
|
+
}
|
|
26187
|
+
return void 0;
|
|
26188
|
+
}
|
|
26161
26189
|
function normalizeProjectsResponse(data) {
|
|
26162
26190
|
const body = data;
|
|
26163
26191
|
const list = Array.isArray(data) ? data : Array.isArray(body.data) ? body.data : Array.isArray(body.apps) ? body.apps : Array.isArray(body.projects) ? body.projects : [];
|
|
26164
|
-
return list.map((item) => item).map((item) =>
|
|
26165
|
-
|
|
26166
|
-
|
|
26167
|
-
|
|
26168
|
-
|
|
26169
|
-
|
|
26170
|
-
|
|
26171
|
-
|
|
26192
|
+
return list.map((item) => item).map((item) => {
|
|
26193
|
+
const userId = stringField(item, "userId", "user_id");
|
|
26194
|
+
return {
|
|
26195
|
+
id: String(item.id || item.app_id || item.project_id || ""),
|
|
26196
|
+
name: stringField(item, "name", "title"),
|
|
26197
|
+
userId,
|
|
26198
|
+
user_id: userId,
|
|
26199
|
+
createdAt: stringField(item, "createdAt", "created_at"),
|
|
26200
|
+
archivedAt: nullableStringField(item, "archivedAt", "archived_at"),
|
|
26201
|
+
deletedAt: nullableStringField(item, "deletedAt", "deleted_at"),
|
|
26202
|
+
gameType: stringField(item, "gameType", "game_type"),
|
|
26203
|
+
icon: numberField(item, "icon"),
|
|
26204
|
+
iconColor: numberField(item, "iconColor", "icon_color"),
|
|
26205
|
+
lastAccessedAt: nullableStringField(item, "lastAccessedAt", "last_accessed_at"),
|
|
26206
|
+
lastConversationAt: stringField(item, "lastConversationAt", "last_conversation_at"),
|
|
26207
|
+
metadata: item.metadata,
|
|
26208
|
+
pinnedAt: nullableStringField(item, "pinnedAt", "pinned_at"),
|
|
26209
|
+
stage: stringField(item, "stage"),
|
|
26210
|
+
sce_endpoint: stringField(item, "sce_endpoint", "sce_mcp_url"),
|
|
26211
|
+
git_url: stringField(item, "git_url"),
|
|
26212
|
+
raw: item
|
|
26213
|
+
};
|
|
26214
|
+
}).filter((project) => project.id.length > 0);
|
|
26172
26215
|
}
|
|
26173
26216
|
async function runProjects(args, flags) {
|
|
26174
26217
|
const subcommand = args[0] || "list";
|
|
@@ -26265,41 +26308,70 @@ async function pushProject(flags) {
|
|
|
26265
26308
|
`);
|
|
26266
26309
|
}
|
|
26267
26310
|
async function cloneMakerProject(options) {
|
|
26268
|
-
|
|
26311
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h;
|
|
26269
26312
|
const target = path6.resolve(options.targetDir);
|
|
26270
26313
|
ensureTargetCanBindApp(target, options.appId);
|
|
26314
|
+
const warnings = createPreCloneWarnings(target);
|
|
26315
|
+
(_a2 = options.onProgress) == null ? void 0 : _a2.call(options, {
|
|
26316
|
+
progress: 0,
|
|
26317
|
+
total: 100,
|
|
26318
|
+
phase: "pre_clone_check",
|
|
26319
|
+
message: formatPreCloneProgressMessage(options.appId, warnings)
|
|
26320
|
+
});
|
|
26321
|
+
ensureGitAvailable();
|
|
26322
|
+
(_b = options.onProgress) == null ? void 0 : _b.call(options, {
|
|
26323
|
+
progress: 1,
|
|
26324
|
+
total: 100,
|
|
26325
|
+
phase: "prepare",
|
|
26326
|
+
message: `Preparing Maker project ${options.appId}`
|
|
26327
|
+
});
|
|
26271
26328
|
let pat = await requestMakerPat({
|
|
26272
26329
|
jwt: options.jwt,
|
|
26273
26330
|
pat: options.pat,
|
|
26274
26331
|
name: options.patName || "first-pat",
|
|
26275
26332
|
force: options.forcePat
|
|
26276
26333
|
});
|
|
26334
|
+
(_c = options.onProgress) == null ? void 0 : _c.call(options, {
|
|
26335
|
+
progress: 5,
|
|
26336
|
+
total: 100,
|
|
26337
|
+
phase: "auth",
|
|
26338
|
+
message: "Maker PAT ready for git authentication"
|
|
26339
|
+
});
|
|
26277
26340
|
const gitBase = getMakerGitBase();
|
|
26278
26341
|
const gitUrl = `${gitBase}/${options.appId}.git`;
|
|
26279
26342
|
let authUrl = makeAuthenticatedGitUrl(gitUrl, pat.token);
|
|
26280
26343
|
let retriedWithNewPat = false;
|
|
26281
26344
|
let transientRetries = 0;
|
|
26282
|
-
if (isGitRepo(target)) {
|
|
26345
|
+
if (isGitRepo(target) && hasGitHead(target)) {
|
|
26346
|
+
(_d = options.onProgress) == null ? void 0 : _d.call(options, {
|
|
26347
|
+
progress: 10,
|
|
26348
|
+
total: 100,
|
|
26349
|
+
phase: "fetch",
|
|
26350
|
+
message: "Existing git repository found; fetching origin"
|
|
26351
|
+
});
|
|
26283
26352
|
await setOrigin(target, authUrl);
|
|
26284
26353
|
try {
|
|
26285
26354
|
transientRetries += await runGitWithTransientRetry(["fetch", "origin"], {
|
|
26286
|
-
cwd: target
|
|
26355
|
+
cwd: target,
|
|
26356
|
+
onProgress: options.onProgress
|
|
26287
26357
|
});
|
|
26288
26358
|
} catch (error2) {
|
|
26289
|
-
if (options.forcePat) {
|
|
26290
|
-
throw error2;
|
|
26359
|
+
if (options.forcePat || !isAuthGitError(error2)) {
|
|
26360
|
+
throw withPreCloneWarnings(error2, warnings);
|
|
26291
26361
|
}
|
|
26292
|
-
pat = await
|
|
26362
|
+
pat = await refreshPatAfterAuthFailure(error2, {
|
|
26293
26363
|
jwt: options.jwt,
|
|
26294
26364
|
pat: options.pat,
|
|
26295
|
-
name: options.patName || "first-pat"
|
|
26296
|
-
force: true
|
|
26365
|
+
name: options.patName || "first-pat"
|
|
26297
26366
|
});
|
|
26298
26367
|
authUrl = makeAuthenticatedGitUrl(gitUrl, pat.token);
|
|
26299
26368
|
retriedWithNewPat = true;
|
|
26300
26369
|
await setOrigin(target, authUrl);
|
|
26301
26370
|
transientRetries += await runGitWithTransientRetry(["fetch", "origin"], {
|
|
26302
|
-
cwd: target
|
|
26371
|
+
cwd: target,
|
|
26372
|
+
onProgress: options.onProgress
|
|
26373
|
+
}).catch((retryError) => {
|
|
26374
|
+
throw withPreCloneWarnings(retryError, warnings);
|
|
26303
26375
|
});
|
|
26304
26376
|
}
|
|
26305
26377
|
saveProjectConfig(target, {
|
|
@@ -26307,59 +26379,99 @@ async function cloneMakerProject(options) {
|
|
|
26307
26379
|
user_id: options.userId || await resolveMakerProjectUserId(options),
|
|
26308
26380
|
sce_endpoint: options.sceEndpoint
|
|
26309
26381
|
});
|
|
26382
|
+
(_e = options.onProgress) == null ? void 0 : _e.call(options, {
|
|
26383
|
+
progress: 100,
|
|
26384
|
+
total: 100,
|
|
26385
|
+
phase: "done",
|
|
26386
|
+
message: "Maker project fetch completed"
|
|
26387
|
+
});
|
|
26310
26388
|
return {
|
|
26311
26389
|
appId: options.appId,
|
|
26312
26390
|
targetDir: target,
|
|
26313
26391
|
status: "fetched",
|
|
26314
26392
|
retriedWithNewPat,
|
|
26315
|
-
transientRetries
|
|
26393
|
+
transientRetries,
|
|
26394
|
+
warnings
|
|
26316
26395
|
};
|
|
26317
26396
|
}
|
|
26318
|
-
if (
|
|
26319
|
-
|
|
26320
|
-
|
|
26321
|
-
`${target} is not empty and is not a git repository.`,
|
|
26322
|
-
"Maker clone can be run multiple times after the directory is a git repo, but the first clone requires an empty target directory.",
|
|
26323
|
-
"Please open an empty directory, or remove the unrelated files before cloning."
|
|
26324
|
-
].join("\n")
|
|
26397
|
+
if (isGitRepo(target)) {
|
|
26398
|
+
warnings.push(
|
|
26399
|
+
"Target directory already contained git metadata but no checked-out commit. Maker MCP will fetch and check out the remote Maker project branch before reporting success."
|
|
26325
26400
|
);
|
|
26326
26401
|
}
|
|
26327
26402
|
try {
|
|
26328
|
-
|
|
26329
|
-
|
|
26403
|
+
(_f = options.onProgress) == null ? void 0 : _f.call(options, {
|
|
26404
|
+
progress: 10,
|
|
26405
|
+
total: 100,
|
|
26406
|
+
phase: "clone",
|
|
26407
|
+
message: `Cloning Maker project ${options.appId}`
|
|
26330
26408
|
});
|
|
26409
|
+
transientRetries += await cloneOrInitializeTarget(
|
|
26410
|
+
target,
|
|
26411
|
+
authUrl,
|
|
26412
|
+
pat.token,
|
|
26413
|
+
options.onProgress
|
|
26414
|
+
);
|
|
26331
26415
|
} catch (error2) {
|
|
26332
|
-
if (options.forcePat) {
|
|
26333
|
-
throw error2;
|
|
26416
|
+
if (options.forcePat || !isAuthGitError(error2)) {
|
|
26417
|
+
throw withPreCloneWarnings(error2, warnings);
|
|
26334
26418
|
}
|
|
26335
|
-
pat = await
|
|
26419
|
+
pat = await refreshPatAfterAuthFailure(error2, {
|
|
26336
26420
|
jwt: options.jwt,
|
|
26337
26421
|
pat: options.pat,
|
|
26338
|
-
name: options.patName || "first-pat"
|
|
26339
|
-
force: true
|
|
26422
|
+
name: options.patName || "first-pat"
|
|
26340
26423
|
});
|
|
26341
26424
|
authUrl = makeAuthenticatedGitUrl(gitUrl, pat.token);
|
|
26342
26425
|
retriedWithNewPat = true;
|
|
26343
|
-
|
|
26344
|
-
|
|
26426
|
+
(_g = options.onProgress) == null ? void 0 : _g.call(options, {
|
|
26427
|
+
progress: 10,
|
|
26428
|
+
total: 100,
|
|
26429
|
+
phase: "clone",
|
|
26430
|
+
message: `Retrying clone for Maker project ${options.appId} with refreshed PAT`
|
|
26345
26431
|
});
|
|
26432
|
+
transientRetries += await cloneOrInitializeTarget(
|
|
26433
|
+
target,
|
|
26434
|
+
authUrl,
|
|
26435
|
+
pat.token,
|
|
26436
|
+
options.onProgress
|
|
26437
|
+
).catch((retryError) => {
|
|
26438
|
+
throw withPreCloneWarnings(retryError, warnings);
|
|
26439
|
+
});
|
|
26440
|
+
}
|
|
26441
|
+
try {
|
|
26442
|
+
ensureGitHeadCheckedOut(target);
|
|
26443
|
+
} catch (error2) {
|
|
26444
|
+
throw withPreCloneWarnings(error2, warnings);
|
|
26346
26445
|
}
|
|
26347
26446
|
saveProjectConfig(target, {
|
|
26348
26447
|
project_id: options.appId,
|
|
26349
26448
|
user_id: options.userId || await resolveMakerProjectUserId(options),
|
|
26350
26449
|
sce_endpoint: options.sceEndpoint
|
|
26351
26450
|
});
|
|
26451
|
+
(_h = options.onProgress) == null ? void 0 : _h.call(options, {
|
|
26452
|
+
progress: 100,
|
|
26453
|
+
total: 100,
|
|
26454
|
+
phase: "done",
|
|
26455
|
+
message: "Maker project clone completed"
|
|
26456
|
+
});
|
|
26352
26457
|
return {
|
|
26353
26458
|
appId: options.appId,
|
|
26354
26459
|
targetDir: target,
|
|
26355
26460
|
status: "cloned",
|
|
26356
26461
|
retriedWithNewPat,
|
|
26357
|
-
transientRetries
|
|
26462
|
+
transientRetries,
|
|
26463
|
+
warnings
|
|
26358
26464
|
};
|
|
26359
26465
|
}
|
|
26360
26466
|
async function pushMakerProject(options) {
|
|
26361
|
-
var _a2;
|
|
26467
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
26362
26468
|
ensureGitAvailable();
|
|
26469
|
+
(_a2 = options.onProgress) == null ? void 0 : _a2.call(options, {
|
|
26470
|
+
progress: 0,
|
|
26471
|
+
total: 100,
|
|
26472
|
+
phase: "prepare",
|
|
26473
|
+
message: "Preparing Maker project push"
|
|
26474
|
+
});
|
|
26363
26475
|
const cwd = path6.resolve(options.cwd);
|
|
26364
26476
|
if (!isGitRepo(cwd)) {
|
|
26365
26477
|
throw new Error(`${cwd} is not a git repository.`);
|
|
@@ -26377,11 +26489,24 @@ async function pushMakerProject(options) {
|
|
|
26377
26489
|
appId: project.project_id,
|
|
26378
26490
|
jwt: options.jwt,
|
|
26379
26491
|
pat: options.pat,
|
|
26380
|
-
forcePat: options.forcePat
|
|
26492
|
+
forcePat: options.forcePat,
|
|
26493
|
+
onProgress: options.onProgress
|
|
26494
|
+
});
|
|
26495
|
+
(_b = options.onProgress) == null ? void 0 : _b.call(options, {
|
|
26496
|
+
progress: 10,
|
|
26497
|
+
total: 100,
|
|
26498
|
+
phase: "auth",
|
|
26499
|
+
message: "Authenticated Maker git origin ready"
|
|
26381
26500
|
});
|
|
26382
26501
|
const statusBefore = await readGit(["status", "--porcelain"], cwd);
|
|
26383
26502
|
const branch = await currentBranch(cwd, options.branch);
|
|
26384
26503
|
if (!statusBefore.trim() && !options.allowEmpty) {
|
|
26504
|
+
(_c = options.onProgress) == null ? void 0 : _c.call(options, {
|
|
26505
|
+
progress: 100,
|
|
26506
|
+
total: 100,
|
|
26507
|
+
phase: "done",
|
|
26508
|
+
message: "Maker project has no local changes to push"
|
|
26509
|
+
});
|
|
26385
26510
|
return {
|
|
26386
26511
|
branch,
|
|
26387
26512
|
committed: false,
|
|
@@ -26390,9 +26515,21 @@ async function pushMakerProject(options) {
|
|
|
26390
26515
|
status: "clean"
|
|
26391
26516
|
};
|
|
26392
26517
|
}
|
|
26393
|
-
if ((
|
|
26518
|
+
if ((_d = options.files) == null ? void 0 : _d.length) {
|
|
26519
|
+
(_e = options.onProgress) == null ? void 0 : _e.call(options, {
|
|
26520
|
+
progress: 20,
|
|
26521
|
+
total: 100,
|
|
26522
|
+
phase: "stage",
|
|
26523
|
+
message: "Staging selected files"
|
|
26524
|
+
});
|
|
26394
26525
|
await runGit(["add", ...options.files], { cwd });
|
|
26395
26526
|
} else {
|
|
26527
|
+
(_f = options.onProgress) == null ? void 0 : _f.call(options, {
|
|
26528
|
+
progress: 20,
|
|
26529
|
+
total: 100,
|
|
26530
|
+
phase: "stage",
|
|
26531
|
+
message: "Staging all local changes"
|
|
26532
|
+
});
|
|
26396
26533
|
await runGit(["add", "-A"], { cwd });
|
|
26397
26534
|
}
|
|
26398
26535
|
const staged = await readGit(["diff", "--cached", "--name-only"], cwd);
|
|
@@ -26400,6 +26537,12 @@ async function pushMakerProject(options) {
|
|
|
26400
26537
|
let commitHash;
|
|
26401
26538
|
const message = options.message || generateCommitMessage(statusBefore);
|
|
26402
26539
|
if (staged.trim() || options.allowEmpty) {
|
|
26540
|
+
(_g = options.onProgress) == null ? void 0 : _g.call(options, {
|
|
26541
|
+
progress: 45,
|
|
26542
|
+
total: 100,
|
|
26543
|
+
phase: "commit",
|
|
26544
|
+
message: "Creating local Maker project commit"
|
|
26545
|
+
});
|
|
26403
26546
|
await runGit(
|
|
26404
26547
|
[
|
|
26405
26548
|
"-c",
|
|
@@ -26417,7 +26560,13 @@ async function pushMakerProject(options) {
|
|
|
26417
26560
|
commitHash = (await readGit(["rev-parse", "--short", "HEAD"], cwd)).trim();
|
|
26418
26561
|
}
|
|
26419
26562
|
try {
|
|
26420
|
-
|
|
26563
|
+
(_h = options.onProgress) == null ? void 0 : _h.call(options, {
|
|
26564
|
+
progress: 65,
|
|
26565
|
+
total: 100,
|
|
26566
|
+
phase: "push",
|
|
26567
|
+
message: `Pushing Maker project to ${branch}`
|
|
26568
|
+
});
|
|
26569
|
+
await pushGit(["push", "origin", `HEAD:${branch}`], cwd, options.onProgress);
|
|
26421
26570
|
} catch (error2) {
|
|
26422
26571
|
const failure = toMakerGitFailure(error2, "push");
|
|
26423
26572
|
return {
|
|
@@ -26431,6 +26580,12 @@ async function pushMakerProject(options) {
|
|
|
26431
26580
|
ahead: await readAheadState(cwd)
|
|
26432
26581
|
};
|
|
26433
26582
|
}
|
|
26583
|
+
(_i = options.onProgress) == null ? void 0 : _i.call(options, {
|
|
26584
|
+
progress: 100,
|
|
26585
|
+
total: 100,
|
|
26586
|
+
phase: "done",
|
|
26587
|
+
message: "Maker project push completed"
|
|
26588
|
+
});
|
|
26434
26589
|
return {
|
|
26435
26590
|
branch,
|
|
26436
26591
|
committed,
|
|
@@ -26545,7 +26700,7 @@ function nextActionForFailure(classification) {
|
|
|
26545
26700
|
return "保留本地提交,不要重复提交;把错误详情反馈给用户,并在确认后重试 push。";
|
|
26546
26701
|
}
|
|
26547
26702
|
}
|
|
26548
|
-
function pushGit(args, cwd) {
|
|
26703
|
+
function pushGit(args, cwd, onProgress) {
|
|
26549
26704
|
return new Promise((resolve2, reject) => {
|
|
26550
26705
|
const gitCommand = getGitCommand();
|
|
26551
26706
|
const child = spawn(gitCommand, args, {
|
|
@@ -26556,6 +26711,7 @@ function pushGit(args, cwd) {
|
|
|
26556
26711
|
let stderr = "";
|
|
26557
26712
|
child.stderr.on("data", (chunk) => {
|
|
26558
26713
|
stderr += String(chunk);
|
|
26714
|
+
emitGitProgress(chunk, onProgress);
|
|
26559
26715
|
});
|
|
26560
26716
|
child.stdout.on("data", (chunk) => {
|
|
26561
26717
|
stdout += String(chunk);
|
|
@@ -26605,6 +26761,7 @@ async function resolveMakerProjectUserId(options) {
|
|
|
26605
26761
|
}
|
|
26606
26762
|
}
|
|
26607
26763
|
async function ensureAuthenticatedOrigin(options) {
|
|
26764
|
+
var _a2;
|
|
26608
26765
|
const pat = await requestMakerPat({
|
|
26609
26766
|
jwt: options.jwt,
|
|
26610
26767
|
pat: options.pat,
|
|
@@ -26615,15 +26772,189 @@ async function ensureAuthenticatedOrigin(options) {
|
|
|
26615
26772
|
const gitUrl = `${gitBase}/${options.appId}.git`;
|
|
26616
26773
|
const authUrl = makeAuthenticatedGitUrl(gitUrl, pat.token);
|
|
26617
26774
|
await setOrigin(options.cwd, authUrl);
|
|
26775
|
+
(_a2 = options.onProgress) == null ? void 0 : _a2.call(options, {
|
|
26776
|
+
progress: 8,
|
|
26777
|
+
total: 100,
|
|
26778
|
+
phase: "auth",
|
|
26779
|
+
message: "Maker git origin updated with PAT authentication"
|
|
26780
|
+
});
|
|
26618
26781
|
}
|
|
26619
26782
|
function makeAuthenticatedGitUrl(gitUrl, pat) {
|
|
26620
26783
|
return gitUrl.replace(/^https:\/\//, `https://git:${encodeURIComponent(pat)}@`);
|
|
26621
26784
|
}
|
|
26622
|
-
function
|
|
26785
|
+
async function cloneOrInitializeTarget(target, authUrl, pat, onProgress) {
|
|
26786
|
+
if (fs4.existsSync(target) && hasDirectoryEntries(target)) {
|
|
26787
|
+
onProgress == null ? void 0 : onProgress({
|
|
26788
|
+
progress: 10,
|
|
26789
|
+
total: 100,
|
|
26790
|
+
phase: "clone",
|
|
26791
|
+
message: "Target directory is not empty; initializing git repository in place and keeping existing untracked files unless they conflict with Maker project files."
|
|
26792
|
+
});
|
|
26793
|
+
let transientRetries = 0;
|
|
26794
|
+
transientRetries += await runGitCaptureWithTransientRetry(["init", target], {
|
|
26795
|
+
sanitize: pat,
|
|
26796
|
+
onProgress
|
|
26797
|
+
});
|
|
26798
|
+
await setOrigin(target, authUrl);
|
|
26799
|
+
transientRetries += await runGitWithTransientRetry(["fetch", "origin"], {
|
|
26800
|
+
cwd: target,
|
|
26801
|
+
onProgress
|
|
26802
|
+
});
|
|
26803
|
+
const branch = await resolveRemoteDefaultBranch(target);
|
|
26804
|
+
await assertNoCheckoutFileConflicts(target, branch);
|
|
26805
|
+
try {
|
|
26806
|
+
transientRetries += await runGitCaptureWithTransientRetry(
|
|
26807
|
+
["checkout", "-B", branch, `origin/${branch}`],
|
|
26808
|
+
{
|
|
26809
|
+
cwd: target,
|
|
26810
|
+
sanitize: pat,
|
|
26811
|
+
onProgress
|
|
26812
|
+
}
|
|
26813
|
+
);
|
|
26814
|
+
} catch (error2) {
|
|
26815
|
+
throw enhanceCheckoutConflictError(error2, target);
|
|
26816
|
+
}
|
|
26817
|
+
return transientRetries;
|
|
26818
|
+
}
|
|
26819
|
+
return runGitCaptureWithTransientRetry(["clone", authUrl, target], {
|
|
26820
|
+
sanitize: pat,
|
|
26821
|
+
onProgress
|
|
26822
|
+
});
|
|
26823
|
+
}
|
|
26824
|
+
function hasDirectoryEntries(target) {
|
|
26623
26825
|
if (!fs4.existsSync(target)) {
|
|
26624
26826
|
return false;
|
|
26625
26827
|
}
|
|
26626
|
-
return fs4.readdirSync(target).
|
|
26828
|
+
return fs4.readdirSync(target).length > 0;
|
|
26829
|
+
}
|
|
26830
|
+
function listLocalFiles(root) {
|
|
26831
|
+
if (!fs4.existsSync(root)) {
|
|
26832
|
+
return [];
|
|
26833
|
+
}
|
|
26834
|
+
const files = [];
|
|
26835
|
+
const visit = (dir, relativeDir) => {
|
|
26836
|
+
for (const entry of fs4.readdirSync(dir, { withFileTypes: true })) {
|
|
26837
|
+
const relativePath = relativeDir ? `${relativeDir}/${entry.name}` : entry.name;
|
|
26838
|
+
if (entry.name === ".git" || relativePath === ".maker-mcp" || relativePath.startsWith(".maker-mcp/") || entry.name === ".DS_Store") {
|
|
26839
|
+
continue;
|
|
26840
|
+
}
|
|
26841
|
+
const fullPath = path6.join(dir, entry.name);
|
|
26842
|
+
if (entry.isDirectory()) {
|
|
26843
|
+
visit(fullPath, relativePath);
|
|
26844
|
+
continue;
|
|
26845
|
+
}
|
|
26846
|
+
if (entry.isFile()) {
|
|
26847
|
+
files.push(relativePath);
|
|
26848
|
+
}
|
|
26849
|
+
}
|
|
26850
|
+
};
|
|
26851
|
+
visit(root, "");
|
|
26852
|
+
return files;
|
|
26853
|
+
}
|
|
26854
|
+
function listPreCloneNoticeFiles(root) {
|
|
26855
|
+
if (!fs4.existsSync(root)) {
|
|
26856
|
+
return [];
|
|
26857
|
+
}
|
|
26858
|
+
return fs4.readdirSync(root, { withFileTypes: true }).filter((entry) => !isIgnorablePreCloneEntry(entry.name)).map((entry) => entry.name).sort();
|
|
26859
|
+
}
|
|
26860
|
+
function createPreCloneWarnings(target) {
|
|
26861
|
+
const preCloneLocalFiles = listPreCloneNoticeFiles(target);
|
|
26862
|
+
if (preCloneLocalFiles.length === 0) {
|
|
26863
|
+
return [];
|
|
26864
|
+
}
|
|
26865
|
+
const preview = preCloneLocalFiles.slice(0, 10);
|
|
26866
|
+
return [
|
|
26867
|
+
[
|
|
26868
|
+
"Pre-clone notice: target directory already contains local files. Maker MCP will keep them and continue unless they conflict with Maker project files.",
|
|
26869
|
+
`local_file_count: ${preCloneLocalFiles.length}`,
|
|
26870
|
+
"local_files:",
|
|
26871
|
+
...preview.map((file2) => ` - ${file2}`),
|
|
26872
|
+
preCloneLocalFiles.length > preview.length ? ` - ... ${preCloneLocalFiles.length - preview.length} more` : ""
|
|
26873
|
+
].filter(Boolean).join("\n")
|
|
26874
|
+
];
|
|
26875
|
+
}
|
|
26876
|
+
function formatPreCloneProgressMessage(appId, warnings) {
|
|
26877
|
+
if (warnings.length === 0) {
|
|
26878
|
+
return `Pre-clone local directory check passed for Maker project ${appId}`;
|
|
26879
|
+
}
|
|
26880
|
+
return [
|
|
26881
|
+
`Pre-clone local directory check found existing local files for Maker project ${appId}.`,
|
|
26882
|
+
...warnings
|
|
26883
|
+
].join("\n");
|
|
26884
|
+
}
|
|
26885
|
+
function isIgnorablePreCloneEntry(entryName) {
|
|
26886
|
+
return entryName === ".DS_Store" || entryName.startsWith(".");
|
|
26887
|
+
}
|
|
26888
|
+
function isAuthGitError(error2) {
|
|
26889
|
+
return toMakerGitFailure(error2, "clone").classification === "auth";
|
|
26890
|
+
}
|
|
26891
|
+
async function refreshPatAfterAuthFailure(originalError, options) {
|
|
26892
|
+
try {
|
|
26893
|
+
return await requestMakerPat({
|
|
26894
|
+
jwt: options.jwt,
|
|
26895
|
+
pat: options.pat,
|
|
26896
|
+
name: options.name || "first-pat",
|
|
26897
|
+
force: true
|
|
26898
|
+
});
|
|
26899
|
+
} catch (refreshError) {
|
|
26900
|
+
const originalMessage = originalError instanceof Error ? originalError.message : String(originalError);
|
|
26901
|
+
const refreshMessage = refreshError instanceof Error ? refreshError.message : String(refreshError);
|
|
26902
|
+
throw new Error(
|
|
26903
|
+
[
|
|
26904
|
+
"Maker git authentication failed and PAT refresh also failed.",
|
|
26905
|
+
"",
|
|
26906
|
+
"original_git_error:",
|
|
26907
|
+
originalMessage,
|
|
26908
|
+
"",
|
|
26909
|
+
"pat_refresh_error:",
|
|
26910
|
+
refreshMessage
|
|
26911
|
+
].join("\n")
|
|
26912
|
+
);
|
|
26913
|
+
}
|
|
26914
|
+
}
|
|
26915
|
+
function withPreCloneWarnings(error2, warnings) {
|
|
26916
|
+
const original = error2 instanceof Error ? error2 : new Error(String(error2));
|
|
26917
|
+
if (warnings.length === 0) {
|
|
26918
|
+
return original;
|
|
26919
|
+
}
|
|
26920
|
+
return new Error(
|
|
26921
|
+
[
|
|
26922
|
+
"Maker clone failed after pre-clone local directory check.",
|
|
26923
|
+
"",
|
|
26924
|
+
"Pre-clone notices:",
|
|
26925
|
+
...warnings.map((warning) => indentText(warning)),
|
|
26926
|
+
"",
|
|
26927
|
+
"original_error:",
|
|
26928
|
+
original.message
|
|
26929
|
+
].join("\n")
|
|
26930
|
+
);
|
|
26931
|
+
}
|
|
26932
|
+
function indentText(text) {
|
|
26933
|
+
return text.split("\n").map((line) => ` ${line}`).join("\n");
|
|
26934
|
+
}
|
|
26935
|
+
async function assertNoCheckoutFileConflicts(cwd, branch) {
|
|
26936
|
+
const remoteTree = await readGit(["ls-tree", "-r", "--name-only", `origin/${branch}`], cwd);
|
|
26937
|
+
const remoteFiles = new Set(
|
|
26938
|
+
remoteTree.split(/\r?\n/).map((line) => line.trim()).filter(Boolean)
|
|
26939
|
+
);
|
|
26940
|
+
if (remoteFiles.size === 0) {
|
|
26941
|
+
return;
|
|
26942
|
+
}
|
|
26943
|
+
const conflicts = listLocalFiles(cwd).filter((file2) => remoteFiles.has(file2)).sort();
|
|
26944
|
+
if (conflicts.length === 0) {
|
|
26945
|
+
return;
|
|
26946
|
+
}
|
|
26947
|
+
throw new Error(
|
|
26948
|
+
[
|
|
26949
|
+
"Maker clone cannot continue because existing local files have the same paths as files in the remote Maker project.",
|
|
26950
|
+
`target_dir: ${cwd}`,
|
|
26951
|
+
"",
|
|
26952
|
+
"Conflicting local files:",
|
|
26953
|
+
...conflicts.map((file2) => `- ${file2}`),
|
|
26954
|
+
"",
|
|
26955
|
+
"Please move, rename, or delete these local files, then retry maker_clone_to_current_directory."
|
|
26956
|
+
].join("\n")
|
|
26957
|
+
);
|
|
26627
26958
|
}
|
|
26628
26959
|
async function setOrigin(cwd, authUrl) {
|
|
26629
26960
|
await runGit(["remote", "get-url", "origin"], { cwd, quiet: true }).then(() => runGit(["remote", "set-url", "origin", authUrl], { cwd, quiet: true })).catch(() => runGit(["remote", "add", "origin", authUrl], { cwd, quiet: true }));
|
|
@@ -26636,6 +26967,41 @@ function isGitRepo(repoDir) {
|
|
|
26636
26967
|
return false;
|
|
26637
26968
|
}
|
|
26638
26969
|
}
|
|
26970
|
+
function hasGitHead(repoDir) {
|
|
26971
|
+
try {
|
|
26972
|
+
const head = readGitSync(["-C", repoDir, "rev-parse", "--verify", "HEAD"]);
|
|
26973
|
+
return head.trim().length > 0;
|
|
26974
|
+
} catch {
|
|
26975
|
+
return false;
|
|
26976
|
+
}
|
|
26977
|
+
}
|
|
26978
|
+
function ensureGitHeadCheckedOut(repoDir) {
|
|
26979
|
+
if (hasGitHead(repoDir)) {
|
|
26980
|
+
return;
|
|
26981
|
+
}
|
|
26982
|
+
throw new Error(
|
|
26983
|
+
[
|
|
26984
|
+
"Maker clone did not complete checkout: local git repository has no HEAD commit.",
|
|
26985
|
+
`target_dir: ${repoDir}`,
|
|
26986
|
+
"The remote fetch may have succeeded, but project files were not checked out. Please inspect git status and retry maker_clone_to_current_directory."
|
|
26987
|
+
].join("\n")
|
|
26988
|
+
);
|
|
26989
|
+
}
|
|
26990
|
+
function enhanceCheckoutConflictError(error2, target) {
|
|
26991
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
26992
|
+
if (!/untracked working tree files would be overwritten by checkout/i.test(message)) {
|
|
26993
|
+
return error2 instanceof Error ? error2 : new Error(message);
|
|
26994
|
+
}
|
|
26995
|
+
return new Error(
|
|
26996
|
+
[
|
|
26997
|
+
"Maker clone could not check out project files because existing local files would be overwritten.",
|
|
26998
|
+
`target_dir: ${target}`,
|
|
26999
|
+
"Please move, rename, or delete the conflicting local files, then retry maker_clone_to_current_directory.",
|
|
27000
|
+
"",
|
|
27001
|
+
message
|
|
27002
|
+
].join("\n")
|
|
27003
|
+
);
|
|
27004
|
+
}
|
|
26639
27005
|
async function currentBranch(cwd, explicitBranch) {
|
|
26640
27006
|
if (explicitBranch) {
|
|
26641
27007
|
return explicitBranch;
|
|
@@ -26643,6 +27009,20 @@ async function currentBranch(cwd, explicitBranch) {
|
|
|
26643
27009
|
const branch = await readGit(["branch", "--show-current"], cwd);
|
|
26644
27010
|
return branch.trim() || "main";
|
|
26645
27011
|
}
|
|
27012
|
+
async function resolveRemoteDefaultBranch(cwd) {
|
|
27013
|
+
try {
|
|
27014
|
+
const branch = await readGit(["symbolic-ref", "--short", "refs/remotes/origin/HEAD"], cwd);
|
|
27015
|
+
return branch.trim().replace(/^origin\//, "") || "main";
|
|
27016
|
+
} catch {
|
|
27017
|
+
}
|
|
27018
|
+
try {
|
|
27019
|
+
const remoteHead = await readGit(["ls-remote", "--symref", "origin", "HEAD"], cwd);
|
|
27020
|
+
const match = remoteHead.match(/^ref:\s+refs\/heads\/([^\s]+)\s+HEAD/m);
|
|
27021
|
+
return (match == null ? void 0 : match[1]) || "main";
|
|
27022
|
+
} catch {
|
|
27023
|
+
return "main";
|
|
27024
|
+
}
|
|
27025
|
+
}
|
|
26646
27026
|
function readGitSync(args) {
|
|
26647
27027
|
const gitCommand = getGitCommand();
|
|
26648
27028
|
const result = spawnSync3(gitCommand, args, {
|
|
@@ -26725,6 +27105,7 @@ function runGitCapture(args, options = {}) {
|
|
|
26725
27105
|
});
|
|
26726
27106
|
child.stderr.on("data", (chunk) => {
|
|
26727
27107
|
stderr += String(chunk);
|
|
27108
|
+
emitGitProgress(chunk, options.onProgress, options.sanitize);
|
|
26728
27109
|
});
|
|
26729
27110
|
child.on("exit", (code) => {
|
|
26730
27111
|
if (code === 0) {
|
|
@@ -26757,6 +27138,7 @@ function runGit(args, options) {
|
|
|
26757
27138
|
});
|
|
26758
27139
|
child.stderr.on("data", (chunk) => {
|
|
26759
27140
|
stderr += String(chunk);
|
|
27141
|
+
emitGitProgress(chunk, options.onProgress);
|
|
26760
27142
|
});
|
|
26761
27143
|
child.on("exit", (code) => {
|
|
26762
27144
|
if (code === 0) {
|
|
@@ -26796,6 +27178,42 @@ function sanitize(value, secret) {
|
|
|
26796
27178
|
}
|
|
26797
27179
|
return value.split(secret).join("***");
|
|
26798
27180
|
}
|
|
27181
|
+
function emitGitProgress(chunk, onProgress, secret) {
|
|
27182
|
+
if (!onProgress) {
|
|
27183
|
+
return;
|
|
27184
|
+
}
|
|
27185
|
+
for (const rawLine of String(chunk).split(/\r\n|\n|\r/)) {
|
|
27186
|
+
const line = sanitize(rawLine.trim(), secret);
|
|
27187
|
+
const progress = parseGitProgressLine(line);
|
|
27188
|
+
if (progress) {
|
|
27189
|
+
onProgress(progress);
|
|
27190
|
+
}
|
|
27191
|
+
}
|
|
27192
|
+
}
|
|
27193
|
+
function parseGitProgressLine(line) {
|
|
27194
|
+
const message = line.trim();
|
|
27195
|
+
if (!message) {
|
|
27196
|
+
return void 0;
|
|
27197
|
+
}
|
|
27198
|
+
const percentMatch = message.match(
|
|
27199
|
+
/(?:remote:\s*)?(Counting objects|Compressing objects|Receiving objects|Resolving deltas|Writing objects):\s+(\d+)%/i
|
|
27200
|
+
);
|
|
27201
|
+
if (percentMatch) {
|
|
27202
|
+
return {
|
|
27203
|
+
progress: Math.max(0, Math.min(100, Number(percentMatch[2]))),
|
|
27204
|
+
total: 100,
|
|
27205
|
+
phase: "git",
|
|
27206
|
+
message
|
|
27207
|
+
};
|
|
27208
|
+
}
|
|
27209
|
+
if (/^(remote:\s*)?(Cloning into|Enumerating objects|Total )/i.test(message)) {
|
|
27210
|
+
return {
|
|
27211
|
+
phase: "git",
|
|
27212
|
+
message
|
|
27213
|
+
};
|
|
27214
|
+
}
|
|
27215
|
+
return void 0;
|
|
27216
|
+
}
|
|
26799
27217
|
|
|
26800
27218
|
// src/maker/cli/init.ts
|
|
26801
27219
|
async function runInit(flags) {
|
|
@@ -27000,6 +27418,7 @@ async function runStatus(flags) {
|
|
|
27000
27418
|
// src/maker/server/mcp.ts
|
|
27001
27419
|
import fs6 from "node:fs";
|
|
27002
27420
|
import path9 from "node:path";
|
|
27421
|
+
import { fileURLToPath } from "node:url";
|
|
27003
27422
|
|
|
27004
27423
|
// node_modules/zod/v3/helpers/util.js
|
|
27005
27424
|
var util;
|
|
@@ -41962,10 +42381,11 @@ function isElectron() {
|
|
|
41962
42381
|
}
|
|
41963
42382
|
|
|
41964
42383
|
// src/maker/server/mcp.ts
|
|
41965
|
-
var VERSION = true ? "1.22.0-beta.
|
|
42384
|
+
var VERSION = true ? "1.22.0-beta.6" : "dev";
|
|
41966
42385
|
var DEFAULT_PROXY_MCP_NAME = "taptap-proxy";
|
|
41967
42386
|
var DEFAULT_PROXY_PACKAGE = "@taptap/instant-games-open-mcp@1.22.0";
|
|
41968
42387
|
var DEFAULT_BUILD_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
42388
|
+
var LONG_OPERATION_HEARTBEAT_MS = 3 * 60 * 1e3;
|
|
41969
42389
|
var MAKER_WEB_URL = getMakerWebUrl();
|
|
41970
42390
|
var tools = [
|
|
41971
42391
|
{
|
|
@@ -42063,7 +42483,7 @@ var tools = [
|
|
|
42063
42483
|
},
|
|
42064
42484
|
{
|
|
42065
42485
|
name: "maker_clone_to_current_directory",
|
|
42066
|
-
description: 'Clone a Maker app repository into the current Codex/agent working directory. Use after the user chooses an app from the Maker app list for requests like "拉取maker游戏到本地", "把这个maker app拉下来", "clone maker项目", or "下载maker游戏代码". Call this only after maker_list_apps has listed apps and the user has chosen one. Requires local Git. If Git is missing, this tool stops before changing files and returns install guidance; do not retry clone until the user installs Git and git --version works. Requires the selected app_id; uses cached Maker PAT by default.',
|
|
42486
|
+
description: 'Clone a Maker app repository into the current Codex/agent working directory. Use after the user chooses an app from the Maker app list for requests like "拉取maker游戏到本地", "把这个maker app拉下来", "clone maker项目", or "下载maker游戏代码". Call this only after maker_list_apps has listed apps and the user has chosen one. Requires local Git. If Git is missing, this tool stops before changing files and returns install guidance; do not retry clone until the user installs Git and git --version works. The target directory does not have to be empty; before clone, the tool checks local entries and warns about non-config local files while ignoring dot-prefixed config entries such as .claude, .mcp, .skill, .config, and .ini. Existing local files are kept unless they conflict with Maker project files; conflicts fail with a file list. Requires the selected app_id; uses cached Maker PAT by default.',
|
|
42067
42487
|
inputSchema: {
|
|
42068
42488
|
type: "object",
|
|
42069
42489
|
properties: {
|
|
@@ -42184,7 +42604,7 @@ var tools = [
|
|
|
42184
42604
|
},
|
|
42185
42605
|
use_npx: {
|
|
42186
42606
|
type: "boolean",
|
|
42187
|
-
description: "If true, write the script-style npx package command. Defaults to false
|
|
42607
|
+
description: "If true, write the script-style npx package command. Defaults to false and uses the proxy.js bundled with the Maker MCP package when available."
|
|
42188
42608
|
},
|
|
42189
42609
|
pkg: {
|
|
42190
42610
|
type: "string",
|
|
@@ -42253,7 +42673,8 @@ async function startMakerMcpServer() {
|
|
|
42253
42673
|
}
|
|
42254
42674
|
);
|
|
42255
42675
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));
|
|
42256
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
42676
|
+
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
42677
|
+
var _a2, _b, _c;
|
|
42257
42678
|
const name = request.params.name;
|
|
42258
42679
|
try {
|
|
42259
42680
|
if (name === "maker_status") {
|
|
@@ -42442,15 +42863,29 @@ async function startMakerMcpServer() {
|
|
|
42442
42863
|
throw new McpError(ErrorCode.InvalidParams, "app_id is required");
|
|
42443
42864
|
}
|
|
42444
42865
|
const targetDir = args.target_dir || process.cwd();
|
|
42445
|
-
const
|
|
42446
|
-
|
|
42447
|
-
|
|
42448
|
-
|
|
42449
|
-
|
|
42450
|
-
|
|
42451
|
-
|
|
42452
|
-
|
|
42453
|
-
|
|
42866
|
+
const progressReporter = createToolProgressReporter(
|
|
42867
|
+
(_a2 = request.params._meta) == null ? void 0 : _a2.progressToken,
|
|
42868
|
+
extra,
|
|
42869
|
+
"Maker clone"
|
|
42870
|
+
);
|
|
42871
|
+
let result;
|
|
42872
|
+
let progressSummary;
|
|
42873
|
+
try {
|
|
42874
|
+
result = await cloneMakerProject({
|
|
42875
|
+
appId: args.app_id,
|
|
42876
|
+
targetDir,
|
|
42877
|
+
pat: args.pat,
|
|
42878
|
+
userId: args.user_id,
|
|
42879
|
+
jwt: args.jwt,
|
|
42880
|
+
forcePat: args.force_pat === true,
|
|
42881
|
+
sceEndpoint: process.env.SCE_MCP_URL,
|
|
42882
|
+
onProgress: progressReporter.report
|
|
42883
|
+
});
|
|
42884
|
+
progressSummary = progressReporter.finish();
|
|
42885
|
+
} catch (error2) {
|
|
42886
|
+
progressReporter.finish();
|
|
42887
|
+
throw error2;
|
|
42888
|
+
}
|
|
42454
42889
|
return {
|
|
42455
42890
|
content: [
|
|
42456
42891
|
{
|
|
@@ -42458,10 +42893,12 @@ async function startMakerMcpServer() {
|
|
|
42458
42893
|
text: [
|
|
42459
42894
|
"✓ Maker project cloned",
|
|
42460
42895
|
"",
|
|
42896
|
+
...formatCloneWarnings(result.warnings),
|
|
42461
42897
|
`- app_id: ${args.app_id}`,
|
|
42462
42898
|
`- target_dir: ${result.targetDir}`,
|
|
42463
42899
|
`- status: ${result.status}`,
|
|
42464
42900
|
`- retried_with_new_pat: ${result.retriedWithNewPat ? "yes" : "no"}`,
|
|
42901
|
+
...formatProgressSummary(progressSummary),
|
|
42465
42902
|
"- project config: .maker-mcp/config.json"
|
|
42466
42903
|
].join("\n")
|
|
42467
42904
|
}
|
|
@@ -42471,21 +42908,35 @@ async function startMakerMcpServer() {
|
|
|
42471
42908
|
if (name === "maker_push_current_directory" || name === "maker_submit_current_directory") {
|
|
42472
42909
|
const args = request.params.arguments || {};
|
|
42473
42910
|
const targetDir = args.target_dir || process.cwd();
|
|
42474
|
-
const
|
|
42475
|
-
|
|
42476
|
-
|
|
42477
|
-
|
|
42478
|
-
|
|
42479
|
-
|
|
42480
|
-
|
|
42481
|
-
|
|
42482
|
-
|
|
42483
|
-
|
|
42911
|
+
const progressReporter = createToolProgressReporter(
|
|
42912
|
+
(_b = request.params._meta) == null ? void 0 : _b.progressToken,
|
|
42913
|
+
extra,
|
|
42914
|
+
"Maker push"
|
|
42915
|
+
);
|
|
42916
|
+
let result;
|
|
42917
|
+
let progressSummary;
|
|
42918
|
+
try {
|
|
42919
|
+
result = await pushMakerProject({
|
|
42920
|
+
cwd: targetDir,
|
|
42921
|
+
message: args.message,
|
|
42922
|
+
branch: args.branch,
|
|
42923
|
+
files: args.files,
|
|
42924
|
+
allowEmpty: args.allow_empty === true,
|
|
42925
|
+
pat: args.pat,
|
|
42926
|
+
jwt: args.jwt,
|
|
42927
|
+
forcePat: args.force_pat === true,
|
|
42928
|
+
onProgress: progressReporter.report
|
|
42929
|
+
});
|
|
42930
|
+
progressSummary = progressReporter.finish();
|
|
42931
|
+
} catch (error2) {
|
|
42932
|
+
progressReporter.finish();
|
|
42933
|
+
throw error2;
|
|
42934
|
+
}
|
|
42484
42935
|
return {
|
|
42485
42936
|
content: [
|
|
42486
42937
|
{
|
|
42487
42938
|
type: "text",
|
|
42488
|
-
text: formatPushResult(targetDir, result)
|
|
42939
|
+
text: formatPushResult(targetDir, result, progressSummary)
|
|
42489
42940
|
}
|
|
42490
42941
|
]
|
|
42491
42942
|
};
|
|
@@ -42511,22 +42962,36 @@ async function startMakerMcpServer() {
|
|
|
42511
42962
|
}
|
|
42512
42963
|
if (name === "maker_build_current_directory") {
|
|
42513
42964
|
const args = request.params.arguments || {};
|
|
42514
|
-
const
|
|
42515
|
-
|
|
42516
|
-
|
|
42517
|
-
|
|
42518
|
-
|
|
42519
|
-
|
|
42520
|
-
|
|
42521
|
-
|
|
42522
|
-
|
|
42523
|
-
|
|
42524
|
-
|
|
42965
|
+
const progressReporter = createToolProgressReporter(
|
|
42966
|
+
(_c = request.params._meta) == null ? void 0 : _c.progressToken,
|
|
42967
|
+
extra,
|
|
42968
|
+
"Maker build"
|
|
42969
|
+
);
|
|
42970
|
+
let result;
|
|
42971
|
+
let progressSummary;
|
|
42972
|
+
try {
|
|
42973
|
+
result = await buildCurrentDirectory({
|
|
42974
|
+
targetDir: args.target_dir || process.cwd(),
|
|
42975
|
+
entry: args.entry,
|
|
42976
|
+
scriptsPath: args.scriptsPath,
|
|
42977
|
+
entryClient: args.entry_client,
|
|
42978
|
+
entryServer: args.entry_server,
|
|
42979
|
+
multiplayer: args.multiplayer,
|
|
42980
|
+
serverUrl: args.server_url,
|
|
42981
|
+
env: args.env,
|
|
42982
|
+
timeoutMs: args.timeout_ms,
|
|
42983
|
+
onProgress: progressReporter.report
|
|
42984
|
+
});
|
|
42985
|
+
progressSummary = progressReporter.finish();
|
|
42986
|
+
} catch (error2) {
|
|
42987
|
+
progressReporter.finish();
|
|
42988
|
+
throw error2;
|
|
42989
|
+
}
|
|
42525
42990
|
return {
|
|
42526
42991
|
content: [
|
|
42527
42992
|
{
|
|
42528
42993
|
type: "text",
|
|
42529
|
-
text: formatBuildResult(result)
|
|
42994
|
+
text: formatBuildResult(result, progressSummary)
|
|
42530
42995
|
}
|
|
42531
42996
|
]
|
|
42532
42997
|
};
|
|
@@ -42651,12 +43116,32 @@ function formatProjectList(projects) {
|
|
|
42651
43116
|
"Maker apps",
|
|
42652
43117
|
"",
|
|
42653
43118
|
...projects.map(
|
|
42654
|
-
(project, index) => `${index + 1}. ${project.id}${project.name ? ` ${project.name}` : ""}${project.user_id ? ` user_id=${project.user_id}` : ""}`
|
|
43119
|
+
(project, index) => `${index + 1}. ${project.id}${project.name ? ` ${project.name}` : ""}${project.user_id ? ` user_id=${project.user_id}` : ""}${project.gameType ? ` gameType=${project.gameType}` : ""}${project.stage ? ` stage=${project.stage}` : ""}${project.createdAt ? ` createdAt=${project.createdAt}` : ""}${project.lastConversationAt ? ` lastConversationAt=${project.lastConversationAt}` : ""}`
|
|
42655
43120
|
),
|
|
42656
43121
|
"",
|
|
42657
43122
|
"请让用户选择一个 app,然后调用 maker_clone_to_current_directory。"
|
|
42658
43123
|
].join("\n");
|
|
42659
43124
|
}
|
|
43125
|
+
function formatCloneWarnings(warnings) {
|
|
43126
|
+
if (warnings.length === 0) {
|
|
43127
|
+
return [
|
|
43128
|
+
"Pre-clone local directory check",
|
|
43129
|
+
"",
|
|
43130
|
+
"- result: checked",
|
|
43131
|
+
"- local_files: none found before clone, ignoring dot-prefixed local config entries",
|
|
43132
|
+
""
|
|
43133
|
+
];
|
|
43134
|
+
}
|
|
43135
|
+
return [
|
|
43136
|
+
"Pre-clone local directory check",
|
|
43137
|
+
"",
|
|
43138
|
+
"- result: found local files before clone",
|
|
43139
|
+
"- action: kept local files and continued unless they conflicted with Maker project files",
|
|
43140
|
+
"",
|
|
43141
|
+
...warnings.map((warning) => `- ${warning}`),
|
|
43142
|
+
""
|
|
43143
|
+
];
|
|
43144
|
+
}
|
|
42660
43145
|
function createRemoteProxyContext(options) {
|
|
42661
43146
|
const identify = identifyMakerProject({ cwd: options.targetDir });
|
|
42662
43147
|
if (!identify.projectRoot || !identify.projectId) {
|
|
@@ -42752,19 +43237,23 @@ function configureRemoteProxy(options) {
|
|
|
42752
43237
|
envVars: proxy.envVars
|
|
42753
43238
|
};
|
|
42754
43239
|
}
|
|
42755
|
-
function resolveLocalProxyBundle() {
|
|
42756
|
-
const
|
|
42757
|
-
const
|
|
42758
|
-
|
|
42759
|
-
|
|
42760
|
-
|
|
42761
|
-
const
|
|
42762
|
-
|
|
42763
|
-
|
|
43240
|
+
function resolveLocalProxyBundle(options) {
|
|
43241
|
+
const currentModuleUrl = (options == null ? void 0 : options.currentModuleUrl) || (typeof __MAKER_BUNDLE_URL__ !== "undefined" ? __MAKER_BUNDLE_URL__ : void 0);
|
|
43242
|
+
const currentModuleDir = currentModuleUrl ? path9.dirname(fileURLToPath(currentModuleUrl)) : "";
|
|
43243
|
+
const makerEntry = (options == null ? void 0 : options.makerEntry) ?? process.argv[1];
|
|
43244
|
+
const makerEntryDir = makerEntry ? path9.dirname(path9.resolve(makerEntry)) : "";
|
|
43245
|
+
const cwd = (options == null ? void 0 : options.cwd) ?? process.cwd();
|
|
43246
|
+
const candidates = [
|
|
43247
|
+
currentModuleDir ? path9.join(currentModuleDir, "proxy.js") : "",
|
|
43248
|
+
makerEntryDir ? path9.join(makerEntryDir, "..", "dist", "proxy.js") : "",
|
|
43249
|
+
path9.resolve(cwd, "dist", "proxy.js")
|
|
43250
|
+
].filter(Boolean);
|
|
43251
|
+
for (const candidate of candidates) {
|
|
43252
|
+
if (fs6.existsSync(candidate)) {
|
|
43253
|
+
return candidate;
|
|
43254
|
+
}
|
|
42764
43255
|
}
|
|
42765
|
-
throw new Error(
|
|
42766
|
-
"Local dist/proxy.js not found. Run npm run build before configuring remote proxy."
|
|
42767
|
-
);
|
|
43256
|
+
throw new Error(`MCP proxy bundle not found. Checked: ${candidates.join(", ")}`);
|
|
42768
43257
|
}
|
|
42769
43258
|
function readMcpJson(filePath) {
|
|
42770
43259
|
if (!fs6.existsSync(filePath)) {
|
|
@@ -42830,6 +43319,84 @@ function formatProxyEnv(envVars) {
|
|
|
42830
43319
|
}
|
|
42831
43320
|
return Object.keys(envVars).map((key) => `${key}=<redacted>`).join(" ");
|
|
42832
43321
|
}
|
|
43322
|
+
function createToolProgressReporter(progressToken, extra, operationName) {
|
|
43323
|
+
var _a2;
|
|
43324
|
+
const startedAt = Date.now();
|
|
43325
|
+
let events = 0;
|
|
43326
|
+
let lastProgress;
|
|
43327
|
+
let lastSentProgress = 0;
|
|
43328
|
+
let finished = false;
|
|
43329
|
+
const sendProgress = (progress) => {
|
|
43330
|
+
if (finished || progressToken === void 0) {
|
|
43331
|
+
return;
|
|
43332
|
+
}
|
|
43333
|
+
const elapsed = formatDuration(Date.now() - startedAt);
|
|
43334
|
+
const numericProgress = progress.progress !== void 0 ? Math.max(lastSentProgress, progress.progress) : Math.max(lastSentProgress, Math.floor((Date.now() - startedAt) / 1e3));
|
|
43335
|
+
lastSentProgress = numericProgress;
|
|
43336
|
+
const message = `${operationName}: ${progress.message} (elapsed ${elapsed})`;
|
|
43337
|
+
void extra.sendNotification({
|
|
43338
|
+
method: "notifications/progress",
|
|
43339
|
+
params: {
|
|
43340
|
+
progressToken,
|
|
43341
|
+
progress: numericProgress,
|
|
43342
|
+
...progress.total !== void 0 ? { total: progress.total } : {},
|
|
43343
|
+
message
|
|
43344
|
+
}
|
|
43345
|
+
}).catch(() => {
|
|
43346
|
+
});
|
|
43347
|
+
};
|
|
43348
|
+
const heartbeat = setInterval(() => {
|
|
43349
|
+
const elapsed = formatDuration(Date.now() - startedAt);
|
|
43350
|
+
sendProgress({
|
|
43351
|
+
progress: lastProgress == null ? void 0 : lastProgress.progress,
|
|
43352
|
+
total: lastProgress == null ? void 0 : lastProgress.total,
|
|
43353
|
+
phase: lastProgress == null ? void 0 : lastProgress.phase,
|
|
43354
|
+
message: `still running; elapsed ${elapsed}; last status: ${(lastProgress == null ? void 0 : lastProgress.message) || "waiting for progress"}`
|
|
43355
|
+
});
|
|
43356
|
+
}, LONG_OPERATION_HEARTBEAT_MS);
|
|
43357
|
+
(_a2 = heartbeat.unref) == null ? void 0 : _a2.call(heartbeat);
|
|
43358
|
+
return {
|
|
43359
|
+
report(progress) {
|
|
43360
|
+
events += 1;
|
|
43361
|
+
lastProgress = progress;
|
|
43362
|
+
sendProgress(progress);
|
|
43363
|
+
},
|
|
43364
|
+
finish() {
|
|
43365
|
+
if (!finished) {
|
|
43366
|
+
finished = true;
|
|
43367
|
+
clearInterval(heartbeat);
|
|
43368
|
+
}
|
|
43369
|
+
const elapsedMs = Date.now() - startedAt;
|
|
43370
|
+
return {
|
|
43371
|
+
elapsedMs,
|
|
43372
|
+
elapsed: formatDuration(elapsedMs),
|
|
43373
|
+
progressEvents: events,
|
|
43374
|
+
lastProgress
|
|
43375
|
+
};
|
|
43376
|
+
}
|
|
43377
|
+
};
|
|
43378
|
+
}
|
|
43379
|
+
function formatProgressSummary(summary) {
|
|
43380
|
+
return [
|
|
43381
|
+
`- elapsed_ms: ${summary.elapsedMs}`,
|
|
43382
|
+
`- elapsed: ${summary.elapsed}`,
|
|
43383
|
+
`- progress_events: ${summary.progressEvents}`,
|
|
43384
|
+
summary.lastProgress ? `- last_progress: ${formatProgressMessage(summary.lastProgress)}` : "- last_progress: (none)"
|
|
43385
|
+
];
|
|
43386
|
+
}
|
|
43387
|
+
function formatProgressMessage(progress) {
|
|
43388
|
+
const percent = progress.progress !== void 0 ? `${progress.progress}${progress.total === 100 ? "%" : ""}` : void 0;
|
|
43389
|
+
return [progress.phase ? `[${progress.phase}]` : "", percent, progress.message].filter(Boolean).join(" ");
|
|
43390
|
+
}
|
|
43391
|
+
function formatDuration(ms) {
|
|
43392
|
+
const totalSeconds = Math.max(0, Math.round(ms / 1e3));
|
|
43393
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
43394
|
+
const seconds = totalSeconds % 60;
|
|
43395
|
+
if (minutes === 0) {
|
|
43396
|
+
return `${seconds}s`;
|
|
43397
|
+
}
|
|
43398
|
+
return `${minutes}m ${seconds}s`;
|
|
43399
|
+
}
|
|
42833
43400
|
async function buildCurrentDirectory(options) {
|
|
42834
43401
|
const proxy = createRemoteProxyContext({
|
|
42835
43402
|
targetDir: options.targetDir,
|
|
@@ -42841,10 +43408,7 @@ async function buildCurrentDirectory(options) {
|
|
|
42841
43408
|
const transport = new StdioClientTransport({
|
|
42842
43409
|
command: proxy.command,
|
|
42843
43410
|
args: proxy.args,
|
|
42844
|
-
env:
|
|
42845
|
-
...process.env,
|
|
42846
|
-
...proxy.envVars
|
|
42847
|
-
},
|
|
43411
|
+
env: mergeStringEnv(process.env, proxy.envVars),
|
|
42848
43412
|
stderr: "pipe"
|
|
42849
43413
|
});
|
|
42850
43414
|
const client = new Client(
|
|
@@ -42866,7 +43430,16 @@ async function buildCurrentDirectory(options) {
|
|
|
42866
43430
|
void 0,
|
|
42867
43431
|
{
|
|
42868
43432
|
timeout: timeoutMs,
|
|
42869
|
-
resetTimeoutOnProgress: true
|
|
43433
|
+
resetTimeoutOnProgress: true,
|
|
43434
|
+
onprogress: (progress) => {
|
|
43435
|
+
var _a2;
|
|
43436
|
+
(_a2 = options.onProgress) == null ? void 0 : _a2.call(options, {
|
|
43437
|
+
progress: progress.progress,
|
|
43438
|
+
total: progress.total,
|
|
43439
|
+
phase: "remote_build",
|
|
43440
|
+
message: progress.message || "Remote Maker build progress"
|
|
43441
|
+
});
|
|
43442
|
+
}
|
|
42870
43443
|
}
|
|
42871
43444
|
);
|
|
42872
43445
|
return {
|
|
@@ -42904,6 +43477,20 @@ function createBuildArgs(projectRoot, options) {
|
|
|
42904
43477
|
}
|
|
42905
43478
|
return buildArgs;
|
|
42906
43479
|
}
|
|
43480
|
+
function mergeStringEnv(...sources) {
|
|
43481
|
+
const result = {};
|
|
43482
|
+
for (const source of sources) {
|
|
43483
|
+
if (!source) {
|
|
43484
|
+
continue;
|
|
43485
|
+
}
|
|
43486
|
+
for (const [key, value] of Object.entries(source)) {
|
|
43487
|
+
if (typeof value === "string") {
|
|
43488
|
+
result[key] = value;
|
|
43489
|
+
}
|
|
43490
|
+
}
|
|
43491
|
+
}
|
|
43492
|
+
return result;
|
|
43493
|
+
}
|
|
42907
43494
|
function formatRemoteToolResult(result) {
|
|
42908
43495
|
if (!result || typeof result !== "object") {
|
|
42909
43496
|
return String(result);
|
|
@@ -42919,7 +43506,7 @@ function formatRemoteToolResult(result) {
|
|
|
42919
43506
|
return JSON.stringify(item);
|
|
42920
43507
|
}).join("\n");
|
|
42921
43508
|
}
|
|
42922
|
-
function formatBuildResult(result) {
|
|
43509
|
+
function formatBuildResult(result, progressSummary) {
|
|
42923
43510
|
return [
|
|
42924
43511
|
"✓ Remote Maker build finished",
|
|
42925
43512
|
"",
|
|
@@ -42930,12 +43517,13 @@ function formatBuildResult(result) {
|
|
|
42930
43517
|
`- env: ${result.env}`,
|
|
42931
43518
|
`- timeout_ms: ${result.timeoutMs}`,
|
|
42932
43519
|
`- build_args: ${JSON.stringify(result.buildArgs)}`,
|
|
43520
|
+
...formatProgressSummary(progressSummary),
|
|
42933
43521
|
"",
|
|
42934
43522
|
"remote_result:",
|
|
42935
43523
|
indent(result.resultText)
|
|
42936
43524
|
].join("\n");
|
|
42937
43525
|
}
|
|
42938
|
-
function formatPushResult(targetDir, result) {
|
|
43526
|
+
function formatPushResult(targetDir, result, progressSummary) {
|
|
42939
43527
|
const lines = [
|
|
42940
43528
|
result.pushed ? "✓ Maker project pushed" : result.status === "clean" ? "Maker project has no changes to push" : "✗ Maker project push failed",
|
|
42941
43529
|
"",
|
|
@@ -42945,7 +43533,8 @@ function formatPushResult(targetDir, result) {
|
|
|
42945
43533
|
`- committed: ${result.committed ? "yes" : "no"}`,
|
|
42946
43534
|
result.commitHash ? `- commit_hash: ${result.commitHash}` : "",
|
|
42947
43535
|
result.message ? `- commit_message: ${result.message}` : "",
|
|
42948
|
-
result.ahead ? `- git_state: ${result.ahead}` : ""
|
|
43536
|
+
result.ahead ? `- git_state: ${result.ahead}` : "",
|
|
43537
|
+
...formatProgressSummary(progressSummary)
|
|
42949
43538
|
].filter(Boolean);
|
|
42950
43539
|
if (!result.failure) {
|
|
42951
43540
|
return lines.join("\n");
|
package/dist/proxy.js
CHANGED
|
@@ -29137,7 +29137,7 @@ var LogWriter = class {
|
|
|
29137
29137
|
};
|
|
29138
29138
|
|
|
29139
29139
|
// src/mcp-proxy/proxy.ts
|
|
29140
|
-
var VERSION = true ? "1.22.0-beta.
|
|
29140
|
+
var VERSION = true ? "1.22.0-beta.6" : "dev";
|
|
29141
29141
|
var TapTapMCPProxy = class {
|
|
29142
29142
|
constructor(config2) {
|
|
29143
29143
|
this.connected = false;
|
package/dist/server.js
CHANGED
|
@@ -6078,7 +6078,7 @@ class MultiplayerManager {
|
|
|
6078
6078
|
// 导出
|
|
6079
6079
|
// export default MultiplayerManager;
|
|
6080
6080
|
// module.exports = MultiplayerManager;
|
|
6081
|
-
// window.MultiplayerManager = MultiplayerManager;`}]}}};var ws;ws="1.22.0-beta.
|
|
6081
|
+
// window.MultiplayerManager = MultiplayerManager;`}]}}};var ws;ws="1.22.0-beta.6";async function MRe(){return Go(Rm,"api_event_relations")}async function NRe(){return Go(Rm,"protocol_template")}async function SD(){return Go(Rm,"complete_example")}async function jRe(){return`# TapTap 多人联机集成指南
|
|
6082
6082
|
|
|
6083
6083
|
---
|
|
6084
6084
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taptap/instant-games-open-mcp",
|
|
3
|
-
"version": "1.22.0-beta.
|
|
3
|
+
"version": "1.22.0-beta.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "TapTap Open API MCP Server - Documentation and Management APIs for TapTap Minigame and H5 Games (Leaderboard, and more features coming)",
|
|
6
6
|
"main": "dist/server.js",
|