Prettier backfill

This commit is contained in:
Matt Rubens
2025-01-17 14:11:28 -05:00
parent 3bcb4ff8c5
commit 60a0a824b9
174 changed files with 15715 additions and 15428 deletions

View File

@@ -1,97 +1,97 @@
import { calculateApiCost } from '../cost';
import { ModelInfo } from '../../shared/api';
import { calculateApiCost } from "../cost"
import { ModelInfo } from "../../shared/api"
describe('Cost Utility', () => {
describe('calculateApiCost', () => {
const mockModelInfo: ModelInfo = {
maxTokens: 8192,
contextWindow: 200_000,
supportsPromptCache: true,
inputPrice: 3.0, // $3 per million tokens
outputPrice: 15.0, // $15 per million tokens
cacheWritesPrice: 3.75, // $3.75 per million tokens
cacheReadsPrice: 0.3, // $0.30 per million tokens
};
describe("Cost Utility", () => {
describe("calculateApiCost", () => {
const mockModelInfo: ModelInfo = {
maxTokens: 8192,
contextWindow: 200_000,
supportsPromptCache: true,
inputPrice: 3.0, // $3 per million tokens
outputPrice: 15.0, // $15 per million tokens
cacheWritesPrice: 3.75, // $3.75 per million tokens
cacheReadsPrice: 0.3, // $0.30 per million tokens
}
it('should calculate basic input/output costs correctly', () => {
const cost = calculateApiCost(mockModelInfo, 1000, 500);
// Input cost: (3.0 / 1_000_000) * 1000 = 0.003
// Output cost: (15.0 / 1_000_000) * 500 = 0.0075
// Total: 0.003 + 0.0075 = 0.0105
expect(cost).toBe(0.0105);
});
it("should calculate basic input/output costs correctly", () => {
const cost = calculateApiCost(mockModelInfo, 1000, 500)
it('should handle cache writes cost', () => {
const cost = calculateApiCost(mockModelInfo, 1000, 500, 2000);
// Input cost: (3.0 / 1_000_000) * 1000 = 0.003
// Output cost: (15.0 / 1_000_000) * 500 = 0.0075
// Cache writes: (3.75 / 1_000_000) * 2000 = 0.0075
// Total: 0.003 + 0.0075 + 0.0075 = 0.018
expect(cost).toBeCloseTo(0.018, 6);
});
// Input cost: (3.0 / 1_000_000) * 1000 = 0.003
// Output cost: (15.0 / 1_000_000) * 500 = 0.0075
// Total: 0.003 + 0.0075 = 0.0105
expect(cost).toBe(0.0105)
})
it('should handle cache reads cost', () => {
const cost = calculateApiCost(mockModelInfo, 1000, 500, undefined, 3000);
// Input cost: (3.0 / 1_000_000) * 1000 = 0.003
// Output cost: (15.0 / 1_000_000) * 500 = 0.0075
// Cache reads: (0.3 / 1_000_000) * 3000 = 0.0009
// Total: 0.003 + 0.0075 + 0.0009 = 0.0114
expect(cost).toBe(0.0114);
});
it("should handle cache writes cost", () => {
const cost = calculateApiCost(mockModelInfo, 1000, 500, 2000)
it('should handle all cost components together', () => {
const cost = calculateApiCost(mockModelInfo, 1000, 500, 2000, 3000);
// Input cost: (3.0 / 1_000_000) * 1000 = 0.003
// Output cost: (15.0 / 1_000_000) * 500 = 0.0075
// Cache writes: (3.75 / 1_000_000) * 2000 = 0.0075
// Cache reads: (0.3 / 1_000_000) * 3000 = 0.0009
// Total: 0.003 + 0.0075 + 0.0075 + 0.0009 = 0.0189
expect(cost).toBe(0.0189);
});
// Input cost: (3.0 / 1_000_000) * 1000 = 0.003
// Output cost: (15.0 / 1_000_000) * 500 = 0.0075
// Cache writes: (3.75 / 1_000_000) * 2000 = 0.0075
// Total: 0.003 + 0.0075 + 0.0075 = 0.018
expect(cost).toBeCloseTo(0.018, 6)
})
it('should handle missing prices gracefully', () => {
const modelWithoutPrices: ModelInfo = {
maxTokens: 8192,
contextWindow: 200_000,
supportsPromptCache: true
};
it("should handle cache reads cost", () => {
const cost = calculateApiCost(mockModelInfo, 1000, 500, undefined, 3000)
const cost = calculateApiCost(modelWithoutPrices, 1000, 500, 2000, 3000);
expect(cost).toBe(0);
});
// Input cost: (3.0 / 1_000_000) * 1000 = 0.003
// Output cost: (15.0 / 1_000_000) * 500 = 0.0075
// Cache reads: (0.3 / 1_000_000) * 3000 = 0.0009
// Total: 0.003 + 0.0075 + 0.0009 = 0.0114
expect(cost).toBe(0.0114)
})
it('should handle zero tokens', () => {
const cost = calculateApiCost(mockModelInfo, 0, 0, 0, 0);
expect(cost).toBe(0);
});
it("should handle all cost components together", () => {
const cost = calculateApiCost(mockModelInfo, 1000, 500, 2000, 3000)
it('should handle undefined cache values', () => {
const cost = calculateApiCost(mockModelInfo, 1000, 500);
// Input cost: (3.0 / 1_000_000) * 1000 = 0.003
// Output cost: (15.0 / 1_000_000) * 500 = 0.0075
// Total: 0.003 + 0.0075 = 0.0105
expect(cost).toBe(0.0105);
});
// Input cost: (3.0 / 1_000_000) * 1000 = 0.003
// Output cost: (15.0 / 1_000_000) * 500 = 0.0075
// Cache writes: (3.75 / 1_000_000) * 2000 = 0.0075
// Cache reads: (0.3 / 1_000_000) * 3000 = 0.0009
// Total: 0.003 + 0.0075 + 0.0075 + 0.0009 = 0.0189
expect(cost).toBe(0.0189)
})
it('should handle missing cache prices', () => {
const modelWithoutCachePrices: ModelInfo = {
...mockModelInfo,
cacheWritesPrice: undefined,
cacheReadsPrice: undefined
};
it("should handle missing prices gracefully", () => {
const modelWithoutPrices: ModelInfo = {
maxTokens: 8192,
contextWindow: 200_000,
supportsPromptCache: true,
}
const cost = calculateApiCost(modelWithoutCachePrices, 1000, 500, 2000, 3000);
// Should only include input and output costs
// Input cost: (3.0 / 1_000_000) * 1000 = 0.003
// Output cost: (15.0 / 1_000_000) * 500 = 0.0075
// Total: 0.003 + 0.0075 = 0.0105
expect(cost).toBe(0.0105);
});
});
});
const cost = calculateApiCost(modelWithoutPrices, 1000, 500, 2000, 3000)
expect(cost).toBe(0)
})
it("should handle zero tokens", () => {
const cost = calculateApiCost(mockModelInfo, 0, 0, 0, 0)
expect(cost).toBe(0)
})
it("should handle undefined cache values", () => {
const cost = calculateApiCost(mockModelInfo, 1000, 500)
// Input cost: (3.0 / 1_000_000) * 1000 = 0.003
// Output cost: (15.0 / 1_000_000) * 500 = 0.0075
// Total: 0.003 + 0.0075 = 0.0105
expect(cost).toBe(0.0105)
})
it("should handle missing cache prices", () => {
const modelWithoutCachePrices: ModelInfo = {
...mockModelInfo,
cacheWritesPrice: undefined,
cacheReadsPrice: undefined,
}
const cost = calculateApiCost(modelWithoutCachePrices, 1000, 500, 2000, 3000)
// Should only include input and output costs
// Input cost: (3.0 / 1_000_000) * 1000 = 0.003
// Output cost: (15.0 / 1_000_000) * 500 = 0.0075
// Total: 0.003 + 0.0075 = 0.0105
expect(cost).toBe(0.0105)
})
})
})

