Function bodies 224 total
SessionCatalog.getSessionSnapshot method · typescript · L93-L103 (11 LOC)electron/sessions/SessionCatalog.ts
private getSessionSnapshot(forceRefresh: boolean): ClaudeSessionSummary[] {
if (forceRefresh || this.cacheTtlMs <= 0) {
return this.refreshCache()
}
const now = Date.now()
if (this.cache && this.cache.expiresAt > now) {
return this.cache.sessions
}
return this.refreshCache()
}SessionCatalog.refreshCache method · typescript · L105-L116 (12 LOC)electron/sessions/SessionCatalog.ts
private refreshCache(): ClaudeSessionSummary[] {
const sessions = this.scanProjects()
if (this.cacheTtlMs > 0) {
this.cache = {
sessions,
expiresAt: Date.now() + this.cacheTtlMs
}
} else {
this.cache = null
}
return sessions
}SessionCatalog.scanProjects method · typescript · L118-L130 (13 LOC)electron/sessions/SessionCatalog.ts
private scanProjects(): ClaudeSessionSummary[] {
if (!existsSync(this.projectsDir)) return []
const sessions: ClaudeSessionSummary[] = []
const projects = readdirSync(this.projectsDir, { withFileTypes: true })
.filter((entry) => entry.isDirectory())
.map((entry) => join(this.projectsDir, entry.name))
for (const projectDir of projects) {
sessions.push(...this.readProjectSessions(projectDir))
}
return sessions
}SessionCatalog.readProjectSessions method · typescript · L132-L145 (14 LOC)electron/sessions/SessionCatalog.ts
private readProjectSessions(projectDir: string): ClaudeSessionSummary[] {
const sessions: ClaudeSessionSummary[] = []
const seenSessionIds = new Set<string>()
const indexPath = join(projectDir, INDEX_FILENAME)
if (existsSync(indexPath)) {
sessions.push(...this.readFromSessionsIndex(indexPath, seenSessionIds))
}
// Fallback for project folders without sessions-index.json (or missing entries).
sessions.push(...this.readFromJsonlFiles(projectDir, seenSessionIds))
return sessions
}SessionCatalog.readFromSessionsIndex method · typescript · L147-L180 (34 LOC)electron/sessions/SessionCatalog.ts
private readFromSessionsIndex(indexPath: string, seenSessionIds: Set<string>): ClaudeSessionSummary[] {
try {
const raw = readFileSync(indexPath, 'utf-8')
const parsed = JSON.parse(raw) as SessionsIndexFile
const entries = parsed.entries ?? []
return entries
.filter((entry) => !!entry.sessionId && !!entry.fullPath)
.map((entry) => {
seenSessionIds.add(entry.sessionId)
const modifiedAt =
entry.modified ??
(entry.fileMtime ? new Date(entry.fileMtime).toISOString() : new Date().toISOString())
const createdAt = entry.created ?? modifiedAt
return {
sessionId: entry.sessionId,
projectPath: entry.projectPath ?? parsed.originalPath ?? '',
firstPrompt: (entry.firstPrompt ?? '').trim(),
messageCount: Math.max(0, entry.messageCount ?? 0),
createdAt,
modifiedAt,
gitBranch: entry.gitBranch ?? null,
SessionCatalog.readFromJsonlFiles method · typescript · L182-L220 (39 LOC)electron/sessions/SessionCatalog.ts
private readFromJsonlFiles(projectDir: string, seenSessionIds: Set<string>): ClaudeSessionSummary[] {
let files: string[] = []
try {
files = readdirSync(projectDir, { withFileTypes: true })
.filter((entry) => entry.isFile() && entry.name.endsWith('.jsonl'))
.map((entry) => join(projectDir, entry.name))
} catch {
return []
}
const sessions: ClaudeSessionSummary[] = []
for (const filePath of files) {
const sessionId = basename(filePath, '.jsonl')
if (seenSessionIds.has(sessionId)) continue
const stat = statSync(filePath)
if (stat.size <= 0) continue
const header = this.readJsonlHeader(filePath)
if (!header) continue
seenSessionIds.add(header.sessionId)
sessions.push({
sessionId: header.sessionId,
projectPath: header.cwd,
firstPrompt: header.firstPrompt,
messageCount: 0,
createdAt: stat.birthtime.toISOString(),
modifiedAt: stat.mtime.tSessionCatalog.readJsonlHeader method · typescript · L222-L282 (61 LOC)electron/sessions/SessionCatalog.ts
private readJsonlHeader(filePath: string): JsonlHeader | null {
try {
const raw = readFileSync(filePath, 'utf-8').slice(0, JSONL_MAX_HEADER_CHARS)
const lines = raw.split('\n')
let sessionId = ''
let cwd = ''
let gitBranch: string | null = null
let isSidechain = false
let firstPrompt = ''
for (const line of lines) {
const trimmed = line.trim()
if (!trimmed) continue
let record: unknown
try {
record = JSON.parse(trimmed)
} catch {
continue
}
if (!record || typeof record !== 'object') continue
const object = record as Record<string, unknown>
if (!sessionId && typeof object.sessionId === 'string') {
sessionId = object.sessionId
}
if (!cwd && typeof object.cwd === 'string') {
cwd = object.cwd
}
if (!gitBranch && typeof object.gitBranch === 'string') {
gitBranch = object.gitBranch
Repobility · code-quality intelligence · https://repobility.com
normalizeReleaseNotes function · typescript · L6-L23 (18 LOC)electron/updates/UpdateService.ts
function normalizeReleaseNotes(notes: unknown): string | null {
if (typeof notes === 'string') {
return notes.trim() || null
}
if (Array.isArray(notes)) {
const lines = notes
.map((entry) => {
if (!entry || typeof entry !== 'object') return ''
const maybeNotes = (entry as { note?: unknown }).note
return typeof maybeNotes === 'string' ? maybeNotes.trim() : ''
})
.filter(Boolean)
return lines.length > 0 ? lines.join('\n\n') : null
}
return null
}UpdateService.constructor method · typescript · L28-L107 (80 LOC)electron/updates/UpdateService.ts
constructor() {
super()
const supported = process.platform === 'win32'
this.state = {
supported,
platform: process.platform,
checking: false,
available: false,
downloaded: false,
downloading: false,
currentVersion: app.getVersion(),
latestVersion: null,
releaseDate: null,
releaseNotes: null,
error: null
}
if (!supported) return
autoUpdater.autoDownload = false
autoUpdater.autoInstallOnAppQuit = true
autoUpdater.on('checking-for-update', () => {
this.patch({ checking: true, error: null })
})
autoUpdater.on('update-available', (info) => {
this.patch({
checking: false,
available: true,
downloaded: false,
latestVersion: info.version ?? null,
releaseDate: info.releaseDate ?? null,
releaseNotes: normalizeReleaseNotes(info.releaseNotes),
error: null
})
})
autoUpdater.on('update-not-available', () => UpdateService.checkForUpdates method · typescript · L113-L118 (6 LOC)electron/updates/UpdateService.ts
async checkForUpdates(): Promise<AppUpdateState> {
if (!this.state.supported) return this.getState()
this.patch({ error: null, checking: true })
await autoUpdater.checkForUpdates()
return this.getState()
}UpdateService.downloadUpdate method · typescript · L120-L126 (7 LOC)electron/updates/UpdateService.ts
async downloadUpdate(): Promise<AppUpdateState> {
if (!this.state.supported) return this.getState()
if (!this.state.available) return this.getState()
this.patch({ error: null, downloading: true })
await autoUpdater.downloadUpdate()
return this.getState()
}UpdateService.installAndRestart method · typescript · L128-L134 (7 LOC)electron/updates/UpdateService.ts
installAndRestart(): boolean {
if (!this.state.supported || !this.state.downloaded) return false
setImmediate(() => {
autoUpdater.quitAndInstall(false, true)
})
return true
}UsageTracker.mkdirSync method · typescript · L86-L96 (11 LOC)electron/usage/UsageTracker.ts
mkdirSync(dataDir, { recursive: true })
this.usagePath = join(dataDir, 'usage.json')
this.store = this.load()
}
recordAgentOutput(
agent: AgentState,
rawData: string,
config: AppConfig,
now: Date = new Date()
): { changed: boolean; alerts: UsageBudgetAlert[]; summary: UsageDailySummary | null } {UsageTracker.getDashboard method · typescript · L155-L186 (32 LOC)electron/usage/UsageTracker.ts
getDashboard(config: AppConfig, options?: UsageDashboardOptions): UsageDashboardSnapshot {
const dayLimit = Math.max(1, Math.min(90, options?.days ?? 14))
this.pruneOldDays()
const days = Object.keys(this.store.days)
.sort((a, b) => b.localeCompare(a))
.slice(0, dayLimit)
.map((date) => this.buildDaySummary(date))
.filter((summary): summary is UsageDailySummary => summary !== null)
const todayDate = toDateKey(new Date())
const today =
days.find((summary) => summary.date === todayDate) ??
this.buildDaySummary(todayDate) ??
createEmptyDaySummary(todayDate)
const finalDays = [...days]
if (!finalDays.some((summary) => summary.date === today.date)) {
finalDays.unshift(today)
}
if (finalDays.length > dayLimit) {
finalDays.length = dayLimit
}
return {
generatedAt: new Date().toISOString(),
today,
days: finalDays,
budget: buildBudgetStatus(today, config)
}
}UsageTracker.createEmptyDaySummary method · typescript · L169-L174 (6 LOC)electron/usage/UsageTracker.ts
createEmptyDaySummary(todayDate)
const finalDays = [...days]
if (!finalDays.some((summary) => summary.date === today.date)) {
finalDays.unshift(today)
}Repobility · severity-and-effort ranking · https://repobility.com
UsageTracker.createStoredAgent method · typescript · L188-L200 (13 LOC)electron/usage/UsageTracker.ts
private createStoredAgent(agent: AgentState, now: Date): StoredUsageAgent {
return {
agentId: agent.id,
agentName: agent.name,
projectDir: agent.projectDir,
projectName: basename(agent.projectDir) || agent.projectDir || 'Workspace',
provider: agent.provider,
model: agent.model,
tokens: 0,
costUsd: 0,
updatedAt: now.toISOString()
}
}UsageTracker.ensureDay method · typescript · L202-L221 (20 LOC)electron/usage/UsageTracker.ts
private ensureDay(dateKey: string, now: Date): StoredUsageDay {
if (!this.store.days[dateKey]) {
this.store.days[dateKey] = {
date: dateKey,
updatedAt: now.toISOString(),
agents: {}
}
}
if (!this.store.alerts[dateKey]) {
this.store.alerts[dateKey] = {
tokenWarningSent: false,
tokenExceededSent: false,
costWarningSent: false,
costExceededSent: false
}
}
return this.store.days[dateKey]
}UsageTracker.buildDaySummary method · typescript · L223-L286 (64 LOC)electron/usage/UsageTracker.ts
private buildDaySummary(dateKey: string): UsageDailySummary | null {
const day = this.store.days[dateKey]
if (!day) return null
const agents: UsageAgentDailyStat[] = Object.values(day.agents)
.map((agent) => ({
...agent,
tokens: Math.max(0, Math.round(agent.tokens)),
costUsd: roundCost(agent.costUsd)
}))
.sort((a, b) => {
if (b.costUsd !== a.costUsd) return b.costUsd - a.costUsd
if (b.tokens !== a.tokens) return b.tokens - a.tokens
return a.agentName.localeCompare(b.agentName)
})
let totalTokens = 0
let totalCost = 0
const projects = new Map<string, UsageProjectDailyStat>()
const projectAgentSets = new Map<string, Set<string>>()
for (const agent of agents) {
totalTokens += agent.tokens
totalCost += agent.costUsd
const existingProject = projects.get(agent.projectDir) ?? {
projectDir: agent.projectDir,
projectName: agent.projectName,
agenUsageTracker.evaluateBudgetTransitions method · typescript · L288-L354 (67 LOC)electron/usage/UsageTracker.ts
private evaluateBudgetTransitions(
dateKey: string,
summary: UsageDailySummary,
config: AppConfig
): UsageBudgetAlert[] {
const alerts: UsageBudgetAlert[] = []
const state = this.store.alerts[dateKey]
if (!state) return alerts
const warningThreshold = clampWarningThreshold(config.usageBudgetWarningThresholdPct)
const tokenBudget = config.usageDailyTokenBudget > 0 ? config.usageDailyTokenBudget : 0
const costBudget = config.usageDailyCostBudgetUsd > 0 ? config.usageDailyCostBudgetUsd : 0
if (tokenBudget > 0) {
const thresholdValue = tokenBudget * (warningThreshold / 100)
if (summary.tokens >= thresholdValue && !state.tokenWarningSent) {
state.tokenWarningSent = true
alerts.push({
date: dateKey,
metric: 'tokens',
level: 'warning',
usage: summary.tokens,
budget: tokenBudget,
percent: (summary.tokens / tokenBudget) * 100
})
}
if (summary.UsageTracker.load method · typescript · L356-L377 (22 LOC)electron/usage/UsageTracker.ts
private load(): UsageStore {
try {
if (existsSync(this.usagePath)) {
const parsed = JSON.parse(readFileSync(this.usagePath, 'utf-8')) as Partial<UsageStore>
if (parsed && typeof parsed === 'object') {
return {
schemaVersion: USAGE_SCHEMA_VERSION,
days: sanitizeDayMap(parsed.days),
alerts: sanitizeAlertMap(parsed.alerts)
}
}
}
} catch {
// Best effort load. Corrupted state resets to empty.
}
return {
schemaVersion: USAGE_SCHEMA_VERSION,
days: {},
alerts: {}
}
}UsageTracker.save method · typescript · L379-L385 (7 LOC)electron/usage/UsageTracker.ts
private save(): void {
try {
writeFileSync(this.usagePath, JSON.stringify(this.store, null, 2), 'utf-8')
} catch {
// Best effort persistence.
}
}UsageTracker.pruneOldDays method · typescript · L387-L396 (10 LOC)electron/usage/UsageTracker.ts
private pruneOldDays(): void {
const dayKeys = Object.keys(this.store.days).sort((a, b) => b.localeCompare(a))
if (dayKeys.length <= MAX_RETAINED_DAYS) return
for (const key of dayKeys.slice(MAX_RETAINED_DAYS)) {
delete this.store.days[key]
delete this.store.alerts[key]
}
this.save()
}sanitizeDayMap function · typescript · L399-L416 (18 LOC)electron/usage/UsageTracker.ts
function sanitizeDayMap(input: unknown): Record<string, StoredUsageDay> {
if (!input || typeof input !== 'object') return {}
const out: Record<string, StoredUsageDay> = {}
for (const [date, day] of Object.entries(input as Record<string, unknown>)) {
if (!day || typeof day !== 'object') continue
const dayObject = day as Partial<StoredUsageDay>
if (typeof dayObject.date !== 'string') continue
const agents = sanitizeAgentMap(dayObject.agents)
out[date] = {
date: dayObject.date,
updatedAt: typeof dayObject.updatedAt === 'string' ? dayObject.updatedAt : new Date().toISOString(),
agents
}
}
return out
}Open data scored by Repobility · https://repobility.com
sanitizeAgentMap function · typescript · L418-L450 (33 LOC)electron/usage/UsageTracker.ts
function sanitizeAgentMap(input: unknown): Record<string, StoredUsageAgent> {
if (!input || typeof input !== 'object') return {}
const out: Record<string, StoredUsageAgent> = {}
for (const [agentId, value] of Object.entries(input as Record<string, unknown>)) {
if (!value || typeof value !== 'object') continue
const entry = value as Partial<StoredUsageAgent>
if (
typeof entry.agentId !== 'string' ||
typeof entry.agentName !== 'string' ||
typeof entry.projectDir !== 'string' ||
typeof entry.projectName !== 'string' ||
typeof entry.provider !== 'string' ||
typeof entry.model !== 'string'
) {
continue
}
out[agentId] = {
agentId: entry.agentId,
agentName: entry.agentName,
projectDir: entry.projectDir,
projectName: entry.projectName,
provider: entry.provider,
model: entry.model,
tokens: sanitizeTokenCount(entry.tokens),
costUsd: typeof entry.costUsd === 'number' && NumbersanitizeAlertMap function · typescript · L452-L468 (17 LOC)electron/usage/UsageTracker.ts
function sanitizeAlertMap(input: unknown): Record<string, StoredBudgetAlertState> {
if (!input || typeof input !== 'object') return {}
const out: Record<string, StoredBudgetAlertState> = {}
for (const [date, value] of Object.entries(input as Record<string, unknown>)) {
if (!value || typeof value !== 'object') continue
const entry = value as Partial<StoredBudgetAlertState>
out[date] = {
tokenWarningSent: entry.tokenWarningSent === true,
tokenExceededSent: entry.tokenExceededSent === true,
costWarningSent: entry.costWarningSent === true,
costExceededSent: entry.costExceededSent === true
}
}
return out
}parseUsageSignals function · typescript · L470-L541 (72 LOC)electron/usage/UsageTracker.ts
function parseUsageSignals(rawData: string): UsageSignals {
const cleaned = rawData.replace(ANSI_REGEX, '').replace(CONTROL_CHARS, '')
const lines = cleaned.split(/\r?\n/)
let tokenCount: number | null = null
let costSessionUsd: number | null = null
let costTodayUsd: number | null = null
for (const line of lines) {
const trimmed = line.trim()
if (!trimmed) continue
const tokenOnlyMatch = trimmed.match(TOKEN_ONLY_PATTERN)
if (tokenOnlyMatch?.[1]) {
const parsed = parseTokenCount(tokenOnlyMatch[1])
if (parsed !== null) {
tokenCount = tokenCount === null ? parsed : Math.max(tokenCount, parsed)
}
}
const tokenPrefixMatch = trimmed.match(TOKEN_COUNT_PREFIX_PATTERN)
if (tokenPrefixMatch?.[1]) {
const parsed = parseTokenCount(tokenPrefixMatch[1])
if (parsed !== null) {
tokenCount = tokenCount === null ? parsed : Math.max(tokenCount, parsed)
}
}
const contextUsageMatch = trimmed.match(CONTEparseTokenCount function · typescript · L549-L554 (6 LOC)electron/usage/UsageTracker.ts
function parseTokenCount(value: string): number | null {
const parsed = parseNumeric(value)
if (parsed === null) return null
if (parsed > MAX_TOKEN_SIGNAL) return null
return parsed
}sanitizeTokenCount function · typescript · L556-L564 (9 LOC)electron/usage/UsageTracker.ts
function sanitizeTokenCount(value: unknown): number {
if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {
return 0
}
if (value > MAX_TOKEN_SIGNAL) {
return 0
}
return value
}toDateKey function · typescript · L566-L571 (6 LOC)electron/usage/UsageTracker.ts
function toDateKey(date: Date): string {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
}buildBudgetStatus function · typescript · L582-L604 (23 LOC)electron/usage/UsageTracker.ts
function buildBudgetStatus(today: UsageDailySummary | null, config: AppConfig): UsageBudgetStatus {
const threshold = clampWarningThreshold(config.usageBudgetWarningThresholdPct)
const tokenBudget = config.usageDailyTokenBudget > 0 ? config.usageDailyTokenBudget : null
const costBudget = config.usageDailyCostBudgetUsd > 0 ? config.usageDailyCostBudgetUsd : null
const tokenUsage = today?.tokens ?? 0
const costUsage = today?.costUsd ?? 0
const tokenUsagePct = tokenBudget ? (tokenUsage / tokenBudget) * 100 : null
const costUsagePct = costBudget ? (costUsage / costBudget) * 100 : null
return {
dailyTokenBudget: tokenBudget,
dailyCostBudgetUsd: costBudget,
warningThresholdPct: threshold,
tokenUsagePct,
costUsagePct,
tokenWarningReached: tokenBudget ? tokenUsage >= tokenBudget * (threshold / 100) : false,
costWarningReached: costBudget ? costUsage >= costBudget * (threshold / 100) : false,
tokenBudgetExceeded: tokenBudget ? tokenUsage >= tokcreateEmptyDaySummary function · typescript · L606-L615 (10 LOC)electron/usage/UsageTracker.ts
function createEmptyDaySummary(date: string): UsageDailySummary {
return {
date,
tokens: 0,
costUsd: 0,
updatedAt: new Date().toISOString(),
agents: [],
projects: []
}
}Repobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
appendPathEntries function · typescript · L12-L24 (13 LOC)electron/util/fix-path.ts
function appendPathEntries(entries: Array<string | null | undefined>): void {
const current = process.env.PATH ?? ''
const existing = new Set(current.split(delimiter).filter((entry) => entry.length > 0))
const merged = [...existing]
for (const entry of entries) {
if (!entry || entry.length === 0 || existing.has(entry)) continue
existing.add(entry)
merged.push(entry)
}
process.env.PATH = merged.join(delimiter)
}fixPath function · typescript · L26-L60 (35 LOC)electron/util/fix-path.ts
export function fixPath(): void {
if (process.platform === 'win32') {
const userHome = process.env.USERPROFILE || process.env.HOME
appendPathEntries([
process.env.APPDATA ? join(process.env.APPDATA, 'npm') : null,
process.env.LOCALAPPDATA ? join(process.env.LOCALAPPDATA, 'Programs', 'nodejs') : null,
userHome ? join(userHome, '.local', 'bin') : null
])
return
}
if (process.platform !== 'darwin') return
try {
const shell = process.env.SHELL || '/bin/zsh'
const result = execSync(`${shell} -ilc 'echo -n "__PATH__=$PATH"'`, {
encoding: 'utf-8',
timeout: 5000
})
const match = result.match(/__PATH__=(.+)/)
if (match?.[1]) {
process.env.PATH = match[1]
}
} catch {
// Fallback: append common binary locations
const home = process.env.HOME
appendPathEntries([
'/usr/local/bin',
'/opt/homebrew/bin',
home ? `${home}/.local/bin` : null,
home ? `${home}/.nvm/versions/node/curreWorkspaceStore.constructor method · typescript · L32-L37 (6 LOC)electron/workspace/WorkspaceStore.ts
constructor() {
const userDataPath = app.getPath('userData')
mkdirSync(userDataPath, { recursive: true })
this.workspacePath = join(userDataPath, 'workspace.json')
this.cache = this.load()
}WorkspaceStore.mkdirSync method · typescript · L34-L41 (8 LOC)electron/workspace/WorkspaceStore.ts
mkdirSync(userDataPath, { recursive: true })
this.workspacePath = join(userDataPath, 'workspace.json')
this.cache = this.load()
}
getAgents(): PersistedWorkspaceAgent[] {
return this.cache.agents.map((agent) => ({ ...agent }))
}WorkspaceStore.setAgents method · typescript · L43-L50 (8 LOC)electron/workspace/WorkspaceStore.ts
setAgents(agents: PersistedWorkspaceAgent[]): PersistedWorkspaceAgent[] {
this.cache = {
...this.cache,
agents: agents.map((agent) => ({ ...agent }))
}
this.save()
return this.getAgents()
}WorkspaceStore.load method · typescript · L52-L74 (23 LOC)electron/workspace/WorkspaceStore.ts
private load(): WorkspaceData {
try {
if (!existsSync(this.workspacePath)) {
this.saveData(DEFAULT_WORKSPACE)
return { ...DEFAULT_WORKSPACE, agents: [] }
}
const raw = readFileSync(this.workspacePath, 'utf-8')
const parsed = JSON.parse(raw) as Partial<WorkspaceData>
const agents = Array.isArray(parsed.agents)
? parsed.agents.filter((agent): agent is PersistedWorkspaceAgent => this.isAgent(agent))
: []
return {
schemaVersion: 1,
agents
}
} catch {
this.saveData(DEFAULT_WORKSPACE)
return { ...DEFAULT_WORKSPACE, agents: [] }
}
}WorkspaceStore.isAgent method · typescript · L76-L90 (15 LOC)electron/workspace/WorkspaceStore.ts
private isAgent(value: unknown): value is PersistedWorkspaceAgent {
if (!value || typeof value !== 'object') return false
const obj = value as Record<string, unknown>
const validProviders = ['claude', 'codex']
return (
typeof obj.id === 'string' &&
typeof obj.name === 'string' &&
typeof obj.projectDir === 'string' &&
typeof obj.model === 'string' &&
(obj.provider === undefined || validProviders.includes(obj.provider as string)) &&
typeof obj.yolo === 'boolean' &&
(typeof obj.sessionId === 'string' || obj.sessionId === null) &&
typeof obj.createdAt === 'string'
)
}WorkspaceStore.saveData method · typescript · L96-L102 (7 LOC)electron/workspace/WorkspaceStore.ts
private saveData(data: WorkspaceData): void {
try {
writeFileSync(this.workspacePath, JSON.stringify(data, null, 2), 'utf-8')
} catch (error) {
console.error('Failed to persist workspace state:', error)
}
}Repobility · code-quality intelligence · https://repobility.com
listPublishedReleases function · javascript · L68-L94 (27 LOC)scripts/release-guard.mjs
function listPublishedReleases(targetRepo) {
try {
const raw = execFileSync(
'gh',
[
'release',
'list',
'--repo',
targetRepo,
'--exclude-drafts',
'--exclude-pre-releases',
'--limit',
'200',
'--json',
'tagName'
],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }
).trim()
if (!raw) return []
const parsed = JSON.parse(raw)
return Array.isArray(parsed) ? parsed : []
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
console.error(`Release guard failed while listing releases: ${message}`)
process.exit(1)
}
}hasCommand function · javascript · L27-L34 (8 LOC)scripts/release-preflight.mjs
function hasCommand(command) {
try {
execSync(`command -v ${command}`, { stdio: 'ignore' })
return true
} catch {
return false
}
}safeCheck function · javascript · L36-L45 (10 LOC)scripts/release-preflight.mjs
function safeCheck(name, command) {
try {
const output = execSync(command, { encoding: 'utf-8' }).trim()
console.log(`[ok] ${name}: ${output}`)
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
console.error(`[fail] ${name}: ${message}`)
process.exit(1)
}
}getProviderForModel function · typescript · L60-L65 (6 LOC)shared/types.ts
export function getProviderForModel(model: ModelId): ProviderId {
for (const [provider, models] of Object.entries(PROVIDER_MODELS)) {
if (models.some((m) => m.id === model)) return provider as ProviderId
}
return 'claude'
}readWorkspaceUiState function · typescript · L36-L75 (40 LOC)src/App.tsx
function readWorkspaceUiState(): PersistedWorkspaceUiState {
try {
const raw = localStorage.getItem(WORKSPACE_UI_STORAGE_KEY)
if (!raw) {
return {
selectedProject: null,
selectedAgentId: null,
viewMode: null,
expandedTilesByProject: {},
sidebarWidth: null,
editorOpen: null
}
}
const parsed = JSON.parse(raw) as Partial<PersistedWorkspaceUiState>
const viewMode = parsed.viewMode
const safeViewMode: ViewMode | null = viewMode === 'grid' || viewMode === 'chat' ? viewMode : null
return {
selectedProject: typeof parsed.selectedProject === 'string' ? parsed.selectedProject : null,
selectedAgentId: typeof parsed.selectedAgentId === 'string' ? parsed.selectedAgentId : null,
viewMode: safeViewMode,
expandedTilesByProject:
parsed.expandedTilesByProject && typeof parsed.expandedTilesByProject === 'object'
? parsed.expandedTilesByProject
: {},
sidebarwriteWorkspaceUiState function · typescript · L77-L83 (7 LOC)src/App.tsx
function writeWorkspaceUiState(state: PersistedWorkspaceUiState): void {
try {
localStorage.setItem(WORKSPACE_UI_STORAGE_KEY, JSON.stringify(state))
} catch {
// Best effort persistence.
}
}ChatView function · typescript · L37-L225 (189 LOC)src/components/ChatView/ChatView.tsx
export function ChatView({
agent,
rawOutput,
onSendInput,
onTerminalData,
onTerminalResize,
onRestartAgent,
onToggleYolo,
onKillAgent,
onRemoveAgent,
editorOpen = false,
onToggleEditor,
editorTabs = [],
editorActiveTabPath = null,
editorFileContents,
onEditorOpenFile,
onEditorCloseTab,
onEditorSelectTab,
onEditorContentChange,
onEditorSaveFile,
theme = 'dark',
defaultEditor = 'vscode',
onSetDefaultEditor
}: ChatViewProps) {
// Prevent browser focus-scroll from moving the outer container.
const containerRef = useRef<HTMLDivElement>(null)
const handleContainerScroll = useCallback(() => {
const el = containerRef.current
if (el && el.scrollTop !== 0) {
el.scrollTop = 0
}
}, [])
// Split panel width management
const [splitRatio, setSplitRatio] = useState(0.5)
const outerRef = useRef<HTMLDivElement>(null)
const handleSplitDrag = useCallback((deltaX: number) => {
const outer = outerRef.current
if (!outer) CodeBracketIcon function · typescript · L227-L243 (17 LOC)src/components/ChatView/ChatView.tsx
function CodeBracketIcon() {
return (
<svg
className={styles.actionIcon}
viewBox="0 0 16 16"
fill="none"
stroke="currentColor"
strokeWidth="1.4"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
>
<path d="M5.5 3.5L2 8l3.5 4.5" />
<path d="M10.5 3.5L14 8l-3.5 4.5" />
</svg>
)
}Repobility · severity-and-effort ranking · https://repobility.com
LockIcon function · typescript · L245-L279 (35 LOC)src/components/ChatView/ChatView.tsx
function LockIcon({ unlocked }: { unlocked: boolean }) {
if (unlocked) {
return (
<svg
className={styles.actionIcon}
viewBox="0 0 16 16"
fill="none"
stroke="currentColor"
strokeWidth="1.4"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
>
<path d="M4 7h8a1 1 0 0 1 1 1v5H3V8a1 1 0 0 1 1-1Z" />
<path d="M6 7V5.3a2.7 2.7 0 0 1 5.1-1.2" />
</svg>
)
}
return (
<svg
className={styles.actionIcon}
viewBox="0 0 16 16"
fill="none"
stroke="currentColor"
strokeWidth="1.4"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
>
<path d="M4 7h8a1 1 0 0 1 1 1v5H3V8a1 1 0 0 1 1-1Z" />
<path d="M5.4 7V5.1a2.6 2.6 0 0 1 5.2 0V7" />
</svg>
)
}StatusBadge function · typescript · L281-L295 (15 LOC)src/components/ChatView/ChatView.tsx
function StatusBadge({ status }: { status: string }) {
const colors: Record<string, string> = {
running: 'var(--color-status-running)',
idle: 'var(--color-status-idle)',
errored: 'var(--color-status-error)',
starting: 'var(--color-status-starting)'
}
return (
<span className={styles.statusBadge}>
<span className={styles.statusDot} style={{ background: colors[status] }} />
{status.charAt(0).toUpperCase() + status.slice(1)}
</span>
)
}HydraIcon function · typescript · L297-L311 (15 LOC)src/components/ChatView/ChatView.tsx
function HydraIcon() {
return (
<svg width="48" height="48" viewBox="0 0 28 28" fill="none" opacity="0.25">
<g transform="translate(3, 2)">
<path d="M7.5 20 Q5.5 14 4 10" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"/>
<circle cx="3.5" cy="8" r="3.2" fill="currentColor"/>
<path d="M11 20 L11 8" stroke="currentColor" strokeWidth="2.8" strokeLinecap="round"/>
<circle cx="11" cy="4.5" r="3.8" fill="currentColor"/>
<path d="M14.5 20 Q16.5 14 18 10" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"/>
<circle cx="18.5" cy="8" r="3.2" fill="currentColor"/>
<rect x="5" y="21" width="12" height="2.4" rx="1.2" fill="currentColor" opacity="0.35"/>
</g>
</svg>
)
}