( session: PiSshSession, repoPath: string, maxDiffBytes: number )
| 105 | * missing, non-zero exit). |
| 106 | */ |
| 107 | export async function captureRepoChanges( |
| 108 | session: PiSshSession, |
| 109 | repoPath: string, |
| 110 | maxDiffBytes: number |
| 111 | ): Promise<{ changedFiles: string[]; diff: string }> { |
| 112 | const scoped = `cd '${escapeShellArg(repoPath)}'` |
| 113 | try { |
| 114 | const tracked = await executeSSHCommand( |
| 115 | session.client, |
| 116 | `${scoped} && git diff --name-only HEAD` |
| 117 | ) |
| 118 | const untracked = await executeSSHCommand( |
| 119 | session.client, |
| 120 | `${scoped} && git ls-files --others --exclude-standard` |
| 121 | ) |
| 122 | const fileSet = new Set<string>() |
| 123 | for (const result of [tracked, untracked]) { |
| 124 | if (result.exitCode !== 0) continue |
| 125 | for (const line of result.stdout.split('\n')) { |
| 126 | const file = line.trim() |
| 127 | if (file) fileSet.add(file) |
| 128 | } |
| 129 | } |
| 130 | const raw = await executeSSHCommand(session.client, `${scoped} && git diff HEAD`) |
| 131 | const out = raw.exitCode === 0 ? raw.stdout : '' |
| 132 | const diff = out.length > maxDiffBytes ? `${out.slice(0, maxDiffBytes)}\n[diff truncated]` : out |
| 133 | return { changedFiles: [...fileSet], diff } |
| 134 | } catch { |
| 135 | return { changedFiles: [], diff: '' } |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | /** Builds the SSH-backed `read`/`write`/`edit`/`bash` tools scoped to `repoPath`. */ |
| 140 | export function buildSshToolSpecs(session: PiSshSession, repoPath: string): PiToolSpec[] { |
no test coverage detected