View File

@@ -1,126 +1,126 @@
import { enhancePrompt } from '../enhance-prompt'
import { ApiConfiguration } from '../../shared/api'
import { buildApiHandler, SingleCompletionHandler } from '../../api'
import { defaultPrompts } from '../../shared/modes'
import { enhancePrompt } from "../enhance-prompt"
import { ApiConfiguration } from "../../shared/api"
import { buildApiHandler, SingleCompletionHandler } from "../../api"
import { defaultPrompts } from "../../shared/modes"
// Mock the API handler
jest.mock('../../api', () => ({
buildApiHandler: jest.fn()
jest.mock("../../api", () => ({
buildApiHandler: jest.fn(),
}))
describe('enhancePrompt', () => {
const mockApiConfig: ApiConfiguration = {
apiProvider: 'openai',
openAiApiKey: 'test-key',
openAiBaseUrl: 'https://api.openai.com/v1'
}
describe("enhancePrompt", () => {
const mockApiConfig: ApiConfiguration = {
apiProvider: "openai",
openAiApiKey: "test-key",
openAiBaseUrl: "https://api.openai.com/v1",
}
beforeEach(() => {
jest.clearAllMocks()
// Mock the API handler with a completePrompt method
;(buildApiHandler as jest.Mock).mockReturnValue({
completePrompt: jest.fn().mockResolvedValue('Enhanced prompt'),
createMessage: jest.fn(),
getModel: jest.fn().mockReturnValue({
id: 'test-model',
info: {
maxTokens: 4096,
contextWindow: 8192,
supportsPromptCache: false
}
})
} as unknown as SingleCompletionHandler)
})
beforeEach(() => {
jest.clearAllMocks()
it('enhances prompt using default enhancement prompt when no custom prompt provided', async () => {
const result = await enhancePrompt(mockApiConfig, 'Test prompt')
expect(result).toBe('Enhanced prompt')
const handler = buildApiHandler(mockApiConfig)
expect((handler as any).completePrompt).toHaveBeenCalledWith(
`${defaultPrompts.enhance}\n\nTest prompt`
)
})
// Mock the API handler with a completePrompt method
;(buildApiHandler as jest.Mock).mockReturnValue({
completePrompt: jest.fn().mockResolvedValue("Enhanced prompt"),
createMessage: jest.fn(),
getModel: jest.fn().mockReturnValue({
id: "test-model",
info: {
maxTokens: 4096,
contextWindow: 8192,
supportsPromptCache: false,
},
}),
} as unknown as SingleCompletionHandler)
})
it('enhances prompt using custom enhancement prompt when provided', async () => {
const customEnhancePrompt = 'You are a custom prompt enhancer'
const result = await enhancePrompt(mockApiConfig, 'Test prompt', customEnhancePrompt)
expect(result).toBe('Enhanced prompt')
const handler = buildApiHandler(mockApiConfig)
expect((handler as any).completePrompt).toHaveBeenCalledWith(
`${customEnhancePrompt}\n\nTest prompt`
)
})
it("enhances prompt using default enhancement prompt when no custom prompt provided", async () => {
const result = await enhancePrompt(mockApiConfig, "Test prompt")
it('throws error for empty prompt input', async () => {
await expect(enhancePrompt(mockApiConfig, '')).rejects.toThrow('No prompt text provided')
})
expect(result).toBe("Enhanced prompt")
const handler = buildApiHandler(mockApiConfig)
expect((handler as any).completePrompt).toHaveBeenCalledWith(`${defaultPrompts.enhance}\n\nTest prompt`)
})
it('throws error for missing API configuration', async () => {
await expect(enhancePrompt({} as ApiConfiguration, 'Test prompt')).rejects.toThrow('No valid API configuration provided')
})
it("enhances prompt using custom enhancement prompt when provided", async () => {
const customEnhancePrompt = "You are a custom prompt enhancer"
it('throws error for API provider that does not support prompt enhancement', async () => {
(buildApiHandler as jest.Mock).mockReturnValue({
// No completePrompt method
createMessage: jest.fn(),
getModel: jest.fn().mockReturnValue({
id: 'test-model',
info: {
maxTokens: 4096,
contextWindow: 8192,
supportsPromptCache: false
}
})
})
const result = await enhancePrompt(mockApiConfig, "Test prompt", customEnhancePrompt)
await expect(enhancePrompt(mockApiConfig, 'Test prompt')).rejects.toThrow('The selected API provider does not support prompt enhancement')
})
expect(result).toBe("Enhanced prompt")
const handler = buildApiHandler(mockApiConfig)
expect((handler as any).completePrompt).toHaveBeenCalledWith(`${customEnhancePrompt}\n\nTest prompt`)
})
it('uses appropriate model based on provider', async () => {
const openRouterConfig: ApiConfiguration = {
apiProvider: 'openrouter',
openRouterApiKey: 'test-key',
openRouterModelId: 'test-model'
}
it("throws error for empty prompt input", async () => {
await expect(enhancePrompt(mockApiConfig, "")).rejects.toThrow("No prompt text provided")
})
// Mock successful enhancement
;(buildApiHandler as jest.Mock).mockReturnValue({
completePrompt: jest.fn().mockResolvedValue('Enhanced prompt'),
createMessage: jest.fn(),
getModel: jest.fn().mockReturnValue({
id: 'test-model',
info: {
maxTokens: 4096,
contextWindow: 8192,
supportsPromptCache: false
}
})
} as unknown as SingleCompletionHandler)
it("throws error for missing API configuration", async () => {
await expect(enhancePrompt({} as ApiConfiguration, "Test prompt")).rejects.toThrow(
"No valid API configuration provided",
)
})
const result = await enhancePrompt(openRouterConfig, 'Test prompt')
expect(buildApiHandler).toHaveBeenCalledWith(openRouterConfig)
expect(result).toBe('Enhanced prompt')
})
it("throws error for API provider that does not support prompt enhancement", async () => {
;(buildApiHandler as jest.Mock).mockReturnValue({
// No completePrompt method
createMessage: jest.fn(),
getModel: jest.fn().mockReturnValue({
id: "test-model",
info: {
maxTokens: 4096,
contextWindow: 8192,
supportsPromptCache: false,
},
}),
})
it('propagates API errors', async () => {
(buildApiHandler as jest.Mock).mockReturnValue({
completePrompt: jest.fn().mockRejectedValue(new Error('API Error')),
createMessage: jest.fn(),
getModel: jest.fn().mockReturnValue({
id: 'test-model',
info: {
maxTokens: 4096,
contextWindow: 8192,
supportsPromptCache: false
}
})
} as unknown as SingleCompletionHandler)
await expect(enhancePrompt(mockApiConfig, "Test prompt")).rejects.toThrow(
"The selected API provider does not support prompt enhancement",
)
})
await expect(enhancePrompt(mockApiConfig, 'Test prompt')).rejects.toThrow('API Error')
})
})
it("uses appropriate model based on provider", async () => {
const openRouterConfig: ApiConfiguration = {
apiProvider: "openrouter",
openRouterApiKey: "test-key",
openRouterModelId: "test-model",
}
// Mock successful enhancement
;(buildApiHandler as jest.Mock).mockReturnValue({
completePrompt: jest.fn().mockResolvedValue("Enhanced prompt"),
createMessage: jest.fn(),
getModel: jest.fn().mockReturnValue({
id: "test-model",
info: {
maxTokens: 4096,
contextWindow: 8192,
supportsPromptCache: false,
},
}),
} as unknown as SingleCompletionHandler)
const result = await enhancePrompt(openRouterConfig, "Test prompt")
expect(buildApiHandler).toHaveBeenCalledWith(openRouterConfig)
expect(result).toBe("Enhanced prompt")
})
it("propagates API errors", async () => {
;(buildApiHandler as jest.Mock).mockReturnValue({
completePrompt: jest.fn().mockRejectedValue(new Error("API Error")),
createMessage: jest.fn(),
getModel: jest.fn().mockReturnValue({
id: "test-model",
info: {
maxTokens: 4096,
contextWindow: 8192,
supportsPromptCache: false,
},
}),
} as unknown as SingleCompletionHandler)
await expect(enhancePrompt(mockApiConfig, "Test prompt")).rejects.toThrow("API Error")
})
})

View File

@@ -1,336 +1,344 @@
import { jest } from '@jest/globals'
import { searchCommits, getCommitInfo, getWorkingState, GitCommit } from '../git'
import { ExecException } from 'child_process'
import { jest } from "@jest/globals"
import { searchCommits, getCommitInfo, getWorkingState, GitCommit } from "../git"
import { ExecException } from "child_process"
type ExecFunction = (
command: string,
options: { cwd?: string },
callback: (error: ExecException | null, result?: { stdout: string; stderr: string }) => void
command: string,
options: { cwd?: string },
callback: (error: ExecException | null, result?: { stdout: string; stderr: string }) => void,
) => void
type PromisifiedExec = (command: string, options?: { cwd?: string }) => Promise<{ stdout: string; stderr: string }>
// Mock child_process.exec
jest.mock('child_process', () => ({
exec: jest.fn()
jest.mock("child_process", () => ({
exec: jest.fn(),
}))
// Mock util.promisify to return our own mock function
jest.mock('util', () => ({
promisify: jest.fn((fn: ExecFunction): PromisifiedExec => {
return async (command: string, options?: { cwd?: string }) => {
// Call the original mock to maintain the mock implementation
return new Promise((resolve, reject) => {
fn(command, options || {}, (error: ExecException | null, result?: { stdout: string; stderr: string }) => {
if (error) {
reject(error)
} else {
resolve(result!)
}
})
})
}
})
jest.mock("util", () => ({
promisify: jest.fn((fn: ExecFunction): PromisifiedExec => {
return async (command: string, options?: { cwd?: string }) => {
// Call the original mock to maintain the mock implementation
return new Promise((resolve, reject) => {
fn(
command,
options || {},
(error: ExecException | null, result?: { stdout: string; stderr: string }) => {
if (error) {
reject(error)
} else {
resolve(result!)
}
},
)
})
}
}),
}))
// Mock extract-text
jest.mock('../../integrations/misc/extract-text', () => ({
truncateOutput: jest.fn(text => text)
jest.mock("../../integrations/misc/extract-text", () => ({
truncateOutput: jest.fn((text) => text),
}))
describe('git utils', () => {
// Get the mock with proper typing
const { exec } = jest.requireMock('child_process') as { exec: jest.MockedFunction<ExecFunction> }
const cwd = '/test/path'
describe("git utils", () => {
// Get the mock with proper typing
const { exec } = jest.requireMock("child_process") as { exec: jest.MockedFunction<ExecFunction> }
const cwd = "/test/path"
beforeEach(() => {
jest.clearAllMocks()
})
beforeEach(() => {
jest.clearAllMocks()
})
describe('searchCommits', () => {
const mockCommitData = [
'abc123def456',
'abc123',
'fix: test commit',
'John Doe',
'2024-01-06',
'def456abc789',
'def456',
'feat: new feature',
'Jane Smith',
'2024-01-05'
].join('\n')
describe("searchCommits", () => {
const mockCommitData = [
"abc123def456",
"abc123",
"fix: test commit",
"John Doe",
"2024-01-06",
"def456abc789",
"def456",
"feat: new feature",
"Jane Smith",
"2024-01-05",
].join("\n")
it('should return commits when git is installed and repo exists', async () => {
// Set up mock responses
const responses = new Map([
['git --version', { stdout: 'git version 2.39.2', stderr: '' }],
['git rev-parse --git-dir', { stdout: '.git', stderr: '' }],
['git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short --grep="test" --regexp-ignore-case', { stdout: mockCommitData, stderr: '' }]
])
it("should return commits when git is installed and repo exists", async () => {
// Set up mock responses
const responses = new Map([
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
["git rev-parse --git-dir", { stdout: ".git", stderr: "" }],
[
'git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short --grep="test" --regexp-ignore-case',
{ stdout: mockCommitData, stderr: "" },
],
])
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
// Find matching response
for (const [cmd, response] of responses) {
if (command === cmd) {
callback(null, response)
return
}
}
callback(new Error(`Unexpected command: ${command}`))
})
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
// Find matching response
for (const [cmd, response] of responses) {
if (command === cmd) {
callback(null, response)
return
}
}
callback(new Error(`Unexpected command: ${command}`))
})
const result = await searchCommits('test', cwd)
const result = await searchCommits("test", cwd)
// First verify the result is correct
expect(result).toHaveLength(2)
expect(result[0]).toEqual({
hash: 'abc123def456',
shortHash: 'abc123',
subject: 'fix: test commit',
author: 'John Doe',
date: '2024-01-06'
})
// First verify the result is correct
expect(result).toHaveLength(2)
expect(result[0]).toEqual({
hash: "abc123def456",
shortHash: "abc123",
subject: "fix: test commit",
author: "John Doe",
date: "2024-01-06",
})
// Then verify all commands were called correctly
expect(exec).toHaveBeenCalledWith(
'git --version',
{},
expect.any(Function)
)
expect(exec).toHaveBeenCalledWith(
'git rev-parse --git-dir',
{ cwd },
expect.any(Function)
)
expect(exec).toHaveBeenCalledWith(
'git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short --grep="test" --regexp-ignore-case',
{ cwd },
expect.any(Function)
)
}, 20000)
// Then verify all commands were called correctly
expect(exec).toHaveBeenCalledWith("git --version", {}, expect.any(Function))
expect(exec).toHaveBeenCalledWith("git rev-parse --git-dir", { cwd }, expect.any(Function))
expect(exec).toHaveBeenCalledWith(
'git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short --grep="test" --regexp-ignore-case',
{ cwd },
expect.any(Function),
)
}, 20000)
it('should return empty array when git is not installed', async () => {
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
if (command === 'git --version') {
callback(new Error('git not found'))
return
}
callback(new Error('Unexpected command'))
})
it("should return empty array when git is not installed", async () => {
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
if (command === "git --version") {
callback(new Error("git not found"))
return
}
callback(new Error("Unexpected command"))
})
const result = await searchCommits('test', cwd)
expect(result).toEqual([])
expect(exec).toHaveBeenCalledWith('git --version', {}, expect.any(Function))
})
const result = await searchCommits("test", cwd)
expect(result).toEqual([])
expect(exec).toHaveBeenCalledWith("git --version", {}, expect.any(Function))
})
it('should return empty array when not in a git repository', async () => {
const responses = new Map([
['git --version', { stdout: 'git version 2.39.2', stderr: '' }],
['git rev-parse --git-dir', null] // null indicates error should be called
])
it("should return empty array when not in a git repository", async () => {
const responses = new Map([
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
["git rev-parse --git-dir", null], // null indicates error should be called
])
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
const response = responses.get(command)
if (response === null) {
callback(new Error('not a git repository'))
} else if (response) {
callback(null, response)
} else {
callback(new Error('Unexpected command'))
}
})
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
const response = responses.get(command)
if (response === null) {
callback(new Error("not a git repository"))
} else if (response) {
callback(null, response)
} else {
callback(new Error("Unexpected command"))
}
})
const result = await searchCommits('test', cwd)
expect(result).toEqual([])
expect(exec).toHaveBeenCalledWith('git --version', {}, expect.any(Function))
expect(exec).toHaveBeenCalledWith('git rev-parse --git-dir', { cwd }, expect.any(Function))
})
const result = await searchCommits("test", cwd)
expect(result).toEqual([])
expect(exec).toHaveBeenCalledWith("git --version", {}, expect.any(Function))
expect(exec).toHaveBeenCalledWith("git rev-parse --git-dir", { cwd }, expect.any(Function))
})
it('should handle hash search when grep search returns no results', async () => {
const responses = new Map([
['git --version', { stdout: 'git version 2.39.2', stderr: '' }],
['git rev-parse --git-dir', { stdout: '.git', stderr: '' }],
['git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short --grep="abc123" --regexp-ignore-case', { stdout: '', stderr: '' }],
['git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short --author-date-order abc123', { stdout: mockCommitData, stderr: '' }]
])
it("should handle hash search when grep search returns no results", async () => {
const responses = new Map([
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
["git rev-parse --git-dir", { stdout: ".git", stderr: "" }],
[
'git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short --grep="abc123" --regexp-ignore-case',
{ stdout: "", stderr: "" },
],
[
'git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short --author-date-order abc123',
{ stdout: mockCommitData, stderr: "" },
],
])
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
for (const [cmd, response] of responses) {
if (command === cmd) {
callback(null, response)
return
}
}
callback(new Error('Unexpected command'))
})
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
for (const [cmd, response] of responses) {
if (command === cmd) {
callback(null, response)
return
}
}
callback(new Error("Unexpected command"))
})
const result = await searchCommits('abc123', cwd)
expect(result).toHaveLength(2)
expect(result[0]).toEqual({
hash: 'abc123def456',
shortHash: 'abc123',
subject: 'fix: test commit',
author: 'John Doe',
date: '2024-01-06'
})
})
})
const result = await searchCommits("abc123", cwd)
expect(result).toHaveLength(2)
expect(result[0]).toEqual({
hash: "abc123def456",
shortHash: "abc123",
subject: "fix: test commit",
author: "John Doe",
date: "2024-01-06",
})
})
})
describe('getCommitInfo', () => {
const mockCommitInfo = [
'abc123def456',
'abc123',
'fix: test commit',
'John Doe',
'2024-01-06',
'Detailed description'
].join('\n')
const mockStats = '1 file changed, 2 insertions(+), 1 deletion(-)'
const mockDiff = '@@ -1,1 +1,2 @@\n-old line\n+new line'
describe("getCommitInfo", () => {
const mockCommitInfo = [
"abc123def456",
"abc123",
"fix: test commit",
"John Doe",
"2024-01-06",
"Detailed description",
].join("\n")
const mockStats = "1 file changed, 2 insertions(+), 1 deletion(-)"
const mockDiff = "@@ -1,1 +1,2 @@\n-old line\n+new line"
it('should return formatted commit info', async () => {
const responses = new Map([
['git --version', { stdout: 'git version 2.39.2', stderr: '' }],
['git rev-parse --git-dir', { stdout: '.git', stderr: '' }],
['git show --format="%H%n%h%n%s%n%an%n%ad%n%b" --no-patch abc123', { stdout: mockCommitInfo, stderr: '' }],
['git show --stat --format="" abc123', { stdout: mockStats, stderr: '' }],
['git show --format="" abc123', { stdout: mockDiff, stderr: '' }]
])
it("should return formatted commit info", async () => {
const responses = new Map([
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
["git rev-parse --git-dir", { stdout: ".git", stderr: "" }],
[
'git show --format="%H%n%h%n%s%n%an%n%ad%n%b" --no-patch abc123',
{ stdout: mockCommitInfo, stderr: "" },
],
['git show --stat --format="" abc123', { stdout: mockStats, stderr: "" }],
['git show --format="" abc123', { stdout: mockDiff, stderr: "" }],
])
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
for (const [cmd, response] of responses) {
if (command.startsWith(cmd)) {
callback(null, response)
return
}
}
callback(new Error('Unexpected command'))
})
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
for (const [cmd, response] of responses) {
if (command.startsWith(cmd)) {
callback(null, response)
return
}
}
callback(new Error("Unexpected command"))
})
const result = await getCommitInfo('abc123', cwd)
expect(result).toContain('Commit: abc123')
expect(result).toContain('Author: John Doe')
expect(result).toContain('Files Changed:')
expect(result).toContain('Full Changes:')
})
const result = await getCommitInfo("abc123", cwd)
expect(result).toContain("Commit: abc123")
expect(result).toContain("Author: John Doe")
expect(result).toContain("Files Changed:")
expect(result).toContain("Full Changes:")
})
it('should return error message when git is not installed', async () => {
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
if (command === 'git --version') {
callback(new Error('git not found'))
return
}
callback(new Error('Unexpected command'))
})
it("should return error message when git is not installed", async () => {
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
if (command === "git --version") {
callback(new Error("git not found"))
return
}
callback(new Error("Unexpected command"))
})
const result = await getCommitInfo('abc123', cwd)
expect(result).toBe('Git is not installed')
})
const result = await getCommitInfo("abc123", cwd)
expect(result).toBe("Git is not installed")
})
it('should return error message when not in a git repository', async () => {
const responses = new Map([
['git --version', { stdout: 'git version 2.39.2', stderr: '' }],
['git rev-parse --git-dir', null] // null indicates error should be called
])
it("should return error message when not in a git repository", async () => {
const responses = new Map([
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
["git rev-parse --git-dir", null], // null indicates error should be called
])
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
const response = responses.get(command)
if (response === null) {
callback(new Error('not a git repository'))
} else if (response) {
callback(null, response)
} else {
callback(new Error('Unexpected command'))
}
})
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
const response = responses.get(command)
if (response === null) {
callback(new Error("not a git repository"))
} else if (response) {
callback(null, response)
} else {
callback(new Error("Unexpected command"))
}
})
const result = await getCommitInfo('abc123', cwd)
expect(result).toBe('Not a git repository')
})
})
const result = await getCommitInfo("abc123", cwd)
expect(result).toBe("Not a git repository")
})
})
describe('getWorkingState', () => {
const mockStatus = ' M src/file1.ts\n?? src/file2.ts'
const mockDiff = '@@ -1,1 +1,2 @@\n-old line\n+new line'
describe("getWorkingState", () => {
const mockStatus = " M src/file1.ts\n?? src/file2.ts"
const mockDiff = "@@ -1,1 +1,2 @@\n-old line\n+new line"
it('should return working directory changes', async () => {
const responses = new Map([
['git --version', { stdout: 'git version 2.39.2', stderr: '' }],
['git rev-parse --git-dir', { stdout: '.git', stderr: '' }],
['git status --short', { stdout: mockStatus, stderr: '' }],
['git diff HEAD', { stdout: mockDiff, stderr: '' }]
])
it("should return working directory changes", async () => {
const responses = new Map([
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
["git rev-parse --git-dir", { stdout: ".git", stderr: "" }],
["git status --short", { stdout: mockStatus, stderr: "" }],
["git diff HEAD", { stdout: mockDiff, stderr: "" }],
])
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
for (const [cmd, response] of responses) {
if (command === cmd) {
callback(null, response)
return
}
}
callback(new Error('Unexpected command'))
})
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
for (const [cmd, response] of responses) {
if (command === cmd) {
callback(null, response)
return
}
}
callback(new Error("Unexpected command"))
})
const result = await getWorkingState(cwd)
expect(result).toContain('Working directory changes:')
expect(result).toContain('src/file1.ts')
expect(result).toContain('src/file2.ts')
})
const result = await getWorkingState(cwd)
expect(result).toContain("Working directory changes:")
expect(result).toContain("src/file1.ts")
expect(result).toContain("src/file2.ts")
})
it('should return message when working directory is clean', async () => {
const responses = new Map([
['git --version', { stdout: 'git version 2.39.2', stderr: '' }],
['git rev-parse --git-dir', { stdout: '.git', stderr: '' }],
['git status --short', { stdout: '', stderr: '' }]
])
it("should return message when working directory is clean", async () => {
const responses = new Map([
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
["git rev-parse --git-dir", { stdout: ".git", stderr: "" }],
["git status --short", { stdout: "", stderr: "" }],
])
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
for (const [cmd, response] of responses) {
if (command === cmd) {
callback(null, response)
return
}
}
callback(new Error('Unexpected command'))
})
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
for (const [cmd, response] of responses) {
if (command === cmd) {
callback(null, response)
return
}
}
callback(new Error("Unexpected command"))
})
const result = await getWorkingState(cwd)
expect(result).toBe('No changes in working directory')
})
const result = await getWorkingState(cwd)
expect(result).toBe("No changes in working directory")
})
it('should return error message when git is not installed', async () => {
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
if (command === 'git --version') {
callback(new Error('git not found'))
return
}
callback(new Error('Unexpected command'))
})
it("should return error message when git is not installed", async () => {
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
if (command === "git --version") {
callback(new Error("git not found"))
return
}
callback(new Error("Unexpected command"))
})
const result = await getWorkingState(cwd)
expect(result).toBe('Git is not installed')
})
const result = await getWorkingState(cwd)
expect(result).toBe("Git is not installed")
})
it('should return error message when not in a git repository', async () => {
const responses = new Map([
['git --version', { stdout: 'git version 2.39.2', stderr: '' }],
['git rev-parse --git-dir', null] // null indicates error should be called
])
it("should return error message when not in a git repository", async () => {
const responses = new Map([
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
["git rev-parse --git-dir", null], // null indicates error should be called
])
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
const response = responses.get(command)
if (response === null) {
callback(new Error('not a git repository'))
} else if (response) {
callback(null, response)
} else {
callback(new Error('Unexpected command'))
}
})
exec.mockImplementation((command: string, options: { cwd?: string }, callback: Function) => {
const response = responses.get(command)
if (response === null) {
callback(new Error("not a git repository"))
} else if (response) {
callback(null, response)
} else {
callback(new Error("Unexpected command"))
}
})
const result = await getWorkingState(cwd)
expect(result).toBe('Not a git repository')
})
})
})
const result = await getWorkingState(cwd)
expect(result).toBe("Not a git repository")
})
})
})

