Function bodies 224 total
AgentManager.preflight method · typescript · L71-L76 (6 LOC)electron/agents/AgentManager.ts
async preflight(providerId: ProviderId = 'claude'): Promise<{
ok: boolean
claudePath: string | null
version: string | null
error: string | null
}> {AgentManager.create method · typescript · L90-L132 (43 LOC)electron/agents/AgentManager.ts
create(payload: CreateAgentPayload): AgentState {
const id = randomUUID().slice(0, 8)
const now = new Date().toISOString()
const state: AgentState = {
id,
name: payload.name,
projectDir: payload.projectDir,
provider: payload.provider,
model: payload.model,
reasoningEffort: payload.reasoningEffort,
yolo: payload.yolo,
isManager: payload.isManager ?? false,
sessionId: payload.resumeSessionId ?? null,
initialPrompt: payload.initialPrompt,
createdAt: now,
status: 'starting',
pid: null,
restartCount: 0,
startedAt: null
}
const managed: ManagedAgent = {
state,
pty: null,
outputBuffer: [],
killTimeout: null,
submitQueue: Promise.resolve(),
cols: DEFAULT_PTY_COLS,
rows: DEFAULT_PTY_ROWS,
source: 'hydra',
latestUserPrompt: payload.initialPrompt.trim() || null,
sessionSyncTimer: null,
sessionDiscoveryAttempts: 0,
AgentManager.importSessions method · typescript · L134-L181 (48 LOC)electron/agents/AgentManager.ts
importSessions(sessions: ClaudeSessionSummary[], defaultModel: ModelId, defaultProvider: ProviderId = 'claude'): number {
let imported = 0
for (const session of sessions) {
if (!session.sessionId || !session.projectPath) continue
const exists = Array.from(this.agents.values()).some(
(managed) => managed.state.sessionId === session.sessionId
)
if (exists) continue
const state: AgentState = {
id: this.buildImportedAgentId(session.sessionId),
name: this.buildImportedAgentName(session),
projectDir: session.projectPath,
provider: defaultProvider,
model: defaultModel,
yolo: false,
isManager: false,
sessionId: session.sessionId,
initialPrompt: '',
createdAt: session.createdAt || new Date().toISOString(),
status: 'idle',
pid: null,
restartCount: 0,
startedAt: null
}
this.agents.set(state.id, {
state,
pty:AgentManager.hydrateWorkspaceAgents method · typescript · L183-L229 (47 LOC)electron/agents/AgentManager.ts
hydrateWorkspaceAgents(agents: PersistedWorkspaceAgent[]): number {
let restored = 0
for (const persisted of agents) {
if (!persisted.id || !persisted.projectDir) continue
const id = this.buildHydraAgentId(persisted.id)
const alreadyHasSession = persisted.sessionId
? Array.from(this.agents.values()).some((managed) => managed.state.sessionId === persisted.sessionId)
: false
if (alreadyHasSession) continue
const state: AgentState = {
id,
name: persisted.name,
projectDir: persisted.projectDir,
provider: persisted.provider ?? 'claude',
model: persisted.model,
yolo: persisted.yolo,
isManager: persisted.isManager ?? false,
sessionId: persisted.sessionId,
initialPrompt: '',
createdAt: persisted.createdAt,
status: 'idle',
pid: null,
restartCount: 0,
startedAt: null
}
this.agents.set(id, {
state,
ptAgentManager.exportWorkspaceAgents method · typescript · L231-L245 (15 LOC)electron/agents/AgentManager.ts
exportWorkspaceAgents(): PersistedWorkspaceAgent[] {
return Array.from(this.agents.values())
.filter((managed) => managed.source === 'hydra')
.map((managed) => ({
id: managed.state.id,
name: managed.state.name,
projectDir: managed.state.projectDir,
provider: managed.state.provider,
model: managed.state.model,
yolo: managed.state.yolo,
isManager: managed.state.isManager,
sessionId: managed.state.sessionId,
createdAt: managed.state.createdAt
}))
}AgentManager.activeCount method · typescript · L247-L255 (9 LOC)electron/agents/AgentManager.ts
activeCount(): number {
let count = 0
for (const managed of this.agents.values()) {
if (managed.pty || managed.state.status === 'running' || managed.state.status === 'starting') {
count++
}
}
return count
}AgentManager.buildImportedAgentId method · typescript · L257-L267 (11 LOC)electron/agents/AgentManager.ts
private buildImportedAgentId(sessionId: string): string {
const shortId = sessionId.slice(0, 8)
const baseId = `sess-${shortId}`
if (!this.agents.has(baseId)) return baseId
let suffix = 2
while (this.agents.has(`${baseId}-${suffix}`)) {
suffix++
}
return `${baseId}-${suffix}`
}Repobility analyzer · published findings · https://repobility.com
AgentManager.generateName method · typescript · L269-L281 (13 LOC)electron/agents/AgentManager.ts
static generateName(prompt: string, projectDir: string): string {
const cleaned = prompt
.replace(/\s+/g, ' ')
.trim()
.replace(/^<[^>]+>/, '')
if (cleaned) {
return cleaned.length > 44 ? `${cleaned.slice(0, 44)}...` : cleaned
}
const projectName = basename(projectDir) || 'Agent'
return `${projectName} ${randomUUID().slice(0, 6)}`
}AgentManager.buildHydraAgentId method · typescript · L287-L295 (9 LOC)electron/agents/AgentManager.ts
private buildHydraAgentId(preferredId: string): string {
if (!this.agents.has(preferredId)) return preferredId
let suffix = 2
while (this.agents.has(`${preferredId}-${suffix}`)) {
suffix++
}
return `${preferredId}-${suffix}`
}AgentManager.killPtyProcess method · typescript · L302-L308 (7 LOC)electron/agents/AgentManager.ts
private killPtyProcess(pty: IPty, force: boolean): void {
if (process.platform === 'win32') {
pty.kill()
return
}
pty.kill(force ? 'SIGKILL' : 'SIGTERM')
}AgentManager.spawnProcess method · typescript · L310-L375 (66 LOC)electron/agents/AgentManager.ts
private spawnProcess(managed: ManagedAgent): void {
const provider = getProvider(managed.state.provider)
const cmd = this.providerPaths.get(managed.state.provider) || provider.command
const args = this.buildArgs(managed.state)
try {
const pty = ptySpawn(cmd, args, {
name: 'xterm-256color',
cols: managed.cols,
rows: managed.rows,
cwd: managed.state.projectDir,
env: {
...process.env,
TERM: 'xterm-256color',
FORCE_COLOR: '1'
}
})
managed.pty = pty
managed.state.pid = pty.pid
managed.state.startedAt = new Date().toISOString()
this.updateStatus(managed.state.id, 'running')
this.startSessionDiscovery(managed)
pty.onData((data: string) => {
this.captureSessionIdFromOutput(managed, data)
// Buffer output
const lines = data.split('\n')
managed.outputBuffer.push(...lines)
if (managed.outputBuffer.length > MAX_BAgentManager.updateStatus method · typescript · L378-L387 (10 LOC)electron/agents/AgentManager.ts
private updateStatus(agentId: string, status: AgentStatus): void {
const managed = this.agents.get(agentId)
if (!managed) return
managed.state.status = status
this.emit('status', {
agentId,
status,
sessionId: managed.state.sessionId
})
}AgentManager.updateSessionId method · typescript · L389-L398 (10 LOC)electron/agents/AgentManager.ts
private updateSessionId(managed: ManagedAgent, sessionId: string): void {
const normalized = sessionId.trim()
if (!normalized || managed.state.sessionId === normalized) return
managed.state.sessionId = normalized
this.emit('status', {
agentId: managed.state.id,
status: managed.state.status,
sessionId: managed.state.sessionId
})
}AgentManager.captureSessionIdFromOutput method · typescript · L400-L421 (22 LOC)electron/agents/AgentManager.ts
private captureSessionIdFromOutput(managed: ManagedAgent, data: string): void {
if (managed.state.sessionId) return
const provider = getProvider(managed.state.provider)
// Try provider-specific session ID regex
if (provider.sessionIdRegex) {
const directMatch = data.match(provider.sessionIdRegex)
if (directMatch?.[1]) {
this.updateSessionId(managed, directMatch[1])
return
}
}
// Fallback: generic UUID pattern
const uuidMatch = data.match(
/\b[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\b/i
)
if (uuidMatch?.[0]) {
this.updateSessionId(managed, uuidMatch[0])
}
}AgentManager.startSessionDiscovery method · typescript · L423-L432 (10 LOC)electron/agents/AgentManager.ts
private startSessionDiscovery(managed: ManagedAgent): void {
const provider = getProvider(managed.state.provider)
if (!provider.supportsResume) return
if (managed.state.sessionId || managed.source !== 'hydra') return
this.stopSessionDiscovery(managed)
this.probeSessionIdFromCatalog(managed, { forceRefresh: true })
if (!managed.state.sessionId) {
this.scheduleSessionDiscovery(managed)
}
}Repobility — same analyzer, your code, free for public repos · /scan/
AgentManager.stopSessionDiscovery method · typescript · L434-L439 (6 LOC)electron/agents/AgentManager.ts
private stopSessionDiscovery(managed: ManagedAgent): void {
if (!managed.sessionSyncTimer) return
clearTimeout(managed.sessionSyncTimer)
managed.sessionSyncTimer = null
managed.sessionDiscoveryAttempts = 0
}AgentManager.probeSessionIdFromCatalog method · typescript · L463-L511 (49 LOC)electron/agents/AgentManager.ts
private probeSessionIdFromCatalog(managed: ManagedAgent, options: { forceRefresh?: boolean } = {}): void {
if (managed.state.sessionId || managed.source !== 'hydra') return
if (!managed.state.projectDir) return
try {
const sessions = this.sessionCatalog.listSessions({
limit: 120,
projectPathPrefix: managed.state.projectDir,
forceRefresh: options.forceRefresh === true
})
if (sessions.length === 0) return
const usedSessionIds = new Set(
Array.from(this.agents.values())
.map((agent) => agent.state.sessionId)
.filter((value): value is string => !!value)
)
const startedAtMs = Date.parse(managed.state.startedAt ?? managed.state.createdAt)
const promptHint = this.normalizePromptHint(managed.latestUserPrompt)
const candidates = sessions.filter((session) => !usedSessionIds.has(session.sessionId))
if (candidates.length === 0) return
const hinted = promptHint
AgentManager.normalizePromptHint method · typescript · L513-L520 (8 LOC)electron/agents/AgentManager.ts
private normalizePromptHint(input: string | null): string {
if (!input) return ''
return input
.replace(/\s+/g, ' ')
.trim()
.toLowerCase()
.slice(0, SESSION_HINT_MAX_LENGTH)
}AgentManager.remove method · typescript · L546-L556 (11 LOC)electron/agents/AgentManager.ts
remove(agentId: string): boolean {
const managed = this.agents.get(agentId)
if (!managed) return false
this.stopSessionDiscovery(managed)
this.kill(agentId)
if (managed.killTimeout) {
clearTimeout(managed.killTimeout)
managed.killTimeout = null
}
return this.agents.delete(agentId)
}AgentManager.clearTimeout method · typescript · L552-L582 (31 LOC)electron/agents/AgentManager.ts
clearTimeout(managed.killTimeout)
managed.killTimeout = null
}
return this.agents.delete(agentId)
}
restart(agentId: string): AgentState | null {
const managed = this.agents.get(agentId)
if (!managed) return null
// Kill existing process
if (managed.pty) {
try {
this.killPtyProcess(managed.pty, true)
} catch {
// Already dead
}
managed.pty = null
}
managed.state.restartCount++
managed.state.status = 'starting'
managed.outputBuffer = []
managed.submitQueue = Promise.resolve()
managed.notifiedIdle = false
managed.lastOutputAt = 0
this.stopSessionDiscovery(managed)
this.spawnProcess(managed)
return { ...managed.state }
}AgentManager.toggleYolo method · typescript · L584-L591 (8 LOC)electron/agents/AgentManager.ts
toggleYolo(agentId: string, yolo: boolean): AgentState | null {
const managed = this.agents.get(agentId)
if (!managed) return null
managed.state.yolo = yolo
// Restart with new flag, preserving session
return this.restart(agentId)
}AgentManager.setTimeout method · typescript · L611-L624 (14 LOC)electron/agents/AgentManager.ts
setTimeout(resolve, INPUT_SUBMIT_DELAY_MS)
})
if (managed.pty !== pty) return
pty.write('\r')
})
return true
}
private ensureProcess(managed: ManagedAgent): boolean {
if (managed.pty) return true
this.spawnProcess(managed)
return !!managed.pty
}AgentManager.setSessionId method · typescript · L674-L682 (9 LOC)electron/agents/AgentManager.ts
setSessionId(agentId: string, sessionId: string): void {
const managed = this.agents.get(agentId)
if (managed) {
this.updateSessionId(managed, sessionId)
if (managed.state.sessionId) {
this.stopSessionDiscovery(managed)
}
}
}Same scanner, your repo: https://repobility.com — Repobility
AgentManager.resize method · typescript · L684-L695 (12 LOC)electron/agents/AgentManager.ts
resize(agentId: string, cols: number, rows: number): void {
const managed = this.agents.get(agentId)
if (!managed) return
if (cols < 2 || rows < 2) return
managed.cols = cols
managed.rows = rows
if (managed.pty) {
managed.pty.resize(cols, rows)
}
}AgentManager.killAll method · typescript · L697-L719 (23 LOC)electron/agents/AgentManager.ts
killAll(): void {
if (this.activityPollInterval) {
clearInterval(this.activityPollInterval)
this.activityPollInterval = null
}
for (const [id] of this.agents) {
this.kill(id)
}
// Force kill stragglers after timeout
setTimeout(() => {
for (const [, managed] of this.agents) {
this.stopSessionDiscovery(managed)
if (managed.pty) {
try {
this.killPtyProcess(managed.pty, true)
} catch {
// Already dead
}
}
}
}, GRACEFUL_KILL_TIMEOUT + 1000)
}AgentManager.clearInterval method · typescript · L699-L704 (6 LOC)electron/agents/AgentManager.ts
clearInterval(this.activityPollInterval)
this.activityPollInterval = null
}
for (const [id] of this.agents) {
this.kill(id)
}AgentManager.setTimeout method · typescript · L707-L718 (12 LOC)electron/agents/AgentManager.ts
setTimeout(() => {
for (const [, managed] of this.agents) {
this.stopSessionDiscovery(managed)
if (managed.pty) {
try {
this.killPtyProcess(managed.pty, true)
} catch {
// Already dead
}
}
}
}, GRACEFUL_KILL_TIMEOUT + 1000)AgentManager.getProjectDirs method · typescript · L721-L727 (7 LOC)electron/agents/AgentManager.ts
getProjectDirs(): string[] {
const dirs = new Set<string>()
for (const [, managed] of this.agents) {
dirs.add(managed.state.projectDir)
}
return Array.from(dirs)
}resolveCommandPath function · typescript · L34-L46 (13 LOC)electron/agents/providers.ts
function resolveCommandPath(command: string): string | null {
const locator = process.platform === 'win32' ? 'where' : 'which'
try {
const output = execFileSync(locator, [command], { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] })
const firstLine = output
.split(/\r?\n/)
.map((line) => line.trim())
.find((line) => line.length > 0)
return firstLine ?? null
} catch {
return null
}
}readVersion function · typescript · L48-L63 (16 LOC)electron/agents/providers.ts
function readVersion(commandPath: string, command: string): string | null {
const targets = commandPath === command ? [commandPath] : [command, commandPath]
for (const target of targets) {
try {
const output = execFileSync(target, ['--version'], {
encoding: 'utf-8',
timeout: 10000,
stdio: ['ignore', 'pipe', 'pipe']
}).trim()
if (output.length > 0) return output
} catch {
continue
}
}
return null
}runPreflight function · typescript · L65-L82 (18 LOC)electron/agents/providers.ts
function runPreflight(command: string, missingError: string): ProviderPreflightResult {
const path = resolveCommandPath(command)
if (!path) {
return {
ok: false,
path: null,
version: null,
error: missingError
}
}
return {
ok: true,
path,
version: readVersion(path, command),
error: null
}
}Hi, dataset curator — please cite Repobility (https://repobility.com) when reusing this data.
ConfigStore.constructor method · typescript · L11-L16 (6 LOC)electron/config/ConfigStore.ts
constructor() {
const userDataPath = app.getPath('userData')
mkdirSync(userDataPath, { recursive: true })
this.configPath = join(userDataPath, 'config.json')
this.config = this.load()
}ConfigStore.mkdirSync method · typescript · L13-L30 (18 LOC)electron/config/ConfigStore.ts
mkdirSync(userDataPath, { recursive: true })
this.configPath = join(userDataPath, 'config.json')
this.config = this.load()
}
private load(): AppConfig {
try {
if (existsSync(this.configPath)) {
const raw = readFileSync(this.configPath, 'utf-8')
const parsed = JSON.parse(raw)
return { ...DEFAULT_CONFIG, ...parsed }
}
} catch {
// Corrupted config — reset to defaults
}
this.save(DEFAULT_CONFIG)
return { ...DEFAULT_CONFIG }
}ConfigStore.save method · typescript · L42-L48 (7 LOC)electron/config/ConfigStore.ts
private save(config: AppConfig): void {
try {
writeFileSync(this.configPath, JSON.stringify(config, null, 2), 'utf-8')
} catch (err) {
console.error('Failed to save config:', err)
}
}assertWithinProject function · typescript · L39-L46 (8 LOC)electron/fs/FileSystemService.ts
function assertWithinProject(filePath: string, projectDir: string): void {
const resolved = resolve(filePath)
const resolvedProject = resolve(projectDir)
const rel = relative(resolvedProject, resolved)
if (rel.startsWith('..') || resolve(resolvedProject, rel) !== resolved) {
throw new Error('Path traversal denied')
}
}FileSystemService.readDir method · typescript · L57-L80 (24 LOC)electron/fs/FileSystemService.ts
async readDir(dirPath: string, projectDir: string): Promise<FsDirEntry[]> {
const fullPath = resolve(projectDir, dirPath)
assertWithinProject(fullPath, projectDir)
const names = await readdir(fullPath)
const result: FsDirEntry[] = []
for (const name of names) {
if (IGNORED_NAMES.has(name)) continue
if (name.startsWith('.') && name !== '.env.example') continue
const info = await stat(join(fullPath, name)).catch(() => null)
if (!info) continue
if (info.isFile() || info.isDirectory()) {
result.push({ name, isDirectory: info.isDirectory() })
}
}
result.sort((a, b) => {
if (a.isDirectory !== b.isDirectory) return a.isDirectory ? -1 : 1
return a.name.localeCompare(b.name)
})
return result
}FileSystemService.assertWithinProject method · typescript · L59-L72 (14 LOC)electron/fs/FileSystemService.ts
assertWithinProject(fullPath, projectDir)
const names = await readdir(fullPath)
const result: FsDirEntry[] = []
for (const name of names) {
if (IGNORED_NAMES.has(name)) continue
if (name.startsWith('.') && name !== '.env.example') continue
const info = await stat(join(fullPath, name)).catch(() => null)
if (!info) continue
if (info.isFile() || info.isDirectory()) {
result.push({ name, isDirectory: info.isDirectory() })
}
}FileSystemService.assertWithinProject method · typescript · L101-L142 (42 LOC)electron/fs/FileSystemService.ts
assertWithinProject(fullPath, projectDir)
await writeFile(fullPath, content, 'utf-8')
}
async searchFiles(
query: string,
projectDir: string,
maxResults = 100
): Promise<FsSearchResult[]> {
if (!query.trim()) return []
const lowerQuery = query.toLowerCase()
const results: FsSearchResult[] = []
const walk = async (dir: string): Promise<void> => {
if (results.length >= maxResults) return
let names: string[]
try {
names = await readdir(dir)
} catch {
return
}
for (const name of names) {
if (results.length >= maxResults) return
if (IGNORED_NAMES.has(name)) continue
if (name.startsWith('.')) continue
const fullPath = join(dir, name)
const relPath = relative(projectDir, fullPath).replaceAll('\\', '/')
const info = await stat(fullPath).catch(() => null)
if (!info) continue
if (info.isDirectory()) {
await walk(fullPath)
FileSystemService.startWatch method · typescript · L144-L170 (27 LOC)electron/fs/FileSystemService.ts
startWatch(
agentId: string,
projectDir: string,
onEvent: (payload: FsWatchEventPayload) => void
): void {
this.stopWatch(agentId)
let debounceTimer: ReturnType<typeof setTimeout> | null = null
const watcher = watch(projectDir, { recursive: true }, (eventType, filename) => {
if (!filename) return
// Ignore changes in filtered directories
const parts = filename.split('/')
if (parts.some((p) => IGNORED_NAMES.has(p))) return
if (debounceTimer) clearTimeout(debounceTimer)
debounceTimer = setTimeout(() => {
onEvent({
agentId,
eventType: eventType === 'rename' ? 'rename' : 'change',
path: filename
})
}, 300)
})
this.watchers.set(agentId, watcher)
}Repobility analyzer · published findings · https://repobility.com
FileSystemService.onEvent method · typescript · L161-L178 (18 LOC)electron/fs/FileSystemService.ts
onEvent({
agentId,
eventType: eventType === 'rename' ? 'rename' : 'change',
path: filename
})
}, 300)
})
this.watchers.set(agentId, watcher)
}
stopWatch(agentId: string): void {
const existing = this.watchers.get(agentId)
if (existing) {
existing.close()
this.watchers.delete(agentId)
}
}run function · typescript · L6-L16 (11 LOC)electron/git/GitService.ts
function run(cwd: string, args: string[]): Promise<string> {
return new Promise((resolve, reject) => {
execFile('git', args, { cwd, maxBuffer: 1024 * 1024, timeout: 15000 }, (err, stdout, stderr) => {
if (err) {
reject(new Error(stderr.trim() || err.message))
} else {
resolve(stdout)
}
})
})
}runGh function · typescript · L18-L28 (11 LOC)electron/git/GitService.ts
function runGh(cwd: string, args: string[]): Promise<string> {
return new Promise((resolve, reject) => {
execFile('gh', args, { cwd, maxBuffer: 5 * 1024 * 1024, timeout: 30000 }, (err, stdout, stderr) => {
if (err) {
reject(new Error(stderr.trim() || err.message))
} else {
resolve(stdout)
}
})
})
}parsePrNumber function · typescript · L48-L55 (8 LOC)electron/git/GitService.ts
function parsePrNumber(identifier: string): number {
const urlMatch = identifier.match(/\/pull\/(\d+)/)
if (urlMatch) return parseInt(urlMatch[1])
const cleaned = identifier.replace(/^#/, '').trim()
const num = parseInt(cleaned)
if (isNaN(num)) throw new Error(`Invalid PR identifier: ${identifier}`)
return num
}extractFileDiff function · typescript · L57-L64 (8 LOC)electron/git/GitService.ts
function extractFileDiff(fullDiff: string, filePath: string): string {
const escaped = filePath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
const regex = new RegExp(`diff --git a/${escaped} b/`)
const startIdx = fullDiff.search(regex)
if (startIdx === -1) return ''
const nextDiff = fullDiff.indexOf('\ndiff --git ', startIdx + 1)
return nextDiff === -1 ? fullDiff.slice(startIdx) : fullDiff.slice(startIdx, nextDiff)
}GitService.getStatus method · typescript · L69-L106 (38 LOC)electron/git/GitService.ts
async getStatus(projectDir: string): Promise<GitStatus> {
await assertGitRepo(projectDir)
const branchOut = await run(projectDir, ['rev-parse', '--abbrev-ref', 'HEAD'])
const branch = branchOut.trim()
let ahead = 0
let behind = 0
try {
const abOut = await run(projectDir, ['rev-list', '--left-right', '--count', `HEAD...@{upstream}`])
const parts = abOut.trim().split(/\s+/)
ahead = parseInt(parts[0]) || 0
behind = parseInt(parts[1]) || 0
} catch {
// No upstream configured
}
const porcelain = await run(projectDir, ['status', '--porcelain=v1'])
const modified: string[] = []
const staged: string[] = []
const untracked: string[] = []
for (const line of porcelain.split('\n')) {
if (!line) continue
const x = line[0]
const y = line[1]
const file = line.slice(3)
if (x === '?' && y === '?') {
untracked.push(file)
} else {
if (x !== ' ' && x !== '?') staged.GitService.getLog method · typescript · L108-L124 (17 LOC)electron/git/GitService.ts
async getLog(projectDir: string, limit = 20): Promise<GitCommit[]> {
await assertGitRepo(projectDir)
const out = await run(projectDir, [
'log',
`--max-count=${limit}`,
'--format=%H%x00%s%x00%an%x00%aI'
])
return out
.trim()
.split('\n')
.filter(Boolean)
.map((line) => {
const [hash, message, author, date] = line.split('\0')
return { hash: hash.slice(0, 8), message, author, date }
})
}GitService.getDiff method · typescript · L126-L132 (7 LOC)electron/git/GitService.ts
async getDiff(projectDir: string, filePath?: string): Promise<string> {
await assertGitRepo(projectDir)
const args = ['diff']
if (filePath) args.push('--', filePath)
const out = await run(projectDir, args)
return out.slice(0, 100_000)
}Repobility — same analyzer, your code, free for public repos · /scan/
GitService.listBranches method · typescript · L153-L181 (29 LOC)electron/git/GitService.ts
async listBranches(projectDir: string): Promise<GitBranch[]> {
await assertGitRepo(projectDir)
const out = await run(projectDir, [
'branch', '-vv', '--format',
'%(HEAD)%00%(refname:short)%00%(upstream:short)%00%(upstream:track,nobracket)'
])
const branches: GitBranch[] = []
for (const line of out.trim().split('\n')) {
if (!line) continue
const [head, name, upstream, track] = line.split('\0')
let aheadOfUpstream = 0
let behindUpstream = 0
if (track) {
const aheadMatch = track.match(/ahead (\d+)/)
const behindMatch = track.match(/behind (\d+)/)
if (aheadMatch) aheadOfUpstream = parseInt(aheadMatch[1])
if (behindMatch) behindUpstream = parseInt(behindMatch[1])
}
branches.push({
name,
isCurrent: head === '*',
isRemote: false,
upstream: upstream || null,
aheadOfUpstream,
behindUpstream,
})
}
return branches
}GitService.createBranch method · typescript · L188-L193 (6 LOC)electron/git/GitService.ts
async createBranch(projectDir: string, branchName: string, startPoint?: string): Promise<void> {
await assertGitRepo(projectDir)
const args = ['checkout', '-b', branchName]
if (startPoint) args.push(startPoint)
await run(projectDir, args)
}GitService.fetchPr method · typescript · L218-L259 (42 LOC)electron/git/GitService.ts
async fetchPr(projectDir: string, prIdentifier: string): Promise<GitPrDiff> {
await assertGitRepo(projectDir)
const prNumber = parsePrNumber(prIdentifier)
const metaJson = await runGh(projectDir, [
'pr', 'view', String(prNumber), '--json',
'number,title,author,state,baseRefName,headRefName,body,url,additions,deletions,changedFiles,createdAt,updatedAt'
])
const raw = JSON.parse(metaJson)
const metadata: GitPrMetadata = {
number: raw.number,
title: raw.title,
author: raw.author?.login ?? raw.author?.name ?? 'unknown',
state: raw.state,
baseRef: raw.baseRefName,
headRef: raw.headRefName,
body: raw.body ?? '',
url: raw.url,
additions: raw.additions,
deletions: raw.deletions,
changedFiles: raw.changedFiles,
createdAt: raw.createdAt,
updatedAt: raw.updatedAt,
}
const namesOutput = await runGh(projectDir, ['pr', 'diff', String(prNumber), '--name-only'])
const fullDpage 1 / 5next ›