Skip to content

Commit 9c1dcbe

Browse files
cursor[bot]cursoragentkentcdodds
authored
fix: resolve relative workshop paths (#589)
Fixes EPICSHOP-ED Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
1 parent 5d7a3c0 commit 9c1dcbe

2 files changed

Lines changed: 22 additions & 6 deletions

File tree

packages/workshop-mcp/src/utils.test.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,26 @@ test('handleWorkshopDirectory rejects blank input (aha)', async () => {
126126
)
127127
})
128128

129-
test('handleWorkshopDirectory rejects relative paths', async () => {
130-
await expect(handleWorkshopDirectory('workshop')).rejects.toThrow(
131-
'The workshop directory must be an absolute path',
132-
)
129+
test('handleWorkshopDirectory resolves relative paths from cwd (aha)', async () => {
130+
await using fixture = await createWorkshopFixture()
131+
vi.mocked(console.error).mockImplementation(() => {})
132+
const originalCwd = process.cwd()
133+
const parentDir = path.dirname(fixture.root)
134+
const relativePath = path.relative(parentDir, fixture.root)
135+
136+
const { init } = await import('@epic-web/workshop-utils/apps.server')
137+
const initMock = vi.mocked(init)
138+
initMock.mockClear()
139+
140+
try {
141+
process.chdir(parentDir)
142+
await expect(handleWorkshopDirectory(relativePath)).resolves.toBe(
143+
fixture.root,
144+
)
145+
expect(initMock).toHaveBeenCalledWith(fixture.root)
146+
} finally {
147+
process.chdir(originalCwd)
148+
}
133149
})
134150

135151
test('handleWorkshopDirectory normalizes playground to workshop root', async () => {

packages/workshop-mcp/src/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { z } from 'zod/v3'
99
export const workshopDirectoryInputSchema = z
1010
.string()
1111
.describe(
12-
'Absolute path to the workshop root directory. Passing a /playground path is allowed and will be normalized to the workshop root.',
12+
'Absolute or relative path to the workshop root directory. Relative paths are resolved from the current working directory. Passing a /playground path is allowed and will be normalized to the workshop root.',
1313
)
1414

1515
async function isWorkshopDirectory(workshopDirectory: string) {
@@ -41,7 +41,7 @@ export async function handleWorkshopDirectory(workshopDirectory: string) {
4141
if (!workshopDirectory) throw new Error('The workshop directory is required')
4242

4343
if (!path.isAbsolute(workshopDirectory)) {
44-
throw new Error('The workshop directory must be an absolute path')
44+
workshopDirectory = path.resolve(process.cwd(), workshopDirectory)
4545
}
4646

4747
if (workshopDirectory.endsWith(`${path.sep}playground`)) {

0 commit comments

Comments
 (0)