View File

@@ -1,135 +1,135 @@
import { arePathsEqual, getReadablePath } from '../path';
import * as path from 'path';
import os from 'os';
import { arePathsEqual, getReadablePath } from "../path"
import * as path from "path"
import os from "os"
describe('Path Utilities', () => {
const originalPlatform = process.platform;
describe("Path Utilities", () => {
const originalPlatform = process.platform
afterEach(() => {
Object.defineProperty(process, 'platform', {
value: originalPlatform
});
});
afterEach(() => {
Object.defineProperty(process, "platform", {
value: originalPlatform,
})
})
describe('String.prototype.toPosix', () => {
it('should convert backslashes to forward slashes', () => {
const windowsPath = 'C:\\Users\\test\\file.txt';
expect(windowsPath.toPosix()).toBe('C:/Users/test/file.txt');
});
describe("String.prototype.toPosix", () => {
it("should convert backslashes to forward slashes", () => {
const windowsPath = "C:\\Users\\test\\file.txt"
expect(windowsPath.toPosix()).toBe("C:/Users/test/file.txt")
})
it('should not modify paths with forward slashes', () => {
const unixPath = '/home/user/file.txt';
expect(unixPath.toPosix()).toBe('/home/user/file.txt');
});
it("should not modify paths with forward slashes", () => {
const unixPath = "/home/user/file.txt"
expect(unixPath.toPosix()).toBe("/home/user/file.txt")
})
it('should preserve extended-length Windows paths', () => {
const extendedPath = '\\\\?\\C:\\Very\\Long\\Path';
expect(extendedPath.toPosix()).toBe('\\\\?\\C:\\Very\\Long\\Path');
});
});
it("should preserve extended-length Windows paths", () => {
const extendedPath = "\\\\?\\C:\\Very\\Long\\Path"
expect(extendedPath.toPosix()).toBe("\\\\?\\C:\\Very\\Long\\Path")
})
})
describe('arePathsEqual', () => {
describe('on Windows', () => {
beforeEach(() => {
Object.defineProperty(process, 'platform', {
value: 'win32'
});
});
describe("arePathsEqual", () => {
describe("on Windows", () => {
beforeEach(() => {
Object.defineProperty(process, "platform", {
value: "win32",
})
})
it('should compare paths case-insensitively', () => {
expect(arePathsEqual('C:\\Users\\Test', 'c:\\users\\test')).toBe(true);
});
it("should compare paths case-insensitively", () => {
expect(arePathsEqual("C:\\Users\\Test", "c:\\users\\test")).toBe(true)
})
it('should handle different path separators', () => {
// Convert both paths to use forward slashes after normalization
const path1 = path.normalize('C:\\Users\\Test').replace(/\\/g, '/');
const path2 = path.normalize('C:/Users/Test').replace(/\\/g, '/');
expect(arePathsEqual(path1, path2)).toBe(true);
});
it("should handle different path separators", () => {
// Convert both paths to use forward slashes after normalization
const path1 = path.normalize("C:\\Users\\Test").replace(/\\/g, "/")
const path2 = path.normalize("C:/Users/Test").replace(/\\/g, "/")
expect(arePathsEqual(path1, path2)).toBe(true)
})
it('should normalize paths with ../', () => {
// Convert both paths to use forward slashes after normalization
const path1 = path.normalize('C:\\Users\\Test\\..\\Test').replace(/\\/g, '/');
const path2 = path.normalize('C:\\Users\\Test').replace(/\\/g, '/');
expect(arePathsEqual(path1, path2)).toBe(true);
});
});
it("should normalize paths with ../", () => {
// Convert both paths to use forward slashes after normalization
const path1 = path.normalize("C:\\Users\\Test\\..\\Test").replace(/\\/g, "/")
const path2 = path.normalize("C:\\Users\\Test").replace(/\\/g, "/")
expect(arePathsEqual(path1, path2)).toBe(true)
})
})
describe('on POSIX', () => {
beforeEach(() => {
Object.defineProperty(process, 'platform', {
value: 'darwin'
});
});
describe("on POSIX", () => {
beforeEach(() => {
Object.defineProperty(process, "platform", {
value: "darwin",
})
})
it('should compare paths case-sensitively', () => {
expect(arePathsEqual('/Users/Test', '/Users/test')).toBe(false);
});
it("should compare paths case-sensitively", () => {
expect(arePathsEqual("/Users/Test", "/Users/test")).toBe(false)
})
it('should normalize paths', () => {
expect(arePathsEqual('/Users/./Test', '/Users/Test')).toBe(true);
});
it("should normalize paths", () => {
expect(arePathsEqual("/Users/./Test", "/Users/Test")).toBe(true)
})
it('should handle trailing slashes', () => {
expect(arePathsEqual('/Users/Test/', '/Users/Test')).toBe(true);
});
});
it("should handle trailing slashes", () => {
expect(arePathsEqual("/Users/Test/", "/Users/Test")).toBe(true)
})
})
describe('edge cases', () => {
it('should handle undefined paths', () => {
expect(arePathsEqual(undefined, undefined)).toBe(true);
expect(arePathsEqual('/test', undefined)).toBe(false);
expect(arePathsEqual(undefined, '/test')).toBe(false);
});
describe("edge cases", () => {
it("should handle undefined paths", () => {
expect(arePathsEqual(undefined, undefined)).toBe(true)
expect(arePathsEqual("/test", undefined)).toBe(false)
expect(arePathsEqual(undefined, "/test")).toBe(false)
})
it('should handle root paths with trailing slashes', () => {
expect(arePathsEqual('/', '/')).toBe(true);
expect(arePathsEqual('C:\\', 'C:\\')).toBe(true);
});
});
});
it("should handle root paths with trailing slashes", () => {
expect(arePathsEqual("/", "/")).toBe(true)
expect(arePathsEqual("C:\\", "C:\\")).toBe(true)
})
})
})
describe('getReadablePath', () => {
const homeDir = os.homedir();
const desktop = path.join(homeDir, 'Desktop');
describe("getReadablePath", () => {
const homeDir = os.homedir()
const desktop = path.join(homeDir, "Desktop")
it('should return basename when path equals cwd', () => {
const cwd = '/Users/test/project';
expect(getReadablePath(cwd, cwd)).toBe('project');
});
it("should return basename when path equals cwd", () => {
const cwd = "/Users/test/project"
expect(getReadablePath(cwd, cwd)).toBe("project")
})
it('should return relative path when inside cwd', () => {
const cwd = '/Users/test/project';
const filePath = '/Users/test/project/src/file.txt';
expect(getReadablePath(cwd, filePath)).toBe('src/file.txt');
});
it("should return relative path when inside cwd", () => {
const cwd = "/Users/test/project"
const filePath = "/Users/test/project/src/file.txt"
expect(getReadablePath(cwd, filePath)).toBe("src/file.txt")
})
it('should return absolute path when outside cwd', () => {
const cwd = '/Users/test/project';
const filePath = '/Users/test/other/file.txt';
expect(getReadablePath(cwd, filePath)).toBe('/Users/test/other/file.txt');
});
it("should return absolute path when outside cwd", () => {
const cwd = "/Users/test/project"
const filePath = "/Users/test/other/file.txt"
expect(getReadablePath(cwd, filePath)).toBe("/Users/test/other/file.txt")
})
it('should handle Desktop as cwd', () => {
const filePath = path.join(desktop, 'file.txt');
expect(getReadablePath(desktop, filePath)).toBe(filePath.toPosix());
});
it("should handle Desktop as cwd", () => {
const filePath = path.join(desktop, "file.txt")
expect(getReadablePath(desktop, filePath)).toBe(filePath.toPosix())
})
it('should handle undefined relative path', () => {
const cwd = '/Users/test/project';
expect(getReadablePath(cwd)).toBe('project');
});
it("should handle undefined relative path", () => {
const cwd = "/Users/test/project"
expect(getReadablePath(cwd)).toBe("project")
})
it('should handle parent directory traversal', () => {
const cwd = '/Users/test/project';
const filePath = '../../other/file.txt';
expect(getReadablePath(cwd, filePath)).toBe('/Users/other/file.txt');
});
it("should handle parent directory traversal", () => {
const cwd = "/Users/test/project"
const filePath = "../../other/file.txt"
expect(getReadablePath(cwd, filePath)).toBe("/Users/other/file.txt")
})
it('should normalize paths with redundant segments', () => {
const cwd = '/Users/test/project';
const filePath = '/Users/test/project/./src/../src/file.txt';
expect(getReadablePath(cwd, filePath)).toBe('src/file.txt');
});
});
});
it("should normalize paths with redundant segments", () => {
const cwd = "/Users/test/project"
const filePath = "/Users/test/project/./src/../src/file.txt"
expect(getReadablePath(cwd, filePath)).toBe("src/file.txt")
})
})
})

