@taptap/instant-games-open-mcp 1.23.6 → 1.23.7-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -2
- package/dist/maker.js +1653 -182
- package/dist/proxy.js +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
- package/skills/taptap-maker-local/SKILL.md +53 -19
package/dist/maker.js
CHANGED
|
@@ -3233,8 +3233,8 @@ var require_utils = __commonJS({
|
|
|
3233
3233
|
}
|
|
3234
3234
|
return ind;
|
|
3235
3235
|
}
|
|
3236
|
-
function removeDotSegments(
|
|
3237
|
-
let input2 =
|
|
3236
|
+
function removeDotSegments(path11) {
|
|
3237
|
+
let input2 = path11;
|
|
3238
3238
|
const output2 = [];
|
|
3239
3239
|
let nextSlash = -1;
|
|
3240
3240
|
let len = 0;
|
|
@@ -3433,8 +3433,8 @@ var require_schemes = __commonJS({
|
|
|
3433
3433
|
wsComponent.secure = void 0;
|
|
3434
3434
|
}
|
|
3435
3435
|
if (wsComponent.resourceName) {
|
|
3436
|
-
const [
|
|
3437
|
-
wsComponent.path =
|
|
3436
|
+
const [path11, query] = wsComponent.resourceName.split("?");
|
|
3437
|
+
wsComponent.path = path11 && path11 !== "/" ? path11 : void 0;
|
|
3438
3438
|
wsComponent.query = query;
|
|
3439
3439
|
wsComponent.resourceName = void 0;
|
|
3440
3440
|
}
|
|
@@ -12491,12 +12491,12 @@ var require_dist = __commonJS({
|
|
|
12491
12491
|
throw new Error(`Unknown format "${name}"`);
|
|
12492
12492
|
return f;
|
|
12493
12493
|
};
|
|
12494
|
-
function addFormats(ajv, list,
|
|
12494
|
+
function addFormats(ajv, list, fs10, exportName) {
|
|
12495
12495
|
var _a2;
|
|
12496
12496
|
var _b;
|
|
12497
12497
|
(_a2 = (_b = ajv.opts.code).formats) !== null && _a2 !== void 0 ? _a2 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
12498
12498
|
for (const f of list)
|
|
12499
|
-
ajv.addFormat(f,
|
|
12499
|
+
ajv.addFormat(f, fs10[f]);
|
|
12500
12500
|
}
|
|
12501
12501
|
module.exports = exports = formatsPlugin;
|
|
12502
12502
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -12509,8 +12509,8 @@ var require_windows = __commonJS({
|
|
|
12509
12509
|
"node_modules/isexe/windows.js"(exports, module) {
|
|
12510
12510
|
module.exports = isexe;
|
|
12511
12511
|
isexe.sync = sync;
|
|
12512
|
-
var
|
|
12513
|
-
function checkPathExt(
|
|
12512
|
+
var fs10 = __require("fs");
|
|
12513
|
+
function checkPathExt(path11, options) {
|
|
12514
12514
|
var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
|
|
12515
12515
|
if (!pathext) {
|
|
12516
12516
|
return true;
|
|
@@ -12521,25 +12521,25 @@ var require_windows = __commonJS({
|
|
|
12521
12521
|
}
|
|
12522
12522
|
for (var i = 0; i < pathext.length; i++) {
|
|
12523
12523
|
var p = pathext[i].toLowerCase();
|
|
12524
|
-
if (p &&
|
|
12524
|
+
if (p && path11.substr(-p.length).toLowerCase() === p) {
|
|
12525
12525
|
return true;
|
|
12526
12526
|
}
|
|
12527
12527
|
}
|
|
12528
12528
|
return false;
|
|
12529
12529
|
}
|
|
12530
|
-
function checkStat(stat,
|
|
12530
|
+
function checkStat(stat, path11, options) {
|
|
12531
12531
|
if (!stat.isSymbolicLink() && !stat.isFile()) {
|
|
12532
12532
|
return false;
|
|
12533
12533
|
}
|
|
12534
|
-
return checkPathExt(
|
|
12534
|
+
return checkPathExt(path11, options);
|
|
12535
12535
|
}
|
|
12536
|
-
function isexe(
|
|
12537
|
-
|
|
12538
|
-
cb(er, er ? false : checkStat(stat,
|
|
12536
|
+
function isexe(path11, options, cb) {
|
|
12537
|
+
fs10.stat(path11, function(er, stat) {
|
|
12538
|
+
cb(er, er ? false : checkStat(stat, path11, options));
|
|
12539
12539
|
});
|
|
12540
12540
|
}
|
|
12541
|
-
function sync(
|
|
12542
|
-
return checkStat(
|
|
12541
|
+
function sync(path11, options) {
|
|
12542
|
+
return checkStat(fs10.statSync(path11), path11, options);
|
|
12543
12543
|
}
|
|
12544
12544
|
}
|
|
12545
12545
|
});
|
|
@@ -12549,14 +12549,14 @@ var require_mode = __commonJS({
|
|
|
12549
12549
|
"node_modules/isexe/mode.js"(exports, module) {
|
|
12550
12550
|
module.exports = isexe;
|
|
12551
12551
|
isexe.sync = sync;
|
|
12552
|
-
var
|
|
12553
|
-
function isexe(
|
|
12554
|
-
|
|
12552
|
+
var fs10 = __require("fs");
|
|
12553
|
+
function isexe(path11, options, cb) {
|
|
12554
|
+
fs10.stat(path11, function(er, stat) {
|
|
12555
12555
|
cb(er, er ? false : checkStat(stat, options));
|
|
12556
12556
|
});
|
|
12557
12557
|
}
|
|
12558
|
-
function sync(
|
|
12559
|
-
return checkStat(
|
|
12558
|
+
function sync(path11, options) {
|
|
12559
|
+
return checkStat(fs10.statSync(path11), options);
|
|
12560
12560
|
}
|
|
12561
12561
|
function checkStat(stat, options) {
|
|
12562
12562
|
return stat.isFile() && checkMode(stat, options);
|
|
@@ -12580,7 +12580,7 @@ var require_mode = __commonJS({
|
|
|
12580
12580
|
// node_modules/isexe/index.js
|
|
12581
12581
|
var require_isexe = __commonJS({
|
|
12582
12582
|
"node_modules/isexe/index.js"(exports, module) {
|
|
12583
|
-
var
|
|
12583
|
+
var fs10 = __require("fs");
|
|
12584
12584
|
var core;
|
|
12585
12585
|
if (process.platform === "win32" || global.TESTING_WINDOWS) {
|
|
12586
12586
|
core = require_windows();
|
|
@@ -12589,7 +12589,7 @@ var require_isexe = __commonJS({
|
|
|
12589
12589
|
}
|
|
12590
12590
|
module.exports = isexe;
|
|
12591
12591
|
isexe.sync = sync;
|
|
12592
|
-
function isexe(
|
|
12592
|
+
function isexe(path11, options, cb) {
|
|
12593
12593
|
if (typeof options === "function") {
|
|
12594
12594
|
cb = options;
|
|
12595
12595
|
options = {};
|
|
@@ -12599,7 +12599,7 @@ var require_isexe = __commonJS({
|
|
|
12599
12599
|
throw new TypeError("callback not provided");
|
|
12600
12600
|
}
|
|
12601
12601
|
return new Promise(function(resolve, reject) {
|
|
12602
|
-
isexe(
|
|
12602
|
+
isexe(path11, options || {}, function(er, is) {
|
|
12603
12603
|
if (er) {
|
|
12604
12604
|
reject(er);
|
|
12605
12605
|
} else {
|
|
@@ -12608,7 +12608,7 @@ var require_isexe = __commonJS({
|
|
|
12608
12608
|
});
|
|
12609
12609
|
});
|
|
12610
12610
|
}
|
|
12611
|
-
core(
|
|
12611
|
+
core(path11, options || {}, function(er, is) {
|
|
12612
12612
|
if (er) {
|
|
12613
12613
|
if (er.code === "EACCES" || options && options.ignoreErrors) {
|
|
12614
12614
|
er = null;
|
|
@@ -12618,9 +12618,9 @@ var require_isexe = __commonJS({
|
|
|
12618
12618
|
cb(er, is);
|
|
12619
12619
|
});
|
|
12620
12620
|
}
|
|
12621
|
-
function sync(
|
|
12621
|
+
function sync(path11, options) {
|
|
12622
12622
|
try {
|
|
12623
|
-
return core.sync(
|
|
12623
|
+
return core.sync(path11, options || {});
|
|
12624
12624
|
} catch (er) {
|
|
12625
12625
|
if (options && options.ignoreErrors || er.code === "EACCES") {
|
|
12626
12626
|
return false;
|
|
@@ -12636,7 +12636,7 @@ var require_isexe = __commonJS({
|
|
|
12636
12636
|
var require_which = __commonJS({
|
|
12637
12637
|
"node_modules/which/which.js"(exports, module) {
|
|
12638
12638
|
var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
|
|
12639
|
-
var
|
|
12639
|
+
var path11 = __require("path");
|
|
12640
12640
|
var COLON = isWindows ? ";" : ":";
|
|
12641
12641
|
var isexe = require_isexe();
|
|
12642
12642
|
var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
|
|
@@ -12674,7 +12674,7 @@ var require_which = __commonJS({
|
|
|
12674
12674
|
return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd));
|
|
12675
12675
|
const ppRaw = pathEnv[i];
|
|
12676
12676
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
12677
|
-
const pCmd =
|
|
12677
|
+
const pCmd = path11.join(pathPart, cmd);
|
|
12678
12678
|
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
12679
12679
|
resolve(subStep(p, i, 0));
|
|
12680
12680
|
});
|
|
@@ -12701,7 +12701,7 @@ var require_which = __commonJS({
|
|
|
12701
12701
|
for (let i = 0; i < pathEnv.length; i++) {
|
|
12702
12702
|
const ppRaw = pathEnv[i];
|
|
12703
12703
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
12704
|
-
const pCmd =
|
|
12704
|
+
const pCmd = path11.join(pathPart, cmd);
|
|
12705
12705
|
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
12706
12706
|
for (let j = 0; j < pathExt.length; j++) {
|
|
12707
12707
|
const cur = p + pathExt[j];
|
|
@@ -12749,7 +12749,7 @@ var require_path_key = __commonJS({
|
|
|
12749
12749
|
var require_resolveCommand = __commonJS({
|
|
12750
12750
|
"node_modules/cross-spawn/lib/util/resolveCommand.js"(exports, module) {
|
|
12751
12751
|
"use strict";
|
|
12752
|
-
var
|
|
12752
|
+
var path11 = __require("path");
|
|
12753
12753
|
var which = require_which();
|
|
12754
12754
|
var getPathKey = require_path_key();
|
|
12755
12755
|
function resolveCommandAttempt(parsed, withoutPathExt) {
|
|
@@ -12767,7 +12767,7 @@ var require_resolveCommand = __commonJS({
|
|
|
12767
12767
|
try {
|
|
12768
12768
|
resolved = which.sync(parsed.command, {
|
|
12769
12769
|
path: env[getPathKey({ env })],
|
|
12770
|
-
pathExt: withoutPathExt ?
|
|
12770
|
+
pathExt: withoutPathExt ? path11.delimiter : void 0
|
|
12771
12771
|
});
|
|
12772
12772
|
} catch (e) {
|
|
12773
12773
|
} finally {
|
|
@@ -12776,7 +12776,7 @@ var require_resolveCommand = __commonJS({
|
|
|
12776
12776
|
}
|
|
12777
12777
|
}
|
|
12778
12778
|
if (resolved) {
|
|
12779
|
-
resolved =
|
|
12779
|
+
resolved = path11.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
|
|
12780
12780
|
}
|
|
12781
12781
|
return resolved;
|
|
12782
12782
|
}
|
|
@@ -12830,8 +12830,8 @@ var require_shebang_command = __commonJS({
|
|
|
12830
12830
|
if (!match) {
|
|
12831
12831
|
return null;
|
|
12832
12832
|
}
|
|
12833
|
-
const [
|
|
12834
|
-
const binary =
|
|
12833
|
+
const [path11, argument] = match[0].replace(/#! ?/, "").split(" ");
|
|
12834
|
+
const binary = path11.split("/").pop();
|
|
12835
12835
|
if (binary === "env") {
|
|
12836
12836
|
return argument;
|
|
12837
12837
|
}
|
|
@@ -12844,16 +12844,16 @@ var require_shebang_command = __commonJS({
|
|
|
12844
12844
|
var require_readShebang = __commonJS({
|
|
12845
12845
|
"node_modules/cross-spawn/lib/util/readShebang.js"(exports, module) {
|
|
12846
12846
|
"use strict";
|
|
12847
|
-
var
|
|
12847
|
+
var fs10 = __require("fs");
|
|
12848
12848
|
var shebangCommand = require_shebang_command();
|
|
12849
12849
|
function readShebang(command) {
|
|
12850
12850
|
const size = 150;
|
|
12851
12851
|
const buffer = Buffer.alloc(size);
|
|
12852
12852
|
let fd;
|
|
12853
12853
|
try {
|
|
12854
|
-
fd =
|
|
12855
|
-
|
|
12856
|
-
|
|
12854
|
+
fd = fs10.openSync(command, "r");
|
|
12855
|
+
fs10.readSync(fd, buffer, 0, size, 0);
|
|
12856
|
+
fs10.closeSync(fd);
|
|
12857
12857
|
} catch (e) {
|
|
12858
12858
|
}
|
|
12859
12859
|
return shebangCommand(buffer.toString());
|
|
@@ -12866,7 +12866,7 @@ var require_readShebang = __commonJS({
|
|
|
12866
12866
|
var require_parse = __commonJS({
|
|
12867
12867
|
"node_modules/cross-spawn/lib/parse.js"(exports, module) {
|
|
12868
12868
|
"use strict";
|
|
12869
|
-
var
|
|
12869
|
+
var path11 = __require("path");
|
|
12870
12870
|
var resolveCommand = require_resolveCommand();
|
|
12871
12871
|
var escape2 = require_escape();
|
|
12872
12872
|
var readShebang = require_readShebang();
|
|
@@ -12891,7 +12891,7 @@ var require_parse = __commonJS({
|
|
|
12891
12891
|
const needsShell = !isExecutableRegExp.test(commandFile);
|
|
12892
12892
|
if (parsed.options.forceShell || needsShell) {
|
|
12893
12893
|
const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
|
|
12894
|
-
parsed.command =
|
|
12894
|
+
parsed.command = path11.normalize(parsed.command);
|
|
12895
12895
|
parsed.command = escape2.command(parsed.command);
|
|
12896
12896
|
parsed.args = parsed.args.map((arg) => escape2.argument(arg, needsDoubleEscapeMetaChars));
|
|
12897
12897
|
const shellCommand = [parsed.command].concat(parsed.args).join(" ");
|
|
@@ -12981,7 +12981,7 @@ var require_cross_spawn = __commonJS({
|
|
|
12981
12981
|
var cp = __require("child_process");
|
|
12982
12982
|
var parse3 = require_parse();
|
|
12983
12983
|
var enoent = require_enoent();
|
|
12984
|
-
function
|
|
12984
|
+
function spawn5(command, args, options) {
|
|
12985
12985
|
const parsed = parse3(command, args, options);
|
|
12986
12986
|
const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
|
|
12987
12987
|
enoent.hookChildProcess(spawned, parsed);
|
|
@@ -12993,8 +12993,8 @@ var require_cross_spawn = __commonJS({
|
|
|
12993
12993
|
result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
|
|
12994
12994
|
return result;
|
|
12995
12995
|
}
|
|
12996
|
-
module.exports =
|
|
12997
|
-
module.exports.spawn =
|
|
12996
|
+
module.exports = spawn5;
|
|
12997
|
+
module.exports.spawn = spawn5;
|
|
12998
12998
|
module.exports.sync = spawnSync5;
|
|
12999
12999
|
module.exports._parse = parse3;
|
|
13000
13000
|
module.exports._enoent = enoent;
|
|
@@ -13002,8 +13002,9 @@ var require_cross_spawn = __commonJS({
|
|
|
13002
13002
|
});
|
|
13003
13003
|
|
|
13004
13004
|
// src/maker/server/mcp.ts
|
|
13005
|
-
import
|
|
13006
|
-
import
|
|
13005
|
+
import { execFileSync, spawn as spawn4 } from "node:child_process";
|
|
13006
|
+
import fs7 from "node:fs";
|
|
13007
|
+
import path8 from "node:path";
|
|
13007
13008
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
13008
13009
|
|
|
13009
13010
|
// node_modules/zod/v3/helpers/util.js
|
|
@@ -13365,8 +13366,8 @@ function getErrorMap() {
|
|
|
13365
13366
|
|
|
13366
13367
|
// node_modules/zod/v3/helpers/parseUtil.js
|
|
13367
13368
|
var makeIssue = (params) => {
|
|
13368
|
-
const { data, path:
|
|
13369
|
-
const fullPath = [...
|
|
13369
|
+
const { data, path: path11, errorMaps, issueData } = params;
|
|
13370
|
+
const fullPath = [...path11, ...issueData.path || []];
|
|
13370
13371
|
const fullIssue = {
|
|
13371
13372
|
...issueData,
|
|
13372
13373
|
path: fullPath
|
|
@@ -13481,11 +13482,11 @@ var errorUtil;
|
|
|
13481
13482
|
|
|
13482
13483
|
// node_modules/zod/v3/types.js
|
|
13483
13484
|
var ParseInputLazyPath = class {
|
|
13484
|
-
constructor(parent, value,
|
|
13485
|
+
constructor(parent, value, path11, key) {
|
|
13485
13486
|
this._cachedPath = [];
|
|
13486
13487
|
this.parent = parent;
|
|
13487
13488
|
this.data = value;
|
|
13488
|
-
this._path =
|
|
13489
|
+
this._path = path11;
|
|
13489
13490
|
this._key = key;
|
|
13490
13491
|
}
|
|
13491
13492
|
get path() {
|
|
@@ -17134,10 +17135,10 @@ function mergeDefs(...defs) {
|
|
|
17134
17135
|
function cloneDef(schema) {
|
|
17135
17136
|
return mergeDefs(schema._zod.def);
|
|
17136
17137
|
}
|
|
17137
|
-
function getElementAtPath(obj,
|
|
17138
|
-
if (!
|
|
17138
|
+
function getElementAtPath(obj, path11) {
|
|
17139
|
+
if (!path11)
|
|
17139
17140
|
return obj;
|
|
17140
|
-
return
|
|
17141
|
+
return path11.reduce((acc, key) => acc == null ? void 0 : acc[key], obj);
|
|
17141
17142
|
}
|
|
17142
17143
|
function promiseAllObject(promisesObj) {
|
|
17143
17144
|
const keys = Object.keys(promisesObj);
|
|
@@ -17522,11 +17523,11 @@ function aborted(x, startIndex = 0) {
|
|
|
17522
17523
|
}
|
|
17523
17524
|
return false;
|
|
17524
17525
|
}
|
|
17525
|
-
function prefixIssues(
|
|
17526
|
+
function prefixIssues(path11, issues) {
|
|
17526
17527
|
return issues.map((iss) => {
|
|
17527
17528
|
var _a2;
|
|
17528
17529
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
17529
|
-
iss.path.unshift(
|
|
17530
|
+
iss.path.unshift(path11);
|
|
17530
17531
|
return iss;
|
|
17531
17532
|
});
|
|
17532
17533
|
}
|
|
@@ -28436,8 +28437,105 @@ function formatIdentifyHint() {
|
|
|
28436
28437
|
].join("\n");
|
|
28437
28438
|
}
|
|
28438
28439
|
|
|
28440
|
+
// src/maker/server/hiddenStdioTransport.ts
|
|
28441
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
28442
|
+
import { PassThrough as PassThrough2 } from "node:stream";
|
|
28443
|
+
var HiddenStdioClientTransport = class {
|
|
28444
|
+
constructor(serverParams) {
|
|
28445
|
+
this.serverParams = serverParams;
|
|
28446
|
+
this.abortController = new AbortController();
|
|
28447
|
+
this.readBuffer = new ReadBuffer();
|
|
28448
|
+
this.stderrStream = serverParams.stderr === "pipe" || serverParams.stderr === "overlapped" ? new PassThrough2() : null;
|
|
28449
|
+
}
|
|
28450
|
+
async start() {
|
|
28451
|
+
if (this.process) {
|
|
28452
|
+
throw new Error("HiddenStdioClientTransport already started.");
|
|
28453
|
+
}
|
|
28454
|
+
await new Promise((resolve, reject) => {
|
|
28455
|
+
var _a2, _b, _c;
|
|
28456
|
+
this.process = spawn2(this.serverParams.command, this.serverParams.args ?? [], {
|
|
28457
|
+
env: this.serverParams.env,
|
|
28458
|
+
stdio: ["pipe", "pipe", this.serverParams.stderr ?? "inherit"],
|
|
28459
|
+
shell: false,
|
|
28460
|
+
signal: this.abortController.signal,
|
|
28461
|
+
windowsHide: true,
|
|
28462
|
+
cwd: this.serverParams.cwd
|
|
28463
|
+
});
|
|
28464
|
+
this.process.on("error", (error2) => {
|
|
28465
|
+
var _a3, _b2;
|
|
28466
|
+
if (error2.name === "AbortError") {
|
|
28467
|
+
(_a3 = this.onclose) == null ? void 0 : _a3.call(this);
|
|
28468
|
+
return;
|
|
28469
|
+
}
|
|
28470
|
+
reject(error2);
|
|
28471
|
+
(_b2 = this.onerror) == null ? void 0 : _b2.call(this, error2);
|
|
28472
|
+
});
|
|
28473
|
+
this.process.on("spawn", () => resolve());
|
|
28474
|
+
this.process.on("close", () => {
|
|
28475
|
+
var _a3;
|
|
28476
|
+
this.process = void 0;
|
|
28477
|
+
(_a3 = this.onclose) == null ? void 0 : _a3.call(this);
|
|
28478
|
+
});
|
|
28479
|
+
(_a2 = this.process.stdin) == null ? void 0 : _a2.on("error", (error2) => {
|
|
28480
|
+
var _a3;
|
|
28481
|
+
return (_a3 = this.onerror) == null ? void 0 : _a3.call(this, error2);
|
|
28482
|
+
});
|
|
28483
|
+
(_b = this.process.stdout) == null ? void 0 : _b.on("data", (chunk) => {
|
|
28484
|
+
this.readBuffer.append(chunk);
|
|
28485
|
+
this.processReadBuffer();
|
|
28486
|
+
});
|
|
28487
|
+
(_c = this.process.stdout) == null ? void 0 : _c.on("error", (error2) => {
|
|
28488
|
+
var _a3;
|
|
28489
|
+
return (_a3 = this.onerror) == null ? void 0 : _a3.call(this, error2);
|
|
28490
|
+
});
|
|
28491
|
+
if (this.stderrStream && this.process.stderr) {
|
|
28492
|
+
this.process.stderr.pipe(this.stderrStream);
|
|
28493
|
+
}
|
|
28494
|
+
});
|
|
28495
|
+
}
|
|
28496
|
+
get stderr() {
|
|
28497
|
+
var _a2;
|
|
28498
|
+
return this.stderrStream || ((_a2 = this.process) == null ? void 0 : _a2.stderr) || null;
|
|
28499
|
+
}
|
|
28500
|
+
get pid() {
|
|
28501
|
+
var _a2;
|
|
28502
|
+
return ((_a2 = this.process) == null ? void 0 : _a2.pid) ?? null;
|
|
28503
|
+
}
|
|
28504
|
+
async close() {
|
|
28505
|
+
this.abortController.abort();
|
|
28506
|
+
this.process = void 0;
|
|
28507
|
+
this.readBuffer.clear();
|
|
28508
|
+
}
|
|
28509
|
+
async send(message) {
|
|
28510
|
+
var _a2;
|
|
28511
|
+
const stdin = (_a2 = this.process) == null ? void 0 : _a2.stdin;
|
|
28512
|
+
if (!stdin) {
|
|
28513
|
+
throw new Error("Not connected");
|
|
28514
|
+
}
|
|
28515
|
+
const json2 = serializeMessage(message);
|
|
28516
|
+
if (stdin.write(json2)) {
|
|
28517
|
+
return;
|
|
28518
|
+
}
|
|
28519
|
+
await new Promise((resolve) => stdin.once("drain", resolve));
|
|
28520
|
+
}
|
|
28521
|
+
processReadBuffer() {
|
|
28522
|
+
var _a2, _b;
|
|
28523
|
+
for (; ; ) {
|
|
28524
|
+
try {
|
|
28525
|
+
const message = this.readBuffer.readMessage();
|
|
28526
|
+
if (message === null) {
|
|
28527
|
+
break;
|
|
28528
|
+
}
|
|
28529
|
+
(_a2 = this.onmessage) == null ? void 0 : _a2.call(this, message);
|
|
28530
|
+
} catch (error2) {
|
|
28531
|
+
(_b = this.onerror) == null ? void 0 : _b.call(this, error2 instanceof Error ? error2 : new Error(String(error2)));
|
|
28532
|
+
}
|
|
28533
|
+
}
|
|
28534
|
+
}
|
|
28535
|
+
};
|
|
28536
|
+
|
|
28439
28537
|
// src/maker/cli/projects.ts
|
|
28440
|
-
import { spawn as
|
|
28538
|
+
import { spawn as spawn3, spawnSync as spawnSync3 } from "node:child_process";
|
|
28441
28539
|
import fs4 from "node:fs";
|
|
28442
28540
|
import path5 from "node:path";
|
|
28443
28541
|
|
|
@@ -28702,20 +28800,38 @@ import { spawnSync as spawnSync2 } from "node:child_process";
|
|
|
28702
28800
|
import fs3 from "node:fs";
|
|
28703
28801
|
import os3 from "node:os";
|
|
28704
28802
|
import path4 from "node:path";
|
|
28705
|
-
var
|
|
28803
|
+
var AI_DEV_KIT_URLS = {
|
|
28804
|
+
production: "https://urhox-demo-platform.spark.xd.com/ai-dev-kit/pd/stable/ai-dev-kit.zip",
|
|
28805
|
+
rnd: "https://urhox-demo-platform.spark.xd.com/ai-dev-kit/rnd/latest/ai-dev-kit.zip"
|
|
28806
|
+
};
|
|
28807
|
+
var DEFAULT_AI_DEV_KIT_URL = AI_DEV_KIT_URLS.production;
|
|
28808
|
+
function resolveDefaultAiDevKitUrl(environment = EnvConfig.environment) {
|
|
28809
|
+
return AI_DEV_KIT_URLS[environment] || AI_DEV_KIT_URLS.production;
|
|
28810
|
+
}
|
|
28706
28811
|
var DEV_KIT_IGNORE_BEGIN = "# >>> TapTap Maker AI dev kit (local only) >>>";
|
|
28707
28812
|
var DEV_KIT_IGNORE_END = "# <<< TapTap Maker AI dev kit (local only) <<<";
|
|
28708
28813
|
var DEV_KIT_GITIGNORE_STAGING_FILE = ".gitignore.dev-kit-before-clone";
|
|
28709
28814
|
var DEV_KIT_REQUIRED_ENTRIES = ["CLAUDE.md", "examples", "templates", "urhox-libs"];
|
|
28815
|
+
var ALWAYS_IGNORED_LOCAL_ENTRIES = [".DS_Store", ".maker"];
|
|
28710
28816
|
var DEV_KIT_MANAGED_ENTRY_CANDIDATES = [
|
|
28817
|
+
".claude",
|
|
28818
|
+
".cli",
|
|
28819
|
+
".codex",
|
|
28820
|
+
".cursor",
|
|
28711
28821
|
".emmylua",
|
|
28822
|
+
".gemini",
|
|
28823
|
+
"AGENTS.md",
|
|
28712
28824
|
"CLAUDE.md",
|
|
28713
28825
|
"engine-docs",
|
|
28714
28826
|
"examples",
|
|
28827
|
+
"schemas",
|
|
28828
|
+
"skills",
|
|
28715
28829
|
"templates",
|
|
28830
|
+
"tools",
|
|
28716
28831
|
"urhox-libs"
|
|
28717
28832
|
];
|
|
28718
28833
|
var SKIPPED_TOP_LEVEL_ENTRIES = /* @__PURE__ */ new Set(["scripts", ".DS_Store", "ai-dev-kit.zip"]);
|
|
28834
|
+
var SKILL_INSTALLER_OUTPUT_ENTRIES = [".claude", ".codex", ".cursor", ".gemini"];
|
|
28719
28835
|
function inspectAiDevKit(targetDir) {
|
|
28720
28836
|
const resolvedTargetDir = path4.resolve(targetDir);
|
|
28721
28837
|
const presentEntries = DEV_KIT_REQUIRED_ENTRIES.filter(
|
|
@@ -28741,7 +28857,7 @@ function listPresentDevKitManagedEntries(targetDir) {
|
|
|
28741
28857
|
async function installAiDevKit(options = {}) {
|
|
28742
28858
|
const targetDir = path4.resolve(options.targetDir || ".");
|
|
28743
28859
|
fs3.mkdirSync(targetDir, { recursive: true });
|
|
28744
|
-
const preparedSource = options.sourceDir ? path4.resolve(options.sourceDir) : await downloadAndExtractDevKit(options.url ||
|
|
28860
|
+
const preparedSource = options.sourceDir ? path4.resolve(options.sourceDir) : await downloadAndExtractDevKit(options.url || resolveDefaultAiDevKitUrl());
|
|
28745
28861
|
const sourceDir = resolveDevKitRoot(preparedSource);
|
|
28746
28862
|
const entries = fs3.readdirSync(sourceDir, { withFileTypes: true });
|
|
28747
28863
|
const installedEntries = [];
|
|
@@ -28756,19 +28872,49 @@ async function installAiDevKit(options = {}) {
|
|
|
28756
28872
|
});
|
|
28757
28873
|
installedEntries.push(entry.name);
|
|
28758
28874
|
}
|
|
28875
|
+
const skillInstaller = runDevKitSkillInstallerForInstall(targetDir, {
|
|
28876
|
+
onStart: options.onSkillInstallerStart
|
|
28877
|
+
});
|
|
28759
28878
|
const stagedGitignorePath = path4.join(targetDir, DEV_KIT_GITIGNORE_STAGING_FILE);
|
|
28760
|
-
writeDevKitStagedGitignore(stagedGitignorePath,
|
|
28879
|
+
writeDevKitStagedGitignore(stagedGitignorePath, [
|
|
28880
|
+
...installedEntries,
|
|
28881
|
+
...listPresentSkillInstallerOutputEntries(targetDir)
|
|
28882
|
+
]);
|
|
28761
28883
|
return {
|
|
28762
28884
|
targetDir,
|
|
28763
28885
|
sourceDir,
|
|
28764
28886
|
installedEntries: installedEntries.sort(),
|
|
28765
28887
|
skippedEntries: skippedEntries.sort(),
|
|
28766
28888
|
gitignorePath: path4.join(targetDir, ".gitignore"),
|
|
28767
|
-
stagedGitignorePath
|
|
28889
|
+
stagedGitignorePath,
|
|
28890
|
+
skillInstaller
|
|
28891
|
+
};
|
|
28892
|
+
}
|
|
28893
|
+
function inspectAiDevKitSkillInstallStatus(targetDir) {
|
|
28894
|
+
const resolvedTargetDir = path4.resolve(targetDir);
|
|
28895
|
+
const targets = SKILL_INSTALLER_OUTPUT_ENTRIES.map((entry) => {
|
|
28896
|
+
const skillsDir = path4.join(resolvedTargetDir, entry, "skills");
|
|
28897
|
+
const present = fs3.existsSync(skillsDir) && fs3.statSync(skillsDir).isDirectory();
|
|
28898
|
+
const skillCount = present ? fs3.readdirSync(skillsDir, { withFileTypes: true }).filter((item) => item.isDirectory() || item.isSymbolicLink()).length : 0;
|
|
28899
|
+
return {
|
|
28900
|
+
name: entry.replace(/^\./, ""),
|
|
28901
|
+
path: skillsDir,
|
|
28902
|
+
present,
|
|
28903
|
+
skillCount
|
|
28904
|
+
};
|
|
28905
|
+
});
|
|
28906
|
+
const installedCount = targets.filter((target) => target.present && target.skillCount > 0).length;
|
|
28907
|
+
const status = installedCount === targets.length ? "installed" : installedCount > 0 ? "partial" : "missing";
|
|
28908
|
+
return {
|
|
28909
|
+
status,
|
|
28910
|
+
summary: targets.map((target) => `${target.name}=${target.skillCount}`).join(", "),
|
|
28911
|
+
targets
|
|
28768
28912
|
};
|
|
28769
28913
|
}
|
|
28770
28914
|
function createDevKitGitignoreBlock(entries) {
|
|
28771
|
-
const ignoreEntries = Array.from(
|
|
28915
|
+
const ignoreEntries = Array.from(
|
|
28916
|
+
new Set([...ALWAYS_IGNORED_LOCAL_ENTRIES, ...entries].map(formatIgnoreEntry))
|
|
28917
|
+
).filter(Boolean).sort();
|
|
28772
28918
|
return [DEV_KIT_IGNORE_BEGIN, ...ignoreEntries, DEV_KIT_IGNORE_END].join("\n");
|
|
28773
28919
|
}
|
|
28774
28920
|
function writeDevKitStagedGitignore(stagedGitignorePath, entries) {
|
|
@@ -28819,6 +28965,87 @@ function copyEntry(source, target, options = {}) {
|
|
|
28819
28965
|
fs3.copyFileSync(source, target);
|
|
28820
28966
|
}
|
|
28821
28967
|
}
|
|
28968
|
+
function installAiDevKitSkills(targetDir, options = {}) {
|
|
28969
|
+
var _a2;
|
|
28970
|
+
const toolsDir = path4.join(targetDir, "tools");
|
|
28971
|
+
if (!fs3.existsSync(toolsDir) || !fs3.statSync(toolsDir).isDirectory()) {
|
|
28972
|
+
return {
|
|
28973
|
+
ok: false,
|
|
28974
|
+
status: "skipped",
|
|
28975
|
+
stdout: "",
|
|
28976
|
+
stderr: "",
|
|
28977
|
+
summary: "skipped: tools directory not found",
|
|
28978
|
+
reason: "tools_not_found"
|
|
28979
|
+
};
|
|
28980
|
+
}
|
|
28981
|
+
const isWindows = process.platform === "win32";
|
|
28982
|
+
const scriptName = isWindows ? "install-skills.ps1" : "install-skills.sh";
|
|
28983
|
+
const scriptPath = path4.join(toolsDir, scriptName);
|
|
28984
|
+
if (!fs3.existsSync(scriptPath)) {
|
|
28985
|
+
return {
|
|
28986
|
+
ok: false,
|
|
28987
|
+
status: "skipped",
|
|
28988
|
+
script: scriptPath,
|
|
28989
|
+
stdout: "",
|
|
28990
|
+
stderr: "",
|
|
28991
|
+
summary: `skipped: ${scriptName} not found`,
|
|
28992
|
+
reason: "script_not_found"
|
|
28993
|
+
};
|
|
28994
|
+
}
|
|
28995
|
+
const command = isWindows ? ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", scriptPath, "all"] : ["bash", scriptPath, "all"];
|
|
28996
|
+
(_a2 = options.onStart) == null ? void 0 : _a2.call(options, {
|
|
28997
|
+
platform: process.platform,
|
|
28998
|
+
script: scriptPath,
|
|
28999
|
+
cwd: toolsDir,
|
|
29000
|
+
command
|
|
29001
|
+
});
|
|
29002
|
+
const result = spawnSync2(command[0], command.slice(1), { cwd: toolsDir, encoding: "utf8" });
|
|
29003
|
+
if (result.status !== 0) {
|
|
29004
|
+
throw new AiDevKitSkillInstallerError(
|
|
29005
|
+
formatFailedSkillInstallerResult({
|
|
29006
|
+
platform: process.platform,
|
|
29007
|
+
scriptPath,
|
|
29008
|
+
toolsDir,
|
|
29009
|
+
command,
|
|
29010
|
+
result
|
|
29011
|
+
})
|
|
29012
|
+
);
|
|
29013
|
+
}
|
|
29014
|
+
const stdout = String(result.stdout || "");
|
|
29015
|
+
const stderr = String(result.stderr || "");
|
|
29016
|
+
return {
|
|
29017
|
+
ok: true,
|
|
29018
|
+
status: "installed",
|
|
29019
|
+
script: scriptPath,
|
|
29020
|
+
stdout,
|
|
29021
|
+
stderr,
|
|
29022
|
+
summary: summarizeSkillInstallerOutput(stdout)
|
|
29023
|
+
};
|
|
29024
|
+
}
|
|
29025
|
+
function runDevKitSkillInstallerForInstall(targetDir, options = {}) {
|
|
29026
|
+
try {
|
|
29027
|
+
return installAiDevKitSkills(targetDir, options);
|
|
29028
|
+
} catch (error2) {
|
|
29029
|
+
if (error2 instanceof AiDevKitSkillInstallerError) {
|
|
29030
|
+
return error2.result;
|
|
29031
|
+
}
|
|
29032
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
29033
|
+
return {
|
|
29034
|
+
ok: false,
|
|
29035
|
+
status: "failed",
|
|
29036
|
+
stdout: "",
|
|
29037
|
+
stderr: "",
|
|
29038
|
+
summary: "failed",
|
|
29039
|
+
reason: "installer_failed",
|
|
29040
|
+
error: message
|
|
29041
|
+
};
|
|
29042
|
+
}
|
|
29043
|
+
}
|
|
29044
|
+
function listPresentSkillInstallerOutputEntries(targetDir) {
|
|
29045
|
+
return SKILL_INSTALLER_OUTPUT_ENTRIES.filter(
|
|
29046
|
+
(entry) => fs3.existsSync(path4.join(targetDir, entry))
|
|
29047
|
+
);
|
|
29048
|
+
}
|
|
28822
29049
|
async function downloadAndExtractDevKit(url2) {
|
|
28823
29050
|
const tempDir = fs3.mkdtempSync(path4.join(os3.tmpdir(), "taptap-maker-ai-dev-kit-"));
|
|
28824
29051
|
const zipPath = path4.join(tempDir, "ai-dev-kit.zip");
|
|
@@ -28895,6 +29122,67 @@ function formatSpawnFailure(result) {
|
|
|
28895
29122
|
var _a2;
|
|
28896
29123
|
return ((_a2 = result.error) == null ? void 0 : _a2.message) || String(result.stderr || "").trim() || String(result.stdout || "").trim() || `exit status ${result.status ?? "unknown"}`;
|
|
28897
29124
|
}
|
|
29125
|
+
function formatDevKitSkillInstallerFailure(options) {
|
|
29126
|
+
return [
|
|
29127
|
+
"Failed to install AI dev kit skills",
|
|
29128
|
+
`platform: ${options.platform}`,
|
|
29129
|
+
`script: ${options.scriptPath}`,
|
|
29130
|
+
`cwd: ${options.toolsDir}`,
|
|
29131
|
+
`command: ${options.command.map(shellQuote).join(" ")}`,
|
|
29132
|
+
`exit_status: ${options.result.status ?? "unknown"}`,
|
|
29133
|
+
options.result.signal ? `signal: ${options.result.signal}` : "",
|
|
29134
|
+
options.result.error ? `spawn_error: ${options.result.error.message}` : "",
|
|
29135
|
+
"stdout:",
|
|
29136
|
+
formatSpawnOutput(options.result.stdout),
|
|
29137
|
+
"stderr:",
|
|
29138
|
+
formatSpawnOutput(options.result.stderr)
|
|
29139
|
+
].filter((line) => line.length > 0).join("\n");
|
|
29140
|
+
}
|
|
29141
|
+
function formatFailedSkillInstallerResult(options) {
|
|
29142
|
+
return {
|
|
29143
|
+
ok: false,
|
|
29144
|
+
status: "failed",
|
|
29145
|
+
script: options.scriptPath,
|
|
29146
|
+
stdout: String(options.result.stdout || ""),
|
|
29147
|
+
stderr: String(options.result.stderr || ""),
|
|
29148
|
+
summary: summarizeSkillInstallerFailure(options.result),
|
|
29149
|
+
reason: "installer_failed",
|
|
29150
|
+
error: formatDevKitSkillInstallerFailure(options)
|
|
29151
|
+
};
|
|
29152
|
+
}
|
|
29153
|
+
function summarizeSkillInstallerFailure(result) {
|
|
29154
|
+
if (typeof result.status === "number") {
|
|
29155
|
+
return `failed: exit_status=${result.status}`;
|
|
29156
|
+
}
|
|
29157
|
+
if (result.signal) {
|
|
29158
|
+
return `failed: signal=${result.signal}`;
|
|
29159
|
+
}
|
|
29160
|
+
if (result.error) {
|
|
29161
|
+
return `failed: ${result.error.message}`;
|
|
29162
|
+
}
|
|
29163
|
+
return "failed";
|
|
29164
|
+
}
|
|
29165
|
+
var AiDevKitSkillInstallerError = class extends Error {
|
|
29166
|
+
constructor(result) {
|
|
29167
|
+
super(result.error || result.summary);
|
|
29168
|
+
this.result = result;
|
|
29169
|
+
this.name = "AiDevKitSkillInstallerError";
|
|
29170
|
+
}
|
|
29171
|
+
};
|
|
29172
|
+
function formatSpawnOutput(value) {
|
|
29173
|
+
const text = String(value || "").trim();
|
|
29174
|
+
return text.length > 0 ? text : "(empty)";
|
|
29175
|
+
}
|
|
29176
|
+
function summarizeSkillInstallerOutput(stdout) {
|
|
29177
|
+
const entries = stdout.split(/\r?\n/).map((line) => line.match(/\[install-skills\]\s+([^:]+):\s+installed=(\d+)/)).filter((match) => Boolean(match)).map((match) => `${match[1]}=${match[2]}`);
|
|
29178
|
+
return entries.length > 0 ? entries.join(", ") : "completed";
|
|
29179
|
+
}
|
|
29180
|
+
function shellQuote(value) {
|
|
29181
|
+
if (/^[A-Za-z0-9_./:=@-]+$/.test(value)) {
|
|
29182
|
+
return value;
|
|
29183
|
+
}
|
|
29184
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
29185
|
+
}
|
|
28898
29186
|
function resolveDevKitRoot(sourceDir) {
|
|
28899
29187
|
const directEntries = fs3.existsSync(sourceDir) ? fs3.readdirSync(sourceDir) : [];
|
|
28900
29188
|
if (looksLikeDevKitRoot(sourceDir)) {
|
|
@@ -28912,6 +29200,9 @@ function looksLikeDevKitRoot(dir) {
|
|
|
28912
29200
|
return fs3.existsSync(path4.join(dir, "engine-docs")) || fs3.existsSync(path4.join(dir, ".emmylua")) || fs3.existsSync(path4.join(dir, "urhox-libs"));
|
|
28913
29201
|
}
|
|
28914
29202
|
function formatIgnoreEntry(entry) {
|
|
29203
|
+
if (entry === ".DS_Store") {
|
|
29204
|
+
return entry;
|
|
29205
|
+
}
|
|
28915
29206
|
return entry.endsWith("/") ? entry : fsSafeDirectoryPattern(entry);
|
|
28916
29207
|
}
|
|
28917
29208
|
function fsSafeDirectoryPattern(entry) {
|
|
@@ -29413,7 +29704,7 @@ async function inspectMakerRemoteSyncStatus(cwd) {
|
|
|
29413
29704
|
}
|
|
29414
29705
|
function getMakerRemoteSyncFailureNextAction(failure) {
|
|
29415
29706
|
if (failure.classification === "auth") {
|
|
29416
|
-
return
|
|
29707
|
+
return `暂时无法检查 Maker 远端是否有新提交:Git 鉴权失败。PAT 页面:${getMakerPatTokensUrl()}。请在该页面创建新的 Maker PAT,然后运行 \`taptap-maker pat set\` 并粘贴 PAT 后,再重新读取 maker://status。`;
|
|
29417
29708
|
}
|
|
29418
29709
|
return "暂时无法检查 Maker 远端是否有新提交。请把 failure 信息反馈给用户;如果只是 503、5xx、超时或网络中断,可稍后重新读取 maker://status。";
|
|
29419
29710
|
}
|
|
@@ -29634,7 +29925,7 @@ function nextActionForFailure(classification) {
|
|
|
29634
29925
|
case "git_missing":
|
|
29635
29926
|
return "本机未检测到可用的 Git。请用户自行安装 Git,并在 `git --version` 可用后重启 MCP 客户端再重试;安装前不要执行 clone、fetch、commit 或 push。";
|
|
29636
29927
|
case "auth":
|
|
29637
|
-
return
|
|
29928
|
+
return `Maker Git 鉴权失败。PAT 页面:${getMakerPatTokensUrl()}。请在该页面创建新的 Maker PAT,然后运行 \`taptap-maker pat set\` 并粘贴 PAT 后重试。`;
|
|
29638
29929
|
case "remote_transient":
|
|
29639
29930
|
return "远端 Maker git 服务临时不可用。本地 commit 会保留;不要手动执行通用 git push,稍后直接重试 maker_build_current_directory。";
|
|
29640
29931
|
case "branch_not_allowed":
|
|
@@ -29652,7 +29943,7 @@ function nextActionForFailure(classification) {
|
|
|
29652
29943
|
function pushGit(args, cwd, onProgress) {
|
|
29653
29944
|
return new Promise((resolve, reject) => {
|
|
29654
29945
|
const gitCommand = getGitCommand();
|
|
29655
|
-
const child =
|
|
29946
|
+
const child = spawn3(gitCommand, args, {
|
|
29656
29947
|
cwd,
|
|
29657
29948
|
stdio: ["ignore", "pipe", "pipe"]
|
|
29658
29949
|
});
|
|
@@ -30128,7 +30419,7 @@ function readGitSync(args) {
|
|
|
30128
30419
|
function readGit(args, cwd) {
|
|
30129
30420
|
return new Promise((resolve, reject) => {
|
|
30130
30421
|
const gitCommand = getGitCommand();
|
|
30131
|
-
const child =
|
|
30422
|
+
const child = spawn3(gitCommand, args, {
|
|
30132
30423
|
cwd,
|
|
30133
30424
|
stdio: ["ignore", "pipe", "pipe"]
|
|
30134
30425
|
});
|
|
@@ -30238,7 +30529,7 @@ function sleep(ms) {
|
|
|
30238
30529
|
function runGitCapture(args, options = {}) {
|
|
30239
30530
|
return new Promise((resolve, reject) => {
|
|
30240
30531
|
const gitCommand = getGitCommand();
|
|
30241
|
-
const child =
|
|
30532
|
+
const child = spawn3(gitCommand, args, {
|
|
30242
30533
|
cwd: options.cwd,
|
|
30243
30534
|
stdio: ["ignore", "pipe", "pipe"]
|
|
30244
30535
|
});
|
|
@@ -30271,7 +30562,7 @@ function runGitCapture(args, options = {}) {
|
|
|
30271
30562
|
function runGit(args, options) {
|
|
30272
30563
|
return new Promise((resolve, reject) => {
|
|
30273
30564
|
const gitCommand = getGitCommand();
|
|
30274
|
-
const child =
|
|
30565
|
+
const child = spawn3(gitCommand, args, {
|
|
30275
30566
|
cwd: options.cwd,
|
|
30276
30567
|
stdio: ["ignore", "pipe", "pipe"]
|
|
30277
30568
|
});
|
|
@@ -30436,11 +30727,13 @@ function formatMakerSkillStatus(_options = {}) {
|
|
|
30436
30727
|
path: path6.join(resolveMakerSkillSourceDir(skill.name), "SKILL.md")
|
|
30437
30728
|
}));
|
|
30438
30729
|
return [
|
|
30439
|
-
"TapTap
|
|
30730
|
+
"TapTap Maker workflow guide documents",
|
|
30440
30731
|
"",
|
|
30441
30732
|
...skillDocuments.map((skill) => `- ${skill.name}: ${skill.path}`),
|
|
30442
30733
|
"",
|
|
30443
|
-
"
|
|
30734
|
+
"Use these documents as reading references for Maker local workflows.",
|
|
30735
|
+
"Maker initialization next_step: execute `taptap-maker init`.",
|
|
30736
|
+
"Load these documents when the current AI client supports reading local guide files."
|
|
30444
30737
|
].join("\n");
|
|
30445
30738
|
}
|
|
30446
30739
|
function resolveMakerSkillSourceDir(skillName = MAKER_LOCAL_SKILL_NAME) {
|
|
@@ -30466,10 +30759,386 @@ function getBundledSkillSourceDir(skillName) {
|
|
|
30466
30759
|
return path6.join(packageRoot, "skills", skillName);
|
|
30467
30760
|
}
|
|
30468
30761
|
|
|
30762
|
+
// src/maker/server/runtimeLogs.ts
|
|
30763
|
+
import fs6 from "node:fs";
|
|
30764
|
+
import path7 from "node:path";
|
|
30765
|
+
var DEFAULT_RUNTIME_LOG_SINCE_SECONDS = 600;
|
|
30766
|
+
var MAX_RUNTIME_LOG_WINDOW_SECONDS = 3600;
|
|
30767
|
+
var DEFAULT_RUNTIME_LOG_TOPICS = ["user_script", "server_user_script"];
|
|
30768
|
+
var MERGED_RUNTIME_LOG_FILE = "runtime.log";
|
|
30769
|
+
var RUNTIME_LOG_FILES_TO_RESET = [
|
|
30770
|
+
MERGED_RUNTIME_LOG_FILE,
|
|
30771
|
+
"state.json",
|
|
30772
|
+
"last-query-runtime-logs-result.json",
|
|
30773
|
+
"runtime.raw.log",
|
|
30774
|
+
"engine.log",
|
|
30775
|
+
"user_script.log",
|
|
30776
|
+
"server_user_script.log"
|
|
30777
|
+
];
|
|
30778
|
+
async function watchRuntimeLogs(options) {
|
|
30779
|
+
var _a2, _b;
|
|
30780
|
+
if (options.reset) {
|
|
30781
|
+
resetRuntimeLogs(options.projectRoot);
|
|
30782
|
+
}
|
|
30783
|
+
const intervalMs = options.intervalMs ?? 5e3;
|
|
30784
|
+
const maxConsecutiveFailures = options.maxConsecutiveFailures;
|
|
30785
|
+
const sleep2 = options.sleep || defaultSleep;
|
|
30786
|
+
const nowMs = options.nowMs || Date.now;
|
|
30787
|
+
let polls = 0;
|
|
30788
|
+
let writtenLogs = 0;
|
|
30789
|
+
let lastResult;
|
|
30790
|
+
let consecutiveFailures = 0;
|
|
30791
|
+
for (; ; ) {
|
|
30792
|
+
try {
|
|
30793
|
+
const previousCursor = lastResult == null ? void 0 : lastResult.nextStartTime;
|
|
30794
|
+
const result = await pullRuntimeLogs({
|
|
30795
|
+
projectRoot: options.projectRoot,
|
|
30796
|
+
projectId: options.projectId,
|
|
30797
|
+
sinceSeconds: options.sinceSeconds,
|
|
30798
|
+
limit: options.limit,
|
|
30799
|
+
nowMs: options.nowMs,
|
|
30800
|
+
callRemoteRuntimeLogs: options.callRemoteRuntimeLogs
|
|
30801
|
+
});
|
|
30802
|
+
polls += 1;
|
|
30803
|
+
writtenLogs += result.writtenLogs;
|
|
30804
|
+
lastResult = result;
|
|
30805
|
+
consecutiveFailures = 0;
|
|
30806
|
+
await ((_a2 = options.onPoll) == null ? void 0 : _a2.call(options, result));
|
|
30807
|
+
if (options.maxPolls !== void 0 && polls >= options.maxPolls) {
|
|
30808
|
+
return { projectRoot: options.projectRoot, polls, writtenLogs, lastResult };
|
|
30809
|
+
}
|
|
30810
|
+
const cursorProgressed = previousCursor === void 0 ? result.writtenLogs > 0 : result.nextStartTime !== previousCursor;
|
|
30811
|
+
if (!result.hasMore || !cursorProgressed) {
|
|
30812
|
+
await sleep2(intervalMs);
|
|
30813
|
+
}
|
|
30814
|
+
} catch (error2) {
|
|
30815
|
+
consecutiveFailures += 1;
|
|
30816
|
+
writeRuntimeLogFailureState(options.projectRoot, {
|
|
30817
|
+
nowMs,
|
|
30818
|
+
consecutiveFailures,
|
|
30819
|
+
error: error2
|
|
30820
|
+
});
|
|
30821
|
+
await ((_b = options.onError) == null ? void 0 : _b.call(options, error2, consecutiveFailures));
|
|
30822
|
+
if (isNonRetryableRuntimeLogError(error2)) {
|
|
30823
|
+
throw new Error(
|
|
30824
|
+
`runtime log watch stopped after non-retryable failure: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
30825
|
+
);
|
|
30826
|
+
}
|
|
30827
|
+
if (maxConsecutiveFailures !== void 0 && consecutiveFailures >= maxConsecutiveFailures) {
|
|
30828
|
+
throw new Error(
|
|
30829
|
+
`runtime log watch stopped after ${consecutiveFailures} consecutive failures: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
30830
|
+
);
|
|
30831
|
+
}
|
|
30832
|
+
await sleep2(intervalMs);
|
|
30833
|
+
}
|
|
30834
|
+
}
|
|
30835
|
+
}
|
|
30836
|
+
async function pullRuntimeLogs(options) {
|
|
30837
|
+
const nowMs = options.nowMs || Date.now;
|
|
30838
|
+
const state = readRuntimeLogState(options.projectRoot);
|
|
30839
|
+
const nowSeconds = nowMs() / 1e3;
|
|
30840
|
+
const stateFresh = (state == null ? void 0 : state.nextStartTime) !== void 0 && isFreshRuntimeLogCursor(state.nextStartTime, nowSeconds);
|
|
30841
|
+
const queryArgs = {};
|
|
30842
|
+
let cursorExpired = false;
|
|
30843
|
+
if (options.startTime !== void 0) {
|
|
30844
|
+
queryArgs.startTime = options.startTime;
|
|
30845
|
+
} else if (stateFresh && state) {
|
|
30846
|
+
queryArgs.startTime = state.nextStartTime;
|
|
30847
|
+
} else {
|
|
30848
|
+
cursorExpired = Boolean(state == null ? void 0 : state.nextStartTime);
|
|
30849
|
+
queryArgs.sinceSeconds = options.sinceSeconds ?? DEFAULT_RUNTIME_LOG_SINCE_SECONDS;
|
|
30850
|
+
}
|
|
30851
|
+
queryArgs.topics = options.topics && options.topics.length > 0 ? options.topics : DEFAULT_RUNTIME_LOG_TOPICS;
|
|
30852
|
+
if (options.limit !== void 0) {
|
|
30853
|
+
queryArgs.limit = options.limit;
|
|
30854
|
+
}
|
|
30855
|
+
const result = await options.callRemoteRuntimeLogs(queryArgs);
|
|
30856
|
+
const appendResult = appendRuntimeLogs(options.projectRoot, result.logs);
|
|
30857
|
+
const nextStartTime = resolveNextRuntimeLogCursor(result);
|
|
30858
|
+
const nowIso = new Date(nowMs()).toISOString();
|
|
30859
|
+
const nextState = {
|
|
30860
|
+
...state || {},
|
|
30861
|
+
...options.projectId ? { appId: options.projectId, projectId: options.projectId } : {},
|
|
30862
|
+
nextStartTime,
|
|
30863
|
+
updatedAt: nowIso,
|
|
30864
|
+
lastPollAt: nowIso,
|
|
30865
|
+
lastSuccessAt: nowIso,
|
|
30866
|
+
lastWrittenLogs: appendResult.written,
|
|
30867
|
+
consecutiveFailures: 0,
|
|
30868
|
+
lastError: null
|
|
30869
|
+
};
|
|
30870
|
+
writeRuntimeLogState(options.projectRoot, nextState);
|
|
30871
|
+
return {
|
|
30872
|
+
projectRoot: options.projectRoot,
|
|
30873
|
+
queryArgs,
|
|
30874
|
+
writtenLogs: appendResult.written,
|
|
30875
|
+
files: appendResult.files,
|
|
30876
|
+
statePath: getRuntimeLogStatePath(options.projectRoot),
|
|
30877
|
+
nextStartTime,
|
|
30878
|
+
serverTime: result.serverTime,
|
|
30879
|
+
hasMore: result.hasMore,
|
|
30880
|
+
cursorExpired
|
|
30881
|
+
};
|
|
30882
|
+
}
|
|
30883
|
+
function resetRuntimeLogs(projectRoot) {
|
|
30884
|
+
const runtimeDir = getRuntimeLogDir(projectRoot);
|
|
30885
|
+
fs6.mkdirSync(runtimeDir, { recursive: true });
|
|
30886
|
+
for (const file2 of RUNTIME_LOG_FILES_TO_RESET) {
|
|
30887
|
+
fs6.rmSync(path7.join(runtimeDir, file2), { force: true });
|
|
30888
|
+
}
|
|
30889
|
+
return runtimeDir;
|
|
30890
|
+
}
|
|
30891
|
+
function readRuntimeLogState(projectRoot) {
|
|
30892
|
+
const statePath = getRuntimeLogStatePath(projectRoot);
|
|
30893
|
+
if (!fs6.existsSync(statePath)) {
|
|
30894
|
+
return null;
|
|
30895
|
+
}
|
|
30896
|
+
try {
|
|
30897
|
+
const state = JSON.parse(fs6.readFileSync(statePath, "utf8"));
|
|
30898
|
+
return isRuntimeLogState(state) ? state : null;
|
|
30899
|
+
} catch {
|
|
30900
|
+
return null;
|
|
30901
|
+
}
|
|
30902
|
+
}
|
|
30903
|
+
function formatRuntimeLogPullResult(result) {
|
|
30904
|
+
return [
|
|
30905
|
+
"✓ Maker runtime logs pulled once",
|
|
30906
|
+
"",
|
|
30907
|
+
`- project_root: ${result.projectRoot}`,
|
|
30908
|
+
`- query_args: ${JSON.stringify(result.queryArgs)}`,
|
|
30909
|
+
`- written_logs: ${result.writtenLogs}`,
|
|
30910
|
+
`- files: ${result.files.length > 0 ? result.files.join(", ") : "(none)"}`,
|
|
30911
|
+
`- state: ${result.statePath}`,
|
|
30912
|
+
`- next_start_time: ${result.nextStartTime}`,
|
|
30913
|
+
`- server_time: ${result.serverTime}`,
|
|
30914
|
+
`- has_more: ${result.hasMore ? "yes" : "no"}`,
|
|
30915
|
+
result.cursorExpired ? "- cursor_expired: yes; old cursor exceeded 1 hour, used default since window" : "- cursor_expired: no",
|
|
30916
|
+
"",
|
|
30917
|
+
result.hasMore ? "next_action: 还有更多远端日志;可以再次调用 maker_pull_runtime_logs 继续拉取。" : "next_action: 日志已写入 .maker/logs/runtime/runtime.log,AI/skill 可直接读取这一份合并日志。"
|
|
30918
|
+
].join("\n");
|
|
30919
|
+
}
|
|
30920
|
+
function normalizeRuntimeLogQueryResult(result) {
|
|
30921
|
+
const payload = findRuntimeLogPayload(extractRemoteToolPayload(result));
|
|
30922
|
+
if (!payload) {
|
|
30923
|
+
throw new Error("query_runtime_logs result does not contain logs array.");
|
|
30924
|
+
}
|
|
30925
|
+
const nextStartTime = payload.nextStartTime ?? payload.next_start_time;
|
|
30926
|
+
const serverTime = payload.serverTime ?? payload.server_time ?? nextStartTime;
|
|
30927
|
+
const hasMore = payload.hasMore ?? payload.has_more ?? false;
|
|
30928
|
+
if (typeof nextStartTime !== "number") {
|
|
30929
|
+
throw new Error("query_runtime_logs result does not contain nextStartTime.");
|
|
30930
|
+
}
|
|
30931
|
+
if (typeof serverTime !== "number") {
|
|
30932
|
+
throw new Error("query_runtime_logs result does not contain serverTime.");
|
|
30933
|
+
}
|
|
30934
|
+
return {
|
|
30935
|
+
logs: payload.logs.map(normalizeRuntimeLogEntry),
|
|
30936
|
+
nextStartTime,
|
|
30937
|
+
serverTime,
|
|
30938
|
+
hasMore: Boolean(hasMore)
|
|
30939
|
+
};
|
|
30940
|
+
}
|
|
30941
|
+
function writeRuntimeLogRawResponse(projectRoot, raw) {
|
|
30942
|
+
const rawPath = path7.join(getRuntimeLogDir(projectRoot), "last-query-runtime-logs-result.json");
|
|
30943
|
+
fs6.mkdirSync(path7.dirname(rawPath), { recursive: true });
|
|
30944
|
+
fs6.writeFileSync(
|
|
30945
|
+
rawPath,
|
|
30946
|
+
`${JSON.stringify({ capturedAt: (/* @__PURE__ */ new Date()).toISOString(), raw }, null, 2)}
|
|
30947
|
+
`,
|
|
30948
|
+
"utf8"
|
|
30949
|
+
);
|
|
30950
|
+
return rawPath;
|
|
30951
|
+
}
|
|
30952
|
+
function appendRuntimeLogs(projectRoot, logs) {
|
|
30953
|
+
fs6.mkdirSync(getRuntimeLogDir(projectRoot), { recursive: true });
|
|
30954
|
+
if (logs.length === 0) {
|
|
30955
|
+
return { files: [], written: 0 };
|
|
30956
|
+
}
|
|
30957
|
+
const filePath = getRuntimeLogPath(projectRoot);
|
|
30958
|
+
let written = 0;
|
|
30959
|
+
for (const log of logs) {
|
|
30960
|
+
const line = JSON.stringify(compactRuntimeLogEntry(log));
|
|
30961
|
+
fs6.appendFileSync(filePath, `${line}
|
|
30962
|
+
`, "utf8");
|
|
30963
|
+
written += 1;
|
|
30964
|
+
}
|
|
30965
|
+
return { files: written > 0 ? [filePath] : [], written };
|
|
30966
|
+
}
|
|
30967
|
+
function writeRuntimeLogState(projectRoot, state) {
|
|
30968
|
+
const statePath = getRuntimeLogStatePath(projectRoot);
|
|
30969
|
+
fs6.mkdirSync(path7.dirname(statePath), { recursive: true });
|
|
30970
|
+
const tempPath = `${statePath}.${process.pid}.${Date.now()}.tmp`;
|
|
30971
|
+
fs6.writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}
|
|
30972
|
+
`, "utf8");
|
|
30973
|
+
fs6.renameSync(tempPath, statePath);
|
|
30974
|
+
}
|
|
30975
|
+
function writeRuntimeLogFailureState(projectRoot, options) {
|
|
30976
|
+
const nowIso = new Date(options.nowMs()).toISOString();
|
|
30977
|
+
writeRuntimeLogState(projectRoot, {
|
|
30978
|
+
...readRuntimeLogState(projectRoot) || {},
|
|
30979
|
+
updatedAt: nowIso,
|
|
30980
|
+
lastPollAt: nowIso,
|
|
30981
|
+
consecutiveFailures: options.consecutiveFailures,
|
|
30982
|
+
lastError: options.error instanceof Error ? options.error.message : String(options.error)
|
|
30983
|
+
});
|
|
30984
|
+
}
|
|
30985
|
+
function isRuntimeLogState(state) {
|
|
30986
|
+
return typeof state.nextStartTime === "number" || typeof state.updatedAt === "string" || typeof state.lastPollAt === "string" || typeof state.lastSuccessAt === "string";
|
|
30987
|
+
}
|
|
30988
|
+
function isFreshRuntimeLogCursor(nextStartTime, nowSeconds) {
|
|
30989
|
+
if (!Number.isFinite(nextStartTime) || nextStartTime <= 0) {
|
|
30990
|
+
return false;
|
|
30991
|
+
}
|
|
30992
|
+
if (nextStartTime > 1e10) {
|
|
30993
|
+
return false;
|
|
30994
|
+
}
|
|
30995
|
+
const ageSeconds = nowSeconds - nextStartTime;
|
|
30996
|
+
return ageSeconds >= -300 && ageSeconds <= MAX_RUNTIME_LOG_WINDOW_SECONDS;
|
|
30997
|
+
}
|
|
30998
|
+
function isNonRetryableRuntimeLogError(error2) {
|
|
30999
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
31000
|
+
return /\b(?:401|403|unauthori[sz]ed|forbidden|pat expired|auth(?:entication|orization)?)\b/i.test(
|
|
31001
|
+
message
|
|
31002
|
+
);
|
|
31003
|
+
}
|
|
31004
|
+
function getRuntimeLogDir(projectRoot) {
|
|
31005
|
+
return path7.join(projectRoot, ".maker", "logs", "runtime");
|
|
31006
|
+
}
|
|
31007
|
+
function getRuntimeLogStatePath(projectRoot) {
|
|
31008
|
+
return path7.join(getRuntimeLogDir(projectRoot), "state.json");
|
|
31009
|
+
}
|
|
31010
|
+
function getRuntimeLogPath(projectRoot) {
|
|
31011
|
+
return path7.join(getRuntimeLogDir(projectRoot), MERGED_RUNTIME_LOG_FILE);
|
|
31012
|
+
}
|
|
31013
|
+
function resolveNextRuntimeLogCursor(result) {
|
|
31014
|
+
const maxLogTime = result.logs.reduce((max, log) => {
|
|
31015
|
+
const value = typeof log.t === "number" ? log.t : typeof log.time === "number" ? log.time : max;
|
|
31016
|
+
return Math.max(max, value);
|
|
31017
|
+
}, Number.NEGATIVE_INFINITY);
|
|
31018
|
+
if (maxLogTime === Number.NEGATIVE_INFINITY) {
|
|
31019
|
+
return result.nextStartTime;
|
|
31020
|
+
}
|
|
31021
|
+
return Math.max(result.nextStartTime, maxLogTime + 1);
|
|
31022
|
+
}
|
|
31023
|
+
function defaultSleep(ms) {
|
|
31024
|
+
return new Promise((resolve) => {
|
|
31025
|
+
setTimeout(resolve, ms);
|
|
31026
|
+
});
|
|
31027
|
+
}
|
|
31028
|
+
function extractRemoteToolPayload(result) {
|
|
31029
|
+
if (!result || typeof result !== "object") {
|
|
31030
|
+
return result;
|
|
31031
|
+
}
|
|
31032
|
+
const structuredContent = result.structuredContent;
|
|
31033
|
+
if (structuredContent) {
|
|
31034
|
+
return structuredContent;
|
|
31035
|
+
}
|
|
31036
|
+
const textItems = extractRemoteToolTextItems(result);
|
|
31037
|
+
if (textItems.length === 0) {
|
|
31038
|
+
return result;
|
|
31039
|
+
}
|
|
31040
|
+
for (const textItem of textItems) {
|
|
31041
|
+
const payload = parseRuntimeLogTextPayload(textItem);
|
|
31042
|
+
if (payload) {
|
|
31043
|
+
return payload;
|
|
31044
|
+
}
|
|
31045
|
+
}
|
|
31046
|
+
const text = textItems.join("\n");
|
|
31047
|
+
return parseRuntimeLogTextPayload(text) || text;
|
|
31048
|
+
}
|
|
31049
|
+
function parseRuntimeLogTextPayload(text) {
|
|
31050
|
+
try {
|
|
31051
|
+
return JSON.parse(text);
|
|
31052
|
+
} catch {
|
|
31053
|
+
return parseRuntimeLogNdjson(text);
|
|
31054
|
+
}
|
|
31055
|
+
}
|
|
31056
|
+
function extractRemoteToolTextItems(result) {
|
|
31057
|
+
if (!result || typeof result !== "object") {
|
|
31058
|
+
return [];
|
|
31059
|
+
}
|
|
31060
|
+
const content = result.content;
|
|
31061
|
+
return (content == null ? void 0 : content.filter((item) => item.type === "text" && typeof item.text === "string").map((item) => item.text)) || [];
|
|
31062
|
+
}
|
|
31063
|
+
function parseRuntimeLogNdjson(text) {
|
|
31064
|
+
const rows = text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
31065
|
+
if (rows.length === 0) {
|
|
31066
|
+
return null;
|
|
31067
|
+
}
|
|
31068
|
+
const parsedRows = [];
|
|
31069
|
+
for (const row of rows) {
|
|
31070
|
+
try {
|
|
31071
|
+
parsedRows.push(JSON.parse(row));
|
|
31072
|
+
} catch {
|
|
31073
|
+
return null;
|
|
31074
|
+
}
|
|
31075
|
+
}
|
|
31076
|
+
const meta3 = parsedRows.find(isRuntimeLogMeta);
|
|
31077
|
+
const logs = parsedRows.filter((row) => !isRuntimeLogMeta(row));
|
|
31078
|
+
if (!meta3 && logs.length === 0) {
|
|
31079
|
+
return null;
|
|
31080
|
+
}
|
|
31081
|
+
return {
|
|
31082
|
+
logs,
|
|
31083
|
+
nextStartTime: meta3 == null ? void 0 : meta3.nextStartTime,
|
|
31084
|
+
next_start_time: meta3 == null ? void 0 : meta3.next_start_time,
|
|
31085
|
+
serverTime: meta3 == null ? void 0 : meta3.serverTime,
|
|
31086
|
+
server_time: meta3 == null ? void 0 : meta3.server_time,
|
|
31087
|
+
hasMore: (meta3 == null ? void 0 : meta3.hasMore) ?? (meta3 == null ? void 0 : meta3.has_more) ?? (meta3 == null ? void 0 : meta3.truncated)
|
|
31088
|
+
};
|
|
31089
|
+
}
|
|
31090
|
+
function findRuntimeLogPayload(value, depth = 0) {
|
|
31091
|
+
if (!value || typeof value !== "object" || depth > 4) {
|
|
31092
|
+
return null;
|
|
31093
|
+
}
|
|
31094
|
+
const candidate = value;
|
|
31095
|
+
if (Array.isArray(candidate.logs)) {
|
|
31096
|
+
return candidate;
|
|
31097
|
+
}
|
|
31098
|
+
if (candidate.type === "meta" && candidate.success === true && typeof candidate.nextStartTime === "number") {
|
|
31099
|
+
return {
|
|
31100
|
+
logs: [],
|
|
31101
|
+
nextStartTime: candidate.nextStartTime,
|
|
31102
|
+
serverTime: candidate.serverTime ?? candidate.nextStartTime,
|
|
31103
|
+
hasMore: Boolean(candidate.truncated)
|
|
31104
|
+
};
|
|
31105
|
+
}
|
|
31106
|
+
const wrappers = value;
|
|
31107
|
+
for (const key of ["data", "result", "payload", "runtimeLogs", "runtime_logs"]) {
|
|
31108
|
+
const nested = findRuntimeLogPayload(wrappers[key], depth + 1);
|
|
31109
|
+
if (nested) {
|
|
31110
|
+
return nested;
|
|
31111
|
+
}
|
|
31112
|
+
}
|
|
31113
|
+
return null;
|
|
31114
|
+
}
|
|
31115
|
+
function isRuntimeLogMeta(value) {
|
|
31116
|
+
return Boolean(value) && typeof value === "object" && value.type === "meta" && value.success === true && (typeof value.nextStartTime === "number" || typeof value.next_start_time === "number");
|
|
31117
|
+
}
|
|
31118
|
+
function normalizeRuntimeLogEntry(entry) {
|
|
31119
|
+
return compactRuntimeLogEntry(entry);
|
|
31120
|
+
}
|
|
31121
|
+
function compactRuntimeLogEntry(entry) {
|
|
31122
|
+
const { id: _id, time: time3, message, ...rest } = entry;
|
|
31123
|
+
const compact = {
|
|
31124
|
+
...rest
|
|
31125
|
+
};
|
|
31126
|
+
if (compact.t === void 0 && time3 !== void 0) {
|
|
31127
|
+
compact.t = time3;
|
|
31128
|
+
}
|
|
31129
|
+
if (compact.msg === void 0 && message !== void 0) {
|
|
31130
|
+
compact.msg = message;
|
|
31131
|
+
}
|
|
31132
|
+
return compact;
|
|
31133
|
+
}
|
|
31134
|
+
|
|
30469
31135
|
// src/maker/server/mcp.ts
|
|
30470
|
-
var VERSION = true ? "1.23.
|
|
31136
|
+
var VERSION = true ? "1.23.7-beta.2" : "dev";
|
|
30471
31137
|
var DEFAULT_PROXY_PACKAGE = "@taptap/instant-games-open-mcp@1.22.0";
|
|
30472
31138
|
var DEFAULT_BUILD_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
31139
|
+
var PREVIEW_REFRESH_TIMEOUT_MS = 15 * 1e3;
|
|
31140
|
+
var WATCHER_STOP_TIMEOUT_MS = 1500;
|
|
31141
|
+
var WATCHER_PROCESS_PATTERN = /(?:\btaptap-maker\b|\bmaker\.js\b).*\blogs\b.*\bwatch\b/;
|
|
30473
31142
|
var LONG_OPERATION_HEARTBEAT_MS = 3 * 60 * 1e3;
|
|
30474
31143
|
var MakerCloneFailedError = class extends Error {
|
|
30475
31144
|
constructor(targetDir, originalError) {
|
|
@@ -30483,7 +31152,7 @@ var MakerCloneFailedError = class extends Error {
|
|
|
30483
31152
|
var tools = [
|
|
30484
31153
|
{
|
|
30485
31154
|
name: "maker_status_lite",
|
|
30486
|
-
description: "Compatibility
|
|
31155
|
+
description: "Compatibility status surface for clients using tool output instead of the maker://status resource. Prefer reading maker://status when resources are available. Shows local Maker status for the user current working directory, including Git, PAT/TapTap auth, project binding, AI dev kit status, and bundled workflow guide document paths. Maker initialization next_step: taptap-maker init.",
|
|
30487
31156
|
inputSchema: {
|
|
30488
31157
|
type: "object",
|
|
30489
31158
|
properties: {
|
|
@@ -30500,7 +31169,7 @@ var tools = [
|
|
|
30500
31169
|
},
|
|
30501
31170
|
{
|
|
30502
31171
|
name: "maker_build_current_directory",
|
|
30503
|
-
description: 'Sync and build the current Maker game. Use this single tool for user requests like "构建", "build", "跑一下", "预览", "验证一下", "提交", "提交代码", "推送", or "push" in a Maker project. If local changes or committed-but-unpushed commits exist, the tool commits when needed, pushes to Maker remote, then triggers remote Maker build. If push fails, build is not started and the result includes recovery details for the local Agent to handle merge/conflict resolution. If push succeeds but remote build fails, report that code is already on Maker remote and include build failure details. Only set confirm_remote_build_without_submit=true when the user explicitly says they do not want to submit local changes and wants to build the current remote version.',
|
|
31172
|
+
description: 'Sync and build the current Maker game. Use this single tool for user requests like "构建", "build", "跑一下", "预览", "验证一下", "提交", "提交代码", "推送", or "push" in a Maker project. If local changes or committed-but-unpushed commits exist, the tool commits when needed, pushes to Maker remote, then triggers remote Maker build. If push fails, build is not started and the result includes recovery details for the local Agent to handle merge/conflict resolution. If push succeeds but remote build fails, report that code is already on Maker remote and include build failure details. After a successful build, a local runtime log watcher is started; for gameplay/runtime diagnostics, read runtime_logs.local_file, and for watcher health read runtime_logs.state_file. Only set confirm_remote_build_without_submit=true when the user explicitly says they do not want to submit local changes and wants to build the current remote version.',
|
|
30504
31173
|
inputSchema: {
|
|
30505
31174
|
type: "object",
|
|
30506
31175
|
properties: {
|
|
@@ -30556,31 +31225,69 @@ var tools = [
|
|
|
30556
31225
|
}
|
|
30557
31226
|
}
|
|
30558
31227
|
}
|
|
30559
|
-
}
|
|
30560
|
-
];
|
|
30561
|
-
var resources = [
|
|
31228
|
+
},
|
|
30562
31229
|
{
|
|
30563
|
-
|
|
30564
|
-
|
|
30565
|
-
|
|
30566
|
-
|
|
30567
|
-
|
|
30568
|
-
|
|
30569
|
-
|
|
30570
|
-
|
|
30571
|
-
|
|
30572
|
-
|
|
30573
|
-
|
|
30574
|
-
|
|
30575
|
-
|
|
30576
|
-
|
|
30577
|
-
|
|
30578
|
-
|
|
30579
|
-
|
|
30580
|
-
|
|
30581
|
-
|
|
30582
|
-
|
|
30583
|
-
|
|
31230
|
+
name: "maker_pull_runtime_logs",
|
|
31231
|
+
description: "Pull Maker Lua runtime logs once from the remote Maker MCP query_runtime_logs tool and write user_script/server_user_script logs to .maker/logs/runtime/runtime.log. This is a one-shot fixed business flow for AI diagnostics; it does not start a watcher, does not keep a long-running MCP call open, and does not clear local logs.",
|
|
31232
|
+
inputSchema: {
|
|
31233
|
+
type: "object",
|
|
31234
|
+
properties: {
|
|
31235
|
+
target_dir: {
|
|
31236
|
+
type: "string",
|
|
31237
|
+
description: "Optional Maker project directory. Defaults to the MCP process cwd. Pass the user current working directory when it differs from the MCP process cwd."
|
|
31238
|
+
},
|
|
31239
|
+
start_time: {
|
|
31240
|
+
type: "number",
|
|
31241
|
+
description: "Optional Unix seconds cursor. If omitted, the tool uses a fresh local state cursor, otherwise defaults to since_seconds."
|
|
31242
|
+
},
|
|
31243
|
+
since_seconds: {
|
|
31244
|
+
type: "number",
|
|
31245
|
+
description: "Optional fallback lookback window in seconds when no fresh cursor exists. Defaults to 600 seconds and is capped by the remote server."
|
|
31246
|
+
},
|
|
31247
|
+
limit: {
|
|
31248
|
+
type: "number",
|
|
31249
|
+
description: "Optional maximum log entries returned by the remote query."
|
|
31250
|
+
},
|
|
31251
|
+
server_url: {
|
|
31252
|
+
type: "string",
|
|
31253
|
+
description: "Optional remote MCP server URL override. Defaults to the Maker endpoint table for TAPTAP_MCP_ENV."
|
|
31254
|
+
},
|
|
31255
|
+
env: {
|
|
31256
|
+
type: "string",
|
|
31257
|
+
enum: ["rnd", "production"],
|
|
31258
|
+
description: "Remote MCP environment. Defaults to TAPTAP_MCP_ENV."
|
|
31259
|
+
},
|
|
31260
|
+
timeout_ms: {
|
|
31261
|
+
type: "number",
|
|
31262
|
+
description: "Optional remote log query timeout in milliseconds. Defaults to 60 seconds."
|
|
31263
|
+
}
|
|
31264
|
+
}
|
|
31265
|
+
}
|
|
31266
|
+
}
|
|
31267
|
+
];
|
|
31268
|
+
var resources = [
|
|
31269
|
+
{
|
|
31270
|
+
uri: "maker://status",
|
|
31271
|
+
name: "Maker status",
|
|
31272
|
+
description: "Local TapTap Maker project status, including Git, PAT/TapTap auth, project binding, AI dev kit status, and bundled workflow guide document paths. Maker initialization next_step: taptap-maker init.",
|
|
31273
|
+
mimeType: "text/plain"
|
|
31274
|
+
}
|
|
31275
|
+
];
|
|
31276
|
+
async function startMakerMcpServer() {
|
|
31277
|
+
const server = new Server(
|
|
31278
|
+
{
|
|
31279
|
+
name: "taptap-maker",
|
|
31280
|
+
version: VERSION
|
|
31281
|
+
},
|
|
31282
|
+
{
|
|
31283
|
+
capabilities: {
|
|
31284
|
+
tools: {},
|
|
31285
|
+
resources: {}
|
|
31286
|
+
}
|
|
31287
|
+
}
|
|
31288
|
+
);
|
|
31289
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));
|
|
31290
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => ({ resources }));
|
|
30584
31291
|
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
30585
31292
|
const uri = request.params.uri;
|
|
30586
31293
|
if (uri !== "maker://status") {
|
|
@@ -30653,6 +31360,30 @@ async function startMakerMcpServer() {
|
|
|
30653
31360
|
]
|
|
30654
31361
|
};
|
|
30655
31362
|
}
|
|
31363
|
+
if (name === "maker_pull_runtime_logs") {
|
|
31364
|
+
const args = request.params.arguments || {};
|
|
31365
|
+
const proxy = createRemoteProxyContext({
|
|
31366
|
+
targetDir: resolveMakerToolTargetDir(args.target_dir),
|
|
31367
|
+
serverUrl: args.server_url,
|
|
31368
|
+
env: args.env
|
|
31369
|
+
});
|
|
31370
|
+
const result = await pullRuntimeLogs({
|
|
31371
|
+
projectRoot: proxy.projectRoot,
|
|
31372
|
+
projectId: proxy.projectId,
|
|
31373
|
+
startTime: args.start_time,
|
|
31374
|
+
sinceSeconds: args.since_seconds,
|
|
31375
|
+
limit: args.limit,
|
|
31376
|
+
callRemoteRuntimeLogs: (queryArgs) => callRemoteRuntimeLogs(proxy, queryArgs, args.timeout_ms)
|
|
31377
|
+
});
|
|
31378
|
+
return {
|
|
31379
|
+
content: [
|
|
31380
|
+
{
|
|
31381
|
+
type: "text",
|
|
31382
|
+
text: formatRuntimeLogPullResult(result)
|
|
31383
|
+
}
|
|
31384
|
+
]
|
|
31385
|
+
};
|
|
31386
|
+
}
|
|
30656
31387
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown Maker tool: ${name}`);
|
|
30657
31388
|
} catch (error2) {
|
|
30658
31389
|
return {
|
|
@@ -30699,8 +31430,8 @@ async function formatStatus(options = {}) {
|
|
|
30699
31430
|
const git = checkGitEnvironment();
|
|
30700
31431
|
const projectSection = identify.projectId ? [
|
|
30701
31432
|
"目标目录已绑定 Maker 项目。",
|
|
30702
|
-
"
|
|
30703
|
-
"本地 Maker
|
|
31433
|
+
"请继续在当前绑定项目上执行状态、提交、构建等操作;用户明确要求切换或重新拉取项目时,再进入项目选择流程。",
|
|
31434
|
+
"本地 Maker 工作流请参考 taptap-maker-local workflow guide document;CLI 负责初始化/PAT/app/clone,MCP 只保留状态和同步构建。"
|
|
30704
31435
|
].join("\n") : isLikelyAiDialogueDirectory(targetDir) ? formatAiDialogueDirectoryHint(targetDir) : pat ? await formatAutoProjectListFromPat() : formatIdentifyHint();
|
|
30705
31436
|
return [
|
|
30706
31437
|
"TapTap Maker MCP status",
|
|
@@ -30738,7 +31469,7 @@ function formatMakerRemoteSyncSkipped() {
|
|
|
30738
31469
|
"Maker remote sync",
|
|
30739
31470
|
"",
|
|
30740
31471
|
"- status: skipped",
|
|
30741
|
-
"- next_action: 已跳过远端同步检查;如需确认是否需要 pull,请重新读取 maker_status_lite
|
|
31472
|
+
"- next_action: 已跳过远端同步检查;如需确认是否需要 pull,请重新读取 maker_status_lite 并启用远端同步检查。"
|
|
30742
31473
|
].join("\n");
|
|
30743
31474
|
}
|
|
30744
31475
|
async function formatMakerRemoteSyncStatus(projectRoot) {
|
|
@@ -30823,7 +31554,7 @@ function formatAiDialogueDirectoryHint(targetDir) {
|
|
|
30823
31554
|
}
|
|
30824
31555
|
function resolveMakerToolTargetDir(targetDir) {
|
|
30825
31556
|
if (targetDir) {
|
|
30826
|
-
return
|
|
31557
|
+
return path8.resolve(targetDir);
|
|
30827
31558
|
}
|
|
30828
31559
|
return process.cwd();
|
|
30829
31560
|
}
|
|
@@ -30838,13 +31569,16 @@ async function formatAiDevKitStatus(projectRoot) {
|
|
|
30838
31569
|
].join("\n");
|
|
30839
31570
|
}
|
|
30840
31571
|
function formatAiDevKitStatusLines(status, devKitStatus) {
|
|
31572
|
+
const skillStatus = inspectAiDevKitSkillInstallStatus(devKitStatus.targetDir);
|
|
30841
31573
|
return [
|
|
30842
31574
|
"AI dev kit",
|
|
30843
31575
|
"",
|
|
30844
31576
|
`- status: ${status}`,
|
|
30845
31577
|
`- required_entries: ${devKitStatus.requiredEntries.join(", ")}`,
|
|
30846
31578
|
`- present_entries: ${devKitStatus.presentEntries.join(", ") || "(none)"}`,
|
|
30847
|
-
`- missing_entries: ${devKitStatus.missingEntries.join(", ") || "(none)"}
|
|
31579
|
+
`- missing_entries: ${devKitStatus.missingEntries.join(", ") || "(none)"}`,
|
|
31580
|
+
`- skill_install_status: ${skillStatus.status}`,
|
|
31581
|
+
`- skill_install_summary: ${skillStatus.summary}`
|
|
30848
31582
|
];
|
|
30849
31583
|
}
|
|
30850
31584
|
async function formatAutoProjectListFromPat() {
|
|
@@ -30852,7 +31586,8 @@ async function formatAutoProjectListFromPat() {
|
|
|
30852
31586
|
const projects = await listMakerProjects();
|
|
30853
31587
|
return [
|
|
30854
31588
|
"本地已有 Maker PAT,当前目录尚未绑定 Maker 项目。",
|
|
30855
|
-
"当前目录未绑定时,先展示下面的 Maker Apps
|
|
31589
|
+
"当前目录未绑定时,先展示下面的 Maker Apps 预览和总数;选择、解释和 clone 顺序请参考 taptap-maker-local workflow guide document。",
|
|
31590
|
+
"用户选择 app 后,next_step: 执行 `taptap-maker init`。",
|
|
30856
31591
|
"",
|
|
30857
31592
|
formatStatusProjectList(projects)
|
|
30858
31593
|
].join("\n");
|
|
@@ -30897,25 +31632,26 @@ function formatStatusProjectList(projects) {
|
|
|
30897
31632
|
"",
|
|
30898
31633
|
hiddenCount > 0 ? `为了保持友好的可读性,默认最多展示 ${visibleProjects.length} 个 app;如需完整列表,可以选择显示全部。` : "已显示全部 app;请询问用户选择。",
|
|
30899
31634
|
hiddenCount > 0 ? "如需完整列表,请运行 taptap-maker apps --json 查看全部 app。" : void 0,
|
|
30900
|
-
"AI 展示建议:如果聊天或客户端宽度足够,可把 app 预览整理成两列紧凑布局;每个 app 保留序号、app_id、名称,以及可用的最近活跃时间或 user_id
|
|
31635
|
+
"AI 展示建议:如果聊天或客户端宽度足够,可把 app 预览整理成两列紧凑布局;每个 app 保留序号、app_id、名称,以及可用的最近活跃时间或 user_id。窄屏保持单列。选择 app 前先获取用户确认。",
|
|
30901
31636
|
"",
|
|
30902
31637
|
...visibleProjects.map(
|
|
30903
31638
|
(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}` : ""}`
|
|
30904
31639
|
),
|
|
30905
31640
|
"",
|
|
30906
|
-
"
|
|
30907
|
-
"
|
|
31641
|
+
"当前目录未绑定且用户要初始化或 clone 时,让用户选择 app 并继续 taptap-maker init。",
|
|
31642
|
+
"用户回复序号或 app_id 后,next_step: 执行 `taptap-maker init`,或让已经启动的 `taptap-maker init` 交互继续读取该选择。",
|
|
31643
|
+
"如果当前目录已绑定 Maker 项目,这个列表仅作账号项目参考;请继续当前项目。用户明确要求切换或重新 clone 时,再进入项目选择流程。"
|
|
30908
31644
|
].filter((line) => line !== void 0).join("\n");
|
|
30909
31645
|
}
|
|
30910
31646
|
function formatClonePartialStateLines(targetDir) {
|
|
30911
|
-
const resolvedTargetDir =
|
|
31647
|
+
const resolvedTargetDir = path8.resolve(targetDir);
|
|
30912
31648
|
const identify = identifyMakerProject({ cwd: resolvedTargetDir });
|
|
30913
31649
|
const gitStatus = inspectMakerDirectoryGitStatus(resolvedTargetDir);
|
|
30914
31650
|
const devKitStatus = inspectAiDevKit(resolvedTargetDir);
|
|
30915
|
-
const stagedDevKitGitignorePath =
|
|
31651
|
+
const stagedDevKitGitignorePath = path8.join(resolvedTargetDir, DEV_KIT_GITIGNORE_STAGING_FILE);
|
|
30916
31652
|
const projectBound = Boolean(identify.projectId);
|
|
30917
31653
|
const gitInitialized = Boolean(
|
|
30918
|
-
gitStatus.isOwnGitRoot ||
|
|
31654
|
+
gitStatus.isOwnGitRoot || fs7.existsSync(path8.join(resolvedTargetDir, ".git"))
|
|
30919
31655
|
);
|
|
30920
31656
|
const safeToRetry = !projectBound;
|
|
30921
31657
|
return [
|
|
@@ -30929,9 +31665,9 @@ function formatClonePartialStateLines(targetDir) {
|
|
|
30929
31665
|
identify.configPath ? `- config: ${identify.configPath}` : "",
|
|
30930
31666
|
`- ai_dev_kit_present: ${devKitStatus.ready ? "yes" : "no"}`,
|
|
30931
31667
|
`- ai_dev_kit_missing_entries: ${devKitStatus.missingEntries.join(", ") || "(none)"}`,
|
|
30932
|
-
`- staged_dev_kit_gitignore: ${
|
|
31668
|
+
`- staged_dev_kit_gitignore: ${fs7.existsSync(stagedDevKitGitignorePath) ? "yes" : "no"}`,
|
|
30933
31669
|
`- safe_to_retry: ${safeToRetry ? "yes" : "no"}`,
|
|
30934
|
-
safeToRetry ? "- next_step: 可以直接重试 taptap-maker init;如果连续失败,建议换一个全新的独立目录重新 clone。" : "- next_step: 当前目录已经有 Maker 绑定信息;先运行 taptap-maker doctor 或读取 maker://status
|
|
31670
|
+
safeToRetry ? "- next_step: 可以直接重试 taptap-maker init;如果连续失败,建议换一个全新的独立目录重新 clone。" : "- next_step: 当前目录已经有 Maker 绑定信息;先运行 taptap-maker doctor 或读取 maker://status 确认状态。"
|
|
30935
31671
|
].filter(Boolean);
|
|
30936
31672
|
}
|
|
30937
31673
|
function createRemoteProxyContext(options) {
|
|
@@ -31000,17 +31736,17 @@ function createRemoteProxyContext(options) {
|
|
|
31000
31736
|
}
|
|
31001
31737
|
function resolveLocalProxyBundle(options) {
|
|
31002
31738
|
const currentModuleUrl = (options == null ? void 0 : options.currentModuleUrl) || (typeof __MAKER_BUNDLE_URL__ !== "undefined" ? __MAKER_BUNDLE_URL__ : void 0);
|
|
31003
|
-
const currentModuleDir = currentModuleUrl ?
|
|
31739
|
+
const currentModuleDir = currentModuleUrl ? path8.dirname(fileURLToPath2(currentModuleUrl)) : "";
|
|
31004
31740
|
const makerEntry = (options == null ? void 0 : options.makerEntry) ?? process.argv[1];
|
|
31005
|
-
const makerEntryDir = makerEntry ?
|
|
31741
|
+
const makerEntryDir = makerEntry ? path8.dirname(path8.resolve(makerEntry)) : "";
|
|
31006
31742
|
const cwd = (options == null ? void 0 : options.cwd) ?? process.cwd();
|
|
31007
31743
|
const candidates = [
|
|
31008
|
-
currentModuleDir ?
|
|
31009
|
-
makerEntryDir ?
|
|
31010
|
-
|
|
31744
|
+
currentModuleDir ? path8.join(currentModuleDir, "proxy.js") : "",
|
|
31745
|
+
makerEntryDir ? path8.join(makerEntryDir, "..", "dist", "proxy.js") : "",
|
|
31746
|
+
path8.resolve(cwd, "dist", "proxy.js")
|
|
31011
31747
|
].filter(Boolean);
|
|
31012
31748
|
for (const candidate of candidates) {
|
|
31013
|
-
if (
|
|
31749
|
+
if (fs7.existsSync(candidate)) {
|
|
31014
31750
|
return candidate;
|
|
31015
31751
|
}
|
|
31016
31752
|
}
|
|
@@ -31098,6 +31834,13 @@ function formatMakerAppWebUrl(projectId, env) {
|
|
|
31098
31834
|
const makerEnv = env === "rnd" || env === "production" ? env : void 0;
|
|
31099
31835
|
return `${getMakerWebUrl(makerEnv)}/app/${encodeURIComponent(projectId)}`;
|
|
31100
31836
|
}
|
|
31837
|
+
var RemoteBuildFailedError = class extends Error {
|
|
31838
|
+
constructor(buildResult) {
|
|
31839
|
+
super(buildResult.resultText);
|
|
31840
|
+
this.name = "RemoteBuildFailedError";
|
|
31841
|
+
this.buildResult = buildResult;
|
|
31842
|
+
}
|
|
31843
|
+
};
|
|
31101
31844
|
async function buildCurrentDirectory(options) {
|
|
31102
31845
|
var _a2;
|
|
31103
31846
|
const localChanges = await readMakerProjectLocalChanges(options.targetDir);
|
|
@@ -31140,11 +31883,27 @@ async function buildCurrentDirectory(options) {
|
|
|
31140
31883
|
submitResult
|
|
31141
31884
|
};
|
|
31142
31885
|
}
|
|
31143
|
-
|
|
31886
|
+
try {
|
|
31887
|
+
return await runRemoteBuildCurrentDirectory(options, options.targetDir);
|
|
31888
|
+
} catch (error2) {
|
|
31889
|
+
if (error2 instanceof RemoteBuildFailedError) {
|
|
31890
|
+
return {
|
|
31891
|
+
mode: "remote_build_failed",
|
|
31892
|
+
projectRoot: error2.buildResult.projectRoot,
|
|
31893
|
+
projectId: error2.buildResult.projectId,
|
|
31894
|
+
buildResult: error2.buildResult,
|
|
31895
|
+
buildFailure: toMakerBuildFailure(error2)
|
|
31896
|
+
};
|
|
31897
|
+
}
|
|
31898
|
+
throw error2;
|
|
31899
|
+
}
|
|
31144
31900
|
}
|
|
31145
31901
|
async function runRemoteBuildCurrentDirectory(options, targetDir) {
|
|
31146
31902
|
if (options.callRemoteBuild) {
|
|
31147
|
-
return options.callRemoteBuild(targetDir)
|
|
31903
|
+
return attachBuildSuccessSideEffects(await options.callRemoteBuild(targetDir), {
|
|
31904
|
+
refreshPreview: options.refreshPreview || skipPreviewRefresh,
|
|
31905
|
+
startRuntimeLogWatch: options.startRuntimeLogWatch
|
|
31906
|
+
});
|
|
31148
31907
|
}
|
|
31149
31908
|
const proxy = createRemoteProxyContext({
|
|
31150
31909
|
targetDir,
|
|
@@ -31190,22 +31949,446 @@ async function runRemoteBuildCurrentDirectory(options, targetDir) {
|
|
|
31190
31949
|
}
|
|
31191
31950
|
}
|
|
31192
31951
|
);
|
|
31952
|
+
if (isRemoteToolError(result)) {
|
|
31953
|
+
throw new Error(formatRemoteToolResult(result));
|
|
31954
|
+
}
|
|
31955
|
+
return attachBuildSuccessSideEffects(
|
|
31956
|
+
{
|
|
31957
|
+
mode: "remote_build",
|
|
31958
|
+
projectRoot: proxy.projectRoot,
|
|
31959
|
+
projectId: proxy.projectId,
|
|
31960
|
+
projectPath: proxy.projectPath,
|
|
31961
|
+
serverUrl: proxy.serverUrl,
|
|
31962
|
+
env: proxy.env,
|
|
31963
|
+
makerUrl: formatMakerAppWebUrl(proxy.projectId, proxy.env),
|
|
31964
|
+
timeoutMs,
|
|
31965
|
+
buildArgs,
|
|
31966
|
+
resultText: formatRemoteToolResult(result)
|
|
31967
|
+
},
|
|
31968
|
+
{
|
|
31969
|
+
refreshPreview: options.refreshPreview,
|
|
31970
|
+
startRuntimeLogWatch: options.startRuntimeLogWatch || startRuntimeLogWatch
|
|
31971
|
+
}
|
|
31972
|
+
);
|
|
31973
|
+
} finally {
|
|
31974
|
+
await client.close();
|
|
31975
|
+
}
|
|
31976
|
+
}
|
|
31977
|
+
async function attachBuildSuccessSideEffects(buildResult, options) {
|
|
31978
|
+
if (isRemoteBuildFailureResult(buildResult)) {
|
|
31979
|
+
throw new RemoteBuildFailedError(buildResult);
|
|
31980
|
+
}
|
|
31981
|
+
const withPreview = await attachPreviewRefresh(buildResult, options.refreshPreview);
|
|
31982
|
+
if (!options.startRuntimeLogWatch) {
|
|
31983
|
+
return withPreview;
|
|
31984
|
+
}
|
|
31985
|
+
return attachRuntimeLogWatch(withPreview, options.startRuntimeLogWatch);
|
|
31986
|
+
}
|
|
31987
|
+
function isRemoteToolError(result) {
|
|
31988
|
+
return Boolean(result && typeof result === "object" && result.isError);
|
|
31989
|
+
}
|
|
31990
|
+
function isRemoteBuildFailureResult(buildResult) {
|
|
31991
|
+
return /\bBUILD FAILED\b/i.test(buildResult.resultText);
|
|
31992
|
+
}
|
|
31993
|
+
async function attachPreviewRefresh(buildResult, refreshPreview = refreshMakerPreview) {
|
|
31994
|
+
try {
|
|
31193
31995
|
return {
|
|
31194
|
-
|
|
31195
|
-
|
|
31196
|
-
|
|
31197
|
-
|
|
31198
|
-
|
|
31199
|
-
|
|
31200
|
-
|
|
31201
|
-
|
|
31202
|
-
|
|
31203
|
-
|
|
31996
|
+
...buildResult,
|
|
31997
|
+
previewRefresh: await refreshPreview(buildResult)
|
|
31998
|
+
};
|
|
31999
|
+
} catch (error2) {
|
|
32000
|
+
return {
|
|
32001
|
+
...buildResult,
|
|
32002
|
+
previewRefresh: {
|
|
32003
|
+
ok: false,
|
|
32004
|
+
status: 0,
|
|
32005
|
+
url: "",
|
|
32006
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
32007
|
+
}
|
|
32008
|
+
};
|
|
32009
|
+
}
|
|
32010
|
+
}
|
|
32011
|
+
async function skipPreviewRefresh(buildResult) {
|
|
32012
|
+
return {
|
|
32013
|
+
ok: false,
|
|
32014
|
+
status: 0,
|
|
32015
|
+
url: "",
|
|
32016
|
+
error: `preview refresh skipped for injected remote build: ${buildResult.projectId}`
|
|
32017
|
+
};
|
|
32018
|
+
}
|
|
32019
|
+
async function attachRuntimeLogWatch(buildResult, startWatch) {
|
|
32020
|
+
try {
|
|
32021
|
+
return {
|
|
32022
|
+
...buildResult,
|
|
32023
|
+
runtimeLogWatch: await startWatch(buildResult)
|
|
32024
|
+
};
|
|
32025
|
+
} catch (error2) {
|
|
32026
|
+
return {
|
|
32027
|
+
...buildResult,
|
|
32028
|
+
runtimeLogWatch: {
|
|
32029
|
+
started: false,
|
|
32030
|
+
command: formatRuntimeLogWatchCommand(buildResult).text,
|
|
32031
|
+
runtimeLog: getRuntimeLogFilePath(buildResult.projectRoot),
|
|
32032
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
32033
|
+
}
|
|
32034
|
+
};
|
|
32035
|
+
}
|
|
32036
|
+
}
|
|
32037
|
+
async function startRuntimeLogWatch(buildResult) {
|
|
32038
|
+
const runtimeDir = path8.join(buildResult.projectRoot, ".maker", "logs", "runtime");
|
|
32039
|
+
fs7.mkdirSync(runtimeDir, { recursive: true });
|
|
32040
|
+
const stdoutLog = path8.join(runtimeDir, "watcher.out.log");
|
|
32041
|
+
const stderrLog = path8.join(runtimeDir, "watcher.err.log");
|
|
32042
|
+
const pidFile = path8.join(runtimeDir, "watcher.pid");
|
|
32043
|
+
const previous = stopExistingRuntimeLogWatcher(pidFile);
|
|
32044
|
+
const outFd = fs7.openSync(stdoutLog, "a");
|
|
32045
|
+
const errFd = fs7.openSync(stderrLog, "a");
|
|
32046
|
+
const command = formatRuntimeLogWatchCommand(buildResult);
|
|
32047
|
+
if (previous.previousStopError) {
|
|
32048
|
+
fs7.closeSync(outFd);
|
|
32049
|
+
fs7.closeSync(errFd);
|
|
32050
|
+
return {
|
|
32051
|
+
started: false,
|
|
32052
|
+
command: command.text,
|
|
32053
|
+
runtimeLog: getRuntimeLogFilePath(buildResult.projectRoot),
|
|
32054
|
+
stdoutLog,
|
|
32055
|
+
stderrLog,
|
|
32056
|
+
pidFile,
|
|
32057
|
+
...previous,
|
|
32058
|
+
error: previous.previousStopError
|
|
32059
|
+
};
|
|
32060
|
+
}
|
|
32061
|
+
try {
|
|
32062
|
+
const child = spawn4(command.command, command.args, {
|
|
32063
|
+
cwd: buildResult.projectRoot,
|
|
32064
|
+
detached: true,
|
|
32065
|
+
env: mergeStringEnv(process.env, { TAPTAP_MCP_ENV: buildResult.env }),
|
|
32066
|
+
stdio: ["ignore", outFd, errFd],
|
|
32067
|
+
windowsHide: true
|
|
32068
|
+
});
|
|
32069
|
+
const spawnError = await waitForSpawnError(child);
|
|
32070
|
+
if (spawnError) {
|
|
32071
|
+
return {
|
|
32072
|
+
started: false,
|
|
32073
|
+
command: command.text,
|
|
32074
|
+
runtimeLog: getRuntimeLogFilePath(buildResult.projectRoot),
|
|
32075
|
+
stdoutLog,
|
|
32076
|
+
stderrLog,
|
|
32077
|
+
pidFile,
|
|
32078
|
+
...previous,
|
|
32079
|
+
error: spawnError.message
|
|
32080
|
+
};
|
|
32081
|
+
}
|
|
32082
|
+
if (!child.pid) {
|
|
32083
|
+
return {
|
|
32084
|
+
started: false,
|
|
32085
|
+
command: command.text,
|
|
32086
|
+
runtimeLog: getRuntimeLogFilePath(buildResult.projectRoot),
|
|
32087
|
+
stdoutLog,
|
|
32088
|
+
stderrLog,
|
|
32089
|
+
pidFile,
|
|
32090
|
+
...previous,
|
|
32091
|
+
error: "runtime log watcher process did not report a pid"
|
|
32092
|
+
};
|
|
32093
|
+
}
|
|
32094
|
+
child.once("error", () => void 0);
|
|
32095
|
+
child.unref();
|
|
32096
|
+
writeRuntimeLogWatcherPidFile(pidFile, {
|
|
32097
|
+
pid: child.pid,
|
|
32098
|
+
command: command.text,
|
|
32099
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
32100
|
+
});
|
|
32101
|
+
return {
|
|
32102
|
+
started: true,
|
|
32103
|
+
command: command.text,
|
|
32104
|
+
runtimeLog: getRuntimeLogFilePath(buildResult.projectRoot),
|
|
32105
|
+
stdoutLog,
|
|
32106
|
+
stderrLog,
|
|
32107
|
+
pidFile,
|
|
32108
|
+
pid: child.pid,
|
|
32109
|
+
...previous
|
|
31204
32110
|
};
|
|
31205
32111
|
} finally {
|
|
31206
|
-
|
|
32112
|
+
fs7.closeSync(outFd);
|
|
32113
|
+
fs7.closeSync(errFd);
|
|
32114
|
+
}
|
|
32115
|
+
}
|
|
32116
|
+
function stopExistingRuntimeLogWatcher(pidFile, options = {}) {
|
|
32117
|
+
if (!fs7.existsSync(pidFile)) {
|
|
32118
|
+
return {};
|
|
32119
|
+
}
|
|
32120
|
+
const pidState = readRuntimeLogWatcherPidState(pidFile);
|
|
32121
|
+
const pid = pidState == null ? void 0 : pidState.pid;
|
|
32122
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
32123
|
+
fs7.rmSync(pidFile, { force: true });
|
|
32124
|
+
return {};
|
|
32125
|
+
}
|
|
32126
|
+
try {
|
|
32127
|
+
process.kill(pid, 0);
|
|
32128
|
+
const processCommand = (options.getProcessCommand || getProcessCommand)(pid);
|
|
32129
|
+
const verifiedCommand = getVerifiedRuntimeLogWatcherCommand(processCommand, pidState);
|
|
32130
|
+
if (!verifiedCommand) {
|
|
32131
|
+
fs7.rmSync(pidFile, { force: true });
|
|
32132
|
+
return {
|
|
32133
|
+
previousPid: pid,
|
|
32134
|
+
previousStopped: false,
|
|
32135
|
+
previousStopError: processCommand ? `process ${pid} does not look like a Maker log watcher: ${processCommand}` : `process ${pid} could not be verified as a Maker log watcher`
|
|
32136
|
+
};
|
|
32137
|
+
}
|
|
32138
|
+
process.kill(pid, "SIGTERM");
|
|
32139
|
+
const stopped = (options.waitForExit || waitForProcessExit)(pid, WATCHER_STOP_TIMEOUT_MS);
|
|
32140
|
+
if (stopped) {
|
|
32141
|
+
fs7.rmSync(pidFile, { force: true });
|
|
32142
|
+
return { previousPid: pid, previousStopped: true };
|
|
32143
|
+
}
|
|
32144
|
+
return {
|
|
32145
|
+
previousPid: pid,
|
|
32146
|
+
previousStopped: false,
|
|
32147
|
+
previousStopError: `process ${pid} did not exit after SIGTERM within ${WATCHER_STOP_TIMEOUT_MS}ms`
|
|
32148
|
+
};
|
|
32149
|
+
} catch (error2) {
|
|
32150
|
+
fs7.rmSync(pidFile, { force: true });
|
|
32151
|
+
const code = error2 && typeof error2 === "object" && "code" in error2 ? String(error2.code) : "";
|
|
32152
|
+
if (code === "ESRCH") {
|
|
32153
|
+
return { previousPid: pid, previousStopped: false };
|
|
32154
|
+
}
|
|
32155
|
+
return {
|
|
32156
|
+
previousPid: pid,
|
|
32157
|
+
previousStopped: false,
|
|
32158
|
+
previousStopError: error2 instanceof Error ? error2.message : String(error2)
|
|
32159
|
+
};
|
|
32160
|
+
}
|
|
32161
|
+
}
|
|
32162
|
+
function readRuntimeLogWatcherPidState(pidFile) {
|
|
32163
|
+
const raw = fs7.readFileSync(pidFile, "utf8").trim();
|
|
32164
|
+
if (!raw) {
|
|
32165
|
+
return null;
|
|
32166
|
+
}
|
|
32167
|
+
try {
|
|
32168
|
+
const parsed = JSON.parse(raw);
|
|
32169
|
+
if (typeof parsed === "number") {
|
|
32170
|
+
return Number.isInteger(parsed) && parsed > 0 ? { pid: parsed, legacy: true } : null;
|
|
32171
|
+
}
|
|
32172
|
+
return typeof parsed.pid === "number" ? parsed : null;
|
|
32173
|
+
} catch {
|
|
32174
|
+
const pid = Number(raw);
|
|
32175
|
+
return Number.isInteger(pid) && pid > 0 ? { pid, legacy: true } : null;
|
|
32176
|
+
}
|
|
32177
|
+
}
|
|
32178
|
+
function writeRuntimeLogWatcherPidFile(pidFile, state) {
|
|
32179
|
+
fs7.writeFileSync(pidFile, `${JSON.stringify(state, null, 2)}
|
|
32180
|
+
`, "utf8");
|
|
32181
|
+
}
|
|
32182
|
+
function getProcessCommand(pid) {
|
|
32183
|
+
if (process.platform === "win32") {
|
|
32184
|
+
return void 0;
|
|
32185
|
+
}
|
|
32186
|
+
try {
|
|
32187
|
+
return execFileSync("ps", ["-p", String(pid), "-o", "command="], {
|
|
32188
|
+
encoding: "utf8",
|
|
32189
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
32190
|
+
}).trim();
|
|
32191
|
+
} catch {
|
|
32192
|
+
return void 0;
|
|
32193
|
+
}
|
|
32194
|
+
}
|
|
32195
|
+
function isRuntimeLogWatcherProcess(command) {
|
|
32196
|
+
return Boolean(command && WATCHER_PROCESS_PATTERN.test(command));
|
|
32197
|
+
}
|
|
32198
|
+
function getVerifiedRuntimeLogWatcherCommand(processCommand, pidState) {
|
|
32199
|
+
if (isRuntimeLogWatcherProcess(processCommand)) {
|
|
32200
|
+
return processCommand;
|
|
32201
|
+
}
|
|
32202
|
+
if (!processCommand && !pidState.legacy && isRuntimeLogWatcherProcess(pidState.command)) {
|
|
32203
|
+
return pidState.command;
|
|
32204
|
+
}
|
|
32205
|
+
return void 0;
|
|
32206
|
+
}
|
|
32207
|
+
function waitForProcessExit(pid, timeoutMs) {
|
|
32208
|
+
const deadline = Date.now() + timeoutMs;
|
|
32209
|
+
while (Date.now() < deadline) {
|
|
32210
|
+
try {
|
|
32211
|
+
process.kill(pid, 0);
|
|
32212
|
+
} catch {
|
|
32213
|
+
return true;
|
|
32214
|
+
}
|
|
32215
|
+
sleepSync(50);
|
|
32216
|
+
}
|
|
32217
|
+
try {
|
|
32218
|
+
process.kill(pid, 0);
|
|
32219
|
+
return false;
|
|
32220
|
+
} catch {
|
|
32221
|
+
return true;
|
|
31207
32222
|
}
|
|
31208
32223
|
}
|
|
32224
|
+
function sleepSync(ms) {
|
|
32225
|
+
const buffer = new SharedArrayBuffer(4);
|
|
32226
|
+
Atomics.wait(new Int32Array(buffer), 0, 0, ms);
|
|
32227
|
+
}
|
|
32228
|
+
function waitForSpawnError(child) {
|
|
32229
|
+
return new Promise((resolve) => {
|
|
32230
|
+
let done = false;
|
|
32231
|
+
const finish = (error2) => {
|
|
32232
|
+
if (done) {
|
|
32233
|
+
return;
|
|
32234
|
+
}
|
|
32235
|
+
done = true;
|
|
32236
|
+
child.off("error", finish);
|
|
32237
|
+
resolve(error2);
|
|
32238
|
+
};
|
|
32239
|
+
child.once("error", finish);
|
|
32240
|
+
setTimeout(() => finish(), 50);
|
|
32241
|
+
});
|
|
32242
|
+
}
|
|
32243
|
+
function formatRuntimeLogWatchCommand(buildResult) {
|
|
32244
|
+
const args = [
|
|
32245
|
+
resolveMakerCliEntry(),
|
|
32246
|
+
"logs",
|
|
32247
|
+
"watch",
|
|
32248
|
+
"--target-dir",
|
|
32249
|
+
buildResult.projectRoot,
|
|
32250
|
+
"--reset",
|
|
32251
|
+
"--interval",
|
|
32252
|
+
"5s",
|
|
32253
|
+
"--env",
|
|
32254
|
+
buildResult.env,
|
|
32255
|
+
"--server-url",
|
|
32256
|
+
buildResult.serverUrl
|
|
32257
|
+
];
|
|
32258
|
+
return {
|
|
32259
|
+
command: process.execPath,
|
|
32260
|
+
args,
|
|
32261
|
+
text: formatLocalShellCommand([process.execPath, ...args])
|
|
32262
|
+
};
|
|
32263
|
+
}
|
|
32264
|
+
function resolveMakerCliEntry() {
|
|
32265
|
+
return process.argv[1] || path8.resolve(process.cwd(), "dist", "maker.js");
|
|
32266
|
+
}
|
|
32267
|
+
function getRuntimeLogFilePath(projectRoot) {
|
|
32268
|
+
return path8.join(projectRoot, ".maker", "logs", "runtime", "runtime.log");
|
|
32269
|
+
}
|
|
32270
|
+
async function refreshMakerPreview(buildResult) {
|
|
32271
|
+
const makerEnv = buildResult.env === "rnd" || buildResult.env === "production" ? buildResult.env : void 0;
|
|
32272
|
+
const apiBase = requireMakerEndpoint("apiBase", getMakerEndpoints(makerEnv).apiBase, makerEnv);
|
|
32273
|
+
const url2 = `${apiBase.replace(/\/$/, "")}/apps/${encodeURIComponent(
|
|
32274
|
+
buildResult.projectId
|
|
32275
|
+
)}/preview-refresh`;
|
|
32276
|
+
const pat = loadPat();
|
|
32277
|
+
if (!(pat == null ? void 0 : pat.token)) {
|
|
32278
|
+
return {
|
|
32279
|
+
ok: false,
|
|
32280
|
+
status: 0,
|
|
32281
|
+
url: url2,
|
|
32282
|
+
error: "Maker PAT not found. Run taptap-maker pat set and paste a Maker PAT first."
|
|
32283
|
+
};
|
|
32284
|
+
}
|
|
32285
|
+
const controller = new AbortController();
|
|
32286
|
+
const timeout = setTimeout(() => {
|
|
32287
|
+
controller.abort();
|
|
32288
|
+
}, PREVIEW_REFRESH_TIMEOUT_MS);
|
|
32289
|
+
try {
|
|
32290
|
+
const response = await fetch(url2, {
|
|
32291
|
+
method: "POST",
|
|
32292
|
+
headers: {
|
|
32293
|
+
Authorization: `Bearer ${pat.token}`,
|
|
32294
|
+
"Content-Type": "application/json"
|
|
32295
|
+
},
|
|
32296
|
+
body: "{}",
|
|
32297
|
+
signal: controller.signal
|
|
32298
|
+
});
|
|
32299
|
+
const responseText = await response.text();
|
|
32300
|
+
return {
|
|
32301
|
+
ok: response.ok,
|
|
32302
|
+
status: response.status,
|
|
32303
|
+
url: url2,
|
|
32304
|
+
...responseText ? { responseText: responseText.slice(0, 2e3) } : {}
|
|
32305
|
+
};
|
|
32306
|
+
} catch (error2) {
|
|
32307
|
+
return {
|
|
32308
|
+
ok: false,
|
|
32309
|
+
status: 0,
|
|
32310
|
+
url: url2,
|
|
32311
|
+
error: error2 instanceof Error && error2.name === "AbortError" ? `preview refresh timed out after ${PREVIEW_REFRESH_TIMEOUT_MS}ms` : error2 instanceof Error ? error2.message : String(error2)
|
|
32312
|
+
};
|
|
32313
|
+
} finally {
|
|
32314
|
+
clearTimeout(timeout);
|
|
32315
|
+
}
|
|
32316
|
+
}
|
|
32317
|
+
async function callRemoteRuntimeLogs(proxy, args, timeoutMs = 60 * 1e3) {
|
|
32318
|
+
const runtimeLogClient = createRemoteRuntimeLogClient(proxy, timeoutMs);
|
|
32319
|
+
try {
|
|
32320
|
+
return await runtimeLogClient.call(args);
|
|
32321
|
+
} finally {
|
|
32322
|
+
await runtimeLogClient.close();
|
|
32323
|
+
}
|
|
32324
|
+
}
|
|
32325
|
+
function createRemoteRuntimeLogClient(proxy, timeoutMs = 60 * 1e3, options = {}) {
|
|
32326
|
+
let client;
|
|
32327
|
+
const createTransport = options.createTransport || (() => new HiddenStdioClientTransport({
|
|
32328
|
+
command: proxy.command,
|
|
32329
|
+
args: proxy.args,
|
|
32330
|
+
env: mergeStringEnv(process.env, proxy.envVars),
|
|
32331
|
+
stderr: "pipe"
|
|
32332
|
+
}));
|
|
32333
|
+
const createClient = options.createClient || (() => new Client(
|
|
32334
|
+
{
|
|
32335
|
+
name: "taptap-maker-runtime-log-forwarder",
|
|
32336
|
+
version: VERSION
|
|
32337
|
+
},
|
|
32338
|
+
{
|
|
32339
|
+
capabilities: {}
|
|
32340
|
+
}
|
|
32341
|
+
));
|
|
32342
|
+
const ensureClient = async () => {
|
|
32343
|
+
if (client) {
|
|
32344
|
+
return client;
|
|
32345
|
+
}
|
|
32346
|
+
const nextClient = createClient();
|
|
32347
|
+
await nextClient.connect(createTransport());
|
|
32348
|
+
client = nextClient;
|
|
32349
|
+
return nextClient;
|
|
32350
|
+
};
|
|
32351
|
+
const close = async () => {
|
|
32352
|
+
const activeClient = client;
|
|
32353
|
+
client = void 0;
|
|
32354
|
+
if (activeClient) {
|
|
32355
|
+
await activeClient.close();
|
|
32356
|
+
}
|
|
32357
|
+
};
|
|
32358
|
+
return {
|
|
32359
|
+
call: async (args) => {
|
|
32360
|
+
const activeClient = await ensureClient();
|
|
32361
|
+
let result;
|
|
32362
|
+
try {
|
|
32363
|
+
result = await activeClient.callTool(
|
|
32364
|
+
{
|
|
32365
|
+
name: "query_runtime_logs",
|
|
32366
|
+
arguments: { ...args }
|
|
32367
|
+
},
|
|
32368
|
+
void 0,
|
|
32369
|
+
{
|
|
32370
|
+
timeout: timeoutMs
|
|
32371
|
+
}
|
|
32372
|
+
);
|
|
32373
|
+
} catch (error2) {
|
|
32374
|
+
await close();
|
|
32375
|
+
throw error2;
|
|
32376
|
+
}
|
|
32377
|
+
try {
|
|
32378
|
+
return normalizeRuntimeLogQueryResult(result);
|
|
32379
|
+
} catch (error2) {
|
|
32380
|
+
const rawPath = writeRuntimeLogRawResponse(proxy.projectRoot, result);
|
|
32381
|
+
throw new Error(
|
|
32382
|
+
[
|
|
32383
|
+
error2 instanceof Error ? error2.message : String(error2),
|
|
32384
|
+
`Raw query_runtime_logs response saved to ${rawPath}`
|
|
32385
|
+
].join(" ")
|
|
32386
|
+
);
|
|
32387
|
+
}
|
|
32388
|
+
},
|
|
32389
|
+
close
|
|
32390
|
+
};
|
|
32391
|
+
}
|
|
31209
32392
|
function toMakerBuildFailure(error2) {
|
|
31210
32393
|
return {
|
|
31211
32394
|
name: error2 instanceof Error ? error2.name : typeof error2,
|
|
@@ -31221,7 +32404,7 @@ function createBuildArgs(projectRoot, options) {
|
|
|
31221
32404
|
if (options.scriptsPath) {
|
|
31222
32405
|
buildArgs.scriptsPath = options.scriptsPath;
|
|
31223
32406
|
}
|
|
31224
|
-
if (!options.entry && !options.scriptsPath && !options.entryClient && !options.entryServer && !options.multiplayer &&
|
|
32407
|
+
if (!options.entry && !options.scriptsPath && !options.entryClient && !options.entryServer && !options.multiplayer && fs7.existsSync(path8.join(projectRoot, "scripts", "main.lua"))) {
|
|
31225
32408
|
buildArgs.entry = "main.lua";
|
|
31226
32409
|
buildArgs.scriptsPath = "scripts";
|
|
31227
32410
|
}
|
|
@@ -31233,7 +32416,7 @@ function createBuildArgs(projectRoot, options) {
|
|
|
31233
32416
|
}
|
|
31234
32417
|
if (options.multiplayer) {
|
|
31235
32418
|
buildArgs.multiplayer = options.multiplayer;
|
|
31236
|
-
} else if (!
|
|
32419
|
+
} else if (!fs7.existsSync(path8.join(projectRoot, ".project", "settings.json"))) {
|
|
31237
32420
|
buildArgs.multiplayer = { enabled: false };
|
|
31238
32421
|
}
|
|
31239
32422
|
return buildArgs;
|
|
@@ -31268,6 +32451,26 @@ function formatRemoteToolResult(result) {
|
|
|
31268
32451
|
}).join("\n");
|
|
31269
32452
|
}
|
|
31270
32453
|
function formatBuildResult(result, progressSummary) {
|
|
32454
|
+
if (result.mode === "remote_build_failed") {
|
|
32455
|
+
return [
|
|
32456
|
+
"✗ Remote Maker build failed",
|
|
32457
|
+
"",
|
|
32458
|
+
`- project_root: ${result.projectRoot}`,
|
|
32459
|
+
`- project_id: ${result.projectId}`,
|
|
32460
|
+
`- maker_url: ${result.buildResult.makerUrl || formatMakerAppWebUrl(result.buildResult.projectId, result.buildResult.env)}`,
|
|
32461
|
+
`- project_path: ${result.buildResult.projectPath}`,
|
|
32462
|
+
`- server_url: ${result.buildResult.serverUrl}`,
|
|
32463
|
+
`- env: ${result.buildResult.env}`,
|
|
32464
|
+
`- timeout_ms: ${result.buildResult.timeoutMs}`,
|
|
32465
|
+
`- build_args: ${JSON.stringify(result.buildResult.buildArgs)}`,
|
|
32466
|
+
...formatProgressSummary(progressSummary),
|
|
32467
|
+
"",
|
|
32468
|
+
...formatMakerBuildFailureLines(result.buildFailure),
|
|
32469
|
+
"",
|
|
32470
|
+
"remote_result:",
|
|
32471
|
+
indent(result.buildResult.resultText)
|
|
32472
|
+
].filter(Boolean).join("\n");
|
|
32473
|
+
}
|
|
31271
32474
|
if (result.mode === "submit_failed_before_build") {
|
|
31272
32475
|
return [
|
|
31273
32476
|
result.submitResult.pushed ? "✓ Maker project submitted; remote build was not started" : result.submitResult.status === "clean" ? "Maker project has no changes to submit; remote build was not started" : "✗ Maker project submit failed; remote build was not started",
|
|
@@ -31334,7 +32537,10 @@ function formatBuildResult(result, progressSummary) {
|
|
|
31334
32537
|
lines.push(
|
|
31335
32538
|
`- timeout_ms: ${result.timeoutMs}`,
|
|
31336
32539
|
`- build_args: ${JSON.stringify(result.buildArgs)}`,
|
|
32540
|
+
...formatPreviewRefreshLines(result.previewRefresh),
|
|
31337
32541
|
...formatProgressSummary(progressSummary),
|
|
32542
|
+
"",
|
|
32543
|
+
...formatRuntimeLogWatchNextActionLines(result),
|
|
31338
32544
|
""
|
|
31339
32545
|
);
|
|
31340
32546
|
if (submitLines.length > 0) {
|
|
@@ -31343,6 +32549,51 @@ function formatBuildResult(result, progressSummary) {
|
|
|
31343
32549
|
lines.push("remote_result:", indent(result.resultText));
|
|
31344
32550
|
return lines.join("\n");
|
|
31345
32551
|
}
|
|
32552
|
+
function formatPreviewRefreshLines(result) {
|
|
32553
|
+
if (!result) {
|
|
32554
|
+
return ["- preview_refresh: (not attempted)"];
|
|
32555
|
+
}
|
|
32556
|
+
return [
|
|
32557
|
+
`- preview_refresh: ${result.ok ? "ok" : "failed"}`,
|
|
32558
|
+
`- preview_refresh_status: ${result.status}`,
|
|
32559
|
+
result.url ? `- preview_refresh_url: ${result.url}` : "",
|
|
32560
|
+
result.error ? `- preview_refresh_error: ${result.error}` : ""
|
|
32561
|
+
].filter(Boolean);
|
|
32562
|
+
}
|
|
32563
|
+
function formatRuntimeLogWatchNextActionLines(result) {
|
|
32564
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
32565
|
+
const command = formatLocalShellCommand([
|
|
32566
|
+
"taptap-maker",
|
|
32567
|
+
"logs",
|
|
32568
|
+
"watch",
|
|
32569
|
+
"--target-dir",
|
|
32570
|
+
result.projectRoot,
|
|
32571
|
+
"--reset",
|
|
32572
|
+
"--interval",
|
|
32573
|
+
"5s"
|
|
32574
|
+
]);
|
|
32575
|
+
return [
|
|
32576
|
+
"runtime_logs:",
|
|
32577
|
+
result.runtimeLogWatch ? `- watch_started: ${result.runtimeLogWatch.started ? "yes" : "no"}` : "- watch_started: (not attempted)",
|
|
32578
|
+
((_a2 = result.runtimeLogWatch) == null ? void 0 : _a2.pid) ? `- watch_pid: ${result.runtimeLogWatch.pid}` : "",
|
|
32579
|
+
`- watch_command: ${command}`,
|
|
32580
|
+
((_b = result.runtimeLogWatch) == null ? void 0 : _b.command) ? `- actual_watch_command: ${result.runtimeLogWatch.command}` : "",
|
|
32581
|
+
`- local_file: ${path8.join(result.projectRoot, ".maker", "logs", "runtime", "runtime.log")}`,
|
|
32582
|
+
((_c = result.runtimeLogWatch) == null ? void 0 : _c.stdoutLog) ? `- watcher_stdout: ${result.runtimeLogWatch.stdoutLog}` : "",
|
|
32583
|
+
((_d = result.runtimeLogWatch) == null ? void 0 : _d.stderrLog) ? `- watcher_stderr: ${result.runtimeLogWatch.stderrLog}` : "",
|
|
32584
|
+
((_e = result.runtimeLogWatch) == null ? void 0 : _e.pidFile) ? `- watcher_pid_file: ${result.runtimeLogWatch.pidFile}` : "",
|
|
32585
|
+
`- state_file: ${path8.join(result.projectRoot, ".maker", "logs", "runtime", "state.json")}`,
|
|
32586
|
+
((_f = result.runtimeLogWatch) == null ? void 0 : _f.previousPid) ? `- previous_watch_pid: ${result.runtimeLogWatch.previousPid}` : "",
|
|
32587
|
+
((_g = result.runtimeLogWatch) == null ? void 0 : _g.previousStopped) !== void 0 ? `- previous_watch_stopped: ${result.runtimeLogWatch.previousStopped ? "yes" : "no"}` : "",
|
|
32588
|
+
((_h = result.runtimeLogWatch) == null ? void 0 : _h.previousStopError) ? `- previous_watch_stop_error: ${result.runtimeLogWatch.previousStopError}` : "",
|
|
32589
|
+
((_i = result.runtimeLogWatch) == null ? void 0 : _i.error) ? `- watch_error: ${result.runtimeLogWatch.error}` : "",
|
|
32590
|
+
((_j = result.runtimeLogWatch) == null ? void 0 : _j.started) ? "- note: 构建成功后已启动本地 CLI watcher,正在清理历史日志并每 5 秒持续追加 Lua 运行日志。" : "- note: 构建成功后应由本地 CLI watcher 清理历史日志,并每 5 秒持续追加 Lua 运行日志。",
|
|
32591
|
+
"- next_action: 如需分析游戏运行结果或报错,请读取 runtime_logs.local_file;如需判断 watcher 是否正常,请读取 runtime_logs.state_file。"
|
|
32592
|
+
].filter(Boolean);
|
|
32593
|
+
}
|
|
32594
|
+
function formatLocalShellCommand(parts) {
|
|
32595
|
+
return parts.map((part) => /\s/.test(part) ? `"${part.replace(/(["\\$`])/g, "\\$1")}"` : part).join(" ");
|
|
32596
|
+
}
|
|
31346
32597
|
function formatPushRecoveryLines(submitResult) {
|
|
31347
32598
|
if (submitResult.pushed || submitResult.status !== "failed_after_commit") {
|
|
31348
32599
|
return [];
|
|
@@ -31448,20 +32699,21 @@ function indent(value) {
|
|
|
31448
32699
|
// src/maker/cli/commands.ts
|
|
31449
32700
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
31450
32701
|
import crypto from "node:crypto";
|
|
31451
|
-
import
|
|
32702
|
+
import fs8 from "node:fs";
|
|
31452
32703
|
import os4 from "node:os";
|
|
31453
|
-
import
|
|
32704
|
+
import path9 from "node:path";
|
|
31454
32705
|
import readline from "node:readline/promises";
|
|
31455
32706
|
import { stdin as input, stdout as output } from "node:process";
|
|
31456
32707
|
var DEFAULT_MCP_NAME = "taptap-maker";
|
|
31457
32708
|
var DEFAULT_PACKAGE = "@taptap/instant-games-open-mcp";
|
|
31458
|
-
var TWO_PART_COMMANDS = /* @__PURE__ */ new Set(["pat", "mcp", "dev-kit"]);
|
|
32709
|
+
var TWO_PART_COMMANDS = /* @__PURE__ */ new Set(["pat", "mcp", "dev-kit", "logs"]);
|
|
31459
32710
|
var BOOLEAN_OPTIONS = /* @__PURE__ */ new Set([
|
|
31460
32711
|
"json",
|
|
31461
32712
|
"skip_confirm",
|
|
31462
32713
|
"skip_mcp_install",
|
|
31463
32714
|
"pat_stdin",
|
|
31464
32715
|
"pat_from_stdin",
|
|
32716
|
+
"reset",
|
|
31465
32717
|
"all",
|
|
31466
32718
|
"h",
|
|
31467
32719
|
"help"
|
|
@@ -31503,6 +32755,10 @@ async function runMakerCli(argv) {
|
|
|
31503
32755
|
await runDevKitUpdate(parsed, ctx);
|
|
31504
32756
|
return;
|
|
31505
32757
|
}
|
|
32758
|
+
if (command === "logs" && subcommand === "watch") {
|
|
32759
|
+
await runLogsWatch(parsed, ctx);
|
|
32760
|
+
return;
|
|
32761
|
+
}
|
|
31506
32762
|
throw new Error(`Unknown taptap-maker command: ${formatUnknownCommand(parsed.command)}`);
|
|
31507
32763
|
}
|
|
31508
32764
|
function parseArgs(argv) {
|
|
@@ -31551,7 +32807,7 @@ function toOptionKey(value) {
|
|
|
31551
32807
|
return value.replace(/-/g, "_");
|
|
31552
32808
|
}
|
|
31553
32809
|
async function runInit(parsed, ctx) {
|
|
31554
|
-
const targetDir =
|
|
32810
|
+
const targetDir = path9.resolve(stringOption(parsed, "target_dir") || process.cwd());
|
|
31555
32811
|
const env = makerEnvOption(parsed);
|
|
31556
32812
|
const skipConfirm = booleanOption(parsed, "skip_confirm");
|
|
31557
32813
|
const skipMcpInstall = booleanOption(parsed, "skip_mcp_install");
|
|
@@ -31569,12 +32825,16 @@ async function runInit(parsed, ctx) {
|
|
|
31569
32825
|
emit(ctx, "doctor", "Git is available", { version: git.version });
|
|
31570
32826
|
const pat = await resolvePat(parsed, ctx);
|
|
31571
32827
|
emit(ctx, "pat", "Maker PAT ready", { saved: getPatPath() });
|
|
31572
|
-
const tapAuth = await requestTapAuthWithPat(pat)
|
|
32828
|
+
const tapAuth = await requestTapAuthWithPat(pat).catch((error2) => {
|
|
32829
|
+
throw appendPatRecoveryUrl(error2, parsed);
|
|
32830
|
+
});
|
|
31573
32831
|
emit(ctx, "tap_auth", "TapTap token exchanged and saved", {
|
|
31574
32832
|
kid: mask(tapAuth.kid),
|
|
31575
32833
|
saved: getTapAuthPath()
|
|
31576
32834
|
});
|
|
31577
|
-
const projects = await listMakerProjects({ pat })
|
|
32835
|
+
const projects = await listMakerProjects({ pat }).catch((error2) => {
|
|
32836
|
+
throw appendPatRecoveryUrl(error2, parsed);
|
|
32837
|
+
});
|
|
31578
32838
|
const selected = await resolveProjectSelection(parsed, projects, {
|
|
31579
32839
|
skipConfirm
|
|
31580
32840
|
});
|
|
@@ -31597,6 +32857,8 @@ async function runInit(parsed, ctx) {
|
|
|
31597
32857
|
userId: selected.user_id,
|
|
31598
32858
|
sceEndpoint: selected.sce_endpoint || process.env.SCE_MCP_URL,
|
|
31599
32859
|
onProgress: (progress) => emitProgress(ctx, "clone", progress)
|
|
32860
|
+
}).catch((error2) => {
|
|
32861
|
+
throw appendPatRecoveryUrl(error2, parsed);
|
|
31600
32862
|
});
|
|
31601
32863
|
emit(ctx, "clone", "Maker project cloned or fetched", cloneResult);
|
|
31602
32864
|
if (!skipMcpInstall) {
|
|
@@ -31624,7 +32886,7 @@ async function runInit(parsed, ctx) {
|
|
|
31624
32886
|
});
|
|
31625
32887
|
}
|
|
31626
32888
|
async function runDoctor(parsed, ctx) {
|
|
31627
|
-
const targetDir =
|
|
32889
|
+
const targetDir = path9.resolve(stringOption(parsed, "target_dir") || process.cwd());
|
|
31628
32890
|
const git = checkGitEnvironment();
|
|
31629
32891
|
const pat = loadPat();
|
|
31630
32892
|
const tapAuth = loadTapAuth();
|
|
@@ -31675,7 +32937,9 @@ async function runApps(parsed, ctx) {
|
|
|
31675
32937
|
warnPatArgExposure();
|
|
31676
32938
|
}
|
|
31677
32939
|
const showAll = booleanOption(parsed, "all");
|
|
31678
|
-
const projects = await listMakerProjects({ pat })
|
|
32940
|
+
const projects = await listMakerProjects({ pat }).catch((error2) => {
|
|
32941
|
+
throw appendPatRecoveryUrl(error2, parsed);
|
|
32942
|
+
});
|
|
31679
32943
|
if (ctx.json) {
|
|
31680
32944
|
writeJson(projects);
|
|
31681
32945
|
return;
|
|
@@ -31686,7 +32950,9 @@ async function runApps(parsed, ctx) {
|
|
|
31686
32950
|
async function runPatSet(parsed, ctx) {
|
|
31687
32951
|
const pat = await resolvePatSet(parsed, ctx);
|
|
31688
32952
|
saveManualMakerPat(pat);
|
|
31689
|
-
const tapAuth = await requestTapAuthWithPat(pat)
|
|
32953
|
+
const tapAuth = await requestTapAuthWithPat(pat).catch((error2) => {
|
|
32954
|
+
throw appendPatRecoveryUrl(error2, parsed);
|
|
32955
|
+
});
|
|
31690
32956
|
emit(ctx, "pat", "Maker PAT and TapTap token saved", {
|
|
31691
32957
|
pat_path: getPatPath(),
|
|
31692
32958
|
tap_auth_path: getTapAuthPath(),
|
|
@@ -31695,7 +32961,7 @@ async function runPatSet(parsed, ctx) {
|
|
|
31695
32961
|
}
|
|
31696
32962
|
async function resolvePatSet(parsed, ctx) {
|
|
31697
32963
|
if (booleanOption(parsed, "pat_stdin") || booleanOption(parsed, "pat_from_stdin")) {
|
|
31698
|
-
const pat =
|
|
32964
|
+
const pat = fs8.readFileSync(0, "utf8").trim();
|
|
31699
32965
|
if (!pat) {
|
|
31700
32966
|
throw new Error("No PAT found on stdin.");
|
|
31701
32967
|
}
|
|
@@ -31822,13 +33088,127 @@ function getMcpVerifyNextSteps(mode, commandText) {
|
|
|
31822
33088
|
];
|
|
31823
33089
|
}
|
|
31824
33090
|
async function runDevKitUpdate(parsed, ctx) {
|
|
31825
|
-
const targetDir =
|
|
33091
|
+
const targetDir = path9.resolve(stringOption(parsed, "target_dir") || process.cwd());
|
|
31826
33092
|
const result = await installAiDevKit({
|
|
31827
33093
|
targetDir,
|
|
31828
33094
|
preserveExisting: true
|
|
31829
33095
|
});
|
|
31830
33096
|
finalizeStagedDevKitGitignore(targetDir);
|
|
31831
|
-
emit(ctx, "dev_kit", "AI dev kit updated", result);
|
|
33097
|
+
emit(ctx, "dev_kit", formatDevKitInstallMessage("AI dev kit updated", result), result);
|
|
33098
|
+
emitDevKitSkillInstallerFailure(ctx, result.skillInstaller, "AI skills install failed");
|
|
33099
|
+
}
|
|
33100
|
+
async function runLogsWatch(parsed, ctx) {
|
|
33101
|
+
const targetDir = path9.resolve(stringOption(parsed, "target_dir") || process.cwd());
|
|
33102
|
+
const intervalMs = parseDurationMs(stringOption(parsed, "interval") || "5s");
|
|
33103
|
+
const timeoutMs = numberOption(parsed, "timeout_ms") ?? 60 * 1e3;
|
|
33104
|
+
const maxPolls = numberOption(parsed, "max_polls");
|
|
33105
|
+
const maxConsecutiveFailures = numberOption(parsed, "max_consecutive_failures");
|
|
33106
|
+
const proxy = createRemoteProxyContext({
|
|
33107
|
+
targetDir,
|
|
33108
|
+
serverUrl: stringOption(parsed, "server_url"),
|
|
33109
|
+
env: makerEnvOption(parsed)
|
|
33110
|
+
});
|
|
33111
|
+
const runtimeDir = path9.join(proxy.projectRoot, ".maker", "logs", "runtime");
|
|
33112
|
+
const runtimeLog = path9.join(runtimeDir, "runtime.log");
|
|
33113
|
+
const pidFile = path9.join(runtimeDir, "watcher.pid");
|
|
33114
|
+
const replacedWatcher = registerRuntimeLogWatcherProcess(pidFile);
|
|
33115
|
+
const runtimeLogClient = createRemoteRuntimeLogClient(proxy, timeoutMs);
|
|
33116
|
+
emit(ctx, "logs_watch_start", "Maker runtime log watcher started", {
|
|
33117
|
+
project_root: proxy.projectRoot,
|
|
33118
|
+
project_id: proxy.projectId,
|
|
33119
|
+
runtime_log: runtimeLog,
|
|
33120
|
+
pid_file: pidFile,
|
|
33121
|
+
pid: process.pid,
|
|
33122
|
+
...replacedWatcher,
|
|
33123
|
+
reset: booleanOption(parsed, "reset"),
|
|
33124
|
+
interval_ms: intervalMs,
|
|
33125
|
+
topics: ["user_script", "server_user_script"]
|
|
33126
|
+
});
|
|
33127
|
+
try {
|
|
33128
|
+
const result = await watchRuntimeLogs({
|
|
33129
|
+
projectRoot: proxy.projectRoot,
|
|
33130
|
+
projectId: proxy.projectId,
|
|
33131
|
+
reset: booleanOption(parsed, "reset"),
|
|
33132
|
+
intervalMs,
|
|
33133
|
+
limit: numberOption(parsed, "limit"),
|
|
33134
|
+
maxPolls,
|
|
33135
|
+
maxConsecutiveFailures,
|
|
33136
|
+
callRemoteRuntimeLogs: (args) => runtimeLogClient.call(args),
|
|
33137
|
+
onPoll: (pullResult) => {
|
|
33138
|
+
emit(ctx, "logs_poll", `Maker runtime logs pulled: ${pullResult.writtenLogs}`, {
|
|
33139
|
+
written_logs: pullResult.writtenLogs,
|
|
33140
|
+
has_more: pullResult.hasMore,
|
|
33141
|
+
next_start_time: pullResult.nextStartTime,
|
|
33142
|
+
files: pullResult.files
|
|
33143
|
+
});
|
|
33144
|
+
},
|
|
33145
|
+
onError: (error2, consecutiveFailures) => {
|
|
33146
|
+
emit(ctx, "logs_poll_error", "Maker runtime log poll failed; watcher will retry", {
|
|
33147
|
+
consecutive_failures: consecutiveFailures,
|
|
33148
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
33149
|
+
});
|
|
33150
|
+
}
|
|
33151
|
+
});
|
|
33152
|
+
emit(ctx, "logs_watch_stop", "Maker runtime log watcher stopped", result);
|
|
33153
|
+
} finally {
|
|
33154
|
+
await runtimeLogClient.close();
|
|
33155
|
+
}
|
|
33156
|
+
}
|
|
33157
|
+
function registerRuntimeLogWatcherProcess(pidFile) {
|
|
33158
|
+
fs8.mkdirSync(path9.dirname(pidFile), { recursive: true });
|
|
33159
|
+
const existingPid = readPidFile(pidFile);
|
|
33160
|
+
const previous = existingPid && existingPid !== process.pid ? stopExistingRuntimeLogWatcher(pidFile) : {};
|
|
33161
|
+
fs8.writeFileSync(
|
|
33162
|
+
pidFile,
|
|
33163
|
+
`${JSON.stringify(
|
|
33164
|
+
{
|
|
33165
|
+
pid: process.pid,
|
|
33166
|
+
command: formatShellCommand([process.execPath, ...process.argv.slice(1)]),
|
|
33167
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
33168
|
+
},
|
|
33169
|
+
null,
|
|
33170
|
+
2
|
|
33171
|
+
)}
|
|
33172
|
+
`,
|
|
33173
|
+
"utf8"
|
|
33174
|
+
);
|
|
33175
|
+
installRuntimeLogWatcherPidCleanup(pidFile);
|
|
33176
|
+
return previous;
|
|
33177
|
+
}
|
|
33178
|
+
function readPidFile(pidFile) {
|
|
33179
|
+
if (!fs8.existsSync(pidFile)) {
|
|
33180
|
+
return void 0;
|
|
33181
|
+
}
|
|
33182
|
+
const raw = fs8.readFileSync(pidFile, "utf8").trim();
|
|
33183
|
+
let pid = Number(raw);
|
|
33184
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
33185
|
+
try {
|
|
33186
|
+
const parsed = JSON.parse(raw);
|
|
33187
|
+
pid = typeof parsed.pid === "number" ? parsed.pid : Number.NaN;
|
|
33188
|
+
} catch {
|
|
33189
|
+
pid = Number.NaN;
|
|
33190
|
+
}
|
|
33191
|
+
}
|
|
33192
|
+
return Number.isInteger(pid) && pid > 0 ? pid : void 0;
|
|
33193
|
+
}
|
|
33194
|
+
function installRuntimeLogWatcherPidCleanup(pidFile) {
|
|
33195
|
+
let cleaned = false;
|
|
33196
|
+
const cleanup = () => {
|
|
33197
|
+
if (cleaned) {
|
|
33198
|
+
return;
|
|
33199
|
+
}
|
|
33200
|
+
cleaned = true;
|
|
33201
|
+
if (readPidFile(pidFile) === process.pid) {
|
|
33202
|
+
fs8.rmSync(pidFile, { force: true });
|
|
33203
|
+
}
|
|
33204
|
+
};
|
|
33205
|
+
process.once("exit", cleanup);
|
|
33206
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
33207
|
+
process.once(signal, () => {
|
|
33208
|
+
cleanup();
|
|
33209
|
+
process.exit(0);
|
|
33210
|
+
});
|
|
33211
|
+
}
|
|
31832
33212
|
}
|
|
31833
33213
|
async function resolvePat(parsed, ctx) {
|
|
31834
33214
|
const fromArgs = stringOption(parsed, "pat");
|
|
@@ -31900,21 +33280,90 @@ async function prepareDevKit(targetDir, ctx) {
|
|
|
31900
33280
|
const before = inspectAiDevKit(targetDir);
|
|
31901
33281
|
if (before.ready) {
|
|
31902
33282
|
writeDevKitStagedGitignore(
|
|
31903
|
-
|
|
33283
|
+
path9.join(targetDir, DEV_KIT_GITIGNORE_STAGING_FILE),
|
|
31904
33284
|
listPresentDevKitManagedEntries(targetDir)
|
|
31905
33285
|
);
|
|
31906
|
-
|
|
33286
|
+
try {
|
|
33287
|
+
const skillInstaller = installAiDevKitSkills(targetDir, {
|
|
33288
|
+
onStart: (event) => emitSkillInstallerStart(ctx, event)
|
|
33289
|
+
});
|
|
33290
|
+
emit(
|
|
33291
|
+
ctx,
|
|
33292
|
+
"dev_kit",
|
|
33293
|
+
formatDevKitInstallMessage("AI dev kit already present", { skillInstaller }),
|
|
33294
|
+
{
|
|
33295
|
+
...before,
|
|
33296
|
+
skillInstaller
|
|
33297
|
+
}
|
|
33298
|
+
);
|
|
33299
|
+
} catch (error2) {
|
|
33300
|
+
const detail = error2 instanceof Error ? error2.message : String(error2);
|
|
33301
|
+
emit(ctx, "dev_kit_warning", `AI skills install failed; clone will continue
|
|
33302
|
+
${detail}`, {
|
|
33303
|
+
error: detail
|
|
33304
|
+
});
|
|
33305
|
+
}
|
|
31907
33306
|
return;
|
|
31908
33307
|
}
|
|
31909
33308
|
try {
|
|
31910
|
-
const result = await installAiDevKit({
|
|
31911
|
-
|
|
33309
|
+
const result = await installAiDevKit({
|
|
33310
|
+
targetDir,
|
|
33311
|
+
onSkillInstallerStart: (event) => emitSkillInstallerStart(ctx, event)
|
|
33312
|
+
});
|
|
33313
|
+
emit(ctx, "dev_kit", formatDevKitInstallMessage("AI dev kit prepared", result), result);
|
|
33314
|
+
emitDevKitSkillInstallerFailure(
|
|
33315
|
+
ctx,
|
|
33316
|
+
result.skillInstaller,
|
|
33317
|
+
"AI skills install failed; clone will continue"
|
|
33318
|
+
);
|
|
31912
33319
|
} catch (error2) {
|
|
31913
|
-
|
|
31914
|
-
|
|
33320
|
+
const detail = error2 instanceof Error ? error2.message : String(error2);
|
|
33321
|
+
emit(ctx, "dev_kit_warning", `AI dev kit preparation failed; clone will continue
|
|
33322
|
+
${detail}`, {
|
|
33323
|
+
error: detail
|
|
31915
33324
|
});
|
|
31916
33325
|
}
|
|
31917
33326
|
}
|
|
33327
|
+
function formatDevKitInstallMessage(message, result) {
|
|
33328
|
+
if (!result.skillInstaller) {
|
|
33329
|
+
return message;
|
|
33330
|
+
}
|
|
33331
|
+
return `${message}
|
|
33332
|
+
AI skills install result: ${result.skillInstaller.summary}`;
|
|
33333
|
+
}
|
|
33334
|
+
function emitSkillInstallerStart(ctx, event) {
|
|
33335
|
+
emit(ctx, "dev_kit_skill_install_start", `AI skills install started: ${event.script}`, event);
|
|
33336
|
+
}
|
|
33337
|
+
function emitDevKitSkillInstallerFailure(ctx, result, message) {
|
|
33338
|
+
if (!result || result.ok || result.status !== "failed") {
|
|
33339
|
+
return;
|
|
33340
|
+
}
|
|
33341
|
+
const detail = result.error || "unknown installer failure";
|
|
33342
|
+
emit(ctx, "dev_kit_warning", `${message}
|
|
33343
|
+
${detail}`, {
|
|
33344
|
+
error: detail
|
|
33345
|
+
});
|
|
33346
|
+
}
|
|
33347
|
+
function appendPatRecoveryUrl(error2, parsed) {
|
|
33348
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
33349
|
+
if (!isPatValidationFailure(message) || message.includes("/pat-tokens")) {
|
|
33350
|
+
return error2 instanceof Error ? error2 : new Error(message);
|
|
33351
|
+
}
|
|
33352
|
+
const patPage = getMakerPatTokensUrl(makerEnvOption(parsed));
|
|
33353
|
+
return new Error(
|
|
33354
|
+
[
|
|
33355
|
+
message,
|
|
33356
|
+
"",
|
|
33357
|
+
`PAT 页面:${patPage}`,
|
|
33358
|
+
"请在该页面创建新的 Maker PAT,然后运行 `taptap-maker pat set` 并粘贴 PAT。"
|
|
33359
|
+
].join("\n")
|
|
33360
|
+
);
|
|
33361
|
+
}
|
|
33362
|
+
function isPatValidationFailure(message) {
|
|
33363
|
+
return /\b(?:PAT_INVALID|HTTP\s*40[13]|40[13]|unauthori[sz]ed|invalid\s+PAT|PAT\s+invalid|expired)\b/i.test(
|
|
33364
|
+
message
|
|
33365
|
+
) || /(?:过期|失效)/.test(message);
|
|
33366
|
+
}
|
|
31918
33367
|
function installMcpConfigs(options) {
|
|
31919
33368
|
return options.ides.map((ide) => installMcpConfig(ide, options));
|
|
31920
33369
|
}
|
|
@@ -31931,7 +33380,7 @@ function installMcpConfig(ide, options) {
|
|
|
31931
33380
|
}
|
|
31932
33381
|
function installMcpConfigUnsafe(ide, options) {
|
|
31933
33382
|
if (ide === "codex") {
|
|
31934
|
-
const configPath =
|
|
33383
|
+
const configPath = path9.join(os4.homedir(), ".codex", "config.toml");
|
|
31935
33384
|
mergeCodexMcpConfig(configPath, options);
|
|
31936
33385
|
return {
|
|
31937
33386
|
ide,
|
|
@@ -31941,7 +33390,7 @@ function installMcpConfigUnsafe(ide, options) {
|
|
|
31941
33390
|
};
|
|
31942
33391
|
}
|
|
31943
33392
|
if (ide === "cursor") {
|
|
31944
|
-
const configPath =
|
|
33393
|
+
const configPath = path9.join(os4.homedir(), ".cursor", "mcp.json");
|
|
31945
33394
|
mergeJsonMcpConfig(configPath, options);
|
|
31946
33395
|
return {
|
|
31947
33396
|
ide,
|
|
@@ -31955,7 +33404,7 @@ function installMcpConfigUnsafe(ide, options) {
|
|
|
31955
33404
|
if (claudeResult.ok) {
|
|
31956
33405
|
return { ide, ok: true, message: "✓ Claude Code MCP config updated with claude mcp add" };
|
|
31957
33406
|
}
|
|
31958
|
-
const configPath =
|
|
33407
|
+
const configPath = path9.join(os4.homedir(), ".claude.json");
|
|
31959
33408
|
mergeJsonMcpConfig(configPath, options);
|
|
31960
33409
|
return {
|
|
31961
33410
|
ide,
|
|
@@ -31972,13 +33421,13 @@ function mergeJsonMcpConfig(configPath, options) {
|
|
|
31972
33421
|
const mcpServers = asObject(existing.mcpServers);
|
|
31973
33422
|
mcpServers[options.mcpName] = createJsonMcpServerConfig(options);
|
|
31974
33423
|
existing.mcpServers = mcpServers;
|
|
31975
|
-
|
|
31976
|
-
|
|
33424
|
+
fs8.mkdirSync(path9.dirname(configPath), { recursive: true });
|
|
33425
|
+
fs8.writeFileSync(configPath, `${JSON.stringify(existing, null, 2)}
|
|
31977
33426
|
`, "utf8");
|
|
31978
33427
|
}
|
|
31979
33428
|
function mergeCodexMcpConfig(configPath, options) {
|
|
31980
33429
|
const backupPath = backupIfExists(configPath);
|
|
31981
|
-
const existing =
|
|
33430
|
+
const existing = fs8.existsSync(configPath) ? fs8.readFileSync(configPath, "utf8") : "";
|
|
31982
33431
|
const sectionPattern = createCodexMcpSectionPattern(options.mcpName);
|
|
31983
33432
|
const withoutOld = existing.replace(sectionPattern, "").trimEnd();
|
|
31984
33433
|
const command = getNpxCommand();
|
|
@@ -31991,9 +33440,9 @@ function mergeCodexMcpConfig(configPath, options) {
|
|
|
31991
33440
|
`TAPTAP_MCP_ENV = "${options.env}"`,
|
|
31992
33441
|
""
|
|
31993
33442
|
].join("\n");
|
|
31994
|
-
|
|
31995
|
-
|
|
31996
|
-
const updated =
|
|
33443
|
+
fs8.mkdirSync(path9.dirname(configPath), { recursive: true });
|
|
33444
|
+
fs8.writeFileSync(configPath, [withoutOld, section].filter(Boolean).join("\n\n"), "utf8");
|
|
33445
|
+
const updated = fs8.readFileSync(configPath, "utf8");
|
|
31997
33446
|
const duplicates = findCodexMcpTableDuplicates(updated, options.mcpName);
|
|
31998
33447
|
if (duplicates.length > 0) {
|
|
31999
33448
|
restoreBackup(configPath, backupPath);
|
|
@@ -32091,10 +33540,10 @@ function getNpxCommand() {
|
|
|
32091
33540
|
return process.platform === "win32" ? "npx.cmd" : "npx";
|
|
32092
33541
|
}
|
|
32093
33542
|
function readJsonObject(filePath) {
|
|
32094
|
-
if (!
|
|
33543
|
+
if (!fs8.existsSync(filePath)) {
|
|
32095
33544
|
return {};
|
|
32096
33545
|
}
|
|
32097
|
-
return JSON.parse(
|
|
33546
|
+
return JSON.parse(fs8.readFileSync(filePath, "utf8"));
|
|
32098
33547
|
}
|
|
32099
33548
|
function asObject(value) {
|
|
32100
33549
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
@@ -32103,26 +33552,26 @@ function asObject(value) {
|
|
|
32103
33552
|
return {};
|
|
32104
33553
|
}
|
|
32105
33554
|
function backupIfExists(filePath) {
|
|
32106
|
-
if (!
|
|
33555
|
+
if (!fs8.existsSync(filePath)) {
|
|
32107
33556
|
return void 0;
|
|
32108
33557
|
}
|
|
32109
33558
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").replace(/\..+$/, "");
|
|
32110
33559
|
const backupPath = `${filePath}.bak.${stamp}`;
|
|
32111
|
-
|
|
33560
|
+
fs8.copyFileSync(filePath, backupPath);
|
|
32112
33561
|
return backupPath;
|
|
32113
33562
|
}
|
|
32114
33563
|
function restoreBackup(filePath, backupPath) {
|
|
32115
33564
|
if (backupPath) {
|
|
32116
|
-
|
|
33565
|
+
fs8.copyFileSync(backupPath, filePath);
|
|
32117
33566
|
return;
|
|
32118
33567
|
}
|
|
32119
|
-
|
|
33568
|
+
fs8.rmSync(filePath, { force: true });
|
|
32120
33569
|
}
|
|
32121
33570
|
function saveInitState(targetDir, state) {
|
|
32122
|
-
|
|
32123
|
-
const key = crypto.createHash("sha256").update(
|
|
32124
|
-
|
|
32125
|
-
|
|
33571
|
+
fs8.mkdirSync(getMakerHome(), { recursive: true });
|
|
33572
|
+
const key = crypto.createHash("sha256").update(path9.resolve(targetDir)).digest("hex").slice(0, 16);
|
|
33573
|
+
fs8.writeFileSync(
|
|
33574
|
+
path9.join(getMakerHome(), `init-state-${key}.json`),
|
|
32126
33575
|
`${JSON.stringify({ ...state, updated_at: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)}
|
|
32127
33576
|
`,
|
|
32128
33577
|
"utf8"
|
|
@@ -32223,7 +33672,7 @@ function formatUnknownCommand(command) {
|
|
|
32223
33672
|
return `${primary} ${isKnownSubcommand(primary, secondary) ? secondary : "<redacted>"}`;
|
|
32224
33673
|
}
|
|
32225
33674
|
function isKnownSubcommand(command, subcommand) {
|
|
32226
|
-
return command === "pat" && subcommand === "set" || command === "mcp" && (subcommand === "install" || subcommand === "verify") || command === "dev-kit" && subcommand === "update";
|
|
33675
|
+
return command === "pat" && subcommand === "set" || command === "mcp" && (subcommand === "install" || subcommand === "verify") || command === "dev-kit" && subcommand === "update" || command === "logs" && subcommand === "watch";
|
|
32227
33676
|
}
|
|
32228
33677
|
function stringOption(parsed, key) {
|
|
32229
33678
|
const value = parsed.options[key];
|
|
@@ -32232,6 +33681,26 @@ function stringOption(parsed, key) {
|
|
|
32232
33681
|
function booleanOption(parsed, key) {
|
|
32233
33682
|
return parsed.options[key] === true || parsed.options[key] === "true";
|
|
32234
33683
|
}
|
|
33684
|
+
function numberOption(parsed, key) {
|
|
33685
|
+
const value = parsed.options[key];
|
|
33686
|
+
if (value === void 0 || value === true || value === false) {
|
|
33687
|
+
return void 0;
|
|
33688
|
+
}
|
|
33689
|
+
const number3 = Number(value);
|
|
33690
|
+
if (!Number.isFinite(number3)) {
|
|
33691
|
+
throw new Error(`Invalid --${key.replace(/_/g, "-")} value: ${value}`);
|
|
33692
|
+
}
|
|
33693
|
+
return number3;
|
|
33694
|
+
}
|
|
33695
|
+
function parseDurationMs(value) {
|
|
33696
|
+
const match = /^(\d+(?:\.\d+)?)(ms|s)?$/.exec(value.trim());
|
|
33697
|
+
if (!match) {
|
|
33698
|
+
throw new Error("Invalid --interval value. Use seconds, or suffix with s/ms.");
|
|
33699
|
+
}
|
|
33700
|
+
const amount = Number(match[1]);
|
|
33701
|
+
const unit = match[2] || "s";
|
|
33702
|
+
return unit === "s" ? amount * 1e3 : amount;
|
|
33703
|
+
}
|
|
32235
33704
|
function makerEnvOption(parsed) {
|
|
32236
33705
|
const env = stringOption(parsed, "env");
|
|
32237
33706
|
if (env === "rnd" || env === "production") {
|
|
@@ -32288,6 +33757,7 @@ function printHelp() {
|
|
|
32288
33757
|
" taptap-maker mcp verify [--package @taptap/instant-games-open-mcp]",
|
|
32289
33758
|
" [--mode npx|self] [--json]",
|
|
32290
33759
|
" taptap-maker dev-kit update [--target-dir DIR] [--json]",
|
|
33760
|
+
" taptap-maker logs watch [--target-dir DIR] [--interval 5s] [--reset] [--json]",
|
|
32291
33761
|
"",
|
|
32292
33762
|
"MCP verify defaults to the npx command written into AI client config.",
|
|
32293
33763
|
"Advanced: init and mcp install accept --package only when testing a different npm package.",
|
|
@@ -32306,14 +33776,14 @@ function formatCliError(error2) {
|
|
|
32306
33776
|
}
|
|
32307
33777
|
|
|
32308
33778
|
// src/maker/crashLog.ts
|
|
32309
|
-
import
|
|
32310
|
-
import
|
|
33779
|
+
import fs9 from "node:fs";
|
|
33780
|
+
import path10 from "node:path";
|
|
32311
33781
|
var DEFAULT_MAX_BYTES = 1024 * 1024;
|
|
32312
33782
|
var DEFAULT_MAX_ENTRY_BYTES = 16 * 1024;
|
|
32313
33783
|
function appendMakerCrashLog(source, error2, options = {}) {
|
|
32314
33784
|
const makerHome = getMakerHome();
|
|
32315
|
-
|
|
32316
|
-
const logPath =
|
|
33785
|
+
fs9.mkdirSync(makerHome, { recursive: true });
|
|
33786
|
+
const logPath = path10.join(makerHome, "mcp-crash.log");
|
|
32317
33787
|
const maxBytes = positiveInteger(options.maxBytes) || resolveEnvBytes("TAPTAP_MAKER_CRASH_LOG_MAX_BYTES", DEFAULT_MAX_BYTES);
|
|
32318
33788
|
const maxEntryBytes = positiveInteger(options.maxEntryBytes) || resolveEnvBytes("TAPTAP_MAKER_CRASH_LOG_MAX_ENTRY_BYTES", DEFAULT_MAX_ENTRY_BYTES);
|
|
32319
33789
|
const message = error2 instanceof Error ? error2.stack || error2.message : String(error2);
|
|
@@ -32323,31 +33793,31 @@ function appendMakerCrashLog(source, error2, options = {}) {
|
|
|
32323
33793
|
);
|
|
32324
33794
|
const entryBytes = Buffer.byteLength(entry, "utf8");
|
|
32325
33795
|
rotateIfNeeded(logPath, maxBytes, entryBytes);
|
|
32326
|
-
|
|
33796
|
+
fs9.appendFileSync(logPath, entry, "utf8");
|
|
32327
33797
|
}
|
|
32328
33798
|
function rotateIfNeeded(logPath, maxBytes, incomingBytes) {
|
|
32329
|
-
if (!
|
|
33799
|
+
if (!fs9.existsSync(logPath)) {
|
|
32330
33800
|
return;
|
|
32331
33801
|
}
|
|
32332
|
-
const currentBytes =
|
|
33802
|
+
const currentBytes = fs9.statSync(logPath).size;
|
|
32333
33803
|
if (currentBytes + incomingBytes <= maxBytes) {
|
|
32334
33804
|
return;
|
|
32335
33805
|
}
|
|
32336
33806
|
const rotatedPath = `${logPath}.1`;
|
|
32337
33807
|
writeFileTail(logPath, rotatedPath, maxBytes);
|
|
32338
|
-
|
|
33808
|
+
fs9.writeFileSync(logPath, "", "utf8");
|
|
32339
33809
|
}
|
|
32340
33810
|
function writeFileTail(sourcePath, targetPath, maxBytes) {
|
|
32341
|
-
const size =
|
|
33811
|
+
const size = fs9.statSync(sourcePath).size;
|
|
32342
33812
|
const bytesToRead = Math.min(size, maxBytes);
|
|
32343
33813
|
const start = Math.max(0, size - bytesToRead);
|
|
32344
|
-
const fd =
|
|
33814
|
+
const fd = fs9.openSync(sourcePath, "r");
|
|
32345
33815
|
try {
|
|
32346
33816
|
const buffer = Buffer.alloc(bytesToRead);
|
|
32347
|
-
|
|
32348
|
-
|
|
33817
|
+
fs9.readSync(fd, buffer, 0, bytesToRead, start);
|
|
33818
|
+
fs9.writeFileSync(targetPath, buffer);
|
|
32349
33819
|
} finally {
|
|
32350
|
-
|
|
33820
|
+
fs9.closeSync(fd);
|
|
32351
33821
|
}
|
|
32352
33822
|
}
|
|
32353
33823
|
function truncateUtf8(value, maxBytes) {
|
|
@@ -32400,6 +33870,7 @@ function printHelp2() {
|
|
|
32400
33870
|
" taptap-maker mcp verify [--package @taptap/instant-games-open-mcp]",
|
|
32401
33871
|
" [--mode npx|self] [--json]",
|
|
32402
33872
|
" taptap-maker dev-kit update [--target-dir DIR] [--json]",
|
|
33873
|
+
" taptap-maker logs watch [--target-dir DIR] [--interval 5s] [--reset] [--json]",
|
|
32403
33874
|
"",
|
|
32404
33875
|
"MCP verify defaults to the npx command written into AI client config.",
|
|
32405
33876
|
"Advanced: init and mcp install accept --package only when testing a different npm package.",
|