@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.
@@ -37,7 +37,7 @@ var import_args = __toESM(require("args"));
37
37
  var import_chalk = __toESM(require("chalk"));
38
38
  var import_promises = __toESM(require("fs/promises"));
39
39
  var import_node_os = __toESM(require("os"));
40
- var import_node_path = __toESM(require("path"));
40
+ var import_node_path2 = __toESM(require("path"));
41
41
  var import_node_child_process = require("child_process");
42
42
  var import_constants = require("@tradejs/core/constants");
43
43
  var import_aiEndpoints = require("@tradejs/core/aiEndpoints");
@@ -117,6 +117,7 @@ ${chunk}`, {
117
117
  var RESEARCH_AGENT_MODEL = "openai/gpt-5.4";
118
118
  var RESEARCH_AGENT_REASONING_EFFORT = "medium";
119
119
  var RESEARCH_AGENT_BRANCH_PREFIX = "codex/research";
120
+ var RESEARCH_AGENT_DEFAULT_GITHUB_ORGANIZATION = "TradeJS-Dev";
120
121
  var buildResearchAgentBranchName = (strategy, runId) => {
121
122
  const normalizedStrategy = strategy.trim().replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^a-zA-Z0-9-]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
122
123
  const normalizedRunId = runId.trim().replace(/[^a-zA-Z0-9-]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
@@ -124,8 +125,15 @@ var buildResearchAgentBranchName = (strategy, runId) => {
124
125
  };
125
126
  var buildResearchAgentCommitMessage = (strategy, runId) => `Research agent: ${strategy} follow-up for ${runId}`;
126
127
  var buildResearchAgentPrTitle = (strategy, runId) => `Research agent: ${strategy} follow-up for ${runId}`;
128
+ var getResearchAgentRepositoryName = (strategy) => {
129
+ if (strategy === "TrendLine" || strategy === "ReverseTrendLine") {
130
+ return "TradeJS-Strategy-TrendLine";
131
+ }
132
+ return `TradeJS-Strategy-${strategy}`;
133
+ };
134
+ var getResearchAgentRepository = (strategy, organization = RESEARCH_AGENT_DEFAULT_GITHUB_ORGANIZATION) => `${organization}/${getResearchAgentRepositoryName(strategy)}`;
127
135
  var getResearchAgentAllowedPathPrefixes = (strategy) => [
128
- `packages/strategies/src/${strategy}/`
136
+ `src/${strategy}/`
129
137
  ];
130
138
  var parseGithubRepositoryFromRemote = (value) => {
131
139
  const trimmed = value.trim();
@@ -179,7 +187,7 @@ var buildResearchAgentPrBody = (params) => {
179
187
  lines.push("");
180
188
  lines.push("## Notes");
181
189
  lines.push("- Created automatically by the TradeJS research agent.");
182
- lines.push("- Base branch: `stable`.");
190
+ lines.push("- Base branch: `main`.");
183
191
  return lines.join("\n");
184
192
  };
185
193
  var normalizeDiffOutput = (value) => {
@@ -232,18 +240,38 @@ ${diffText}`)) {
232
240
  return changedFiles;
233
241
  };
234
242
 
243
+ // src/lib/researchRoots.ts
244
+ var import_node_path = __toESM(require("path"));
245
+ var SOURCE_REPOSITORY_ROOT_ENV = "TRADEJS_SOURCE_REPOSITORY_ROOT";
246
+ var firstNonEmpty = (...values) => values.map((value) => String(value || "").trim()).find(Boolean);
247
+ var resolveResearchRoots = (options = {}) => {
248
+ const cwd = import_node_path.default.resolve(options.cwd || process.cwd());
249
+ const env = options.env || process.env;
250
+ const projectRoot2 = import_node_path.default.resolve(
251
+ firstNonEmpty(options.projectRoot, env.PROJECT_CWD, cwd) || cwd
252
+ );
253
+ const sourceRepositoryRoot = import_node_path.default.resolve(
254
+ firstNonEmpty(
255
+ options.sourceRepositoryRoot,
256
+ env[SOURCE_REPOSITORY_ROOT_ENV],
257
+ cwd
258
+ ) || cwd
259
+ );
260
+ return { projectRoot: projectRoot2, sourceRepositoryRoot };
261
+ };
262
+
235
263
  // src/scripts/agentRun.ts
236
264
  import_args.default.example(
237
265
  "yarn cli:node8g agent-run --runId 1710000000000-trendline --strategy TrendLine",
238
- "Run the OpenRouter-based research follow-up coding agent in a git worktree"
266
+ "Run the OpenRouter-based research follow-up coding agent in a strategy repository"
239
267
  );
240
268
  import_args.default.option(["U", "user"], "Use user config", "root");
241
269
  import_args.default.option(["r", "runId"], "Research run id");
242
270
  import_args.default.option(["s", "strategy"], "Strategy name");
243
271
  import_args.default.option("json", "Print structured JSON summary", false);
