Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/renovate.json5 → .github/renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["github>rstackjs/renovate"]
}

4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
# Run `npm run bump` to bump the version and create a git tag.
push:
tags:
- "v*"
- 'v*'

workflow_dispatch:

Expand Down Expand Up @@ -47,4 +47,4 @@ jobs:
- name: Create GitHub Release
uses: ncipollo/release-action@339a81892b84b4eeb0f6e744e4574d79d0d9b8dd # v1
with:
generateReleaseNotes: "true"
generateReleaseNotes: 'true'
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version: 24.14.1
cache: "pnpm"
cache: 'pnpm'

- name: Install Dependencies
run: pnpm install && npx playwright install
Expand Down
4 changes: 1 addition & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
{
"search.useIgnoreFiles": true,
"cSpell.words": [
"rslint"
],
"cSpell.words": ["rslint"]
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"scripts": {
"build": "rslib",
"dev": "rslib --watch",
"lint": "rslint",
"lint": "rslint && prettier . --check",
"lint:fix": "rslint --fix && prettier . --write",
Comment thread
chenjiahan marked this conversation as resolved.
"prepare": "simple-git-hooks && rslib",
"test": "rstest",
"bump": "npx bumpp"
Expand Down
8 changes: 8 additions & 0 deletions test/agents.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,14 @@ test('should generate AGENTS.md with no tools selected', async () => {
## Development

### Common Development

- Common development instructions
- Available in all templates

## Tools

### Common Tools

- Tools that apply to all templates

### Rstest
Expand Down Expand Up @@ -100,12 +102,14 @@ test('should generate AGENTS.md with single tool selected', async () => {
## Development

### Common Development

- Common development instructions
- Available in all templates

## Tools

### Common Tools

- Tools that apply to all templates

### Rstest
Expand Down Expand Up @@ -163,12 +167,14 @@ test('should generate AGENTS.md with eslint tool and template mapping', async ()
## Development

### Common Development

- Common development instructions
- Available in all templates

## Tools

### Common Tools

- Tools that apply to all templates

### Rstest
Expand Down Expand Up @@ -212,12 +218,14 @@ test('should merge top-level sections from AGENTS.md files', async () => {
## Development

### Common Development

- Common development instructions
- Available in all templates

## Tools

### Common Tools

- Tools that apply to all templates

### Rstest
Expand Down
2 changes: 2 additions & 0 deletions test/custom-tools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ const mocks = rs.hoisted(() => {
stderr: '',
exitCode: 0,
};
// rslint-disable-next-line @typescript-eslint/no-explicit-any
}) as any,
// rslint-disable-next-line @typescript-eslint/no-explicit-any
xSync: rs.fn(() => ({ stdout: '', stderr: '', exitCode: 0 })) as any,
};
});
Expand Down
2 changes: 2 additions & 0 deletions test/fixtures/agents-md/template-common/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ This section provides common guidance for all templates.
## Development

### Common Development

- Common development instructions
- Available in all templates

## Tools

### Common Tools

- Tools that apply to all templates
104 changes: 53 additions & 51 deletions test/skills.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ const mocks = rs.hoisted(() => {
xCalls: [] as ExecCall[],
taskLogEvents: [] as TaskLogEvent[],
commandLogs: [] as string[],
promptOptions: [] as Array<{ value: string; label?: string; hint?: string }>,
promptOptions: [] as Array<{
value: string;
label?: string;
hint?: string;
}>,
};

function createExecStream(result: ExecResult, lines: string[] = []) {
Expand All @@ -60,6 +64,7 @@ const mocks = rs.hoisted(() => {
stderr: '',
exitCode: 0,
});
// rslint-disable-next-line @typescript-eslint/no-explicit-any
}) as any;

const xSync = rs.fn((command: string, args: string[], options: unknown) => {
Expand All @@ -68,6 +73,7 @@ const mocks = rs.hoisted(() => {
stderr: '',
exitCode: 0,
};
// rslint-disable-next-line @typescript-eslint/no-explicit-any
}) as any;

const spinner = (() => ({
Expand Down Expand Up @@ -98,19 +104,21 @@ const mocks = rs.hoisted(() => {
return taskLog({ title });
};

const multiselect = rs.fn(async (options: {
message?: string;
options?: Array<{ value: unknown; label?: string; hint?: string }>;
}) => {
if (options.message?.includes('Select optional skills')) {
state.promptOptions = (options.options ?? []) as Array<{
value: string;
label?: string;
hint?: string;
}>;
}
return [];
}) as typeof promptsActual.multiselect;
const multiselect = rs.fn(
async (options: {
message?: string;
options?: Array<{ value: unknown; label?: string; hint?: string }>;
}) => {
if (options.message?.includes('Select optional skills')) {
state.promptOptions = (options.options ?? []) as Array<{
value: string;
label?: string;
hint?: string;
}>;
}
return [];
},
) as typeof promptsActual.multiselect;

return {
state,
Expand Down Expand Up @@ -199,7 +207,10 @@ function createExecCommand(
if ('then' in Object(output)) {
const promise = Promise.resolve(output).then((resolvedOutput) =>
'result' in resolvedOutput
? mocks.createExecStream(resolvedOutput.result, resolvedOutput.lines)
? mocks.createExecStream(
resolvedOutput.result,
resolvedOutput.lines,
)
: mocks.createExecStream(resolvedOutput),
);

Expand All @@ -209,9 +220,13 @@ function createExecCommand(
finally: promise.finally.bind(promise),
async *[Symbol.asyncIterator]() {
const resolvedOutput = await output;
const stream = 'result' in resolvedOutput
? mocks.createExecStream(resolvedOutput.result, resolvedOutput.lines)
: mocks.createExecStream(resolvedOutput);
const stream =
'result' in resolvedOutput
? mocks.createExecStream(
resolvedOutput.result,
resolvedOutput.lines,
)
: mocks.createExecStream(resolvedOutput);
for await (const line of stream) {
yield line;
}
Expand Down Expand Up @@ -655,14 +670,7 @@ test('should skip skill installation when --dir and --template are used without
source: 'vercel-labs/agent-skills',
},
],
argv: [
'node',
'test',
'--dir',
projectDir,
'--template',
'vanilla',
],
argv: ['node', 'test', '--dir', projectDir, '--template', 'vanilla'],
});

expect(calls).toHaveLength(0);
Expand Down Expand Up @@ -695,15 +703,7 @@ test('should prove --skill skips the skills prompt even without --dir and --temp
source: 'vercel-labs/agent-skills',
},
],
argv: [
'node',
'test',
projectDir,
'--tools',
'',
'--skill',
'git-url',
],
argv: ['node', 'test', projectDir, '--tools', '', '--skill', 'git-url'],
});

expect(skillsPromptReached).toBe(false);
Expand Down Expand Up @@ -1297,23 +1297,25 @@ test('should stream install output and show the command error in the task log wh

test('should order skill prompt options using pre, default, and post order', async () => {
const projectDir = path.join(testDir, 'skills-ordering-proof');
rs.mocked(mocks.multiselect).mockImplementation(async <Value,>({
message,
options,
}: {
message?: string;
options?: Array<{ value: Value; label?: string; hint?: string }>;
}) => {
if (message?.includes('Select optional skills')) {
mocks.state.promptOptions = (options ?? []) as Array<{
value: string;
label?: string;
hint?: string;
}>;
rs.mocked(mocks.multiselect).mockImplementation(
async <Value>({
message,
options,
}: {
message?: string;
options?: Array<{ value: Value; label?: string; hint?: string }>;
}) => {
if (message?.includes('Select optional skills')) {
mocks.state.promptOptions = (options ?? []) as Array<{
value: string;
label?: string;
hint?: string;
}>;
return [];
}
return [];
}
return [];
});
},
);

await create({
name: 'test',
Expand Down
Loading