ai-summon 0.0.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.
Files changed (61) hide show
  1. package/.claude/commands/speckit.analyze.md +184 -0
  2. package/.claude/commands/speckit.checklist.md +294 -0
  3. package/.claude/commands/speckit.clarify.md +177 -0
  4. package/.claude/commands/speckit.constitution.md +78 -0
  5. package/.claude/commands/speckit.implement.md +121 -0
  6. package/.claude/commands/speckit.plan.md +81 -0
  7. package/.claude/commands/speckit.specify.md +204 -0
  8. package/.claude/commands/speckit.tasks.md +108 -0
  9. package/.claude/settings.local.json +23 -0
  10. package/.prettierignore +5 -0
  11. package/.prettierrc.json +10 -0
  12. package/.specify/memory/constitution.md +72 -0
  13. package/.specify/scripts/bash/check-prerequisites.sh +166 -0
  14. package/.specify/scripts/bash/common.sh +113 -0
  15. package/.specify/scripts/bash/create-new-feature.sh +97 -0
  16. package/.specify/scripts/bash/setup-plan.sh +60 -0
  17. package/.specify/scripts/bash/update-agent-context.sh +738 -0
  18. package/.specify/templates/agent-file-template.md +28 -0
  19. package/.specify/templates/checklist-template.md +40 -0
  20. package/.specify/templates/plan-template.md +111 -0
  21. package/.specify/templates/spec-template.md +115 -0
  22. package/.specify/templates/tasks-template.md +250 -0
  23. package/CLAUDE.md +199 -0
  24. package/PRD.md +268 -0
  25. package/README.md +171 -0
  26. package/dist/ai-summon.d.ts +2 -0
  27. package/dist/ai-summon.js +73 -0
  28. package/dist/commands/ide/index.d.ts +3 -0
  29. package/dist/commands/ide/index.js +253 -0
  30. package/dist/commands/init.d.ts +4 -0
  31. package/dist/commands/init.js +55 -0
  32. package/dist/commands/url.d.ts +4 -0
  33. package/dist/commands/url.js +223 -0
  34. package/dist/types/index.d.ts +40 -0
  35. package/dist/types/index.js +1 -0
  36. package/dist/util.d.ts +16 -0
  37. package/dist/util.js +109 -0
  38. package/eslint.config.js +47 -0
  39. package/package.json +47 -0
  40. package/specs/001-cloud-login-feature/contracts/cloud-command.ts +82 -0
  41. package/specs/001-cloud-login-feature/contracts/config-service.ts +170 -0
  42. package/specs/001-cloud-login-feature/data-model.md +269 -0
  43. package/specs/001-cloud-login-feature/plan.md +91 -0
  44. package/specs/001-cloud-login-feature/quickstart.md +366 -0
  45. package/specs/001-cloud-login-feature/research.md +290 -0
  46. package/specs/001-cloud-login-feature/spec.md +195 -0
  47. package/specs/001-cloud-login-feature/tasks.md +235 -0
  48. package/specs/001-cloud-scp-command/contracts/cloud-scp-api.ts +402 -0
  49. package/specs/001-cloud-scp-command/data-model.md +424 -0
  50. package/specs/001-cloud-scp-command/plan.md +124 -0
  51. package/specs/001-cloud-scp-command/quickstart.md +536 -0
  52. package/specs/001-cloud-scp-command/research.md +345 -0
  53. package/specs/001-cloud-scp-command/spec.md +248 -0
  54. package/specs/001-cloud-scp-command/tasks.md +434 -0
  55. package/src/ai-summon.ts +88 -0
  56. package/src/commands/ide/index.ts +322 -0
  57. package/src/commands/init.ts +64 -0
  58. package/src/commands/url.ts +262 -0
  59. package/src/types/index.ts +49 -0
  60. package/src/util.ts +146 -0
  61. package/tsconfig.json +21 -0
