@zltquant/zlt-mcp 0.7.0 → 0.7.1-beta.0
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 +7 -1
- package/package.json +1 -1
- package/zlt-mcp-proxy.bundle.cjs +910 -406
package/zlt-mcp-proxy.bundle.cjs
CHANGED
|
@@ -1147,8 +1147,8 @@ var require_command = __commonJS({
|
|
|
1147
1147
|
"../../node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/command.js"(exports2) {
|
|
1148
1148
|
var EventEmitter = require("node:events").EventEmitter;
|
|
1149
1149
|
var childProcess = require("node:child_process");
|
|
1150
|
-
var
|
|
1151
|
-
var
|
|
1150
|
+
var path19 = require("node:path");
|
|
1151
|
+
var fs20 = require("node:fs");
|
|
1152
1152
|
var process4 = require("node:process");
|
|
1153
1153
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
1154
1154
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -2129,7 +2129,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2129
2129
|
* @param {string} subcommandName
|
|
2130
2130
|
*/
|
|
2131
2131
|
_checkForMissingExecutable(executableFile, executableDir, subcommandName) {
|
|
2132
|
-
if (
|
|
2132
|
+
if (fs20.existsSync(executableFile)) return;
|
|
2133
2133
|
const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
|
|
2134
2134
|
const executableMissing = `'${executableFile}' does not exist
|
|
2135
2135
|
- if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
@@ -2147,11 +2147,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2147
2147
|
let launchWithNode = false;
|
|
2148
2148
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
2149
2149
|
function findFile(baseDir, baseName) {
|
|
2150
|
-
const localBin =
|
|
2151
|
-
if (
|
|
2152
|
-
if (sourceExt.includes(
|
|
2150
|
+
const localBin = path19.resolve(baseDir, baseName);
|
|
2151
|
+
if (fs20.existsSync(localBin)) return localBin;
|
|
2152
|
+
if (sourceExt.includes(path19.extname(baseName))) return void 0;
|
|
2153
2153
|
const foundExt = sourceExt.find(
|
|
2154
|
-
(ext) =>
|
|
2154
|
+
(ext) => fs20.existsSync(`${localBin}${ext}`)
|
|
2155
2155
|
);
|
|
2156
2156
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
2157
2157
|
return void 0;
|
|
@@ -2163,21 +2163,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2163
2163
|
if (this._scriptPath) {
|
|
2164
2164
|
let resolvedScriptPath;
|
|
2165
2165
|
try {
|
|
2166
|
-
resolvedScriptPath =
|
|
2166
|
+
resolvedScriptPath = fs20.realpathSync(this._scriptPath);
|
|
2167
2167
|
} catch {
|
|
2168
2168
|
resolvedScriptPath = this._scriptPath;
|
|
2169
2169
|
}
|
|
2170
|
-
executableDir =
|
|
2171
|
-
|
|
2170
|
+
executableDir = path19.resolve(
|
|
2171
|
+
path19.dirname(resolvedScriptPath),
|
|
2172
2172
|
executableDir
|
|
2173
2173
|
);
|
|
2174
2174
|
}
|
|
2175
2175
|
if (executableDir) {
|
|
2176
2176
|
let localFile = findFile(executableDir, executableFile);
|
|
2177
2177
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
2178
|
-
const legacyName =
|
|
2178
|
+
const legacyName = path19.basename(
|
|
2179
2179
|
this._scriptPath,
|
|
2180
|
-
|
|
2180
|
+
path19.extname(this._scriptPath)
|
|
2181
2181
|
);
|
|
2182
2182
|
if (legacyName !== this._name) {
|
|
2183
2183
|
localFile = findFile(
|
|
@@ -2188,7 +2188,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2188
2188
|
}
|
|
2189
2189
|
executableFile = localFile || executableFile;
|
|
2190
2190
|
}
|
|
2191
|
-
launchWithNode = sourceExt.includes(
|
|
2191
|
+
launchWithNode = sourceExt.includes(path19.extname(executableFile));
|
|
2192
2192
|
let proc;
|
|
2193
2193
|
if (process4.platform !== "win32") {
|
|
2194
2194
|
if (launchWithNode) {
|
|
@@ -3035,7 +3035,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3035
3035
|
* @return {Command}
|
|
3036
3036
|
*/
|
|
3037
3037
|
nameFromFilename(filename) {
|
|
3038
|
-
this._name =
|
|
3038
|
+
this._name = path19.basename(filename, path19.extname(filename));
|
|
3039
3039
|
return this;
|
|
3040
3040
|
}
|
|
3041
3041
|
/**
|
|
@@ -3049,9 +3049,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3049
3049
|
* @param {string} [path]
|
|
3050
3050
|
* @return {(string|null|Command)}
|
|
3051
3051
|
*/
|
|
3052
|
-
executableDir(
|
|
3053
|
-
if (
|
|
3054
|
-
this._executableDir =
|
|
3052
|
+
executableDir(path20) {
|
|
3053
|
+
if (path20 === void 0) return this._executableDir;
|
|
3054
|
+
this._executableDir = path20;
|
|
3055
3055
|
return this;
|
|
3056
3056
|
}
|
|
3057
3057
|
/**
|
|
@@ -3068,9 +3068,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3068
3068
|
helpWidth: context.helpWidth,
|
|
3069
3069
|
outputHasColors: context.hasColors
|
|
3070
3070
|
});
|
|
3071
|
-
const
|
|
3072
|
-
if (context.hasColors) return
|
|
3073
|
-
return this._outputConfiguration.stripColor(
|
|
3071
|
+
const text2 = helper.formatHelp(this, helper);
|
|
3072
|
+
if (context.hasColors) return text2;
|
|
3073
|
+
return this._outputConfiguration.stripColor(text2);
|
|
3074
3074
|
}
|
|
3075
3075
|
/**
|
|
3076
3076
|
* @typedef HelpContext
|
|
@@ -3224,7 +3224,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3224
3224
|
* @param {(string | Function)} text - string to add, or a function returning a string
|
|
3225
3225
|
* @return {Command} `this` command for chaining
|
|
3226
3226
|
*/
|
|
3227
|
-
addHelpText(position,
|
|
3227
|
+
addHelpText(position, text2) {
|
|
3228
3228
|
const allowedValues = ["beforeAll", "before", "after", "afterAll"];
|
|
3229
3229
|
if (!allowedValues.includes(position)) {
|
|
3230
3230
|
throw new Error(`Unexpected value for position to addHelpText.
|
|
@@ -3233,10 +3233,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3233
3233
|
const helpEvent = `${position}Help`;
|
|
3234
3234
|
this.on(helpEvent, (context) => {
|
|
3235
3235
|
let helpStr;
|
|
3236
|
-
if (typeof
|
|
3237
|
-
helpStr =
|
|
3236
|
+
if (typeof text2 === "function") {
|
|
3237
|
+
helpStr = text2({ error: context.error, command: context.command });
|
|
3238
3238
|
} else {
|
|
3239
|
-
helpStr =
|
|
3239
|
+
helpStr = text2;
|
|
3240
3240
|
}
|
|
3241
3241
|
if (helpStr) {
|
|
3242
3242
|
context.write(`${helpStr}
|
|
@@ -6268,22 +6268,22 @@ var require_compile = __commonJS({
|
|
|
6268
6268
|
}
|
|
6269
6269
|
}
|
|
6270
6270
|
exports2.compileSchema = compileSchema;
|
|
6271
|
-
function resolveRef(
|
|
6271
|
+
function resolveRef(root2, baseId, ref) {
|
|
6272
6272
|
var _a;
|
|
6273
6273
|
ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, ref);
|
|
6274
|
-
const schOrFunc =
|
|
6274
|
+
const schOrFunc = root2.refs[ref];
|
|
6275
6275
|
if (schOrFunc)
|
|
6276
6276
|
return schOrFunc;
|
|
6277
|
-
let _sch = resolve10.call(this,
|
|
6277
|
+
let _sch = resolve10.call(this, root2, ref);
|
|
6278
6278
|
if (_sch === void 0) {
|
|
6279
|
-
const schema = (_a =
|
|
6279
|
+
const schema = (_a = root2.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
6280
6280
|
const { schemaId } = this.opts;
|
|
6281
6281
|
if (schema)
|
|
6282
|
-
_sch = new SchemaEnv({ schema, schemaId, root, baseId });
|
|
6282
|
+
_sch = new SchemaEnv({ schema, schemaId, root: root2, baseId });
|
|
6283
6283
|
}
|
|
6284
6284
|
if (_sch === void 0)
|
|
6285
6285
|
return;
|
|
6286
|
-
return
|
|
6286
|
+
return root2.refs[ref] = inlineOrCompile.call(this, _sch);
|
|
6287
6287
|
}
|
|
6288
6288
|
exports2.resolveRef = resolveRef;
|
|
6289
6289
|
function inlineOrCompile(sch) {
|
|
@@ -6301,23 +6301,23 @@ var require_compile = __commonJS({
|
|
|
6301
6301
|
function sameSchemaEnv(s1, s2) {
|
|
6302
6302
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
6303
6303
|
}
|
|
6304
|
-
function resolve10(
|
|
6304
|
+
function resolve10(root2, ref) {
|
|
6305
6305
|
let sch;
|
|
6306
6306
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
6307
6307
|
ref = sch;
|
|
6308
|
-
return sch || this.schemas[ref] || resolveSchema.call(this,
|
|
6308
|
+
return sch || this.schemas[ref] || resolveSchema.call(this, root2, ref);
|
|
6309
6309
|
}
|
|
6310
|
-
function resolveSchema(
|
|
6310
|
+
function resolveSchema(root2, ref) {
|
|
6311
6311
|
const p = this.opts.uriResolver.parse(ref);
|
|
6312
6312
|
const refPath = (0, resolve_1._getFullPath)(this.opts.uriResolver, p);
|
|
6313
|
-
let baseId = (0, resolve_1.getFullPath)(this.opts.uriResolver,
|
|
6314
|
-
if (Object.keys(
|
|
6315
|
-
return getJsonPointer.call(this, p,
|
|
6313
|
+
let baseId = (0, resolve_1.getFullPath)(this.opts.uriResolver, root2.baseId, void 0);
|
|
6314
|
+
if (Object.keys(root2.schema).length > 0 && refPath === baseId) {
|
|
6315
|
+
return getJsonPointer.call(this, p, root2);
|
|
6316
6316
|
}
|
|
6317
6317
|
const id = (0, resolve_1.normalizeId)(refPath);
|
|
6318
6318
|
const schOrRef = this.refs[id] || this.schemas[id];
|
|
6319
6319
|
if (typeof schOrRef == "string") {
|
|
6320
|
-
const sch = resolveSchema.call(this,
|
|
6320
|
+
const sch = resolveSchema.call(this, root2, schOrRef);
|
|
6321
6321
|
if (typeof (sch === null || sch === void 0 ? void 0 : sch.schema) !== "object")
|
|
6322
6322
|
return;
|
|
6323
6323
|
return getJsonPointer.call(this, p, sch);
|
|
@@ -6332,7 +6332,7 @@ var require_compile = __commonJS({
|
|
|
6332
6332
|
const schId = schema[schemaId];
|
|
6333
6333
|
if (schId)
|
|
6334
6334
|
baseId = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schId);
|
|
6335
|
-
return new SchemaEnv({ schema, schemaId, root, baseId });
|
|
6335
|
+
return new SchemaEnv({ schema, schemaId, root: root2, baseId });
|
|
6336
6336
|
}
|
|
6337
6337
|
return getJsonPointer.call(this, p, schOrRef);
|
|
6338
6338
|
}
|
|
@@ -6344,7 +6344,7 @@ var require_compile = __commonJS({
|
|
|
6344
6344
|
"dependencies",
|
|
6345
6345
|
"definitions"
|
|
6346
6346
|
]);
|
|
6347
|
-
function getJsonPointer(parsedRef, { baseId, schema, root }) {
|
|
6347
|
+
function getJsonPointer(parsedRef, { baseId, schema, root: root2 }) {
|
|
6348
6348
|
var _a;
|
|
6349
6349
|
if (((_a = parsedRef.fragment) === null || _a === void 0 ? void 0 : _a[0]) !== "/")
|
|
6350
6350
|
return;
|
|
@@ -6363,10 +6363,10 @@ var require_compile = __commonJS({
|
|
|
6363
6363
|
let env;
|
|
6364
6364
|
if (typeof schema != "boolean" && schema.$ref && !(0, util_1.schemaHasRulesButRef)(schema, this.RULES)) {
|
|
6365
6365
|
const $ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schema.$ref);
|
|
6366
|
-
env = resolveSchema.call(this,
|
|
6366
|
+
env = resolveSchema.call(this, root2, $ref);
|
|
6367
6367
|
}
|
|
6368
6368
|
const { schemaId } = this.opts;
|
|
6369
|
-
env = env || new SchemaEnv({ schema, schemaId, root, baseId });
|
|
6369
|
+
env = env || new SchemaEnv({ schema, schemaId, root: root2, baseId });
|
|
6370
6370
|
if (env.schema !== env.root.schema)
|
|
6371
6371
|
return env;
|
|
6372
6372
|
return void 0;
|
|
@@ -6516,8 +6516,8 @@ var require_utils = __commonJS({
|
|
|
6516
6516
|
}
|
|
6517
6517
|
return ind;
|
|
6518
6518
|
}
|
|
6519
|
-
function removeDotSegments(
|
|
6520
|
-
let input =
|
|
6519
|
+
function removeDotSegments(path19) {
|
|
6520
|
+
let input = path19;
|
|
6521
6521
|
const output = [];
|
|
6522
6522
|
let nextSlash = -1;
|
|
6523
6523
|
let len = 0;
|
|
@@ -6716,8 +6716,8 @@ var require_schemes = __commonJS({
|
|
|
6716
6716
|
wsComponent.secure = void 0;
|
|
6717
6717
|
}
|
|
6718
6718
|
if (wsComponent.resourceName) {
|
|
6719
|
-
const [
|
|
6720
|
-
wsComponent.path =
|
|
6719
|
+
const [path19, query] = wsComponent.resourceName.split("?");
|
|
6720
|
+
wsComponent.path = path19 && path19 !== "/" ? path19 : void 0;
|
|
6721
6721
|
wsComponent.query = query;
|
|
6722
6722
|
wsComponent.resourceName = void 0;
|
|
6723
6723
|
}
|
|
@@ -7408,8 +7408,8 @@ var require_core = __commonJS({
|
|
|
7408
7408
|
keyRef = sch;
|
|
7409
7409
|
if (sch === void 0) {
|
|
7410
7410
|
const { schemaId } = this.opts;
|
|
7411
|
-
const
|
|
7412
|
-
sch = compile_1.resolveSchema.call(this,
|
|
7411
|
+
const root2 = new compile_1.SchemaEnv({ schema: {}, schemaId });
|
|
7412
|
+
sch = compile_1.resolveSchema.call(this, root2, keyRef);
|
|
7413
7413
|
if (!sch)
|
|
7414
7414
|
return;
|
|
7415
7415
|
this.refs[keyRef] = sch;
|
|
@@ -7518,7 +7518,7 @@ var require_core = __commonJS({
|
|
|
7518
7518
|
errorsText(errors = this.errors, { separator = ", ", dataVar = "data" } = {}) {
|
|
7519
7519
|
if (!errors || errors.length === 0)
|
|
7520
7520
|
return "No errors";
|
|
7521
|
-
return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((
|
|
7521
|
+
return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((text2, msg) => text2 + separator + msg);
|
|
7522
7522
|
}
|
|
7523
7523
|
$dataMetaSchema(metaSchema, keywordsJsonPointers) {
|
|
7524
7524
|
const rules = this.RULES.all;
|
|
@@ -7770,20 +7770,20 @@ var require_ref = __commonJS({
|
|
|
7770
7770
|
code(cxt) {
|
|
7771
7771
|
const { gen, schema: $ref, it } = cxt;
|
|
7772
7772
|
const { baseId, schemaEnv: env, validateName, opts, self } = it;
|
|
7773
|
-
const { root } = env;
|
|
7774
|
-
if (($ref === "#" || $ref === "#/") && baseId ===
|
|
7773
|
+
const { root: root2 } = env;
|
|
7774
|
+
if (($ref === "#" || $ref === "#/") && baseId === root2.baseId)
|
|
7775
7775
|
return callRootRef();
|
|
7776
|
-
const schOrEnv = compile_1.resolveRef.call(self,
|
|
7776
|
+
const schOrEnv = compile_1.resolveRef.call(self, root2, baseId, $ref);
|
|
7777
7777
|
if (schOrEnv === void 0)
|
|
7778
7778
|
throw new ref_error_1.default(it.opts.uriResolver, baseId, $ref);
|
|
7779
7779
|
if (schOrEnv instanceof compile_1.SchemaEnv)
|
|
7780
7780
|
return callValidate(schOrEnv);
|
|
7781
7781
|
return inlineRefSchema(schOrEnv);
|
|
7782
7782
|
function callRootRef() {
|
|
7783
|
-
if (env ===
|
|
7783
|
+
if (env === root2)
|
|
7784
7784
|
return callRef(cxt, validateName, env, env.$async);
|
|
7785
|
-
const rootName = gen.scopeValue("root", { ref:
|
|
7786
|
-
return callRef(cxt, (0, codegen_1._)`${rootName}.validate`,
|
|
7785
|
+
const rootName = gen.scopeValue("root", { ref: root2 });
|
|
7786
|
+
return callRef(cxt, (0, codegen_1._)`${rootName}.validate`, root2, root2.$async);
|
|
7787
7787
|
}
|
|
7788
7788
|
function callValidate(sch) {
|
|
7789
7789
|
const v = getValidate(cxt, sch);
|
|
@@ -10079,12 +10079,12 @@ var require_dist = __commonJS({
|
|
|
10079
10079
|
throw new Error(`Unknown format "${name}"`);
|
|
10080
10080
|
return f;
|
|
10081
10081
|
};
|
|
10082
|
-
function addFormats(ajv, list,
|
|
10082
|
+
function addFormats(ajv, list, fs20, exportName) {
|
|
10083
10083
|
var _a;
|
|
10084
10084
|
var _b;
|
|
10085
10085
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
10086
10086
|
for (const f of list)
|
|
10087
|
-
ajv.addFormat(f,
|
|
10087
|
+
ajv.addFormat(f, fs20[f]);
|
|
10088
10088
|
}
|
|
10089
10089
|
module2.exports = exports2 = formatsPlugin;
|
|
10090
10090
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -10097,8 +10097,8 @@ var require_windows = __commonJS({
|
|
|
10097
10097
|
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.js"(exports2, module2) {
|
|
10098
10098
|
module2.exports = isexe;
|
|
10099
10099
|
isexe.sync = sync;
|
|
10100
|
-
var
|
|
10101
|
-
function checkPathExt(
|
|
10100
|
+
var fs20 = require("fs");
|
|
10101
|
+
function checkPathExt(path19, options) {
|
|
10102
10102
|
var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
|
|
10103
10103
|
if (!pathext) {
|
|
10104
10104
|
return true;
|
|
@@ -10109,25 +10109,25 @@ var require_windows = __commonJS({
|
|
|
10109
10109
|
}
|
|
10110
10110
|
for (var i = 0; i < pathext.length; i++) {
|
|
10111
10111
|
var p = pathext[i].toLowerCase();
|
|
10112
|
-
if (p &&
|
|
10112
|
+
if (p && path19.substr(-p.length).toLowerCase() === p) {
|
|
10113
10113
|
return true;
|
|
10114
10114
|
}
|
|
10115
10115
|
}
|
|
10116
10116
|
return false;
|
|
10117
10117
|
}
|
|
10118
|
-
function checkStat(stat,
|
|
10118
|
+
function checkStat(stat, path19, options) {
|
|
10119
10119
|
if (!stat.isSymbolicLink() && !stat.isFile()) {
|
|
10120
10120
|
return false;
|
|
10121
10121
|
}
|
|
10122
|
-
return checkPathExt(
|
|
10122
|
+
return checkPathExt(path19, options);
|
|
10123
10123
|
}
|
|
10124
|
-
function isexe(
|
|
10125
|
-
|
|
10126
|
-
cb(er, er ? false : checkStat(stat,
|
|
10124
|
+
function isexe(path19, options, cb) {
|
|
10125
|
+
fs20.stat(path19, function(er, stat) {
|
|
10126
|
+
cb(er, er ? false : checkStat(stat, path19, options));
|
|
10127
10127
|
});
|
|
10128
10128
|
}
|
|
10129
|
-
function sync(
|
|
10130
|
-
return checkStat(
|
|
10129
|
+
function sync(path19, options) {
|
|
10130
|
+
return checkStat(fs20.statSync(path19), path19, options);
|
|
10131
10131
|
}
|
|
10132
10132
|
}
|
|
10133
10133
|
});
|
|
@@ -10137,14 +10137,14 @@ var require_mode = __commonJS({
|
|
|
10137
10137
|
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.js"(exports2, module2) {
|
|
10138
10138
|
module2.exports = isexe;
|
|
10139
10139
|
isexe.sync = sync;
|
|
10140
|
-
var
|
|
10141
|
-
function isexe(
|
|
10142
|
-
|
|
10140
|
+
var fs20 = require("fs");
|
|
10141
|
+
function isexe(path19, options, cb) {
|
|
10142
|
+
fs20.stat(path19, function(er, stat) {
|
|
10143
10143
|
cb(er, er ? false : checkStat(stat, options));
|
|
10144
10144
|
});
|
|
10145
10145
|
}
|
|
10146
|
-
function sync(
|
|
10147
|
-
return checkStat(
|
|
10146
|
+
function sync(path19, options) {
|
|
10147
|
+
return checkStat(fs20.statSync(path19), options);
|
|
10148
10148
|
}
|
|
10149
10149
|
function checkStat(stat, options) {
|
|
10150
10150
|
return stat.isFile() && checkMode(stat, options);
|
|
@@ -10168,7 +10168,7 @@ var require_mode = __commonJS({
|
|
|
10168
10168
|
// ../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js
|
|
10169
10169
|
var require_isexe = __commonJS({
|
|
10170
10170
|
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js"(exports2, module2) {
|
|
10171
|
-
var
|
|
10171
|
+
var fs20 = require("fs");
|
|
10172
10172
|
var core;
|
|
10173
10173
|
if (process.platform === "win32" || global.TESTING_WINDOWS) {
|
|
10174
10174
|
core = require_windows();
|
|
@@ -10177,7 +10177,7 @@ var require_isexe = __commonJS({
|
|
|
10177
10177
|
}
|
|
10178
10178
|
module2.exports = isexe;
|
|
10179
10179
|
isexe.sync = sync;
|
|
10180
|
-
function isexe(
|
|
10180
|
+
function isexe(path19, options, cb) {
|
|
10181
10181
|
if (typeof options === "function") {
|
|
10182
10182
|
cb = options;
|
|
10183
10183
|
options = {};
|
|
@@ -10187,7 +10187,7 @@ var require_isexe = __commonJS({
|
|
|
10187
10187
|
throw new TypeError("callback not provided");
|
|
10188
10188
|
}
|
|
10189
10189
|
return new Promise(function(resolve10, reject) {
|
|
10190
|
-
isexe(
|
|
10190
|
+
isexe(path19, options || {}, function(er, is) {
|
|
10191
10191
|
if (er) {
|
|
10192
10192
|
reject(er);
|
|
10193
10193
|
} else {
|
|
@@ -10196,7 +10196,7 @@ var require_isexe = __commonJS({
|
|
|
10196
10196
|
});
|
|
10197
10197
|
});
|
|
10198
10198
|
}
|
|
10199
|
-
core(
|
|
10199
|
+
core(path19, options || {}, function(er, is) {
|
|
10200
10200
|
if (er) {
|
|
10201
10201
|
if (er.code === "EACCES" || options && options.ignoreErrors) {
|
|
10202
10202
|
er = null;
|
|
@@ -10206,9 +10206,9 @@ var require_isexe = __commonJS({
|
|
|
10206
10206
|
cb(er, is);
|
|
10207
10207
|
});
|
|
10208
10208
|
}
|
|
10209
|
-
function sync(
|
|
10209
|
+
function sync(path19, options) {
|
|
10210
10210
|
try {
|
|
10211
|
-
return core.sync(
|
|
10211
|
+
return core.sync(path19, options || {});
|
|
10212
10212
|
} catch (er) {
|
|
10213
10213
|
if (options && options.ignoreErrors || er.code === "EACCES") {
|
|
10214
10214
|
return false;
|
|
@@ -10224,7 +10224,7 @@ var require_isexe = __commonJS({
|
|
|
10224
10224
|
var require_which = __commonJS({
|
|
10225
10225
|
"../../node_modules/.pnpm/which@2.0.2/node_modules/which/which.js"(exports2, module2) {
|
|
10226
10226
|
var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
|
|
10227
|
-
var
|
|
10227
|
+
var path19 = require("path");
|
|
10228
10228
|
var COLON = isWindows ? ";" : ":";
|
|
10229
10229
|
var isexe = require_isexe();
|
|
10230
10230
|
var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
|
|
@@ -10262,7 +10262,7 @@ var require_which = __commonJS({
|
|
|
10262
10262
|
return opt.all && found.length ? resolve10(found) : reject(getNotFoundError(cmd));
|
|
10263
10263
|
const ppRaw = pathEnv[i];
|
|
10264
10264
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
10265
|
-
const pCmd =
|
|
10265
|
+
const pCmd = path19.join(pathPart, cmd);
|
|
10266
10266
|
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
10267
10267
|
resolve10(subStep(p, i, 0));
|
|
10268
10268
|
});
|
|
@@ -10289,7 +10289,7 @@ var require_which = __commonJS({
|
|
|
10289
10289
|
for (let i = 0; i < pathEnv.length; i++) {
|
|
10290
10290
|
const ppRaw = pathEnv[i];
|
|
10291
10291
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
10292
|
-
const pCmd =
|
|
10292
|
+
const pCmd = path19.join(pathPart, cmd);
|
|
10293
10293
|
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
10294
10294
|
for (let j = 0; j < pathExt.length; j++) {
|
|
10295
10295
|
const cur = p + pathExt[j];
|
|
@@ -10337,7 +10337,7 @@ var require_path_key = __commonJS({
|
|
|
10337
10337
|
var require_resolveCommand = __commonJS({
|
|
10338
10338
|
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js"(exports2, module2) {
|
|
10339
10339
|
"use strict";
|
|
10340
|
-
var
|
|
10340
|
+
var path19 = require("path");
|
|
10341
10341
|
var which = require_which();
|
|
10342
10342
|
var getPathKey = require_path_key();
|
|
10343
10343
|
function resolveCommandAttempt(parsed, withoutPathExt) {
|
|
@@ -10355,7 +10355,7 @@ var require_resolveCommand = __commonJS({
|
|
|
10355
10355
|
try {
|
|
10356
10356
|
resolved = which.sync(parsed.command, {
|
|
10357
10357
|
path: env[getPathKey({ env })],
|
|
10358
|
-
pathExt: withoutPathExt ?
|
|
10358
|
+
pathExt: withoutPathExt ? path19.delimiter : void 0
|
|
10359
10359
|
});
|
|
10360
10360
|
} catch (e) {
|
|
10361
10361
|
} finally {
|
|
@@ -10364,7 +10364,7 @@ var require_resolveCommand = __commonJS({
|
|
|
10364
10364
|
}
|
|
10365
10365
|
}
|
|
10366
10366
|
if (resolved) {
|
|
10367
|
-
resolved =
|
|
10367
|
+
resolved = path19.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
|
|
10368
10368
|
}
|
|
10369
10369
|
return resolved;
|
|
10370
10370
|
}
|
|
@@ -10418,8 +10418,8 @@ var require_shebang_command = __commonJS({
|
|
|
10418
10418
|
if (!match) {
|
|
10419
10419
|
return null;
|
|
10420
10420
|
}
|
|
10421
|
-
const [
|
|
10422
|
-
const binary =
|
|
10421
|
+
const [path19, argument] = match[0].replace(/#! ?/, "").split(" ");
|
|
10422
|
+
const binary = path19.split("/").pop();
|
|
10423
10423
|
if (binary === "env") {
|
|
10424
10424
|
return argument;
|
|
10425
10425
|
}
|
|
@@ -10432,16 +10432,16 @@ var require_shebang_command = __commonJS({
|
|
|
10432
10432
|
var require_readShebang = __commonJS({
|
|
10433
10433
|
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js"(exports2, module2) {
|
|
10434
10434
|
"use strict";
|
|
10435
|
-
var
|
|
10435
|
+
var fs20 = require("fs");
|
|
10436
10436
|
var shebangCommand = require_shebang_command();
|
|
10437
10437
|
function readShebang(command) {
|
|
10438
10438
|
const size = 150;
|
|
10439
10439
|
const buffer = Buffer.alloc(size);
|
|
10440
10440
|
let fd;
|
|
10441
10441
|
try {
|
|
10442
|
-
fd =
|
|
10443
|
-
|
|
10444
|
-
|
|
10442
|
+
fd = fs20.openSync(command, "r");
|
|
10443
|
+
fs20.readSync(fd, buffer, 0, size, 0);
|
|
10444
|
+
fs20.closeSync(fd);
|
|
10445
10445
|
} catch (e) {
|
|
10446
10446
|
}
|
|
10447
10447
|
return shebangCommand(buffer.toString());
|
|
@@ -10454,7 +10454,7 @@ var require_readShebang = __commonJS({
|
|
|
10454
10454
|
var require_parse = __commonJS({
|
|
10455
10455
|
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js"(exports2, module2) {
|
|
10456
10456
|
"use strict";
|
|
10457
|
-
var
|
|
10457
|
+
var path19 = require("path");
|
|
10458
10458
|
var resolveCommand = require_resolveCommand();
|
|
10459
10459
|
var escape2 = require_escape();
|
|
10460
10460
|
var readShebang = require_readShebang();
|
|
@@ -10479,7 +10479,7 @@ var require_parse = __commonJS({
|
|
|
10479
10479
|
const needsShell = !isExecutableRegExp.test(commandFile);
|
|
10480
10480
|
if (parsed.options.forceShell || needsShell) {
|
|
10481
10481
|
const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
|
|
10482
|
-
parsed.command =
|
|
10482
|
+
parsed.command = path19.normalize(parsed.command);
|
|
10483
10483
|
parsed.command = escape2.command(parsed.command);
|
|
10484
10484
|
parsed.args = parsed.args.map((arg) => escape2.argument(arg, needsDoubleEscapeMetaChars));
|
|
10485
10485
|
const shellCommand = [parsed.command].concat(parsed.args).join(" ");
|
|
@@ -10575,7 +10575,7 @@ var require_cross_spawn = __commonJS({
|
|
|
10575
10575
|
enoent.hookChildProcess(spawned, parsed);
|
|
10576
10576
|
return spawned;
|
|
10577
10577
|
}
|
|
10578
|
-
function
|
|
10578
|
+
function spawnSync4(command, args, options) {
|
|
10579
10579
|
const parsed = parse3(command, args, options);
|
|
10580
10580
|
const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
|
|
10581
10581
|
result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
|
|
@@ -10583,7 +10583,7 @@ var require_cross_spawn = __commonJS({
|
|
|
10583
10583
|
}
|
|
10584
10584
|
module2.exports = spawn4;
|
|
10585
10585
|
module2.exports.spawn = spawn4;
|
|
10586
|
-
module2.exports.sync =
|
|
10586
|
+
module2.exports.sync = spawnSync4;
|
|
10587
10587
|
module2.exports._parse = parse3;
|
|
10588
10588
|
module2.exports._enoent = enoent;
|
|
10589
10589
|
}
|
|
@@ -10637,11 +10637,11 @@ var CliEvidence = class {
|
|
|
10637
10637
|
logFd;
|
|
10638
10638
|
teeWrite;
|
|
10639
10639
|
constructor(directory, provenance, command) {
|
|
10640
|
-
const
|
|
10641
|
-
fs.mkdirSync(
|
|
10642
|
-
this.resultFile = path.join(
|
|
10643
|
-
this.diagnosticsFile = path.join(
|
|
10644
|
-
this.executionFile = path.join(
|
|
10640
|
+
const root2 = path.resolve(directory);
|
|
10641
|
+
fs.mkdirSync(root2);
|
|
10642
|
+
this.resultFile = path.join(root2, "result.json");
|
|
10643
|
+
this.diagnosticsFile = path.join(root2, "diagnostics.log");
|
|
10644
|
+
this.executionFile = path.join(root2, "execution.json");
|
|
10645
10645
|
this.state = {
|
|
10646
10646
|
schemaVersion: 1,
|
|
10647
10647
|
command,
|
|
@@ -10799,28 +10799,28 @@ var UNSUPPORTED_SCHEMA_KEYWORDS = [
|
|
|
10799
10799
|
"propertyNames",
|
|
10800
10800
|
"unevaluatedProperties"
|
|
10801
10801
|
];
|
|
10802
|
-
function unsupportedSchemaConstraint(schemaValue,
|
|
10802
|
+
function unsupportedSchemaConstraint(schemaValue, path19 = "inputSchema") {
|
|
10803
10803
|
const schema = record(schemaValue);
|
|
10804
|
-
if (!schema) return
|
|
10804
|
+
if (!schema) return path19;
|
|
10805
10805
|
for (const keyword of UNSUPPORTED_SCHEMA_KEYWORDS) {
|
|
10806
|
-
if (Object.prototype.hasOwnProperty.call(schema, keyword)) return `${
|
|
10806
|
+
if (Object.prototype.hasOwnProperty.call(schema, keyword)) return `${path19}.${keyword}`;
|
|
10807
10807
|
}
|
|
10808
10808
|
const properties = record(schema.properties);
|
|
10809
10809
|
if (properties) {
|
|
10810
10810
|
for (const [name, property] of Object.entries(properties)) {
|
|
10811
|
-
const unsupported = unsupportedSchemaConstraint(property, `${
|
|
10811
|
+
const unsupported = unsupportedSchemaConstraint(property, `${path19}.properties.${name}`);
|
|
10812
10812
|
if (unsupported) return unsupported;
|
|
10813
10813
|
}
|
|
10814
10814
|
}
|
|
10815
10815
|
if (schema.items !== void 0) {
|
|
10816
|
-
const unsupported = unsupportedSchemaConstraint(schema.items, `${
|
|
10816
|
+
const unsupported = unsupportedSchemaConstraint(schema.items, `${path19}.items`);
|
|
10817
10817
|
if (unsupported) return unsupported;
|
|
10818
10818
|
}
|
|
10819
10819
|
return void 0;
|
|
10820
10820
|
}
|
|
10821
|
-
function explicitValue(schemaValue,
|
|
10821
|
+
function explicitValue(schemaValue, path19) {
|
|
10822
10822
|
const schema = record(schemaValue);
|
|
10823
|
-
if (!schema) return { available: false, missing: [
|
|
10823
|
+
if (!schema) return { available: false, missing: [path19] };
|
|
10824
10824
|
if (Object.prototype.hasOwnProperty.call(schema, "example")) {
|
|
10825
10825
|
return { available: true, value: cloneValue(schema.example), missing: [] };
|
|
10826
10826
|
}
|
|
@@ -10842,13 +10842,13 @@ function explicitValue(schemaValue, path18) {
|
|
|
10842
10842
|
const value = {};
|
|
10843
10843
|
const missing = [];
|
|
10844
10844
|
for (const name of required2) {
|
|
10845
|
-
const child = explicitValue(properties[name],
|
|
10845
|
+
const child = explicitValue(properties[name], path19 ? `${path19}.${name}` : name);
|
|
10846
10846
|
if (child.available) value[name] = child.value;
|
|
10847
10847
|
missing.push(...child.missing);
|
|
10848
10848
|
}
|
|
10849
10849
|
return { available: missing.length === 0, value, missing };
|
|
10850
10850
|
}
|
|
10851
|
-
return { available: false, missing: [
|
|
10851
|
+
return { available: false, missing: [path19] };
|
|
10852
10852
|
}
|
|
10853
10853
|
function buildArgumentExample(tool) {
|
|
10854
10854
|
const schema = record(tool.inputSchema);
|
|
@@ -10939,11 +10939,11 @@ function buildCliUsage(tool, tools) {
|
|
|
10939
10939
|
}
|
|
10940
10940
|
|
|
10941
10941
|
// src/index.ts
|
|
10942
|
-
var
|
|
10943
|
-
var
|
|
10942
|
+
var fs19 = __toESM(require("node:fs"), 1);
|
|
10943
|
+
var path18 = __toESM(require("node:path"), 1);
|
|
10944
10944
|
|
|
10945
10945
|
// src/cli.ts
|
|
10946
|
-
var
|
|
10946
|
+
var fs12 = __toESM(require("fs"), 1);
|
|
10947
10947
|
var path11 = __toESM(require("path"), 1);
|
|
10948
10948
|
|
|
10949
10949
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/core.js
|
|
@@ -11141,10 +11141,10 @@ function assignProp(target, prop, value) {
|
|
|
11141
11141
|
configurable: true
|
|
11142
11142
|
});
|
|
11143
11143
|
}
|
|
11144
|
-
function getElementAtPath(obj,
|
|
11145
|
-
if (!
|
|
11144
|
+
function getElementAtPath(obj, path19) {
|
|
11145
|
+
if (!path19)
|
|
11146
11146
|
return obj;
|
|
11147
|
-
return
|
|
11147
|
+
return path19.reduce((acc, key) => acc?.[key], obj);
|
|
11148
11148
|
}
|
|
11149
11149
|
function promiseAllObject(promisesObj) {
|
|
11150
11150
|
const keys = Object.keys(promisesObj);
|
|
@@ -11464,11 +11464,11 @@ function aborted(x, startIndex = 0) {
|
|
|
11464
11464
|
}
|
|
11465
11465
|
return false;
|
|
11466
11466
|
}
|
|
11467
|
-
function prefixIssues(
|
|
11467
|
+
function prefixIssues(path19, issues) {
|
|
11468
11468
|
return issues.map((iss) => {
|
|
11469
11469
|
var _a;
|
|
11470
11470
|
(_a = iss).path ?? (_a.path = []);
|
|
11471
|
-
iss.path.unshift(
|
|
11471
|
+
iss.path.unshift(path19);
|
|
11472
11472
|
return iss;
|
|
11473
11473
|
});
|
|
11474
11474
|
}
|
|
@@ -18612,12 +18612,12 @@ function applyInstallerMirror(config2, mirror) {
|
|
|
18612
18612
|
};
|
|
18613
18613
|
}
|
|
18614
18614
|
function parseInstallerOverride(raw) {
|
|
18615
|
-
const
|
|
18616
|
-
if (!
|
|
18615
|
+
const text2 = raw?.trim();
|
|
18616
|
+
if (!text2)
|
|
18617
18617
|
return {};
|
|
18618
18618
|
let parsed;
|
|
18619
18619
|
try {
|
|
18620
|
-
parsed = JSON.parse(
|
|
18620
|
+
parsed = JSON.parse(text2);
|
|
18621
18621
|
} catch (error2) {
|
|
18622
18622
|
throw new Error(`ZLT_ASSISTANT_INSTALLER_OVERRIDE \u4E0D\u662F\u5408\u6CD5 JSON: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
18623
18623
|
}
|
|
@@ -19493,23 +19493,23 @@ var AssistantMasterIpcClient = class {
|
|
|
19493
19493
|
}
|
|
19494
19494
|
};
|
|
19495
19495
|
async function startManualServices(workRoot, zltContent, config2, onProgress, trace = silentRuntimeTrace, options = {}) {
|
|
19496
|
-
const
|
|
19496
|
+
const client2 = new AssistantMasterIpcClient();
|
|
19497
19497
|
try {
|
|
19498
|
-
await trace.run("\u8FDE\u63A5\u667A\u80FD\u7BA1\u5BB6\u4E3B\u7BA1\u9053", () =>
|
|
19499
|
-
await trace.run(options.registerConsumerPid === false ? "\u542F\u52A8\u9ED8\u8BA4\u540E\u53F0\u670D\u52A1\uFF08\u72EC\u7ACBCLI\u4E0D\u767B\u8BB0PID\uFF09" : "\u542F\u52A8\u9ED8\u8BA4\u540E\u53F0\u670D\u52A1\u5E76\u767B\u8BB0\u5BBF\u4E3B\u8FDB\u7A0B", () =>
|
|
19500
|
-
await trace.run("\u8F6E\u8BE2\u540E\u53F0\u670D\u52A1\u542F\u52A8\u72B6\u6001", () =>
|
|
19498
|
+
await trace.run("\u8FDE\u63A5\u667A\u80FD\u7BA1\u5BB6\u4E3B\u7BA1\u9053", () => client2.connect(zltContent, config2, trace), { timeoutMs: config2.ipcConnectTimeout });
|
|
19499
|
+
await trace.run(options.registerConsumerPid === false ? "\u542F\u52A8\u9ED8\u8BA4\u540E\u53F0\u670D\u52A1\uFF08\u72EC\u7ACBCLI\u4E0D\u767B\u8BB0PID\uFF09" : "\u542F\u52A8\u9ED8\u8BA4\u540E\u53F0\u670D\u52A1\u5E76\u767B\u8BB0\u5BBF\u4E3B\u8FDB\u7A0B", () => client2.startDefaultServices(config2, onProgress, trace, options));
|
|
19500
|
+
await trace.run("\u8F6E\u8BE2\u540E\u53F0\u670D\u52A1\u542F\u52A8\u72B6\u6001", () => client2.pollStartupServices(config2, trace), { serviceIndices: config2.startupCheckIndices });
|
|
19501
19501
|
await trace.run("\u7B49\u5F85\u540E\u53F0\u670D\u52A1\u521B\u5EFAZLTAF\u7BA1\u9053", () => waitForPipe(workRoot, "ZLTAF", config2.zltafPipeWait), { timeoutMs: config2.zltafPipeWait });
|
|
19502
19502
|
} finally {
|
|
19503
|
-
await trace.run("\u65AD\u5F00\u4E34\u65F6\u667A\u80FD\u7BA1\u5BB6\u4E3B\u7BA1\u9053\u8FDE\u63A5", () =>
|
|
19503
|
+
await trace.run("\u65AD\u5F00\u4E34\u65F6\u667A\u80FD\u7BA1\u5BB6\u4E3B\u7BA1\u9053\u8FDE\u63A5", () => client2.disconnect());
|
|
19504
19504
|
}
|
|
19505
19505
|
}
|
|
19506
19506
|
async function installBacktestModules(workRoot, zltContent, config2, onProgress, hooks = {}) {
|
|
19507
|
-
const
|
|
19507
|
+
const client2 = new AssistantMasterIpcClient();
|
|
19508
19508
|
try {
|
|
19509
|
-
await
|
|
19510
|
-
return await
|
|
19509
|
+
await client2.connect(zltContent, config2);
|
|
19510
|
+
return await client2.installBacktestModules(workRoot, config2, onProgress, hooks);
|
|
19511
19511
|
} finally {
|
|
19512
|
-
await
|
|
19512
|
+
await client2.disconnect();
|
|
19513
19513
|
}
|
|
19514
19514
|
}
|
|
19515
19515
|
async function waitForPipe(workRoot, pipePrefix, timeout) {
|
|
@@ -19526,18 +19526,18 @@ async function waitForPipe(workRoot, pipePrefix, timeout) {
|
|
|
19526
19526
|
throw new Error(`\u7B49\u5F85 ${pipePrefix} \u7BA1\u9053\u8D85\u65F6`);
|
|
19527
19527
|
}
|
|
19528
19528
|
async function readZltContent(workRoot, temporaryZltFile) {
|
|
19529
|
-
const
|
|
19530
|
-
const
|
|
19531
|
-
const zltFile =
|
|
19532
|
-
return
|
|
19529
|
+
const fs20 = await import("fs");
|
|
19530
|
+
const path19 = await import("path");
|
|
19531
|
+
const zltFile = path19.join(workRoot, temporaryZltFile || "Temporary/zlt");
|
|
19532
|
+
return fs20.existsSync(zltFile) ? fs20.readFileSync(zltFile, "utf-8").trim() : "";
|
|
19533
19533
|
}
|
|
19534
19534
|
async function pipeExists2(pipeName) {
|
|
19535
|
-
const
|
|
19535
|
+
const fs20 = await import("fs");
|
|
19536
19536
|
try {
|
|
19537
19537
|
if (process.platform === "win32") {
|
|
19538
|
-
return
|
|
19538
|
+
return fs20.readdirSync("\\\\.\\pipe\\").includes(pipeName);
|
|
19539
19539
|
}
|
|
19540
|
-
return
|
|
19540
|
+
return fs20.existsSync(`/tmp/${pipeName}`);
|
|
19541
19541
|
} catch {
|
|
19542
19542
|
return false;
|
|
19543
19543
|
}
|
|
@@ -19588,18 +19588,18 @@ function serviceName(index) {
|
|
|
19588
19588
|
}
|
|
19589
19589
|
}
|
|
19590
19590
|
function describeServiceStatus(response) {
|
|
19591
|
-
const
|
|
19592
|
-
const data = isRecord(
|
|
19591
|
+
const record5 = isRecord(response) ? response : {};
|
|
19592
|
+
const data = isRecord(record5.data) ? record5.data : isRecord(record5.Data) ? record5.Data : record5;
|
|
19593
19593
|
const rawStatus = data.status ?? data.Status;
|
|
19594
|
-
const retCode =
|
|
19594
|
+
const retCode = record5.iRet ?? record5.IRet ?? record5.ErrNo;
|
|
19595
19595
|
const ready = isServiceReady(response);
|
|
19596
19596
|
const reason = ready ? "\u670D\u52A1\u72B6\u6001\u4E3A2\u4E14\u5E94\u7B54\u901A\u8FC7\u6210\u529F\u5224\u5B9A" : rawStatus === void 0 ? "\u5E94\u7B54\u7F3A\u5C11\u670D\u52A1\u72B6\u6001\u5B57\u6BB5" : Number(rawStatus) !== 2 ? "\u670D\u52A1\u72B6\u6001\u5C1A\u672A\u8FBE\u5230\u5C31\u7EEA\u503C2" : "\u72B6\u6001\u4E3A2\u4F46\u5E94\u7B54\u9519\u8BEF\u7801\u672A\u901A\u8FC7\u6210\u529F\u5224\u5B9A";
|
|
19597
|
-
const serviceMessage = data.msg ?? data.message ?? data.ErrMsg ??
|
|
19597
|
+
const serviceMessage = data.msg ?? data.message ?? data.ErrMsg ?? record5.msg ?? record5.message ?? record5.ErrMsg;
|
|
19598
19598
|
return {
|
|
19599
19599
|
ready,
|
|
19600
19600
|
rawStatus: rawStatus ?? null,
|
|
19601
19601
|
retCode: retCode ?? null,
|
|
19602
|
-
success:
|
|
19602
|
+
success: record5.success ?? null,
|
|
19603
19603
|
serviceMessage,
|
|
19604
19604
|
reason,
|
|
19605
19605
|
result: `${ready ? "\u5DF2\u5C31\u7EEA" : "\u672A\u5C31\u7EEA"}\uFF1A${reason}${serviceMessage ? `\uFF1B\u670D\u52A1\u6D88\u606F\uFF1A${serviceMessage}` : ""}`
|
|
@@ -19783,8 +19783,8 @@ async function updateRuntimeLeaseActiveJob(handle, runId, active2, options = {})
|
|
|
19783
19783
|
async function releaseRuntimeLease(handle, options = {}) {
|
|
19784
19784
|
const deps = options.deps ?? defaultRuntimeLifecycleDeps;
|
|
19785
19785
|
return withLifecycleLock(handle.workRoot, deps, async (stateDir) => {
|
|
19786
|
-
const
|
|
19787
|
-
if (
|
|
19786
|
+
const record5 = readJson(leasePath(stateDir, handle.token));
|
|
19787
|
+
if (record5 && sameIdentity(record5.holder, handle.holder)) {
|
|
19788
19788
|
fs4.rmSync(leasePath(stateDir, handle.token), { force: true });
|
|
19789
19789
|
}
|
|
19790
19790
|
const recordedOwner = readJson(ownerPath(stateDir));
|
|
@@ -19987,13 +19987,13 @@ function readAndPruneStore(stateDir, deps) {
|
|
|
19987
19987
|
if (!entry.isFile() || !entry.name.endsWith(".json"))
|
|
19988
19988
|
continue;
|
|
19989
19989
|
const filePath = path4.join(leasesDir, entry.name);
|
|
19990
|
-
const
|
|
19991
|
-
const current =
|
|
19992
|
-
if (!
|
|
19990
|
+
const record5 = readJson(filePath);
|
|
19991
|
+
const current = record5 ? deps.inspectProcess(record5.holder.pid) : null;
|
|
19992
|
+
if (!record5 || !current || !sameIdentity(current, record5.holder)) {
|
|
19993
19993
|
fs4.rmSync(filePath, { force: true });
|
|
19994
19994
|
continue;
|
|
19995
19995
|
}
|
|
19996
|
-
leases.push(
|
|
19996
|
+
leases.push(record5);
|
|
19997
19997
|
}
|
|
19998
19998
|
let owner = normalizeRuntimeOwnerRecord(readJson(ownerPath(stateDir)));
|
|
19999
19999
|
if (owner) {
|
|
@@ -20005,21 +20005,21 @@ function readAndPruneStore(stateDir, deps) {
|
|
|
20005
20005
|
}
|
|
20006
20006
|
return { owner, leases };
|
|
20007
20007
|
}
|
|
20008
|
-
function normalizeRuntimeOwnerRecord(
|
|
20009
|
-
if (!
|
|
20008
|
+
function normalizeRuntimeOwnerRecord(record5) {
|
|
20009
|
+
if (!record5)
|
|
20010
20010
|
return null;
|
|
20011
|
-
const activeJobIds = new Set(normalizeRunIds(
|
|
20012
|
-
const legacyBoundJobIds = normalizeRunIds(
|
|
20013
|
-
const legacyResolvedJobIds = new Set(normalizeRunIds(
|
|
20011
|
+
const activeJobIds = new Set(normalizeRunIds(record5.activeJobIds));
|
|
20012
|
+
const legacyBoundJobIds = normalizeRunIds(record5.legacyBoundJobIds);
|
|
20013
|
+
const legacyResolvedJobIds = new Set(normalizeRunIds(record5.legacyResolvedJobIds));
|
|
20014
20014
|
for (const runId of legacyBoundJobIds) {
|
|
20015
20015
|
activeJobIds.add(runId);
|
|
20016
20016
|
legacyResolvedJobIds.delete(runId);
|
|
20017
20017
|
}
|
|
20018
20018
|
return {
|
|
20019
|
-
process:
|
|
20020
|
-
startedAt:
|
|
20019
|
+
process: record5.process,
|
|
20020
|
+
startedAt: record5.startedAt,
|
|
20021
20021
|
activeJobIds: [...activeJobIds].sort(),
|
|
20022
|
-
legacyActiveJobs:
|
|
20022
|
+
legacyActiveJobs: record5.legacyActiveJobs === void 0 ? normalizeLegacyActiveJobs(record5.activeJobs) : normalizeLegacyActiveJobs(record5.legacyActiveJobs),
|
|
20023
20023
|
legacyBoundJobIds,
|
|
20024
20024
|
legacyResolvedJobIds: [...legacyResolvedJobIds].sort()
|
|
20025
20025
|
};
|
|
@@ -21324,8 +21324,8 @@ function downloadFile(url, destination, redirectCount = 0, timeoutMs = 0, initia
|
|
|
21324
21324
|
fail2(error2);
|
|
21325
21325
|
}
|
|
21326
21326
|
};
|
|
21327
|
-
const
|
|
21328
|
-
const request =
|
|
21327
|
+
const client2 = url.startsWith("https:") ? https : http;
|
|
21328
|
+
const request = client2.get(url, {
|
|
21329
21329
|
headers: {
|
|
21330
21330
|
"User-Agent": "ZLT-Quant-Runtime/0.1",
|
|
21331
21331
|
Accept: "application/octet-stream,*/*;q=0.8"
|
|
@@ -21409,8 +21409,8 @@ function getGitExePath(workRoot) {
|
|
|
21409
21409
|
function areBacktestModuleRuntimeFilesPresent(workRoot) {
|
|
21410
21410
|
return fs6.existsSync(getZltafExePath(workRoot)) && fs6.existsSync(getZltafConfigPath(workRoot));
|
|
21411
21411
|
}
|
|
21412
|
-
function assertPathInside(
|
|
21413
|
-
const resolvedRoot = path6.resolve(
|
|
21412
|
+
function assertPathInside(root2, targetPath) {
|
|
21413
|
+
const resolvedRoot = path6.resolve(root2);
|
|
21414
21414
|
const resolvedTarget = path6.resolve(targetPath);
|
|
21415
21415
|
const relative2 = path6.relative(resolvedRoot, resolvedTarget);
|
|
21416
21416
|
if (relative2.startsWith("..") || path6.isAbsolute(relative2)) {
|
|
@@ -21490,9 +21490,54 @@ async function waitForZltafPipe(workRoot, config2, options) {
|
|
|
21490
21490
|
}
|
|
21491
21491
|
|
|
21492
21492
|
// ../zlt-runtime-core/dist/auth.js
|
|
21493
|
-
var
|
|
21493
|
+
var fs8 = __toESM(require("fs"), 1);
|
|
21494
21494
|
var os2 = __toESM(require("os"), 1);
|
|
21495
21495
|
var path7 = __toESM(require("path"), 1);
|
|
21496
|
+
|
|
21497
|
+
// ../zlt-runtime-core/dist/private-path.js
|
|
21498
|
+
var fs7 = __toESM(require("node:fs"), 1);
|
|
21499
|
+
var import_node_child_process = require("node:child_process");
|
|
21500
|
+
function protectPrivatePath(target, directory = false) {
|
|
21501
|
+
if (fs7.lstatSync(target).isSymbolicLink())
|
|
21502
|
+
throw new Error("Private authentication path is invalid");
|
|
21503
|
+
if (process.platform !== "win32") {
|
|
21504
|
+
fs7.chmodSync(target, directory ? 448 : 384);
|
|
21505
|
+
return;
|
|
21506
|
+
}
|
|
21507
|
+
const script = `
|
|
21508
|
+
$ErrorActionPreference = 'Stop'
|
|
21509
|
+
$targetPath = $env:ZLT_AUTH_PRIVATE_PATH
|
|
21510
|
+
$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().User
|
|
21511
|
+
$isDirectory = $env:ZLT_AUTH_PRIVATE_DIRECTORY -eq '1'
|
|
21512
|
+
if ($isDirectory) {
|
|
21513
|
+
$acl = New-Object System.Security.AccessControl.DirectorySecurity
|
|
21514
|
+
$inheritance = [System.Security.AccessControl.InheritanceFlags]'ContainerInherit, ObjectInherit'
|
|
21515
|
+
} else {
|
|
21516
|
+
$acl = New-Object System.Security.AccessControl.FileSecurity
|
|
21517
|
+
$inheritance = [System.Security.AccessControl.InheritanceFlags]::None
|
|
21518
|
+
}
|
|
21519
|
+
$acl.SetOwner($identity)
|
|
21520
|
+
$acl.SetAccessRuleProtection($true, $false)
|
|
21521
|
+
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($identity, 'FullControl', $inheritance, 'None', 'Allow')
|
|
21522
|
+
$acl.AddAccessRule($rule)
|
|
21523
|
+
if ($isDirectory) {
|
|
21524
|
+
[System.IO.Directory]::SetAccessControl($targetPath, $acl)
|
|
21525
|
+
} else {
|
|
21526
|
+
[System.IO.File]::SetAccessControl($targetPath, $acl)
|
|
21527
|
+
}
|
|
21528
|
+
`;
|
|
21529
|
+
const result = (0, import_node_child_process.spawnSync)("powershell.exe", ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", script], {
|
|
21530
|
+
env: { ...process.env, ZLT_AUTH_PRIVATE_PATH: target, ZLT_AUTH_PRIVATE_DIRECTORY: directory ? "1" : "0" },
|
|
21531
|
+
windowsHide: true,
|
|
21532
|
+
timeout: 15e3,
|
|
21533
|
+
encoding: "utf8",
|
|
21534
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
21535
|
+
});
|
|
21536
|
+
if (result.error || result.status !== 0)
|
|
21537
|
+
throw new Error("Could not protect private authentication storage");
|
|
21538
|
+
}
|
|
21539
|
+
|
|
21540
|
+
// ../zlt-runtime-core/dist/auth.js
|
|
21496
21541
|
var DEFAULT_ZLTQUANT_API_BASE = "https://api.zltquant.com";
|
|
21497
21542
|
function resolveZltQuantHome(env = process.env) {
|
|
21498
21543
|
const configuredHome = env.ZLTQUANT_HOME?.trim();
|
|
@@ -21508,9 +21553,9 @@ function resolveCredentialsPath(env = process.env) {
|
|
|
21508
21553
|
}
|
|
21509
21554
|
function readCredentials(env = process.env) {
|
|
21510
21555
|
const credentialsPath = resolveCredentialsPath(env);
|
|
21511
|
-
if (!
|
|
21556
|
+
if (!fs8.existsSync(credentialsPath))
|
|
21512
21557
|
return null;
|
|
21513
|
-
const parsed = JSON.parse(
|
|
21558
|
+
const parsed = JSON.parse(fs8.readFileSync(credentialsPath, "utf-8"));
|
|
21514
21559
|
const apiKey = typeof parsed.apiKey === "string" ? parsed.apiKey.trim() : "";
|
|
21515
21560
|
if (!apiKey)
|
|
21516
21561
|
return null;
|
|
@@ -21540,6 +21585,9 @@ function writeCredentials(input, env = process.env) {
|
|
|
21540
21585
|
throw new Error("ZLTQuant API key is required");
|
|
21541
21586
|
if (!source)
|
|
21542
21587
|
throw new Error("ZLTQuant credential source is required");
|
|
21588
|
+
if (source === "zlt-mcp-device-login" && env.ZLTQUANT_CREDENTIALS?.trim()) {
|
|
21589
|
+
throw new Error("Device login cannot write a custom credential path");
|
|
21590
|
+
}
|
|
21543
21591
|
if (env.ZLTQUANT_CREDENTIALS?.trim() && tryReadCredentials(env)) {
|
|
21544
21592
|
return getAuthStatus(env);
|
|
21545
21593
|
}
|
|
@@ -21550,19 +21598,53 @@ function writeCredentials(input, env = process.env) {
|
|
|
21550
21598
|
source,
|
|
21551
21599
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
21552
21600
|
};
|
|
21553
|
-
|
|
21601
|
+
fs8.mkdirSync(path7.dirname(credentialsPath), { recursive: true });
|
|
21554
21602
|
const tempPath = `${credentialsPath}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`;
|
|
21555
21603
|
try {
|
|
21556
|
-
|
|
21604
|
+
if (source === "zlt-mcp-device-login") {
|
|
21605
|
+
fs8.closeSync(fs8.openSync(tempPath, "wx", 384));
|
|
21606
|
+
protectPrivatePath(tempPath);
|
|
21607
|
+
}
|
|
21608
|
+
fs8.writeFileSync(tempPath, `${JSON.stringify(credentials, null, 2)}
|
|
21557
21609
|
`, { encoding: "utf-8", mode: 384 });
|
|
21558
21610
|
chmodOwnerOnly(tempPath);
|
|
21559
|
-
|
|
21611
|
+
if (source === "zlt-mcp-device-login") {
|
|
21612
|
+
try {
|
|
21613
|
+
fs8.linkSync(tempPath, credentialsPath);
|
|
21614
|
+
} catch (error2) {
|
|
21615
|
+
if (error2.code !== "EEXIST")
|
|
21616
|
+
throw error2;
|
|
21617
|
+
return getAuthStatus(env);
|
|
21618
|
+
}
|
|
21619
|
+
fs8.rmSync(tempPath, { force: true });
|
|
21620
|
+
} else {
|
|
21621
|
+
fs8.renameSync(tempPath, credentialsPath);
|
|
21622
|
+
}
|
|
21560
21623
|
chmodOwnerOnly(credentialsPath);
|
|
21561
21624
|
} finally {
|
|
21562
|
-
|
|
21625
|
+
fs8.rmSync(tempPath, { force: true });
|
|
21563
21626
|
}
|
|
21564
21627
|
return fileAuthStatus(credentialsPath, resolveZltQuantHome(env), credentials);
|
|
21565
21628
|
}
|
|
21629
|
+
function removeCredentials(input, env = process.env) {
|
|
21630
|
+
if (env.ZLTQUANT_CREDENTIALS?.trim())
|
|
21631
|
+
return false;
|
|
21632
|
+
const apiKey = input.apiKey.trim();
|
|
21633
|
+
const source = input.source.trim();
|
|
21634
|
+
if (!apiKey || !source)
|
|
21635
|
+
return false;
|
|
21636
|
+
const credentials = tryReadCredentials(env);
|
|
21637
|
+
if (!credentials || credentials.apiKey !== apiKey || credentials.source !== source)
|
|
21638
|
+
return false;
|
|
21639
|
+
try {
|
|
21640
|
+
fs8.unlinkSync(resolveCredentialsPath(env));
|
|
21641
|
+
return true;
|
|
21642
|
+
} catch (error2) {
|
|
21643
|
+
if (error2.code === "ENOENT")
|
|
21644
|
+
return false;
|
|
21645
|
+
throw error2;
|
|
21646
|
+
}
|
|
21647
|
+
}
|
|
21566
21648
|
function getAuthStatus(env = process.env) {
|
|
21567
21649
|
const credentialsPath = resolveCredentialsPath(env);
|
|
21568
21650
|
const zltquantHome = resolveZltQuantHome(env);
|
|
@@ -21636,7 +21718,7 @@ function tryReadCredentials(env) {
|
|
|
21636
21718
|
}
|
|
21637
21719
|
function chmodOwnerOnly(filePath) {
|
|
21638
21720
|
try {
|
|
21639
|
-
|
|
21721
|
+
fs8.chmodSync(filePath, 384);
|
|
21640
21722
|
} catch {
|
|
21641
21723
|
}
|
|
21642
21724
|
}
|
|
@@ -21652,9 +21734,230 @@ function fileAuthStatus(credentialsPath, zltquantHome, credentials) {
|
|
|
21652
21734
|
};
|
|
21653
21735
|
}
|
|
21654
21736
|
|
|
21737
|
+
// ../zlt-runtime-core/dist/device-auth.js
|
|
21738
|
+
var DeviceAuthorizationError = class extends Error {
|
|
21739
|
+
code;
|
|
21740
|
+
constructor(code, message = code) {
|
|
21741
|
+
super(message);
|
|
21742
|
+
this.name = "DeviceAuthorizationError";
|
|
21743
|
+
this.code = code;
|
|
21744
|
+
}
|
|
21745
|
+
};
|
|
21746
|
+
var DEFAULT_API_BASE = "https://api.zltquant.com";
|
|
21747
|
+
var MAX_RESPONSE_BYTES = 64 * 1024;
|
|
21748
|
+
async function startDeviceAuthorization(options = {}) {
|
|
21749
|
+
const base = validatedBase(options.apiBase || DEFAULT_API_BASE);
|
|
21750
|
+
const issuedAt = (options.now ?? Date.now)();
|
|
21751
|
+
const value = await requestJson(options, base, "/api/v1/auth/device/start", {});
|
|
21752
|
+
if (!record3(value) || !text(value.deviceId) || !text(value.userCode) || !text(value.verificationUri) || !text(value.verificationUriComplete) || !positive(value.expiresIn) || !positive(value.interval))
|
|
21753
|
+
malformed("start");
|
|
21754
|
+
validateVerificationUri(value.verificationUri, base, false);
|
|
21755
|
+
validateVerificationUri(value.verificationUriComplete, base, true, value.userCode);
|
|
21756
|
+
return {
|
|
21757
|
+
deviceId: value.deviceId,
|
|
21758
|
+
userCode: value.userCode,
|
|
21759
|
+
verificationUri: value.verificationUri,
|
|
21760
|
+
verificationUriComplete: value.verificationUriComplete,
|
|
21761
|
+
expiresIn: value.expiresIn,
|
|
21762
|
+
interval: value.interval,
|
|
21763
|
+
issuedAt,
|
|
21764
|
+
gatewayOrigin: base.origin
|
|
21765
|
+
};
|
|
21766
|
+
}
|
|
21767
|
+
async function pollDeviceAuthorization(session, options = {}) {
|
|
21768
|
+
if (!validSession(session))
|
|
21769
|
+
throw new DeviceAuthorizationError("malformed_response", "Device authorization session is invalid");
|
|
21770
|
+
const deviceId = session.deviceId;
|
|
21771
|
+
const now = options.now ?? Date.now;
|
|
21772
|
+
const duration3 = options.maxDurationMs ?? session.expiresIn * 1e3;
|
|
21773
|
+
const deadline = Math.min(session.issuedAt + session.expiresIn * 1e3, session.issuedAt + duration3);
|
|
21774
|
+
const base = validatedBase(options.apiBase || DEFAULT_API_BASE);
|
|
21775
|
+
if (base.origin !== session.gatewayOrigin)
|
|
21776
|
+
throw new DeviceAuthorizationError("invalid_endpoint", "Polling endpoint has an unexpected origin");
|
|
21777
|
+
let interval = Math.max(session.interval, 1);
|
|
21778
|
+
for (let attempt = 0; attempt < (options.maxAttempts ?? 120); attempt += 1) {
|
|
21779
|
+
if (now() >= deadline)
|
|
21780
|
+
throw new DeviceAuthorizationError("expired_token", "Device authorization expired");
|
|
21781
|
+
await wait(options.sleep, Math.min(interval * 1e3, deadline - now()), options.signal);
|
|
21782
|
+
if (now() >= deadline)
|
|
21783
|
+
throw new DeviceAuthorizationError("expired_token", "Device authorization expired");
|
|
21784
|
+
const remaining = deadline - now();
|
|
21785
|
+
const value = await requestJson({ ...options, requestTimeoutMs: Math.min(options.requestTimeoutMs ?? 15e3, remaining) }, base, "/api/v1/auth/device/poll", { deviceId }, true);
|
|
21786
|
+
if (now() >= deadline)
|
|
21787
|
+
throw new DeviceAuthorizationError("expired_token", "Device authorization expired");
|
|
21788
|
+
if (!record3(value))
|
|
21789
|
+
malformed("poll");
|
|
21790
|
+
if (value.error === "authorization_pending")
|
|
21791
|
+
continue;
|
|
21792
|
+
if (value.error === "slow_down") {
|
|
21793
|
+
interval += 5;
|
|
21794
|
+
continue;
|
|
21795
|
+
}
|
|
21796
|
+
if (value.error === "expired_token" || value.error === "access_denied")
|
|
21797
|
+
throw new DeviceAuthorizationError(value.error);
|
|
21798
|
+
if (!text(value.apiKey) || !text(value.apiBase))
|
|
21799
|
+
malformed("poll");
|
|
21800
|
+
const apiBase = validatedBase(value.apiBase);
|
|
21801
|
+
if (apiBase.origin !== base.origin)
|
|
21802
|
+
throw new DeviceAuthorizationError("invalid_endpoint", "Authorized API endpoint has an unexpected origin");
|
|
21803
|
+
return { apiKey: value.apiKey.trim(), apiBase: apiBase.href.replace(/\/$/, "") };
|
|
21804
|
+
}
|
|
21805
|
+
throw new DeviceAuthorizationError("expired_token", "Device authorization polling limit reached");
|
|
21806
|
+
}
|
|
21807
|
+
function persistDeviceAuthorization(grant, env) {
|
|
21808
|
+
const current = getAuthStatus(env);
|
|
21809
|
+
if (current.configured)
|
|
21810
|
+
return { status: "already_configured", authStatus: current };
|
|
21811
|
+
if (env?.ZLTQUANT_CREDENTIALS?.trim())
|
|
21812
|
+
throw new DeviceAuthorizationError("credentials_conflict", "A custom credential path is configured");
|
|
21813
|
+
writeCredentials({ ...grant, source: "zlt-mcp-device-login" }, env);
|
|
21814
|
+
const credentials = readCredentials(env);
|
|
21815
|
+
const authStatus2 = getAuthStatus(env);
|
|
21816
|
+
if (!credentials || credentials.apiKey !== grant.apiKey.trim() || credentials.apiBase !== grant.apiBase.trim().replace(/\/$/, "") || credentials.source !== "zlt-mcp-device-login" || !authStatus2.configured || authStatus2.source !== "file")
|
|
21817
|
+
throw new DeviceAuthorizationError("credentials_conflict", "Persisted device credential is not effective");
|
|
21818
|
+
return { status: "success", authStatus: authStatus2 };
|
|
21819
|
+
}
|
|
21820
|
+
async function requestJson(options, base, path19, payload, allowPoll400 = false) {
|
|
21821
|
+
const controller = new AbortController();
|
|
21822
|
+
const externalAbort = () => controller.abort();
|
|
21823
|
+
if (options.signal?.aborted)
|
|
21824
|
+
controller.abort();
|
|
21825
|
+
else
|
|
21826
|
+
options.signal?.addEventListener("abort", externalAbort, { once: true });
|
|
21827
|
+
const timeout = setTimeout(() => controller.abort(), options.requestTimeoutMs ?? 15e3);
|
|
21828
|
+
try {
|
|
21829
|
+
const response = await (options.fetch ?? globalThis.fetch)(new URL(path19, base), {
|
|
21830
|
+
method: "POST",
|
|
21831
|
+
redirect: "error",
|
|
21832
|
+
headers: { "content-type": "application/json" },
|
|
21833
|
+
body: JSON.stringify(payload),
|
|
21834
|
+
signal: controller.signal
|
|
21835
|
+
});
|
|
21836
|
+
const body = await readBoundedJson(response);
|
|
21837
|
+
if (!response.ok && !(allowPoll400 && response.status === 400 && record3(body) && ["authorization_pending", "slow_down", "expired_token", "access_denied"].includes(String(body.error))))
|
|
21838
|
+
throw new DeviceAuthorizationError("http_error", "Device authorization request failed");
|
|
21839
|
+
return body;
|
|
21840
|
+
} catch (error2) {
|
|
21841
|
+
if (error2 instanceof DeviceAuthorizationError)
|
|
21842
|
+
throw error2;
|
|
21843
|
+
if (controller.signal.aborted && options.signal?.aborted)
|
|
21844
|
+
throw new DeviceAuthorizationError("aborted", "Device authorization was cancelled");
|
|
21845
|
+
throw new DeviceAuthorizationError("transport", "Device authorization request failed");
|
|
21846
|
+
} finally {
|
|
21847
|
+
clearTimeout(timeout);
|
|
21848
|
+
options.signal?.removeEventListener("abort", externalAbort);
|
|
21849
|
+
}
|
|
21850
|
+
}
|
|
21851
|
+
async function readBoundedJson(response) {
|
|
21852
|
+
const declaredLength = response.headers.get("content-length");
|
|
21853
|
+
if (declaredLength !== null) {
|
|
21854
|
+
const length = Number(declaredLength);
|
|
21855
|
+
if (!Number.isFinite(length) || length < 0 || length > MAX_RESPONSE_BYTES)
|
|
21856
|
+
malformed("response");
|
|
21857
|
+
}
|
|
21858
|
+
const reader = response.body?.getReader();
|
|
21859
|
+
if (!reader)
|
|
21860
|
+
malformed("response");
|
|
21861
|
+
const decoder = new TextDecoder();
|
|
21862
|
+
let size = 0;
|
|
21863
|
+
let text2 = "";
|
|
21864
|
+
try {
|
|
21865
|
+
while (true) {
|
|
21866
|
+
const { done, value } = await reader.read();
|
|
21867
|
+
if (done)
|
|
21868
|
+
break;
|
|
21869
|
+
size += value.byteLength;
|
|
21870
|
+
if (size > MAX_RESPONSE_BYTES) {
|
|
21871
|
+
await reader.cancel();
|
|
21872
|
+
malformed("response");
|
|
21873
|
+
}
|
|
21874
|
+
text2 += decoder.decode(value, { stream: true });
|
|
21875
|
+
}
|
|
21876
|
+
text2 += decoder.decode();
|
|
21877
|
+
try {
|
|
21878
|
+
return JSON.parse(text2);
|
|
21879
|
+
} catch {
|
|
21880
|
+
malformed("response");
|
|
21881
|
+
}
|
|
21882
|
+
} finally {
|
|
21883
|
+
reader.releaseLock();
|
|
21884
|
+
}
|
|
21885
|
+
}
|
|
21886
|
+
function validatedBase(value) {
|
|
21887
|
+
try {
|
|
21888
|
+
const url = new URL(value);
|
|
21889
|
+
if (url.protocol !== "https:" || url.username || url.password || url.search || url.hash || url.pathname !== "/")
|
|
21890
|
+
throw 0;
|
|
21891
|
+
return url;
|
|
21892
|
+
} catch {
|
|
21893
|
+
throw new DeviceAuthorizationError("invalid_endpoint", "Device authorization endpoint is invalid");
|
|
21894
|
+
}
|
|
21895
|
+
}
|
|
21896
|
+
function validateVerificationUri(value, base, complete, userCode) {
|
|
21897
|
+
let url;
|
|
21898
|
+
try {
|
|
21899
|
+
url = new URL(value);
|
|
21900
|
+
} catch {
|
|
21901
|
+
throw new DeviceAuthorizationError("invalid_endpoint", "Verification URI is invalid");
|
|
21902
|
+
}
|
|
21903
|
+
if (url.protocol !== "https:" || url.username || url.password || url.hash || url.origin !== base.origin || url.searchParams.has("device_id"))
|
|
21904
|
+
throw new DeviceAuthorizationError("invalid_endpoint", "Verification URI is invalid");
|
|
21905
|
+
const keys = [...url.searchParams.keys()];
|
|
21906
|
+
if (complete && url.searchParams.get("user_code") !== userCode)
|
|
21907
|
+
throw new DeviceAuthorizationError("invalid_endpoint", "Verification URI query is invalid");
|
|
21908
|
+
if (!complete && keys.length || complete && (keys.length !== 1 || keys[0] !== "user_code"))
|
|
21909
|
+
throw new DeviceAuthorizationError("invalid_endpoint", "Verification URI query is invalid");
|
|
21910
|
+
}
|
|
21911
|
+
function record3(value) {
|
|
21912
|
+
return typeof value === "object" && value !== null;
|
|
21913
|
+
}
|
|
21914
|
+
function validSession(value) {
|
|
21915
|
+
if (!record3(value))
|
|
21916
|
+
return false;
|
|
21917
|
+
try {
|
|
21918
|
+
const shape = text(value.deviceId) && text(value.userCode) && text(value.verificationUri) && text(value.verificationUriComplete) && positive(value.expiresIn) && positive(value.interval) && typeof value.issuedAt === "number" && Number.isFinite(value.issuedAt) && text(value.gatewayOrigin) && new URL(value.verificationUri).origin === value.gatewayOrigin && new URL(value.verificationUriComplete).origin === value.gatewayOrigin;
|
|
21919
|
+
if (!shape)
|
|
21920
|
+
return false;
|
|
21921
|
+
const base = validatedBase(value.gatewayOrigin);
|
|
21922
|
+
validateVerificationUri(value.verificationUri, base, false);
|
|
21923
|
+
validateVerificationUri(value.verificationUriComplete, base, true, value.userCode);
|
|
21924
|
+
return true;
|
|
21925
|
+
} catch {
|
|
21926
|
+
return false;
|
|
21927
|
+
}
|
|
21928
|
+
}
|
|
21929
|
+
function text(value) {
|
|
21930
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
21931
|
+
}
|
|
21932
|
+
function positive(value) {
|
|
21933
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
21934
|
+
}
|
|
21935
|
+
function malformed(part) {
|
|
21936
|
+
throw new DeviceAuthorizationError("malformed_response", `Device authorization ${part} response is invalid`);
|
|
21937
|
+
}
|
|
21938
|
+
async function wait(custom2, ms, signal) {
|
|
21939
|
+
if (signal?.aborted)
|
|
21940
|
+
throw new DeviceAuthorizationError("aborted", "Device authorization was cancelled");
|
|
21941
|
+
const sleeper = custom2 ? custom2(ms, signal) : new Promise((resolve10, reject) => {
|
|
21942
|
+
const onAbort = () => {
|
|
21943
|
+
clearTimeout(timer);
|
|
21944
|
+
signal?.removeEventListener("abort", onAbort);
|
|
21945
|
+
reject(new DeviceAuthorizationError("aborted", "Device authorization was cancelled"));
|
|
21946
|
+
};
|
|
21947
|
+
const timer = setTimeout(() => {
|
|
21948
|
+
signal?.removeEventListener("abort", onAbort);
|
|
21949
|
+
resolve10();
|
|
21950
|
+
}, ms);
|
|
21951
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
21952
|
+
});
|
|
21953
|
+
await sleeper;
|
|
21954
|
+
if (signal?.aborted)
|
|
21955
|
+
throw new DeviceAuthorizationError("aborted", "Device authorization was cancelled");
|
|
21956
|
+
}
|
|
21957
|
+
|
|
21655
21958
|
// ../zlt-runtime-core/dist/zltaf-ipc.js
|
|
21656
21959
|
var import_node_crypto = require("node:crypto");
|
|
21657
|
-
var
|
|
21960
|
+
var fs9 = __toESM(require("node:fs"), 1);
|
|
21658
21961
|
var net2 = __toESM(require("node:net"), 1);
|
|
21659
21962
|
var os3 = __toESM(require("node:os"), 1);
|
|
21660
21963
|
var path8 = __toESM(require("node:path"), 1);
|
|
@@ -21827,7 +22130,7 @@ function flushLogQueue() {
|
|
|
21827
22130
|
logWriteInFlight = true;
|
|
21828
22131
|
const batch = pendingLogLines.splice(0).join("");
|
|
21829
22132
|
try {
|
|
21830
|
-
|
|
22133
|
+
fs9.appendFile(LOG_FILE, batch, "utf8", () => {
|
|
21831
22134
|
logWriteInFlight = false;
|
|
21832
22135
|
flushLogQueue();
|
|
21833
22136
|
});
|
|
@@ -22008,10 +22311,10 @@ __export(config_exports, {
|
|
|
22008
22311
|
resolveDefaultConfigPath: () => resolveDefaultConfigPath,
|
|
22009
22312
|
resolveDefaultRuntimeConfigPath: () => resolveDefaultRuntimeConfigPath
|
|
22010
22313
|
});
|
|
22011
|
-
var
|
|
22314
|
+
var fs10 = __toESM(require("fs"), 1);
|
|
22012
22315
|
var path9 = __toESM(require("path"), 1);
|
|
22013
22316
|
function loadConfig(configPath) {
|
|
22014
|
-
const raw =
|
|
22317
|
+
const raw = fs10.readFileSync(configPath, "utf-8");
|
|
22015
22318
|
return JSON.parse(raw);
|
|
22016
22319
|
}
|
|
22017
22320
|
function resolveDefaultConfigPath() {
|
|
@@ -22023,7 +22326,7 @@ function resolveDefaultConfigPath() {
|
|
|
22023
22326
|
cwdCandidate
|
|
22024
22327
|
];
|
|
22025
22328
|
for (const candidate of candidates) {
|
|
22026
|
-
if (
|
|
22329
|
+
if (fs10.existsSync(candidate)) return candidate;
|
|
22027
22330
|
}
|
|
22028
22331
|
return cwdCandidate;
|
|
22029
22332
|
}
|
|
@@ -22034,7 +22337,7 @@ function resolveDefaultRuntimeConfigPath() {
|
|
|
22034
22337
|
path9.resolve(path9.dirname(process.argv[1] || ""), "runtime.cfg.json"),
|
|
22035
22338
|
path9.resolve(process.cwd(), "runtime.cfg.json")
|
|
22036
22339
|
];
|
|
22037
|
-
return candidates.find((candidate) =>
|
|
22340
|
+
return candidates.find((candidate) => fs10.existsSync(candidate));
|
|
22038
22341
|
}
|
|
22039
22342
|
var matchingPipeNames2 = matchingPipeNames;
|
|
22040
22343
|
|
|
@@ -22068,7 +22371,7 @@ function hasHighBytes(str) {
|
|
|
22068
22371
|
}
|
|
22069
22372
|
|
|
22070
22373
|
// src/download-verification.ts
|
|
22071
|
-
var
|
|
22374
|
+
var fs11 = __toESM(require("node:fs"), 1);
|
|
22072
22375
|
var path10 = __toESM(require("node:path"), 1);
|
|
22073
22376
|
var MAX_INVENTORY_ENTRIES = 25e3;
|
|
22074
22377
|
var MAX_INVENTORY_DEPTH = 8;
|
|
@@ -22079,10 +22382,10 @@ function isRecord2(value) {
|
|
|
22079
22382
|
function payloadOf(result) {
|
|
22080
22383
|
if (isRecord2(result.structuredContent)) return result.structuredContent;
|
|
22081
22384
|
const content = Array.isArray(result.content) ? result.content : [];
|
|
22082
|
-
const
|
|
22083
|
-
if (!isRecord2(
|
|
22385
|
+
const text2 = content.find((item) => isRecord2(item) && item.type === "text" && typeof item.text === "string");
|
|
22386
|
+
if (!isRecord2(text2)) return null;
|
|
22084
22387
|
try {
|
|
22085
|
-
const parsed = JSON.parse(
|
|
22388
|
+
const parsed = JSON.parse(text2.text);
|
|
22086
22389
|
return isRecord2(parsed) ? parsed : null;
|
|
22087
22390
|
} catch {
|
|
22088
22391
|
return null;
|
|
@@ -22142,9 +22445,9 @@ async function downloadAndVerify(args, invoke, inventory, onUuid) {
|
|
|
22142
22445
|
evidence.uuid = uuid2;
|
|
22143
22446
|
onUuid?.(uuid2);
|
|
22144
22447
|
try {
|
|
22145
|
-
const
|
|
22146
|
-
evidence.stages.wait =
|
|
22147
|
-
if (!doneAndVerifiable(
|
|
22448
|
+
const wait2 = await invoke("mcp-wait", { kind: "download", id: uuid2 });
|
|
22449
|
+
evidence.stages.wait = wait2;
|
|
22450
|
+
if (!doneAndVerifiable(wait2, uuid2)) {
|
|
22148
22451
|
evidence.nextAction = "inspect-wait-before-retry";
|
|
22149
22452
|
return workflowResult(evidence);
|
|
22150
22453
|
}
|
|
@@ -22167,7 +22470,7 @@ async function downloadAndVerify(args, invoke, inventory, onUuid) {
|
|
|
22167
22470
|
function configuredDownloadHome(clientRootDir) {
|
|
22168
22471
|
try {
|
|
22169
22472
|
const configPath = path10.join(clientRootDir, "zltHost", "moudles", "dcm.json");
|
|
22170
|
-
const config2 = JSON.parse(
|
|
22473
|
+
const config2 = JSON.parse(fs11.readFileSync(configPath, "utf8"));
|
|
22171
22474
|
if (!isRecord2(config2) || typeof config2.download_home !== "string" || !config2.download_home.trim()) return null;
|
|
22172
22475
|
const expanded = config2.download_home.trim().replace(/%HomePath%/gi, clientRootDir);
|
|
22173
22476
|
return path10.isAbsolute(expanded) ? path10.resolve(expanded) : path10.resolve(clientRootDir, expanded);
|
|
@@ -22212,14 +22515,14 @@ function inventoryDownloadedFiles(clientRootDir, params, diskSpace, limits = {})
|
|
|
22212
22515
|
if (scopes.some((scope) => !scope.exchangeId || !/^(dk|mk|tk)[a-z0-9_-]*$/.test(scope.dataType))) {
|
|
22213
22516
|
return unknown2("unsupported-physical-layout", configured);
|
|
22214
22517
|
}
|
|
22215
|
-
let
|
|
22518
|
+
let root2;
|
|
22216
22519
|
try {
|
|
22217
|
-
const configuredStat =
|
|
22520
|
+
const configuredStat = fs11.lstatSync(configured);
|
|
22218
22521
|
if (configuredStat.isSymbolicLink() || typeof configuredStat.attributes === "number" && (configuredStat.attributes & 1024) !== 0) {
|
|
22219
22522
|
return unknown2("symlink-or-reparse-point", configured);
|
|
22220
22523
|
}
|
|
22221
|
-
|
|
22222
|
-
if (!
|
|
22524
|
+
root2 = fs11.realpathSync(configured);
|
|
22525
|
+
if (!fs11.statSync(root2).isDirectory()) return unknown2("download-home-not-directory", configured);
|
|
22223
22526
|
} catch {
|
|
22224
22527
|
return unknown2("download-home-unavailable", configured);
|
|
22225
22528
|
}
|
|
@@ -22230,13 +22533,13 @@ function inventoryDownloadedFiles(clientRootDir, params, diskSpace, limits = {})
|
|
|
22230
22533
|
try {
|
|
22231
22534
|
for (const scope of scopes) {
|
|
22232
22535
|
for (const lane of ["his", "rel"]) {
|
|
22233
|
-
let candidate =
|
|
22536
|
+
let candidate = root2;
|
|
22234
22537
|
let present = true;
|
|
22235
22538
|
for (const segment of ["hqdata", lane, scope.exchangeId, scope.dataType]) {
|
|
22236
22539
|
candidate = path10.join(candidate, segment);
|
|
22237
22540
|
let component;
|
|
22238
22541
|
try {
|
|
22239
|
-
component =
|
|
22542
|
+
component = fs11.lstatSync(candidate);
|
|
22240
22543
|
} catch (error2) {
|
|
22241
22544
|
if (error2.code === "ENOENT") {
|
|
22242
22545
|
present = false;
|
|
@@ -22257,12 +22560,12 @@ function inventoryDownloadedFiles(clientRootDir, params, diskSpace, limits = {})
|
|
|
22257
22560
|
}
|
|
22258
22561
|
while (queue.length > 0) {
|
|
22259
22562
|
const current = queue.shift();
|
|
22260
|
-
for (const entry of
|
|
22563
|
+
for (const entry of fs11.readdirSync(current.dir, { withFileTypes: true })) {
|
|
22261
22564
|
entries += 1;
|
|
22262
22565
|
if (entries > (limits.maxEntries ?? MAX_INVENTORY_ENTRIES)) return unknown2("inventory-entry-limit", configured);
|
|
22263
22566
|
const full = path10.join(current.dir, entry.name);
|
|
22264
22567
|
if (entry.isSymbolicLink()) return unknown2("symlink-or-reparse-point", configured);
|
|
22265
|
-
const stat =
|
|
22568
|
+
const stat = fs11.lstatSync(full);
|
|
22266
22569
|
const attrs = stat.attributes;
|
|
22267
22570
|
if (stat.isSymbolicLink() || typeof attrs === "number" && (attrs & 1024) !== 0) return unknown2("symlink-or-reparse-point", configured);
|
|
22268
22571
|
if (entry.isDirectory()) {
|
|
@@ -22286,8 +22589,8 @@ var RESPONSE_FILE_THRESHOLD = 1024;
|
|
|
22286
22589
|
var HISTORY_MAX_LINES = 1e3;
|
|
22287
22590
|
var ASYNC_BACKTEST_TOOLS = /* @__PURE__ */ new Set(["mcp-create-and-run-backtest", "mcp-re-backtest"]);
|
|
22288
22591
|
function getOutputDir(clientRootDir) {
|
|
22289
|
-
const
|
|
22290
|
-
return
|
|
22592
|
+
const root2 = clientRootDir.replace(/\/+$/, "");
|
|
22593
|
+
return root2 + "/Temporary/zlt-cli";
|
|
22291
22594
|
}
|
|
22292
22595
|
function getTimestamp() {
|
|
22293
22596
|
const d = /* @__PURE__ */ new Date();
|
|
@@ -22297,46 +22600,46 @@ function getTimestampISO() {
|
|
|
22297
22600
|
return (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").substring(0, 19);
|
|
22298
22601
|
}
|
|
22299
22602
|
function ensureDir(dir) {
|
|
22300
|
-
|
|
22603
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
22301
22604
|
}
|
|
22302
22605
|
function writeResponseFile(outputDir, content) {
|
|
22303
22606
|
ensureDir(outputDir);
|
|
22304
22607
|
const filename = `resp_${getTimestamp()}.json`;
|
|
22305
22608
|
const filePath = path11.join(outputDir, filename);
|
|
22306
|
-
|
|
22609
|
+
fs12.writeFileSync(filePath, content, "utf-8");
|
|
22307
22610
|
return filePath;
|
|
22308
22611
|
}
|
|
22309
22612
|
function appendHistory(outputDir, uri, statusCode, contentSize, respFile) {
|
|
22310
22613
|
ensureDir(outputDir);
|
|
22311
22614
|
const historyPath = path11.join(outputDir, "history.jsonl");
|
|
22312
|
-
if (
|
|
22313
|
-
const lines =
|
|
22615
|
+
if (fs12.existsSync(historyPath)) {
|
|
22616
|
+
const lines = fs12.readFileSync(historyPath, "utf-8").split("\n").filter((l) => l.trim());
|
|
22314
22617
|
if (lines.length > HISTORY_MAX_LINES) {
|
|
22315
22618
|
const kept = lines.slice(lines.length - HISTORY_MAX_LINES);
|
|
22316
|
-
|
|
22619
|
+
fs12.writeFileSync(historyPath, kept.join("\n") + "\n", "utf-8");
|
|
22317
22620
|
}
|
|
22318
22621
|
}
|
|
22319
|
-
const
|
|
22622
|
+
const record5 = {
|
|
22320
22623
|
time: getTimestampISO(),
|
|
22321
22624
|
uri,
|
|
22322
22625
|
status: statusCode,
|
|
22323
22626
|
size: contentSize
|
|
22324
22627
|
};
|
|
22325
|
-
if (respFile)
|
|
22326
|
-
|
|
22628
|
+
if (respFile) record5.file = respFile;
|
|
22629
|
+
fs12.appendFileSync(historyPath, JSON.stringify(record5) + "\n", "utf-8");
|
|
22327
22630
|
}
|
|
22328
22631
|
function cleanOutput(clientRootDir, maxDays = 1) {
|
|
22329
22632
|
const outputDir = getOutputDir(clientRootDir);
|
|
22330
|
-
if (!
|
|
22633
|
+
if (!fs12.existsSync(outputDir)) return 0;
|
|
22331
22634
|
const now = Date.now();
|
|
22332
22635
|
const cutoff = now - maxDays * 864e5;
|
|
22333
22636
|
let removed = 0;
|
|
22334
|
-
for (const entry of
|
|
22637
|
+
for (const entry of fs12.readdirSync(outputDir)) {
|
|
22335
22638
|
if (!entry.startsWith("resp_") || !entry.endsWith(".json")) continue;
|
|
22336
22639
|
const filePath = path11.join(outputDir, entry);
|
|
22337
|
-
const stat =
|
|
22640
|
+
const stat = fs12.statSync(filePath);
|
|
22338
22641
|
if (stat.mtimeMs < cutoff) {
|
|
22339
|
-
|
|
22642
|
+
fs12.unlinkSync(filePath);
|
|
22340
22643
|
removed++;
|
|
22341
22644
|
}
|
|
22342
22645
|
}
|
|
@@ -22361,7 +22664,7 @@ async function execCommand(funcName, options) {
|
|
|
22361
22664
|
}
|
|
22362
22665
|
let bodyFromFile = bodyOverride || "";
|
|
22363
22666
|
if (!bodyFromFile && bodyFile) {
|
|
22364
|
-
bodyFromFile =
|
|
22667
|
+
bodyFromFile = fs12.readFileSync(bodyFile, "utf-8");
|
|
22365
22668
|
}
|
|
22366
22669
|
const tool = config2.tools.find((t) => t.name === funcName);
|
|
22367
22670
|
if (tool?.localHandler === "currentUser") {
|
|
@@ -22369,10 +22672,10 @@ async function execCommand(funcName, options) {
|
|
|
22369
22672
|
return;
|
|
22370
22673
|
}
|
|
22371
22674
|
const pipePath = discoverPipePath2(clientRootDir, tool?.pipName || config2.zltconfig.pipName);
|
|
22372
|
-
const
|
|
22675
|
+
const client2 = new ZltafIpcClient();
|
|
22373
22676
|
const outputDir = getOutputDir(clientRootDir);
|
|
22374
22677
|
try {
|
|
22375
|
-
await
|
|
22678
|
+
await client2.connect(pipePath, config2.connection.timeout);
|
|
22376
22679
|
let ipcUri;
|
|
22377
22680
|
let params = {};
|
|
22378
22681
|
let body;
|
|
@@ -22392,7 +22695,7 @@ async function execCommand(funcName, options) {
|
|
|
22392
22695
|
body = bodyFromFile || (Object.keys(bizOptions).length > 0 ? JSON.stringify(bizOptions) : "{}");
|
|
22393
22696
|
}
|
|
22394
22697
|
const timeout = tool ? buildIpcTimeout(tool, bizOptions, config2.connection.timeout) : config2.connection.timeout;
|
|
22395
|
-
const response = await
|
|
22698
|
+
const response = await client2.invoke(ipcUri, params, body, timeout, customHeaders);
|
|
22396
22699
|
const output = response.content ? decodePipeText(response.content) : "";
|
|
22397
22700
|
const contentSize = Buffer.byteLength(output, "utf-8");
|
|
22398
22701
|
ensureDir(outputDir);
|
|
@@ -22420,14 +22723,14 @@ async function execCommand(funcName, options) {
|
|
|
22420
22723
|
`);
|
|
22421
22724
|
process.exitCode = 1;
|
|
22422
22725
|
} finally {
|
|
22423
|
-
await
|
|
22726
|
+
await client2.disconnect();
|
|
22424
22727
|
}
|
|
22425
22728
|
}
|
|
22426
22729
|
function parseMcpArgs(argsJson, argsFile) {
|
|
22427
22730
|
if (argsJson !== void 0 && argsFile !== void 0) {
|
|
22428
22731
|
throw new Error("Use only one of --args-json and --args-file");
|
|
22429
22732
|
}
|
|
22430
|
-
const raw = argsFile !== void 0 ?
|
|
22733
|
+
const raw = argsFile !== void 0 ? fs12.readFileSync(argsFile, "utf-8") : argsJson !== void 0 ? argsJson : "{}";
|
|
22431
22734
|
let parsed;
|
|
22432
22735
|
try {
|
|
22433
22736
|
parsed = JSON.parse(raw);
|
|
@@ -22482,10 +22785,10 @@ function parseMcpResult(result) {
|
|
|
22482
22785
|
return result.structuredContent;
|
|
22483
22786
|
}
|
|
22484
22787
|
const content = Array.isArray(result.content) ? result.content : [];
|
|
22485
|
-
const
|
|
22486
|
-
if (!
|
|
22788
|
+
const text2 = content.find((item) => item && typeof item === "object" && item.type === "text" && typeof item.text === "string");
|
|
22789
|
+
if (!text2) return null;
|
|
22487
22790
|
try {
|
|
22488
|
-
const parsed = JSON.parse(
|
|
22791
|
+
const parsed = JSON.parse(text2.text);
|
|
22489
22792
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
22490
22793
|
} catch {
|
|
22491
22794
|
return null;
|
|
@@ -22496,17 +22799,17 @@ function backtestHandoff(result) {
|
|
|
22496
22799
|
const payload = parseMcpResult(result);
|
|
22497
22800
|
const data = payload?.Data;
|
|
22498
22801
|
if (!data || typeof data !== "object" || Array.isArray(data)) return null;
|
|
22499
|
-
const
|
|
22500
|
-
const status = Number(
|
|
22802
|
+
const record5 = data;
|
|
22803
|
+
const status = Number(record5.status);
|
|
22501
22804
|
if (Number.isFinite(status) && status !== 0 && status !== 1) return null;
|
|
22502
|
-
const runId = typeof
|
|
22805
|
+
const runId = typeof record5.runId === "string" ? record5.runId.trim() : "";
|
|
22503
22806
|
if (!runId) return null;
|
|
22504
|
-
const evidence =
|
|
22505
|
-
const rawCodePath = typeof
|
|
22807
|
+
const evidence = record5.evidence && typeof record5.evidence === "object" && !Array.isArray(record5.evidence) ? record5.evidence : void 0;
|
|
22808
|
+
const rawCodePath = typeof record5.codePath === "string" ? record5.codePath.trim() : typeof evidence?.runDir === "string" ? evidence.runDir.trim() : "";
|
|
22506
22809
|
return {
|
|
22507
22810
|
runId,
|
|
22508
22811
|
...rawCodePath && path11.isAbsolute(rawCodePath) ? { codePath: rawCodePath } : {},
|
|
22509
|
-
...
|
|
22812
|
+
...record5.attemptFence !== void 0 ? { attemptFence: record5.attemptFence } : {}
|
|
22510
22813
|
};
|
|
22511
22814
|
}
|
|
22512
22815
|
function mcpErrorCode(result) {
|
|
@@ -22554,18 +22857,18 @@ function mergeBacktestWait(launched, waited, handoff) {
|
|
|
22554
22857
|
const payload = { ...waitPayload, Data: mergedData };
|
|
22555
22858
|
const content = Array.isArray(waited.content) ? [...waited.content] : [];
|
|
22556
22859
|
const textIndex = content.findIndex((item) => item && typeof item === "object" && item.type === "text");
|
|
22557
|
-
const
|
|
22558
|
-
if (textIndex < 0) content.push(
|
|
22559
|
-
else content[textIndex] =
|
|
22860
|
+
const text2 = { type: "text", text: JSON.stringify(payload) };
|
|
22861
|
+
if (textIndex < 0) content.push(text2);
|
|
22862
|
+
else content[textIndex] = text2;
|
|
22560
22863
|
return { ...waited, content, ...waited.structuredContent ? { structuredContent: payload } : {} };
|
|
22561
22864
|
}
|
|
22562
22865
|
async function callMcpTool(name, args = {}, options = {}) {
|
|
22563
22866
|
if (options.verifyDownload && name !== "mcp-download-data") {
|
|
22564
22867
|
throw new Error("verifyDownload is supported only for mcp-download-data");
|
|
22565
22868
|
}
|
|
22566
|
-
const { client, transport } = createMcpClient(options);
|
|
22869
|
+
const { client: client2, transport } = createMcpClient(options);
|
|
22567
22870
|
try {
|
|
22568
|
-
await
|
|
22871
|
+
await client2.connect(transport);
|
|
22569
22872
|
const timeout = options.timeoutMs ?? 6e4;
|
|
22570
22873
|
const showProgress = options.showProgress !== false;
|
|
22571
22874
|
const startedAt = Date.now();
|
|
@@ -22596,7 +22899,7 @@ async function callMcpTool(name, args = {}, options = {}) {
|
|
|
22596
22899
|
cancellation.abort(new Error("MCP call exceeded --max-total-timeout-ms"));
|
|
22597
22900
|
}, totalTimeoutMs) : void 0;
|
|
22598
22901
|
try {
|
|
22599
|
-
return await
|
|
22902
|
+
return await client2.callTool({ name: tool, arguments: toolArgs }, void 0, {
|
|
22600
22903
|
...requestOptions,
|
|
22601
22904
|
...cancellation ? { signal: cancellation.signal } : {}
|
|
22602
22905
|
});
|
|
@@ -22678,7 +22981,7 @@ async function callMcpTool(name, args = {}, options = {}) {
|
|
|
22678
22981
|
}
|
|
22679
22982
|
return result;
|
|
22680
22983
|
} finally {
|
|
22681
|
-
await
|
|
22984
|
+
await client2.close().catch((error2) => {
|
|
22682
22985
|
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
22683
22986
|
process.stderr.write(`[zlt-mcp-cli] close failed: ${message}
|
|
22684
22987
|
`);
|
|
@@ -22686,19 +22989,19 @@ async function callMcpTool(name, args = {}, options = {}) {
|
|
|
22686
22989
|
}
|
|
22687
22990
|
}
|
|
22688
22991
|
async function listMcpTools(options = {}) {
|
|
22689
|
-
const { client, transport } = createMcpClient(options);
|
|
22992
|
+
const { client: client2, transport } = createMcpClient(options);
|
|
22690
22993
|
try {
|
|
22691
|
-
await
|
|
22994
|
+
await client2.connect(transport);
|
|
22692
22995
|
const tools = [];
|
|
22693
22996
|
let cursor;
|
|
22694
22997
|
do {
|
|
22695
|
-
const page = await
|
|
22998
|
+
const page = await client2.listTools(cursor ? { cursor } : void 0);
|
|
22696
22999
|
tools.push(...page.tools);
|
|
22697
23000
|
cursor = page.nextCursor;
|
|
22698
23001
|
} while (cursor);
|
|
22699
23002
|
return { tools };
|
|
22700
23003
|
} finally {
|
|
22701
|
-
await
|
|
23004
|
+
await client2.close().catch((error2) => {
|
|
22702
23005
|
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
22703
23006
|
process.stderr.write(`[zlt-mcp-cli] close failed: ${message}
|
|
22704
23007
|
`);
|
|
@@ -22759,7 +23062,7 @@ function buildIpcTimeout(tool, options, defaultTimeout) {
|
|
|
22759
23062
|
}
|
|
22760
23063
|
|
|
22761
23064
|
// src/skill-generator.ts
|
|
22762
|
-
var
|
|
23065
|
+
var fs13 = __toESM(require("fs"), 1);
|
|
22763
23066
|
var path12 = __toESM(require("path"), 1);
|
|
22764
23067
|
function generateSkills(configPath, opts) {
|
|
22765
23068
|
const config2 = loadConfig(configPath);
|
|
@@ -22777,11 +23080,11 @@ ${content}
|
|
|
22777
23080
|
`);
|
|
22778
23081
|
} else {
|
|
22779
23082
|
const outDir = opts.output || ".claude/skills/zlt";
|
|
22780
|
-
if (!
|
|
22781
|
-
|
|
23083
|
+
if (!fs13.existsSync(outDir)) {
|
|
23084
|
+
fs13.mkdirSync(outDir, { recursive: true });
|
|
22782
23085
|
}
|
|
22783
23086
|
const filePath = path12.join(outDir, `zlt-${tool.name.replace(/_/g, "-")}.md`);
|
|
22784
|
-
|
|
23087
|
+
fs13.writeFileSync(filePath, content);
|
|
22785
23088
|
process.stderr.write(`Generated: ${filePath}
|
|
22786
23089
|
`);
|
|
22787
23090
|
}
|
|
@@ -23473,13 +23776,13 @@ var StdioServerTransport = class {
|
|
|
23473
23776
|
};
|
|
23474
23777
|
|
|
23475
23778
|
// src/mcp-server.ts
|
|
23476
|
-
var
|
|
23779
|
+
var fs17 = __toESM(require("node:fs"), 1);
|
|
23477
23780
|
|
|
23478
23781
|
// src/install-task.ts
|
|
23479
|
-
var
|
|
23782
|
+
var fs14 = __toESM(require("node:fs"), 1);
|
|
23480
23783
|
var os4 = __toESM(require("node:os"), 1);
|
|
23481
23784
|
var path13 = __toESM(require("node:path"), 1);
|
|
23482
|
-
var
|
|
23785
|
+
var import_node_child_process2 = require("node:child_process");
|
|
23483
23786
|
var DEFAULT_TASK_ROOT = path13.join(os4.tmpdir(), "zlt-mcp-install-tasks");
|
|
23484
23787
|
var STARTUP_GRACE_MS = 3e4;
|
|
23485
23788
|
function taskRoot() {
|
|
@@ -23488,25 +23791,25 @@ function taskRoot() {
|
|
|
23488
23791
|
function taskPath(taskId) {
|
|
23489
23792
|
return path13.join(taskRoot(), `${taskId}.json`);
|
|
23490
23793
|
}
|
|
23491
|
-
function write(
|
|
23492
|
-
|
|
23493
|
-
const target = taskPath(
|
|
23794
|
+
function write(record5) {
|
|
23795
|
+
fs14.mkdirSync(taskRoot(), { recursive: true });
|
|
23796
|
+
const target = taskPath(record5.taskId);
|
|
23494
23797
|
const temporary = `${target}.${process.pid}.tmp`;
|
|
23495
|
-
|
|
23798
|
+
fs14.writeFileSync(temporary, `${JSON.stringify(record5)}
|
|
23496
23799
|
`, "utf8");
|
|
23497
|
-
|
|
23800
|
+
fs14.renameSync(temporary, target);
|
|
23498
23801
|
}
|
|
23499
23802
|
function readRaw(taskId) {
|
|
23500
23803
|
if (!/^[A-Za-z0-9_-]+$/.test(taskId)) return void 0;
|
|
23501
23804
|
try {
|
|
23502
|
-
const
|
|
23503
|
-
return
|
|
23805
|
+
const record5 = JSON.parse(fs14.readFileSync(taskPath(taskId), "utf8"));
|
|
23806
|
+
return record5.taskId === taskId ? record5 : void 0;
|
|
23504
23807
|
} catch {
|
|
23505
23808
|
return void 0;
|
|
23506
23809
|
}
|
|
23507
23810
|
}
|
|
23508
|
-
function active(
|
|
23509
|
-
return
|
|
23811
|
+
function active(record5) {
|
|
23812
|
+
return record5.status === "queued" || record5.status === "running";
|
|
23510
23813
|
}
|
|
23511
23814
|
function alive(pid) {
|
|
23512
23815
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
@@ -23531,7 +23834,7 @@ function readInstallTask(taskId) {
|
|
|
23531
23834
|
let pid = current.workerPid;
|
|
23532
23835
|
if (!pid) {
|
|
23533
23836
|
try {
|
|
23534
|
-
pid = Number(
|
|
23837
|
+
pid = Number(fs14.readFileSync(`${taskPath(taskId)}.pid`, "utf8"));
|
|
23535
23838
|
} catch {
|
|
23536
23839
|
}
|
|
23537
23840
|
}
|
|
@@ -23540,10 +23843,10 @@ function readInstallTask(taskId) {
|
|
|
23540
23843
|
if (!pid && current.status === "queued" && age >= 0 && age < STARTUP_GRACE_MS && (!current.launcherPid || alive(current.launcherPid))) return current;
|
|
23541
23844
|
return fail(taskId, INTERRUPTED);
|
|
23542
23845
|
}
|
|
23543
|
-
function startInstallTask(entrypoint, argsJson, spawnProcess =
|
|
23846
|
+
function startInstallTask(entrypoint, argsJson, spawnProcess = import_node_child_process2.spawn) {
|
|
23544
23847
|
let files = [];
|
|
23545
23848
|
try {
|
|
23546
|
-
files =
|
|
23849
|
+
files = fs14.readdirSync(taskRoot());
|
|
23547
23850
|
} catch (error2) {
|
|
23548
23851
|
if (error2.code !== "ENOENT") throw error2;
|
|
23549
23852
|
}
|
|
@@ -23554,17 +23857,17 @@ function startInstallTask(entrypoint, argsJson, spawnProcess = import_node_child
|
|
|
23554
23857
|
if (existing && active(existing)) return readInstallTask(taskId2);
|
|
23555
23858
|
}
|
|
23556
23859
|
const taskId = `install-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
23557
|
-
const
|
|
23860
|
+
const record5 = {
|
|
23558
23861
|
taskId,
|
|
23559
23862
|
status: "queued",
|
|
23560
23863
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23561
23864
|
launcherPid: process.pid,
|
|
23562
23865
|
logPath: path13.join(taskRoot(), `${taskId}.log`)
|
|
23563
23866
|
};
|
|
23564
|
-
write(
|
|
23867
|
+
write(record5);
|
|
23565
23868
|
let logFd;
|
|
23566
23869
|
try {
|
|
23567
|
-
logFd =
|
|
23870
|
+
logFd = fs14.openSync(record5.logPath, "a");
|
|
23568
23871
|
const child = spawnProcess(process.execPath, [entrypoint, "__install-worker", taskId, argsJson], {
|
|
23569
23872
|
detached: true,
|
|
23570
23873
|
stdio: ["ignore", logFd, logFd],
|
|
@@ -23577,12 +23880,12 @@ function startInstallTask(entrypoint, argsJson, spawnProcess = import_node_child
|
|
|
23577
23880
|
child.once("exit", (code, signal) => {
|
|
23578
23881
|
fail(taskId, `${INTERRUPTED} (exit=${code}, signal=${signal})`);
|
|
23579
23882
|
});
|
|
23580
|
-
if (child.pid)
|
|
23883
|
+
if (child.pid) fs14.writeFileSync(`${taskPath(taskId)}.pid`, String(child.pid), "utf8");
|
|
23581
23884
|
child.unref();
|
|
23582
23885
|
} catch (error2) {
|
|
23583
23886
|
fail(taskId, `\u5B89\u88C5\u5DE5\u4F5C\u8FDB\u7A0B\u542F\u52A8\u5931\u8D25: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
23584
23887
|
} finally {
|
|
23585
|
-
if (logFd !== void 0)
|
|
23888
|
+
if (logFd !== void 0) fs14.closeSync(logFd);
|
|
23586
23889
|
}
|
|
23587
23890
|
return readRaw(taskId);
|
|
23588
23891
|
}
|
|
@@ -23610,7 +23913,7 @@ function updateInstallTask(taskId, update) {
|
|
|
23610
23913
|
var import_promises = require("node:timers/promises");
|
|
23611
23914
|
|
|
23612
23915
|
// src/tool-pipeline.ts
|
|
23613
|
-
var
|
|
23916
|
+
var fs16 = __toESM(require("node:fs"), 1);
|
|
23614
23917
|
var path15 = __toESM(require("node:path"), 1);
|
|
23615
23918
|
var import_node_crypto3 = require("node:crypto");
|
|
23616
23919
|
|
|
@@ -23622,7 +23925,7 @@ var MASKED_FACTOR_MESSAGE = "\u56E0\u5B50\u7814\u7A76\u529F\u80FD\u5728\u5F53\u5
|
|
|
23622
23925
|
var MASKED_FUTURES_MESSAGE = "\u671F\u8D27\u56DE\u6D4B\u5728\u5F53\u524D\u7248\u672C\u672A\u5F00\u653E\uFF1ArunParams.marketIds \u542B\u671F\u8D27\u4EA4\u6613\u6240\uFF08zj/zs/ds/sq/gq\uFF09\u6216 account_list \u7684 account_type \u4E3A\u671F\u8D27\u3002\u8BF7\u4F7F\u7528\u80A1\u7968\u5E02\u573A\uFF08sh/sz\uFF09\u4E0E account_type=1\u3002";
|
|
23623
23926
|
|
|
23624
23927
|
// src/backtest-config.ts
|
|
23625
|
-
var
|
|
23928
|
+
var fs15 = __toESM(require("node:fs"), 1);
|
|
23626
23929
|
var path14 = __toESM(require("node:path"), 1);
|
|
23627
23930
|
var import_node_crypto2 = require("node:crypto");
|
|
23628
23931
|
var BACKTEST_CONFIG_KEYS = [
|
|
@@ -23662,7 +23965,7 @@ var FEE_KEYS = [
|
|
|
23662
23965
|
"close_tax",
|
|
23663
23966
|
"margin_ratio"
|
|
23664
23967
|
];
|
|
23665
|
-
var
|
|
23968
|
+
var record4 = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
23666
23969
|
var pick2 = (v, keys) => Object.fromEntries(keys.filter((k) => Object.prototype.hasOwnProperty.call(v, k)).map((k) => [k, v[k]]));
|
|
23667
23970
|
function readBacktestBaseline(tool, args) {
|
|
23668
23971
|
const create = tool === "mcp-create-and-run-backtest";
|
|
@@ -23670,40 +23973,40 @@ function readBacktestBaseline(tool, args) {
|
|
|
23670
23973
|
const directory = args[create ? "strategyPath" : "codePath"];
|
|
23671
23974
|
if (directory === void 0) return void 0;
|
|
23672
23975
|
if (typeof directory !== "string" || !path14.isAbsolute(directory)) throw new Error("Configuration baseline requires an absolute directory path");
|
|
23673
|
-
const
|
|
23674
|
-
if (create && path14.basename(path14.dirname(
|
|
23976
|
+
const root2 = fs15.realpathSync(directory);
|
|
23977
|
+
if (create && path14.basename(path14.dirname(root2)).toLowerCase() === "backtest") {
|
|
23675
23978
|
throw new Error("strategyPath must identify the strategy root, not a historical backtest directory");
|
|
23676
23979
|
}
|
|
23677
|
-
const file = path14.join(
|
|
23678
|
-
const raw =
|
|
23980
|
+
const file = path14.join(root2, ".vscode", "tradesetting.json");
|
|
23981
|
+
const raw = fs15.readFileSync(file);
|
|
23679
23982
|
let config2;
|
|
23680
23983
|
try {
|
|
23681
23984
|
config2 = JSON.parse(raw.toString("utf8").replace(/^\uFEFF/, ""));
|
|
23682
23985
|
} catch {
|
|
23683
23986
|
throw new Error("Configuration baseline is not valid JSON");
|
|
23684
23987
|
}
|
|
23685
|
-
if (!
|
|
23988
|
+
if (!record4(config2) || config2.strategy_id !== args.strategyId) throw new Error("Configuration baseline strategy_id is missing or mismatched");
|
|
23686
23989
|
if (!create && (typeof args.runId !== "string" || config2.backtest_id !== args.runId)) {
|
|
23687
23990
|
throw new Error("Configuration baseline backtest_id does not match the requested runId");
|
|
23688
23991
|
}
|
|
23689
23992
|
const params = pick2(config2, [...BACKTEST_CONFIG_KEYS, ...INTERNAL_CONFIG_KEYS]);
|
|
23690
23993
|
for (const key of ["base_tpl_obj", "ratio_tpl_obj"]) {
|
|
23691
|
-
if (params[key] !== void 0 && !
|
|
23994
|
+
if (params[key] !== void 0 && !record4(params[key])) throw new Error(`Configuration baseline ${key} must be an object`);
|
|
23692
23995
|
}
|
|
23693
|
-
if (
|
|
23694
|
-
if (
|
|
23996
|
+
if (record4(params.base_tpl_obj)) params.base_tpl_obj = pick2(params.base_tpl_obj, BASE_KEYS);
|
|
23997
|
+
if (record4(params.ratio_tpl_obj)) {
|
|
23695
23998
|
const fees = params.ratio_tpl_obj;
|
|
23696
23999
|
for (const asset of ["stock", "future", "fund", "bond"]) {
|
|
23697
|
-
if (fees[asset] !== void 0 && !
|
|
24000
|
+
if (fees[asset] !== void 0 && !record4(fees[asset])) throw new Error(`Configuration baseline fee section ${asset} must be an object`);
|
|
23698
24001
|
}
|
|
23699
24002
|
params.ratio_tpl_obj = {
|
|
23700
24003
|
...pick2(fees, ["name", "zhCnName"]),
|
|
23701
|
-
...Object.fromEntries(["stock", "future", "fund", "bond"].filter((k) =>
|
|
24004
|
+
...Object.fromEntries(["stock", "future", "fund", "bond"].filter((k) => record4(fees[k])).map((k) => [k, pick2(fees[k], FEE_KEYS)]))
|
|
23702
24005
|
};
|
|
23703
24006
|
}
|
|
23704
24007
|
if (Array.isArray(params.account_list)) {
|
|
23705
24008
|
params.account_list = params.account_list.map((account) => {
|
|
23706
|
-
if (!
|
|
24009
|
+
if (!record4(account)) throw new Error("Configuration baseline account_list contains a non-object");
|
|
23707
24010
|
const result = pick2(account, ["pindex", "account_id", "cash", "account_type"]);
|
|
23708
24011
|
if (create && typeof result.account_id === "string" && /^RN-[A-Za-z0-9-]+_\d+$/.test(result.account_id)) result.account_id = "";
|
|
23709
24012
|
return result;
|
|
@@ -23717,7 +24020,7 @@ function readBacktestBaseline(tool, args) {
|
|
|
23717
24020
|
}
|
|
23718
24021
|
function reconcileBaselineCapital(params, overrides) {
|
|
23719
24022
|
const accounts = params.account_list;
|
|
23720
|
-
if (!Array.isArray(accounts) || !accounts.length || accounts.some((a) => !
|
|
24023
|
+
if (!Array.isArray(accounts) || !accounts.length || accounts.some((a) => !record4(a) || typeof a.cash !== "number" || !Number.isFinite(a.cash) || a.cash < 0)) {
|
|
23721
24024
|
throw new Error("Configuration baseline requires accounts with finite nonnegative cash");
|
|
23722
24025
|
}
|
|
23723
24026
|
const explicitCapital = Object.prototype.hasOwnProperty.call(overrides, "initial_capital");
|
|
@@ -23807,7 +24110,7 @@ function prepareToolCallArgs(tool, args, contexts) {
|
|
|
23807
24110
|
}
|
|
23808
24111
|
function validateDataRangeArguments(args) {
|
|
23809
24112
|
const errors = [];
|
|
23810
|
-
const error2 = (
|
|
24113
|
+
const error2 = (path19, message) => errors.push({ path: path19, message });
|
|
23811
24114
|
const input = stripControlParams(args);
|
|
23812
24115
|
for (const key of Object.keys(input)) {
|
|
23813
24116
|
if (key !== "params") error2(`$.${key}`, "Unsupported top-level field; query combinations belong in params[]. Date filters are not accepted.");
|
|
@@ -23867,18 +24170,18 @@ function refuseMaskedFuturesBacktest(tool, args) {
|
|
|
23867
24170
|
userAction: "\u5F53\u524D\u7248\u672C\u4EC5\u652F\u6301\u80A1\u7968\u56DE\u6D4B\uFF08sh/sz\uFF09\uFF1B\u671F\u8D27\u56DE\u6D4B\u8BF7\u7B49\u5F85\u540E\u7EED\u7248\u672C\u5F00\u653E\u3002"
|
|
23868
24171
|
}, true);
|
|
23869
24172
|
}
|
|
23870
|
-
async function dispatchSpecialTool(tool, args,
|
|
24173
|
+
async function dispatchSpecialTool(tool, args, client2, timeout, session, waitControl) {
|
|
23871
24174
|
if (tool.name === "mcp-factor-task-status") {
|
|
23872
|
-
return handleFactorTaskStatus(tool, args,
|
|
24175
|
+
return handleFactorTaskStatus(tool, args, client2, timeout, session);
|
|
23873
24176
|
}
|
|
23874
24177
|
if (tool.name === "mcp-wait") {
|
|
23875
|
-
return runWait(tool, args,
|
|
24178
|
+
return runWait(tool, args, client2, timeout, session, waitControl);
|
|
23876
24179
|
}
|
|
23877
24180
|
if (tool.name === "mcp-factor-value-query") {
|
|
23878
24181
|
const hasRecord = typeof args.calculateRecordId === "string" && args.calculateRecordId.length > 0;
|
|
23879
24182
|
const hasFactor = typeof args.factorId === "string" && args.factorId.length > 0;
|
|
23880
|
-
if (!hasRecord && hasFactor) return queryFactorValuesForLatestRecord(tool, args,
|
|
23881
|
-
if (hasRecord) return queryFactorValuesForGivenRecord(tool, args,
|
|
24183
|
+
if (!hasRecord && hasFactor) return queryFactorValuesForLatestRecord(tool, args, client2, timeout, session);
|
|
24184
|
+
if (hasRecord) return queryFactorValuesForGivenRecord(tool, args, client2, timeout, session);
|
|
23882
24185
|
}
|
|
23883
24186
|
if (tool.name === "mcp-factor-calculate-start" || tool.name === "mcp-factor-calculate-incremental-start") {
|
|
23884
24187
|
const factorId = typeof args.factorId === "string" ? args.factorId : "";
|
|
@@ -23886,15 +24189,15 @@ async function dispatchSpecialTool(tool, args, client, timeout, session, waitCon
|
|
|
23886
24189
|
if (blocked) return blocked;
|
|
23887
24190
|
}
|
|
23888
24191
|
if (tool.name === "mcp-get-strategy-list") {
|
|
23889
|
-
return listStrategies(
|
|
24192
|
+
return listStrategies(client2, args, timeout, session.repairHint);
|
|
23890
24193
|
}
|
|
23891
24194
|
if (tool.name === "mcp-create-strategy") {
|
|
23892
|
-
return rejectDuplicateStrategyName(
|
|
24195
|
+
return rejectDuplicateStrategyName(client2, args, timeout, session.repairHint);
|
|
23893
24196
|
}
|
|
23894
24197
|
if (tool.name === "mcp-create-strategy-with-template") {
|
|
23895
24198
|
return injectDebugRunId(tool, injectStrategyDocsHint(
|
|
23896
24199
|
tool,
|
|
23897
|
-
await createStrategyWithTemplate(
|
|
24200
|
+
await createStrategyWithTemplate(client2, args, timeout, session.repairHint),
|
|
23898
24201
|
session.docsPath
|
|
23899
24202
|
));
|
|
23900
24203
|
}
|
|
@@ -23969,7 +24272,7 @@ function readSlaveProperties(filePath) {
|
|
|
23969
24272
|
const entries = /* @__PURE__ */ new Map();
|
|
23970
24273
|
let raw;
|
|
23971
24274
|
try {
|
|
23972
|
-
raw =
|
|
24275
|
+
raw = fs16.readFileSync(filePath, "utf-8");
|
|
23973
24276
|
} catch {
|
|
23974
24277
|
return entries;
|
|
23975
24278
|
}
|
|
@@ -23991,13 +24294,13 @@ function resolveFactorProjectRoot(clientRootDir) {
|
|
|
23991
24294
|
if (!clientRootDir) return void 0;
|
|
23992
24295
|
const cached2 = factorProjectRootCache.get(clientRootDir);
|
|
23993
24296
|
if (cached2) return cached2;
|
|
23994
|
-
const
|
|
24297
|
+
const root2 = clientRootDir.replace(/[\\/]+$/, "");
|
|
23995
24298
|
const configured = expandSlaveValue(
|
|
23996
|
-
readSlaveProperties(path15.join(
|
|
24299
|
+
readSlaveProperties(path15.join(root2, ...ZLTAF_CONFIG_SEGMENTS)),
|
|
23997
24300
|
"slave.factor.project-path",
|
|
23998
|
-
|
|
24301
|
+
root2
|
|
23999
24302
|
);
|
|
24000
|
-
const resolved = configured ? path15.normalize(configured) : path15.join(
|
|
24303
|
+
const resolved = configured ? path15.normalize(configured) : path15.join(root2, ...FALLBACK_FACTOR_PROJECT_PATH);
|
|
24001
24304
|
factorProjectRootCache.set(clientRootDir, resolved);
|
|
24002
24305
|
return resolved;
|
|
24003
24306
|
}
|
|
@@ -24012,7 +24315,7 @@ function checkFactorSourceLoadable(clientRootDir, factorId) {
|
|
|
24012
24315
|
if (!workspacePath) return null;
|
|
24013
24316
|
let source;
|
|
24014
24317
|
try {
|
|
24015
|
-
source =
|
|
24318
|
+
source = fs16.readFileSync(path15.join(workspacePath, "main.py"), "utf8");
|
|
24016
24319
|
} catch {
|
|
24017
24320
|
return null;
|
|
24018
24321
|
}
|
|
@@ -24036,11 +24339,11 @@ function checkFactorSourceLoadable(clientRootDir, factorId) {
|
|
|
24036
24339
|
}
|
|
24037
24340
|
function echoFactorWorkspacePath(tool, result, clientRootDir) {
|
|
24038
24341
|
if (tool.name !== "mcp-factor-detail" || result.isError || !clientRootDir) return result;
|
|
24039
|
-
const
|
|
24040
|
-
if (typeof
|
|
24342
|
+
const text2 = result.content?.[0]?.text;
|
|
24343
|
+
if (typeof text2 !== "string") return result;
|
|
24041
24344
|
let parsed;
|
|
24042
24345
|
try {
|
|
24043
|
-
parsed = JSON.parse(
|
|
24346
|
+
parsed = JSON.parse(text2);
|
|
24044
24347
|
} catch {
|
|
24045
24348
|
return result;
|
|
24046
24349
|
}
|
|
@@ -24257,7 +24560,7 @@ function backtestWindowPreflightError(tool, reason, message, details) {
|
|
|
24257
24560
|
function isExistingAbsoluteDirectory(value) {
|
|
24258
24561
|
if (!value || !path15.isAbsolute(value)) return false;
|
|
24259
24562
|
try {
|
|
24260
|
-
return
|
|
24563
|
+
return fs16.statSync(value).isDirectory();
|
|
24261
24564
|
} catch {
|
|
24262
24565
|
return false;
|
|
24263
24566
|
}
|
|
@@ -24265,8 +24568,8 @@ function isExistingAbsoluteDirectory(value) {
|
|
|
24265
24568
|
function readBacktestIdFromCodePath(codePath) {
|
|
24266
24569
|
try {
|
|
24267
24570
|
const tradesettingPath = path15.join(codePath, ".vscode", "tradesetting.json");
|
|
24268
|
-
if (!
|
|
24269
|
-
const parsed = JSON.parse(
|
|
24571
|
+
if (!fs16.existsSync(tradesettingPath)) return void 0;
|
|
24572
|
+
const parsed = JSON.parse(fs16.readFileSync(tradesettingPath, "utf-8"));
|
|
24270
24573
|
if (!isRecord3(parsed)) return void 0;
|
|
24271
24574
|
const value = parsed.backtest_id ?? parsed.backtestId;
|
|
24272
24575
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
@@ -24504,9 +24807,9 @@ var DCM_PROGRESS_TOOL = {
|
|
|
24504
24807
|
name: "mcp-get-download-progress",
|
|
24505
24808
|
responseTransform: "downloadProgress"
|
|
24506
24809
|
};
|
|
24507
|
-
async function probeDataPrep(
|
|
24810
|
+
async function probeDataPrep(client2, timeout) {
|
|
24508
24811
|
try {
|
|
24509
|
-
const response = await
|
|
24812
|
+
const response = await client2.invoke(
|
|
24510
24813
|
DCM_PROGRESS_URI,
|
|
24511
24814
|
{},
|
|
24512
24815
|
JSON.stringify({ uuid: "0" }),
|
|
@@ -24531,8 +24834,8 @@ async function probeDataPrep(client, timeout) {
|
|
|
24531
24834
|
return void 0;
|
|
24532
24835
|
}
|
|
24533
24836
|
}
|
|
24534
|
-
async function handleFactorTaskStatus(tool, args,
|
|
24535
|
-
const response = await
|
|
24837
|
+
async function handleFactorTaskStatus(tool, args, client2, timeout, session) {
|
|
24838
|
+
const response = await client2.invoke(
|
|
24536
24839
|
buildIpcUri2(tool, args),
|
|
24537
24840
|
buildIpcParams(tool, args),
|
|
24538
24841
|
buildIpcBody2(tool, args),
|
|
@@ -24546,7 +24849,7 @@ async function handleFactorTaskStatus(tool, args, client, timeout, session) {
|
|
|
24546
24849
|
if (isRecord3(parsed) && isRecord3(parsed.Data)) {
|
|
24547
24850
|
const data = parsed.Data;
|
|
24548
24851
|
if (Number(data.status) === 1 && Number(data.progress) === 0) {
|
|
24549
|
-
const dataPrep = await probeDataPrep(
|
|
24852
|
+
const dataPrep = await probeDataPrep(client2, timeout);
|
|
24550
24853
|
if (dataPrep) {
|
|
24551
24854
|
enriched = {
|
|
24552
24855
|
content: [{ type: "text", text: JSON.stringify({ ...parsed, Data: { ...data, dataPrep } }) }]
|
|
@@ -24618,9 +24921,9 @@ var FACTOR_LATEST_SUCCESS_TOOL = {
|
|
|
24618
24921
|
name: "mcp-factor-calculate-latest-success",
|
|
24619
24922
|
ipcUri: FACTOR_LATEST_SUCCESS_URI
|
|
24620
24923
|
};
|
|
24621
|
-
async function resolveLatestCalculateRecordId(
|
|
24924
|
+
async function resolveLatestCalculateRecordId(client2, factorId, storageScope, timeout) {
|
|
24622
24925
|
try {
|
|
24623
|
-
const response = await
|
|
24926
|
+
const response = await client2.invoke(
|
|
24624
24927
|
FACTOR_LATEST_SUCCESS_URI,
|
|
24625
24928
|
{},
|
|
24626
24929
|
JSON.stringify({ factorId, storageScope }),
|
|
@@ -24693,9 +24996,9 @@ function extractEdmsRows(parsed) {
|
|
|
24693
24996
|
}
|
|
24694
24997
|
return rows;
|
|
24695
24998
|
}
|
|
24696
|
-
async function readFactorCrossSection(
|
|
24999
|
+
async function readFactorCrossSection(client2, readWith, dayStartMs, timeout) {
|
|
24697
25000
|
try {
|
|
24698
|
-
const response = await
|
|
25001
|
+
const response = await client2.invoke(
|
|
24699
25002
|
ZLT_EDMS_GET_EXDATA_URI,
|
|
24700
25003
|
{},
|
|
24701
25004
|
buildEdmsExDataBody(readWith, dayStartMs),
|
|
@@ -24726,7 +25029,7 @@ function markResolvedRecordSource(result) {
|
|
|
24726
25029
|
return result;
|
|
24727
25030
|
}
|
|
24728
25031
|
}
|
|
24729
|
-
async function fillFactorValuesFromEdms(base, args,
|
|
25032
|
+
async function fillFactorValuesFromEdms(base, args, client2, timeout, recordEndDate) {
|
|
24730
25033
|
if (base.isError || base.content.length === 0) return base;
|
|
24731
25034
|
let parsed;
|
|
24732
25035
|
try {
|
|
@@ -24753,7 +25056,7 @@ async function fillFactorValuesFromEdms(base, args, client, timeout, recordEndDa
|
|
|
24753
25056
|
let usedMs = anchor;
|
|
24754
25057
|
for (let back = 0; back < attempts; back += 1) {
|
|
24755
25058
|
usedMs = anchor - back * ZLT_EDMS_DAY_MS;
|
|
24756
|
-
rows = await readFactorCrossSection(
|
|
25059
|
+
rows = await readFactorCrossSection(client2, target, usedMs, timeout);
|
|
24757
25060
|
if (rows) break;
|
|
24758
25061
|
}
|
|
24759
25062
|
if (!rows) return base;
|
|
@@ -24784,23 +25087,23 @@ async function fillFactorValuesFromEdms(base, args, client, timeout, recordEndDa
|
|
|
24784
25087
|
}]
|
|
24785
25088
|
};
|
|
24786
25089
|
}
|
|
24787
|
-
async function queryFactorValuesForGivenRecord(tool, args,
|
|
25090
|
+
async function queryFactorValuesForGivenRecord(tool, args, client2, timeout, session) {
|
|
24788
25091
|
try {
|
|
24789
|
-
const response = await
|
|
25092
|
+
const response = await client2.invoke(
|
|
24790
25093
|
buildIpcUri2(tool, args),
|
|
24791
25094
|
buildIpcParams(tool, args),
|
|
24792
25095
|
buildIpcBody2(tool, args),
|
|
24793
25096
|
timeout
|
|
24794
25097
|
);
|
|
24795
25098
|
const base = handleIpcResponse(response, tool, session.repairHint);
|
|
24796
|
-
return await fillFactorValuesFromEdms(base, args,
|
|
25099
|
+
return await fillFactorValuesFromEdms(base, args, client2, timeout, millisToChinaDate(Date.now()));
|
|
24797
25100
|
} catch {
|
|
24798
25101
|
return null;
|
|
24799
25102
|
}
|
|
24800
25103
|
}
|
|
24801
|
-
async function queryFactorValuesForLatestRecord(tool, args,
|
|
25104
|
+
async function queryFactorValuesForLatestRecord(tool, args, client2, timeout, session) {
|
|
24802
25105
|
const factorId = typeof args.factorId === "string" ? args.factorId : "";
|
|
24803
|
-
const resolved = await resolveLatestCalculateRecordId(
|
|
25106
|
+
const resolved = await resolveLatestCalculateRecordId(client2, factorId, FACTOR_RESEARCH_SCOPE, timeout);
|
|
24804
25107
|
if (resolved.noRecord) {
|
|
24805
25108
|
return jsonToolResult(
|
|
24806
25109
|
10055,
|
|
@@ -24818,7 +25121,7 @@ async function queryFactorValuesForLatestRecord(tool, args, client, timeout, ses
|
|
|
24818
25121
|
if (!resolved.id) return null;
|
|
24819
25122
|
const finalArgs = { ...args, calculateRecordId: resolved.id };
|
|
24820
25123
|
try {
|
|
24821
|
-
const response = await
|
|
25124
|
+
const response = await client2.invoke(
|
|
24822
25125
|
buildIpcUri2(tool, finalArgs),
|
|
24823
25126
|
buildIpcParams(tool, finalArgs),
|
|
24824
25127
|
buildIpcBody2(tool, finalArgs),
|
|
@@ -24828,7 +25131,7 @@ async function queryFactorValuesForLatestRecord(tool, args, client, timeout, ses
|
|
|
24828
25131
|
const filled = await fillFactorValuesFromEdms(
|
|
24829
25132
|
base,
|
|
24830
25133
|
args,
|
|
24831
|
-
|
|
25134
|
+
client2,
|
|
24832
25135
|
timeout,
|
|
24833
25136
|
resolved.endDate ?? millisToChinaDate(Date.now())
|
|
24834
25137
|
);
|
|
@@ -24963,9 +25266,9 @@ var FACTOR_FAILURE_SIGNATURES = [
|
|
|
24963
25266
|
function factorFailureMessage(data) {
|
|
24964
25267
|
if (typeof data.errorMessage === "string" && data.errorMessage) return data.errorMessage;
|
|
24965
25268
|
for (const key of ["calculateRecord", "detectRecord"]) {
|
|
24966
|
-
const
|
|
24967
|
-
if (isRecord3(
|
|
24968
|
-
return
|
|
25269
|
+
const record5 = data[key];
|
|
25270
|
+
if (isRecord3(record5) && typeof record5.errorMessage === "string" && record5.errorMessage) {
|
|
25271
|
+
return record5.errorMessage;
|
|
24969
25272
|
}
|
|
24970
25273
|
}
|
|
24971
25274
|
return "";
|
|
@@ -25287,14 +25590,14 @@ function backtestWaitLane(runId, session, codePath, resultBaseline, attemptStart
|
|
|
25287
25590
|
}
|
|
25288
25591
|
};
|
|
25289
25592
|
}
|
|
25290
|
-
async function runWaitLoop(lane,
|
|
25593
|
+
async function runWaitLoop(lane, client2, timeout, session, control) {
|
|
25291
25594
|
let failureCount = 0;
|
|
25292
25595
|
for (; ; ) {
|
|
25293
25596
|
if (control.abortSignal?.aborted) return waitError(10047, "\u5DF2\u53D6\u6D88\u7B49\u5F85\u3002");
|
|
25294
25597
|
let response;
|
|
25295
25598
|
try {
|
|
25296
25599
|
const pollArgs = lane.pollArgs();
|
|
25297
|
-
response = await
|
|
25600
|
+
response = await client2.invoke(
|
|
25298
25601
|
buildIpcUri2(lane.pollIdentity, pollArgs),
|
|
25299
25602
|
buildIpcParams(lane.pollIdentity, pollArgs),
|
|
25300
25603
|
buildIpcBody2(lane.pollIdentity, pollArgs),
|
|
@@ -25328,7 +25631,7 @@ async function runWaitLoop(lane, client, timeout, session, control) {
|
|
|
25328
25631
|
await sleepUnlessAborted(WAIT_POLL_INTERVAL_MS, control.abortSignal);
|
|
25329
25632
|
}
|
|
25330
25633
|
}
|
|
25331
|
-
async function runWait(_tool, args,
|
|
25634
|
+
async function runWait(_tool, args, client2, timeout, session, control) {
|
|
25332
25635
|
const kind = typeof args.kind === "string" ? args.kind : "";
|
|
25333
25636
|
const id = typeof args.id === "string" ? args.id.trim() : "";
|
|
25334
25637
|
const suppliedCodePath = typeof args.codePath === "string" ? args.codePath.trim() : "";
|
|
@@ -25425,7 +25728,7 @@ async function runWait(_tool, args, client, timeout, session, control) {
|
|
|
25425
25728
|
}
|
|
25426
25729
|
);
|
|
25427
25730
|
}
|
|
25428
|
-
return runWaitLoop(lane,
|
|
25731
|
+
return runWaitLoop(lane, client2, timeout, session, control);
|
|
25429
25732
|
}
|
|
25430
25733
|
function applyBacktestResultGuards(tool, args, result, states, contexts, activeRunIds) {
|
|
25431
25734
|
const completionResult = applyBacktestCompletionGuard(tool, args, result, contexts);
|
|
@@ -25444,10 +25747,10 @@ function applyBacktestResultGuards(tool, args, result, states, contexts, activeR
|
|
|
25444
25747
|
function readRunResultFile(codePath) {
|
|
25445
25748
|
try {
|
|
25446
25749
|
const resultPath = path15.join(codePath, "log", "result.json");
|
|
25447
|
-
if (!
|
|
25448
|
-
const before =
|
|
25449
|
-
const raw =
|
|
25450
|
-
const after =
|
|
25750
|
+
if (!fs16.existsSync(resultPath)) return null;
|
|
25751
|
+
const before = fs16.statSync(resultPath);
|
|
25752
|
+
const raw = fs16.readFileSync(resultPath);
|
|
25753
|
+
const after = fs16.statSync(resultPath);
|
|
25451
25754
|
if (before.mtimeMs !== after.mtimeMs || before.size !== after.size) return null;
|
|
25452
25755
|
const parsed = JSON.parse(raw.toString("utf-8"));
|
|
25453
25756
|
if (!isRecord3(parsed)) return null;
|
|
@@ -25663,8 +25966,8 @@ function hashBacktestSource(codePath) {
|
|
|
25663
25966
|
if (!codePath) return void 0;
|
|
25664
25967
|
try {
|
|
25665
25968
|
const sourcePath = path15.join(codePath, "main.py");
|
|
25666
|
-
if (!
|
|
25667
|
-
return (0, import_node_crypto3.createHash)("sha256").update(
|
|
25969
|
+
if (!fs16.statSync(sourcePath).isFile()) return void 0;
|
|
25970
|
+
return (0, import_node_crypto3.createHash)("sha256").update(fs16.readFileSync(sourcePath)).digest("hex");
|
|
25668
25971
|
} catch {
|
|
25669
25972
|
return void 0;
|
|
25670
25973
|
}
|
|
@@ -25720,7 +26023,7 @@ function resolveStrategyDocsPath(clientRootDir) {
|
|
|
25720
26023
|
"docs"
|
|
25721
26024
|
);
|
|
25722
26025
|
try {
|
|
25723
|
-
if (!
|
|
26026
|
+
if (!fs16.existsSync(docsPath)) return void 0;
|
|
25724
26027
|
} catch {
|
|
25725
26028
|
return void 0;
|
|
25726
26029
|
}
|
|
@@ -25737,7 +26040,7 @@ function injectDebugRunId(tool, result) {
|
|
|
25737
26040
|
const localPath = typeof parsed.Data.localPath === "string" ? parsed.Data.localPath.trim() : "";
|
|
25738
26041
|
if (!localPath) return result;
|
|
25739
26042
|
const settings = JSON.parse(
|
|
25740
|
-
|
|
26043
|
+
fs16.readFileSync(path15.join(localPath, ".vscode", "tradesetting.json"), "utf8")
|
|
25741
26044
|
);
|
|
25742
26045
|
const debugRunId = isRecord3(settings) && typeof settings.backtest_id === "string" ? settings.backtest_id.trim() : "";
|
|
25743
26046
|
if (!debugRunId) return result;
|
|
@@ -25936,13 +26239,13 @@ function handleIpcResponse(response, tool, repairHint = identityRepairHint, data
|
|
|
25936
26239
|
};
|
|
25937
26240
|
}
|
|
25938
26241
|
const data = repairHint(parsed.data);
|
|
25939
|
-
const
|
|
26242
|
+
const text2 = typeof data === "string" ? applyResponseTransform(data, tool, dataRoots) : applyResponseTransform(JSON.stringify(data), tool, dataRoots);
|
|
25940
26243
|
return {
|
|
25941
|
-
content: [{ type: "text", text }],
|
|
26244
|
+
content: [{ type: "text", text: text2 }],
|
|
25942
26245
|
isError: isIpcBusinessError(data) || void 0
|
|
25943
26246
|
};
|
|
25944
26247
|
}
|
|
25945
|
-
async function listStrategies(
|
|
26248
|
+
async function listStrategies(client2, args, timeout, repairHint = identityRepairHint) {
|
|
25946
26249
|
const statusValue = Number(args.status);
|
|
25947
26250
|
const status = Number.isFinite(statusValue) ? statusValue : 0;
|
|
25948
26251
|
const treeIdValue = Number(args.treeId);
|
|
@@ -25950,13 +26253,13 @@ async function listStrategies(client, args, timeout, repairHint = identityRepair
|
|
|
25950
26253
|
try {
|
|
25951
26254
|
if (treeId !== 0) {
|
|
25952
26255
|
return handleIpcResponse(
|
|
25953
|
-
await
|
|
26256
|
+
await client2.invoke("/zltaf_slave/v1/strategy/list", {}, JSON.stringify({ status, treeId }), timeout),
|
|
25954
26257
|
void 0,
|
|
25955
26258
|
repairHint
|
|
25956
26259
|
);
|
|
25957
26260
|
}
|
|
25958
26261
|
const treeResult = handleIpcResponse(
|
|
25959
|
-
await
|
|
26262
|
+
await client2.invoke("/zltaf_slave/v1/strategy-tree/list", {}, JSON.stringify({ treeType: "strategy" }), timeout),
|
|
25960
26263
|
void 0,
|
|
25961
26264
|
repairHint
|
|
25962
26265
|
);
|
|
@@ -25965,7 +26268,7 @@ async function listStrategies(client, args, timeout, repairHint = identityRepair
|
|
|
25965
26268
|
const merged = [];
|
|
25966
26269
|
for (const tree of extractStrategyTreeIds(treeResult)) {
|
|
25967
26270
|
const listResult = handleIpcResponse(
|
|
25968
|
-
await
|
|
26271
|
+
await client2.invoke("/zltaf_slave/v1/strategy/list", {}, JSON.stringify({ status, treeId: tree }), timeout),
|
|
25969
26272
|
void 0,
|
|
25970
26273
|
repairHint
|
|
25971
26274
|
);
|
|
@@ -25989,10 +26292,10 @@ async function listStrategies(client, args, timeout, repairHint = identityRepair
|
|
|
25989
26292
|
};
|
|
25990
26293
|
}
|
|
25991
26294
|
}
|
|
25992
|
-
async function rejectDuplicateStrategyName(
|
|
26295
|
+
async function rejectDuplicateStrategyName(client2, args, timeout, repairHint = identityRepairHint) {
|
|
25993
26296
|
const strategyName = typeof args.name === "string" ? args.name.trim() : "";
|
|
25994
26297
|
if (!strategyName) return null;
|
|
25995
|
-
const listResult = await listStrategies(
|
|
26298
|
+
const listResult = await listStrategies(client2, { status: 0, treeId: 0 }, timeout, repairHint);
|
|
25996
26299
|
if (listResult.isError) return listResult;
|
|
25997
26300
|
const existing = extractDataArray(listResult).find((item) => isRecord3(item) && typeof item.strategyName === "string" && item.strategyName.trim() === strategyName);
|
|
25998
26301
|
if (!isRecord3(existing)) return null;
|
|
@@ -26010,10 +26313,10 @@ async function rejectDuplicateStrategyName(client, args, timeout, repairHint = i
|
|
|
26010
26313
|
true
|
|
26011
26314
|
);
|
|
26012
26315
|
}
|
|
26013
|
-
async function createStrategyWithTemplate(
|
|
26316
|
+
async function createStrategyWithTemplate(client2, args, timeout, repairHint = identityRepairHint) {
|
|
26014
26317
|
let createResponse;
|
|
26015
26318
|
try {
|
|
26016
|
-
createResponse = await
|
|
26319
|
+
createResponse = await client2.invoke(
|
|
26017
26320
|
"/zltaf_slave/v1/strategy/create-with-template",
|
|
26018
26321
|
{},
|
|
26019
26322
|
JSON.stringify(stripControlParams(args)),
|
|
@@ -26048,7 +26351,7 @@ async function createStrategyWithTemplate(client, args, timeout, repairHint = id
|
|
|
26048
26351
|
const detailBody = { strategyId };
|
|
26049
26352
|
if (typeof args.userId === "string" && args.userId.trim()) detailBody.userId = args.userId.trim();
|
|
26050
26353
|
try {
|
|
26051
|
-
const detailResponse = await
|
|
26354
|
+
const detailResponse = await client2.invoke(
|
|
26052
26355
|
"/zltaf_slave/v1/strategy/detail",
|
|
26053
26356
|
{},
|
|
26054
26357
|
JSON.stringify(detailBody),
|
|
@@ -26092,14 +26395,14 @@ function extractStrategyTreeIds(result) {
|
|
|
26092
26395
|
}
|
|
26093
26396
|
return ids;
|
|
26094
26397
|
}
|
|
26095
|
-
async function executeSteps(steps,
|
|
26398
|
+
async function executeSteps(steps, client2, initialBody, timeout, repairHint = identityRepairHint, toolName) {
|
|
26096
26399
|
let body = { ...initialBody };
|
|
26097
26400
|
for (let i = 0; i < steps.length; i++) {
|
|
26098
26401
|
const step = steps[i];
|
|
26099
26402
|
const stepBody = buildStepBody(step, body);
|
|
26100
26403
|
let response;
|
|
26101
26404
|
try {
|
|
26102
|
-
response = await
|
|
26405
|
+
response = await client2.invoke(step.uri, {}, JSON.stringify(stepBody), timeout);
|
|
26103
26406
|
} catch (err) {
|
|
26104
26407
|
const message = err instanceof Error ? err.message : String(err);
|
|
26105
26408
|
return {
|
|
@@ -26233,12 +26536,12 @@ function preflightCreatedBacktestSource(toolName, body) {
|
|
|
26233
26536
|
if (toolName !== "mcp-create-and-run-backtest") return null;
|
|
26234
26537
|
const runId = typeof body.runId === "string" ? body.runId.trim() : "";
|
|
26235
26538
|
const codePath = typeof body.codePath === "string" ? body.codePath.trim() : "";
|
|
26236
|
-
if (!codePath || !
|
|
26539
|
+
if (!codePath || !fs16.existsSync(codePath)) return null;
|
|
26237
26540
|
const sourcePath = path15.join(codePath, "main.py");
|
|
26238
|
-
if (!
|
|
26541
|
+
if (!fs16.existsSync(sourcePath)) return null;
|
|
26239
26542
|
let source;
|
|
26240
26543
|
try {
|
|
26241
|
-
source =
|
|
26544
|
+
source = fs16.readFileSync(sourcePath, "utf8");
|
|
26242
26545
|
} catch (error2) {
|
|
26243
26546
|
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
26244
26547
|
return jsonToolResult(10061, "\u56DE\u6D4B\u4EE3\u7801\u5FEB\u7167\u65E0\u6CD5\u8BFB\u53D6\uFF0C\u672A\u542F\u52A8\u7B56\u7565\u5F15\u64CE\u3002", {
|
|
@@ -26320,12 +26623,12 @@ function isIpcBusinessError(value) {
|
|
|
26320
26623
|
const errNo = Number(value.ErrNo);
|
|
26321
26624
|
return Number.isFinite(errNo) && errNo !== 0;
|
|
26322
26625
|
}
|
|
26323
|
-
function parseMalformedBusinessError(
|
|
26324
|
-
const codeMatch =
|
|
26626
|
+
function parseMalformedBusinessError(text2) {
|
|
26627
|
+
const codeMatch = text2.match(/"code"\s*:\s*(-?\d+)/);
|
|
26325
26628
|
if (!codeMatch) return null;
|
|
26326
26629
|
const errNo = Number(codeMatch[1]);
|
|
26327
26630
|
if (!Number.isFinite(errNo) || errNo === 0) return null;
|
|
26328
|
-
const cleaned =
|
|
26631
|
+
const cleaned = text2.replace(/\u0000/g, "");
|
|
26329
26632
|
const messageMatch = cleaned.match(/"message"\s*:\s*"([\s\S]*)"\s*\}?\s*$/);
|
|
26330
26633
|
const errMsg = messageMatch ? messageMatch[1].replace(/\\"/g, '"') : cleaned;
|
|
26331
26634
|
return {
|
|
@@ -26334,10 +26637,10 @@ function parseMalformedBusinessError(text) {
|
|
|
26334
26637
|
Data: { raw: cleaned }
|
|
26335
26638
|
};
|
|
26336
26639
|
}
|
|
26337
|
-
function applyResponseTransform(
|
|
26338
|
-
if (!tool?.responseTransform || !
|
|
26640
|
+
function applyResponseTransform(text2, tool, dataRoots) {
|
|
26641
|
+
if (!tool?.responseTransform || !text2) return text2;
|
|
26339
26642
|
try {
|
|
26340
|
-
const parsed = JSON.parse(
|
|
26643
|
+
const parsed = JSON.parse(text2);
|
|
26341
26644
|
if (tool.responseTransform === "dataRange") {
|
|
26342
26645
|
return JSON.stringify(formatDataRangeResult(parsed, dataRoots));
|
|
26343
26646
|
}
|
|
@@ -26354,9 +26657,9 @@ function applyResponseTransform(text, tool, dataRoots) {
|
|
|
26354
26657
|
return JSON.stringify(formatFactorValuesResult(parsed));
|
|
26355
26658
|
}
|
|
26356
26659
|
} catch {
|
|
26357
|
-
return
|
|
26660
|
+
return text2;
|
|
26358
26661
|
}
|
|
26359
|
-
return
|
|
26662
|
+
return text2;
|
|
26360
26663
|
}
|
|
26361
26664
|
var FACTOR_VALUES_RESULT_KIND = "factor-values";
|
|
26362
26665
|
function parseFactorOutputPath(outputPath) {
|
|
@@ -26478,7 +26781,7 @@ function normalizeDataRoot(raw, clientRootDir) {
|
|
|
26478
26781
|
}
|
|
26479
26782
|
function readJsonFile(filePath) {
|
|
26480
26783
|
try {
|
|
26481
|
-
const parsed = JSON.parse(
|
|
26784
|
+
const parsed = JSON.parse(fs16.readFileSync(filePath, "utf-8"));
|
|
26482
26785
|
return isRecord3(parsed) ? parsed : void 0;
|
|
26483
26786
|
} catch {
|
|
26484
26787
|
return void 0;
|
|
@@ -26491,11 +26794,11 @@ function resolveDataRoots(clientRootDir) {
|
|
|
26491
26794
|
const readAt = dataRootsReadAt.get(clientRootDir) ?? 0;
|
|
26492
26795
|
const cached2 = Date.now() - readAt < DATA_ROOTS_TTL_MS ? dataRootsCache.get(clientRootDir) : void 0;
|
|
26493
26796
|
if (cached2) return cached2;
|
|
26494
|
-
const
|
|
26495
|
-
const dcSdk = readJsonFile(path15.join(
|
|
26496
|
-
const dcm = readJsonFile(path15.join(
|
|
26497
|
-
const engineRoot = normalizeDataRoot(isRecord3(dcSdk?.mdf) ? dcSdk.mdf.path : void 0,
|
|
26498
|
-
const downloadRoot = normalizeDataRoot(dcm?.download_home,
|
|
26797
|
+
const root2 = clientRootDir.replace(/[\\/]+$/, "");
|
|
26798
|
+
const dcSdk = readJsonFile(path15.join(root2, ...DC_SDK_CONFIG_SEGMENTS));
|
|
26799
|
+
const dcm = readJsonFile(path15.join(root2, ...DCM_CONFIG_SEGMENTS));
|
|
26800
|
+
const engineRoot = normalizeDataRoot(isRecord3(dcSdk?.mdf) ? dcSdk.mdf.path : void 0, root2);
|
|
26801
|
+
const downloadRoot = normalizeDataRoot(dcm?.download_home, root2);
|
|
26499
26802
|
const resolved = Boolean(engineRoot && downloadRoot);
|
|
26500
26803
|
const status = {
|
|
26501
26804
|
engineRoot,
|
|
@@ -26525,7 +26828,7 @@ function engineHasAnyHqSeries(engineRoot, series) {
|
|
|
26525
26828
|
for (const { exchangeId, dataType } of series) {
|
|
26526
26829
|
const dir = path15.join(engineRoot, "hqdata", "his", exchangeId, dataType);
|
|
26527
26830
|
try {
|
|
26528
|
-
if (
|
|
26831
|
+
if (fs16.existsSync(dir) && fs16.readdirSync(dir).length > 0) return true;
|
|
26529
26832
|
} catch {
|
|
26530
26833
|
return void 0;
|
|
26531
26834
|
}
|
|
@@ -26930,8 +27233,8 @@ function describeDataRangeSecurityClass(legacyValue, tokenClass, idToName) {
|
|
|
26930
27233
|
return idToName[nibble * 16] || `\u7C7B\u522B${tokenClass}`;
|
|
26931
27234
|
}
|
|
26932
27235
|
function compactDataRangeDate(value) {
|
|
26933
|
-
const
|
|
26934
|
-
const match =
|
|
27236
|
+
const text2 = typeof value === "number" || typeof value === "string" ? String(value).trim() : "";
|
|
27237
|
+
const match = text2.match(/^((?:19|20)\d{2})(\d{2})(\d{2})/);
|
|
26935
27238
|
if (!match) return null;
|
|
26936
27239
|
const [, year, month, day] = match;
|
|
26937
27240
|
const candidate = /* @__PURE__ */ new Date(`${year}-${month}-${day}T00:00:00Z`);
|
|
@@ -26953,7 +27256,7 @@ async function waitForCacheRead(probe, timeoutMs, control = {}, clock = { now: D
|
|
|
26953
27256
|
const started = clock.now();
|
|
26954
27257
|
let attempts = 0;
|
|
26955
27258
|
let upstream;
|
|
26956
|
-
const
|
|
27259
|
+
const finish2 = (cacheRead, reason) => ({
|
|
26957
27260
|
cacheRead,
|
|
26958
27261
|
cacheWrite: "unverified",
|
|
26959
27262
|
reason,
|
|
@@ -26964,36 +27267,36 @@ async function waitForCacheRead(probe, timeoutMs, control = {}, clock = { now: D
|
|
|
26964
27267
|
stopAutoRetry: cacheRead !== "ready"
|
|
26965
27268
|
});
|
|
26966
27269
|
while (true) {
|
|
26967
|
-
if (control.abortSignal?.aborted) return
|
|
27270
|
+
if (control.abortSignal?.aborted) return finish2("unknown", "cancelled");
|
|
26968
27271
|
control.heartbeat?.(attempts, { message: "Checking cache.read readiness; cache.write remains unverified" });
|
|
26969
27272
|
try {
|
|
26970
27273
|
attempts++;
|
|
26971
27274
|
upstream = await probe(timeoutMs === 0 ? 2e4 : Math.max(1, Math.min(2e4, timeoutMs - (clock.now() - started))));
|
|
26972
27275
|
} catch (error2) {
|
|
26973
27276
|
upstream = { message: error2 instanceof Error ? error2.message : String(error2) };
|
|
26974
|
-
return
|
|
27277
|
+
return finish2("unknown", "probe-failed");
|
|
26975
27278
|
}
|
|
26976
|
-
if (control.abortSignal?.aborted) return
|
|
27279
|
+
if (control.abortSignal?.aborted) return finish2("unknown", "cancelled");
|
|
26977
27280
|
const envelope = isRecord3(upstream) ? upstream : {};
|
|
26978
27281
|
if (envelope.ErrNo === 0) {
|
|
26979
27282
|
const data = isRecord3(envelope.Data) ? envelope.Data : {};
|
|
26980
27283
|
if (typeof data.download_home === "string" && data.download_home.trim() && (typeof data.disk_free === "number" || typeof data.disk_free === "string") && String(data.disk_free).trim() && Number.isFinite(Number(data.disk_free)) && Number(data.disk_free) >= 0) {
|
|
26981
27284
|
upstream = { ErrNo: 0, ErrMsg: envelope.ErrMsg, Data: { download_home: data.download_home, disk_free: data.disk_free } };
|
|
26982
|
-
return
|
|
27285
|
+
return finish2("ready", "diskspace-response");
|
|
26983
27286
|
}
|
|
26984
|
-
return
|
|
27287
|
+
return finish2("unknown", "unrecognized-response");
|
|
26985
27288
|
}
|
|
26986
27289
|
if (Number(envelope.ErrNo) !== 3 || !/^storage initializing; capability=cache\.read\s*$/i.test(String(envelope.ErrMsg ?? ""))) {
|
|
26987
|
-
return
|
|
27290
|
+
return finish2("unknown", "upstream-error");
|
|
26988
27291
|
}
|
|
26989
27292
|
const remaining = timeoutMs - (clock.now() - started);
|
|
26990
|
-
if (remaining <= 0) return
|
|
27293
|
+
if (remaining <= 0) return finish2("initializing", "deadline");
|
|
26991
27294
|
try {
|
|
26992
27295
|
await clock.sleep(Math.min(3e3, remaining), control.abortSignal);
|
|
26993
27296
|
} catch {
|
|
26994
|
-
return
|
|
27297
|
+
return finish2("unknown", "cancelled");
|
|
26995
27298
|
}
|
|
26996
|
-
if (clock.now() - started >= timeoutMs) return
|
|
27299
|
+
if (clock.now() - started >= timeoutMs) return finish2("initializing", "deadline");
|
|
26997
27300
|
}
|
|
26998
27301
|
}
|
|
26999
27302
|
|
|
@@ -27102,9 +27405,9 @@ function readTextFileHead(filePath, maxBytes = 1048576) {
|
|
|
27102
27405
|
}
|
|
27103
27406
|
}
|
|
27104
27407
|
function summarizeEngineDataView(runDir) {
|
|
27105
|
-
const
|
|
27106
|
-
if (
|
|
27107
|
-
const match = /Mdf Setting\((\{.*?\})\)/.exec(
|
|
27408
|
+
const text2 = readTextFileHead(import_node_path.default.join(runDir, "log", "strategy.log"));
|
|
27409
|
+
if (text2 === null) return { available: false };
|
|
27410
|
+
const match = /Mdf Setting\((\{.*?\})\)/.exec(text2);
|
|
27108
27411
|
if (!match) return { available: false };
|
|
27109
27412
|
let payload;
|
|
27110
27413
|
try {
|
|
@@ -27162,9 +27465,9 @@ function emptyEntrust() {
|
|
|
27162
27465
|
};
|
|
27163
27466
|
}
|
|
27164
27467
|
function summarizeEntrust(runDir) {
|
|
27165
|
-
const
|
|
27166
|
-
if (
|
|
27167
|
-
const lines =
|
|
27468
|
+
const text2 = readTextFile(import_node_path.default.join(runDir, "log", "zlt_entrust.csv"));
|
|
27469
|
+
if (text2 === null) return emptyEntrust();
|
|
27470
|
+
const lines = text2.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
27168
27471
|
if (lines.length === 0) return emptyEntrust();
|
|
27169
27472
|
const header = parseCsvLine(lines[0]).map((name) => name.trim());
|
|
27170
27473
|
const indexByName = /* @__PURE__ */ new Map();
|
|
@@ -27220,14 +27523,14 @@ function isFuturesSecurity(code) {
|
|
|
27220
27523
|
return FUTURES_MARKET_IDS.has(normalized.slice(0, 2)) && /[a-z]/.test(normalized.slice(2));
|
|
27221
27524
|
}
|
|
27222
27525
|
function summarizeRejections(runDir) {
|
|
27223
|
-
const
|
|
27224
|
-
if (
|
|
27526
|
+
const text2 = readTextFile(import_node_path.default.join(runDir, "log", "strategy_user.log"));
|
|
27527
|
+
if (text2 === null) {
|
|
27225
27528
|
return { available: false, total: 0, byReason: {}, structuralFailure: false, samples: [] };
|
|
27226
27529
|
}
|
|
27227
27530
|
const byReason = {};
|
|
27228
27531
|
const samples = [];
|
|
27229
27532
|
let total = 0;
|
|
27230
|
-
for (const line of
|
|
27533
|
+
for (const line of text2.split(/\r?\n/)) {
|
|
27231
27534
|
if (!line.includes("[error]") && !line.includes("Traceback")) continue;
|
|
27232
27535
|
total += 1;
|
|
27233
27536
|
const matched = REJECTION_PATTERNS.find((pattern) => line.includes(pattern));
|
|
@@ -27320,9 +27623,9 @@ function evenStride(items, limit) {
|
|
|
27320
27623
|
return Array.from({ length: limit }, (_, i) => items[Math.round(i * last / (limit - 1))]);
|
|
27321
27624
|
}
|
|
27322
27625
|
var UNITS_NOTE = "\u6536\u76CA\u7C7B\u5B57\u6BB5\uFF08*Pct\uFF09\u5DF2\u662F\u767E\u5206\u6570\uFF0C-15.62 \u5373 -15.62%\uFF1BwinRate / dailyWinRate \u662F 0-1 \u7684\u6BD4\u4F8B\u3002positionRatePct / turnoverRatePct \u6309\u5B9E\u6D4B\u53D6\u503C\u8303\u56F4\u5224\u4E3A\u767E\u5206\u6570\uFF08\u89C2\u6D4B\u5230 91.18 / 92.44\uFF09\uFF0C\u4E0A\u6E38\u672A\u7ED9\u51FA\u4E66\u9762\u53E3\u5F84\u3002";
|
|
27323
|
-
function numberOrNull2(
|
|
27324
|
-
if (
|
|
27325
|
-
const trimmed =
|
|
27626
|
+
function numberOrNull2(text2) {
|
|
27627
|
+
if (text2 === void 0) return null;
|
|
27628
|
+
const trimmed = text2.trim();
|
|
27326
27629
|
if (!trimmed) return null;
|
|
27327
27630
|
const value = Number(trimmed);
|
|
27328
27631
|
return Number.isFinite(value) ? value : null;
|
|
@@ -27340,9 +27643,9 @@ function deriveMaxDrawdownWindow(equity, reportedPct) {
|
|
|
27340
27643
|
peakDate = point.date;
|
|
27341
27644
|
}
|
|
27342
27645
|
if (peak <= 0 || peakDate === void 0) continue;
|
|
27343
|
-
const
|
|
27344
|
-
if (
|
|
27345
|
-
worst =
|
|
27646
|
+
const drop2 = (peak - asset) / peak * 100;
|
|
27647
|
+
if (drop2 > worst) {
|
|
27648
|
+
worst = drop2;
|
|
27346
27649
|
window = { startDate: peakDate, endDate: point.date };
|
|
27347
27650
|
}
|
|
27348
27651
|
}
|
|
@@ -27360,12 +27663,12 @@ function checkRelativeReturn(performance) {
|
|
|
27360
27663
|
}
|
|
27361
27664
|
function summarizeBacktestProfit(runDir, options = {}) {
|
|
27362
27665
|
const notes = [];
|
|
27363
|
-
const
|
|
27364
|
-
if (
|
|
27666
|
+
const text2 = readTextFile(import_node_path.default.join(runDir, "log", PROFIT_CSV));
|
|
27667
|
+
if (text2 === null) {
|
|
27365
27668
|
notes.push(`\u672A\u627E\u5230 log/${PROFIT_CSV}\u3002\u56DE\u6D4B\u672A\u8DD1\u5B8C\u3001\u88AB\u53D6\u6D88\uFF0C\u6216 codePath \u6307\u5411\u4E86\u522B\u7684\u76EE\u5F55\u65F6\u4F1A\u8FD9\u6837\uFF1B\u5148\u7528 mcp-get-backtest-state \u786E\u8BA4 status=5\u3002`);
|
|
27366
27669
|
return { runDir, available: false, rows: 0, notes };
|
|
27367
27670
|
}
|
|
27368
|
-
const lines =
|
|
27671
|
+
const lines = text2.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
27369
27672
|
const header = lines.length > 0 ? parseCsvLine(lines[0]).map((name) => name.trim()) : [];
|
|
27370
27673
|
const indexByName = /* @__PURE__ */ new Map();
|
|
27371
27674
|
header.forEach((name, index) => {
|
|
@@ -27592,8 +27895,8 @@ async function startMcpServer() {
|
|
|
27592
27895
|
};
|
|
27593
27896
|
const recordActiveDownload = (result) => {
|
|
27594
27897
|
if (!runtimeLease) return;
|
|
27595
|
-
const
|
|
27596
|
-
const match =
|
|
27898
|
+
const text2 = result.content?.map((item) => item.type === "text" ? item.text : "").join("\n") ?? "";
|
|
27899
|
+
const match = text2.match(/"uuid"\s*:\s*"([^"]+)"/);
|
|
27597
27900
|
if (!match) return;
|
|
27598
27901
|
leaseStateUpdate = leaseStateUpdate.then(() => updateRuntimeLeaseActiveJob(runtimeLease, "runtime:explicit-start", false)).then(() => updateRuntimeLeaseActiveJob(runtimeLease, `download:${match[1]}`, true)).catch((error2) => {
|
|
27599
27902
|
process.stderr.write(`[zlt-mcp-proxy] runtime download lease update failed: ${error2 instanceof Error ? error2.message : String(error2)}
|
|
@@ -27609,9 +27912,9 @@ async function startMcpServer() {
|
|
|
27609
27912
|
};
|
|
27610
27913
|
const clearCompletedDownload = (requestedId, result) => {
|
|
27611
27914
|
if (!runtimeLease) return;
|
|
27612
|
-
const
|
|
27613
|
-
if (!/"terminal"\s*:\s*true|TASK_STATUS_(?:DONE|FAILED|PAUSED|STOPPED|CANCELLED)/i.test(
|
|
27614
|
-
const uuid2 =
|
|
27915
|
+
const text2 = result.content?.map((item) => item.type === "text" ? item.text : "").join("\n") ?? "";
|
|
27916
|
+
if (!/"terminal"\s*:\s*true|TASK_STATUS_(?:DONE|FAILED|PAUSED|STOPPED|CANCELLED)/i.test(text2)) return;
|
|
27917
|
+
const uuid2 = text2.match(/"uuid"\s*:\s*"([^"]+)"/)?.[1] ?? requestedId;
|
|
27615
27918
|
if (!uuid2 || uuid2 === "0") return;
|
|
27616
27919
|
leaseStateUpdate = leaseStateUpdate.then(() => updateRuntimeLeaseActiveJob(runtimeLease, `download:${uuid2}`, false)).catch((error2) => {
|
|
27617
27920
|
process.stderr.write(`[zlt-mcp-proxy] runtime download lease cleanup failed: ${error2 instanceof Error ? error2.message : String(error2)}
|
|
@@ -27622,13 +27925,13 @@ async function startMcpServer() {
|
|
|
27622
27925
|
let entry = clients.get(pipePath);
|
|
27623
27926
|
const isInitialConnection = !entry;
|
|
27624
27927
|
if (!entry) {
|
|
27625
|
-
const
|
|
27626
|
-
|
|
27928
|
+
const client2 = new ZltafIpcClient();
|
|
27929
|
+
client2.onDisconnect = () => {
|
|
27627
27930
|
const action = reconnectEnabled ? "\u4E0B\u6B21\u8C03\u7528\u65F6\u5C06\u81EA\u52A8\u91CD\u8FDE" : "\u81EA\u52A8\u91CD\u8FDE\u5DF2\u7981\u7528";
|
|
27628
27931
|
process.stderr.write(`[zlt-mcp-proxy] IPC \u670D\u52A1\u7AEF\u5DF2\u65AD\u5F00\u8FDE\u63A5 (${pipePath})\uFF0C${action}
|
|
27629
27932
|
`);
|
|
27630
27933
|
};
|
|
27631
|
-
entry = { client, reconnecting: null };
|
|
27934
|
+
entry = { client: client2, reconnecting: null };
|
|
27632
27935
|
clients.set(pipePath, entry);
|
|
27633
27936
|
}
|
|
27634
27937
|
if (entry.client.isConnected()) return entry.client;
|
|
@@ -27727,10 +28030,10 @@ async function startMcpServer() {
|
|
|
27727
28030
|
runRuntimeDoctor,
|
|
27728
28031
|
async (workRoot, timeoutMs) => {
|
|
27729
28032
|
const pipe2 = discoverInstallPipePath(workRoot, process.env.ZLT_PIPE_NAME?.trim() || config2.zltconfig.pipName);
|
|
27730
|
-
const
|
|
27731
|
-
if (!
|
|
28033
|
+
const client2 = await ensureConnected(pipe2);
|
|
28034
|
+
if (!client2) throw new Error("cache readiness pipe unavailable");
|
|
27732
28035
|
return waitForCacheRead(async (probeTimeoutMs) => {
|
|
27733
|
-
const response = await
|
|
28036
|
+
const response = await client2.invoke("/zltaf_slave/forward_ipc/zltdcm/diskspace", {}, "{}", probeTimeoutMs);
|
|
27734
28037
|
const parsed = parseIpcRawResponse(response);
|
|
27735
28038
|
if (!parsed.isSuccess) throw new Error(parsed.errorText);
|
|
27736
28039
|
return parsed.data;
|
|
@@ -27831,9 +28134,9 @@ async function startMcpServer() {
|
|
|
27831
28134
|
if (shutdownPromise) return shutdownPromise;
|
|
27832
28135
|
shutdownPromise = (async () => {
|
|
27833
28136
|
process.stderr.write("[zlt-mcp-proxy] \u6B63\u5728\u5173\u95ED\uFF0C\u65AD\u5F00\u6240\u6709 IPC \u8FDE\u63A5...\n");
|
|
27834
|
-
for (const { client } of clients.values()) {
|
|
28137
|
+
for (const { client: client2 } of clients.values()) {
|
|
27835
28138
|
try {
|
|
27836
|
-
await
|
|
28139
|
+
await client2.disconnect();
|
|
27837
28140
|
} catch {
|
|
27838
28141
|
}
|
|
27839
28142
|
}
|
|
@@ -28330,7 +28633,7 @@ async function prepareRuntimeForIpc(options) {
|
|
|
28330
28633
|
function buildRuntimeFallbackRoots(configuredRoot) {
|
|
28331
28634
|
const roots = [configuredRoot, getDefaultInstallPath()];
|
|
28332
28635
|
if (process.platform === "win32") roots.push("C:\\ZLTClient", "D:\\ZLTClient");
|
|
28333
|
-
return [...new Set(roots.map((
|
|
28636
|
+
return [...new Set(roots.map((root2) => root2.trim()).filter(Boolean))];
|
|
28334
28637
|
}
|
|
28335
28638
|
function barePipeName(value) {
|
|
28336
28639
|
const windowsPrefix = "\\\\.\\pipe\\";
|
|
@@ -28356,7 +28659,7 @@ function syncCredentialsFromEnvAtStartup() {
|
|
|
28356
28659
|
function inspectDoctorAuth() {
|
|
28357
28660
|
try {
|
|
28358
28661
|
const auth = getAuthStatus();
|
|
28359
|
-
const invalidFile = !auth.configured &&
|
|
28662
|
+
const invalidFile = !auth.configured && fs17.existsSync(auth.credentialsPath);
|
|
28360
28663
|
return {
|
|
28361
28664
|
configured: auth.configured,
|
|
28362
28665
|
status: auth.configured ? "configured" : invalidFile ? "invalid-config" : "missing",
|
|
@@ -28476,6 +28779,163 @@ function runtimeRecoveryStopData(message, extra = {}, handler = "runtimeStart")
|
|
|
28476
28779
|
};
|
|
28477
28780
|
}
|
|
28478
28781
|
|
|
28782
|
+
// src/auth-cli.ts
|
|
28783
|
+
var fs18 = __toESM(require("node:fs"), 1);
|
|
28784
|
+
var path17 = __toESM(require("node:path"), 1);
|
|
28785
|
+
var import_node_crypto4 = require("node:crypto");
|
|
28786
|
+
var SOURCE = "zlt-mcp-device-login";
|
|
28787
|
+
var client = {
|
|
28788
|
+
start: () => startDeviceAuthorization(),
|
|
28789
|
+
poll: (s, o) => pollDeviceAuthorization(s, o),
|
|
28790
|
+
persist: (grant, env) => persistDeviceAuthorization(grant, env)
|
|
28791
|
+
};
|
|
28792
|
+
function escapeWidgetHtml(v) {
|
|
28793
|
+
return v.replace(
|
|
28794
|
+
/[&<>"']/g,
|
|
28795
|
+
(c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]
|
|
28796
|
+
);
|
|
28797
|
+
}
|
|
28798
|
+
function buildShowWidgetPayload(s) {
|
|
28799
|
+
if (!validSession(s)) throw new Error("Invalid authentication session");
|
|
28800
|
+
return {
|
|
28801
|
+
name: "show_widget",
|
|
28802
|
+
arguments: {
|
|
28803
|
+
title: "ZLT Quant sign in",
|
|
28804
|
+
widget_code: `<section style="font: 14px/1.6 var(--font-sans, sans-serif); padding: 16px; border: 1px solid var(--color-border-secondary, #ddd); border-radius: 12px"><h2 style="font-size: 16px; margin: 0 0 12px">\u767B\u5F55\u667A\u91CF\u901A</h2><p>\u5728\u667A\u91CF\u901A\u7F51\u5173\u767B\u5F55\uFF0C\u5E76\u6838\u5BF9\u6B64\u8BBE\u5907\u7801\uFF1A</p><p style="font: 24px var(--font-mono, monospace); letter-spacing: 3px">${escapeWidgetHtml(s.userCode)}</p><p><a target="_blank" rel="noopener noreferrer" href="${escapeWidgetHtml(s.verificationUriComplete)}">\u6253\u5F00\u767B\u5F55\u9875\u9762</a></p><p style="font-size: 12px">${escapeWidgetHtml(s.verificationUri)} \xB7 \u8BBE\u5907\u7801 ${Math.ceil(s.expiresIn / 60)} \u5206\u949F\u5185\u6709\u6548\u3002\u767B\u5F55\u5B8C\u6210\u540E\u8BF7\u8FD4\u56DE\u6B64\u5BF9\u8BDD\u3002</p></section>`,
|
|
28805
|
+
loading_messages: JSON.stringify(["\u51C6\u5907\u767B\u5F55\u5361\u7247"])
|
|
28806
|
+
}
|
|
28807
|
+
};
|
|
28808
|
+
}
|
|
28809
|
+
var root = (e = process.env) => path17.join(resolveZltQuantHome(e), "device-auth-sessions");
|
|
28810
|
+
function saveDeviceSession(s, e = process.env) {
|
|
28811
|
+
if (!validSession(s)) throw new Error("Invalid authentication session");
|
|
28812
|
+
const id = (0, import_node_crypto4.randomUUID)();
|
|
28813
|
+
fs18.mkdirSync(root(e), { recursive: true, mode: 448 });
|
|
28814
|
+
protectPrivatePath(root(e), true);
|
|
28815
|
+
fs18.writeFileSync(
|
|
28816
|
+
path17.join(root(e), id + ".json"),
|
|
28817
|
+
JSON.stringify({ authorization: s, expiresAt: s.issuedAt + s.expiresIn * 1e3 }),
|
|
28818
|
+
{ mode: 384, flag: "wx" }
|
|
28819
|
+
);
|
|
28820
|
+
return id;
|
|
28821
|
+
}
|
|
28822
|
+
function load(id, e = process.env) {
|
|
28823
|
+
sessionPath(id, e);
|
|
28824
|
+
try {
|
|
28825
|
+
if (fs18.lstatSync(root(e)).isSymbolicLink()) throw Error();
|
|
28826
|
+
const file = sessionPath(id, e);
|
|
28827
|
+
const stat = fs18.lstatSync(file);
|
|
28828
|
+
if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 8192) throw Error();
|
|
28829
|
+
const saved = JSON.parse(fs18.readFileSync(file, "utf8"));
|
|
28830
|
+
if (!saved || typeof saved !== "object" || !("authorization" in saved) || !validSession(saved.authorization)) throw Error();
|
|
28831
|
+
return { authorization: saved.authorization };
|
|
28832
|
+
} catch {
|
|
28833
|
+
drop(id, e);
|
|
28834
|
+
throw Error("Authentication session is missing or invalid; start login again");
|
|
28835
|
+
}
|
|
28836
|
+
}
|
|
28837
|
+
function authErrorMessage(error2) {
|
|
28838
|
+
if (error2 instanceof DeviceAuthorizationError) return `Device login failed (${error2.code})`;
|
|
28839
|
+
const safe = [
|
|
28840
|
+
"Invalid authentication session",
|
|
28841
|
+
"Authentication session is missing or invalid; start login again",
|
|
28842
|
+
"Authentication session is unavailable or already being waited on",
|
|
28843
|
+
"Authentication is already configured",
|
|
28844
|
+
"Sign in completed but credential is not effective",
|
|
28845
|
+
"Could not protect private authentication storage"
|
|
28846
|
+
];
|
|
28847
|
+
if (error2 instanceof Error && safe.includes(error2.message)) return error2.message;
|
|
28848
|
+
return "Authentication operation failed; check local credential configuration and storage permissions. No credential was returned.";
|
|
28849
|
+
}
|
|
28850
|
+
function sessionPath(id, e = process.env) {
|
|
28851
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(id)) throw Error("Invalid authentication session");
|
|
28852
|
+
return path17.join(root(e), id + ".json");
|
|
28853
|
+
}
|
|
28854
|
+
function drop(id, e = process.env) {
|
|
28855
|
+
fs18.rmSync(sessionPath(id, e), { force: true });
|
|
28856
|
+
}
|
|
28857
|
+
function preflight(e) {
|
|
28858
|
+
if (e.ZLTQUANT_CREDENTIALS || e.ZLTQUANT_API_KEY || readCredentials(e))
|
|
28859
|
+
throw Error("Authentication is already configured");
|
|
28860
|
+
}
|
|
28861
|
+
async function finish(s, e, c, json) {
|
|
28862
|
+
const grant = await c.poll(s, {
|
|
28863
|
+
maxDurationMs: s.expiresIn * 1e3
|
|
28864
|
+
});
|
|
28865
|
+
const receipt = c.persist(grant, e);
|
|
28866
|
+
if (receipt.status !== "success" || !receipt.authStatus.configured || receipt.authStatus.source !== "file")
|
|
28867
|
+
throw Error("Sign in completed but credential is not effective");
|
|
28868
|
+
const a = receipt.authStatus;
|
|
28869
|
+
const o = {
|
|
28870
|
+
status: "success",
|
|
28871
|
+
configured: true,
|
|
28872
|
+
source: a.source,
|
|
28873
|
+
apiKeyMask: a.apiKeyMask,
|
|
28874
|
+
apiBase: a.apiBase
|
|
28875
|
+
};
|
|
28876
|
+
process.stdout.write(json ? JSON.stringify(o) + "\n" : `Signed in (${a.apiKeyMask}).
|
|
28877
|
+
`);
|
|
28878
|
+
return o;
|
|
28879
|
+
}
|
|
28880
|
+
async function runAuthLogin(o = {}) {
|
|
28881
|
+
const e = o.env || process.env;
|
|
28882
|
+
preflight(e);
|
|
28883
|
+
const c = o.client || client, s = await c.start();
|
|
28884
|
+
if (o.widget) {
|
|
28885
|
+
const out = {
|
|
28886
|
+
status: "pending",
|
|
28887
|
+
session: saveDeviceSession(s, e),
|
|
28888
|
+
verificationUri: s.verificationUri,
|
|
28889
|
+
verificationUriComplete: s.verificationUriComplete,
|
|
28890
|
+
userCode: s.userCode,
|
|
28891
|
+
expiresIn: s.expiresIn,
|
|
28892
|
+
widget: buildShowWidgetPayload(s)
|
|
28893
|
+
};
|
|
28894
|
+
process.stdout.write(JSON.stringify(out) + "\n");
|
|
28895
|
+
return out;
|
|
28896
|
+
}
|
|
28897
|
+
process.stdout.write(
|
|
28898
|
+
o.json ? JSON.stringify({
|
|
28899
|
+
status: "pending",
|
|
28900
|
+
verificationUri: s.verificationUri,
|
|
28901
|
+
userCode: s.userCode
|
|
28902
|
+
}) + "\n" : `Open ${s.verificationUri} and enter code ${s.userCode}.
|
|
28903
|
+
`
|
|
28904
|
+
);
|
|
28905
|
+
return finish(s, e, c, o.json);
|
|
28906
|
+
}
|
|
28907
|
+
async function runAuthWait(id, o = {}) {
|
|
28908
|
+
const e = o.env || process.env;
|
|
28909
|
+
preflight(e);
|
|
28910
|
+
const lockPath = sessionPath(id, e) + ".lock";
|
|
28911
|
+
let lock;
|
|
28912
|
+
try {
|
|
28913
|
+
lock = fs18.openSync(lockPath, "wx", 384);
|
|
28914
|
+
} catch {
|
|
28915
|
+
throw Error("Authentication session is unavailable or already being waited on");
|
|
28916
|
+
}
|
|
28917
|
+
try {
|
|
28918
|
+
const x = load(id, e);
|
|
28919
|
+
const result = await finish(x.authorization, e, o.client || client, o.json);
|
|
28920
|
+
drop(id, e);
|
|
28921
|
+
return result;
|
|
28922
|
+
} catch (error2) {
|
|
28923
|
+
if (error2 instanceof DeviceAuthorizationError && ["expired_token", "access_denied"].includes(error2.code)) drop(id, e);
|
|
28924
|
+
throw error2;
|
|
28925
|
+
} finally {
|
|
28926
|
+
fs18.closeSync(lock);
|
|
28927
|
+
fs18.rmSync(lockPath, { force: true });
|
|
28928
|
+
}
|
|
28929
|
+
}
|
|
28930
|
+
var authStatus = (e = process.env) => getAuthStatus(e);
|
|
28931
|
+
function authLogout(e = process.env) {
|
|
28932
|
+
if (e.ZLTQUANT_CREDENTIALS || e.ZLTQUANT_API_KEY)
|
|
28933
|
+
return { removed: false, status: getAuthStatus(e) };
|
|
28934
|
+
const c = readCredentials(e);
|
|
28935
|
+
const removed = !!c && c.source === SOURCE && removeCredentials({ apiKey: c.apiKey, source: SOURCE }, e);
|
|
28936
|
+
return { removed, status: getAuthStatus(e) };
|
|
28937
|
+
}
|
|
28938
|
+
|
|
28479
28939
|
// src/index.ts
|
|
28480
28940
|
var CLI_NAME = "zlt-mcp";
|
|
28481
28941
|
var CLI_FALLBACK_PACKAGE_NAME = "@zltquant/zlt-mcp";
|
|
@@ -28516,6 +28976,50 @@ if (process.argv.length <= 2) {
|
|
|
28516
28976
|
}));
|
|
28517
28977
|
});
|
|
28518
28978
|
program2.name(CLI_NAME).description("MCP proxy for ZLTHost IPC service").version(resolveCliVersion()).configureOutput({ outputError: writeCliArgumentError }).addHelpText("after", "\nDiscovery: list for names; list --tool <name> --json for one complete input schema.\nUse call --help for input, output and diagnostic handling.\nFor npx registry selection, put --registry before the package name; it is not a zlt-mcp option.");
|
|
28979
|
+
const auth = program2.command("auth").description("Manage local ZLT Quant authentication");
|
|
28980
|
+
auth.command("login").description("Sign in with a device code").option("--json", "Emit a JSON descriptor and status").option("--widget", "Return a login card immediately; render it before running auth wait").addHelpText("after", "\nAgent flow: auth login --widget --json returns a local session ID and widget descriptor.\nInvoke the host show_widget tool with widget.arguments, or show the login URL/code.\nThen run auth wait --session <returned-id> --json. The descriptor alone does not render a widget.\nWithout --widget this command waits in the foreground. Never paste keys or private session files into chat.").action(async (options) => {
|
|
28981
|
+
try {
|
|
28982
|
+
await runAuthLogin(options);
|
|
28983
|
+
} catch (error2) {
|
|
28984
|
+
process.stderr.write(`Error: ${authErrorMessage(error2)}
|
|
28985
|
+
`);
|
|
28986
|
+
process.exitCode = 1;
|
|
28987
|
+
}
|
|
28988
|
+
});
|
|
28989
|
+
auth.command("status").description("Show masked local authentication status").option("--json", "Emit JSON").action((options) => {
|
|
28990
|
+
try {
|
|
28991
|
+
const status = authStatus();
|
|
28992
|
+
process.stdout.write(options.json ? `${JSON.stringify(status)}
|
|
28993
|
+
` : `${status.configured ? `Configured (${status.apiKeyMask})` : "Not configured"}
|
|
28994
|
+
`);
|
|
28995
|
+
} catch (error2) {
|
|
28996
|
+
process.stderr.write(`Error: ${authErrorMessage(error2)}
|
|
28997
|
+
`);
|
|
28998
|
+
process.exitCode = 1;
|
|
28999
|
+
}
|
|
29000
|
+
});
|
|
29001
|
+
auth.command("wait").description("Complete a saved device-code sign in").requiredOption("--session <id>", "Opaque local session ID from auth login --widget").option("--json", "Emit JSON").action(async (options) => {
|
|
29002
|
+
try {
|
|
29003
|
+
await runAuthWait(options.session, options);
|
|
29004
|
+
} catch (error2) {
|
|
29005
|
+
process.stderr.write(`Error: ${authErrorMessage(error2)}
|
|
29006
|
+
`);
|
|
29007
|
+
process.exitCode = 1;
|
|
29008
|
+
}
|
|
29009
|
+
});
|
|
29010
|
+
auth.command("logout").description("Remove only CLI-login-owned credentials locally; does not revoke the gateway key").option("--json", "Emit JSON").action((options) => {
|
|
29011
|
+
try {
|
|
29012
|
+
const result = authLogout();
|
|
29013
|
+
const output = { removed: result.removed, configured: result.status.configured, source: result.status.source, apiKeyMask: result.status.apiKeyMask };
|
|
29014
|
+
process.stdout.write(options.json ? `${JSON.stringify(output)}
|
|
29015
|
+
` : `${result.removed ? "Signed out locally." : "No removable credentials found."}
|
|
29016
|
+
`);
|
|
29017
|
+
} catch (error2) {
|
|
29018
|
+
process.stderr.write(`Error: ${authErrorMessage(error2)}
|
|
29019
|
+
`);
|
|
29020
|
+
process.exitCode = 1;
|
|
29021
|
+
}
|
|
29022
|
+
});
|
|
28519
29023
|
program2.command("call <tool>").description("Call any MCP tool through the bundled MCP server").configureOutput({ outputError: writeCliArgumentError }).option("--args-json <json>", "JSON object containing tool arguments").option("--args-file <path>", "Read the JSON argument object from a file").option("--output-json <path>", "Save the complete result to a new JSON file and print a compact receipt").option("--evidence-dir <path>", "Create a new directory for the result, diagnostics and execution status").option("--verify-download", "For mcp-download-data: wait once and collect verification evidence").option("--timeout-ms <ms>", "MCP request inactivity timeout in milliseconds").option("--max-total-timeout-ms <ms>", "Optional hard upper bound for the call, including install/backtest wait").option("--no-progress", "Suppress progress diagnostics on stderr").addHelpText("after", COMMON_CALL_HELP).action(async (tool, options) => {
|
|
28520
29024
|
let outputFd;
|
|
28521
29025
|
let stage = "arguments";
|
|
@@ -28529,9 +29033,9 @@ if (process.argv.length <= 2) {
|
|
|
28529
29033
|
const args = parseMcpArgs(options.argsJson, options.argsFile);
|
|
28530
29034
|
const timeoutMs = parseTimeoutOption(options.timeoutMs, "--timeout-ms");
|
|
28531
29035
|
const maxTotalTimeoutMs = parseTimeoutOption(options.maxTotalTimeoutMs, "--max-total-timeout-ms");
|
|
28532
|
-
const resultFile = evidence?.resultFile ?? (options.outputJson === void 0 ? void 0 :
|
|
29036
|
+
const resultFile = evidence?.resultFile ?? (options.outputJson === void 0 ? void 0 : path18.resolve(options.outputJson));
|
|
28533
29037
|
stage = "output_prepare";
|
|
28534
|
-
if (resultFile !== void 0) outputFd =
|
|
29038
|
+
if (resultFile !== void 0) outputFd = fs19.openSync(resultFile, "wx");
|
|
28535
29039
|
stage = "tool_call";
|
|
28536
29040
|
evidence?.started(tool);
|
|
28537
29041
|
toolExecution = "unknown";
|
|
@@ -28551,10 +29055,10 @@ if (process.argv.length <= 2) {
|
|
|
28551
29055
|
if (outputFd !== void 0 && resultFile !== void 0) {
|
|
28552
29056
|
stage = "output_write";
|
|
28553
29057
|
try {
|
|
28554
|
-
|
|
29058
|
+
fs19.writeFileSync(outputFd, serialized, "utf-8");
|
|
28555
29059
|
const fd = outputFd;
|
|
28556
29060
|
outputFd = void 0;
|
|
28557
|
-
|
|
29061
|
+
fs19.closeSync(fd);
|
|
28558
29062
|
} catch (error2) {
|
|
28559
29063
|
process.stdout.write(serialized);
|
|
28560
29064
|
throw new Error(`Tool returned a result, but saving ${resultFile} failed; complete result is on stdout. Do not repeat the tool automatically. ${String(error2)}`);
|
|
@@ -28597,7 +29101,7 @@ if (process.argv.length <= 2) {
|
|
|
28597
29101
|
const fd = outputFd;
|
|
28598
29102
|
outputFd = void 0;
|
|
28599
29103
|
try {
|
|
28600
|
-
|
|
29104
|
+
fs19.closeSync(fd);
|
|
28601
29105
|
} catch (error2) {
|
|
28602
29106
|
process.exitCode = 1;
|
|
28603
29107
|
process.stderr.write(`Error: result file close failed; toolExecution=${toolExecution}; ${String(error2)}
|
|
@@ -28628,7 +29132,7 @@ if (process.argv.length <= 2) {
|
|
|
28628
29132
|
const complete = withCliProvenance(result);
|
|
28629
29133
|
const serialized = JSON.stringify(complete) + "\n";
|
|
28630
29134
|
try {
|
|
28631
|
-
|
|
29135
|
+
fs19.writeFileSync(evidence.resultFile, serialized, { encoding: "utf8", flag: "wx" });
|
|
28632
29136
|
evidence.completed("not_reported", 0);
|
|
28633
29137
|
} catch (error2) {
|
|
28634
29138
|
process.stdout.write(serialized);
|
|
@@ -28756,17 +29260,17 @@ function resolveCliVersion() {
|
|
|
28756
29260
|
return resolveCliPackageProvenance().packageVersion;
|
|
28757
29261
|
}
|
|
28758
29262
|
function resolveCliPackageProvenance() {
|
|
28759
|
-
let current =
|
|
29263
|
+
let current = path18.dirname(path18.resolve(process.argv[1] || process.cwd()));
|
|
28760
29264
|
for (let depth = 0; depth < 6; depth += 1) {
|
|
28761
|
-
const manifestPath =
|
|
29265
|
+
const manifestPath = path18.join(current, "package.json");
|
|
28762
29266
|
try {
|
|
28763
|
-
const manifest = JSON.parse(
|
|
29267
|
+
const manifest = JSON.parse(fs19.readFileSync(manifestPath, "utf-8"));
|
|
28764
29268
|
if ((manifest.name === "@zltquant/zlt-mcp" || manifest.name === "zlt-mcp-proxy") && typeof manifest.version === "string") {
|
|
28765
29269
|
return { packageName: manifest.name, packageVersion: manifest.version };
|
|
28766
29270
|
}
|
|
28767
29271
|
} catch {
|
|
28768
29272
|
}
|
|
28769
|
-
const parent =
|
|
29273
|
+
const parent = path18.dirname(current);
|
|
28770
29274
|
if (parent === current) break;
|
|
28771
29275
|
current = parent;
|
|
28772
29276
|
}
|