@plainconceptsplatform/agent-harness 2.0.0 → 2.1.0
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/README.md +426 -419
- package/package.json +3 -3
- package/src/commands/join.js +244 -244
- package/src/commands/shared.js +27 -27
- package/src/commands/single.js +79 -79
- package/src/commands/update.js +109 -109
- package/src/commands/wizard.js +134 -134
- package/src/content/.agents/skills/browser-automation/SKILL.md +66 -66
- package/src/content/.agents/skills/pc-guardrails-generic/SKILL.md +68 -68
- package/src/content/.agents/skills/pc-guardrails-project/SKILL.md +8 -8
- package/src/content/.agents/skills/pc-make-architecture/SKILL.md +51 -51
- package/src/content/.agents/skills/pc-make-architecture/structure-template.md +38 -38
- package/src/content/.agents/skills/pc-make-design/SKILL.md +68 -68
- package/src/content/.agents/skills/pc-make-engineer/SKILL.md +219 -219
- package/src/content/.agents/skills/pc-make-engineer/signal-mapping.md +68 -68
- package/src/content/.agents/skills/pc-make-engineer/template.md +81 -81
- package/src/content/.agents/skills/pc-make-evidence-scaffold/SKILL.md +18 -18
- package/src/content/.agents/skills/pc-make-evidence-scaffold/evidence-contract.md +29 -29
- package/src/content/.agents/skills/pc-make-guardrails/SKILL.md +74 -74
- package/src/content/.agents/skills/pc-make-guardrails/category-reference.md +68 -68
- package/src/content/.agents/skills/pc-make-merge-risk-assess/SKILL.md +70 -70
- package/src/content/.agents/skills/pc-make-merge-risk-assess/category-reference.md +98 -98
- package/src/content/.agents/skills/pc-make-user-model/SKILL.md +66 -66
- package/src/content/.agents/skills/pc-ops-evidence/SKILL.md +127 -127
- package/src/content/.agents/skills/pc-ops-ship/SKILL.md +18 -18
- package/src/content/.agents/skills/pc-plan-apply/SKILL.md +83 -83
- package/src/content/.agents/skills/pc-plan-apply/simple-mode.md +21 -21
- package/src/content/.agents/skills/pc-plan-archive/SKILL.md +63 -63
- package/src/content/.agents/skills/pc-plan-explore/SKILL.md +9 -9
- package/src/content/.agents/skills/pc-plan-goal/SKILL.md +94 -94
- package/src/content/.agents/skills/pc-plan-goal/branching.md +30 -30
- package/src/content/.agents/skills/pc-plan-goal/failure-policy.md +30 -30
- package/src/content/.agents/skills/pc-plan-goal/output-mode.md +9 -9
- package/src/content/.agents/skills/pc-plan-goal/output.md +68 -68
- package/src/content/.agents/skills/pc-plan-propose/SKILL.md +125 -125
- package/src/content/.agents/skills/pc-plan-propose/task-annotation.md +39 -39
- package/src/content/.agents/skills/pc-plan-quick/SKILL.md +62 -62
- package/src/content/.agents/skills/pc-plan-story/SKILL.md +146 -146
- package/src/content/.agents/skills/pc-repo-audit/SKILL.md +44 -44
- package/src/content/.agents/skills/pc-repo-help/SKILL.md +91 -91
- package/src/content/.agents/skills/pc-repo-initialize/SKILL.md +130 -130
- package/src/content/.agents/skills/pc-repo-onboard/SKILL.md +87 -87
- package/src/content/.agents/skills/pc-repo-verify/SKILL.md +34 -34
- package/src/content/.agents/skills/pc-userstory-az/SKILL.md +157 -157
- package/src/content/.agents/skills/pc-userstory-browser/SKILL.md +132 -132
- package/src/content/.agents/skills/pc-userstory-gh/SKILL.md +120 -120
- package/src/content/.agents/skills/pc-userstory-jira/SKILL.md +131 -131
- package/src/content/.opencode/_gitignore +9 -7
- package/src/content/.opencode/commands/init.md +5 -5
- package/src/content/.opencode/commands/make-architecture.md +5 -5
- package/src/content/.opencode/commands/make-design.md +5 -5
- package/src/content/.opencode/commands/make-engineer.md +5 -5
- package/src/content/.opencode/commands/make-evidence-scaffold.md +5 -5
- package/src/content/.opencode/commands/make-guardrails.md +5 -5
- package/src/content/.opencode/commands/make-user-model.md +5 -5
- package/src/content/.opencode/commands/ops-backlog.md +10 -10
- package/src/content/.opencode/commands/ops-evidence.md +9 -9
- package/src/content/.opencode/commands/ops-review.md +8 -8
- package/src/content/.opencode/commands/ops-ship.md +9 -9
- package/src/content/.opencode/commands/plan-apply.md +9 -9
- package/src/content/.opencode/commands/plan-archive.md +5 -5
- package/src/content/.opencode/commands/plan-explore.md +9 -9
- package/src/content/.opencode/commands/plan-goal.md +5 -5
- package/src/content/.opencode/commands/plan-propose.md +9 -9
- package/src/content/.opencode/commands/plan-quick.md +5 -5
- package/src/content/.opencode/commands/plan-story.md +9 -9
- package/src/content/.opencode/commands/repo-audit.md +5 -5
- package/src/content/.opencode/commands/repo-help.md +5 -5
- package/src/content/.opencode/commands/repo-initialize.md +5 -5
- package/src/content/.opencode/commands/repo-onboard.md +5 -5
- package/src/content/.opencode/commands/repo-verify.md +5 -5
- package/src/content/.opencode/plugins/pc-subagent-monitor.js +139 -139
- package/src/content/.opencode/plugins/pc-subagent-tiers.js +281 -179
- package/src/content/.opencode/plugins/pc-system-reminders.js +96 -96
- package/src/content/.opencode/tui/pc-subagents.tsx +98 -98
- package/src/content/.opencode/tui.json +6 -6
- package/src/content/AGENTS.md +71 -71
- package/src/content/opencode.jsonc +39 -31
- package/src/fragments/archive/az.md +95 -95
- package/src/fragments/archive/gh.md +94 -94
- package/src/fragments/archive/gl.md +94 -94
- package/src/fragments/archive/none.md +73 -73
- package/src/fragments/guardrails/codegraph.md +7 -7
- package/src/fragments/guardrails/humanizer.md +4 -4
- package/src/fragments/guardrails/memory.md +4 -4
- package/src/fragments/guardrails/rtk.md +3 -3
- package/src/fragments/guardrails/simple-english.md +4 -4
- package/src/fragments/ops-backlog/az.md +28 -28
- package/src/fragments/ops-backlog/gh.md +29 -29
- package/src/fragments/ops-backlog/jira.md +28 -28
- package/src/fragments/ops-evidence/az.md +41 -41
- package/src/fragments/ops-evidence/gh.md +53 -53
- package/src/fragments/ops-evidence/jira.md +38 -38
- package/src/fragments/ops-review/az.md +62 -62
- package/src/fragments/ops-review/gh.md +52 -52
- package/src/fragments/ops-review/gl.md +56 -56
- package/src/fragments/ops-ship/az.md +80 -80
- package/src/fragments/ops-ship/gh.md +68 -68
- package/src/fragments/ops-ship/gl.md +85 -85
- package/src/index.js +107 -107
- package/src/presets/agents-content.json +53 -53
- package/src/presets/models.json +68 -68
- package/src/steps/copy/agents.js +118 -118
- package/src/steps/copy/commands.js +91 -91
- package/src/steps/copy/fullstack-engineer.js +85 -83
- package/src/steps/copy/index.js +88 -88
- package/src/steps/copy/opencode-json.js +147 -129
- package/src/steps/copy/skills.js +196 -196
- package/src/steps/metadata/index.js +108 -108
- package/src/steps/models/write.js +34 -34
- package/src/steps/optimization/patch-guardrails.js +108 -108
- package/src/utils/copy.js +108 -108
- package/src/utils/legacy-check.js +30 -30
- package/src/utils/models-cache.js +58 -58
- package/src/utils/paths.js +67 -64
- package/src/utils/update-manifest.js +49 -49
- package/src/content/.opencode/plugins/pc-system-reminders.test.js +0 -35
package/src/commands/single.js
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
import fse from 'fs-extra'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import { fileURLToPath } from 'url'
|
|
4
|
-
import { cleanAiFiles } from '../steps/clean/index.js'
|
|
5
|
-
import { copyContentStep } from '../steps/copy/index.js'
|
|
6
|
-
import { chooseModels } from '../steps/models/index.js'
|
|
7
|
-
import { initOpenspec } from '../steps/openspec/index.js'
|
|
8
|
-
import { tokenOptimizationStep } from '../steps/optimization/index.js'
|
|
9
|
-
import { choosePlatform } from '../steps/platform/index.js'
|
|
10
|
-
import { installBrowser } from '../steps/browser/index.js'
|
|
11
|
-
import { writeHarnessConfig } from '../steps/metadata/index.js'
|
|
12
|
-
import { readHarnessConfig } from './shared.js'
|
|
13
|
-
|
|
14
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
15
|
-
const platformsPreset = await fse.readJson(path.resolve(__dirname, '../presets/platforms.json'))
|
|
16
|
-
// platforms.json is the single source of truth for valid platform values.
|
|
17
|
-
// Hardcoding a subset here silently rewrote jira/gitlab/browser projects to github.
|
|
18
|
-
const VALID_PLATFORMS = new Set(platformsPreset.map(p => p.value))
|
|
19
|
-
|
|
20
|
-
export function resolvePlatform(value, fallback = 'github') {
|
|
21
|
-
return VALID_PLATFORMS.has(value) ? value : fallback
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export async function runSingleCommand(command) {
|
|
25
|
-
const saved = await readHarnessConfig()
|
|
26
|
-
const ctx = {
|
|
27
|
-
hasDesign: !!saved?.preexisting?.design,
|
|
28
|
-
hasArchitecture: !!saved?.preexisting?.architecture,
|
|
29
|
-
hasOpenspec: !!saved?.preexisting?.openspec,
|
|
30
|
-
sourceMode: saved?.source?.mode ?? 'current',
|
|
31
|
-
sourceRoots: Array.isArray(saved?.source?.roots) ? saved.source.roots : [],
|
|
32
|
-
maxConcurrentAgents: saved?.agents?.maxConcurrent ?? 3,
|
|
33
|
-
}
|
|
34
|
-
const backlogPlatform = saved?.platform?.backlog
|
|
35
|
-
const repoPlatform = saved?.platform?.repo
|
|
36
|
-
const resolvedBacklog = resolvePlatform(backlogPlatform)
|
|
37
|
-
const resolvedRepo = resolvePlatform(repoPlatform)
|
|
38
|
-
|
|
39
|
-
const handlers = {
|
|
40
|
-
clean: async () => {
|
|
41
|
-
await cleanAiFiles()
|
|
42
|
-
},
|
|
43
|
-
platform: async () => {
|
|
44
|
-
await choosePlatform()
|
|
45
|
-
},
|
|
46
|
-
copy: async () => {
|
|
47
|
-
await copyContentStep({ backlogPlatform: resolvedBacklog, repoPlatform: resolvedRepo }, ctx)
|
|
48
|
-
},
|
|
49
|
-
openspec: async () => {
|
|
50
|
-
await initOpenspec()
|
|
51
|
-
},
|
|
52
|
-
models: async () => {
|
|
53
|
-
await chooseModels()
|
|
54
|
-
},
|
|
55
|
-
optimization: async () => {
|
|
56
|
-
await tokenOptimizationStep({ ctx })
|
|
57
|
-
},
|
|
58
|
-
browser: async () => {
|
|
59
|
-
await installBrowser()
|
|
60
|
-
},
|
|
61
|
-
metadata: async () => {
|
|
62
|
-
await writeHarnessConfig({
|
|
63
|
-
...ctx,
|
|
64
|
-
backlogPlatform: resolvedBacklog,
|
|
65
|
-
repoPlatform: resolvedRepo,
|
|
66
|
-
maxConcurrentAgents: saved?.agents?.maxConcurrent ?? 3,
|
|
67
|
-
planModel: saved?.models?.plan ?? null,
|
|
68
|
-
buildModel: saved?.models?.build ?? null,
|
|
69
|
-
fastModel: saved?.models?.fast ?? null,
|
|
70
|
-
optionalTools: saved?.tools ?? null,
|
|
71
|
-
})
|
|
72
|
-
},
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const handler = handlers[command]
|
|
76
|
-
if (!handler) return false
|
|
77
|
-
await handler()
|
|
78
|
-
return true
|
|
79
|
-
}
|
|
1
|
+
import fse from 'fs-extra'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'url'
|
|
4
|
+
import { cleanAiFiles } from '../steps/clean/index.js'
|
|
5
|
+
import { copyContentStep } from '../steps/copy/index.js'
|
|
6
|
+
import { chooseModels } from '../steps/models/index.js'
|
|
7
|
+
import { initOpenspec } from '../steps/openspec/index.js'
|
|
8
|
+
import { tokenOptimizationStep } from '../steps/optimization/index.js'
|
|
9
|
+
import { choosePlatform } from '../steps/platform/index.js'
|
|
10
|
+
import { installBrowser } from '../steps/browser/index.js'
|
|
11
|
+
import { writeHarnessConfig } from '../steps/metadata/index.js'
|
|
12
|
+
import { readHarnessConfig } from './shared.js'
|
|
13
|
+
|
|
14
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
15
|
+
const platformsPreset = await fse.readJson(path.resolve(__dirname, '../presets/platforms.json'))
|
|
16
|
+
// platforms.json is the single source of truth for valid platform values.
|
|
17
|
+
// Hardcoding a subset here silently rewrote jira/gitlab/browser projects to github.
|
|
18
|
+
const VALID_PLATFORMS = new Set(platformsPreset.map(p => p.value))
|
|
19
|
+
|
|
20
|
+
export function resolvePlatform(value, fallback = 'github') {
|
|
21
|
+
return VALID_PLATFORMS.has(value) ? value : fallback
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function runSingleCommand(command) {
|
|
25
|
+
const saved = await readHarnessConfig()
|
|
26
|
+
const ctx = {
|
|
27
|
+
hasDesign: !!saved?.preexisting?.design,
|
|
28
|
+
hasArchitecture: !!saved?.preexisting?.architecture,
|
|
29
|
+
hasOpenspec: !!saved?.preexisting?.openspec,
|
|
30
|
+
sourceMode: saved?.source?.mode ?? 'current',
|
|
31
|
+
sourceRoots: Array.isArray(saved?.source?.roots) ? saved.source.roots : [],
|
|
32
|
+
maxConcurrentAgents: saved?.agents?.maxConcurrent ?? 3,
|
|
33
|
+
}
|
|
34
|
+
const backlogPlatform = saved?.platform?.backlog
|
|
35
|
+
const repoPlatform = saved?.platform?.repo
|
|
36
|
+
const resolvedBacklog = resolvePlatform(backlogPlatform)
|
|
37
|
+
const resolvedRepo = resolvePlatform(repoPlatform)
|
|
38
|
+
|
|
39
|
+
const handlers = {
|
|
40
|
+
clean: async () => {
|
|
41
|
+
await cleanAiFiles()
|
|
42
|
+
},
|
|
43
|
+
platform: async () => {
|
|
44
|
+
await choosePlatform()
|
|
45
|
+
},
|
|
46
|
+
copy: async () => {
|
|
47
|
+
await copyContentStep({ backlogPlatform: resolvedBacklog, repoPlatform: resolvedRepo }, ctx)
|
|
48
|
+
},
|
|
49
|
+
openspec: async () => {
|
|
50
|
+
await initOpenspec()
|
|
51
|
+
},
|
|
52
|
+
models: async () => {
|
|
53
|
+
await chooseModels()
|
|
54
|
+
},
|
|
55
|
+
optimization: async () => {
|
|
56
|
+
await tokenOptimizationStep({ ctx })
|
|
57
|
+
},
|
|
58
|
+
browser: async () => {
|
|
59
|
+
await installBrowser()
|
|
60
|
+
},
|
|
61
|
+
metadata: async () => {
|
|
62
|
+
await writeHarnessConfig({
|
|
63
|
+
...ctx,
|
|
64
|
+
backlogPlatform: resolvedBacklog,
|
|
65
|
+
repoPlatform: resolvedRepo,
|
|
66
|
+
maxConcurrentAgents: saved?.agents?.maxConcurrent ?? 3,
|
|
67
|
+
planModel: saved?.models?.plan ?? null,
|
|
68
|
+
buildModel: saved?.models?.build ?? null,
|
|
69
|
+
fastModel: saved?.models?.fast ?? null,
|
|
70
|
+
optionalTools: saved?.tools ?? null,
|
|
71
|
+
})
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const handler = handlers[command]
|
|
76
|
+
if (!handler) return false
|
|
77
|
+
await handler()
|
|
78
|
+
return true
|
|
79
|
+
}
|
package/src/commands/update.js
CHANGED
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
import chalk from 'chalk'
|
|
2
|
-
import { execa } from 'execa'
|
|
3
|
-
import fse from 'fs-extra'
|
|
4
|
-
import path from 'node:path'
|
|
5
|
-
import { fileURLToPath } from 'url'
|
|
6
|
-
import { readHarnessConfig } from './shared.js'
|
|
7
|
-
import { copyContentStep } from '../steps/copy/index.js'
|
|
8
|
-
import { writeModelsToConfigs } from '../steps/models/write.js'
|
|
9
|
-
import { patchGuardrails } from '../steps/optimization/patch-guardrails.js'
|
|
10
|
-
import { writeHarnessConfig } from '../steps/metadata/index.js'
|
|
11
|
-
import { exit } from '../utils/process.js'
|
|
12
|
-
|
|
13
|
-
const SIMPLE_ENGLISH_ENTRY = {
|
|
14
|
-
source: 'AminBlg/SimpleEnglish',
|
|
15
|
-
sourceType: 'github',
|
|
16
|
-
skillPath: 'skills/simple-english/SKILL.md',
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
20
|
-
const platformsPreset = await fse.readJson(path.resolve(__dirname, '../presets/platforms.json'))
|
|
21
|
-
const VALID_PLATFORMS = new Set(platformsPreset.map(p => p.value))
|
|
22
|
-
|
|
23
|
-
function resolvePlatform(value, fallback = 'github') {
|
|
24
|
-
return VALID_PLATFORMS.has(value) ? value : fallback
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export async function runUpdate() {
|
|
28
|
-
const saved = await readHarnessConfig()
|
|
29
|
-
if (!saved?.platform) {
|
|
30
|
-
console.log(chalk.red('No agent-harness config found. Run the wizard first.'))
|
|
31
|
-
exit(1)
|
|
32
|
-
return
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const backlogPlatform = resolvePlatform(saved.platform.backlog)
|
|
36
|
-
const repoPlatform = resolvePlatform(saved.platform.repo)
|
|
37
|
-
|
|
38
|
-
const ctx = {
|
|
39
|
-
hasDesign: !!saved.preexisting?.design,
|
|
40
|
-
hasArchitecture: !!saved.preexisting?.architecture,
|
|
41
|
-
hasOpenspec: !!saved.preexisting?.openspec,
|
|
42
|
-
sourceMode: saved.source?.mode ?? 'current',
|
|
43
|
-
sourceRoots: Array.isArray(saved.source?.roots) ? saved.source.roots : [],
|
|
44
|
-
maxConcurrentAgents: saved.agents?.maxConcurrent ?? 3,
|
|
45
|
-
installScope: 'local',
|
|
46
|
-
skipSkills: false,
|
|
47
|
-
updateMode: true,
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
console.log()
|
|
51
|
-
console.log(chalk.bold('Updating project from saved config'))
|
|
52
|
-
console.log(chalk.dim(` backlog: ${backlogPlatform} repo: ${repoPlatform} agents: ${ctx.maxConcurrentAgents}`))
|
|
53
|
-
console.log()
|
|
54
|
-
|
|
55
|
-
await copyContentStep({ backlogPlatform, repoPlatform }, ctx)
|
|
56
|
-
|
|
57
|
-
if (saved.models) {
|
|
58
|
-
await writeModelsToConfigs({ buildModel: saved.models.build })
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const tools = saved.tools ?? {}
|
|
62
|
-
await migrateCavemanSkill(tools)
|
|
63
|
-
await patchGuardrails({
|
|
64
|
-
rtk: !!tools.rtk,
|
|
65
|
-
simpleEnglish: !!(tools.simpleEnglish || tools.caveman),
|
|
66
|
-
codegraph: !!tools.codegraph,
|
|
67
|
-
memory: !!tools.memory,
|
|
68
|
-
humanizer: !!tools.humanizer,
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
await writeHarnessConfig({
|
|
72
|
-
...ctx,
|
|
73
|
-
backlogPlatform,
|
|
74
|
-
repoPlatform,
|
|
75
|
-
maxConcurrentAgents: ctx.maxConcurrentAgents,
|
|
76
|
-
planModel: saved.models?.plan ?? null,
|
|
77
|
-
buildModel: saved.models?.build ?? null,
|
|
78
|
-
fastModel: saved.models?.fast ?? null,
|
|
79
|
-
optionalTools: tools,
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
console.log()
|
|
83
|
-
console.log(chalk.bold.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
|
|
84
|
-
console.log(chalk.bold.green(' Update complete!'))
|
|
85
|
-
console.log(chalk.bold.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
|
|
86
|
-
console.log()
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
async function migrateCavemanSkill(tools) {
|
|
90
|
-
if (!tools.caveman || tools.simpleEnglish) return
|
|
91
|
-
|
|
92
|
-
const lockPath = path.join(process.cwd(), 'skills-lock.json')
|
|
93
|
-
const lock = await fse.readJson(lockPath).catch(() => ({ version: 1, skills: {} }))
|
|
94
|
-
lock.skills ??= {}
|
|
95
|
-
delete lock.skills.caveman
|
|
96
|
-
lock.skills['simple-english'] = SIMPLE_ENGLISH_ENTRY
|
|
97
|
-
await fse.writeJson(lockPath, lock, { spaces: 2 })
|
|
98
|
-
await fse.remove(path.join(process.cwd(), '.agents', 'skills', 'caveman'))
|
|
99
|
-
|
|
100
|
-
const result = await execa('npx', ['skills', 'experimental_install', '--yes'], {
|
|
101
|
-
cwd: process.cwd(),
|
|
102
|
-
reject: false,
|
|
103
|
-
stdio: 'pipe',
|
|
104
|
-
timeout: 600000,
|
|
105
|
-
})
|
|
106
|
-
if (result.exitCode !== 0) {
|
|
107
|
-
console.log(chalk.yellow('Simple English was added to skills-lock.json but could not be installed. Run npx skills experimental_install --yes.'))
|
|
108
|
-
}
|
|
109
|
-
}
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import { execa } from 'execa'
|
|
3
|
+
import fse from 'fs-extra'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'url'
|
|
6
|
+
import { readHarnessConfig } from './shared.js'
|
|
7
|
+
import { copyContentStep } from '../steps/copy/index.js'
|
|
8
|
+
import { writeModelsToConfigs } from '../steps/models/write.js'
|
|
9
|
+
import { patchGuardrails } from '../steps/optimization/patch-guardrails.js'
|
|
10
|
+
import { writeHarnessConfig } from '../steps/metadata/index.js'
|
|
11
|
+
import { exit } from '../utils/process.js'
|
|
12
|
+
|
|
13
|
+
const SIMPLE_ENGLISH_ENTRY = {
|
|
14
|
+
source: 'AminBlg/SimpleEnglish',
|
|
15
|
+
sourceType: 'github',
|
|
16
|
+
skillPath: 'skills/simple-english/SKILL.md',
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
20
|
+
const platformsPreset = await fse.readJson(path.resolve(__dirname, '../presets/platforms.json'))
|
|
21
|
+
const VALID_PLATFORMS = new Set(platformsPreset.map(p => p.value))
|
|
22
|
+
|
|
23
|
+
function resolvePlatform(value, fallback = 'github') {
|
|
24
|
+
return VALID_PLATFORMS.has(value) ? value : fallback
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function runUpdate() {
|
|
28
|
+
const saved = await readHarnessConfig()
|
|
29
|
+
if (!saved?.platform) {
|
|
30
|
+
console.log(chalk.red('No agent-harness config found. Run the wizard first.'))
|
|
31
|
+
exit(1)
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const backlogPlatform = resolvePlatform(saved.platform.backlog)
|
|
36
|
+
const repoPlatform = resolvePlatform(saved.platform.repo)
|
|
37
|
+
|
|
38
|
+
const ctx = {
|
|
39
|
+
hasDesign: !!saved.preexisting?.design,
|
|
40
|
+
hasArchitecture: !!saved.preexisting?.architecture,
|
|
41
|
+
hasOpenspec: !!saved.preexisting?.openspec,
|
|
42
|
+
sourceMode: saved.source?.mode ?? 'current',
|
|
43
|
+
sourceRoots: Array.isArray(saved.source?.roots) ? saved.source.roots : [],
|
|
44
|
+
maxConcurrentAgents: saved.agents?.maxConcurrent ?? 3,
|
|
45
|
+
installScope: 'local',
|
|
46
|
+
skipSkills: false,
|
|
47
|
+
updateMode: true,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
console.log()
|
|
51
|
+
console.log(chalk.bold('Updating project from saved config'))
|
|
52
|
+
console.log(chalk.dim(` backlog: ${backlogPlatform} repo: ${repoPlatform} agents: ${ctx.maxConcurrentAgents}`))
|
|
53
|
+
console.log()
|
|
54
|
+
|
|
55
|
+
await copyContentStep({ backlogPlatform, repoPlatform }, ctx)
|
|
56
|
+
|
|
57
|
+
if (saved.models) {
|
|
58
|
+
await writeModelsToConfigs({ buildModel: saved.models.build })
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const tools = saved.tools ?? {}
|
|
62
|
+
await migrateCavemanSkill(tools)
|
|
63
|
+
await patchGuardrails({
|
|
64
|
+
rtk: !!tools.rtk,
|
|
65
|
+
simpleEnglish: !!(tools.simpleEnglish || tools.caveman),
|
|
66
|
+
codegraph: !!tools.codegraph,
|
|
67
|
+
memory: !!tools.memory,
|
|
68
|
+
humanizer: !!tools.humanizer,
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
await writeHarnessConfig({
|
|
72
|
+
...ctx,
|
|
73
|
+
backlogPlatform,
|
|
74
|
+
repoPlatform,
|
|
75
|
+
maxConcurrentAgents: ctx.maxConcurrentAgents,
|
|
76
|
+
planModel: saved.models?.plan ?? null,
|
|
77
|
+
buildModel: saved.models?.build ?? null,
|
|
78
|
+
fastModel: saved.models?.fast ?? null,
|
|
79
|
+
optionalTools: tools,
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
console.log()
|
|
83
|
+
console.log(chalk.bold.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
|
|
84
|
+
console.log(chalk.bold.green(' Update complete!'))
|
|
85
|
+
console.log(chalk.bold.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
|
|
86
|
+
console.log()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function migrateCavemanSkill(tools) {
|
|
90
|
+
if (!tools.caveman || tools.simpleEnglish) return
|
|
91
|
+
|
|
92
|
+
const lockPath = path.join(process.cwd(), 'skills-lock.json')
|
|
93
|
+
const lock = await fse.readJson(lockPath).catch(() => ({ version: 1, skills: {} }))
|
|
94
|
+
lock.skills ??= {}
|
|
95
|
+
delete lock.skills.caveman
|
|
96
|
+
lock.skills['simple-english'] = SIMPLE_ENGLISH_ENTRY
|
|
97
|
+
await fse.writeJson(lockPath, lock, { spaces: 2 })
|
|
98
|
+
await fse.remove(path.join(process.cwd(), '.agents', 'skills', 'caveman'))
|
|
99
|
+
|
|
100
|
+
const result = await execa('npx', ['skills', 'experimental_install', '--yes'], {
|
|
101
|
+
cwd: process.cwd(),
|
|
102
|
+
reject: false,
|
|
103
|
+
stdio: 'pipe',
|
|
104
|
+
timeout: 600000,
|
|
105
|
+
})
|
|
106
|
+
if (result.exitCode !== 0) {
|
|
107
|
+
console.log(chalk.yellow('Simple English was added to skills-lock.json but could not be installed. Run npx skills experimental_install --yes.'))
|
|
108
|
+
}
|
|
109
|
+
}
|
package/src/commands/wizard.js
CHANGED
|
@@ -1,134 +1,134 @@
|
|
|
1
|
-
import { select as wizardSelect } from '@inquirer/prompts'
|
|
2
|
-
import chalk from 'chalk'
|
|
3
|
-
import { ensureGitLongpaths } from './shared.js'
|
|
4
|
-
import { chooseSourceScope } from '../steps/source/index.js'
|
|
5
|
-
import { cleanAiFiles } from '../steps/clean/index.js'
|
|
6
|
-
import { choosePlatform } from '../steps/platform/index.js'
|
|
7
|
-
import { copyContentStep } from '../steps/copy/index.js'
|
|
8
|
-
import { initOpenspec } from '../steps/openspec/index.js'
|
|
9
|
-
import { chooseModels } from '../steps/models/index.js'
|
|
10
|
-
import { tokenOptimizationStep } from '../steps/optimization/index.js'
|
|
11
|
-
import { installBrowser } from '../steps/browser/index.js'
|
|
12
|
-
import { writeHarnessConfig } from '../steps/metadata/index.js'
|
|
13
|
-
|
|
14
|
-
export async function runWizard(version) {
|
|
15
|
-
const logo = chalk.hex('#fe3d57')
|
|
16
|
-
const bannerLines = [
|
|
17
|
-
logo(' '),
|
|
18
|
-
logo(' ▒▒▒▒▒▒▒▒▒▒▒▒▒ '),
|
|
19
|
-
logo(' ▒▒▓ ▓▒▓ '),
|
|
20
|
-
logo(' ▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▓▓▒▒▒▒▒ '),
|
|
21
|
-
logo(' ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓ '),
|
|
22
|
-
logo(' ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓ '),
|
|
23
|
-
logo(' ▓▒▒▒▒░░░▒▒▒▒▒▒▒▒▒▒▒░░░▒▒▒▓▓ '),
|
|
24
|
-
logo(' ▓▓▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓▓▓ '),
|
|
25
|
-
logo(' ▓▓▒▒▒▒▒▒░▒▒▒▒▒▒▒░▒▒▒▒▒▒▓▓ '),
|
|
26
|
-
logo(' ▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓ '),
|
|
27
|
-
logo(' ▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓ '),
|
|
28
|
-
logo(' ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ '),
|
|
29
|
-
'',
|
|
30
|
-
chalk.bold(' 🧰 agent-harness') + chalk.dim(` v${version}`),
|
|
31
|
-
chalk.dim(' Prepare your codebase for AI agents'),
|
|
32
|
-
]
|
|
33
|
-
|
|
34
|
-
for (const line of bannerLines) console.log(line)
|
|
35
|
-
console.log()
|
|
36
|
-
console.log(' This tool will set up your project with a team of AI agents,')
|
|
37
|
-
console.log(' install skills, select models, and configure OpenCode.')
|
|
38
|
-
console.log()
|
|
39
|
-
|
|
40
|
-
// Only wait for Enter in a real interactive TTY
|
|
41
|
-
if (process.stdin.isTTY) {
|
|
42
|
-
console.log(chalk.bold(' Press Enter to begin...'))
|
|
43
|
-
console.log()
|
|
44
|
-
await new Promise(resolve => {
|
|
45
|
-
process.stdin.resume()
|
|
46
|
-
process.stdin.once('data', () => {
|
|
47
|
-
process.stdin.pause()
|
|
48
|
-
resolve()
|
|
49
|
-
})
|
|
50
|
-
})
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const longpathsConfigured = await ensureGitLongpaths()
|
|
54
|
-
if (longpathsConfigured) console.log(chalk.dim(' Git long paths enabled for this repository.'))
|
|
55
|
-
|
|
56
|
-
const scope = await chooseSourceScope()
|
|
57
|
-
|
|
58
|
-
const maxConcurrentAgents = await wizardSelect({
|
|
59
|
-
message: 'Max concurrent agents:',
|
|
60
|
-
default: 3,
|
|
61
|
-
choices: [
|
|
62
|
-
{ name: '1', value: 1, description: 'Serial: one agent at a time' },
|
|
63
|
-
{ name: '2', value: 2, description: 'Conservative: lower resource usage' },
|
|
64
|
-
{ name: '3 (default)', value: 3, description: 'Recommended: balances speed vs MCP load' },
|
|
65
|
-
{ name: '4', value: 4, description: 'Higher parallelism' },
|
|
66
|
-
{ name: '5', value: 5, description: 'Maximum: needs more resources' },
|
|
67
|
-
],
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
const installScope = await wizardSelect({
|
|
71
|
-
message: 'Install dependencies:',
|
|
72
|
-
default: 'local',
|
|
73
|
-
choices: [
|
|
74
|
-
{ name: 'Locally (default)', value: 'local', description: 'Install tools project-locally where possible' },
|
|
75
|
-
{ name: 'Globally', value: 'global', description: 'Install tools globally (affects all projects on this machine)' },
|
|
76
|
-
],
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
const preserve = await cleanAiFiles({ removeLegacyConfig: true })
|
|
80
|
-
const ctx = { ...preserve, ...scope, maxConcurrentAgents, installScope }
|
|
81
|
-
|
|
82
|
-
const { backlogPlatform, repoPlatform } = await choosePlatform()
|
|
83
|
-
|
|
84
|
-
await copyContentStep({ backlogPlatform, repoPlatform }, ctx)
|
|
85
|
-
|
|
86
|
-
const openspec = await initOpenspec()
|
|
87
|
-
|
|
88
|
-
const selectedModels = await chooseModels()
|
|
89
|
-
|
|
90
|
-
const tokenOpt = await tokenOptimizationStep({ ctx })
|
|
91
|
-
const { rtk, quota, simpleEnglish, codegraph, memory, humanizer } = tokenOpt
|
|
92
|
-
|
|
93
|
-
await installBrowser(ctx)
|
|
94
|
-
|
|
95
|
-
await writeHarnessConfig({
|
|
96
|
-
...ctx,
|
|
97
|
-
backlogPlatform,
|
|
98
|
-
repoPlatform,
|
|
99
|
-
openspec,
|
|
100
|
-
maxConcurrentAgents,
|
|
101
|
-
installScope,
|
|
102
|
-
additionalSkillsProvider: 'npx-skills',
|
|
103
|
-
...selectedModels,
|
|
104
|
-
optionalTools: { rtk, quota, simpleEnglish, codegraph, memory, humanizer },
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
const toGenerate = [
|
|
108
|
-
!ctx.hasDesign && 'DESIGN.md',
|
|
109
|
-
!ctx.hasArchitecture && 'ARCHITECTURE.md',
|
|
110
|
-
].filter(Boolean)
|
|
111
|
-
|
|
112
|
-
console.log()
|
|
113
|
-
console.log(chalk.bold.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
|
|
114
|
-
console.log(chalk.bold.green(' Onboarding complete!'))
|
|
115
|
-
console.log(chalk.bold.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
|
|
116
|
-
console.log()
|
|
117
|
-
console.log(' Open this project in OpenCode and type:')
|
|
118
|
-
console.log(chalk.bold(' "/init"'))
|
|
119
|
-
console.log(' Or run the following command in your terminal:')
|
|
120
|
-
console.log(chalk.bold(' opencode --prompt "/init" --model "opencode/big-pickle" '))
|
|
121
|
-
console.log()
|
|
122
|
-
console.log(chalk.dim(' Note: the first time you open OpenCode in this project,'))
|
|
123
|
-
console.log(chalk.dim(' it will install plugin dependencies. You may see a black'))
|
|
124
|
-
console.log(chalk.dim(' screen for a moment: this is normal. Wait for it to load.'))
|
|
125
|
-
console.log()
|
|
126
|
-
if (toGenerate.length > 0) {
|
|
127
|
-
console.log(` OpenCode will generate ${toGenerate.join(' and ')}`)
|
|
128
|
-
console.log(' from your actual codebase, then activate the agent team.')
|
|
129
|
-
} else {
|
|
130
|
-
console.log(' OpenCode will activate the agent team.')
|
|
131
|
-
}
|
|
132
|
-
console.log(` Source scope: ${ctx.sourceMode === 'parent-selected' ? ctx.sourceRoots.map(p => `../${p.split(/[/\\]/).pop()}`).join(', ') : 'current folder'}`)
|
|
133
|
-
console.log()
|
|
134
|
-
}
|
|
1
|
+
import { select as wizardSelect } from '@inquirer/prompts'
|
|
2
|
+
import chalk from 'chalk'
|
|
3
|
+
import { ensureGitLongpaths } from './shared.js'
|
|
4
|
+
import { chooseSourceScope } from '../steps/source/index.js'
|
|
5
|
+
import { cleanAiFiles } from '../steps/clean/index.js'
|
|
6
|
+
import { choosePlatform } from '../steps/platform/index.js'
|
|
7
|
+
import { copyContentStep } from '../steps/copy/index.js'
|
|
8
|
+
import { initOpenspec } from '../steps/openspec/index.js'
|
|
9
|
+
import { chooseModels } from '../steps/models/index.js'
|
|
10
|
+
import { tokenOptimizationStep } from '../steps/optimization/index.js'
|
|
11
|
+
import { installBrowser } from '../steps/browser/index.js'
|
|
12
|
+
import { writeHarnessConfig } from '../steps/metadata/index.js'
|
|
13
|
+
|
|
14
|
+
export async function runWizard(version) {
|
|
15
|
+
const logo = chalk.hex('#fe3d57')
|
|
16
|
+
const bannerLines = [
|
|
17
|
+
logo(' '),
|
|
18
|
+
logo(' ▒▒▒▒▒▒▒▒▒▒▒▒▒ '),
|
|
19
|
+
logo(' ▒▒▓ ▓▒▓ '),
|
|
20
|
+
logo(' ▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▓▓▒▒▒▒▒ '),
|
|
21
|
+
logo(' ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓ '),
|
|
22
|
+
logo(' ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓ '),
|
|
23
|
+
logo(' ▓▒▒▒▒░░░▒▒▒▒▒▒▒▒▒▒▒░░░▒▒▒▓▓ '),
|
|
24
|
+
logo(' ▓▓▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓▓▓ '),
|
|
25
|
+
logo(' ▓▓▒▒▒▒▒▒░▒▒▒▒▒▒▒░▒▒▒▒▒▒▓▓ '),
|
|
26
|
+
logo(' ▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓ '),
|
|
27
|
+
logo(' ▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓ '),
|
|
28
|
+
logo(' ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ '),
|
|
29
|
+
'',
|
|
30
|
+
chalk.bold(' 🧰 agent-harness') + chalk.dim(` v${version}`),
|
|
31
|
+
chalk.dim(' Prepare your codebase for AI agents'),
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
for (const line of bannerLines) console.log(line)
|
|
35
|
+
console.log()
|
|
36
|
+
console.log(' This tool will set up your project with a team of AI agents,')
|
|
37
|
+
console.log(' install skills, select models, and configure OpenCode.')
|
|
38
|
+
console.log()
|
|
39
|
+
|
|
40
|
+
// Only wait for Enter in a real interactive TTY
|
|
41
|
+
if (process.stdin.isTTY) {
|
|
42
|
+
console.log(chalk.bold(' Press Enter to begin...'))
|
|
43
|
+
console.log()
|
|
44
|
+
await new Promise(resolve => {
|
|
45
|
+
process.stdin.resume()
|
|
46
|
+
process.stdin.once('data', () => {
|
|
47
|
+
process.stdin.pause()
|
|
48
|
+
resolve()
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const longpathsConfigured = await ensureGitLongpaths()
|
|
54
|
+
if (longpathsConfigured) console.log(chalk.dim(' Git long paths enabled for this repository.'))
|
|
55
|
+
|
|
56
|
+
const scope = await chooseSourceScope()
|
|
57
|
+
|
|
58
|
+
const maxConcurrentAgents = await wizardSelect({
|
|
59
|
+
message: 'Max concurrent agents:',
|
|
60
|
+
default: 3,
|
|
61
|
+
choices: [
|
|
62
|
+
{ name: '1', value: 1, description: 'Serial: one agent at a time' },
|
|
63
|
+
{ name: '2', value: 2, description: 'Conservative: lower resource usage' },
|
|
64
|
+
{ name: '3 (default)', value: 3, description: 'Recommended: balances speed vs MCP load' },
|
|
65
|
+
{ name: '4', value: 4, description: 'Higher parallelism' },
|
|
66
|
+
{ name: '5', value: 5, description: 'Maximum: needs more resources' },
|
|
67
|
+
],
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
const installScope = await wizardSelect({
|
|
71
|
+
message: 'Install dependencies:',
|
|
72
|
+
default: 'local',
|
|
73
|
+
choices: [
|
|
74
|
+
{ name: 'Locally (default)', value: 'local', description: 'Install tools project-locally where possible' },
|
|
75
|
+
{ name: 'Globally', value: 'global', description: 'Install tools globally (affects all projects on this machine)' },
|
|
76
|
+
],
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
const preserve = await cleanAiFiles({ removeLegacyConfig: true })
|
|
80
|
+
const ctx = { ...preserve, ...scope, maxConcurrentAgents, installScope }
|
|
81
|
+
|
|
82
|
+
const { backlogPlatform, repoPlatform } = await choosePlatform()
|
|
83
|
+
|
|
84
|
+
await copyContentStep({ backlogPlatform, repoPlatform }, ctx)
|
|
85
|
+
|
|
86
|
+
const openspec = await initOpenspec()
|
|
87
|
+
|
|
88
|
+
const selectedModels = await chooseModels()
|
|
89
|
+
|
|
90
|
+
const tokenOpt = await tokenOptimizationStep({ ctx })
|
|
91
|
+
const { rtk, quota, simpleEnglish, codegraph, memory, humanizer } = tokenOpt
|
|
92
|
+
|
|
93
|
+
await installBrowser(ctx)
|
|
94
|
+
|
|
95
|
+
await writeHarnessConfig({
|
|
96
|
+
...ctx,
|
|
97
|
+
backlogPlatform,
|
|
98
|
+
repoPlatform,
|
|
99
|
+
openspec,
|
|
100
|
+
maxConcurrentAgents,
|
|
101
|
+
installScope,
|
|
102
|
+
additionalSkillsProvider: 'npx-skills',
|
|
103
|
+
...selectedModels,
|
|
104
|
+
optionalTools: { rtk, quota, simpleEnglish, codegraph, memory, humanizer },
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
const toGenerate = [
|
|
108
|
+
!ctx.hasDesign && 'DESIGN.md',
|
|
109
|
+
!ctx.hasArchitecture && 'ARCHITECTURE.md',
|
|
110
|
+
].filter(Boolean)
|
|
111
|
+
|
|
112
|
+
console.log()
|
|
113
|
+
console.log(chalk.bold.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
|
|
114
|
+
console.log(chalk.bold.green(' Onboarding complete!'))
|
|
115
|
+
console.log(chalk.bold.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))
|
|
116
|
+
console.log()
|
|
117
|
+
console.log(' Open this project in OpenCode and type:')
|
|
118
|
+
console.log(chalk.bold(' "/init"'))
|
|
119
|
+
console.log(' Or run the following command in your terminal:')
|
|
120
|
+
console.log(chalk.bold(' opencode --prompt "/init" --model "opencode/big-pickle" '))
|
|
121
|
+
console.log()
|
|
122
|
+
console.log(chalk.dim(' Note: the first time you open OpenCode in this project,'))
|
|
123
|
+
console.log(chalk.dim(' it will install plugin dependencies. You may see a black'))
|
|
124
|
+
console.log(chalk.dim(' screen for a moment: this is normal. Wait for it to load.'))
|
|
125
|
+
console.log()
|
|
126
|
+
if (toGenerate.length > 0) {
|
|
127
|
+
console.log(` OpenCode will generate ${toGenerate.join(' and ')}`)
|
|
128
|
+
console.log(' from your actual codebase, then activate the agent team.')
|
|
129
|
+
} else {
|
|
130
|
+
console.log(' OpenCode will activate the agent team.')
|
|
131
|
+
}
|
|
132
|
+
console.log(` Source scope: ${ctx.sourceMode === 'parent-selected' ? ctx.sourceRoots.map(p => `../${p.split(/[/\\]/).pop()}`).join(', ') : 'current folder'}`)
|
|
133
|
+
console.log()
|
|
134
|
+
}
|