@@ -0,0 +1,402 @@
1
+ /**
2
+ * API Contract: Cloud SCP Command
3
+ *
4
+ * This file defines the public API contract for the hsh cloud scp command.
5
+ * It serves as the interface specification for the command implementation.
6
+ *
7
+ * Feature: 001-cloud-scp-command
8
+ * Date: 2025-10-11
9
+ */
10
+
11
+ import { Environment, CloudConfig } from '../../../src/types/index.js';
12
+
13
+ // ============================================================================
14
+ // Command-Line Interface Contract
15
+ // ============================================================================
16
+
17
+ /**
18
+ * Command Signature:
19
+ * hsh cloud scp [options] <local-path> <remote-path>
20
+ *
21
+ * Options:
22
+ * -r, --recursive Copy directories recursively
23
+ * --env <environment> Environment: dev, staging, or prod
24
+ * --service <service> Service name (e.g., todo-mini, wuhan-mall)
25
+ *
26
+ * Arguments:
27
+ * <local-path> Local file or directory path to copy
28
+ * <remote-path> Remote destination path on target server
29
+ *
30
+ * Examples:
31
+ * hsh cloud scp ./config.json /etc/app/config.json --env dev --service my-app
32
+ * hsh cloud scp -r ./dist /var/www/html --env staging --service my-app
33
+ * hsh cloud scp ./deploy.sh /root/scripts/
34
+ */
35
+
36
+ // ============================================================================
37
+ // Type Definitions
38
+ // ============================================================================
39
+
40
+ /**
41
+ * SCP command options parsed from CLI flags
42
+ */
43
+ export interface ScpOptions {
44
+ /**
45
+ * Target environment (dev, staging, or prod)
46
+ * If undefined, user will be prompted to select
47
+ */
48
+ env?: Environment;
49
+
50
+ /**
51
+ * Target service name
52
+ * If undefined, user will be prompted to select from available services
53
+ */
54
+ service?: string;
55
+
56
+ /**
57
+ * Whether to copy directories recursively
58
+ * Required true for directory copies, ignored for files
59
+ */
60
+ recursive?: boolean;
61
+ }
62
+
63
+ /**
64
+ * Result of local path validation
65
+ */
66
+ export interface PathValidationResult {
67
+ /** Whether the path exists on the local filesystem */
68
+ exists: boolean;
69
+
70
+ /** Whether the path is a directory */
71
+ isDirectory: boolean;
72
+
73
+ /** Whether the path is a regular file */
74
+ isFile: boolean;
75
+
76
+ /** The validated path (may be resolved to absolute) */
77
+ path: string;
78
+ }
79
+
80
+ /**
81
+ * Complete execution context for SCP operation
82
+ */
83
+ export interface ScpExecutionContext {
84
+ /** Selected service name */
85
+ service: string;
86
+
87
+ /** Selected environment */
88
+ environment: Environment;
89
+
90
+ /** Cloud configuration (IP and private key) */
91
+ cloudConfig: CloudConfig;
92
+
93
+ /** Validated local source path */
94
+ localPath: string;
95
+
96
+ /** Remote destination path */
97
+ remotePath: string;
98
+
99
+ /** Whether to use recursive flag */
100
+ isRecursive: boolean;
101
+ }
102
+
103
+ /**
104
+ * SCP operation metadata for logging/tracking
105
+ */
106
+ export interface ScpOperation {
107
+ /** Local source path */
108
+ localPath: string;
109
+
110
+ /** Remote destination path */
111
+ remotePath: string;
112
+
113
+ /** Target service */
114
+ service: string;
115
+
116
+ /** Target environment */
117
+ environment: Environment;
118
+
119
+ /** Whether operation was recursive */
120
+ isDirectory: boolean;
121
+
122
+ /** Operation timestamp */
123
+ timestamp: Date;
124
+ }
125
+
126
+ // ============================================================================
127
+ // Main API Function
128
+ // ============================================================================
129
+
130
+ /**
131
+ * Execute SCP file transfer to cloud instance
132
+ *
133
+ * @param localPath - Local file or directory path to copy
134
+ * @param remotePath - Remote destination path on target server
135
+ * @param options - Command options (environment, service, recursive flag)
136
+ *
137
+ * @throws {Error} If local path doesn't exist
138
+ * @throws {Error} If directory copy attempted without -r flag
139
+ * @throws {Error} If service or environment not found in configuration
140
+ * @throws {Error} If private key validation fails
141
+ * @throws {Error} If SSH/SCP connection fails
142
+ *
143
+ * @returns Promise that resolves when file transfer completes successfully
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * // Copy file with explicit options
148
+ * await cloudScp('./config.json', '/etc/app/', {
149
+ * env: 'dev',
150
+ * service: 'my-app',
151
+ * recursive: false
152
+ * });
153
+ *
154
+ * // Copy directory with interactive prompts
155
+ * await cloudScp('./dist', '/var/www/html', {
156
+ * recursive: true
157
+ * // env and service will be prompted
158
+ * });
159
+ * ```
160
+ */
161
+ export async function cloudScp(
162
+ localPath: string,
163
+ remotePath: string,
164
+ options: ScpOptions
165
+ ): Promise<void>;
166
+
167
+ // ============================================================================
168
+ // Helper Functions (Exported for Testing/Reuse)
169
+ // ============================================================================
170
+
171
+ /**
172
+ * Validate that local path exists and determine its type
173
+ *
174
+ * @param path - Local file or directory path to validate
175
+ * @returns Promise resolving to validation result
176
+ *
177
+ * @throws {Error} If permission denied or other filesystem error
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * const result = await validateLocalPath('./dist');
182
+ * if (!result.exists) {
183
+ * console.error('Path not found');
184
+ * } else if (result.isDirectory && !options.recursive) {
185
+ * console.error('Use -r flag for directories');
186
+ * }
187
+ * ```
188
+ */
189
+ export async function validateLocalPath(path: string): Promise<PathValidationResult>;
190
+
191
+ /**
192
+ * Build complete execution context from user input and configuration
193
+ *
194
+ * @param localPath - Validated local source path
195
+ * @param remotePath - Remote destination path
196
+ * @param options - Command options
197
+ * @param config - Application configuration
198
+ * @param pathInfo - Path validation result
199
+ *
200
+ * @returns Promise resolving to execution context
201
+ *
202
+ * @throws {Error} If service or environment not found in configuration
203
+ */
204
+ export async function buildExecutionContext(
205
+ localPath: string,
206
+ remotePath: string,
207
+ options: ScpOptions,
208
+ config: Config,
209
+ pathInfo: PathValidationResult
210
+ ): Promise<ScpExecutionContext>;
211
+
212
+ /**
213
+ * Construct and execute SCP command via SSH wrapper
214
+ *
215
+ * @param context - Complete execution context
216
+ *
217
+ * @returns Promise that resolves when SCP command completes
218
+ *
219
+ * @throws {Error} If SCP/SSH command fails
220
+ *
221
+ * @example
222
+ * ```typescript
223
+ * const context: ScpExecutionContext = {
224
+ * service: 'my-app',
225
+ * environment: 'dev',
226
+ * cloudConfig: { ip: '192.168.1.10', privateKeyFile: '/path/to/key.pem' },
227
+ * localPath: './dist',
228
+ * remotePath: '/var/www/html',
229
+ * isRecursive: true
230
+ * };
231
+ *
232
+ * await executeScpCommand(context);
233
+ * // Output: ✅ Successfully copied to my-app (dev): /var/www/html
234
+ * ```
235
+ */
236
+ export async function executeScpCommand(context: ScpExecutionContext): Promise<void>;
237
+
238
+ // ============================================================================
239
+ // Validation Rules
240
+ // ============================================================================
241
+
242
+ /**
243
+ * Validation rules applied during command execution:
244
+ *
245
+ * 1. Local Path Validation:
246
+ * - Path must exist on local filesystem
247
+ * - Path must be readable (file permission check)
248
+ * - If directory: -r flag must be provided
249
+ *
250
+ * 2. Configuration Validation:
251
+ * - Service must exist in config.yiren
252
+ * - Environment must exist for selected service
253
+ * - CloudConfig must have valid ip and privateKeyFile
254
+ *
255
+ * 3. Private Key Validation:
256
+ * - Private key file must exist
257
+ * - Private key file should have 600 permissions (warning if not)
258
+ *
259
+ * 4. Production Safety:
260
+ * - Production environment requires explicit confirmation
261
+ * - Confirmation must be affirmative (default: false)
262
+ *
263
+ * 5. Remote Path Validation:
264
+ * - Remote path must be non-empty string
265
+ * - Format validation delegated to SSH/SCP
266
+ */
267
+
268
+ // ============================================================================
269
+ // Error Handling Contract
270
+ // ============================================================================
271
+
272
+ /**
273
+ * Error Categories:
274
+ *
275
+ * 1. Path Errors:
276
+ * - "❌ Local path not found: {path}"
277
+ * - "❌ Permission denied: {path}"
278
+ * - "❌ Cannot copy directory without -r flag"
279
+ *
280
+ * 2. Configuration Errors:
281
+ * - "❌ No cloud services configured in yiren section"
282
+ * - "❌ Service '{service}' not found in configuration"
283
+ * - "❌ Environment '{env}' not configured for service '{service}'"
284
+ *
285
+ * 3. SSH/SCP Errors (handled by handleSSHError):
286
+ * - "❌ Connection timeout - check network connectivity and IP address"
287
+ * - "❌ Authentication failed - check private key file permissions and path"
288
+ * - "❌ Host unreachable - verify IP address and network access"
289
+ * - "❌ Connection refused - check if SSH service is running on target host"
290
+ *
291
+ * 4. User Cancellation:
292
+ * - "⏸️ Production operation cancelled."
293
+ */
294
+
295
+ // ============================================================================
296
+ // Success Messages
297
+ // ============================================================================
298
+
299
+ /**
300
+ * Success message format:
301
+ * "✅ Successfully copied to {service} ({environment}): {remotePath}"
302
+ *
303
+ * Example:
304
+ * "✅ Successfully copied to my-app (dev): /var/www/html"
305
+ */
306
+
307
+ // ============================================================================
308
+ // Configuration Contract
309
+ // ============================================================================
310
+
311
+ /**
312
+ * Configuration structure (reuses existing cloud login config):
313
+ *
314
+ * ~/.ai/config.json:
315
+ * {
316
+ * "yiren": {
317
+ * "[service-name]": {
318
+ * "dev": {
319
+ * "ip": "192.168.1.10",
320
+ * "privateKeyFile": "/path/to/dev-key.pem"
321
+ * },
322
+ * "staging": {
323
+ * "ip": "192.168.1.20",
324
+ * "privateKeyFile": "/path/to/staging-key.pem"
325
+ * },
326
+ * "prod": {
327
+ * "ip": "192.168.1.30",
328
+ * "privateKeyFile": "/path/to/prod-key.pem"
329
+ * }
330
+ * }
331
+ * }
332
+ * }
333
+ *
334
+ * No schema changes required - 100% compatible with cloud login configuration
335
+ */
336
+
337
+ // ============================================================================
338
+ // Integration Points
339
+ // ============================================================================
340
+
341
+ /**
342
+ * Functions reused from existing cloud.ts module:
343
+ *
344
+ * - validatePrivateKey(privateKeyFile: string): Promise<void>
345
+ * → Validates SSH private key existence and permissions
346
+ *
347
+ * - handleSSHError(error: any): void
348
+ * → Handles SSH/SCP connection errors with user-friendly messages
349
+ *
350
+ * - promptForService(availableServices: string[]): Promise<string>
351
+ * → Interactive service selection prompt
352
+ *
353
+ * - promptForEnvironment(availableEnvironments: Environment[]): Promise<Environment>
354
+ * → Interactive environment selection prompt
355
+ *
356
+ * - readConfig(): Config
357
+ * → Reads configuration from ~/.ai/config.json (from util.ts)
358
+ */
359
+
360
+ // ============================================================================
361
+ // Testing Contract
362
+ // ============================================================================
363
+
364
+ /**
365
+ * Testable scenarios:
366
+ *
367
+ * 1. Happy Path - File Copy:
368
+ * Input: Valid file path, valid remote path, valid service/env
369
+ * Expected: SCP command executed successfully
370
+ *
371
+ * 2. Happy Path - Directory Copy:
372
+ * Input: Valid directory path with -r flag, valid remote path, valid service/env
373
+ * Expected: SCP command with -r flag executed successfully
374
+ *
375
+ * 3. Error - Missing File:
376
+ * Input: Non-existent file path
377
+ * Expected: Error message "❌ Local path not found: {path}"
378
+ *
379
+ * 4. Error - Directory without -r:
380
+ * Input: Directory path without -r flag
381
+ * Expected: Error message "❌ Cannot copy directory without -r flag"
382
+ *
383
+ * 5. Error - Service Not Found:
384
+ * Input: Invalid service name
385
+ * Expected: Error message "❌ Service '{service}' not found in configuration"
386
+ *
387
+ * 6. Interactive - Service Selection:
388
+ * Input: No --service flag provided
389
+ * Expected: Prompt displays available services, accepts selection
390
+ *
391
+ * 7. Interactive - Environment Selection:
392
+ * Input: No --env flag provided
393
+ * Expected: Prompt displays available environments, accepts selection
394
+ *
395
+ * 8. Safety - Production Confirmation:
396
+ * Input: --env prod
397
+ * Expected: Production warning prompt, requires confirmation
398
+ *
399
+ * 9. Safety - Production Cancelled:
400
+ * Input: --env prod, user declines confirmation
401
+ * Expected: Operation cancelled with message "⏸️ Production operation cancelled."
402
+ */