@saeed42/worktree-worker 1.5.0 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.js +164 -0
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -1664,6 +1664,170 @@ git.delete("/config", async (c) => {
1664
1664
  );
1665
1665
  }
1666
1666
  });
1667
+ var gitExecSchema = z3.object({
1668
+ args: z3.array(z3.string()).min(1, "At least one git argument is required"),
1669
+ cwd: z3.string().optional()
1670
+ });
1671
+ git.post("/exec", async (c) => {
1672
+ const log = logger.child({ route: "git/exec" });
1673
+ try {
1674
+ const body = await c.req.json().catch(() => ({}));
1675
+ const parsed = gitExecSchema.safeParse(body);
1676
+ if (!parsed.success) {
1677
+ return c.json(
1678
+ { success: false, error: { code: "VALIDATION_ERROR", message: parsed.error.message } },
1679
+ 400
1680
+ );
1681
+ }
1682
+ const { args, cwd } = parsed.data;
1683
+ const command = args[0];
1684
+ const allowedCommands = [
1685
+ "log",
1686
+ "show",
1687
+ "diff",
1688
+ "status",
1689
+ "branch",
1690
+ "rev-list",
1691
+ "rev-parse",
1692
+ "ls-files",
1693
+ "ls-tree",
1694
+ "cat-file",
1695
+ "describe",
1696
+ "shortlog",
1697
+ "blame",
1698
+ "stash",
1699
+ // Allow stash list
1700
+ "remote",
1701
+ // Allow remote -v
1702
+ "config"
1703
+ // Allow config --get
1704
+ ];
1705
+ const blockedCommands = [
1706
+ "push",
1707
+ "pull",
1708
+ "fetch",
1709
+ "clone",
1710
+ "reset",
1711
+ "checkout",
1712
+ "merge",
1713
+ "rebase",
1714
+ "cherry-pick",
1715
+ "revert",
1716
+ "rm",
1717
+ "mv",
1718
+ "clean",
1719
+ "gc",
1720
+ "prune",
1721
+ "filter-branch",
1722
+ "reflog"
1723
+ ];
1724
+ if (blockedCommands.includes(command)) {
1725
+ log.warn("Blocked dangerous git command", { command, args });
1726
+ return c.json(
1727
+ { success: false, error: { code: "FORBIDDEN", message: `Command '${command}' is not allowed` } },
1728
+ 403
1729
+ );
1730
+ }
1731
+ if (!allowedCommands.includes(command)) {
1732
+ log.warn("Unknown git command attempted", { command, args });
1733
+ return c.json(
1734
+ { success: false, error: { code: "FORBIDDEN", message: `Command '${command}' is not allowed` } },
1735
+ 403
1736
+ );
1737
+ }
1738
+ log.debug("Executing git command", { args: args.slice(0, 3), cwd });
1739
+ const result = await gitService.exec(args, cwd);
1740
+ return c.json({
1741
+ success: result.code === 0,
1742
+ data: {
1743
+ stdout: result.stdout,
1744
+ stderr: result.stderr,
1745
+ code: result.code
1746
+ }
1747
+ });
1748
+ } catch (err) {
1749
+ const error = err;
1750
+ log.error("Failed to execute git command", { error: error.message });
1751
+ return c.json(
1752
+ { success: false, error: { code: "INTERNAL_ERROR", message: error.message } },
1753
+ 500
1754
+ );
1755
+ }
1756
+ });
1757
+ var commitsQuerySchema = z3.object({
1758
+ cwd: z3.string().min(1, "Working directory is required"),
1759
+ baseBranch: z3.string().optional().default("main"),
1760
+ limit: z3.coerce.number().optional().default(50)
1761
+ });
1762
+ git.get("/commits", async (c) => {
1763
+ const log = logger.child({ route: "git/commits" });
1764
+ try {
1765
+ const query = c.req.query();
1766
+ const parsed = commitsQuerySchema.safeParse(query);
1767
+ if (!parsed.success) {
1768
+ return c.json(
1769
+ { success: false, error: { code: "VALIDATION_ERROR", message: parsed.error.message } },
1770
+ 400
1771
+ );
1772
+ }
1773
+ const { cwd, baseBranch, limit } = parsed.data;
1774
+ const branchResult = await gitService.exec(["rev-parse", "--abbrev-ref", "HEAD"], cwd);
1775
+ const currentBranch = branchResult.code === 0 ? branchResult.stdout.trim() : "unknown";
1776
+ const logResult = await gitService.exec([
1777
+ "log",
1778
+ `origin/${baseBranch}..HEAD`,
1779
+ `--format=%H|%h|%s|%an|%ae|%aI`,
1780
+ "--no-merges",
1781
+ `-n${limit}`
1782
+ ], cwd);
1783
+ let commits = [];
1784
+ if (logResult.code === 0 && logResult.stdout.trim()) {
1785
+ const lines = logResult.stdout.trim().split("\n").filter(Boolean);
1786
+ commits = lines.map((line) => {
1787
+ const [sha, shortSha, message, author, authorEmail, date] = line.split("|");
1788
+ return { sha, shortSha, message, author, authorEmail, date };
1789
+ });
1790
+ }
1791
+ let ahead = commits.length;
1792
+ let behind = 0;
1793
+ const revListResult = await gitService.exec([
1794
+ "rev-list",
1795
+ "--left-right",
1796
+ "--count",
1797
+ `origin/${baseBranch}...HEAD`
1798
+ ], cwd);
1799
+ if (revListResult.code === 0 && revListResult.stdout.trim()) {
1800
+ const parts = revListResult.stdout.trim().split(/\s+/);
1801
+ if (parts.length >= 2) {
1802
+ behind = parseInt(parts[0], 10) || 0;
1803
+ ahead = parseInt(parts[1], 10) || commits.length;
1804
+ }
1805
+ }
1806
+ log.debug("Fetched commits", {
1807
+ branch: currentBranch,
1808
+ count: commits.length,
1809
+ ahead,
1810
+ behind
1811
+ });
1812
+ return c.json({
1813
+ success: true,
1814
+ data: {
1815
+ commits,
1816
+ branch: currentBranch,
1817
+ baseBranch,
1818
+ ahead,
1819
+ behind
1820
+ }
1821
+ });
1822
+ } catch (err) {
1823
+ const error = err;
1824
+ log.error("Failed to get commits", { error: error.message });
1825
+ return c.json(
1826
+ { success: false, error: { code: "INTERNAL_ERROR", message: error.message } },
1827
+ 500
1828
+ );
1829
+ }
1830
+ });
1667
1831
 
1668
1832
  // src/main.ts
1669
1833
  var app = new Hono5();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saeed42/worktree-worker",
3
- "version": "1.5.0",
3
+ "version": "1.6.2",
4
4
  "description": "Git worktree management service for AI agent trials",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",