@inspecto-dev/cli 0.2.0-alpha.5 → 0.3.0-alpha.1
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/.turbo/turbo-build.log +19 -20
- package/CHANGELOG.md +22 -0
- package/README.md +93 -11
- package/bin/inspecto.js +5 -1
- package/dist/bin.d.ts +5 -1
- package/dist/bin.js +530 -49
- package/dist/chunk-FZS2TLXQ.js +3140 -0
- package/dist/index.d.ts +233 -2
- package/dist/index.js +17 -3
- package/package.json +3 -2
- package/src/bin.ts +286 -66
- package/src/commands/apply.ts +118 -0
- package/src/commands/detect.ts +59 -0
- package/src/commands/doctor.ts +225 -72
- package/src/commands/init.ts +143 -183
- package/src/commands/integration-install.ts +452 -0
- package/src/commands/onboard.ts +50 -0
- package/src/commands/plan.ts +41 -0
- package/src/detect/build-tool.ts +107 -3
- package/src/index.ts +17 -2
- package/src/inject/ast-injector.ts +17 -6
- package/src/inject/extension.ts +40 -22
- package/src/inject/gitignore.ts +10 -3
- package/src/instructions.ts +60 -46
- package/src/onboarding/apply.ts +364 -0
- package/src/onboarding/context.ts +36 -0
- package/src/onboarding/planner.ts +284 -0
- package/src/onboarding/session.ts +434 -0
- package/src/onboarding/target-resolution.ts +116 -0
- package/src/prompts.ts +54 -11
- package/src/types.ts +184 -0
- package/src/utils/fs.ts +2 -1
- package/src/utils/logger.ts +9 -0
- package/src/utils/output.ts +40 -0
- package/tests/apply.test.ts +583 -0
- package/tests/ast-injector.test.ts +50 -0
- package/tests/build-tool.test.ts +3 -5
- package/tests/detect.test.ts +94 -0
- package/tests/doctor.test.ts +224 -0
- package/tests/init.test.ts +364 -0
- package/tests/install-wrapper.test.ts +76 -0
- package/tests/instructions.test.ts +61 -0
- package/tests/integration-install.test.ts +294 -0
- package/tests/logger.test.ts +100 -0
- package/tests/onboard.test.ts +258 -0
- package/tests/plan.test.ts +713 -0
- package/tests/workspace-build-tool.test.ts +75 -0
- package/.turbo/turbo-test.log +0 -16
- package/dist/chunk-MIHQGC3L.js +0 -1720
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,188 @@
|
|
|
2
2
|
type PackageManager = 'bun' | 'pnpm' | 'yarn' | 'npm';
|
|
3
3
|
/** Supported build tools (v1) */
|
|
4
4
|
type BuildTool = 'vite' | 'webpack' | 'rspack' | 'rsbuild' | 'esbuild' | 'rollup';
|
|
5
|
+
/** Machine-readable status for onboarding commands */
|
|
6
|
+
type CommandStatus = 'ok' | 'warning' | 'blocked' | 'error';
|
|
7
|
+
/** Assistant-facing status for single-entry onboarding */
|
|
8
|
+
type OnboardStatus = 'success' | 'partial_success' | 'needs_target_selection' | 'needs_confirmation' | 'error';
|
|
9
|
+
/** Structured message emitted by onboarding commands */
|
|
10
|
+
interface CommandMessage {
|
|
11
|
+
code: string;
|
|
12
|
+
message: string;
|
|
13
|
+
}
|
|
14
|
+
interface OnboardingProvider {
|
|
15
|
+
id: string;
|
|
16
|
+
label: string;
|
|
17
|
+
supported: boolean;
|
|
18
|
+
preferredMode: 'cli' | 'extension';
|
|
19
|
+
}
|
|
20
|
+
/** Detected build tool with its config path */
|
|
21
|
+
interface BuildToolDetection {
|
|
22
|
+
tool: BuildTool;
|
|
23
|
+
configPath: string;
|
|
24
|
+
/** Human-readable label like "Vite (vite.config.ts)" */
|
|
25
|
+
label: string;
|
|
26
|
+
/** Whether this is a legacy rspack version (< 0.4.0) */
|
|
27
|
+
isLegacyRspack?: boolean;
|
|
28
|
+
/** Whether this is Webpack 4.x */
|
|
29
|
+
isLegacyWebpack?: boolean;
|
|
30
|
+
/** Relative package path when using --packages */
|
|
31
|
+
packagePath?: string;
|
|
32
|
+
}
|
|
33
|
+
/** Normalized onboarding context shared by detection/planning */
|
|
34
|
+
interface OnboardingContext {
|
|
35
|
+
root: string;
|
|
36
|
+
packageManager: PackageManager;
|
|
37
|
+
buildTools: {
|
|
38
|
+
supported: BuildToolDetection[];
|
|
39
|
+
unsupported: string[];
|
|
40
|
+
};
|
|
41
|
+
frameworks: {
|
|
42
|
+
supported: string[];
|
|
43
|
+
unsupported: string[];
|
|
44
|
+
};
|
|
45
|
+
ides: Array<{
|
|
46
|
+
ide: string;
|
|
47
|
+
supported: boolean;
|
|
48
|
+
}>;
|
|
49
|
+
providers: OnboardingProvider[];
|
|
50
|
+
}
|
|
51
|
+
interface OnboardingTargetCandidate {
|
|
52
|
+
packagePath: string;
|
|
53
|
+
configPath: string;
|
|
54
|
+
buildTool: BuildTool;
|
|
55
|
+
frameworks: string[];
|
|
56
|
+
automaticInjection: boolean;
|
|
57
|
+
}
|
|
58
|
+
interface OnboardingTargetResolution {
|
|
59
|
+
status: 'resolved' | 'needs_selection';
|
|
60
|
+
selected?: OnboardingTargetCandidate;
|
|
61
|
+
candidates: OnboardingTargetCandidate[];
|
|
62
|
+
reason: string;
|
|
63
|
+
}
|
|
64
|
+
interface OnboardingSummary {
|
|
65
|
+
headline: string;
|
|
66
|
+
changes: string[];
|
|
67
|
+
risks: string[];
|
|
68
|
+
manualFollowUp: string[];
|
|
69
|
+
}
|
|
70
|
+
interface OnboardingConfirmation {
|
|
71
|
+
required: boolean;
|
|
72
|
+
reason?: string;
|
|
73
|
+
question?: string;
|
|
74
|
+
}
|
|
75
|
+
interface OnboardingExecutionResult {
|
|
76
|
+
changedFiles: string[];
|
|
77
|
+
installedDependencies: string[];
|
|
78
|
+
selectedProviderDefault?: string;
|
|
79
|
+
selectedIDE?: string;
|
|
80
|
+
mutations: Mutation[];
|
|
81
|
+
}
|
|
82
|
+
interface OnboardingDiagnostics {
|
|
83
|
+
warnings: string[];
|
|
84
|
+
errors: string[];
|
|
85
|
+
nextSteps: string[];
|
|
86
|
+
}
|
|
87
|
+
interface OnboardingIdeExtensionStatus {
|
|
88
|
+
required: boolean;
|
|
89
|
+
installed: boolean;
|
|
90
|
+
manualRequired: boolean;
|
|
91
|
+
installCommand?: string;
|
|
92
|
+
marketplaceUrl?: string;
|
|
93
|
+
openVsxUrl?: string;
|
|
94
|
+
}
|
|
95
|
+
interface OnboardingVerification {
|
|
96
|
+
available: boolean;
|
|
97
|
+
devCommand?: string;
|
|
98
|
+
message: string;
|
|
99
|
+
}
|
|
100
|
+
interface ResolvedOnboardingSession {
|
|
101
|
+
status: OnboardStatus;
|
|
102
|
+
target: OnboardingTargetResolution;
|
|
103
|
+
summary: OnboardingSummary;
|
|
104
|
+
confirmation: OnboardingConfirmation;
|
|
105
|
+
verification: OnboardingVerification;
|
|
106
|
+
context: OnboardingContext;
|
|
107
|
+
plan: PlanResult;
|
|
108
|
+
projectRoot: string;
|
|
109
|
+
selectedIDE?: {
|
|
110
|
+
ide: string;
|
|
111
|
+
supported: boolean;
|
|
112
|
+
} | null;
|
|
113
|
+
providerDefault?: string;
|
|
114
|
+
}
|
|
115
|
+
interface OnboardCommandResult {
|
|
116
|
+
status: OnboardStatus;
|
|
117
|
+
target: OnboardingTargetResolution;
|
|
118
|
+
summary: OnboardingSummary;
|
|
119
|
+
confirmation: OnboardingConfirmation;
|
|
120
|
+
ideExtension?: OnboardingIdeExtensionStatus;
|
|
121
|
+
verification?: OnboardingVerification;
|
|
122
|
+
result?: OnboardingExecutionResult;
|
|
123
|
+
diagnostics?: OnboardingDiagnostics;
|
|
124
|
+
}
|
|
125
|
+
/** Machine-readable detection output for skill-first onboarding */
|
|
126
|
+
interface DetectionResult {
|
|
127
|
+
status: CommandStatus;
|
|
128
|
+
warnings: CommandMessage[];
|
|
129
|
+
blockers: CommandMessage[];
|
|
130
|
+
project: {
|
|
131
|
+
root: string;
|
|
132
|
+
packageManager: PackageManager;
|
|
133
|
+
};
|
|
134
|
+
environment: {
|
|
135
|
+
frameworks: string[];
|
|
136
|
+
unsupportedFrameworks: string[];
|
|
137
|
+
buildTools: BuildToolDetection[];
|
|
138
|
+
unsupportedBuildTools: string[];
|
|
139
|
+
ides: Array<{
|
|
140
|
+
ide: string;
|
|
141
|
+
supported: boolean;
|
|
142
|
+
}>;
|
|
143
|
+
providers: OnboardingProvider[];
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/** Machine-readable onboarding plan output */
|
|
147
|
+
interface PlanResult {
|
|
148
|
+
status: CommandStatus;
|
|
149
|
+
warnings: CommandMessage[];
|
|
150
|
+
blockers: CommandMessage[];
|
|
151
|
+
strategy: 'supported' | 'manual' | 'unsupported';
|
|
152
|
+
actions: Array<{
|
|
153
|
+
type: 'install_dependency' | 'modify_file' | 'install_extension' | 'manual_step';
|
|
154
|
+
target: string;
|
|
155
|
+
description: string;
|
|
156
|
+
}>;
|
|
157
|
+
defaults: {
|
|
158
|
+
provider?: string;
|
|
159
|
+
ide?: string;
|
|
160
|
+
shared: boolean;
|
|
161
|
+
extension: boolean;
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/** A single doctor diagnostic check/result */
|
|
165
|
+
interface DoctorDiagnostic {
|
|
166
|
+
code: string;
|
|
167
|
+
status: 'ok' | 'warning' | 'error';
|
|
168
|
+
message: string;
|
|
169
|
+
hints: string[];
|
|
170
|
+
details?: Record<string, unknown>;
|
|
171
|
+
}
|
|
172
|
+
/** Machine-readable diagnostics output for `inspecto doctor` */
|
|
173
|
+
interface DoctorResult {
|
|
174
|
+
status: CommandStatus;
|
|
175
|
+
summary: {
|
|
176
|
+
errors: number;
|
|
177
|
+
warnings: number;
|
|
178
|
+
};
|
|
179
|
+
project: {
|
|
180
|
+
root: string;
|
|
181
|
+
packageManager?: PackageManager;
|
|
182
|
+
};
|
|
183
|
+
errors: DoctorDiagnostic[];
|
|
184
|
+
warnings: DoctorDiagnostic[];
|
|
185
|
+
checks: DoctorDiagnostic[];
|
|
186
|
+
}
|
|
5
187
|
/** Options passed to `inspecto init` */
|
|
6
188
|
interface InitOptions {
|
|
7
189
|
shared: boolean;
|
|
@@ -30,12 +212,61 @@ interface InstallLock {
|
|
|
30
212
|
mutations: Mutation[];
|
|
31
213
|
}
|
|
32
214
|
|
|
215
|
+
interface ApplyOnboardingResult {
|
|
216
|
+
status: CommandStatus;
|
|
217
|
+
mutations: Mutation[];
|
|
218
|
+
postInstall: {
|
|
219
|
+
installFailed: boolean;
|
|
220
|
+
injectionFailed: boolean;
|
|
221
|
+
manualExtensionInstallNeeded: boolean;
|
|
222
|
+
nextSteps: string[];
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
interface ApplyCommandOptions {
|
|
227
|
+
json?: boolean;
|
|
228
|
+
shared?: boolean;
|
|
229
|
+
skipInstall?: boolean;
|
|
230
|
+
dryRun?: boolean;
|
|
231
|
+
noExtension?: boolean;
|
|
232
|
+
}
|
|
233
|
+
interface ApplyCommandResult extends ApplyOnboardingResult {
|
|
234
|
+
plan: PlanResult;
|
|
235
|
+
}
|
|
236
|
+
declare function apply(options?: ApplyCommandOptions): Promise<ApplyCommandResult>;
|
|
237
|
+
|
|
238
|
+
declare function detect(json?: boolean): Promise<DetectionResult>;
|
|
239
|
+
|
|
33
240
|
declare function init(options: InitOptions): Promise<void>;
|
|
34
241
|
|
|
35
|
-
|
|
242
|
+
interface DoctorCommandOptions {
|
|
243
|
+
json?: boolean;
|
|
244
|
+
}
|
|
245
|
+
declare function collectDoctorResult(root?: string): Promise<DoctorResult>;
|
|
246
|
+
declare function doctor(options?: DoctorCommandOptions | boolean): Promise<DoctorResult>;
|
|
247
|
+
|
|
248
|
+
interface OnboardCommandOptions {
|
|
249
|
+
json?: boolean;
|
|
250
|
+
target?: string;
|
|
251
|
+
yes?: boolean;
|
|
252
|
+
shared?: boolean;
|
|
253
|
+
skipInstall?: boolean;
|
|
254
|
+
dryRun?: boolean;
|
|
255
|
+
noExtension?: boolean;
|
|
256
|
+
}
|
|
257
|
+
declare function onboard(options?: OnboardCommandOptions): Promise<OnboardCommandResult>;
|
|
258
|
+
|
|
259
|
+
declare function plan(json?: boolean): Promise<PlanResult>;
|
|
36
260
|
|
|
37
261
|
declare function teardown(): Promise<void>;
|
|
38
262
|
|
|
263
|
+
interface ReportCommandErrorOptions {
|
|
264
|
+
debug?: boolean;
|
|
265
|
+
json?: boolean;
|
|
266
|
+
}
|
|
267
|
+
declare function writeCommandOutput<T>(result: T, json: boolean, renderText: (value: T) => void): T;
|
|
268
|
+
declare function reportCommandError(error: unknown, options?: ReportCommandErrorOptions): void;
|
|
269
|
+
|
|
39
270
|
type Framework = 'react' | 'vue';
|
|
40
271
|
|
|
41
|
-
export { type BuildTool, type Framework, type InitOptions, type InstallLock, type PackageManager, doctor, init, teardown };
|
|
272
|
+
export { type BuildTool, type DoctorDiagnostic, type DoctorResult, type Framework, type InitOptions, type InstallLock, type OnboardCommandResult, type OnboardStatus, type PackageManager, type ResolvedOnboardingSession, apply, collectDoctorResult, detect, doctor, init, onboard, plan, reportCommandError, teardown, writeCommandOutput };
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
|
+
apply,
|
|
3
|
+
collectDoctorResult,
|
|
4
|
+
detect,
|
|
2
5
|
doctor,
|
|
3
6
|
init,
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
onboard,
|
|
8
|
+
plan,
|
|
9
|
+
reportCommandError,
|
|
10
|
+
teardown,
|
|
11
|
+
writeCommandOutput
|
|
12
|
+
} from "./chunk-FZS2TLXQ.js";
|
|
6
13
|
export {
|
|
14
|
+
apply,
|
|
15
|
+
collectDoctorResult,
|
|
16
|
+
detect,
|
|
7
17
|
doctor,
|
|
8
18
|
init,
|
|
9
|
-
|
|
19
|
+
onboard,
|
|
20
|
+
plan,
|
|
21
|
+
reportCommandError,
|
|
22
|
+
teardown,
|
|
23
|
+
writeCommandOutput
|
|
10
24
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inspecto-dev/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-alpha.1",
|
|
4
4
|
"description": "CLI tools for Inspecto onboarding and lifecycle management",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"inspecto",
|
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"cac": "^6.7.14",
|
|
19
19
|
"magicast": "^0.5.2",
|
|
20
|
+
"ora": "^9.3.0",
|
|
20
21
|
"picocolors": "^1.0.0",
|
|
21
22
|
"prompts": "^2.4.2",
|
|
22
|
-
"@inspecto-dev/types": "0.
|
|
23
|
+
"@inspecto-dev/types": "0.3.0-alpha.1"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|
|
25
26
|
"@types/node": "^20.0.0",
|
package/src/bin.ts
CHANGED
|
@@ -4,22 +4,34 @@
|
|
|
4
4
|
// v1 scope: VS Code | React + Vue | Vite + Webpack + Rspack + esbuild + Rollup
|
|
5
5
|
// ============================================================
|
|
6
6
|
import { cac, type CAC } from 'cac'
|
|
7
|
+
import { fileURLToPath } from 'node:url'
|
|
7
8
|
import { createRequire } from 'node:module'
|
|
9
|
+
import { apply } from './commands/apply.js'
|
|
10
|
+
import { detect } from './commands/detect.js'
|
|
8
11
|
import { init } from './commands/init.js'
|
|
9
12
|
import { doctor } from './commands/doctor.js'
|
|
13
|
+
import { onboard } from './commands/onboard.js'
|
|
14
|
+
import { plan } from './commands/plan.js'
|
|
10
15
|
import { teardown } from './commands/teardown.js'
|
|
11
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
type InstallIntegrationOptions,
|
|
18
|
+
installIntegration,
|
|
19
|
+
printIntegrationList,
|
|
20
|
+
printIntegrationPath,
|
|
21
|
+
} from './commands/integration-install.js'
|
|
22
|
+
import { reportCommandError } from './utils/output.js'
|
|
12
23
|
|
|
13
24
|
const require = createRequire(import.meta.url)
|
|
14
25
|
const { version } = require('../package.json')
|
|
15
26
|
|
|
16
|
-
// cac object
|
|
17
|
-
const cli: CAC = cac('inspecto')
|
|
18
|
-
|
|
19
27
|
interface GlobalOptions {
|
|
20
28
|
debug?: boolean
|
|
21
29
|
}
|
|
22
30
|
|
|
31
|
+
interface JsonCommandOptions extends GlobalOptions {
|
|
32
|
+
json?: boolean
|
|
33
|
+
}
|
|
34
|
+
|
|
23
35
|
interface InitCommandOptions extends GlobalOptions {
|
|
24
36
|
shared?: boolean
|
|
25
37
|
skipInstall?: boolean
|
|
@@ -30,74 +42,282 @@ interface InitCommandOptions extends GlobalOptions {
|
|
|
30
42
|
force?: boolean
|
|
31
43
|
}
|
|
32
44
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
45
|
+
interface ApplyCommandOptions extends JsonCommandOptions {
|
|
46
|
+
shared?: boolean
|
|
47
|
+
skipInstall?: boolean
|
|
48
|
+
dryRun?: boolean
|
|
49
|
+
extension?: boolean
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface OnboardCliOptions extends JsonCommandOptions {
|
|
53
|
+
target?: string
|
|
54
|
+
yes?: boolean
|
|
55
|
+
shared?: boolean
|
|
56
|
+
skipInstall?: boolean
|
|
57
|
+
dryRun?: boolean
|
|
58
|
+
extension?: boolean
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface IntegrationCommandOptions extends GlobalOptions {
|
|
62
|
+
scope?: string
|
|
63
|
+
mode?: string
|
|
64
|
+
force?: boolean
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const integrationScopes = ['project', 'user'] as const
|
|
68
|
+
const integrationModes = ['instructions', 'agents', 'rules'] as const
|
|
69
|
+
|
|
70
|
+
function exitWithError(error: unknown, options: JsonCommandOptions = {}): never {
|
|
71
|
+
reportCommandError(error, {
|
|
72
|
+
debug: options.debug ?? false,
|
|
73
|
+
json: options.json ?? false,
|
|
63
74
|
})
|
|
75
|
+
process.exit(1)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function createCli(_argv: readonly string[] = process.argv): CAC {
|
|
79
|
+
const cli: CAC = cac('inspecto')
|
|
64
80
|
|
|
65
|
-
cli
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
81
|
+
cli
|
|
82
|
+
.command('init', 'Set up Inspecto in your project')
|
|
83
|
+
.option('--shared', 'Share .inspecto/settings.json with your team via Git', { default: false })
|
|
84
|
+
.option('--skip-install', 'Skip npm dependency installation', { default: false })
|
|
85
|
+
.option('--dry-run', 'Preview changes without modifying files', { default: false })
|
|
86
|
+
.option('--provider <provider>', 'Set default provider (e.g. copilot, claude-code)')
|
|
87
|
+
.option('--no-extension', 'Skip VS Code extension installation', { default: false })
|
|
88
|
+
.option('--packages <names>', '(Monorepo) Comma-separated list of packages to inject')
|
|
89
|
+
.option('--force', 'Force initialization even if environment is unsupported', {
|
|
90
|
+
default: false,
|
|
91
|
+
})
|
|
92
|
+
.option('--debug', 'Enable debug mode to show full error traces', { default: false })
|
|
93
|
+
.action(async (options: InitCommandOptions) => {
|
|
94
|
+
try {
|
|
95
|
+
await init({
|
|
96
|
+
shared: options.shared ?? false,
|
|
97
|
+
skipInstall: options.skipInstall ?? false,
|
|
98
|
+
dryRun: options.dryRun ?? false,
|
|
99
|
+
...(options.provider && { provider: options.provider }),
|
|
100
|
+
noExtension: options.noExtension ?? false,
|
|
101
|
+
...(options.packages && {
|
|
102
|
+
packages: options.packages.split(',').map((s: string) => s.trim()),
|
|
103
|
+
}),
|
|
104
|
+
force: options.force ?? false,
|
|
105
|
+
})
|
|
106
|
+
} catch (error) {
|
|
107
|
+
exitWithError(error, options)
|
|
75
108
|
}
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
})
|
|
109
|
+
})
|
|
79
110
|
|
|
80
|
-
cli
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
console.error(err.stack)
|
|
111
|
+
cli
|
|
112
|
+
.command('doctor', 'Diagnose your Inspecto installation')
|
|
113
|
+
.option('--json', 'Print machine-readable JSON output', { default: false })
|
|
114
|
+
.option('--debug', 'Enable debug mode to show full error traces', { default: false })
|
|
115
|
+
.action(async (options: JsonCommandOptions) => {
|
|
116
|
+
try {
|
|
117
|
+
await doctor({ json: options.json ?? false })
|
|
118
|
+
} catch (error) {
|
|
119
|
+
exitWithError(error, options)
|
|
90
120
|
}
|
|
91
|
-
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
cli
|
|
124
|
+
.command('onboard', 'Run assistant-oriented Inspecto onboarding in one structured flow')
|
|
125
|
+
.option('--json', 'Print machine-readable JSON output', { default: false })
|
|
126
|
+
.option('--target <packagePath>', 'Select a monorepo target package explicitly')
|
|
127
|
+
.option('--yes', 'Accept a lightweight confirmation gate automatically', { default: false })
|
|
128
|
+
.option('--shared', 'Write shared Inspecto settings instead of local-only settings')
|
|
129
|
+
.option('--skip-install', 'Skip npm dependency installation')
|
|
130
|
+
.option('--dry-run', 'Preview changes without modifying files')
|
|
131
|
+
.option('--no-extension', 'Skip IDE extension installation')
|
|
132
|
+
.option('--debug', 'Enable debug mode to show full error traces', { default: false })
|
|
133
|
+
.action(async (options: OnboardCliOptions) => {
|
|
134
|
+
try {
|
|
135
|
+
await onboard({
|
|
136
|
+
json: options.json ?? false,
|
|
137
|
+
...(options.target && { target: options.target }),
|
|
138
|
+
yes: options.yes ?? false,
|
|
139
|
+
...(options.shared !== undefined && { shared: options.shared }),
|
|
140
|
+
...(options.skipInstall !== undefined && { skipInstall: options.skipInstall }),
|
|
141
|
+
...(options.dryRun !== undefined && { dryRun: options.dryRun }),
|
|
142
|
+
...(options.extension === false && { noExtension: true }),
|
|
143
|
+
})
|
|
144
|
+
} catch (error) {
|
|
145
|
+
exitWithError(error, options)
|
|
146
|
+
}
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
cli
|
|
150
|
+
.command('detect', 'Detect whether the current project can be onboarded automatically')
|
|
151
|
+
.option('--json', 'Print machine-readable JSON output', { default: false })
|
|
152
|
+
.option('--debug', 'Enable debug mode to show full error traces', { default: false })
|
|
153
|
+
.action(async (options: JsonCommandOptions) => {
|
|
154
|
+
try {
|
|
155
|
+
await detect(options.json ?? false)
|
|
156
|
+
} catch (error) {
|
|
157
|
+
exitWithError(error, options)
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
cli
|
|
162
|
+
.command('plan', 'Preview the onboarding plan for the current project')
|
|
163
|
+
.option('--json', 'Print machine-readable JSON output', { default: false })
|
|
164
|
+
.option('--debug', 'Enable debug mode to show full error traces', { default: false })
|
|
165
|
+
.action(async (options: JsonCommandOptions) => {
|
|
166
|
+
try {
|
|
167
|
+
await plan(options.json ?? false)
|
|
168
|
+
} catch (error) {
|
|
169
|
+
exitWithError(error, options)
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
cli
|
|
174
|
+
.command('apply', 'Apply the onboarding plan to the current project')
|
|
175
|
+
.option('--json', 'Print machine-readable JSON output', { default: false })
|
|
176
|
+
.option('--shared', 'Write shared Inspecto settings instead of local-only settings')
|
|
177
|
+
.option('--skip-install', 'Skip npm dependency installation')
|
|
178
|
+
.option('--dry-run', 'Preview changes without modifying files')
|
|
179
|
+
.option('--no-extension', 'Skip IDE extension installation')
|
|
180
|
+
.option('--debug', 'Enable debug mode to show full error traces', { default: false })
|
|
181
|
+
.action(async (options: ApplyCommandOptions) => {
|
|
182
|
+
try {
|
|
183
|
+
await apply({
|
|
184
|
+
json: options.json ?? false,
|
|
185
|
+
...(options.shared !== undefined && { shared: options.shared }),
|
|
186
|
+
...(options.skipInstall !== undefined && { skipInstall: options.skipInstall }),
|
|
187
|
+
...(options.dryRun !== undefined && { dryRun: options.dryRun }),
|
|
188
|
+
...(options.extension === false && { noExtension: true }),
|
|
189
|
+
})
|
|
190
|
+
} catch (error) {
|
|
191
|
+
exitWithError(error, options)
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
cli
|
|
196
|
+
.command('teardown', 'Remove Inspecto from your project')
|
|
197
|
+
.option('--debug', 'Enable debug mode to show full error traces', { default: false })
|
|
198
|
+
.action(async (options: GlobalOptions) => {
|
|
199
|
+
try {
|
|
200
|
+
await teardown()
|
|
201
|
+
} catch (error) {
|
|
202
|
+
exitWithError(error, options)
|
|
203
|
+
}
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
cli
|
|
207
|
+
.command('integrations [...args]', 'Manage assistant integration assets')
|
|
208
|
+
.option(
|
|
209
|
+
'--scope <scope>',
|
|
210
|
+
'Set install scope for supported assistants (e.g. claude-code: project|user)',
|
|
211
|
+
)
|
|
212
|
+
.option(
|
|
213
|
+
'--mode <mode>',
|
|
214
|
+
'Set install mode for supported assistants (e.g. copilot: instructions|agents)',
|
|
215
|
+
)
|
|
216
|
+
.option('--force', 'Overwrite existing integration files', { default: false })
|
|
217
|
+
.option('--debug', 'Enable debug mode to show full error traces', { default: false })
|
|
218
|
+
.action(async (args: string[], options: IntegrationCommandOptions) => {
|
|
219
|
+
try {
|
|
220
|
+
const [subcommand, assistant, ...rest] = args
|
|
221
|
+
const integrationOptions = buildIntegrationOptions(options)
|
|
222
|
+
|
|
223
|
+
if (subcommand === 'list') {
|
|
224
|
+
if (assistant || rest.length > 0 || options.scope || options.mode || options.force) {
|
|
225
|
+
throw new Error(
|
|
226
|
+
'The `list` subcommand does not accept assistant names, --scope, --mode, or --force.',
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
printIntegrationList()
|
|
231
|
+
return
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (subcommand === 'path' && assistant) {
|
|
235
|
+
if (rest.length > 0) {
|
|
236
|
+
throw new Error('The `path` subcommand accepts exactly one assistant argument.')
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (options.force) {
|
|
240
|
+
throw new Error('The `path` subcommand does not support `--force`.')
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
printIntegrationPath(assistant, integrationOptions)
|
|
244
|
+
return
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (subcommand !== 'install' || !assistant) {
|
|
248
|
+
throw new Error(
|
|
249
|
+
[
|
|
250
|
+
'Usage:',
|
|
251
|
+
' inspecto integrations list',
|
|
252
|
+
' inspecto integrations path <assistant> [--scope <scope>] [--mode <mode>]',
|
|
253
|
+
' inspecto integrations install <assistant> [--scope <scope>] [--mode <mode>] [--force]',
|
|
254
|
+
].join('\n'),
|
|
255
|
+
)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (rest.length > 0) {
|
|
259
|
+
throw new Error('The `install` subcommand accepts exactly one assistant argument.')
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
await installIntegration(assistant, {
|
|
263
|
+
...integrationOptions,
|
|
264
|
+
force: options.force ?? false,
|
|
265
|
+
})
|
|
266
|
+
} catch (error) {
|
|
267
|
+
exitWithError(error, options)
|
|
268
|
+
}
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
cli.help()
|
|
272
|
+
cli.version(version)
|
|
273
|
+
|
|
274
|
+
return cli
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function buildIntegrationOptions(options: IntegrationCommandOptions): InstallIntegrationOptions {
|
|
278
|
+
const resolved: InstallIntegrationOptions = {}
|
|
279
|
+
|
|
280
|
+
if (options.scope) {
|
|
281
|
+
if (isIntegrationScope(options.scope)) {
|
|
282
|
+
resolved.scope = options.scope
|
|
283
|
+
} else {
|
|
284
|
+
throw new Error(`Unknown integration scope: ${options.scope}`)
|
|
92
285
|
}
|
|
93
|
-
}
|
|
286
|
+
}
|
|
94
287
|
|
|
95
|
-
|
|
96
|
-
|
|
288
|
+
if (options.mode) {
|
|
289
|
+
if (isIntegrationMode(options.mode)) {
|
|
290
|
+
resolved.mode = options.mode
|
|
291
|
+
} else {
|
|
292
|
+
throw new Error(`Unknown integration mode: ${options.mode}`)
|
|
293
|
+
}
|
|
294
|
+
}
|
|
97
295
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
296
|
+
return resolved
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function isIntegrationScope(
|
|
300
|
+
value: string,
|
|
301
|
+
): value is NonNullable<InstallIntegrationOptions['scope']> {
|
|
302
|
+
return (integrationScopes as readonly string[]).includes(value)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function isIntegrationMode(value: string): value is NonNullable<InstallIntegrationOptions['mode']> {
|
|
306
|
+
return (integrationModes as readonly string[]).includes(value)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export async function runCli(argv: readonly string[] = process.argv): Promise<void> {
|
|
310
|
+
const cli = createCli(argv)
|
|
311
|
+
const parsedArgv = [...argv]
|
|
312
|
+
|
|
313
|
+
try {
|
|
314
|
+
await cli.parse(parsedArgv)
|
|
315
|
+
} catch (error) {
|
|
316
|
+
exitWithError(error, { json: argv.includes('--json') })
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const entryPath = process.argv[1]
|
|
321
|
+
if (entryPath && fileURLToPath(import.meta.url) === entryPath) {
|
|
322
|
+
void runCli()
|
|
103
323
|
}
|