opencode-onboard 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +304 -301
- package/content/.agents/agents/basic-engineer.md +4 -2
- package/content/.agents/agents/devops-manager.md +123 -123
- package/content/.agents/skills/ob-default/SKILL.md +25 -21
- package/content/.agents/skills/ob-generic-guardrails/SKILL.md +36 -32
- package/content/.agents/skills/ob-global/SKILL.md +92 -49
- package/content/.agents/skills/ob-pullrequest-az/SKILL.md +168 -160
- package/content/.agents/skills/ob-pullrequest-gh/SKILL.md +140 -136
- package/content/.opencode/commands/create-engineer.md +109 -0
- package/content/.opencode/commands/init.md +1 -1
- package/content/.opencode/commands/main.md +1 -1
- package/content/.opencode/commands/opsx-apply.md +131 -70
- package/content/.opencode/commands/plan.md +1 -1
- package/content/.opencode/plugins/session-log.js +523 -519
- package/content/.opencode/skills/openspec-apply-change/SKILL.md +86 -64
- package/content/AGENTS.md +67 -39
- package/package.json +1 -1
- package/src/commands/join.js +3 -3
- package/src/commands/single.js +2 -0
- package/src/commands/wizard.js +124 -99
- package/src/presets/browser.json +22 -18
- package/src/presets/optimization.json +27 -22
- package/src/presets/source.json +7 -1
- package/src/steps/browser/browser.test.js +115 -81
- package/src/steps/browser/index.js +62 -54
- package/src/steps/clean/index.js +108 -107
- package/src/steps/copy/agents.js +28 -0
- package/src/steps/copy/copy.test.js +1 -0
- package/src/steps/copy/index.js +2 -1
- package/src/steps/metadata/index.js +63 -61
- package/src/steps/models/format.js +61 -60
- package/src/steps/models/write.test.js +117 -117
- package/src/steps/openspec/ensemble.js +30 -7
- package/src/steps/openspec/ensemble.test.js +79 -79
- package/src/steps/openspec/index.js +121 -32
- package/src/steps/openspec/index.test.js +63 -0
- package/src/steps/optimization/caveman.js +34 -29
- package/src/steps/optimization/codegraph.js +52 -0
- package/src/steps/optimization/global.js +88 -64
- package/src/steps/optimization/global.test.js +99 -0
- package/src/steps/optimization/index.js +109 -101
- package/src/steps/optimization/optimization.test.js +101 -93
- package/src/steps/optimization/quota.js +84 -84
- package/src/steps/source/index.js +48 -0
- package/src/steps/source/source.test.js +124 -91
- package/src/utils/__tests__/copy.test.js +117 -117
- package/src/utils/exec-spinner.js +47 -47
- package/src/utils/exec.js +134 -131
- package/src/utils/terminal.js +6 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
|
2
|
+
import fs from 'node:fs'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import os from 'node:os'
|
|
5
|
+
|
|
6
|
+
vi.mock('../../utils/exec.js', () => ({
|
|
7
|
+
info: vi.fn(),
|
|
8
|
+
success: vi.fn(),
|
|
9
|
+
warn: vi.fn(),
|
|
10
|
+
}))
|
|
11
|
+
|
|
12
|
+
import { configureObGlobal } from './global.js'
|
|
13
|
+
|
|
14
|
+
const SKILL_TEMPLATE = `## Token Optimization Rules
|
|
15
|
+
|
|
16
|
+
<!-- OB-SOURCE-ROOTS-START -->
|
|
17
|
+
placeholder
|
|
18
|
+
<!-- OB-SOURCE-ROOTS-END -->
|
|
19
|
+
|
|
20
|
+
<!-- OB-RTK-START -->
|
|
21
|
+
placeholder
|
|
22
|
+
<!-- OB-RTK-END -->
|
|
23
|
+
|
|
24
|
+
<!-- OB-CAVEMAN-START -->
|
|
25
|
+
placeholder
|
|
26
|
+
<!-- OB-CAVEMAN-END -->
|
|
27
|
+
|
|
28
|
+
<!-- OB-CODEGRAPH-START -->
|
|
29
|
+
placeholder
|
|
30
|
+
<!-- OB-CODEGRAPH-END -->
|
|
31
|
+
`
|
|
32
|
+
|
|
33
|
+
describe('configureObGlobal()', () => {
|
|
34
|
+
let tmpDir
|
|
35
|
+
let skillPath
|
|
36
|
+
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ob-global-test-'))
|
|
39
|
+
const skillDir = path.join(tmpDir, '.agents', 'skills', 'ob-global')
|
|
40
|
+
fs.mkdirSync(skillDir, { recursive: true })
|
|
41
|
+
skillPath = path.join(skillDir, 'SKILL.md')
|
|
42
|
+
fs.writeFileSync(skillPath, SKILL_TEMPLATE, 'utf-8')
|
|
43
|
+
vi.spyOn(process, 'cwd').mockReturnValue(tmpDir)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
afterEach(() => {
|
|
47
|
+
fs.rmSync(tmpDir, { recursive: true, force: true })
|
|
48
|
+
vi.restoreAllMocks()
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('returns configured:false when ob-global skill is missing', async () => {
|
|
52
|
+
fs.rmSync(skillPath)
|
|
53
|
+
const result = await configureObGlobal()
|
|
54
|
+
expect(result).toEqual({ configured: false })
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('injects source roots section', async () => {
|
|
58
|
+
await configureObGlobal({ sourceRoots: [tmpDir] }, {})
|
|
59
|
+
const content = fs.readFileSync(skillPath, 'utf-8')
|
|
60
|
+
expect(content).toContain('Read and analyze code ONLY from these roots')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('injects RTK section when rtk is opted in', async () => {
|
|
64
|
+
await configureObGlobal({}, { rtk: { optedIn: true } })
|
|
65
|
+
const content = fs.readFileSync(skillPath, 'utf-8')
|
|
66
|
+
expect(content).toContain('RTK, MANDATORY')
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('injects RTK not-selected note when rtk is not opted in', async () => {
|
|
70
|
+
await configureObGlobal({}, { rtk: { optedIn: false } })
|
|
71
|
+
const content = fs.readFileSync(skillPath, 'utf-8')
|
|
72
|
+
expect(content).toContain('RTK was not selected during onboarding')
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('injects caveman section when caveman is opted in', async () => {
|
|
76
|
+
await configureObGlobal({}, { caveman: { optedIn: true } })
|
|
77
|
+
const content = fs.readFileSync(skillPath, 'utf-8')
|
|
78
|
+
expect(content).toContain('caveman mode')
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('injects codegraph section when codegraph is opted in', async () => {
|
|
82
|
+
await configureObGlobal({}, { codegraph: { optedIn: true } })
|
|
83
|
+
const content = fs.readFileSync(skillPath, 'utf-8')
|
|
84
|
+
expect(content).toContain('CodeGraph')
|
|
85
|
+
expect(content).toContain('codegraph_explore')
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('injects codegraph not-selected note when codegraph is not opted in', async () => {
|
|
89
|
+
await configureObGlobal({}, { codegraph: { optedIn: false } })
|
|
90
|
+
const content = fs.readFileSync(skillPath, 'utf-8')
|
|
91
|
+
expect(content).toContain('Codegraph was not selected during onboarding')
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('returns configured:true with skill path on success', async () => {
|
|
95
|
+
const result = await configureObGlobal({}, {})
|
|
96
|
+
expect(result.configured).toBe(true)
|
|
97
|
+
expect(result.path).toBe(skillPath)
|
|
98
|
+
})
|
|
99
|
+
})
|
|
@@ -1,101 +1,109 @@
|
|
|
1
|
-
import { checkbox, confirm } from '@inquirer/prompts'
|
|
2
|
-
import fse from 'fs-extra'
|
|
3
|
-
import path from 'path'
|
|
4
|
-
import { fileURLToPath } from 'url'
|
|
5
|
-
import { code, commandExists, header, info, loading, success, warn } from '../../utils/exec.js'
|
|
6
|
-
import { installQuota } from './quota.js'
|
|
7
|
-
import { installCaveman } from './caveman.js'
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
info('
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
: {
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
1
|
+
import { checkbox, confirm } from '@inquirer/prompts'
|
|
2
|
+
import fse from 'fs-extra'
|
|
3
|
+
import path from 'path'
|
|
4
|
+
import { fileURLToPath } from 'url'
|
|
5
|
+
import { code, commandExists, header, info, loading, success, warn } from '../../utils/exec.js'
|
|
6
|
+
import { installQuota } from './quota.js'
|
|
7
|
+
import { installCaveman } from './caveman.js'
|
|
8
|
+
import { installCodegraph } from './codegraph.js'
|
|
9
|
+
import { enableCavemanGuidance } from './caveman-guidance.js'
|
|
10
|
+
import { configureObGlobal } from './global.js'
|
|
11
|
+
|
|
12
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
13
|
+
const OPTIMIZATION_PRESET_PATH = path.resolve(__dirname, '../../presets/optimization.json')
|
|
14
|
+
const optimizationPreset = await fse.readJson(OPTIMIZATION_PRESET_PATH)
|
|
15
|
+
|
|
16
|
+
export async function checkRtk(options = {}) {
|
|
17
|
+
if (!options.skipHeader) header('Checking rtk')
|
|
18
|
+
|
|
19
|
+
let shouldCheck = true
|
|
20
|
+
if (!options.skipPrompt) {
|
|
21
|
+
info('Recommended: install and verify rtk for safer agent CLI command execution.')
|
|
22
|
+
shouldCheck = await confirm({
|
|
23
|
+
message: 'Check rtk now?',
|
|
24
|
+
default: true,
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!shouldCheck) {
|
|
29
|
+
warn('Skipped rtk check (you can install it later)')
|
|
30
|
+
return { optedIn: false, checked: false, available: false }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
loading('checking rtk...')
|
|
34
|
+
|
|
35
|
+
const available = await commandExists('rtk')
|
|
36
|
+
|
|
37
|
+
if (available) {
|
|
38
|
+
success('rtk is available')
|
|
39
|
+
return { optedIn: true, checked: true, available: true }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
warn('rtk not found on PATH.')
|
|
43
|
+
console.log()
|
|
44
|
+
info('rtk is required for agents to run CLI commands safely.')
|
|
45
|
+
info('Install it from: https://github.com/rtk-ai/rtk#pre-built-binaries')
|
|
46
|
+
console.log()
|
|
47
|
+
info('After installing, verify with:')
|
|
48
|
+
code(['rtk --version'])
|
|
49
|
+
return { optedIn: true, checked: true, available: false }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function tokenOptimizationStep(options = {}) {
|
|
53
|
+
header('Step 8, Token optimization tools')
|
|
54
|
+
|
|
55
|
+
const defaultSelected = optimizationPreset.choices
|
|
56
|
+
.filter(choice => choice.checked)
|
|
57
|
+
.map(choice => choice.value)
|
|
58
|
+
let selected = defaultSelected
|
|
59
|
+
|
|
60
|
+
if (!options.skipPrompt && process.stdin.isTTY) {
|
|
61
|
+
info(optimizationPreset.info)
|
|
62
|
+
const timeoutMs = optimizationPreset.timeoutMs
|
|
63
|
+
const choice = await Promise.race([
|
|
64
|
+
checkbox({
|
|
65
|
+
message: optimizationPreset.message,
|
|
66
|
+
choices: optimizationPreset.choices,
|
|
67
|
+
}),
|
|
68
|
+
new Promise(resolve => { setTimeout(() => resolve(defaultSelected), timeoutMs) }),
|
|
69
|
+
])
|
|
70
|
+
selected = Array.isArray(choice) ? choice : defaultSelected
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
loading('applying token optimization selections...')
|
|
74
|
+
|
|
75
|
+
const installScope = options.ctx?.installScope || 'local'
|
|
76
|
+
|
|
77
|
+
const has = value => selected.includes(value)
|
|
78
|
+
|
|
79
|
+
const rtk = has('rtk')
|
|
80
|
+
? await checkRtk({ skipHeader: true, skipPrompt: true })
|
|
81
|
+
: { optedIn: false, checked: false, available: false }
|
|
82
|
+
|
|
83
|
+
const quota = has('quota')
|
|
84
|
+
? await installQuota({ skipHeader: true, skipPrompt: true })
|
|
85
|
+
: { optedIn: false, installed: false }
|
|
86
|
+
|
|
87
|
+
const caveman = has('caveman')
|
|
88
|
+
? await installCaveman({
|
|
89
|
+
skipHeader: true,
|
|
90
|
+
skipPrompt: true,
|
|
91
|
+
installScope,
|
|
92
|
+
})
|
|
93
|
+
: { optedIn: false, installed: false }
|
|
94
|
+
|
|
95
|
+
const cavemanGuidance = has('caveman')
|
|
96
|
+
? await enableCavemanGuidance(caveman)
|
|
97
|
+
: { enabled: false }
|
|
98
|
+
|
|
99
|
+
const codegraph = has('codegraph')
|
|
100
|
+
? await installCodegraph({ skipHeader: true, installScope })
|
|
101
|
+
: { optedIn: false, installed: false }
|
|
102
|
+
|
|
103
|
+
const obGlobal = await configureObGlobal(options.ctx || {}, { rtk, quota, caveman, cavemanGuidance, codegraph })
|
|
104
|
+
|
|
105
|
+
if (selected.length === 0) warn('No token optimization tools selected')
|
|
106
|
+
else success('Token optimization step completed')
|
|
107
|
+
|
|
108
|
+
return { rtk, quota, caveman, cavemanGuidance, codegraph, obGlobal }
|
|
109
|
+
}
|
|
@@ -1,93 +1,101 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
-
|
|
3
|
-
vi.mock('@inquirer/prompts', () => ({
|
|
4
|
-
checkbox: vi.fn(),
|
|
5
|
-
confirm: vi.fn(),
|
|
6
|
-
}))
|
|
7
|
-
|
|
8
|
-
vi.mock('../../utils/exec.js', () => ({
|
|
9
|
-
code: vi.fn(),
|
|
10
|
-
commandExists: vi.fn(),
|
|
11
|
-
header: vi.fn(),
|
|
12
|
-
info: vi.fn(),
|
|
13
|
-
loading: vi.fn(),
|
|
14
|
-
success: vi.fn(),
|
|
15
|
-
warn: vi.fn(),
|
|
16
|
-
}))
|
|
17
|
-
|
|
18
|
-
vi.mock('./quota.js', () => ({ installQuota: vi.fn() }))
|
|
19
|
-
vi.mock('./caveman.js', () => ({ installCaveman: vi.fn() }))
|
|
20
|
-
vi.mock('./
|
|
21
|
-
vi.mock('./
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
{ value: '
|
|
32
|
-
{ value: '
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
expect(
|
|
71
|
-
expect(
|
|
72
|
-
expect(
|
|
73
|
-
expect(
|
|
74
|
-
expect(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
expect(
|
|
89
|
-
expect(
|
|
90
|
-
expect(
|
|
91
|
-
expect(
|
|
92
|
-
|
|
93
|
-
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
|
|
3
|
+
vi.mock('@inquirer/prompts', () => ({
|
|
4
|
+
checkbox: vi.fn(),
|
|
5
|
+
confirm: vi.fn(),
|
|
6
|
+
}))
|
|
7
|
+
|
|
8
|
+
vi.mock('../../utils/exec.js', () => ({
|
|
9
|
+
code: vi.fn(),
|
|
10
|
+
commandExists: vi.fn(),
|
|
11
|
+
header: vi.fn(),
|
|
12
|
+
info: vi.fn(),
|
|
13
|
+
loading: vi.fn(),
|
|
14
|
+
success: vi.fn(),
|
|
15
|
+
warn: vi.fn(),
|
|
16
|
+
}))
|
|
17
|
+
|
|
18
|
+
vi.mock('./quota.js', () => ({ installQuota: vi.fn() }))
|
|
19
|
+
vi.mock('./caveman.js', () => ({ installCaveman: vi.fn() }))
|
|
20
|
+
vi.mock('./codegraph.js', () => ({ installCodegraph: vi.fn() }))
|
|
21
|
+
vi.mock('./caveman-guidance.js', () => ({ enableCavemanGuidance: vi.fn() }))
|
|
22
|
+
vi.mock('./global.js', () => ({ configureObGlobal: vi.fn() }))
|
|
23
|
+
|
|
24
|
+
vi.mock('fs-extra', () => ({
|
|
25
|
+
default: {
|
|
26
|
+
readJson: vi.fn().mockResolvedValue({
|
|
27
|
+
info: 'Token optimization info',
|
|
28
|
+
message: 'Select tools',
|
|
29
|
+
timeoutMs: 5000,
|
|
30
|
+
choices: [
|
|
31
|
+
{ value: 'rtk', checked: false },
|
|
32
|
+
{ value: 'quota', checked: false },
|
|
33
|
+
{ value: 'caveman', checked: false },
|
|
34
|
+
{ value: 'codegraph', checked: false },
|
|
35
|
+
],
|
|
36
|
+
}),
|
|
37
|
+
},
|
|
38
|
+
}))
|
|
39
|
+
|
|
40
|
+
import { checkbox } from '@inquirer/prompts'
|
|
41
|
+
import { commandExists, warn } from '../../utils/exec.js'
|
|
42
|
+
import { installQuota } from './quota.js'
|
|
43
|
+
import { installCaveman } from './caveman.js'
|
|
44
|
+
import { installCodegraph } from './codegraph.js'
|
|
45
|
+
import { enableCavemanGuidance } from './caveman-guidance.js'
|
|
46
|
+
import { configureObGlobal } from './global.js'
|
|
47
|
+
import { tokenOptimizationStep } from './index.js'
|
|
48
|
+
|
|
49
|
+
describe('tokenOptimizationStep()', () => {
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
vi.clearAllMocks()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('runs all optimizations by default selection', async () => {
|
|
55
|
+
const originalIsTTY = process.stdin.isTTY
|
|
56
|
+
Object.defineProperty(process.stdin, 'isTTY', { value: true, configurable: true })
|
|
57
|
+
|
|
58
|
+
checkbox.mockResolvedValue(['rtk', 'quota', 'caveman', 'codegraph'])
|
|
59
|
+
commandExists.mockResolvedValue(true)
|
|
60
|
+
installQuota.mockResolvedValue({ optedIn: true, installed: true })
|
|
61
|
+
installCaveman.mockResolvedValue({ optedIn: true, installed: true })
|
|
62
|
+
installCodegraph.mockResolvedValue({ optedIn: true, installed: true })
|
|
63
|
+
enableCavemanGuidance.mockResolvedValue({ enabled: true })
|
|
64
|
+
configureObGlobal.mockResolvedValue({ configured: true })
|
|
65
|
+
|
|
66
|
+
const result = await tokenOptimizationStep()
|
|
67
|
+
|
|
68
|
+
Object.defineProperty(process.stdin, 'isTTY', { value: originalIsTTY, configurable: true })
|
|
69
|
+
|
|
70
|
+
expect(commandExists).toHaveBeenCalledWith('rtk')
|
|
71
|
+
expect(installQuota).toHaveBeenCalledWith({ skipHeader: true, skipPrompt: true })
|
|
72
|
+
expect(installCaveman).toHaveBeenCalledWith(expect.objectContaining({ skipHeader: true, skipPrompt: true }))
|
|
73
|
+
expect(installCodegraph).toHaveBeenCalledWith(expect.objectContaining({ skipHeader: true }))
|
|
74
|
+
expect(enableCavemanGuidance).toHaveBeenCalledWith({ optedIn: true, installed: true })
|
|
75
|
+
expect(configureObGlobal).toHaveBeenCalled()
|
|
76
|
+
expect(result.rtk.available).toBe(true)
|
|
77
|
+
expect(result.quota.installed).toBe(true)
|
|
78
|
+
expect(result.caveman.installed).toBe(true)
|
|
79
|
+
expect(result.cavemanGuidance.enabled).toBe(true)
|
|
80
|
+
expect(result.codegraph.installed).toBe(true)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('skips all tools when nothing is selected', async () => {
|
|
84
|
+
checkbox.mockResolvedValue([])
|
|
85
|
+
|
|
86
|
+
const result = await tokenOptimizationStep()
|
|
87
|
+
|
|
88
|
+
expect(commandExists).not.toHaveBeenCalled()
|
|
89
|
+
expect(installQuota).not.toHaveBeenCalled()
|
|
90
|
+
expect(installCaveman).not.toHaveBeenCalled()
|
|
91
|
+
expect(installCodegraph).not.toHaveBeenCalled()
|
|
92
|
+
expect(enableCavemanGuidance).not.toHaveBeenCalled()
|
|
93
|
+
expect(configureObGlobal).toHaveBeenCalled()
|
|
94
|
+
expect(warn).toHaveBeenCalledWith('No token optimization tools selected')
|
|
95
|
+
expect(result.rtk.optedIn).toBe(false)
|
|
96
|
+
expect(result.quota.optedIn).toBe(false)
|
|
97
|
+
expect(result.caveman.optedIn).toBe(false)
|
|
98
|
+
expect(result.cavemanGuidance.enabled).toBe(false)
|
|
99
|
+
expect(result.codegraph.optedIn).toBe(false)
|
|
100
|
+
})
|
|
101
|
+
})
|