View File

@@ -6,22 +6,26 @@ import { defaultPrompts } from "../shared/modes"
* Enhances a prompt using the configured API without creating a full Cline instance or task history.
* This is a lightweight alternative that only uses the API's completion functionality.
*/
export async function enhancePrompt(apiConfiguration: ApiConfiguration, promptText: string, enhancePrompt?: string): Promise<string> {
if (!promptText) {
throw new Error("No prompt text provided")
}
if (!apiConfiguration || !apiConfiguration.apiProvider) {
throw new Error("No valid API configuration provided")
}
const handler = buildApiHandler(apiConfiguration)
// Check if handler supports single completions
if (!('completePrompt' in handler)) {
throw new Error("The selected API provider does not support prompt enhancement")
}
const enhancePromptText = enhancePrompt ?? defaultPrompts.enhance
const prompt = `${enhancePromptText}\n\n${promptText}`
return (handler as SingleCompletionHandler).completePrompt(prompt)
}
export async function enhancePrompt(
apiConfiguration: ApiConfiguration,
promptText: string,
enhancePrompt?: string,
): Promise<string> {
if (!promptText) {
throw new Error("No prompt text provided")
}
if (!apiConfiguration || !apiConfiguration.apiProvider) {
throw new Error("No valid API configuration provided")
}
const handler = buildApiHandler(apiConfiguration)
// Check if handler supports single completions
if (!("completePrompt" in handler)) {
throw new Error("The selected API provider does not support prompt enhancement")
}
const enhancePromptText = enhancePrompt ?? defaultPrompts.enhance
const prompt = `${enhancePromptText}\n\n${promptText}`
return (handler as SingleCompletionHandler).completePrompt(prompt)
}