244
272
  var flags = import_args.default.parse(process.argv);
245
- var projectRoot = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
246
- var AGENT_SYSTEM_PROMPT = `You are a senior TypeScript trading research coding agent working inside the TradeJS monorepo.
273
+ var { projectRoot } = resolveResearchRoots();
274
+ var AGENT_SYSTEM_PROMPT = `You are a senior TypeScript trading research coding agent working inside a standalone TradeJS strategy repository.
247
275
 
248
276
  Output ONLY one of:
249
277
  1. A unified git diff relative to repo root that can be applied with git apply.
@@ -320,7 +348,7 @@ var listFilesRecursive = async (targetPath) => {
320
348
  const entries = await import_promises.default.readdir(targetPath, { withFileTypes: true });
321
349
  const nested = await Promise.all(
322
350
  entries.map(async (entry) => {
323
- const absolutePath = import_node_path.default.join(targetPath, entry.name);
351
+ const absolutePath = import_node_path2.default.join(targetPath, entry.name);
324
352
  if (entry.isDirectory()) {
325
353
  return listFilesRecursive(absolutePath);
326
354
  }
@@ -333,13 +361,7 @@ var listFilesRecursive = async (targetPath) => {
333
361
  }
334
362
  };
335
363
  var collectStrategyContextFiles = async (worktreePath, strategy) => {
336
- const strategyRoot = import_node_path.default.join(
337
- worktreePath,
338
- "packages",
339
- "strategies",
340
- "src",
341
- strategy
342
- );
364
+ const strategyRoot = import_node_path2.default.join(worktreePath, "src", strategy);
343
365
  const strategyFiles = await listFilesRecursive(strategyRoot);
344
366
  const files = strategyFiles.filter(
345
367
  (filePath) => /\.(ts|tsx|md)$/.test(filePath)
@@ -347,7 +369,7 @@ var collectStrategyContextFiles = async (worktreePath, strategy) => {
347
369
  return [...new Set(files)].sort((left, right) => left.localeCompare(right));
348
370
  };
349
371
  var renderFileContext = async (worktreePath, filePath) => {
350
- const relativePath = import_node_path.default.relative(worktreePath, filePath).replace(/\\/g, "/");
372
+ const relativePath = import_node_path2.default.relative(worktreePath, filePath).replace(/\\/g, "/");
351
373
  const content = await import_promises.default.readFile(filePath, "utf8");
352
374
  return [
353
375
  `=== FILE: ${relativePath} ===`,
@@ -459,8 +481,8 @@ var requestAgentDiff = async (userName, messages) => {
459
481
  return normalized;
460
482
  };
461
483
  var applyDiff = async (worktreePath, diffText) => {
462
- const tempDir = await import_promises.default.mkdtemp(import_node_path.default.join(import_node_os.default.tmpdir(), "tradejs-agent-"));
463
- const patchPath = import_node_path.default.join(tempDir, "agent.patch");
484
+ const tempDir = await import_promises.default.mkdtemp(import_node_path2.default.join(import_node_os.default.tmpdir(), "tradejs-agent-"));
485
+ const patchPath = import_node_path2.default.join(tempDir, "agent.patch");
464
486
  try {
465
487
  await import_promises.default.writeFile(patchPath, diffText, "utf8");
466
488
  await runCommandOrThrow(
@@ -489,20 +511,17 @@ var getChangedFilesFromGit = async (worktreePath) => {
489
511
  };
490
512
  var runValidationSuite = async (worktreePath, agentRun) => {
491
513
  const commands = [
492
- ["prettify", ["yarn", "prettify"]],
493
- ["typecheck", ["yarn", "typecheck"]],
494
- ["unit", ["yarn", "unit"]]
514
+ ["checks", ["yarn", "checks"]]
495
515
  ];
496
516
  agentRun.validation = {
497
- prettify: "pending",
498
- typecheck: "pending",
499
- unit: "pending"
517
+ checks: "pending"
500
518
  };
501
519
  for (const [key, command] of commands) {
502
520
  const result = await runCommand(command[0], command.slice(1), {
503
521
  cwd: worktreePath,
504
522
  env: {
505
- PROJECT_CWD: worktreePath,
523
+ PROJECT_CWD: projectRoot,
524
+ [SOURCE_REPOSITORY_ROOT_ENV]: worktreePath,
506
525
  DOTENV_CONFIG_PATH: process.env.DOTENV_CONFIG_PATH
507
526
  }
508
527
  });
@@ -605,9 +624,6 @@ var saveAgentRun = async (userName, runId, strategy, agentRun) => {
605
624
  });
606
625
  };
607
626
  var resolveGithubRepository = async (worktreePath) => {
608
- if (process.env.AGENT_GITHUB_REPOSITORY?.trim()) {
609
- return process.env.AGENT_GITHUB_REPOSITORY.trim();
610
- }
611
627
  const remote = await runCommandOrThrow(
612
628
  "git",
613
629
  ["-C", worktreePath, "remote", "get-url", "origin"],
@@ -629,7 +645,7 @@ var createGithubPullRequest = async (params) => {
629
645
  if (!owner || !repo) {
630
646
  throw new Error(`Invalid GitHub repository value: ${repository}`);
631
647
  }
632
- const baseBranch = process.env.AGENT_GITHUB_BASE_BRANCH?.trim() || "stable";
648
+ const baseBranch = process.env.AGENT_GITHUB_BASE_BRANCH?.trim() || "main";
633
649
  const head = `${owner}:${params.branchName}`;
634
650
  const headers = {
635
651
  Authorization: `Bearer ${token}`,
@@ -683,31 +699,39 @@ var createGithubPullRequest = async (params) => {
683
699
  reused: false
684
700
  };
685
701
  };
686
- var createWorktree = async (branchName) => {
687
- const worktreeToken = branchName.replace(/[/:]+/g, "--");
688
- const worktreeRoot = import_node_path.default.join(projectRoot, ".agent-worktrees");
689
- const worktreePath = import_node_path.default.join(worktreeRoot, worktreeToken);
690
- await import_promises.default.mkdir(worktreeRoot, { recursive: true });
691
- await runCommand("git", ["worktree", "remove", "--force", worktreePath], {
692
- cwd: projectRoot
693
- });
694
- await runCommandOrThrow("git", ["fetch", "origin", "stable"], {
695
- cwd: projectRoot
696
- });
702
+ var createStrategyCheckout = async (strategy, branchName) => {
703
+ const organization = process.env.AGENT_GITHUB_ORGANIZATION?.trim() || "TradeJS-Dev";
704
+ const repository = getResearchAgentRepository(strategy, organization);
705
+ const baseBranch = process.env.AGENT_GITHUB_BASE_BRANCH?.trim() || "main";
706
+ const checkoutBase = import_node_path2.default.join(
707
+ projectRoot,
708
+ "data",
709
+ "cache",
710
+ "research-agent-checkouts"
711
+ );
712
+ await import_promises.default.mkdir(checkoutBase, { recursive: true });
713
+ const checkoutRoot = await import_promises.default.mkdtemp(import_node_path2.default.join(checkoutBase, "strategy-"));
714
+ const checkoutPath = import_node_path2.default.join(checkoutRoot, "repository");
697
715
  await runCommandOrThrow(
698
716
  "git",
699
- ["worktree", "add", "-B", branchName, worktreePath, "origin/stable"],
700
- {
701
- cwd: projectRoot
702
- }
717
+ [
718
+ "clone",
719
+ "--branch",
720
+ baseBranch,
721
+ "--single-branch",
722
+ `git@github.com:${repository}.git`,
723
+ checkoutPath
724
+ ],
725
+ { cwd: checkoutRoot }
703
726
  );
704
- return worktreePath;
705
- };
706
- var cleanupWorktree = async (worktreePath) => {
707
- await runCommand("git", ["worktree", "remove", "--force", worktreePath], {
708
- cwd: projectRoot
709
- });
727
+ await runCommandOrThrow(
728
+ "git",
729
+ ["-C", checkoutPath, "switch", "-c", branchName],
730
+ { cwd: checkoutPath }
731
+ );
732
+ return { checkoutPath, checkoutRoot, repository };
710
733
  };
734
+ var cleanupStrategyCheckout = async (checkoutRoot) => import_promises.default.rm(checkoutRoot, { recursive: true, force: true });
711
735
  var main = async () => {
712
736
  const userName = String(flags.user || "root").trim() || "root";
713
737
  const requestedRunId = String(flags.runId || "").trim();
@@ -733,10 +757,17 @@ var main = async () => {
733
757
  summary: "Awaiting model patch",
734
758
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
735
759
  };
760
+ let checkoutRoot = "";
736
761
  let worktreePath = "";
737
762
  await saveAgentRun(userName, run.runId, run.strategy, agentRun);
738
763
  try {
739
- worktreePath = await createWorktree(branchName);
764
+ const checkout = await createStrategyCheckout(run.strategy, branchName);
765
+ checkoutRoot = checkout.checkoutRoot;
766
+ worktreePath = checkout.checkoutPath;
767
+ agentRun.repository = checkout.repository;
768
+ await runCommandOrThrow("yarn", ["install", "--immutable"], {
769
+ cwd: worktreePath
770
+ });
740
771
  const userPrompt = await buildPrompt(worktreePath, run, allowedPrefixes);
741
772
  const messages = [
742
773
  { role: "system", content: AGENT_SYSTEM_PROMPT },
@@ -888,8 +919,8 @@ Return a corrected unified diff only. Keep the same allowed paths.`
888
919
  }
889
920
  process.exit(1);
890
921
  } finally {
891
- if (worktreePath) {
892
- await cleanupWorktree(worktreePath);
922
+ if (checkoutRoot) {
923
+ await cleanupStrategyCheckout(checkoutRoot);
893
924
  }
894
925
  }
895
926
  };