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
30 changes: 30 additions & 0 deletions packages/cli/e2e/__tests__/skills.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ import { runCheckly } from '../run-checkly'
const actionIds = ACTIONS.map(a => a.id)
const referenceShortIds = REFERENCES.map(r => r.id.replace('configure-', ''))
const investigateReferenceShortIds = INVESTIGATE_REFERENCES.map(r => r.id.replace('investigate-', ''))
const referencesByAction = ACTIONS.flatMap(action => {
if (!('references' in action)) {
return []
}

return action.references.map(reference => ({
actionId: action.id,
shortId: reference.id.replace(`${action.id}-`, ''),
}))
})

describe('checkly skills', () => {
let fixt: FixtureSandbox
Expand Down Expand Up @@ -44,6 +54,26 @@ describe('checkly skills', () => {
expect(stdout).toContain(`$ checkly skills investigate ${investigateReferenceShortIds[0]}`)
})

it('should list all actions and references in help output', async () => {
const { stdout } = await runCheckly(fixt, ['skills', '--help'])

expect(stdout).toContain('Available actions and references:')
expect(stdout).toContain('checkly skills configure api-checks')
expect(stdout).toContain('checkly skills investigate alerting')

for (const id of actionIds) {
expect(stdout).toContain(`|- ${id}`)
}

for (const { actionId, shortId } of referencesByAction) {
expect(stdout).toContain(`|- ${actionId}`)
expect(stdout).toContain(`| |- ${shortId}`)
}

expect(stdout).not.toContain(REFERENCES[0].description)
expect(stdout).not.toContain(INVESTIGATE_REFERENCES[0].description)
})

it('should show the initialize action content', async () => {
const { stdout } = await runCheckly(fixt, ['skills', 'initialize'])
expect(stdout).toBeTruthy()
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/src/commands/__tests__/command-metadata.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import ImportCommit from '../import/commit.js'
import ImportCancel from '../import/cancel.js'
import PwTest from '../pw-test.js'
import SyncPlaywright from '../sync-playwright.js'
import Skills from '../skills/index.js'
import SkillsInstall from '../skills/install.js'
import AccountPlan from '../account/plan.js'
import Members from '../members.js'
Expand Down Expand Up @@ -91,6 +92,7 @@ const commands: Array<[string, typeof BaseCommand]> = [
['import cancel', ImportCancel],
['pw-test', PwTest],
['sync-playwright', SyncPlaywright],
['skills', Skills],
['skills install', SkillsInstall],
]

Expand Down
49 changes: 44 additions & 5 deletions packages/cli/src/commands/skills/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,57 @@ const __dirname = dirname(fileURLToPath(import.meta.url))

const REFERENCES_DIR = join(__dirname, '../../ai-context/skills-command/references')

function referenceShortId (actionId: string, referenceId: string): string {
return referenceId.replace(`${actionId}-`, '')
}

function formatAvailableActionTree (): string {
return [
' checkly skills',
...ACTIONS.flatMap(action => {
const actionLine = ` |- ${action.id}`
if (!('references' in action)) {
return [actionLine]
}

const references = action.references
.map(reference => ` | |- ${referenceShortId(action.id, reference.id)}`)
return [actionLine, ...references]
}),
].join('\n')
}

export default class Skills extends BaseCommand {
static hidden = false
static description = 'Show Checkly AI skills, actions and their references.'
static readOnly = true
static destructive = false
static idempotent = true
static description = [
'Show Checkly AI skills, actions and their references.',
'',
'Run `checkly skills` to print the full catalog, `checkly skills <action>` for an action guide, or `checkly skills <action> <reference>` for a specific reference.',
'',
'Available actions and references:',
formatAvailableActionTree(),
'',
'Use `checkly skills <action>` or `checkly skills <action> <reference>` to open the detailed guidance.',
].join('\n')

static examples = [
'checkly skills',
'checkly skills configure',
'checkly skills configure api-checks',
'checkly skills investigate alerting',
]

static args = {
action: Args.string({
required: false,
description: 'The action name (e.g. "configure", "initialize").',
description: 'Action to open. Available actions are listed below.',
}),
reference: Args.string({
required: false,
description: 'A specific reference within the action (e.g. "api-checks").',
description: 'Reference to open for the selected action. Available references are listed below.',
}),
}

Expand Down Expand Up @@ -75,7 +114,7 @@ export default class Skills extends BaseCommand {
this.log(` $ checkly skills ${action.id}`)
if ('references' in action) {
const firstRef = action.references[0]
const refId = firstRef.id.replace(`${action.id}-`, '')
const refId = referenceShortId(action.id, firstRef.id)
this.log(` $ checkly skills ${action.id} ${refId}`)
}
}
Expand All @@ -98,7 +137,7 @@ export default class Skills extends BaseCommand {
this.log(`References for "${action.id}":\n`)

const refs = action.references.map(r => ({
shortId: r.id.replace(`${action.id}-`, ''),
shortId: referenceShortId(action.id, r.id),
description: r.description,
}))
const maxRefLen = Math.max(...refs.map(r => r.shortId.length))
Expand Down
Loading