View File

@@ -15,7 +15,7 @@ export interface GitCommit {
async function checkGitRepo(cwd: string): Promise<boolean> {
try {
await execAsync('git rev-parse --git-dir', { cwd })
await execAsync("git rev-parse --git-dir", { cwd })
return true
} catch (error) {
return false
@@ -24,7 +24,7 @@ async function checkGitRepo(cwd: string): Promise<boolean> {
async function checkGitInstalled(): Promise<boolean> {
try {
await execAsync('git --version')
await execAsync("git --version")
return true
} catch (error) {
return false
@@ -47,18 +47,16 @@ export async function searchCommits(query: string, cwd: string): Promise<GitComm
// Search commits by hash or message, limiting to 10 results
const { stdout } = await execAsync(
`git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short ` +
`--grep="${query}" --regexp-ignore-case`,
{ cwd }
`git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short ` + `--grep="${query}" --regexp-ignore-case`,
{ cwd },
)
let output = stdout
if (!output.trim() && /^[a-f0-9]+$/i.test(query)) {
// If no results from grep search and query looks like a hash, try searching by hash
const { stdout: hashStdout } = await execAsync(
`git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short ` +
`--author-date-order ${query}`,
{ cwd }
`git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short ` + `--author-date-order ${query}`,
{ cwd },
).catch(() => ({ stdout: "" }))
if (!hashStdout.trim()) {
@@ -69,7 +67,10 @@ export async function searchCommits(query: string, cwd: string): Promise<GitComm
}
const commits: GitCommit[] = []
const lines = output.trim().split("\n").filter(line => line !== "--")
const lines = output
.trim()
.split("\n")
.filter((line) => line !== "--")
for (let i = 0; i < lines.length; i += 5) {
commits.push({
@@ -77,7 +78,7 @@ export async function searchCommits(query: string, cwd: string): Promise<GitComm
shortHash: lines[i + 1],
subject: lines[i + 2],
author: lines[i + 3],
date: lines[i + 4]
date: lines[i + 4],
})
}
@@ -101,34 +102,27 @@ export async function getCommitInfo(hash: string, cwd: string): Promise<string>
}
// Get commit info, stats, and diff separately
const { stdout: info } = await execAsync(
`git show --format="%H%n%h%n%s%n%an%n%ad%n%b" --no-patch ${hash}`,
{ cwd }
)
const [fullHash, shortHash, subject, author, date, body] = info.trim().split('\n')
const { stdout: stats } = await execAsync(
`git show --stat --format="" ${hash}`,
{ cwd }
)
const { stdout: info } = await execAsync(`git show --format="%H%n%h%n%s%n%an%n%ad%n%b" --no-patch ${hash}`, {
cwd,
})
const [fullHash, shortHash, subject, author, date, body] = info.trim().split("\n")
const { stdout: diff } = await execAsync(
`git show --format="" ${hash}`,
{ cwd }
)
const { stdout: stats } = await execAsync(`git show --stat --format="" ${hash}`, { cwd })
const { stdout: diff } = await execAsync(`git show --format="" ${hash}`, { cwd })
const summary = [
`Commit: ${shortHash} (${fullHash})`,
`Author: ${author}`,
`Date: ${date}`,
`\nMessage: ${subject}`,
body ? `\nDescription:\n${body}` : '',
'\nFiles Changed:',
body ? `\nDescription:\n${body}` : "",
"\nFiles Changed:",
stats.trim(),
'\nFull Changes:'
].join('\n')
"\nFull Changes:",
].join("\n")
const output = summary + '\n\n' + diff.trim()
const output = summary + "\n\n" + diff.trim()
return truncateOutput(output, GIT_OUTPUT_LINE_LIMIT)
} catch (error) {
console.error("Error getting commit info:", error)
@@ -149,13 +143,13 @@ export async function getWorkingState(cwd: string): Promise<string> {
}
// Get status of working directory
const { stdout: status } = await execAsync('git status --short', { cwd })
const { stdout: status } = await execAsync("git status --short", { cwd })
if (!status.trim()) {
return "No changes in working directory"
}
// Get all changes (both staged and unstaged) compared to HEAD
const { stdout: diff } = await execAsync('git diff HEAD', { cwd })
const { stdout: diff } = await execAsync("git diff HEAD", { cwd })
const lineLimit = GIT_OUTPUT_LINE_LIMIT
const output = `Working directory changes:\n\n${status}\n\n${diff}`.trim()
return truncateOutput(output, lineLimit)
@@ -163,4 +157,4 @@ export async function getWorkingState(cwd: string): Promise<string> {
console.error("Error getting working state:", error)
return `Failed to get working state: ${error instanceof Error ? error.message : String(error)}`
}
}
}

View File

@@ -21,7 +21,7 @@ export const isWAV = (filepath: string): boolean => {
}
let isSoundEnabled = false
let volume = .5
let volume = 0.5
/**
* Set sound configuration