@saeed42/worktree-worker 1.0.0 → 1.1.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.
Files changed (3) hide show
  1. package/README.md +28 -7
  2. package/dist/main.js +155 -68
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,15 +1,19 @@
1
- # @orgn/worktree-worker
1
+ # @saeed42/worktree-worker
2
2
 
3
3
  Git worktree management service for AI agent trials. Runs as an npm package in CodeSandbox or any Node.js environment.
4
4
 
5
+ ## Security
6
+
7
+ **GitHub tokens are NEVER persisted to disk.** All authenticated operations require the token to be passed in the request body. This is critical for sandbox environments where credentials should not be stored.
8
+
5
9
  ## Installation
6
10
 
7
11
  ```bash
8
12
  # Install globally
9
- npm install -g @orgn/worktree-worker
13
+ npm install -g @saeed42/worktree-worker
10
14
 
11
15
  # Or add to your project
12
- npm install @orgn/worktree-worker
16
+ npm install @saeed42/worktree-worker
13
17
  ```
14
18
 
15
19
  ## Quick Start
@@ -32,7 +36,7 @@ Add to your `package.json`:
32
36
  ```json
33
37
  {
34
38
  "dependencies": {
35
- "@orgn/worktree-worker": "^1.0.0"
39
+ "@saeed42/worktree-worker": "^1.0.0"
36
40
  },
37
41
  "scripts": {
38
42
  "worktree-worker": "worktree-worker"
@@ -43,13 +47,13 @@ Add to your `package.json`:
43
47
  Or run directly:
44
48
 
45
49
  ```bash
46
- npx @orgn/worktree-worker
50
+ npx @saeed42/worktree-worker
47
51
  ```
48
52
 
49
53
  ### Run Programmatically
50
54
 
51
55
  ```typescript
52
- import { app } from '@orgn/worktree-worker';
56
+ import { app } from '@saeed42/worktree-worker';
53
57
 
54
58
  // The app is a Hono instance
55
59
  // You can extend it or use it as middleware
@@ -133,10 +137,13 @@ curl -X POST http://localhost:8787/v1/trials/abc123/worktree/reset \
133
137
  -H "Content-Type: application/json" \
134
138
  -d '{
135
139
  "baseBranch": "main",
136
- "trialBranch": "feature/my-feature"
140
+ "trialBranch": "feature/my-feature",
141
+ "githubToken": "ghp_xxx"
137
142
  }'
138
143
  ```
139
144
 
145
+ > **Note:** `githubToken` is required for private repositories. The token is used inline and **never stored on disk**.
146
+
140
147
  Response:
141
148
 
142
149
  ```json
@@ -165,6 +172,20 @@ curl -X POST http://localhost:8787/v1/trials/abc123/worktree/commit \
165
172
  }'
166
173
  ```
167
174
 
175
+ ### Push Changes
176
+
177
+ ```bash
178
+ curl -X POST http://localhost:8787/v1/trials/abc123/worktree/push \
179
+ -H "Authorization: Bearer your-token" \
180
+ -H "Content-Type: application/json" \
181
+ -d '{
182
+ "githubToken": "ghp_xxx",
183
+ "force": false
184
+ }'
185
+ ```
186
+
187
+ > **Note:** `githubToken` is **required** for push operations. The token is used inline and **never stored on disk**.
188
+
168
189
  ## Development
169
190
 
170
191
  ```bash
package/dist/main.js CHANGED
@@ -188,13 +188,36 @@ var GitService = class {
188
188
  return result.stdout.trim();
189
189
  }
190
190
  /**
191
- * Fetch from remote
191
+ * Build authenticated URL (token is NEVER persisted)
192
192
  */
