@tradejs/cli 3.0.1 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/cli.js +3707 -2983
- package/dist/lib/aiPocketSearch.js +10 -0
- package/dist/lib/aiTrainResearch.js +24 -15
- package/dist/lib/coreResearch.js +52 -20
- package/dist/lib/researchAgent.js +16 -2
- package/dist/lib/researchRoots.js +59 -0
- package/dist/lib/runtimeLineage.js +43 -19
- package/dist/lib/runtimeModeConfig.js +1 -1
- package/dist/lib/runtimeSignalsStorage.js +2 -1
- package/dist/lib/strategyGateFingerprint.js +26 -15
- package/dist/lib/strategyRelease.js +266 -253
- package/dist/scripts/agentRun.js +83 -52
- package/dist/scripts/aiPocketSearch.js +2269 -1972
- package/dist/scripts/aiTrain.js +24 -15
- package/dist/scripts/coreResearch.js +91 -30
- package/dist/scripts/replay.js +69 -27
- package/dist/scripts/replayRunner.js +69 -27
- package/dist/scripts/researchAuto.js +34 -13
- package/dist/scripts/runtimeConfig.js +290 -0
- package/dist/scripts/runtimeEvidence.js +2 -1
- package/dist/scripts/runtimeParity.js +1 -1
- package/dist/scripts/runtimeScorecard.js +108 -103
- package/dist/scripts/signals.js +162 -224
- package/dist/scripts/signalsDaemon.js +162 -224
- package/dist/scripts/strategyRelease.js +222 -209
- package/dist/scripts/test-ml.js +8 -2
- package/package.json +13 -10
|
@@ -32,6 +32,8 @@ __export(aiPocketSearch_exports, {
|
|
|
32
32
|
summarizeAiPocketRows: () => summarizeAiPocketRows
|
|
33
33
|
});
|
|
34
34
|
module.exports = __toCommonJS(aiPocketSearch_exports);
|
|
35
|
+
|
|
36
|
+
// src/lib/aiPocketSearch/features.ts
|
|
35
37
|
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
36
38
|
var DAYS_PER_WEEK = 7;
|
|
37
39
|
var DAYS_PER_MONTH = 30.4375;
|
|
@@ -674,6 +676,8 @@ var collectAiPocketFeatureSnapshot = ({
|
|
|
674
676
|
return { features, featureCoverage };
|
|
675
677
|
};
|
|
676
678
|
var collectAiPocketFeatures = (options) => collectAiPocketFeatureSnapshot(options).features;
|
|
679
|
+
|
|
680
|
+
// src/lib/aiPocketSearch/summary.ts
|
|
677
681
|
var formatNumber = (value) => {
|
|
678
682
|
if (Number.isInteger(value)) {
|
|
679
683
|
return String(value);
|
|
@@ -970,6 +974,8 @@ var summarizeAiPocketFeatureCoverage = (rows, family) => {
|
|
|
970
974
|
maxTimestamp
|
|
971
975
|
};
|
|
972
976
|
};
|
|
977
|
+
|
|
978
|
+
// src/lib/aiPocketSearch/predicates.ts
|
|
973
979
|
var matchesPredicate = (value, predicate) => {
|
|
974
980
|
if (predicate.kind === "numeric") {
|
|
975
981
|
if (!isFiniteNumber(value)) {
|
|
@@ -1218,6 +1224,8 @@ var buildAiPocketPredicateResult = (rows, options = {}) => {
|
|
|
1218
1224
|
return { featureKeys: buckets.size, predicates };
|
|
1219
1225
|
};
|
|
1220
1226
|
var buildAiPocketPredicates = (rows, options = {}) => buildAiPocketPredicateResult(rows, options).predicates.map(toPublicPredicate);
|
|
1227
|
+
|
|
1228
|
+
// src/lib/aiPocketSearch/searchEngine.ts
|
|
1221
1229
|
var scorePositivePocket = (summary) => {
|
|
1222
1230
|
const profitFactor = summary.profitFactor ?? (summary.grossLoss === 0 ? 8 : 0);
|
|
1223
1231
|
const winRate = summary.winRate ?? 0;
|
|
@@ -1796,6 +1804,8 @@ var searchAiPockets = (rows, options = {}) => {
|
|
|
1796
1804
|
}
|
|
1797
1805
|
};
|
|
1798
1806
|
};
|
|
1807
|
+
|
|
1808
|
+
// src/lib/aiPocketSearch/markdownReport.ts
|
|
1799
1809
|
var formatMdNumber = (value, digits = 2) => value == null || !Number.isFinite(value) ? "n/a" : value.toFixed(digits);
|
|
1800
1810
|
var formatMdPercent = (value) => value == null || !Number.isFinite(value) ? "n/a" : `${(value * 100).toFixed(1)}%`;
|
|
1801
1811
|
var escapeMarkdownCell = (value) => String(value ?? "n/a").replace(/\|/g, "\\|").replace(/\n/g, "<br>");
|
|
@@ -346,28 +346,37 @@ var import_types = require("@tradejs/types");
|
|
|
346
346
|
|
|
347
347
|
// src/lib/strategyGateFingerprint.ts
|
|
348
348
|
var import_node_crypto = require("crypto");
|
|
349
|
+
var import_node_module = require("module");
|
|
349
350
|
var import_promises = __toESM(require("fs/promises"));
|
|
350
351
|
var import_node_path = __toESM(require("path"));
|
|
351
|
-
var
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
"
|
|
357
|
-
"
|
|
358
|
-
"packages/core/src/utils/strategyHelpers/signalBuilders.ts"
|
|
352
|
+
var toPackageToken = (strategyName) => strategyName.replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").replace(/([a-z\d])([A-Z])/g, "$1-$2").toLowerCase();
|
|
353
|
+
var getStrategyPackageName = (strategyName) => strategyName === "TrendLine" || strategyName === "ReverseTrendLine" ? "@tradejs/strategy-trend-line" : `@tradejs/strategy-${toPackageToken(strategyName)}`;
|
|
354
|
+
var gateFingerprintSpecifiers = (strategyName) => [
|
|
355
|
+
getStrategyPackageName(strategyName),
|
|
356
|
+
"@tradejs/strategy-kit/ai-gate",
|
|
357
|
+
"@tradejs/node/ai",
|
|
358
|
+
"@tradejs/core/strategies"
|
|
359
359
|
];
|
|
360
360
|
var resolveStrategyGateFingerprint = async ({
|
|
361
361
|
projectRoot,
|
|
362
362
|
strategyName,
|
|
363
363
|
gitSha
|
|
364
364
|
}) => {
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
365
|
+
const projectManifestPath = import_node_path.default.join(projectRoot, "package.json");
|
|
366
|
+
const projectExists = await import_promises.default.access(projectManifestPath).then(() => true).catch(() => false);
|
|
367
|
+
const requireFromProject = projectExists ? (0, import_node_module.createRequire)(projectManifestPath) : null;
|
|
368
|
+
const candidates = requireFromProject ? await Promise.all(
|
|
369
|
+
gateFingerprintSpecifiers(strategyName).map(async (specifier) => {
|
|
370
|
+
let resolvedPath;
|
|
371
|
+
try {
|
|
372
|
+
resolvedPath = requireFromProject.resolve(specifier);
|
|
373
|
+
} catch {
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
const content = await import_promises.default.readFile(resolvedPath).catch(() => null);
|
|
377
|
+
return content == null ? null : { specifier, content };
|
|
369
378
|
})
|
|
370
|
-
);
|
|
379
|
+
) : [];
|
|
371
380
|
const sourceEntries = candidates.filter(
|
|
372
381
|
(entry) => entry != null
|
|
373
382
|
);
|
|
@@ -375,7 +384,7 @@ var resolveStrategyGateFingerprint = async ({
|
|
|
375
384
|
hash.update(strategyName);
|
|
376
385
|
if (sourceEntries.length) {
|
|
377
386
|
for (const entry of sourceEntries) {
|
|
378
|
-
hash.update(entry.
|
|
387
|
+
hash.update(entry.specifier);
|
|
379
388
|
hash.update(entry.content);
|
|
380
389
|
}
|
|
381
390
|
} else {
|
|
@@ -383,7 +392,7 @@ var resolveStrategyGateFingerprint = async ({
|
|
|
383
392
|
}
|
|
384
393
|
return {
|
|
385
394
|
gateFingerprint: hash.digest("hex").slice(0, 16),
|
|
386
|
-
gateFingerprintFiles: sourceEntries.map((entry) => entry.
|
|
395
|
+
gateFingerprintFiles: sourceEntries.map((entry) => entry.specifier)
|
|
387
396
|
};
|
|
388
397
|
};
|
|
389
398
|
|
package/dist/lib/coreResearch.js
CHANGED
|
@@ -46,7 +46,7 @@ module.exports = __toCommonJS(coreResearch_exports);
|
|
|
46
46
|
|
|
47
47
|
// src/lib/coreResearch/orchestrator.ts
|
|
48
48
|
var import_promises4 = __toESM(require("fs/promises"));
|
|
49
|
-
var
|
|
49
|
+
var import_node_path6 = __toESM(require("path"));
|
|
50
50
|
var import_node_child_process = require("child_process");
|
|
51
51
|
var import_node_crypto5 = require("crypto");
|
|
52
52
|
var import_coreResearch = require("@tradejs/infra/coreResearch");
|
|
@@ -2116,6 +2116,10 @@ var summarizeCoreResearchTrace = async (filePaths = []) => {
|
|
|
2116
2116
|
};
|
|
2117
2117
|
};
|
|
2118
2118
|
|
|
2119
|
+
// src/lib/researchRoots.ts
|
|
2120
|
+
var import_node_path5 = __toESM(require("path"));
|
|
2121
|
+
var SOURCE_REPOSITORY_ROOT_ENV = "TRADEJS_SOURCE_REPOSITORY_ROOT";
|
|
2122
|
+
|
|
2119
2123
|
// src/lib/coreResearch/orchestrator.ts
|
|
2120
2124
|
var summarizeSupplementalFiles = async (params) => {
|
|
2121
2125
|
const loaded = await readCoreResearchVariant({
|
|
@@ -2308,7 +2312,7 @@ var analyzeCoreResearchPrepared = async (spec, options = {}) => {
|
|
|
2308
2312
|
const primarySourceHashes = Object.fromEntries(
|
|
2309
2313
|
analyses.flatMap(
|
|
2310
2314
|
(analysis) => analysis.files.map((file) => [
|
|
2311
|
-
|
|
2315
|
+
import_node_path6.default.relative(paths.researchDir, file.path),
|
|
2312
2316
|
file.sha256
|
|
2313
2317
|
])
|
|
2314
2318
|
)
|
|
@@ -2327,8 +2331,8 @@ var analyzeCoreResearchPrepared = async (spec, options = {}) => {
|
|
|
2327
2331
|
const supplementalSourceHashes = Object.fromEntries(
|
|
2328
2332
|
await Promise.all(
|
|
2329
2333
|
supplementalSourcePaths.map(async (filePath) => [
|
|
2330
|
-
|
|
2331
|
-
await sha256File(
|
|
2334
|
+
import_node_path6.default.relative(paths.researchDir, import_node_path6.default.resolve(filePath)),
|
|
2335
|
+
await sha256File(import_node_path6.default.resolve(filePath))
|
|
2332
2336
|
])
|
|
2333
2337
|
)
|
|
2334
2338
|
);
|
|
@@ -2405,7 +2409,7 @@ var analyzeCoreResearchPrepared = async (spec, options = {}) => {
|
|
|
2405
2409
|
"trades.jsonl": await sha256File(paths.tradesPath),
|
|
2406
2410
|
"report.html": await sha256File(paths.reportPath)
|
|
2407
2411
|
};
|
|
2408
|
-
const resolvedRunsPath =
|
|
2412
|
+
const resolvedRunsPath = import_node_path6.default.join(paths.researchDir, "resolved-runs.json");
|
|
2409
2413
|
try {
|
|
2410
2414
|
artifactHashes["resolved-runs.json"] = await sha256File(resolvedRunsPath);
|
|
2411
2415
|
} catch (error) {
|
|
@@ -2415,7 +2419,7 @@ var analyzeCoreResearchPrepared = async (spec, options = {}) => {
|
|
|
2415
2419
|
for (const name of await import_promises4.default.readdir(paths.runLogDir)) {
|
|
2416
2420
|
if (!name.endsWith(".log")) continue;
|
|
2417
2421
|
artifactHashes[`runs/${name}`] = await sha256File(
|
|
2418
|
-
|
|
2422
|
+
import_node_path6.default.join(paths.runLogDir, name)
|
|
2419
2423
|
);
|
|
2420
2424
|
}
|
|
2421
2425
|
} catch (error) {
|
|
@@ -2472,12 +2476,14 @@ var analyzeCoreResearch = async (spec, options = {}) => {
|
|
|
2472
2476
|
}
|
|
2473
2477
|
};
|
|
2474
2478
|
var createCoreResearchSpecTemplate = (params) => {
|
|
2475
|
-
const rootDir =
|
|
2476
|
-
|
|
2479
|
+
const rootDir = import_node_path6.default.relative(
|
|
2480
|
+
import_node_path6.default.resolve(params.projectRoot),
|
|
2481
|
+
import_node_path6.default.join(import_node_path6.default.resolve(params.projectRoot), "data", "research", "core")
|
|
2482
|
+
).replace(/\\/g, "/");
|
|
2477
2483
|
const lineage = (() => {
|
|
2478
2484
|
try {
|
|
2479
2485
|
const gitSha = (0, import_node_child_process.execFileSync)("git", ["rev-parse", "HEAD"], {
|
|
2480
|
-
cwd:
|
|
2486
|
+
cwd: params.sourceRepositoryRoot,
|
|
2481
2487
|
encoding: "utf8",
|
|
2482
2488
|
stdio: ["ignore", "pipe", "ignore"]
|
|
2483
2489
|
}).trim();
|
|
@@ -2485,13 +2491,23 @@ var createCoreResearchSpecTemplate = (params) => {
|
|
|
2485
2491
|
"git",
|
|
2486
2492
|
["diff", "--binary", "--no-ext-diff", "HEAD"],
|
|
2487
2493
|
{
|
|
2488
|
-
cwd:
|
|
2494
|
+
cwd: params.sourceRepositoryRoot,
|
|
2489
2495
|
encoding: "utf8",
|
|
2490
2496
|
stdio: ["ignore", "pipe", "ignore"]
|
|
2491
2497
|
}
|
|
2492
2498
|
);
|
|
2499
|
+
const sourceRepository = (0, import_node_child_process.execFileSync)(
|
|
2500
|
+
"git",
|
|
2501
|
+
["remote", "get-url", "origin"],
|
|
2502
|
+
{
|
|
2503
|
+
cwd: params.sourceRepositoryRoot,
|
|
2504
|
+
encoding: "utf8",
|
|
2505
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2506
|
+
}
|
|
2507
|
+
).trim();
|
|
2493
2508
|
return {
|
|
2494
2509
|
gitSha,
|
|
2510
|
+
...sourceRepository ? { sourceRepository } : {},
|
|
2495
2511
|
...dirtyDiff ? {
|
|
2496
2512
|
dirtyDiffSha256: (0, import_node_crypto5.createHash)("sha256").update(dirtyDiff).digest("hex")
|
|
2497
2513
|
} : {}
|
|
@@ -2592,11 +2608,11 @@ var createCoreResearchSpecTemplate = (params) => {
|
|
|
2592
2608
|
};
|
|
2593
2609
|
var runCommand = async (params) => {
|
|
2594
2610
|
if (!params.command.length) throw new Error("Cannot run an empty command");
|
|
2595
|
-
await import_promises4.default.mkdir(
|
|
2611
|
+
await import_promises4.default.mkdir(import_node_path6.default.dirname(params.logPath), { recursive: true });
|
|
2596
2612
|
const chunks = [];
|
|
2597
2613
|
const child = (0, import_node_child_process.spawn)(params.command[0], params.command.slice(1), {
|
|
2598
2614
|
cwd: params.cwd,
|
|
2599
|
-
env: process.env,
|
|
2615
|
+
env: { ...process.env, ...params.env },
|
|
2600
2616
|
stdio: ["ignore", "pipe", "pipe"]
|
|
2601
2617
|
});
|
|
2602
2618
|
const capture = (chunk) => {
|
|
@@ -2664,7 +2680,7 @@ var validateCoreResearchRunCommand = (params) => {
|
|
|
2664
2680
|
};
|
|
2665
2681
|
var runCoreResearch = async (params) => {
|
|
2666
2682
|
const { spec } = params;
|
|
2667
|
-
const cwd =
|
|
2683
|
+
const cwd = import_node_path6.default.resolve(params.cwd ?? process.cwd());
|
|
2668
2684
|
const prepared = await prepareCoreResearch(spec);
|
|
2669
2685
|
const resolvedVariants = [];
|
|
2670
2686
|
for (const variant of spec.variants) {
|
|
@@ -2682,7 +2698,7 @@ var runCoreResearch = async (params) => {
|
|
|
2682
2698
|
artifactHashes: { variant: sha256Json(variant) }
|
|
2683
2699
|
});
|
|
2684
2700
|
let runId = "";
|
|
2685
|
-
const backtestLogPath =
|
|
2701
|
+
const backtestLogPath = import_node_path6.default.join(
|
|
2686
2702
|
prepared.paths.runLogDir,
|
|
2687
2703
|
`${variant.id}-backtest.log`
|
|
2688
2704
|
);
|
|
@@ -2691,6 +2707,14 @@ var runCoreResearch = async (params) => {
|
|
|
2691
2707
|
command: variant.command,
|
|
2692
2708
|
cwd,
|
|
2693
2709
|
logPath: backtestLogPath,
|
|
2710
|
+
env: {
|
|
2711
|
+
PROJECT_CWD: cwd,
|
|
2712
|
+
...params.sourceRepositoryRoot ? {
|
|
2713
|
+
[SOURCE_REPOSITORY_ROOT_ENV]: import_node_path6.default.resolve(
|
|
2714
|
+
params.sourceRepositoryRoot
|
|
2715
|
+
)
|
|
2716
|
+
} : {}
|
|
2717
|
+
},
|
|
2694
2718
|
onLine: (line) => {
|
|
2695
2719
|
const match = line.match(
|
|
2696
2720
|
/backtest run id:\s*([0-9]{12}-[a-f0-9]{8})/i
|
|
@@ -2701,12 +2725,12 @@ var runCoreResearch = async (params) => {
|
|
|
2701
2725
|
if (!runId) {
|
|
2702
2726
|
throw new Error(`Backtest for ${variant.id} did not report a run id`);
|
|
2703
2727
|
}
|
|
2704
|
-
const exportLogPath =
|
|
2728
|
+
const exportLogPath = import_node_path6.default.join(
|
|
2705
2729
|
prepared.paths.runLogDir,
|
|
2706
2730
|
`${variant.id}-export.log`
|
|
2707
2731
|
);
|
|
2708
2732
|
const exportParts = [];
|
|
2709
|
-
const cliPath =
|
|
2733
|
+
const cliPath = import_node_path6.default.resolve(process.argv[1]);
|
|
2710
2734
|
await runCommand({
|
|
2711
2735
|
command: [
|
|
2712
2736
|
process.execPath,
|
|
@@ -2723,9 +2747,17 @@ var runCoreResearch = async (params) => {
|
|
|
2723
2747
|
],
|
|
2724
2748
|
cwd,
|
|
2725
2749
|
logPath: exportLogPath,
|
|
2750
|
+
env: {
|
|
2751
|
+
PROJECT_CWD: cwd,
|
|
2752
|
+
...params.sourceRepositoryRoot ? {
|
|
2753
|
+
[SOURCE_REPOSITORY_ROOT_ENV]: import_node_path6.default.resolve(
|
|
2754
|
+
params.sourceRepositoryRoot
|
|
2755
|
+
)
|
|
2756
|
+
} : {}
|
|
2757
|
+
},
|
|
2726
2758
|
onLine: (line) => {
|
|
2727
2759
|
const match = line.match(/^part\d+:\s+(.+)$/);
|
|
2728
|
-
if (match) exportParts.push(
|
|
2760
|
+
if (match) exportParts.push(import_node_path6.default.resolve(cwd, match[1].trim()));
|
|
2729
2761
|
}
|
|
2730
2762
|
});
|
|
2731
2763
|
if (!exportParts.length) {
|
|
@@ -2736,7 +2768,7 @@ var runCoreResearch = async (params) => {
|
|
|
2736
2768
|
const traceFiles = await (0, import_coreResearch.listCoreResearchTraceFiles)({
|
|
2737
2769
|
strategyName: spec.strategy,
|
|
2738
2770
|
runId,
|
|
2739
|
-
outDir:
|
|
2771
|
+
outDir: import_node_path6.default.resolve(cwd, "data/research/core/trace")
|
|
2740
2772
|
});
|
|
2741
2773
|
resolvedVariants.push({
|
|
2742
2774
|
...variant,
|
|
@@ -2756,7 +2788,7 @@ var runCoreResearch = async (params) => {
|
|
|
2756
2788
|
...Object.fromEntries(
|
|
2757
2789
|
await Promise.all(
|
|
2758
2790
|
exportParts.map(async (filePath) => [
|
|
2759
|
-
|
|
2791
|
+
import_node_path6.default.basename(filePath),
|
|
2760
2792
|
await sha256File(filePath)
|
|
2761
2793
|
])
|
|
2762
2794
|
)
|
|
@@ -2775,7 +2807,7 @@ var runCoreResearch = async (params) => {
|
|
|
2775
2807
|
}
|
|
2776
2808
|
}
|
|
2777
2809
|
await writeJsonAtomic(
|
|
2778
|
-
|
|
2810
|
+
import_node_path6.default.join(prepared.paths.researchDir, "resolved-runs.json"),
|
|
2779
2811
|
{
|
|
2780
2812
|
schema: "tradejs-core-research-resolved-runs/v1",
|
|
2781
2813
|
researchId: spec.researchId,
|
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var researchAgent_exports = {};
|
|
22
22
|
__export(researchAgent_exports, {
|
|
23
23
|
RESEARCH_AGENT_BRANCH_PREFIX: () => RESEARCH_AGENT_BRANCH_PREFIX,
|
|
24
|
+
RESEARCH_AGENT_DEFAULT_GITHUB_ORGANIZATION: () => RESEARCH_AGENT_DEFAULT_GITHUB_ORGANIZATION,
|
|
24
25
|
RESEARCH_AGENT_MODEL: () => RESEARCH_AGENT_MODEL,
|
|
25
26
|
RESEARCH_AGENT_REASONING_EFFORT: () => RESEARCH_AGENT_REASONING_EFFORT,
|
|
26
27
|
assertDiffAllowed: () => assertDiffAllowed,
|
|
@@ -29,6 +30,8 @@ __export(researchAgent_exports, {
|
|
|
29
30
|
buildResearchAgentPrBody: () => buildResearchAgentPrBody,
|
|
30
31
|
buildResearchAgentPrTitle: () => buildResearchAgentPrTitle,
|
|
31
32
|
getResearchAgentAllowedPathPrefixes: () => getResearchAgentAllowedPathPrefixes,
|
|
33
|
+
getResearchAgentRepository: () => getResearchAgentRepository,
|
|
34
|
+
getResearchAgentRepositoryName: () => getResearchAgentRepositoryName,
|
|
32
35
|
normalizeDiffOutput: () => normalizeDiffOutput,
|
|
33
36
|
parseChangedFilesFromDiff: () => parseChangedFilesFromDiff,
|
|
34
37
|
parseGithubRepositoryFromRemote: () => parseGithubRepositoryFromRemote
|
|
@@ -37,6 +40,7 @@ module.exports = __toCommonJS(researchAgent_exports);
|
|
|
37
40
|
var RESEARCH_AGENT_MODEL = "openai/gpt-5.4";
|
|
38
41
|
var RESEARCH_AGENT_REASONING_EFFORT = "medium";
|
|
39
42
|
var RESEARCH_AGENT_BRANCH_PREFIX = "codex/research";
|
|
43
|
+
var RESEARCH_AGENT_DEFAULT_GITHUB_ORGANIZATION = "TradeJS-Dev";
|
|
40
44
|
var buildResearchAgentBranchName = (strategy, runId) => {
|
|
41
45
|
const normalizedStrategy = strategy.trim().replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^a-zA-Z0-9-]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
|
|
42
46
|
const normalizedRunId = runId.trim().replace(/[^a-zA-Z0-9-]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
|
|
@@ -44,8 +48,15 @@ var buildResearchAgentBranchName = (strategy, runId) => {
|
|
|
44
48
|
};
|
|
45
49
|
var buildResearchAgentCommitMessage = (strategy, runId) => `Research agent: ${strategy} follow-up for ${runId}`;
|
|
46
50
|
var buildResearchAgentPrTitle = (strategy, runId) => `Research agent: ${strategy} follow-up for ${runId}`;
|
|
51
|
+
var getResearchAgentRepositoryName = (strategy) => {
|
|
52
|
+
if (strategy === "TrendLine" || strategy === "ReverseTrendLine") {
|
|
53
|
+
return "TradeJS-Strategy-TrendLine";
|
|
54
|
+
}
|
|
55
|
+
return `TradeJS-Strategy-${strategy}`;
|
|
56
|
+
};
|
|
57
|
+
var getResearchAgentRepository = (strategy, organization = RESEARCH_AGENT_DEFAULT_GITHUB_ORGANIZATION) => `${organization}/${getResearchAgentRepositoryName(strategy)}`;
|
|
47
58
|
var getResearchAgentAllowedPathPrefixes = (strategy) => [
|
|
48
|
-
`
|
|
59
|
+
`src/${strategy}/`
|
|
49
60
|
];
|
|
50
61
|
var parseGithubRepositoryFromRemote = (value) => {
|
|
51
62
|
const trimmed = value.trim();
|
|
@@ -99,7 +110,7 @@ var buildResearchAgentPrBody = (params) => {
|
|
|
99
110
|
lines.push("");
|
|
100
111
|
lines.push("## Notes");
|
|
101
112
|
lines.push("- Created automatically by the TradeJS research agent.");
|
|
102
|
-
lines.push("- Base branch: `
|
|
113
|
+
lines.push("- Base branch: `main`.");
|
|
103
114
|
return lines.join("\n");
|
|
104
115
|
};
|
|
105
116
|
var normalizeDiffOutput = (value) => {
|
|
@@ -154,6 +165,7 @@ ${diffText}`)) {
|
|
|
154
165
|
// Annotate the CommonJS export names for ESM import in node:
|
|
155
166
|
0 && (module.exports = {
|
|
156
167
|
RESEARCH_AGENT_BRANCH_PREFIX,
|
|
168
|
+
RESEARCH_AGENT_DEFAULT_GITHUB_ORGANIZATION,
|
|
157
169
|
RESEARCH_AGENT_MODEL,
|
|
158
170
|
RESEARCH_AGENT_REASONING_EFFORT,
|
|
159
171
|
assertDiffAllowed,
|
|
@@ -162,6 +174,8 @@ ${diffText}`)) {
|
|
|
162
174
|
buildResearchAgentPrBody,
|
|
163
175
|
buildResearchAgentPrTitle,
|
|
164
176
|
getResearchAgentAllowedPathPrefixes,
|
|
177
|
+
getResearchAgentRepository,
|
|
178
|
+
getResearchAgentRepositoryName,
|
|
165
179
|
normalizeDiffOutput,
|
|
166
180
|
parseChangedFilesFromDiff,
|
|
167
181
|
parseGithubRepositoryFromRemote
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/lib/researchRoots.ts
|
|
31
|
+
var researchRoots_exports = {};
|
|
32
|
+
__export(researchRoots_exports, {
|
|
33
|
+
SOURCE_REPOSITORY_ROOT_ENV: () => SOURCE_REPOSITORY_ROOT_ENV,
|
|
34
|
+
resolveResearchRoots: () => resolveResearchRoots
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(researchRoots_exports);
|
|
37
|
+
var import_node_path = __toESM(require("path"));
|
|
38
|
+
var SOURCE_REPOSITORY_ROOT_ENV = "TRADEJS_SOURCE_REPOSITORY_ROOT";
|
|
39
|
+
var firstNonEmpty = (...values) => values.map((value) => String(value || "").trim()).find(Boolean);
|
|
40
|
+
var resolveResearchRoots = (options = {}) => {
|
|
41
|
+
const cwd = import_node_path.default.resolve(options.cwd || process.cwd());
|
|
42
|
+
const env = options.env || process.env;
|
|
43
|
+
const projectRoot = import_node_path.default.resolve(
|
|
44
|
+
firstNonEmpty(options.projectRoot, env.PROJECT_CWD, cwd) || cwd
|
|
45
|
+
);
|
|
46
|
+
const sourceRepositoryRoot = import_node_path.default.resolve(
|
|
47
|
+
firstNonEmpty(
|
|
48
|
+
options.sourceRepositoryRoot,
|
|
49
|
+
env[SOURCE_REPOSITORY_ROOT_ENV],
|
|
50
|
+
cwd
|
|
51
|
+
) || cwd
|
|
52
|
+
);
|
|
53
|
+
return { projectRoot, sourceRepositoryRoot };
|
|
54
|
+
};
|
|
55
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
56
|
+
0 && (module.exports = {
|
|
57
|
+
SOURCE_REPOSITORY_ROOT_ENV,
|
|
58
|
+
resolveResearchRoots
|
|
59
|
+
});
|
|
@@ -47,28 +47,37 @@ var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvid
|
|
|
47
47
|
|
|
48
48
|
// src/lib/strategyGateFingerprint.ts
|
|
49
49
|
var import_node_crypto = require("crypto");
|
|
50
|
+
var import_node_module = require("module");
|
|
50
51
|
var import_promises = __toESM(require("fs/promises"));
|
|
51
52
|
var import_node_path = __toESM(require("path"));
|
|
52
|
-
var
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"packages/core/src/utils/strategyHelpers/signalBuilders.ts"
|
|
53
|
+
var toPackageToken = (strategyName) => strategyName.replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").replace(/([a-z\d])([A-Z])/g, "$1-$2").toLowerCase();
|
|
54
|
+
var getStrategyPackageName = (strategyName) => strategyName === "TrendLine" || strategyName === "ReverseTrendLine" ? "@tradejs/strategy-trend-line" : `@tradejs/strategy-${toPackageToken(strategyName)}`;
|
|
55
|
+
var gateFingerprintSpecifiers = (strategyName) => [
|
|
56
|
+
getStrategyPackageName(strategyName),
|
|
57
|
+
"@tradejs/strategy-kit/ai-gate",
|
|
58
|
+
"@tradejs/node/ai",
|
|
59
|
+
"@tradejs/core/strategies"
|
|
60
60
|
];
|
|
61
61
|
var resolveStrategyGateFingerprint = async ({
|
|
62
62
|
projectRoot,
|
|
63
63
|
strategyName,
|
|
64
64
|
gitSha
|
|
65
65
|
}) => {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
const projectManifestPath = import_node_path.default.join(projectRoot, "package.json");
|
|
67
|
+
const projectExists = await import_promises.default.access(projectManifestPath).then(() => true).catch(() => false);
|
|
68
|
+
const requireFromProject = projectExists ? (0, import_node_module.createRequire)(projectManifestPath) : null;
|
|
69
|
+
const candidates = requireFromProject ? await Promise.all(
|
|
70
|
+
gateFingerprintSpecifiers(strategyName).map(async (specifier) => {
|
|
71
|
+
let resolvedPath;
|
|
72
|
+
try {
|
|
73
|
+
resolvedPath = requireFromProject.resolve(specifier);
|
|
74
|
+
} catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
const content = await import_promises.default.readFile(resolvedPath).catch(() => null);
|
|
78
|
+
return content == null ? null : { specifier, content };
|
|
70
79
|
})
|
|
71
|
-
);
|
|
80
|
+
) : [];
|
|
72
81
|
const sourceEntries = candidates.filter(
|
|
73
82
|
(entry) => entry != null
|
|
74
83
|
);
|
|
@@ -76,7 +85,7 @@ var resolveStrategyGateFingerprint = async ({
|
|
|
76
85
|
hash.update(strategyName);
|
|
77
86
|
if (sourceEntries.length) {
|
|
78
87
|
for (const entry of sourceEntries) {
|
|
79
|
-
hash.update(entry.
|
|
88
|
+
hash.update(entry.specifier);
|
|
80
89
|
hash.update(entry.content);
|
|
81
90
|
}
|
|
82
91
|
} else {
|
|
@@ -84,7 +93,7 @@ var resolveStrategyGateFingerprint = async ({
|
|
|
84
93
|
}
|
|
85
94
|
return {
|
|
86
95
|
gateFingerprint: hash.digest("hex").slice(0, 16),
|
|
87
|
-
gateFingerprintFiles: sourceEntries.map((entry) => entry.
|
|
96
|
+
gateFingerprintFiles: sourceEntries.map((entry) => entry.specifier)
|
|
88
97
|
};
|
|
89
98
|
};
|
|
90
99
|
|
|
@@ -263,14 +272,29 @@ var resolveRuntimeGateFingerprint = async ({
|
|
|
263
272
|
gateFingerprintCache.set(cacheKey, result);
|
|
264
273
|
return result;
|
|
265
274
|
};
|
|
266
|
-
|
|
275
|
+
async function buildRuntimeLineage({
|
|
267
276
|
projectRoot,
|
|
268
277
|
strategyName,
|
|
269
278
|
compositionId,
|
|
279
|
+
releaseVersion,
|
|
280
|
+
strategyPackageVersion,
|
|
281
|
+
runtimePackageVersion,
|
|
270
282
|
config,
|
|
271
283
|
runContext,
|
|
272
284
|
env = process.env
|
|
273
|
-
})
|
|
285
|
+
}) {
|
|
286
|
+
if (releaseVersion != null) {
|
|
287
|
+
if (!Number.isSafeInteger(releaseVersion) || releaseVersion <= 0) {
|
|
288
|
+
throw new Error(`Invalid runtime releaseVersion: ${releaseVersion}`);
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
schemaVersion: 2,
|
|
292
|
+
releaseVersion,
|
|
293
|
+
strategyPackageVersion,
|
|
294
|
+
runtimePackageVersion,
|
|
295
|
+
maxLossValue: resolveRuntimeMaxLossValue(config)
|
|
296
|
+
};
|
|
297
|
+
}
|
|
274
298
|
const git = resolveGitLineage(projectRoot);
|
|
275
299
|
const hyperliquidPerpUniverseFingerprint = typeof import_strategies.getHyperliquidPerpUniverseSnapshot === "function" ? (0, import_strategies.getHyperliquidPerpUniverseSnapshot)().fingerprint : await resolveSnapshotFingerprint(
|
|
276
300
|
projectRoot,
|
|
@@ -305,8 +329,8 @@ var buildRuntimeLineage = async ({
|
|
|
305
329
|
contextFingerprint: fingerprintRuntimeValue(context),
|
|
306
330
|
maxLossValue: resolveRuntimeMaxLossValue(config)
|
|
307
331
|
};
|
|
308
|
-
}
|
|
309
|
-
var runtimeLineageKey = (lineage) => [
|
|
332
|
+
}
|
|
333
|
+
var runtimeLineageKey = (lineage) => lineage.schemaVersion === 2 ? ["v2", lineage.releaseVersion].join(":") : [
|
|
310
334
|
lineage.schemaVersion,
|
|
311
335
|
lineage.compositionId ?? "unbound-composition",
|
|
312
336
|
lineage.gitSha ?? "unknown",
|
|
@@ -41,7 +41,7 @@ var buildRuntimeModeStrategyConfig = ({
|
|
|
41
41
|
...strategyConfig,
|
|
42
42
|
ENV: env,
|
|
43
43
|
MAKE_ORDERS: makeOrders,
|
|
44
|
-
INTERVAL: interval,
|
|
44
|
+
INTERVAL: strategyConfig.INTERVAL ?? interval,
|
|
45
45
|
...typeof recordRuntimeTrades === "boolean" ? { RECORD_RUNTIME_TRADES: recordRuntimeTrades } : {},
|
|
46
46
|
...aiReplayAnalyses?.length ? { AI_REPLAY_ANALYSES: aiReplayAnalyses } : {}
|
|
47
47
|
});
|
|
@@ -63,7 +63,8 @@ var toRuntimeSignalBucketRef = (signal) => ({
|
|
|
63
63
|
symbol: signal.symbol,
|
|
64
64
|
strategy: signal.strategy,
|
|
65
65
|
timestamp: signal.timestamp,
|
|
66
|
-
...signal.runtimeConfigId && signal.runtimeConfigId !== "config" ? { runtimeConfigId: signal.runtimeConfigId } : {}
|
|
66
|
+
...signal.runtimeConfigId && signal.runtimeConfigId !== "config" ? { runtimeConfigId: signal.runtimeConfigId } : {},
|
|
67
|
+
...signal.runtimeReleaseVersion ? { runtimeReleaseVersion: signal.runtimeReleaseVersion } : {}
|
|
67
68
|
});
|
|
68
69
|
var shouldStoreRuntimeSignalDiagnostics = (signal) => signal.orderStatus === "completed" || signal.orderStatus === "failed";
|
|
69
70
|
var toStoredRuntimeSignal = (signal) => {
|
|
@@ -30,32 +30,42 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/lib/strategyGateFingerprint.ts
|
|
31
31
|
var strategyGateFingerprint_exports = {};
|
|
32
32
|
__export(strategyGateFingerprint_exports, {
|
|
33
|
+
getStrategyPackageName: () => getStrategyPackageName,
|
|
33
34
|
resolveStrategyGateFingerprint: () => resolveStrategyGateFingerprint
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(strategyGateFingerprint_exports);
|
|
36
37
|
var import_node_crypto = require("crypto");
|
|
38
|
+
var import_node_module = require("module");
|
|
37
39
|
var import_promises = __toESM(require("fs/promises"));
|
|
38
40
|
var import_node_path = __toESM(require("path"));
|
|
39
|
-
var
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"packages/core/src/utils/strategyHelpers/signalBuilders.ts"
|
|
41
|
+
var toPackageToken = (strategyName) => strategyName.replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").replace(/([a-z\d])([A-Z])/g, "$1-$2").toLowerCase();
|
|
42
|
+
var getStrategyPackageName = (strategyName) => strategyName === "TrendLine" || strategyName === "ReverseTrendLine" ? "@tradejs/strategy-trend-line" : `@tradejs/strategy-${toPackageToken(strategyName)}`;
|
|
43
|
+
var gateFingerprintSpecifiers = (strategyName) => [
|
|
44
|
+
getStrategyPackageName(strategyName),
|
|
45
|
+
"@tradejs/strategy-kit/ai-gate",
|
|
46
|
+
"@tradejs/node/ai",
|
|
47
|
+
"@tradejs/core/strategies"
|
|
47
48
|
];
|
|
48
49
|
var resolveStrategyGateFingerprint = async ({
|
|
49
50
|
projectRoot,
|
|
50
51
|
strategyName,
|
|
51
52
|
gitSha
|
|
52
53
|
}) => {
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
const projectManifestPath = import_node_path.default.join(projectRoot, "package.json");
|
|
55
|
+
const projectExists = await import_promises.default.access(projectManifestPath).then(() => true).catch(() => false);
|
|
56
|
+
const requireFromProject = projectExists ? (0, import_node_module.createRequire)(projectManifestPath) : null;
|
|
57
|
+
const candidates = requireFromProject ? await Promise.all(
|
|
58
|
+
gateFingerprintSpecifiers(strategyName).map(async (specifier) => {
|
|
59
|
+
let resolvedPath;
|
|
60
|
+
try {
|
|
61
|
+
resolvedPath = requireFromProject.resolve(specifier);
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const content = await import_promises.default.readFile(resolvedPath).catch(() => null);
|
|
66
|
+
return content == null ? null : { specifier, content };
|
|
57
67
|
})
|
|
58
|
-
);
|
|
68
|
+
) : [];
|
|
59
69
|
const sourceEntries = candidates.filter(
|
|
60
70
|
(entry) => entry != null
|
|
61
71
|
);
|
|
@@ -63,7 +73,7 @@ var resolveStrategyGateFingerprint = async ({
|
|
|
63
73
|
hash.update(strategyName);
|
|
64
74
|
if (sourceEntries.length) {
|
|
65
75
|
for (const entry of sourceEntries) {
|
|
66
|
-
hash.update(entry.
|
|
76
|
+
hash.update(entry.specifier);
|
|
67
77
|
hash.update(entry.content);
|
|
68
78
|
}
|
|
69
79
|
} else {
|
|
@@ -71,10 +81,11 @@ var resolveStrategyGateFingerprint = async ({
|
|
|
71
81
|
}
|
|
72
82
|
return {
|
|
73
83
|
gateFingerprint: hash.digest("hex").slice(0, 16),
|
|
74
|
-
gateFingerprintFiles: sourceEntries.map((entry) => entry.
|
|
84
|
+
gateFingerprintFiles: sourceEntries.map((entry) => entry.specifier)
|
|
75
85
|
};
|
|
76
86
|
};
|
|
77
87
|
// Annotate the CommonJS export names for ESM import in node:
|
|
78
88
|
0 && (module.exports = {
|
|
89
|
+
getStrategyPackageName,
|
|
79
90
|
resolveStrategyGateFingerprint
|
|
80
91
|
});
|