@posthog/agent 1.25.0 → 1.26.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/dist/_virtual/_tslib.js +74 -0
- package/dist/_virtual/_tslib.js.map +1 -0
- package/dist/_virtual/index.js +2 -2
- package/dist/_virtual/index2.js +2 -2
- package/dist/_virtual/index8.js +2 -2
- package/dist/_virtual/index9.js +2 -2
- package/dist/node_modules/@agentclientprotocol/sdk/dist/acp.js +284 -3
- package/dist/node_modules/@agentclientprotocol/sdk/dist/acp.js.map +1 -1
- package/dist/node_modules/@agentclientprotocol/sdk/dist/schema.js +2 -1
- package/dist/node_modules/@agentclientprotocol/sdk/dist/schema.js.map +1 -1
- package/dist/node_modules/ajv/dist/ajv.js +1 -1
- package/dist/node_modules/ajv/dist/compile/codegen/index.js +1 -1
- package/dist/node_modules/ajv/dist/compile/validate/index.js +1 -1
- package/dist/node_modules/ajv/dist/vocabularies/discriminator/index.js +1 -1
- package/dist/node_modules/ajv-formats/dist/index.js +1 -1
- package/dist/package.json.js +1 -1
- package/dist/src/adapters/claude/claude.d.ts.map +1 -1
- package/dist/src/adapters/claude/claude.js +21 -5
- package/dist/src/adapters/claude/claude.js.map +1 -1
- package/dist/src/adapters/claude/mcp-server.js +105 -92
- package/dist/src/adapters/claude/mcp-server.js.map +1 -1
- package/dist/src/adapters/claude/tools.d.ts.map +1 -1
- package/dist/src/adapters/claude/tools.js +8 -1
- package/dist/src/adapters/claude/tools.js.map +1 -1
- package/dist/src/agent.d.ts +7 -1
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +151 -0
- package/dist/src/agent.js.map +1 -1
- package/dist/src/session-store.d.ts +7 -2
- package/dist/src/session-store.d.ts.map +1 -1
- package/dist/src/session-store.js +11 -0
- package/dist/src/session-store.js.map +1 -1
- package/dist/src/worktree-manager.d.ts.map +1 -1
- package/dist/src/worktree-manager.js +3 -5
- package/dist/src/worktree-manager.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/claude/claude.ts +21 -5
- package/src/adapters/claude/tools.ts +8 -1
- package/src/agent.ts +213 -1
- package/src/session-store.ts +18 -3
- package/src/worktree-manager.ts +4 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worktree-manager.js","sources":["../../src/worktree-manager.ts"],"sourcesContent":["import { exec, execFile } from \"node:child_process\";\nimport * as crypto from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport type { WorktreeInfo } from \"./types.js\";\nimport { Logger } from \"./utils/logger.js\";\n\nconst execAsync = promisify(exec);\nconst execFileAsync = promisify(execFile);\n\nexport interface WorktreeConfig {\n mainRepoPath: string;\n worktreeBasePath?: string;\n logger?: Logger;\n}\n\nconst ADJECTIVES = [\n \"swift\",\n \"bright\",\n \"calm\",\n \"bold\",\n \"gentle\",\n \"quick\",\n \"soft\",\n \"warm\",\n \"cool\",\n \"wise\",\n \"keen\",\n \"brave\",\n \"clear\",\n \"crisp\",\n \"deep\",\n \"fair\",\n \"fine\",\n \"free\",\n \"glad\",\n \"good\",\n \"grand\",\n \"great\",\n \"happy\",\n \"kind\",\n \"light\",\n \"lively\",\n \"neat\",\n \"nice\",\n \"plain\",\n \"proud\",\n \"pure\",\n \"rare\",\n \"rich\",\n \"safe\",\n \"sharp\",\n \"shy\",\n \"simple\",\n \"slim\",\n \"smart\",\n \"smooth\",\n \"solid\",\n \"sound\",\n \"spare\",\n \"stable\",\n \"steady\",\n \"still\",\n \"strong\",\n \"sure\",\n \"sweet\",\n \"tall\",\n \"agile\",\n \"ancient\",\n \"autumn\",\n \"azure\",\n \"cosmic\",\n \"daring\",\n \"dawn\",\n \"dusty\",\n \"eager\",\n \"early\",\n \"endless\",\n \"fading\",\n \"fallen\",\n \"famous\",\n \"feral\",\n \"fierce\",\n \"fleet\",\n \"foggy\",\n \"forest\",\n \"frozen\",\n \"gleeful\",\n \"golden\",\n \"hazy\",\n \"hidden\",\n \"hollow\",\n \"humble\",\n \"hushed\",\n \"icy\",\n \"inner\",\n \"late\",\n \"lazy\",\n \"little\",\n \"lone\",\n \"long\",\n \"lost\",\n \"lucky\",\n \"lunar\",\n \"magic\",\n \"mellow\",\n \"mighty\",\n \"misty\",\n \"modest\",\n \"mossy\",\n \"mystic\",\n \"nimble\",\n \"noble\",\n \"ocean\",\n \"outer\",\n \"pale\",\n \"paper\",\n \"patient\",\n \"peaceful\",\n \"phantom\",\n \"polite\",\n \"primal\",\n \"quiet\",\n \"rapid\",\n \"restless\",\n \"rising\",\n \"roaming\",\n \"rocky\",\n \"rustic\",\n \"sacred\",\n \"sandy\",\n \"secret\",\n \"serene\",\n \"shadow\",\n \"shining\",\n \"silent\",\n \"silky\",\n \"silver\",\n \"sleek\",\n \"snowy\",\n \"solar\",\n \"solemn\",\n \"spring\",\n \"starry\",\n \"stormy\",\n \"summer\",\n \"sunny\",\n \"tender\",\n \"thorny\",\n \"tiny\",\n \"tranquil\",\n \"twilight\",\n \"upward\",\n \"velvet\",\n \"vivid\",\n \"wandering\",\n \"wary\",\n \"wild\",\n \"windy\",\n \"winter\",\n \"wispy\",\n \"young\",\n];\n\nconst COLORS = [\n \"blue\",\n \"red\",\n \"green\",\n \"amber\",\n \"coral\",\n \"jade\",\n \"pearl\",\n \"ruby\",\n \"sage\",\n \"teal\",\n \"gold\",\n \"silver\",\n \"bronze\",\n \"copper\",\n \"ivory\",\n \"onyx\",\n \"opal\",\n \"rose\",\n \"slate\",\n \"violet\",\n \"aqua\",\n \"azure\",\n \"beige\",\n \"black\",\n \"brass\",\n \"brick\",\n \"brown\",\n \"cedar\",\n \"charcoal\",\n \"cherry\",\n \"chestnut\",\n \"chrome\",\n \"cider\",\n \"cinnamon\",\n \"citrus\",\n \"clay\",\n \"cloud\",\n \"cobalt\",\n \"cocoa\",\n \"cream\",\n \"crimson\",\n \"crystal\",\n \"cyan\",\n \"denim\",\n \"dusk\",\n \"ebony\",\n \"ember\",\n \"emerald\",\n \"fern\",\n \"flame\",\n \"flint\",\n \"forest\",\n \"frost\",\n \"garnet\",\n \"ginger\",\n \"glacier\",\n \"granite\",\n \"grape\",\n \"gray\",\n \"hazel\",\n \"honey\",\n \"indigo\",\n \"iron\",\n \"lapis\",\n \"lava\",\n \"lavender\",\n \"lemon\",\n \"lilac\",\n \"lime\",\n \"magenta\",\n \"mahogany\",\n \"maple\",\n \"marble\",\n \"maroon\",\n \"mauve\",\n \"midnight\",\n \"mint\",\n \"mocha\",\n \"moss\",\n \"mustard\",\n \"navy\",\n \"nickel\",\n \"obsidian\",\n \"ochre\",\n \"olive\",\n \"orange\",\n \"orchid\",\n \"peach\",\n \"pine\",\n \"pink\",\n \"plum\",\n \"porcelain\",\n \"purple\",\n \"quartz\",\n \"rust\",\n \"saffron\",\n \"salmon\",\n \"sand\",\n \"sapphire\",\n \"scarlet\",\n \"sepia\",\n \"shadow\",\n \"sienna\",\n \"smoke\",\n \"snow\",\n \"steel\",\n \"stone\",\n \"storm\",\n \"sunset\",\n \"tan\",\n \"tangerine\",\n \"taupe\",\n \"terra\",\n \"timber\",\n \"topaz\",\n \"turquoise\",\n \"umber\",\n \"vanilla\",\n \"walnut\",\n \"wheat\",\n \"white\",\n \"wine\",\n \"yellow\",\n];\n\nconst ANIMALS = [\n \"fox\",\n \"owl\",\n \"bear\",\n \"wolf\",\n \"hawk\",\n \"deer\",\n \"lynx\",\n \"otter\",\n \"raven\",\n \"falcon\",\n \"badger\",\n \"beaver\",\n \"bison\",\n \"bobcat\",\n \"crane\",\n \"eagle\",\n \"ferret\",\n \"finch\",\n \"gopher\",\n \"heron\",\n \"jaguar\",\n \"koala\",\n \"lemur\",\n \"marten\",\n \"mink\",\n \"moose\",\n \"newt\",\n \"ocelot\",\n \"osprey\",\n \"panda\",\n \"parrot\",\n \"pelican\",\n \"puma\",\n \"quail\",\n \"rabbit\",\n \"raccoon\",\n \"salmon\",\n \"seal\",\n \"shark\",\n \"shrew\",\n \"sloth\",\n \"snake\",\n \"spider\",\n \"squid\",\n \"stork\",\n \"swan\",\n \"tiger\",\n \"toucan\",\n \"turtle\",\n \"whale\",\n \"albatross\",\n \"ant\",\n \"antelope\",\n \"armadillo\",\n \"baboon\",\n \"bat\",\n \"bee\",\n \"beetle\",\n \"buffalo\",\n \"butterfly\",\n \"camel\",\n \"cardinal\",\n \"caribou\",\n \"catfish\",\n \"cheetah\",\n \"chipmunk\",\n \"cicada\",\n \"clam\",\n \"cobra\",\n \"condor\",\n \"corgi\",\n \"cougar\",\n \"coyote\",\n \"crab\",\n \"cricket\",\n \"crow\",\n \"dolphin\",\n \"donkey\",\n \"dove\",\n \"dragonfly\",\n \"duck\",\n \"eel\",\n \"egret\",\n \"elephant\",\n \"elk\",\n \"emu\",\n \"firefly\",\n \"flamingo\",\n \"frog\",\n \"gazelle\",\n \"gecko\",\n \"gibbon\",\n \"giraffe\",\n \"goat\",\n \"goose\",\n \"gorilla\",\n \"grasshopper\",\n \"grouse\",\n \"gull\",\n \"hamster\",\n \"hare\",\n \"hedgehog\",\n \"hippo\",\n \"hornet\",\n \"horse\",\n \"hound\",\n \"hummingbird\",\n \"hyena\",\n \"ibis\",\n \"iguana\",\n \"impala\",\n \"jackal\",\n \"jay\",\n \"jellyfish\",\n \"kangaroo\",\n \"kestrel\",\n \"kingfisher\",\n \"kite\",\n \"kiwi\",\n \"lark\",\n \"leopard\",\n \"lion\",\n \"lizard\",\n \"llama\",\n \"lobster\",\n \"loon\",\n \"macaw\",\n \"magpie\",\n \"mallard\",\n \"mammoth\",\n \"manatee\",\n \"mantis\",\n \"marlin\",\n \"marmot\",\n \"meerkat\",\n \"mockingbird\",\n \"mole\",\n \"mongoose\",\n \"monkey\",\n \"moth\",\n \"mouse\",\n \"mule\",\n \"narwhal\",\n \"nightingale\",\n \"octopus\",\n \"opossum\",\n \"orangutan\",\n \"oriole\",\n \"ostrich\",\n \"oyster\",\n \"panther\",\n \"peacock\",\n \"penguin\",\n \"pheasant\",\n \"pig\",\n \"pigeon\",\n \"pike\",\n \"piranha\",\n \"platypus\",\n \"pony\",\n \"porcupine\",\n \"porpoise\",\n \"python\",\n \"raven\",\n \"ray\",\n \"reindeer\",\n \"rhino\",\n \"robin\",\n \"rooster\",\n \"salamander\",\n \"sandpiper\",\n \"sardine\",\n \"scorpion\",\n \"seagull\",\n \"seahorse\",\n \"skunk\",\n \"snail\",\n \"sparrow\",\n \"squirrel\",\n \"starfish\",\n \"starling\",\n \"stingray\",\n \"swallow\",\n \"tapir\",\n \"termite\",\n \"tern\",\n \"toad\",\n \"trout\",\n \"tuna\",\n \"viper\",\n \"vulture\",\n \"walrus\",\n \"wasp\",\n \"weasel\",\n \"wombat\",\n \"woodpecker\",\n \"wren\",\n \"yak\",\n \"zebra\",\n];\n\nconst WORKTREE_FOLDER_NAME = \".array\";\n\nexport class WorktreeManager {\n private mainRepoPath: string;\n private worktreeBasePath: string | null;\n private repoName: string;\n private logger: Logger;\n\n constructor(config: WorktreeConfig) {\n this.mainRepoPath = config.mainRepoPath;\n this.worktreeBasePath = config.worktreeBasePath || null;\n this.repoName = path.basename(config.mainRepoPath);\n this.logger =\n config.logger ||\n new Logger({ debug: false, prefix: \"[WorktreeManager]\" });\n }\n\n private usesExternalPath(): boolean {\n return this.worktreeBasePath !== null;\n }\n\n private async runGitCommand(command: string): Promise<string> {\n try {\n const { stdout } = await execAsync(`git ${command}`, {\n cwd: this.mainRepoPath,\n });\n return stdout.trim();\n } catch (error) {\n throw new Error(`Git command failed: ${command}\\n${error}`);\n }\n }\n\n private randomElement<T>(array: T[]): T {\n return array[crypto.randomInt(array.length)];\n }\n\n generateWorktreeName(): string {\n const adjective = this.randomElement(ADJECTIVES);\n const color = this.randomElement(COLORS);\n const animal = this.randomElement(ANIMALS);\n return `${adjective}-${color}-${animal}`;\n }\n\n private getWorktreeFolderPath(): string {\n if (this.worktreeBasePath) {\n return path.join(this.worktreeBasePath, this.repoName);\n }\n return path.join(this.mainRepoPath, WORKTREE_FOLDER_NAME);\n }\n\n private getWorktreePath(name: string): string {\n return path.join(this.getWorktreeFolderPath(), name);\n }\n\n async worktreeExists(name: string): Promise<boolean> {\n const worktreePath = this.getWorktreePath(name);\n try {\n await fs.access(worktreePath);\n return true;\n } catch {\n return false;\n }\n }\n\n async ensureArrayDirIgnored(): Promise<void> {\n // Use .git/info/exclude instead of .gitignore to avoid modifying tracked files\n const excludePath = path.join(this.mainRepoPath, \".git\", \"info\", \"exclude\");\n const ignorePattern = `/${WORKTREE_FOLDER_NAME}/`;\n\n let content = \"\";\n try {\n content = await fs.readFile(excludePath, \"utf-8\");\n } catch {\n // File doesn't exist or .git/info doesn't exist\n }\n\n // Check if pattern is already present\n if (\n content.includes(`/${WORKTREE_FOLDER_NAME}/`) ||\n content.includes(`/${WORKTREE_FOLDER_NAME}`)\n ) {\n this.logger.debug(\"Exclude file already contains .array folder pattern\");\n return;\n }\n\n // Ensure .git/info directory exists\n const infoDir = path.join(this.mainRepoPath, \".git\", \"info\");\n await fs.mkdir(infoDir, { recursive: true });\n\n // Append the pattern\n const newContent = `${content.trimEnd()}\\n\\n# Array worktrees\\n${ignorePattern}\\n`;\n await fs.writeFile(excludePath, newContent);\n this.logger.info(\"Added .array folder to .git/info/exclude\");\n }\n\n private async generateUniqueWorktreeName(): Promise<string> {\n let name = this.generateWorktreeName();\n let attempts = 0;\n const maxAttempts = 100;\n\n while ((await this.worktreeExists(name)) && attempts < maxAttempts) {\n name = this.generateWorktreeName();\n attempts++;\n }\n\n if (attempts >= maxAttempts) {\n // Fallback: append timestamp\n name = `${this.generateWorktreeName()}-${Date.now()}`;\n }\n\n return name;\n }\n\n private async getDefaultBranch(): Promise<string> {\n try {\n const remoteBranch = await this.runGitCommand(\n \"symbolic-ref refs/remotes/origin/HEAD\",\n );\n return remoteBranch.replace(\"refs/remotes/origin/\", \"\");\n } catch {\n // Fallback: check if main exists, otherwise use master\n try {\n await this.runGitCommand(\"rev-parse --verify main\");\n return \"main\";\n } catch {\n try {\n await this.runGitCommand(\"rev-parse --verify master\");\n return \"master\";\n } catch {\n throw new Error(\n \"Cannot determine default branch. No main or master branch found.\",\n );\n }\n }\n }\n }\n\n async createWorktree(): Promise<WorktreeInfo> {\n // Only modify .git/info/exclude when using in-repo storage\n if (!this.usesExternalPath()) {\n await this.ensureArrayDirIgnored();\n }\n\n // Ensure the worktree folder exists when using external path\n if (this.usesExternalPath()) {\n const folderPath = this.getWorktreeFolderPath();\n await fs.mkdir(folderPath, { recursive: true });\n }\n\n // Generate unique worktree name\n const worktreeName = await this.generateUniqueWorktreeName();\n const worktreePath = this.getWorktreePath(worktreeName);\n const branchName = `posthog/${worktreeName}`;\n const baseBranch = await this.getDefaultBranch();\n\n this.logger.info(\"Creating worktree\", {\n worktreeName,\n worktreePath,\n branchName,\n baseBranch,\n external: this.usesExternalPath(),\n });\n\n // Create the worktree with a new branch\n if (this.usesExternalPath()) {\n // Use absolute path for external worktrees\n await this.runGitCommand(\n `worktree add -b \"${branchName}\" \"${worktreePath}\" \"${baseBranch}\"`,\n );\n } else {\n // Use relative path from repo root for in-repo worktrees\n const relativePath = `${WORKTREE_FOLDER_NAME}/${worktreeName}`;\n await this.runGitCommand(\n `worktree add -b \"${branchName}\" \"./${relativePath}\" \"${baseBranch}\"`,\n );\n }\n\n const createdAt = new Date().toISOString();\n\n this.logger.info(\"Worktree created successfully\", {\n worktreeName,\n worktreePath,\n branchName,\n });\n\n return {\n worktreePath,\n worktreeName,\n branchName,\n baseBranch,\n createdAt,\n };\n }\n\n async deleteWorktree(worktreePath: string): Promise<void> {\n this.logger.info(\"Deleting worktree\", { worktreePath });\n\n try {\n // First, try to remove the worktree via git using execFileAsync for safety\n await execFileAsync(\n \"git\",\n [\"worktree\", \"remove\", worktreePath, \"--force\"],\n {\n cwd: this.mainRepoPath,\n },\n );\n this.logger.info(\"Worktree deleted successfully\", { worktreePath });\n } catch (error) {\n this.logger.warn(\n \"Git worktree remove failed, attempting manual cleanup\",\n {\n worktreePath,\n error,\n },\n );\n\n // Manual cleanup if git command fails\n try {\n await fs.rm(worktreePath, { recursive: true, force: true });\n // Also prune the worktree list\n await this.runGitCommand(\"worktree prune\");\n this.logger.info(\"Worktree cleaned up manually\", { worktreePath });\n } catch (cleanupError) {\n this.logger.error(\"Failed to cleanup worktree\", {\n worktreePath,\n cleanupError,\n });\n throw cleanupError;\n }\n }\n }\n\n async getWorktreeInfo(worktreePath: string): Promise<WorktreeInfo | null> {\n try {\n // Parse the worktree list to find info about this worktree\n const output = await this.runGitCommand(\"worktree list --porcelain\");\n const worktrees = this.parseWorktreeList(output);\n\n const worktree = worktrees.find((w) => w.worktreePath === worktreePath);\n return worktree || null;\n } catch (error) {\n this.logger.debug(\"Failed to get worktree info\", { worktreePath, error });\n return null;\n }\n }\n\n async listWorktrees(): Promise<WorktreeInfo[]> {\n try {\n const output = await this.runGitCommand(\"worktree list --porcelain\");\n return this.parseWorktreeList(output);\n } catch (error) {\n this.logger.debug(\"Failed to list worktrees\", { error });\n return [];\n }\n }\n\n private parseWorktreeList(output: string): WorktreeInfo[] {\n const worktrees: WorktreeInfo[] = [];\n const entries = output.split(\"\\n\\n\").filter((e) => e.trim());\n const worktreeFolderPath = this.getWorktreeFolderPath();\n\n for (const entry of entries) {\n const lines = entry.split(\"\\n\");\n let worktreePath = \"\";\n let branchName = \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"worktree \")) {\n worktreePath = line.replace(\"worktree \", \"\");\n } else if (line.startsWith(\"branch refs/heads/\")) {\n branchName = line.replace(\"branch refs/heads/\", \"\");\n }\n }\n\n // Include worktrees that:\n // 1. Are in our worktree folder (external or in-repo)\n // 2. Have a posthog/ branch prefix (our naming convention)\n const isInWorktreeFolder = worktreePath?.startsWith(worktreeFolderPath);\n const isPosthogBranch = branchName?.startsWith(\"posthog/\");\n\n if (\n worktreePath &&\n branchName &&\n (isInWorktreeFolder || isPosthogBranch)\n ) {\n const worktreeName = path.basename(worktreePath);\n worktrees.push({\n worktreePath,\n worktreeName,\n branchName,\n baseBranch: \"\",\n createdAt: \"\",\n });\n }\n }\n\n return worktrees;\n }\n\n async isWorktree(repoPath: string): Promise<boolean> {\n try {\n const { stdout } = await execAsync(\n \"git rev-parse --is-inside-work-tree\",\n { cwd: repoPath },\n );\n if (stdout.trim() !== \"true\") {\n return false;\n }\n\n // Check if there's a .git file (worktrees have a .git file, not a .git directory)\n const gitPath = path.join(repoPath, \".git\");\n const stat = await fs.stat(gitPath);\n return stat.isFile(); // Worktrees have .git as a file, main repos have .git as a directory\n } catch {\n return false;\n }\n }\n\n async getMainRepoPathFromWorktree(\n worktreePath: string,\n ): Promise<string | null> {\n try {\n const gitFilePath = path.join(worktreePath, \".git\");\n const content = await fs.readFile(gitFilePath, \"utf-8\");\n\n // The .git file in a worktree contains: gitdir: /path/to/main/.git/worktrees/name\n const match = content.match(/gitdir:\\s*(.+)/);\n if (match) {\n const gitDir = match[1].trim();\n // Go up from .git/worktrees/name to get the main repo path\n // The gitdir points to something like: /main/repo/.git/worktrees/worktree-name\n const mainGitDir = path.resolve(gitDir, \"..\", \"..\", \"..\");\n return mainGitDir;\n }\n return null;\n } catch {\n return null;\n }\n }\n\n async cleanupOrphanedWorktrees(associatedWorktreePaths: string[]): Promise<{\n deleted: string[];\n errors: Array<{ path: string; error: string }>;\n }> {\n this.logger.info(\"Starting cleanup of orphaned worktrees\");\n\n const allWorktrees = await this.listWorktrees();\n const deleted: string[] = [];\n const errors: Array<{ path: string; error: string }> = [];\n\n const associatedPathsSet = new Set(\n associatedWorktreePaths.map((p) => path.resolve(p)),\n );\n\n for (const worktree of allWorktrees) {\n const resolvedPath = path.resolve(worktree.worktreePath);\n\n if (!associatedPathsSet.has(resolvedPath)) {\n this.logger.info(\"Found orphaned worktree\", {\n path: worktree.worktreePath,\n });\n\n try {\n await this.deleteWorktree(worktree.worktreePath);\n deleted.push(worktree.worktreePath);\n this.logger.info(\"Deleted orphaned worktree\", {\n path: worktree.worktreePath,\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n errors.push({\n path: worktree.worktreePath,\n error: errorMessage,\n });\n this.logger.error(\"Failed to delete orphaned worktree\", {\n path: worktree.worktreePath,\n error: errorMessage,\n });\n }\n }\n }\n\n this.logger.info(\"Cleanup completed\", {\n deleted: deleted.length,\n errors: errors.length,\n });\n\n return { deleted, errors };\n }\n}\n"],"names":[],"mappings":";;;;;;;AAQA,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC;AACjC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC;AAQzC,MAAM,UAAU,GAAG;IACjB,OAAO;IACP,QAAQ;IACR,MAAM;IACN,MAAM;IACN,QAAQ;IACR,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,MAAM;IACN,OAAO;IACP,QAAQ;IACR,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,KAAK;IACL,QAAQ;IACR,MAAM;IACN,OAAO;IACP,QAAQ;IACR,OAAO;IACP,OAAO;IACP,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;IACP,SAAS;IACT,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,OAAO;IACP,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,KAAK;IACL,OAAO;IACP,MAAM;IACN,MAAM;IACN,QAAQ;IACR,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,OAAO;IACP,OAAO;IACP,MAAM;IACN,OAAO;IACP,SAAS;IACT,UAAU;IACV,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,OAAO;IACP,UAAU;IACV,QAAQ;IACR,SAAS;IACT,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,OAAO;IACP,OAAO;IACP,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,UAAU;IACV,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,WAAW;IACX,MAAM;IACN,MAAM;IACN,OAAO;IACP,QAAQ;IACR,OAAO;IACP,OAAO;CACR;AAED,MAAM,MAAM,GAAG;IACb,MAAM;IACN,KAAK;IACL,OAAO;IACP,OAAO;IACP,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,QAAQ;IACR,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,UAAU;IACV,QAAQ;IACR,UAAU;IACV,QAAQ;IACR,OAAO;IACP,UAAU;IACV,QAAQ;IACR,MAAM;IACN,OAAO;IACP,QAAQ;IACR,OAAO;IACP,OAAO;IACP,SAAS;IACT,SAAS;IACT,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;IACP,OAAO;IACP,SAAS;IACT,MAAM;IACN,OAAO;IACP,OAAO;IACP,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,SAAS;IACT,OAAO;IACP,MAAM;IACN,OAAO;IACP,OAAO;IACP,QAAQ;IACR,MAAM;IACN,OAAO;IACP,MAAM;IACN,UAAU;IACV,OAAO;IACP,OAAO;IACP,MAAM;IACN,SAAS;IACT,UAAU;IACV,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,UAAU;IACV,MAAM;IACN,OAAO;IACP,MAAM;IACN,SAAS;IACT,MAAM;IACN,QAAQ;IACR,UAAU;IACV,OAAO;IACP,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,WAAW;IACX,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,SAAS;IACT,QAAQ;IACR,MAAM;IACN,UAAU;IACV,SAAS;IACT,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,QAAQ;IACR,KAAK;IACL,WAAW;IACX,OAAO;IACP,OAAO;IACP,QAAQ;IACR,OAAO;IACP,WAAW;IACX,OAAO;IACP,SAAS;IACT,QAAQ;IACR,OAAO;IACP,OAAO;IACP,MAAM;IACN,QAAQ;CACT;AAED,MAAM,OAAO,GAAG;IACd,KAAK;IACL,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,OAAO;IACP,OAAO;IACP,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,OAAO;IACP,OAAO;IACP,QAAQ;IACR,MAAM;IACN,OAAO;IACP,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,SAAS;IACT,MAAM;IACN,OAAO;IACP,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,QAAQ;IACR,OAAO;IACP,OAAO;IACP,MAAM;IACN,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,WAAW;IACX,KAAK;IACL,UAAU;IACV,WAAW;IACX,QAAQ;IACR,KAAK;IACL,KAAK;IACL,QAAQ;IACR,SAAS;IACT,WAAW;IACX,OAAO;IACP,UAAU;IACV,SAAS;IACT,SAAS;IACT,SAAS;IACT,UAAU;IACV,QAAQ;IACR,MAAM;IACN,OAAO;IACP,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,SAAS;IACT,MAAM;IACN,SAAS;IACT,QAAQ;IACR,MAAM;IACN,WAAW;IACX,MAAM;IACN,KAAK;IACL,OAAO;IACP,UAAU;IACV,KAAK;IACL,KAAK;IACL,SAAS;IACT,UAAU;IACV,MAAM;IACN,SAAS;IACT,OAAO;IACP,QAAQ;IACR,SAAS;IACT,MAAM;IACN,OAAO;IACP,SAAS;IACT,aAAa;IACb,QAAQ;IACR,MAAM;IACN,SAAS;IACT,MAAM;IACN,UAAU;IACV,OAAO;IACP,QAAQ;IACR,OAAO;IACP,OAAO;IACP,aAAa;IACb,OAAO;IACP,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,KAAK;IACL,WAAW;IACX,UAAU;IACV,SAAS;IACT,YAAY;IACZ,MAAM;IACN,MAAM;IACN,MAAM;IACN,SAAS;IACT,MAAM;IACN,QAAQ;IACR,OAAO;IACP,SAAS;IACT,MAAM;IACN,OAAO;IACP,QAAQ;IACR,SAAS;IACT,SAAS;IACT,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,aAAa;IACb,MAAM;IACN,UAAU;IACV,QAAQ;IACR,MAAM;IACN,OAAO;IACP,MAAM;IACN,SAAS;IACT,aAAa;IACb,SAAS;IACT,SAAS;IACT,WAAW;IACX,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,SAAS;IACT,SAAS;IACT,SAAS;IACT,UAAU;IACV,KAAK;IACL,QAAQ;IACR,MAAM;IACN,SAAS;IACT,UAAU;IACV,MAAM;IACN,WAAW;IACX,UAAU;IACV,QAAQ;IACR,OAAO;IACP,KAAK;IACL,UAAU;IACV,OAAO;IACP,OAAO;IACP,SAAS;IACT,YAAY;IACZ,WAAW;IACX,SAAS;IACT,UAAU;IACV,SAAS;IACT,UAAU;IACV,OAAO;IACP,OAAO;IACP,SAAS;IACT,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,SAAS;IACT,OAAO;IACP,SAAS;IACT,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;IACP,SAAS;IACT,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,YAAY;IACZ,MAAM;IACN,KAAK;IACL,OAAO;CACR;AAED,MAAM,oBAAoB,GAAG,QAAQ;MAExB,eAAe,CAAA;AAClB,IAAA,YAAY;AACZ,IAAA,gBAAgB;AAChB,IAAA,QAAQ;AACR,IAAA,MAAM;AAEd,IAAA,WAAA,CAAY,MAAsB,EAAA;AAChC,QAAA,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY;QACvC,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,IAAI,IAAI;QACvD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC;AAClD,QAAA,IAAI,CAAC,MAAM;AACT,YAAA,MAAM,CAAC,MAAM;AACb,gBAAA,IAAI,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC7D;IAEQ,gBAAgB,GAAA;AACtB,QAAA,OAAO,IAAI,CAAC,gBAAgB,KAAK,IAAI;IACvC;IAEQ,MAAM,aAAa,CAAC,OAAe,EAAA;AACzC,QAAA,IAAI;YACF,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,CAAA,IAAA,EAAO,OAAO,CAAA,CAAE,EAAE;gBACnD,GAAG,EAAE,IAAI,CAAC,YAAY;AACvB,aAAA,CAAC;AACF,YAAA,OAAO,MAAM,CAAC,IAAI,EAAE;QACtB;QAAE,OAAO,KAAK,EAAE;YACd,MAAM,IAAI,KAAK,CAAC,CAAA,oBAAA,EAAuB,OAAO,CAAA,EAAA,EAAK,KAAK,CAAA,CAAE,CAAC;QAC7D;IACF;AAEQ,IAAA,aAAa,CAAI,KAAU,EAAA;QACjC,OAAO,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9C;IAEA,oBAAoB,GAAA;QAClB,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC;QAChD,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;AAC1C,QAAA,OAAO,GAAG,SAAS,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,EAAI,MAAM,EAAE;IAC1C;IAEQ,qBAAqB,GAAA;AAC3B,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;AACzB,YAAA,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC;QACxD;QACA,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,oBAAoB,CAAC;IAC3D;AAEQ,IAAA,eAAe,CAAC,IAAY,EAAA;QAClC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,IAAI,CAAC;IACtD;IAEA,MAAM,cAAc,CAAC,IAAY,EAAA;QAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;AAC/C,QAAA,IAAI;AACF,YAAA,MAAM,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC;AAC7B,YAAA,OAAO,IAAI;QACb;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,KAAK;QACd;IACF;AAEA,IAAA,MAAM,qBAAqB,GAAA;;AAEzB,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;AAC3E,QAAA,MAAM,aAAa,GAAG,CAAA,CAAA,EAAI,oBAAoB,GAAG;QAEjD,IAAI,OAAO,GAAG,EAAE;AAChB,QAAA,IAAI;YACF,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;QACnD;AAAE,QAAA,MAAM;;QAER;;AAGA,QAAA,IACE,OAAO,CAAC,QAAQ,CAAC,CAAA,CAAA,EAAI,oBAAoB,GAAG,CAAC;YAC7C,OAAO,CAAC,QAAQ,CAAC,CAAA,CAAA,EAAI,oBAAoB,CAAA,CAAE,CAAC,EAC5C;AACA,YAAA,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,qDAAqD,CAAC;YACxE;QACF;;AAGA,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC;AAC5D,QAAA,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;;QAG5C,MAAM,UAAU,GAAG,CAAA,EAAG,OAAO,CAAC,OAAO,EAAE,CAAA,uBAAA,EAA0B,aAAa,CAAA,EAAA,CAAI;QAClF,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,UAAU,CAAC;AAC3C,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,0CAA0C,CAAC;IAC9D;AAEQ,IAAA,MAAM,0BAA0B,GAAA;AACtC,QAAA,IAAI,IAAI,GAAG,IAAI,CAAC,oBAAoB,EAAE;QACtC,IAAI,QAAQ,GAAG,CAAC;QAChB,MAAM,WAAW,GAAG,GAAG;AAEvB,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,QAAQ,GAAG,WAAW,EAAE;AAClE,YAAA,IAAI,GAAG,IAAI,CAAC,oBAAoB,EAAE;AAClC,YAAA,QAAQ,EAAE;QACZ;AAEA,QAAA,IAAI,QAAQ,IAAI,WAAW,EAAE;;AAE3B,YAAA,IAAI,GAAG,CAAA,EAAG,IAAI,CAAC,oBAAoB,EAAE,CAAA,CAAA,EAAI,IAAI,CAAC,GAAG,EAAE,CAAA,CAAE;QACvD;AAEA,QAAA,OAAO,IAAI;IACb;AAEQ,IAAA,MAAM,gBAAgB,GAAA;AAC5B,QAAA,IAAI;YACF,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,aAAa,CAC3C,uCAAuC,CACxC;YACD,OAAO,YAAY,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC;QACzD;AAAE,QAAA,MAAM;;AAEN,YAAA,IAAI;AACF,gBAAA,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;AACnD,gBAAA,OAAO,MAAM;YACf;AAAE,YAAA,MAAM;AACN,gBAAA,IAAI;AACF,oBAAA,MAAM,IAAI,CAAC,aAAa,CAAC,2BAA2B,CAAC;AACrD,oBAAA,OAAO,QAAQ;gBACjB;AAAE,gBAAA,MAAM;AACN,oBAAA,MAAM,IAAI,KAAK,CACb,kEAAkE,CACnE;gBACH;YACF;QACF;IACF;AAEA,IAAA,MAAM,cAAc,GAAA;;AAElB,QAAA,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE;AAC5B,YAAA,MAAM,IAAI,CAAC,qBAAqB,EAAE;QACpC;;AAGA,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE,EAAE;AAC3B,YAAA,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,EAAE;AAC/C,YAAA,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QACjD;;AAGA,QAAA,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,0BAA0B,EAAE;QAC5D,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC;AACvD,QAAA,MAAM,UAAU,GAAG,CAAA,QAAA,EAAW,YAAY,EAAE;AAC5C,QAAA,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE;AAEhD,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE;YACpC,YAAY;YACZ,YAAY;YACZ,UAAU;YACV,UAAU;AACV,YAAA,QAAQ,EAAE,IAAI,CAAC,gBAAgB,EAAE;AAClC,SAAA,CAAC;;AAGF,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE,EAAE;;AAE3B,YAAA,MAAM,IAAI,CAAC,aAAa,CACtB,CAAA,iBAAA,EAAoB,UAAU,CAAA,GAAA,EAAM,YAAY,CAAA,GAAA,EAAM,UAAU,CAAA,CAAA,CAAG,CACpE;QACH;aAAO;;AAEL,YAAA,MAAM,YAAY,GAAG,CAAA,EAAG,oBAAoB,CAAA,CAAA,EAAI,YAAY,EAAE;AAC9D,YAAA,MAAM,IAAI,CAAC,aAAa,CACtB,CAAA,iBAAA,EAAoB,UAAU,CAAA,KAAA,EAAQ,YAAY,CAAA,GAAA,EAAM,UAAU,CAAA,CAAA,CAAG,CACtE;QACH;QAEA,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AAE1C,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE;YAChD,YAAY;YACZ,YAAY;YACZ,UAAU;AACX,SAAA,CAAC;QAEF,OAAO;YACL,YAAY;YACZ,YAAY;YACZ,UAAU;YACV,UAAU;YACV,SAAS;SACV;IACH;IAEA,MAAM,cAAc,CAAC,YAAoB,EAAA;QACvC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,YAAY,EAAE,CAAC;AAEvD,QAAA,IAAI;;AAEF,YAAA,MAAM,aAAa,CACjB,KAAK,EACL,CAAC,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,CAAC,EAC/C;gBACE,GAAG,EAAE,IAAI,CAAC,YAAY;AACvB,aAAA,CACF;YACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE,EAAE,YAAY,EAAE,CAAC;QACrE;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,uDAAuD,EACvD;gBACE,YAAY;gBACZ,KAAK;AACN,aAAA,CACF;;AAGD,YAAA,IAAI;AACF,gBAAA,MAAM,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;;AAE3D,gBAAA,MAAM,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC;gBAC1C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,EAAE,YAAY,EAAE,CAAC;YACpE;YAAE,OAAO,YAAY,EAAE;AACrB,gBAAA,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE;oBAC9C,YAAY;oBACZ,YAAY;AACb,iBAAA,CAAC;AACF,gBAAA,MAAM,YAAY;YACpB;QACF;IACF;IAEA,MAAM,eAAe,CAAC,YAAoB,EAAA;AACxC,QAAA,IAAI;;YAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,2BAA2B,CAAC;YACpE,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC;AAEhD,YAAA,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,KAAK,YAAY,CAAC;YACvE,OAAO,QAAQ,IAAI,IAAI;QACzB;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;AACzE,YAAA,OAAO,IAAI;QACb;IACF;AAEA,IAAA,MAAM,aAAa,GAAA;AACjB,QAAA,IAAI;YACF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,2BAA2B,CAAC;AACpE,YAAA,OAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC;QACvC;QAAE,OAAO,KAAK,EAAE;YACd,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE,EAAE,KAAK,EAAE,CAAC;AACxD,YAAA,OAAO,EAAE;QACX;IACF;AAEQ,IAAA,iBAAiB,CAAC,MAAc,EAAA;QACtC,MAAM,SAAS,GAAmB,EAAE;QACpC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;AAC5D,QAAA,MAAM,kBAAkB,GAAG,IAAI,CAAC,qBAAqB,EAAE;AAEvD,QAAA,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE;YAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC;YAC/B,IAAI,YAAY,GAAG,EAAE;YACrB,IAAI,UAAU,GAAG,EAAE;AAEnB,YAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;AACxB,gBAAA,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE;oBAChC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC9C;AAAO,qBAAA,IAAI,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,EAAE;oBAChD,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC;gBACrD;YACF;;;;YAKA,MAAM,kBAAkB,GAAG,YAAY,EAAE,UAAU,CAAC,kBAAkB,CAAC;YACvE,MAAM,eAAe,GAAG,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC;AAE1D,YAAA,IACE,YAAY;gBACZ,UAAU;AACV,iBAAC,kBAAkB,IAAI,eAAe,CAAC,EACvC;gBACA,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;gBAChD,SAAS,CAAC,IAAI,CAAC;oBACb,YAAY;oBACZ,YAAY;oBACZ,UAAU;AACV,oBAAA,UAAU,EAAE,EAAE;AACd,oBAAA,SAAS,EAAE,EAAE;AACd,iBAAA,CAAC;YACJ;QACF;AAEA,QAAA,OAAO,SAAS;IAClB;IAEA,MAAM,UAAU,CAAC,QAAgB,EAAA;AAC/B,QAAA,IAAI;AACF,YAAA,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAChC,qCAAqC,EACrC,EAAE,GAAG,EAAE,QAAQ,EAAE,CAClB;AACD,YAAA,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,MAAM,EAAE;AAC5B,gBAAA,OAAO,KAAK;YACd;;YAGA,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC;YAC3C,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;AACnC,YAAA,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,KAAK;QACd;IACF;IAEA,MAAM,2BAA2B,CAC/B,YAAoB,EAAA;AAEpB,QAAA,IAAI;YACF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC;YACnD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;;YAGvD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC;YAC7C,IAAI,KAAK,EAAE;gBACT,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;;;AAG9B,gBAAA,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;AACzD,gBAAA,OAAO,UAAU;YACnB;AACA,YAAA,OAAO,IAAI;QACb;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,IAAI;QACb;IACF;IAEA,MAAM,wBAAwB,CAAC,uBAAiC,EAAA;AAI9D,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wCAAwC,CAAC;AAE1D,QAAA,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE;QAC/C,MAAM,OAAO,GAAa,EAAE;QAC5B,MAAM,MAAM,GAA2C,EAAE;QAEzD,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAChC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CACpD;AAED,QAAA,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE;YACnC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;YAExD,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE;AACzC,gBAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE;oBAC1C,IAAI,EAAE,QAAQ,CAAC,YAAY;AAC5B,iBAAA,CAAC;AAEF,gBAAA,IAAI;oBACF,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,YAAY,CAAC;AAChD,oBAAA,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;AACnC,oBAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,EAAE;wBAC5C,IAAI,EAAE,QAAQ,CAAC,YAAY;AAC5B,qBAAA,CAAC;gBACJ;gBAAE,OAAO,KAAK,EAAE;AACd,oBAAA,MAAM,YAAY,GAChB,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;oBACxD,MAAM,CAAC,IAAI,CAAC;wBACV,IAAI,EAAE,QAAQ,CAAC,YAAY;AAC3B,wBAAA,KAAK,EAAE,YAAY;AACpB,qBAAA,CAAC;AACF,oBAAA,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,EAAE;wBACtD,IAAI,EAAE,QAAQ,CAAC,YAAY;AAC3B,wBAAA,KAAK,EAAE,YAAY;AACpB,qBAAA,CAAC;gBACJ;YACF;QACF;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE;YACpC,OAAO,EAAE,OAAO,CAAC,MAAM;YACvB,MAAM,EAAE,MAAM,CAAC,MAAM;AACtB,SAAA,CAAC;AAEF,QAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE;IAC5B;AACD;;;;"}
|
|
1
|
+
{"version":3,"file":"worktree-manager.js","sources":["../../src/worktree-manager.ts"],"sourcesContent":["import { exec, execFile } from \"node:child_process\";\nimport * as crypto from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport type { WorktreeInfo } from \"./types.js\";\nimport { Logger } from \"./utils/logger.js\";\n\nconst execAsync = promisify(exec);\nconst execFileAsync = promisify(execFile);\n\nexport interface WorktreeConfig {\n mainRepoPath: string;\n worktreeBasePath?: string;\n logger?: Logger;\n}\n\nconst ADJECTIVES = [\n \"swift\",\n \"bright\",\n \"calm\",\n \"bold\",\n \"gentle\",\n \"quick\",\n \"soft\",\n \"warm\",\n \"cool\",\n \"wise\",\n \"keen\",\n \"brave\",\n \"clear\",\n \"crisp\",\n \"deep\",\n \"fair\",\n \"fine\",\n \"free\",\n \"glad\",\n \"good\",\n \"grand\",\n \"great\",\n \"happy\",\n \"kind\",\n \"light\",\n \"lively\",\n \"neat\",\n \"nice\",\n \"plain\",\n \"proud\",\n \"pure\",\n \"rare\",\n \"rich\",\n \"safe\",\n \"sharp\",\n \"shy\",\n \"simple\",\n \"slim\",\n \"smart\",\n \"smooth\",\n \"solid\",\n \"sound\",\n \"spare\",\n \"stable\",\n \"steady\",\n \"still\",\n \"strong\",\n \"sure\",\n \"sweet\",\n \"tall\",\n \"agile\",\n \"ancient\",\n \"autumn\",\n \"azure\",\n \"cosmic\",\n \"daring\",\n \"dawn\",\n \"dusty\",\n \"eager\",\n \"early\",\n \"endless\",\n \"fading\",\n \"fallen\",\n \"famous\",\n \"feral\",\n \"fierce\",\n \"fleet\",\n \"foggy\",\n \"forest\",\n \"frozen\",\n \"gleeful\",\n \"golden\",\n \"hazy\",\n \"hidden\",\n \"hollow\",\n \"humble\",\n \"hushed\",\n \"icy\",\n \"inner\",\n \"late\",\n \"lazy\",\n \"little\",\n \"lone\",\n \"long\",\n \"lost\",\n \"lucky\",\n \"lunar\",\n \"magic\",\n \"mellow\",\n \"mighty\",\n \"misty\",\n \"modest\",\n \"mossy\",\n \"mystic\",\n \"nimble\",\n \"noble\",\n \"ocean\",\n \"outer\",\n \"pale\",\n \"paper\",\n \"patient\",\n \"peaceful\",\n \"phantom\",\n \"polite\",\n \"primal\",\n \"quiet\",\n \"rapid\",\n \"restless\",\n \"rising\",\n \"roaming\",\n \"rocky\",\n \"rustic\",\n \"sacred\",\n \"sandy\",\n \"secret\",\n \"serene\",\n \"shadow\",\n \"shining\",\n \"silent\",\n \"silky\",\n \"silver\",\n \"sleek\",\n \"snowy\",\n \"solar\",\n \"solemn\",\n \"spring\",\n \"starry\",\n \"stormy\",\n \"summer\",\n \"sunny\",\n \"tender\",\n \"thorny\",\n \"tiny\",\n \"tranquil\",\n \"twilight\",\n \"upward\",\n \"velvet\",\n \"vivid\",\n \"wandering\",\n \"wary\",\n \"wild\",\n \"windy\",\n \"winter\",\n \"wispy\",\n \"young\",\n];\n\nconst COLORS = [\n \"blue\",\n \"red\",\n \"green\",\n \"amber\",\n \"coral\",\n \"jade\",\n \"pearl\",\n \"ruby\",\n \"sage\",\n \"teal\",\n \"gold\",\n \"silver\",\n \"bronze\",\n \"copper\",\n \"ivory\",\n \"onyx\",\n \"opal\",\n \"rose\",\n \"slate\",\n \"violet\",\n \"aqua\",\n \"azure\",\n \"beige\",\n \"black\",\n \"brass\",\n \"brick\",\n \"brown\",\n \"cedar\",\n \"charcoal\",\n \"cherry\",\n \"chestnut\",\n \"chrome\",\n \"cider\",\n \"cinnamon\",\n \"citrus\",\n \"clay\",\n \"cloud\",\n \"cobalt\",\n \"cocoa\",\n \"cream\",\n \"crimson\",\n \"crystal\",\n \"cyan\",\n \"denim\",\n \"dusk\",\n \"ebony\",\n \"ember\",\n \"emerald\",\n \"fern\",\n \"flame\",\n \"flint\",\n \"forest\",\n \"frost\",\n \"garnet\",\n \"ginger\",\n \"glacier\",\n \"granite\",\n \"grape\",\n \"gray\",\n \"hazel\",\n \"honey\",\n \"indigo\",\n \"iron\",\n \"lapis\",\n \"lava\",\n \"lavender\",\n \"lemon\",\n \"lilac\",\n \"lime\",\n \"magenta\",\n \"mahogany\",\n \"maple\",\n \"marble\",\n \"maroon\",\n \"mauve\",\n \"midnight\",\n \"mint\",\n \"mocha\",\n \"moss\",\n \"mustard\",\n \"navy\",\n \"nickel\",\n \"obsidian\",\n \"ochre\",\n \"olive\",\n \"orange\",\n \"orchid\",\n \"peach\",\n \"pine\",\n \"pink\",\n \"plum\",\n \"porcelain\",\n \"purple\",\n \"quartz\",\n \"rust\",\n \"saffron\",\n \"salmon\",\n \"sand\",\n \"sapphire\",\n \"scarlet\",\n \"sepia\",\n \"shadow\",\n \"sienna\",\n \"smoke\",\n \"snow\",\n \"steel\",\n \"stone\",\n \"storm\",\n \"sunset\",\n \"tan\",\n \"tangerine\",\n \"taupe\",\n \"terra\",\n \"timber\",\n \"topaz\",\n \"turquoise\",\n \"umber\",\n \"vanilla\",\n \"walnut\",\n \"wheat\",\n \"white\",\n \"wine\",\n \"yellow\",\n];\n\nconst ANIMALS = [\n \"fox\",\n \"owl\",\n \"bear\",\n \"wolf\",\n \"hawk\",\n \"deer\",\n \"lynx\",\n \"otter\",\n \"raven\",\n \"falcon\",\n \"badger\",\n \"beaver\",\n \"bison\",\n \"bobcat\",\n \"crane\",\n \"eagle\",\n \"ferret\",\n \"finch\",\n \"gopher\",\n \"heron\",\n \"jaguar\",\n \"koala\",\n \"lemur\",\n \"marten\",\n \"mink\",\n \"moose\",\n \"newt\",\n \"ocelot\",\n \"osprey\",\n \"panda\",\n \"parrot\",\n \"pelican\",\n \"puma\",\n \"quail\",\n \"rabbit\",\n \"raccoon\",\n \"salmon\",\n \"seal\",\n \"shark\",\n \"shrew\",\n \"sloth\",\n \"snake\",\n \"spider\",\n \"squid\",\n \"stork\",\n \"swan\",\n \"tiger\",\n \"toucan\",\n \"turtle\",\n \"whale\",\n \"albatross\",\n \"ant\",\n \"antelope\",\n \"armadillo\",\n \"baboon\",\n \"bat\",\n \"bee\",\n \"beetle\",\n \"buffalo\",\n \"butterfly\",\n \"camel\",\n \"cardinal\",\n \"caribou\",\n \"catfish\",\n \"cheetah\",\n \"chipmunk\",\n \"cicada\",\n \"clam\",\n \"cobra\",\n \"condor\",\n \"corgi\",\n \"cougar\",\n \"coyote\",\n \"crab\",\n \"cricket\",\n \"crow\",\n \"dolphin\",\n \"donkey\",\n \"dove\",\n \"dragonfly\",\n \"duck\",\n \"eel\",\n \"egret\",\n \"elephant\",\n \"elk\",\n \"emu\",\n \"firefly\",\n \"flamingo\",\n \"frog\",\n \"gazelle\",\n \"gecko\",\n \"gibbon\",\n \"giraffe\",\n \"goat\",\n \"goose\",\n \"gorilla\",\n \"grasshopper\",\n \"grouse\",\n \"gull\",\n \"hamster\",\n \"hare\",\n \"hedgehog\",\n \"hippo\",\n \"hornet\",\n \"horse\",\n \"hound\",\n \"hummingbird\",\n \"hyena\",\n \"ibis\",\n \"iguana\",\n \"impala\",\n \"jackal\",\n \"jay\",\n \"jellyfish\",\n \"kangaroo\",\n \"kestrel\",\n \"kingfisher\",\n \"kite\",\n \"kiwi\",\n \"lark\",\n \"leopard\",\n \"lion\",\n \"lizard\",\n \"llama\",\n \"lobster\",\n \"loon\",\n \"macaw\",\n \"magpie\",\n \"mallard\",\n \"mammoth\",\n \"manatee\",\n \"mantis\",\n \"marlin\",\n \"marmot\",\n \"meerkat\",\n \"mockingbird\",\n \"mole\",\n \"mongoose\",\n \"monkey\",\n \"moth\",\n \"mouse\",\n \"mule\",\n \"narwhal\",\n \"nightingale\",\n \"octopus\",\n \"opossum\",\n \"orangutan\",\n \"oriole\",\n \"ostrich\",\n \"oyster\",\n \"panther\",\n \"peacock\",\n \"penguin\",\n \"pheasant\",\n \"pig\",\n \"pigeon\",\n \"pike\",\n \"piranha\",\n \"platypus\",\n \"pony\",\n \"porcupine\",\n \"porpoise\",\n \"python\",\n \"raven\",\n \"ray\",\n \"reindeer\",\n \"rhino\",\n \"robin\",\n \"rooster\",\n \"salamander\",\n \"sandpiper\",\n \"sardine\",\n \"scorpion\",\n \"seagull\",\n \"seahorse\",\n \"skunk\",\n \"snail\",\n \"sparrow\",\n \"squirrel\",\n \"starfish\",\n \"starling\",\n \"stingray\",\n \"swallow\",\n \"tapir\",\n \"termite\",\n \"tern\",\n \"toad\",\n \"trout\",\n \"tuna\",\n \"viper\",\n \"vulture\",\n \"walrus\",\n \"wasp\",\n \"weasel\",\n \"wombat\",\n \"woodpecker\",\n \"wren\",\n \"yak\",\n \"zebra\",\n];\n\nconst WORKTREE_FOLDER_NAME = \".array\";\n\nexport class WorktreeManager {\n private mainRepoPath: string;\n private worktreeBasePath: string | null;\n private repoName: string;\n private logger: Logger;\n\n constructor(config: WorktreeConfig) {\n this.mainRepoPath = config.mainRepoPath;\n this.worktreeBasePath = config.worktreeBasePath || null;\n this.repoName = path.basename(config.mainRepoPath);\n this.logger =\n config.logger ||\n new Logger({ debug: false, prefix: \"[WorktreeManager]\" });\n }\n\n private usesExternalPath(): boolean {\n return this.worktreeBasePath !== null;\n }\n\n private async runGitCommand(command: string): Promise<string> {\n try {\n const { stdout } = await execAsync(`git ${command}`, {\n cwd: this.mainRepoPath,\n });\n return stdout.trim();\n } catch (error) {\n throw new Error(`Git command failed: ${command}\\n${error}`);\n }\n }\n\n private randomElement<T>(array: T[]): T {\n return array[crypto.randomInt(array.length)];\n }\n\n generateWorktreeName(): string {\n const adjective = this.randomElement(ADJECTIVES);\n const color = this.randomElement(COLORS);\n const animal = this.randomElement(ANIMALS);\n return `${adjective}-${color}-${animal}`;\n }\n\n private getWorktreeFolderPath(): string {\n if (this.worktreeBasePath) {\n return path.join(this.worktreeBasePath, this.repoName);\n }\n return path.join(this.mainRepoPath, WORKTREE_FOLDER_NAME);\n }\n\n private getWorktreePath(name: string): string {\n return path.join(this.getWorktreeFolderPath(), name);\n }\n\n async worktreeExists(name: string): Promise<boolean> {\n const worktreePath = this.getWorktreePath(name);\n try {\n await fs.access(worktreePath);\n return true;\n } catch {\n return false;\n }\n }\n\n async ensureArrayDirIgnored(): Promise<void> {\n // Use .git/info/exclude instead of .gitignore to avoid modifying tracked files\n const excludePath = path.join(this.mainRepoPath, \".git\", \"info\", \"exclude\");\n const ignorePattern = `/${WORKTREE_FOLDER_NAME}/`;\n\n let content = \"\";\n try {\n content = await fs.readFile(excludePath, \"utf-8\");\n } catch {\n // File doesn't exist or .git/info doesn't exist\n }\n\n // Check if pattern is already present\n if (\n content.includes(`/${WORKTREE_FOLDER_NAME}/`) ||\n content.includes(`/${WORKTREE_FOLDER_NAME}`)\n ) {\n this.logger.debug(\"Exclude file already contains .array folder pattern\");\n return;\n }\n\n // Ensure .git/info directory exists\n const infoDir = path.join(this.mainRepoPath, \".git\", \"info\");\n await fs.mkdir(infoDir, { recursive: true });\n\n // Append the pattern\n const newContent = `${content.trimEnd()}\\n\\n# Array worktrees\\n${ignorePattern}\\n`;\n await fs.writeFile(excludePath, newContent);\n this.logger.info(\"Added .array folder to .git/info/exclude\");\n }\n\n private async generateUniqueWorktreeName(): Promise<string> {\n let name = this.generateWorktreeName();\n let attempts = 0;\n const maxAttempts = 100;\n\n while ((await this.worktreeExists(name)) && attempts < maxAttempts) {\n name = this.generateWorktreeName();\n attempts++;\n }\n\n if (attempts >= maxAttempts) {\n // Fallback: append timestamp\n name = `${this.generateWorktreeName()}-${Date.now()}`;\n }\n\n return name;\n }\n\n private async getDefaultBranch(): Promise<string> {\n try {\n const remoteBranch = await this.runGitCommand(\n \"symbolic-ref refs/remotes/origin/HEAD\",\n );\n return remoteBranch.replace(\"refs/remotes/origin/\", \"\");\n } catch {\n // Fallback: check if main exists, otherwise use master\n try {\n await this.runGitCommand(\"rev-parse --verify main\");\n return \"main\";\n } catch {\n try {\n await this.runGitCommand(\"rev-parse --verify master\");\n return \"master\";\n } catch {\n throw new Error(\n \"Cannot determine default branch. No main or master branch found.\",\n );\n }\n }\n }\n }\n\n async createWorktree(): Promise<WorktreeInfo> {\n // Only modify .git/info/exclude when using in-repo storage\n if (!this.usesExternalPath()) {\n await this.ensureArrayDirIgnored();\n }\n\n // Ensure the worktree folder exists when using external path\n if (this.usesExternalPath()) {\n const folderPath = this.getWorktreeFolderPath();\n await fs.mkdir(folderPath, { recursive: true });\n }\n\n // Generate unique worktree name\n const worktreeName = await this.generateUniqueWorktreeName();\n const worktreePath = this.getWorktreePath(worktreeName);\n const branchName = `array/${worktreeName}`;\n const baseBranch = await this.getDefaultBranch();\n\n this.logger.info(\"Creating worktree\", {\n worktreeName,\n worktreePath,\n branchName,\n baseBranch,\n external: this.usesExternalPath(),\n });\n\n // Create the worktree with a new branch\n if (this.usesExternalPath()) {\n // Use absolute path for external worktrees\n await this.runGitCommand(\n `worktree add -b \"${branchName}\" \"${worktreePath}\" \"${baseBranch}\"`,\n );\n } else {\n // Use relative path from repo root for in-repo worktrees\n const relativePath = `${WORKTREE_FOLDER_NAME}/${worktreeName}`;\n await this.runGitCommand(\n `worktree add -b \"${branchName}\" \"./${relativePath}\" \"${baseBranch}\"`,\n );\n }\n\n const createdAt = new Date().toISOString();\n\n this.logger.info(\"Worktree created successfully\", {\n worktreeName,\n worktreePath,\n branchName,\n });\n\n return {\n worktreePath,\n worktreeName,\n branchName,\n baseBranch,\n createdAt,\n };\n }\n\n async deleteWorktree(worktreePath: string): Promise<void> {\n this.logger.info(\"Deleting worktree\", { worktreePath });\n\n try {\n // First, try to remove the worktree via git using execFileAsync for safety\n await execFileAsync(\n \"git\",\n [\"worktree\", \"remove\", worktreePath, \"--force\"],\n {\n cwd: this.mainRepoPath,\n },\n );\n this.logger.info(\"Worktree deleted successfully\", { worktreePath });\n } catch (error) {\n this.logger.warn(\n \"Git worktree remove failed, attempting manual cleanup\",\n {\n worktreePath,\n error,\n },\n );\n\n // Manual cleanup if git command fails\n try {\n await fs.rm(worktreePath, { recursive: true, force: true });\n // Also prune the worktree list\n await this.runGitCommand(\"worktree prune\");\n this.logger.info(\"Worktree cleaned up manually\", { worktreePath });\n } catch (cleanupError) {\n this.logger.error(\"Failed to cleanup worktree\", {\n worktreePath,\n cleanupError,\n });\n throw cleanupError;\n }\n }\n }\n\n async getWorktreeInfo(worktreePath: string): Promise<WorktreeInfo | null> {\n try {\n // Parse the worktree list to find info about this worktree\n const output = await this.runGitCommand(\"worktree list --porcelain\");\n const worktrees = this.parseWorktreeList(output);\n\n const worktree = worktrees.find((w) => w.worktreePath === worktreePath);\n return worktree || null;\n } catch (error) {\n this.logger.debug(\"Failed to get worktree info\", { worktreePath, error });\n return null;\n }\n }\n\n async listWorktrees(): Promise<WorktreeInfo[]> {\n try {\n const output = await this.runGitCommand(\"worktree list --porcelain\");\n return this.parseWorktreeList(output);\n } catch (error) {\n this.logger.debug(\"Failed to list worktrees\", { error });\n return [];\n }\n }\n\n private parseWorktreeList(output: string): WorktreeInfo[] {\n const worktrees: WorktreeInfo[] = [];\n const entries = output.split(\"\\n\\n\").filter((e) => e.trim());\n const worktreeFolderPath = this.getWorktreeFolderPath();\n\n for (const entry of entries) {\n const lines = entry.split(\"\\n\");\n let worktreePath = \"\";\n let branchName = \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"worktree \")) {\n worktreePath = line.replace(\"worktree \", \"\");\n } else if (line.startsWith(\"branch refs/heads/\")) {\n branchName = line.replace(\"branch refs/heads/\", \"\");\n }\n }\n\n // Include worktrees that:\n // 1. Are in our worktree folder (external or in-repo)\n // 2. Have a posthog/ branch prefix (our naming convention)\n const isInWorktreeFolder = worktreePath?.startsWith(worktreeFolderPath);\n const isArrayBranch =\n branchName?.startsWith(\"array/\") || branchName?.startsWith(\"posthog/\");\n\n if (worktreePath && branchName && (isInWorktreeFolder || isArrayBranch)) {\n const worktreeName = path.basename(worktreePath);\n worktrees.push({\n worktreePath,\n worktreeName,\n branchName,\n baseBranch: \"\",\n createdAt: \"\",\n });\n }\n }\n\n return worktrees;\n }\n\n async isWorktree(repoPath: string): Promise<boolean> {\n try {\n const { stdout } = await execAsync(\n \"git rev-parse --is-inside-work-tree\",\n { cwd: repoPath },\n );\n if (stdout.trim() !== \"true\") {\n return false;\n }\n\n // Check if there's a .git file (worktrees have a .git file, not a .git directory)\n const gitPath = path.join(repoPath, \".git\");\n const stat = await fs.stat(gitPath);\n return stat.isFile(); // Worktrees have .git as a file, main repos have .git as a directory\n } catch {\n return false;\n }\n }\n\n async getMainRepoPathFromWorktree(\n worktreePath: string,\n ): Promise<string | null> {\n try {\n const gitFilePath = path.join(worktreePath, \".git\");\n const content = await fs.readFile(gitFilePath, \"utf-8\");\n\n // The .git file in a worktree contains: gitdir: /path/to/main/.git/worktrees/name\n const match = content.match(/gitdir:\\s*(.+)/);\n if (match) {\n const gitDir = match[1].trim();\n // Go up from .git/worktrees/name to get the main repo path\n // The gitdir points to something like: /main/repo/.git/worktrees/worktree-name\n const mainGitDir = path.resolve(gitDir, \"..\", \"..\", \"..\");\n return mainGitDir;\n }\n return null;\n } catch {\n return null;\n }\n }\n\n async cleanupOrphanedWorktrees(associatedWorktreePaths: string[]): Promise<{\n deleted: string[];\n errors: Array<{ path: string; error: string }>;\n }> {\n this.logger.info(\"Starting cleanup of orphaned worktrees\");\n\n const allWorktrees = await this.listWorktrees();\n const deleted: string[] = [];\n const errors: Array<{ path: string; error: string }> = [];\n\n const associatedPathsSet = new Set(\n associatedWorktreePaths.map((p) => path.resolve(p)),\n );\n\n for (const worktree of allWorktrees) {\n const resolvedPath = path.resolve(worktree.worktreePath);\n\n if (!associatedPathsSet.has(resolvedPath)) {\n this.logger.info(\"Found orphaned worktree\", {\n path: worktree.worktreePath,\n });\n\n try {\n await this.deleteWorktree(worktree.worktreePath);\n deleted.push(worktree.worktreePath);\n this.logger.info(\"Deleted orphaned worktree\", {\n path: worktree.worktreePath,\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n errors.push({\n path: worktree.worktreePath,\n error: errorMessage,\n });\n this.logger.error(\"Failed to delete orphaned worktree\", {\n path: worktree.worktreePath,\n error: errorMessage,\n });\n }\n }\n }\n\n this.logger.info(\"Cleanup completed\", {\n deleted: deleted.length,\n errors: errors.length,\n });\n\n return { deleted, errors };\n }\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@posthog/agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.26.0",
|
|
4
4
|
"repository": "https://github.com/PostHog/array",
|
|
5
5
|
"description": "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -171,7 +171,7 @@ export class ClaudeAcpAgent implements Agent {
|
|
|
171
171
|
fileContentCache: { [key: string]: string };
|
|
172
172
|
backgroundTerminals: { [key: string]: BackgroundTerminal } = {};
|
|
173
173
|
clientCapabilities?: ClientCapabilities;
|
|
174
|
-
logger: Logger = new Logger({ debug:
|
|
174
|
+
logger: Logger = new Logger({ debug: true, prefix: "[ClaudeAcpAgent]" });
|
|
175
175
|
sessionStore?: SessionStore;
|
|
176
176
|
|
|
177
177
|
constructor(client: AgentSideConnection, sessionStore?: SessionStore) {
|
|
@@ -341,9 +341,13 @@ export class ClaudeAcpAgent implements Agent {
|
|
|
341
341
|
allowDangerouslySkipPermissions: !IS_ROOT,
|
|
342
342
|
permissionMode,
|
|
343
343
|
canUseTool: this.canUseTool(sessionId),
|
|
344
|
-
//
|
|
345
|
-
//
|
|
346
|
-
|
|
344
|
+
// Use "node" to resolve via PATH where a symlink to Electron exists.
|
|
345
|
+
// This avoids launching the Electron binary directly from the app bundle,
|
|
346
|
+
// which can cause dock icons to appear on macOS even with ELECTRON_RUN_AS_NODE.
|
|
347
|
+
executable: "node",
|
|
348
|
+
// Prevent spawned Electron processes from showing in dock/tray.
|
|
349
|
+
// Must merge with process.env since SDK replaces rather than merges.
|
|
350
|
+
env: { ...process.env, ELECTRON_RUN_AS_NODE: "1" },
|
|
347
351
|
...(process.env.CLAUDE_CODE_EXECUTABLE && {
|
|
348
352
|
pathToClaudeCodeExecutable: process.env.CLAUDE_CODE_EXECUTABLE,
|
|
349
353
|
}),
|
|
@@ -930,6 +934,7 @@ export class ClaudeAcpAgent implements Agent {
|
|
|
930
934
|
async resumeSession(
|
|
931
935
|
params: LoadSessionRequest,
|
|
932
936
|
): Promise<LoadSessionResponse> {
|
|
937
|
+
this.logger.info("[RESUME] Resuming session", { params });
|
|
933
938
|
const { sessionId } = params;
|
|
934
939
|
|
|
935
940
|
// Extract persistence config and SDK session ID from _meta
|
|
@@ -976,6 +981,11 @@ export class ClaudeAcpAgent implements Agent {
|
|
|
976
981
|
|
|
977
982
|
const permissionMode = "default";
|
|
978
983
|
|
|
984
|
+
this.logger.info("Resuming session", {
|
|
985
|
+
cwd: params.cwd,
|
|
986
|
+
sdkSessionId,
|
|
987
|
+
persistence,
|
|
988
|
+
});
|
|
979
989
|
const options: Options = {
|
|
980
990
|
cwd: params.cwd,
|
|
981
991
|
includePartialMessages: true,
|
|
@@ -986,7 +996,13 @@ export class ClaudeAcpAgent implements Agent {
|
|
|
986
996
|
permissionMode,
|
|
987
997
|
canUseTool: this.canUseTool(sessionId),
|
|
988
998
|
stderr: (err) => this.logger.error(err),
|
|
989
|
-
|
|
999
|
+
// Use "node" to resolve via PATH where a symlink to Electron exists.
|
|
1000
|
+
// This avoids launching the Electron binary directly from the app bundle,
|
|
1001
|
+
// which can cause dock icons to appear on macOS even with ELECTRON_RUN_AS_NODE.
|
|
1002
|
+
executable: "node",
|
|
1003
|
+
// Prevent spawned Electron processes from showing in dock/tray.
|
|
1004
|
+
// Must merge with process.env since SDK replaces rather than merges.
|
|
1005
|
+
env: { ...process.env, ELECTRON_RUN_AS_NODE: "1" },
|
|
990
1006
|
...(process.env.CLAUDE_CODE_EXECUTABLE && {
|
|
991
1007
|
pathToClaudeCodeExecutable: process.env.CLAUDE_CODE_EXECUTABLE,
|
|
992
1008
|
}),
|
|
@@ -153,7 +153,14 @@ export function toolInfoFromToolUse(
|
|
|
153
153
|
title: "Read File",
|
|
154
154
|
kind: "read",
|
|
155
155
|
content: [],
|
|
156
|
-
locations:
|
|
156
|
+
locations: input.file_path
|
|
157
|
+
? [
|
|
158
|
+
{
|
|
159
|
+
path: input.file_path,
|
|
160
|
+
line: input.offset ?? 0,
|
|
161
|
+
},
|
|
162
|
+
]
|
|
163
|
+
: [],
|
|
157
164
|
};
|
|
158
165
|
|
|
159
166
|
case "LS":
|
package/src/agent.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Client,
|
|
3
|
+
ClientSideConnection,
|
|
4
|
+
type ContentBlock,
|
|
5
|
+
ndJsonStream,
|
|
6
|
+
PROTOCOL_VERSION,
|
|
7
|
+
type RequestPermissionRequest,
|
|
8
|
+
type RequestPermissionResponse,
|
|
9
|
+
type SessionNotification,
|
|
10
|
+
} from "@agentclientprotocol/sdk";
|
|
1
11
|
import { POSTHOG_NOTIFICATIONS } from "./acp-extensions.js";
|
|
2
12
|
import {
|
|
3
13
|
createAcpConnection,
|
|
@@ -10,7 +20,13 @@ import { PromptBuilder } from "./prompt-builder.js";
|
|
|
10
20
|
import { SessionStore } from "./session-store.js";
|
|
11
21
|
import { TaskManager } from "./task-manager.js";
|
|
12
22
|
import { TemplateManager } from "./template-manager.js";
|
|
13
|
-
import type {
|
|
23
|
+
import type {
|
|
24
|
+
AgentConfig,
|
|
25
|
+
CanUseTool,
|
|
26
|
+
StoredNotification,
|
|
27
|
+
Task,
|
|
28
|
+
TaskExecutionOptions,
|
|
29
|
+
} from "./types.js";
|
|
14
30
|
import { Logger } from "./utils/logger.js";
|
|
15
31
|
import { TASK_WORKFLOW } from "./workflow/config.js";
|
|
16
32
|
import type { SendNotification, WorkflowRuntime } from "./workflow/types.js";
|
|
@@ -312,6 +328,29 @@ export class Agent {
|
|
|
312
328
|
return this.posthogAPI;
|
|
313
329
|
}
|
|
314
330
|
|
|
331
|
+
/**
|
|
332
|
+
* Send a notification to a cloud task run's S3 log.
|
|
333
|
+
* The cloud runner will pick up new notifications via interrupt polling.
|
|
334
|
+
*/
|
|
335
|
+
async sendNotification(
|
|
336
|
+
taskId: string,
|
|
337
|
+
runId: string,
|
|
338
|
+
notification: StoredNotification,
|
|
339
|
+
): Promise<void> {
|
|
340
|
+
if (!this.posthogAPI) {
|
|
341
|
+
throw new Error(
|
|
342
|
+
"PostHog API not configured. Cannot send notification to cloud task.",
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
await this.posthogAPI.appendTaskRunLog(taskId, runId, [notification]);
|
|
347
|
+
this.logger.debug("Notification sent to cloud task", {
|
|
348
|
+
taskId,
|
|
349
|
+
runId,
|
|
350
|
+
method: notification.notification.method,
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
|
|
315
354
|
async getTaskFiles(taskId: string): Promise<any[]> {
|
|
316
355
|
this.logger.debug("Getting task files", { taskId });
|
|
317
356
|
const files = await this.fileManager.getTaskFiles(taskId);
|
|
@@ -493,6 +532,179 @@ Generated by PostHog Agent`;
|
|
|
493
532
|
}
|
|
494
533
|
}
|
|
495
534
|
|
|
535
|
+
async runTaskCloud(
|
|
536
|
+
taskId: string,
|
|
537
|
+
taskRunId: string,
|
|
538
|
+
options: TaskExecutionOptions = {},
|
|
539
|
+
): Promise<void> {
|
|
540
|
+
await this._configureLlmGateway();
|
|
541
|
+
|
|
542
|
+
const task = await this.fetchTask(taskId);
|
|
543
|
+
const cwd = options.repositoryPath || this.workingDirectory;
|
|
544
|
+
const taskSlug = (task as any).slug || task.id;
|
|
545
|
+
|
|
546
|
+
this.currentRunId = taskRunId;
|
|
547
|
+
|
|
548
|
+
this.logger.info("Starting cloud task execution", {
|
|
549
|
+
taskId: task.id,
|
|
550
|
+
taskSlug,
|
|
551
|
+
taskRunId,
|
|
552
|
+
cwd,
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
if (!this.sessionStore) {
|
|
556
|
+
throw new Error(
|
|
557
|
+
"SessionStore required for cloud mode. Ensure PostHog API credentials are configured.",
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// Start session in SessionStore (updates task run status to in_progress)
|
|
562
|
+
const taskRun = await this.sessionStore.start(taskRunId, taskId, taskRunId);
|
|
563
|
+
this.logger.debug("Session started", {
|
|
564
|
+
taskRunId,
|
|
565
|
+
logUrl: taskRun?.log_url,
|
|
566
|
+
});
|
|
567
|
+
|
|
568
|
+
// Create internal ACP connection with S3 persistence
|
|
569
|
+
const acpConnection = createAcpConnection({
|
|
570
|
+
sessionStore: this.sessionStore,
|
|
571
|
+
sessionId: taskRunId,
|
|
572
|
+
taskId: task.id,
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
// Create client connection using the client-side streams
|
|
576
|
+
const clientStream = ndJsonStream(
|
|
577
|
+
acpConnection.clientStreams.writable as WritableStream<Uint8Array>,
|
|
578
|
+
acpConnection.clientStreams.readable as ReadableStream<Uint8Array>,
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
// Create auto-approving client for headless cloud mode
|
|
582
|
+
const cloudClient: Client = {
|
|
583
|
+
async requestPermission(params) {
|
|
584
|
+
const allowOption = params.options.find(
|
|
585
|
+
(o) => o.kind === "allow_once" || o.kind === "allow_always",
|
|
586
|
+
);
|
|
587
|
+
return {
|
|
588
|
+
outcome: {
|
|
589
|
+
outcome: "selected",
|
|
590
|
+
optionId: allowOption?.optionId ?? params.options[0].optionId,
|
|
591
|
+
},
|
|
592
|
+
};
|
|
593
|
+
},
|
|
594
|
+
async sessionUpdate(_params) {
|
|
595
|
+
// Notifications are already being persisted to S3 via tapped streams
|
|
596
|
+
},
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
const clientConnection = new ClientSideConnection(
|
|
600
|
+
(_agent) => cloudClient,
|
|
601
|
+
clientStream,
|
|
602
|
+
);
|
|
603
|
+
|
|
604
|
+
try {
|
|
605
|
+
// Initialize the connection
|
|
606
|
+
await clientConnection.initialize({
|
|
607
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
608
|
+
clientCapabilities: {},
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
// Create new session
|
|
612
|
+
await clientConnection.newSession({
|
|
613
|
+
cwd,
|
|
614
|
+
mcpServers: [],
|
|
615
|
+
_meta: { sessionId: taskRunId },
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
// Prepare git branch if not skipped
|
|
619
|
+
if (!options.skipGitBranch) {
|
|
620
|
+
const sendNotification: SendNotification = async (method, params) => {
|
|
621
|
+
this.logger.debug(`Notification: ${method}`, params);
|
|
622
|
+
await acpConnection.agentConnection.extNotification?.(method, params);
|
|
623
|
+
};
|
|
624
|
+
await this.prepareTaskBranch(taskSlug, true, sendNotification);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Build initial prompt from task description
|
|
628
|
+
const initialPrompt: ContentBlock[] = [
|
|
629
|
+
{
|
|
630
|
+
type: "text",
|
|
631
|
+
text: `# Task: ${task.title}\n\n${task.description}`,
|
|
632
|
+
},
|
|
633
|
+
];
|
|
634
|
+
|
|
635
|
+
// Track the last known log entry count for interrupt polling
|
|
636
|
+
let lastKnownEntryCount = 0;
|
|
637
|
+
let isPolling = true;
|
|
638
|
+
|
|
639
|
+
// Start interrupt polling in background
|
|
640
|
+
const pollForInterrupts = async () => {
|
|
641
|
+
while (isPolling) {
|
|
642
|
+
await new Promise((resolve) => setTimeout(resolve, 2000)); // Poll every 2 seconds
|
|
643
|
+
if (!isPolling) break;
|
|
644
|
+
|
|
645
|
+
try {
|
|
646
|
+
const newEntries = await this.sessionStore!.pollForNewEntries(
|
|
647
|
+
taskRunId,
|
|
648
|
+
lastKnownEntryCount,
|
|
649
|
+
);
|
|
650
|
+
|
|
651
|
+
for (const entry of newEntries) {
|
|
652
|
+
lastKnownEntryCount++;
|
|
653
|
+
// Look for user_message notifications
|
|
654
|
+
if (
|
|
655
|
+
entry.notification?.method === "sessionUpdate" &&
|
|
656
|
+
(entry.notification?.params as any)?.sessionUpdate ===
|
|
657
|
+
"user_message"
|
|
658
|
+
) {
|
|
659
|
+
const content = (entry.notification?.params as any)?.content;
|
|
660
|
+
if (content) {
|
|
661
|
+
this.logger.info("Processing user interrupt", { content });
|
|
662
|
+
// Send as new prompt - will be processed after current prompt completes
|
|
663
|
+
await clientConnection.prompt({
|
|
664
|
+
sessionId: taskRunId,
|
|
665
|
+
prompt: Array.isArray(content) ? content : [content],
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
} catch (err) {
|
|
671
|
+
this.logger.warn("Interrupt polling error", { error: err });
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
// Start polling in background (don't await)
|
|
677
|
+
const pollingPromise = pollForInterrupts();
|
|
678
|
+
|
|
679
|
+
// Send initial prompt and wait for completion
|
|
680
|
+
this.logger.info("Sending initial prompt to agent");
|
|
681
|
+
const result = await clientConnection.prompt({
|
|
682
|
+
sessionId: taskRunId,
|
|
683
|
+
prompt: initialPrompt,
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
// Stop interrupt polling
|
|
687
|
+
isPolling = false;
|
|
688
|
+
await pollingPromise;
|
|
689
|
+
|
|
690
|
+
this.logger.info("Task execution complete", {
|
|
691
|
+
taskId: task.id,
|
|
692
|
+
stopReason: result.stopReason,
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
await this.sessionStore.complete(taskRunId);
|
|
696
|
+
} catch (error) {
|
|
697
|
+
const errorMessage =
|
|
698
|
+
error instanceof Error ? error.message : String(error);
|
|
699
|
+
this.logger.error("Cloud task execution failed", {
|
|
700
|
+
taskId: task.id,
|
|
701
|
+
error: errorMessage,
|
|
702
|
+
});
|
|
703
|
+
await this.sessionStore.fail(taskRunId, errorMessage);
|
|
704
|
+
throw error;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
496
708
|
private async ensurePullRequest(
|
|
497
709
|
task: Task,
|
|
498
710
|
stepResults: Record<string, any>,
|
package/src/session-store.ts
CHANGED
|
@@ -90,7 +90,7 @@ export class SessionStore {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
/** Load raw JSON-RPC messages from S3 */
|
|
93
|
-
async load(logUrl: string): Promise<
|
|
93
|
+
async load(logUrl: string): Promise<StoredNotification[]> {
|
|
94
94
|
const response = await fetch(logUrl);
|
|
95
95
|
|
|
96
96
|
if (!response.ok) {
|
|
@@ -105,12 +105,27 @@ export class SessionStore {
|
|
|
105
105
|
.split("\n")
|
|
106
106
|
.map((line) => {
|
|
107
107
|
try {
|
|
108
|
-
return JSON.parse(line);
|
|
108
|
+
return JSON.parse(line) as StoredNotification;
|
|
109
109
|
} catch {
|
|
110
110
|
return null;
|
|
111
111
|
}
|
|
112
112
|
})
|
|
113
|
-
.filter((entry): entry is
|
|
113
|
+
.filter((entry): entry is StoredNotification => entry !== null);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Poll S3 for new entries since last check.
|
|
118
|
+
* Used for interrupt handling in cloud mode.
|
|
119
|
+
*/
|
|
120
|
+
async pollForNewEntries(
|
|
121
|
+
sessionId: string,
|
|
122
|
+
lastKnownCount: number,
|
|
123
|
+
): Promise<StoredNotification[]> {
|
|
124
|
+
const config = this.configs.get(sessionId);
|
|
125
|
+
if (!config?.logUrl) return [];
|
|
126
|
+
|
|
127
|
+
const entries = await this.load(config.logUrl);
|
|
128
|
+
return entries.slice(lastKnownCount);
|
|
114
129
|
}
|
|
115
130
|
|
|
116
131
|
/** Force flush pending entries */
|
package/src/worktree-manager.ts
CHANGED
|
@@ -643,7 +643,7 @@ export class WorktreeManager {
|
|
|
643
643
|
// Generate unique worktree name
|
|
644
644
|
const worktreeName = await this.generateUniqueWorktreeName();
|
|
645
645
|
const worktreePath = this.getWorktreePath(worktreeName);
|
|
646
|
-
const branchName = `
|
|
646
|
+
const branchName = `array/${worktreeName}`;
|
|
647
647
|
const baseBranch = await this.getDefaultBranch();
|
|
648
648
|
|
|
649
649
|
this.logger.info("Creating worktree", {
|
|
@@ -769,13 +769,10 @@ export class WorktreeManager {
|
|
|
769
769
|
// 1. Are in our worktree folder (external or in-repo)
|
|
770
770
|
// 2. Have a posthog/ branch prefix (our naming convention)
|
|
771
771
|
const isInWorktreeFolder = worktreePath?.startsWith(worktreeFolderPath);
|
|
772
|
-
const
|
|
772
|
+
const isArrayBranch =
|
|
773
|
+
branchName?.startsWith("array/") || branchName?.startsWith("posthog/");
|
|
773
774
|
|
|
774
|
-
if (
|
|
775
|
-
worktreePath &&
|
|
776
|
-
branchName &&
|
|
777
|
-
(isInWorktreeFolder || isPosthogBranch)
|
|
778
|
-
) {
|
|
775
|
+
if (worktreePath && branchName && (isInWorktreeFolder || isArrayBranch)) {
|
|
779
776
|
const worktreeName = path.basename(worktreePath);
|
|
780
777
|
worktrees.push({
|
|
781
778
|
worktreePath,
|