193
- async fetch(remote = "origin", cwd) {
193
+ buildAuthUrl(repoUrl, githubToken) {
194
+ if (!githubToken) return repoUrl;
195
+ const urlWithoutProtocol = repoUrl.replace(/^https?:\/\//, "");
196
+ return `https://x-access-token:${githubToken}@${urlWithoutProtocol}`;
197
+ }
198
+ /**
199
+ * Get remote URL and inject auth if token provided
200
+ */
201
+ async getAuthenticatedRemoteUrl(remote, cwd, githubToken) {
202
+ const url = await this.getRemoteUrl(remote, cwd);
203
+ if (!url) return null;
204
+ return githubToken ? this.buildAuthUrl(url, githubToken) : url;
205
+ }
206
+ /**
207
+ * Fetch from remote (token used inline, never persisted)
208
+ */
209
+ async fetch(remote = "origin", cwd, auth) {
210
+ if (auth?.githubToken) {
211
+ const authUrl = await this.getAuthenticatedRemoteUrl(remote, cwd || env.BASE_WORKSPACE_DIR, auth.githubToken);
212
+ if (authUrl) {
213
+ await this.execOrThrow(["fetch", authUrl], cwd);
214
+ return;
215
+ }
216
+ }
194
217
  await this.execOrThrow(["fetch", remote], cwd);
195
218
  }
196
219
  /**
197
- * Clone a repository
220
+ * Clone a repository (token used inline, never persisted)
198
221
  */
199
222
  async cloneRepo(repoUrl, targetDir, options) {
200
223
  const args = ["clone"];
@@ -206,7 +229,8 @@ var GitService = class {
206
229
  if (options?.branch) {
207
230
  args.push("--branch", options.branch);
208
231
  }
209
- args.push(repoUrl, targetDir);
232
+ const cloneUrl = options?.githubToken ? this.buildAuthUrl(repoUrl, options.githubToken) : repoUrl;
233
+ args.push(cloneUrl, targetDir);
210
234
  const parentDir = targetDir.split("/").slice(0, -1).join("/") || "/";
211
235
  await this.execOrThrow(args, parentDir);
212
236
  }
@@ -329,9 +353,18 @@ var GitService = class {
329
353
  return this.getHeadSha(cwd);
330
354
  }
331
355
  /**
332
- * Push
356
+ * Push (token used inline, never persisted)
333
357
  */
334
- async push(remote, branch, force = false, cwd) {
358
+ async push(remote, branch, force = false, cwd, auth) {
359
+ if (auth?.githubToken) {
360
+ const authUrl = await this.getAuthenticatedRemoteUrl(remote, cwd || env.BASE_WORKSPACE_DIR, auth.githubToken);
361
+ if (authUrl) {
362
+ const args2 = ["push", authUrl, branch];
363
+ if (force) args2.push("--force");
364
+ await this.execOrThrow(args2, cwd);
365
+ return;
366
+ }
367
+ }
335
368
  const args = ["push", remote, branch];
336
369
  if (force) args.push("--force");
337
370
  await this.execOrThrow(args, cwd);
@@ -417,7 +450,7 @@ import { Hono as Hono2 } from "hono";
417
450
  import { z } from "zod";
418
451
 
419
452
  // src/services/repo.service.ts
420
- import { mkdir as mkdir2, rm, stat as stat2, writeFile } from "fs/promises";
453
+ import { mkdir as mkdir2, readdir, rm, stat as stat2 } from "fs/promises";
421
454
  var RepoService = class {
422
455
  /**
423
456
  * Check if the repository is initialized
@@ -467,71 +500,113 @@ var RepoService = class {
467
500
  }
468
501
  /**
469
502
  * Initialize/clone the repository
503
+ * SECURITY: githubToken is used inline and NEVER persisted
504
+ *
505
+ * Smart init logic:
506
+ * - No repo exists → Clone it
507
+ * - Repo exists, same URL → Fetch latest (idempotent)
508
+ * - Repo exists, different URL, force=false → Error
509
+ * - Repo exists, different URL, force=true → Clean all worktrees → Delete repo → Re-clone
470
510
  */
471
511
  async initRepo(options) {
472
512
  const log = logger.child({ service: "repo", action: "init" });
473
513
  const repoRoot = env.BASE_WORKSPACE_DIR;
514
+ const auth = options.githubToken ? { githubToken: options.githubToken } : void 0;
515
+ const normalizeUrl = (url) => {
516
+ return url.replace(/^https:\/\/[^@]+@/, "https://").replace(/\.git$/, "").replace(/\/$/, "").toLowerCase();
517
+ };
518
+ const requestedUrl = normalizeUrl(options.repoUrl);
474
519
  log.info("Initializing repository", {
475
520
  repoUrl: options.repoUrl.replace(/ghp_[a-zA-Z0-9]+/, "ghp_***"),
476
521
  branch: options.branch,
477
- force: options.force
522
+ force: options.force,
523
+ hasToken: !!options.githubToken
478
524
  });
479
525
  const status = await this.getStatus();
480
- if (status.initialized && !options.force) {
481
- log.info("Repository already initialized");
482
- return {
483
- path: repoRoot,
484
- branch: status.branch || env.DEFAULT_BRANCH,
485
- headSha: status.headSha || "",
486
- remote: status.remote
487
- };
488
- }
489
- if (options.force && status.initialized) {
490
- log.info("Force flag set, removing existing repo");
526
+ if (status.initialized) {
527
+ const currentUrl = normalizeUrl(status.remote || "");
528
+ const isSameRepo = currentUrl === requestedUrl;
529
+ if (isSameRepo) {
530
+ log.info("Repository already initialized with same URL, fetching latest");
531
+ await gitService.fetch("origin", repoRoot, auth);
532
+ const targetBranch = options.branch || env.DEFAULT_BRANCH;
533
+ const currentBranch = status.branch || "";
534
+ if (targetBranch !== currentBranch) {
535
+ log.info("Switching to requested branch", { from: currentBranch, to: targetBranch });
536
+ const checkoutResult = await gitService.exec(["checkout", targetBranch], repoRoot);
537
+ if (checkoutResult.code !== 0) {
538
+ await gitService.exec(["checkout", "-b", targetBranch, `origin/${targetBranch}`], repoRoot);
539
+ }
540
+ }
541
+ const headSha2 = await gitService.getHeadSha(repoRoot);
542
+ const branch2 = await gitService.getCurrentBranch(repoRoot);
543
+ return { path: repoRoot, branch: branch2, headSha: headSha2, remote: status.remote };
544
+ }
545
+ if (!options.force) {
546
+ throw new Error(
547
+ `Repository already initialized with different URL. Current: ${currentUrl}, Requested: ${requestedUrl}. Use force=true to re-initialize (this will delete all worktrees).`
548
+ );
549
+ }
550
+ log.warn("Force re-init: cleaning all worktrees and repo");
551
+ await this.cleanAllWorktrees();
491
552
  await rm(repoRoot, { recursive: true, force: true });
492
553
  }
493
554
  const parentDir = repoRoot.split("/").slice(0, -1).join("/");
494
555
  await mkdir2(parentDir, { recursive: true });
495
556
  await mkdir2(env.TRIALS_WORKSPACE_DIR, { recursive: true });
496
- let cloneUrl = options.repoUrl;
497
- if (options.githubToken) {
498
- const urlWithoutProtocol = options.repoUrl.replace(/^https?:\/\//, "");
499
- cloneUrl = `https://x-access-token:${options.githubToken}@${urlWithoutProtocol}`;
500
- }
501
557
  const branch = options.branch || env.DEFAULT_BRANCH;
502
558
  log.info("Cloning repository", { branch });
503
- await gitService.cloneRepo(cloneUrl, repoRoot, {
559
+ await gitService.cloneRepo(options.repoUrl, repoRoot, {
504
560
  branch,
505
- blobless: true
561
+ blobless: true,
562
+ githubToken: options.githubToken
506
563
  });
507
564
  await gitService.exec(["config", "--local", "user.name", "origin-agent[bot]"], repoRoot);
508
565
  await gitService.exec(["config", "--local", "user.email", "origin-agent[bot]@users.noreply.github.com"], repoRoot);
509
566
  await gitService.exec(["config", "--local", "safe.directory", repoRoot], repoRoot);
510
567
  const cleanUrl = options.repoUrl.replace(/^https:\/\/[^@]+@/, "https://");
511
568
  await gitService.exec(["remote", "set-url", "origin", cleanUrl], repoRoot);
512
- if (options.githubToken) {
513
- await this.updateCredentials(options.githubToken);
514
- }
515
569
  const headSha = await gitService.getHeadSha(repoRoot);
516
570
  const remote = await gitService.getRemoteUrl("origin", repoRoot);
517
571
  log.info("Repository initialized", { branch, headSha });
518
572
  return { path: repoRoot, branch, headSha, remote };
519
573
  }
574
+ /**
575
+ * Clean all worktrees (used before force re-init)
576
+ */
577
+ async cleanAllWorktrees() {
578
+ const log = logger.child({ service: "repo", action: "cleanAllWorktrees" });
579
+ try {
580
+ const entries = await readdir(env.TRIALS_WORKSPACE_DIR, { withFileTypes: true });
581
+ for (const entry of entries) {
582
+ if (entry.isDirectory()) {
583
+ const worktreePath = `${env.TRIALS_WORKSPACE_DIR}/${entry.name}`;
584
+ log.info("Removing worktree", { path: worktreePath });
585
+ await rm(worktreePath, { recursive: true, force: true });
586
+ }
587
+ }
588
+ await gitService.pruneWorktrees(env.BASE_WORKSPACE_DIR).catch(() => {
589
+ });
590
+ log.info("All worktrees cleaned");
591
+ } catch (err) {
592
+ log.debug("No worktrees to clean", { error: err.message });
593
+ }
594
+ }
520
595
  /**
521
596
  * Update/pull the repository
597
+ * SECURITY: githubToken is used inline and NEVER persisted
522
598
  */
523
599
  async updateRepo(options) {
524
600
  const log = logger.child({ service: "repo", action: "update" });
525
601
  const repoRoot = env.BASE_WORKSPACE_DIR;
602
+ const auth = options?.githubToken ? { githubToken: options.githubToken } : void 0;
526
603
  const status = await this.getStatus();
527
604
  if (!status.initialized) {
528
605
  throw new Error("Repository not initialized");
529
606
  }
530
- if (options?.githubToken) {
531
- await this.updateCredentials(options.githubToken);
532
- }
607
+ log.info("Updating repository", { hasToken: !!options?.githubToken });
533
608
  log.info("Fetching from remote");
534
- await gitService.fetch("origin", repoRoot);
609
+ await gitService.fetch("origin", repoRoot, auth);
535
610
  if (options?.branch && options.branch !== status.branch) {
536
611
  log.info("Checking out branch", { branch: options.branch });
537
612
  await gitService.execOrThrow(["checkout", options.branch], repoRoot);
@@ -545,19 +620,6 @@ var RepoService = class {
545
620
  const remote = await gitService.getRemoteUrl("origin", repoRoot);
546
621
  return { path: repoRoot, branch, headSha, remote };
547
622
  }
548
- /**
549
- * Update git credentials
550
- */
551
- async updateCredentials(githubToken) {
552
- const log = logger.child({ service: "repo", action: "updateCredentials" });
553
- const repoRoot = env.BASE_WORKSPACE_DIR;
554
- await gitService.exec(["config", "--global", "credential.helper", "store --file=/tmp/.git-credentials"], repoRoot);
555
- await gitService.exec(["config", "--global", "core.askPass", ""], repoRoot);
556
- const credentialsContent = `https://x-access-token:${githubToken}@github.com
557
- `;
558
- await writeFile("/tmp/.git-credentials", credentialsContent, { mode: 384 });
559
- log.info("Credentials updated");
560
- }
561
623
  /**
562
624
  * List branches
563
625
  */
@@ -651,7 +713,7 @@ import { Hono as Hono3 } from "hono";
651
713
  import { z as z2 } from "zod";
652
714
 
653
715
  // src/services/worktree.service.ts
654
- import { mkdir as mkdir3, rm as rm2, stat as stat3, readdir } from "fs/promises";
716
+ import { mkdir as mkdir3, rm as rm2, stat as stat3, readdir as readdir2 } from "fs/promises";
655
717
  var WorktreeService = class {
656
718
  /**
657
719
  * Get the isolated workspace directory for a specific trial.
@@ -674,6 +736,7 @@ var WorktreeService = class {
674
736
  }
675
737
  /**
676
738
  * Reset or create a worktree for a trial
739
+ * SECURITY: githubToken is used inline and NEVER persisted
677
740
  */
678
741
  async resetWorktree(trialId, options) {
679
742
  const log = logger.child({ trialId, service: "worktree" });
@@ -681,11 +744,13 @@ var WorktreeService = class {
681
744
  const worktreePath = this.getWorktreePath(trialId, branchName);
682
745
  const baseBranch = options.baseBranch || env.DEFAULT_BRANCH;
683
746
  const baseRepoDir = env.BASE_WORKSPACE_DIR;
747
+ const auth = options.githubToken ? { githubToken: options.githubToken } : void 0;
684
748
  log.info("Starting worktree reset (v3 architecture)", {
685
749
  worktreePath,
686
750
  branchName,
687
751
  baseBranch,
688
- baseRepoDir
752
+ baseRepoDir,
753
+ hasToken: !!options.githubToken
689
754
  });
690
755
  await mkdir3(env.TRIALS_WORKSPACE_DIR, { recursive: true });
691
756
  try {
@@ -694,7 +759,7 @@ var WorktreeService = class {
694
759
  const gitFile = await stat3(`${worktreePath}/.git`).catch(() => null);
695
760
  if (gitFile) {
696
761
  log.info("Worktree already exists, fetching latest");
697
- await gitService.fetch("origin", worktreePath).catch(() => {
762
+ await gitService.fetch("origin", worktreePath, auth).catch(() => {
698
763
  });
699
764
  const headSha2 = await gitService.getHeadSha(worktreePath);
700
765
  return { worktreePath, branch: branchName, headSha: headSha2 };
@@ -703,7 +768,7 @@ var WorktreeService = class {
703
768
  } catch {
704
769
  }
705
770
  log.info("Fetching from remote");
706
- await gitService.fetch("origin", baseRepoDir);
771
+ await gitService.fetch("origin", baseRepoDir, auth);
707
772
  try {
708
773
  await gitService.removeWorktree(worktreePath, true, baseRepoDir);
709
774
  } catch {
@@ -848,12 +913,14 @@ var WorktreeService = class {
848
913
  }
849
914
  /**
850
915
  * Push branch
916
+ * SECURITY: githubToken is used inline and NEVER persisted
851
917
  */
852
- async pushBranch(trialId, remote = "origin", force = false, trialBranch) {
918
+ async pushBranch(trialId, remote = "origin", force = false, trialBranch, githubToken) {
853
919
  const branchName = trialBranch || this.getBranchName(trialId);
854
920
  const worktreePath = this.getWorktreePath(trialId, branchName);
921
+ const auth = githubToken ? { githubToken } : void 0;
855
922
  const branch = await gitService.getCurrentBranch(worktreePath);
856
- await gitService.push(remote, branch, force, worktreePath);
923
+ await gitService.push(remote, branch, force, worktreePath, auth);
857
924
  return { branch, pushed: true };
858
925
  }
859
926
  /**
@@ -865,7 +932,7 @@ var WorktreeService = class {
865
932
  const errors = [];
866
933
  const cutoffTime = Date.now() - env.CLEANUP_AFTER_HOURS * 60 * 60 * 1e3;
867
934
  try {
868
- const entries = await readdir(env.TRIALS_WORKSPACE_DIR, { withFileTypes: true });
935
+ const entries = await readdir2(env.TRIALS_WORKSPACE_DIR, { withFileTypes: true });
869
936
  for (const entry of entries) {
870
937
  if (!entry.isDirectory()) continue;
871
938
  const worktreePath = `${env.TRIALS_WORKSPACE_DIR}/${entry.name}`;
@@ -897,18 +964,23 @@ var worktree = new Hono3();
897
964
  var resetWorktreeSchema = z2.object({
898
965
  baseBranch: z2.string().default("main"),
899
966
  trialBranch: z2.string().optional(),
900
- force: z2.boolean().default(false)
967
+ force: z2.boolean().default(false),
968
+ githubToken: z2.string().optional()
969
+ // Required for private repos
901
970
  });
902
971
  var commitSchema = z2.object({
903
972
  message: z2.string().min(1),
904
973
  author: z2.object({
905
974
  name: z2.string(),
906
975
  email: z2.string().email()
907
- }).optional()
976
+ }).optional(),
977
+ trialBranch: z2.string().optional()
908
978
  });
909
979
  var pushSchema = z2.object({
910
980
  remote: z2.string().default("origin"),
911
- force: z2.boolean().default(false)
981
+ force: z2.boolean().default(false),
982
+ githubToken: z2.string().min(1, "GitHub token is required for push operations"),
983
+ trialBranch: z2.string().optional()
912
984
  });
913
985
  worktree.post("/trials/:trialId/worktree/reset", async (c) => {
914
986
  const trialId = c.req.param("trialId");
@@ -926,12 +998,14 @@ worktree.post("/trials/:trialId/worktree/reset", async (c) => {
926
998
  log.info("Creating/resetting worktree", {
927
999
  baseBranch: input.baseBranch,
928
1000
  trialBranch: input.trialBranch,
929
- force: input.force
1001
+ force: input.force,
1002
+ hasToken: !!input.githubToken
930
1003
  });
931
1004
  const result = await worktreeService.resetWorktree(trialId, {
932
1005
  baseBranch: input.baseBranch,
933
1006
  trialBranch: input.trialBranch,
934
- force: input.force
1007
+ force: input.force,
1008
+ githubToken: input.githubToken
935
1009
  });
936
1010
  return c.json({ success: true, data: result });
937
1011
  } catch (err) {
@@ -942,10 +1016,11 @@ worktree.post("/trials/:trialId/worktree/reset", async (c) => {
942
1016
  });
943
1017
  worktree.delete("/trials/:trialId/worktree", async (c) => {
944
1018
  const trialId = c.req.param("trialId");
945
- const log = logger.child({ route: "worktree/delete", trialId });
1019
+ const trialBranch = c.req.query("trialBranch");
1020
+ const log = logger.child({ route: "worktree/delete", trialId, trialBranch });
946
1021
  try {
947
1022
  log.info("Deleting worktree");
948
- await worktreeService.deleteWorktree(trialId);
1023
+ await worktreeService.deleteWorktree(trialId, trialBranch);
949
1024
  return c.json({ success: true, data: { deleted: true } });
950
1025
  } catch (err) {
951
1026
  const error = err;
@@ -955,9 +1030,10 @@ worktree.delete("/trials/:trialId/worktree", async (c) => {
955
1030
  });
956
1031
  worktree.get("/trials/:trialId/worktree/status", async (c) => {
957
1032
  const trialId = c.req.param("trialId");
958
- const log = logger.child({ route: "worktree/status", trialId });
1033
+ const trialBranch = c.req.query("trialBranch");
1034
+ const log = logger.child({ route: "worktree/status", trialId, trialBranch });
959
1035
  try {
960
- const status = await worktreeService.getWorktreeStatus(trialId);
1036
+ const status = await worktreeService.getWorktreeStatus(trialId, trialBranch);
961
1037
  return c.json({ success: true, data: status });
962
1038
  } catch (err) {
963
1039
  const error = err;
@@ -967,9 +1043,10 @@ worktree.get("/trials/:trialId/worktree/status", async (c) => {
967
1043
  });
968
1044
  worktree.get("/trials/:trialId/worktree/diff", async (c) => {
969
1045
  const trialId = c.req.param("trialId");
970
- const log = logger.child({ route: "worktree/diff", trialId });
1046
+ const trialBranch = c.req.query("trialBranch");
1047
+ const log = logger.child({ route: "worktree/diff", trialId, trialBranch });
971
1048
  try {
972
- const diff = await worktreeService.getWorktreeDiff(trialId);
1049
+ const diff = await worktreeService.getWorktreeDiff(trialId, trialBranch);
973
1050
  return c.json({ success: true, data: diff });
974
1051
  } catch (err) {
975
1052
  const error = err;
@@ -989,11 +1066,15 @@ worktree.post("/trials/:trialId/worktree/commit", async (c) => {
989
1066
  400
990
1067
  );
991
1068
  }
992
- log.info("Committing changes", { message: parsed.data.message.slice(0, 50) });
1069
+ log.info("Committing changes", {
1070
+ message: parsed.data.message.slice(0, 50),
1071
+ trialBranch: parsed.data.trialBranch
1072
+ });
993
1073
  const result = await worktreeService.commitChanges(
994
1074
  trialId,
995
1075
  parsed.data.message,
996
- parsed.data.author
1076
+ parsed.data.author,
1077
+ parsed.data.trialBranch
997
1078
  );
998
1079
  return c.json({ success: true, data: result });
999
1080
  } catch (err) {
@@ -1014,11 +1095,17 @@ worktree.post("/trials/:trialId/worktree/push", async (c) => {
1014
1095
  400
1015
1096
  );
1016
1097
  }
1017
- log.info("Pushing to remote", { remote: parsed.data.remote, force: parsed.data.force });
1098
+ log.info("Pushing to remote", {
1099
+ remote: parsed.data.remote,
1100
+ force: parsed.data.force,
1101
+ trialBranch: parsed.data.trialBranch
1102
+ });
1018
1103
  const result = await worktreeService.pushBranch(
1019
1104
  trialId,
1020
1105
  parsed.data.remote,
1021
- parsed.data.force
1106
+ parsed.data.force,
1107
+ parsed.data.trialBranch,
1108
+ parsed.data.githubToken
1022
1109
  );
1023
1110
  return c.json({ success: true, data: result });
1024
1111
  } catch (err) {
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@saeed42/worktree-worker",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Git worktree management service for AI agent trials",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",
7
7
  "bin": {
8
- "opencode-ai": "./dist/main.js"
8
+ "worktree-worker": "./dist/main.js"
9
9
  },
10
10
  "scripts": {
11
11
  "build": "tsup",