@memnexus-ai/cli 0.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/.env.example +13 -0
- package/.eslintrc.js +24 -0
- package/.github/ISSUE_TEMPLATE/phase-1-foundation.md +1078 -0
- package/.github/workflows/publish.yml +277 -0
- package/.github/workflows/test-app-token.yml +54 -0
- package/.npmrc.backup +3 -0
- package/.npmrc.example +6 -0
- package/.prettierignore +4 -0
- package/.prettierrc +8 -0
- package/CHANGELOG.md +138 -0
- package/PLATFORM_TESTING.md +243 -0
- package/README.md +986 -0
- package/RELEASE.md +428 -0
- package/RELEASE_READINESS.md +253 -0
- package/USAGE.md +1373 -0
- package/bin/mx.js +2 -0
- package/dist/commands/apikeys.d.ts +7 -0
- package/dist/commands/apikeys.d.ts.map +1 -0
- package/dist/commands/apikeys.js +133 -0
- package/dist/commands/apikeys.js.map +1 -0
- package/dist/commands/artifacts.d.ts +7 -0
- package/dist/commands/artifacts.d.ts.map +1 -0
- package/dist/commands/artifacts.js +277 -0
- package/dist/commands/artifacts.js.map +1 -0
- package/dist/commands/auth.d.ts +7 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +119 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/communities.d.ts +7 -0
- package/dist/commands/communities.d.ts.map +1 -0
- package/dist/commands/communities.js +137 -0
- package/dist/commands/communities.js.map +1 -0
- package/dist/commands/config.d.ts +7 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +138 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/conversations.d.ts +7 -0
- package/dist/commands/conversations.d.ts.map +1 -0
- package/dist/commands/conversations.js +160 -0
- package/dist/commands/conversations.js.map +1 -0
- package/dist/commands/facts.d.ts +7 -0
- package/dist/commands/facts.d.ts.map +1 -0
- package/dist/commands/facts.js +298 -0
- package/dist/commands/facts.js.map +1 -0
- package/dist/commands/graphrag.d.ts +7 -0
- package/dist/commands/graphrag.d.ts.map +1 -0
- package/dist/commands/graphrag.js +139 -0
- package/dist/commands/graphrag.js.map +1 -0
- package/dist/commands/memories.d.ts +7 -0
- package/dist/commands/memories.d.ts.map +1 -0
- package/dist/commands/memories.js +304 -0
- package/dist/commands/memories.js.map +1 -0
- package/dist/commands/patterns.d.ts +7 -0
- package/dist/commands/patterns.d.ts.map +1 -0
- package/dist/commands/patterns.js +227 -0
- package/dist/commands/patterns.js.map +1 -0
- package/dist/commands/system.d.ts +7 -0
- package/dist/commands/system.d.ts.map +1 -0
- package/dist/commands/system.js +97 -0
- package/dist/commands/system.js.map +1 -0
- package/dist/commands/topics.d.ts +7 -0
- package/dist/commands/topics.d.ts.map +1 -0
- package/dist/commands/topics.js +314 -0
- package/dist/commands/topics.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-client.d.ts +29 -0
- package/dist/lib/api-client.d.ts.map +1 -0
- package/dist/lib/api-client.js +64 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/auth.d.ts +10 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +47 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/config.d.ts +19 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +59 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/errors.d.ts +7 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +133 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/formatters.d.ts +12 -0
- package/dist/lib/formatters.d.ts.map +1 -0
- package/dist/lib/formatters.js +103 -0
- package/dist/lib/formatters.js.map +1 -0
- package/dist/lib/spinner.d.ts +54 -0
- package/dist/lib/spinner.d.ts.map +1 -0
- package/dist/lib/spinner.js +108 -0
- package/dist/lib/spinner.js.map +1 -0
- package/dist/lib/validators.d.ts +92 -0
- package/dist/lib/validators.d.ts.map +1 -0
- package/dist/lib/validators.js +257 -0
- package/dist/lib/validators.js.map +1 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/docs/README.md +219 -0
- package/docs/code-generation-strategy.md +560 -0
- package/docs/prd.md +748 -0
- package/docs/sync-strategy.md +533 -0
- package/jest.config.js +30 -0
- package/package.json +67 -0
- package/scripts/install-deps.sh +38 -0
- package/src/commands/apikeys.ts +144 -0
- package/src/commands/artifacts.ts +296 -0
- package/src/commands/auth.ts +122 -0
- package/src/commands/communities.ts +153 -0
- package/src/commands/config.ts +144 -0
- package/src/commands/conversations.ts +176 -0
- package/src/commands/facts.ts +320 -0
- package/src/commands/graphrag.ts +149 -0
- package/src/commands/memories.ts +332 -0
- package/src/commands/patterns.ts +251 -0
- package/src/commands/system.ts +102 -0
- package/src/commands/topics.ts +354 -0
- package/src/index.ts +43 -0
- package/src/lib/api-client.ts +68 -0
- package/src/lib/auth.ts +42 -0
- package/src/lib/config.ts +68 -0
- package/src/lib/errors.ts +143 -0
- package/src/lib/formatters.ts +123 -0
- package/src/lib/spinner.ts +113 -0
- package/src/lib/validators.ts +302 -0
- package/src/types/index.ts +17 -0
- package/tests/__mocks__/chalk.ts +16 -0
- package/tests/__mocks__/cli-table3.ts +37 -0
- package/tests/__mocks__/configstore.ts +38 -0
- package/tests/commands/apikeys.test.ts +179 -0
- package/tests/commands/artifacts.test.ts +194 -0
- package/tests/commands/auth.test.ts +120 -0
- package/tests/commands/communities.test.ts +154 -0
- package/tests/commands/config.test.ts +154 -0
- package/tests/commands/conversations.test.ts +136 -0
- package/tests/commands/facts.test.ts +210 -0
- package/tests/commands/graphrag.test.ts +194 -0
- package/tests/commands/memories.test.ts +215 -0
- package/tests/commands/patterns.test.ts +201 -0
- package/tests/commands/system.test.ts +172 -0
- package/tests/commands/topics.test.ts +274 -0
- package/tests/lib/auth.test.ts +77 -0
- package/tests/lib/config.test.ts +50 -0
- package/tests/lib/errors.test.ts +126 -0
- package/tests/lib/formatters.test.ts +87 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
# CLI Code Generation Strategy
|
|
2
|
+
|
|
3
|
+
## The Core Problem
|
|
4
|
+
|
|
5
|
+
**Question**: When we add/remove/change APIs, what updates the actual CLI code?
|
|
6
|
+
|
|
7
|
+
**Current Gap**: While `@memnexus-ai/contracts` auto-generates TypeScript types from OpenAPI, **the CLI command implementations must be written manually**.
|
|
8
|
+
|
|
9
|
+
### What's Automated Today β
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
// When you add: POST /api/artifacts/export to OpenAPI spec
|
|
13
|
+
// This happens automatically:
|
|
14
|
+
// 1. Types are generated in @memnexus-ai/contracts
|
|
15
|
+
export interface ExportArtifactRequest {
|
|
16
|
+
format: 'pdf' | 'json' | 'csv';
|
|
17
|
+
artifactIds: string[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// 2. Client method is created
|
|
21
|
+
class CoreApiClient {
|
|
22
|
+
artifacts = {
|
|
23
|
+
export: (data: ExportArtifactRequest) => Promise<Blob>
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### What's Manual Today β
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
// Someone must manually write:
|
|
32
|
+
// 1. CLI command in src/commands/artifacts.ts
|
|
33
|
+
program
|
|
34
|
+
.command('artifacts export')
|
|
35
|
+
.option('--format <format>', 'Export format')
|
|
36
|
+
.option('--output <file>', 'Output file path')
|
|
37
|
+
.action(async (options) => {
|
|
38
|
+
const client = getApiClient();
|
|
39
|
+
const result = await client.artifacts.export({...});
|
|
40
|
+
// Format output, handle errors, etc.
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// 2. Help text
|
|
44
|
+
// 3. Input validation
|
|
45
|
+
// 4. Output formatting
|
|
46
|
+
// 5. Error handling
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Evaluated Solutions
|
|
50
|
+
|
|
51
|
+
### Option 1: Full Auto-Generation (Not Recommended)
|
|
52
|
+
|
|
53
|
+
**Tools Investigated**:
|
|
54
|
+
- **openapi-cli-generator** - Generates Go CLIs only
|
|
55
|
+
- **Restish** - Runtime API client (Go), not code generator
|
|
56
|
+
- **OpenAPI Generator** - No TypeScript/Commander.js templates
|
|
57
|
+
|
|
58
|
+
**Why Not Recommended**:
|
|
59
|
+
- β No mature tools for TypeScript/Commander.js generation
|
|
60
|
+
- β Generated code is often rigid and hard to customize
|
|
61
|
+
- β Loses the "developer experience" polish (help text, examples, validation)
|
|
62
|
+
- β Difficult to add custom logic (formatters, interactive prompts)
|
|
63
|
+
- β Breaking changes harder to manage with generated code
|
|
64
|
+
|
|
65
|
+
**Verdict**: Full auto-generation trades flexibility for convenience, which isn't worth it for a developer-facing CLI.
|
|
66
|
+
|
|
67
|
+
### Option 2: Hybrid Approach (Recommended)
|
|
68
|
+
|
|
69
|
+
**Philosophy**: Auto-generate scaffolding, manually implement business logic.
|
|
70
|
+
|
|
71
|
+
**What to Auto-Generate**:
|
|
72
|
+
1. Command structure skeleton
|
|
73
|
+
2. Type definitions (already done via contracts)
|
|
74
|
+
3. Basic parameter parsing
|
|
75
|
+
4. API method invocations
|
|
76
|
+
|
|
77
|
+
**What to Keep Manual**:
|
|
78
|
+
1. Help text and examples
|
|
79
|
+
2. Output formatting logic
|
|
80
|
+
3. Error messages and handling
|
|
81
|
+
4. Interactive prompts
|
|
82
|
+
5. Complex validation
|
|
83
|
+
6. Edge case handling
|
|
84
|
+
|
|
85
|
+
### Option 3: Convention-Based Generation (Best for MemNexus)
|
|
86
|
+
|
|
87
|
+
**Philosophy**: Use conventions + metadata to minimize manual work while keeping flexibility.
|
|
88
|
+
|
|
89
|
+
## Recommended Approach: Smart Scaffolding
|
|
90
|
+
|
|
91
|
+
### 1. Command Scaffold Generator
|
|
92
|
+
|
|
93
|
+
Create a custom generator that creates **starter templates** from OpenAPI spec:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Developer runs this when new API endpoint added:
|
|
97
|
+
npm run generate:command -- --operation exportArtifact
|
|
98
|
+
|
|
99
|
+
# Generates: src/commands/artifacts-export.ts with skeleton
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Generated Template**:
|
|
103
|
+
```typescript
|
|
104
|
+
// AUTO-GENERATED SKELETON - DO NOT EDIT HEADER
|
|
105
|
+
// Generated from: POST /api/artifacts/export
|
|
106
|
+
// Last updated: 2025-11-13T10:00:00Z
|
|
107
|
+
|
|
108
|
+
import { Command } from 'commander';
|
|
109
|
+
import { getApiClient } from '../lib/api-client';
|
|
110
|
+
import type { ExportArtifactRequest } from '@memnexus-ai/contracts';
|
|
111
|
+
|
|
112
|
+
export const exportArtifactCommand = new Command('export')
|
|
113
|
+
.description('Export artifacts to various formats')
|
|
114
|
+
// TODO: Add detailed help text and examples
|
|
115
|
+
.option('--format <format>', 'Export format (pdf, json, csv)')
|
|
116
|
+
.option('--artifact-ids <ids...>', 'Artifact IDs to export')
|
|
117
|
+
.option('--output <file>', 'Output file path')
|
|
118
|
+
.action(async (options) => {
|
|
119
|
+
try {
|
|
120
|
+
const client = getApiClient();
|
|
121
|
+
|
|
122
|
+
// TODO: Add input validation
|
|
123
|
+
const request: ExportArtifactRequest = {
|
|
124
|
+
format: options.format,
|
|
125
|
+
artifactIds: options.artifactIds,
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// TODO: Add progress indicator
|
|
129
|
+
const result = await client.artifacts.export(request);
|
|
130
|
+
|
|
131
|
+
// TODO: Implement output formatting
|
|
132
|
+
console.log('Export completed:', result);
|
|
133
|
+
} catch (error) {
|
|
134
|
+
// TODO: Improve error handling
|
|
135
|
+
console.error('Export failed:', error);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### 2. Implementation Workflow
|
|
142
|
+
|
|
143
|
+
**Step 1: API Change**
|
|
144
|
+
```bash
|
|
145
|
+
cd mx-core-api
|
|
146
|
+
# Add new endpoint
|
|
147
|
+
# Update OpenAPI spec
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Step 2: Contracts Update**
|
|
151
|
+
```bash
|
|
152
|
+
cd mx-api-gateway/contracts
|
|
153
|
+
npm run generate:sdk # Auto-generates types
|
|
154
|
+
npm run build
|
|
155
|
+
npm run test
|
|
156
|
+
# Publish via GitHub Actions
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Step 3: CLI Scaffold Generation**
|
|
160
|
+
```bash
|
|
161
|
+
cd mx-cli
|
|
162
|
+
npm install @memnexus-ai/contracts@latest
|
|
163
|
+
|
|
164
|
+
# Run custom scaffold generator
|
|
165
|
+
npm run generate:command -- --spec ../mx-api-gateway/contracts/openapi.yaml
|
|
166
|
+
|
|
167
|
+
# Or interactive mode:
|
|
168
|
+
npm run generate:command
|
|
169
|
+
# ? Select operation to implement: POST /api/artifacts/export
|
|
170
|
+
# ? Command name: artifacts export
|
|
171
|
+
# β Generated src/commands/artifacts-export.ts
|
|
172
|
+
# β Updated src/commands/index.ts
|
|
173
|
+
# TODO: Implement business logic in src/commands/artifacts-export.ts
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Step 4: Developer Implements**
|
|
177
|
+
```typescript
|
|
178
|
+
// Developer fills in TODOs:
|
|
179
|
+
.description('Export artifacts to PDF, JSON, or CSV formats')
|
|
180
|
+
.addHelpText('after', `
|
|
181
|
+
Examples:
|
|
182
|
+
$ mx artifacts export --format pdf --artifact-ids art_123 art_456 --output export.pdf
|
|
183
|
+
$ mx artifacts export --format json --artifact-ids art_123 --output export.json
|
|
184
|
+
`)
|
|
185
|
+
.option('--format <format>', 'Export format', (val) => {
|
|
186
|
+
if (!['pdf', 'json', 'csv'].includes(val)) {
|
|
187
|
+
throw new Error('Format must be pdf, json, or csv');
|
|
188
|
+
}
|
|
189
|
+
return val;
|
|
190
|
+
})
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Step 5: Test & Publish**
|
|
194
|
+
```bash
|
|
195
|
+
npm run build
|
|
196
|
+
npm test
|
|
197
|
+
# Push to main β GitHub Actions publishes
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### 3. Scaffold Generator Implementation
|
|
201
|
+
|
|
202
|
+
**Tool**: Custom Node.js script using `openapi-typescript` AST
|
|
203
|
+
|
|
204
|
+
**Location**: `mx-cli/scripts/generate-command.ts`
|
|
205
|
+
|
|
206
|
+
**Key Features**:
|
|
207
|
+
1. **Parse OpenAPI Spec** - Read operation definitions
|
|
208
|
+
2. **Extract Metadata**:
|
|
209
|
+
- HTTP method & path
|
|
210
|
+
- Parameters (path, query, body)
|
|
211
|
+
- Request/response schemas
|
|
212
|
+
- Description & tags
|
|
213
|
+
3. **Generate Command File** - Template with TODOs
|
|
214
|
+
4. **Update Index** - Auto-register command
|
|
215
|
+
5. **Generate Test Stub** - Basic test template
|
|
216
|
+
|
|
217
|
+
**Usage**:
|
|
218
|
+
```bash
|
|
219
|
+
# Interactive mode
|
|
220
|
+
npm run generate:command
|
|
221
|
+
|
|
222
|
+
# CLI mode
|
|
223
|
+
npm run generate:command -- \
|
|
224
|
+
--spec ../mx-api-gateway/contracts/openapi.yaml \
|
|
225
|
+
--operation exportArtifact \
|
|
226
|
+
--command-path artifacts.export
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Example Generator Script**:
|
|
230
|
+
```typescript
|
|
231
|
+
// scripts/generate-command.ts
|
|
232
|
+
import fs from 'fs';
|
|
233
|
+
import path from 'path';
|
|
234
|
+
import { parse } from 'yaml';
|
|
235
|
+
|
|
236
|
+
interface GenerateOptions {
|
|
237
|
+
spec: string;
|
|
238
|
+
operation: string;
|
|
239
|
+
commandPath: string;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function generateCommand(options: GenerateOptions): void {
|
|
243
|
+
// 1. Parse OpenAPI spec
|
|
244
|
+
const spec = parse(fs.readFileSync(options.spec, 'utf8'));
|
|
245
|
+
|
|
246
|
+
// 2. Find operation
|
|
247
|
+
const operation = findOperation(spec, options.operation);
|
|
248
|
+
if (!operation) {
|
|
249
|
+
throw new Error(`Operation ${options.operation} not found`);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// 3. Extract metadata
|
|
253
|
+
const metadata = extractMetadata(operation);
|
|
254
|
+
|
|
255
|
+
// 4. Generate command file
|
|
256
|
+
const template = generateTemplate(metadata);
|
|
257
|
+
const outputPath = path.join(
|
|
258
|
+
'src/commands',
|
|
259
|
+
`${options.commandPath.replace('.', '-')}.ts`
|
|
260
|
+
);
|
|
261
|
+
fs.writeFileSync(outputPath, template);
|
|
262
|
+
|
|
263
|
+
// 5. Update index
|
|
264
|
+
updateCommandIndex(options.commandPath, outputPath);
|
|
265
|
+
|
|
266
|
+
console.log(`β Generated ${outputPath}`);
|
|
267
|
+
console.log('TODO: Implement business logic and polish the command');
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### 4. Detection of Missing Commands
|
|
272
|
+
|
|
273
|
+
**Problem**: How to know when API changes require CLI updates?
|
|
274
|
+
|
|
275
|
+
**Solution**: Automated comparison tool
|
|
276
|
+
|
|
277
|
+
**Tool**: `mx-cli/scripts/check-coverage.ts`
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
// Checks which API operations don't have CLI commands
|
|
281
|
+
npm run check:coverage
|
|
282
|
+
|
|
283
|
+
// Output:
|
|
284
|
+
// β GET /api/memories - Implemented (src/commands/memories.ts)
|
|
285
|
+
// β POST /api/memories - Implemented (src/commands/memories.ts)
|
|
286
|
+
// β POST /api/artifacts/export - NOT IMPLEMENTED
|
|
287
|
+
// β GET /api/patterns/recommendations - NOT IMPLEMENTED
|
|
288
|
+
//
|
|
289
|
+
// Coverage: 45/47 operations (95.7%)
|
|
290
|
+
// Run 'npm run generate:command' to scaffold missing commands
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
**Implementation**:
|
|
294
|
+
```typescript
|
|
295
|
+
// scripts/check-coverage.ts
|
|
296
|
+
import { parse } from 'yaml';
|
|
297
|
+
import { getAllCommands } from '../src/commands';
|
|
298
|
+
|
|
299
|
+
function checkCoverage(): void {
|
|
300
|
+
const spec = loadOpenAPISpec();
|
|
301
|
+
const operations = extractAllOperations(spec);
|
|
302
|
+
const commands = getAllCommands();
|
|
303
|
+
|
|
304
|
+
const missing: string[] = [];
|
|
305
|
+
|
|
306
|
+
for (const op of operations) {
|
|
307
|
+
const commandExists = commands.some(cmd =>
|
|
308
|
+
cmd.operationId === op.operationId
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
if (commandExists) {
|
|
312
|
+
console.log(`β ${op.method} ${op.path} - Implemented`);
|
|
313
|
+
} else {
|
|
314
|
+
console.log(`β ${op.method} ${op.path} - NOT IMPLEMENTED`);
|
|
315
|
+
missing.push(op.operationId);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (missing.length > 0) {
|
|
320
|
+
console.log(`\nβ οΈ ${missing.length} operations not implemented`);
|
|
321
|
+
console.log(`Run: npm run generate:command --operation ${missing[0]}`);
|
|
322
|
+
process.exit(1); // Fail CI/CD
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**Integration with CI/CD**:
|
|
328
|
+
```yaml
|
|
329
|
+
# .github/workflows/publish.yml
|
|
330
|
+
jobs:
|
|
331
|
+
validate:
|
|
332
|
+
steps:
|
|
333
|
+
- name: Check API coverage
|
|
334
|
+
run: |
|
|
335
|
+
npm run check:coverage
|
|
336
|
+
# Fails if operations are missing
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### 5. Metadata-Driven Commands
|
|
340
|
+
|
|
341
|
+
**Philosophy**: Store command metadata alongside OpenAPI extensions
|
|
342
|
+
|
|
343
|
+
**OpenAPI Extensions**:
|
|
344
|
+
```yaml
|
|
345
|
+
# openapi.yaml
|
|
346
|
+
paths:
|
|
347
|
+
/api/artifacts/export:
|
|
348
|
+
post:
|
|
349
|
+
operationId: exportArtifact
|
|
350
|
+
x-cli-command: artifacts export
|
|
351
|
+
x-cli-examples:
|
|
352
|
+
- description: Export single artifact as PDF
|
|
353
|
+
command: mx artifacts export --format pdf --artifact-ids art_123 --output export.pdf
|
|
354
|
+
- description: Export multiple artifacts as JSON
|
|
355
|
+
command: mx artifacts export --format json --artifact-ids art_123 art_456 --output export.json
|
|
356
|
+
x-cli-options:
|
|
357
|
+
format:
|
|
358
|
+
help: Output format (pdf, json, csv)
|
|
359
|
+
required: true
|
|
360
|
+
output:
|
|
361
|
+
help: Output file path
|
|
362
|
+
required: true
|
|
363
|
+
summary: Export artifacts to various formats
|
|
364
|
+
description: |
|
|
365
|
+
Export one or more artifacts to PDF, JSON, or CSV format.
|
|
366
|
+
The export is generated asynchronously and streamed to the output file.
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
**Generated Command Uses Metadata**:
|
|
370
|
+
```typescript
|
|
371
|
+
// Auto-generated from x-cli-* extensions
|
|
372
|
+
export const exportArtifactCommand = new Command('export')
|
|
373
|
+
.description('Export artifacts to various formats')
|
|
374
|
+
.addHelpText('after', `
|
|
375
|
+
Examples:
|
|
376
|
+
$ mx artifacts export --format pdf --artifact-ids art_123 --output export.pdf
|
|
377
|
+
$ mx artifacts export --format json --artifact-ids art_123 art_456 --output export.json
|
|
378
|
+
`)
|
|
379
|
+
.option('--format <format>', 'Output format (pdf, json, csv)', { required: true })
|
|
380
|
+
.option('--output <file>', 'Output file path', { required: true })
|
|
381
|
+
.action(async (options) => {
|
|
382
|
+
// Implementation...
|
|
383
|
+
});
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### 6. Update Notification System
|
|
387
|
+
|
|
388
|
+
**Problem**: Developers need to know when CLI is out of sync
|
|
389
|
+
|
|
390
|
+
**Solution**: Automated PR creation
|
|
391
|
+
|
|
392
|
+
```yaml
|
|
393
|
+
# .github/workflows/check-cli-sync.yml
|
|
394
|
+
name: Check CLI Sync
|
|
395
|
+
|
|
396
|
+
on:
|
|
397
|
+
workflow_run:
|
|
398
|
+
workflows: ["Publish Contracts Package"]
|
|
399
|
+
types: [completed]
|
|
400
|
+
|
|
401
|
+
jobs:
|
|
402
|
+
check-sync:
|
|
403
|
+
runs-on: ubuntu-latest
|
|
404
|
+
steps:
|
|
405
|
+
- name: Checkout
|
|
406
|
+
uses: actions/checkout@v4
|
|
407
|
+
|
|
408
|
+
- name: Install contracts package
|
|
409
|
+
run: |
|
|
410
|
+
cd mx-cli
|
|
411
|
+
npm install @memnexus-ai/contracts@latest
|
|
412
|
+
|
|
413
|
+
- name: Check coverage
|
|
414
|
+
id: coverage
|
|
415
|
+
run: |
|
|
416
|
+
cd mx-cli
|
|
417
|
+
npm run check:coverage || echo "missing=true" >> $GITHUB_OUTPUT
|
|
418
|
+
|
|
419
|
+
- name: Create PR if out of sync
|
|
420
|
+
if: steps.coverage.outputs.missing == 'true'
|
|
421
|
+
uses: peter-evans/create-pull-request@v5
|
|
422
|
+
with:
|
|
423
|
+
title: "π Update CLI for new API endpoints"
|
|
424
|
+
body: |
|
|
425
|
+
## New API Endpoints Detected
|
|
426
|
+
|
|
427
|
+
The `@memnexus-ai/contracts` package has been updated with new API operations.
|
|
428
|
+
The following CLI commands need to be implemented:
|
|
429
|
+
|
|
430
|
+
${{ steps.coverage.outputs.missing_operations }}
|
|
431
|
+
|
|
432
|
+
### Next Steps
|
|
433
|
+
1. Run `npm run generate:command` to scaffold new commands
|
|
434
|
+
2. Implement business logic for each command
|
|
435
|
+
3. Add tests
|
|
436
|
+
4. Update documentation
|
|
437
|
+
|
|
438
|
+
### Related
|
|
439
|
+
- Contracts version: `${{ steps.coverage.outputs.contracts_version }}`
|
|
440
|
+
- PR will auto-close when all operations are implemented
|
|
441
|
+
labels: enhancement, auto-generated
|
|
442
|
+
branch: cli-sync-update
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
## Comparison: Manual vs. Hybrid
|
|
446
|
+
|
|
447
|
+
### Fully Manual (Current State)
|
|
448
|
+
|
|
449
|
+
**Time per Endpoint**: ~2-4 hours
|
|
450
|
+
- Write command boilerplate (30 min)
|
|
451
|
+
- Implement business logic (1-2 hours)
|
|
452
|
+
- Write tests (30-60 min)
|
|
453
|
+
- Write documentation (30 min)
|
|
454
|
+
|
|
455
|
+
**Pros**:
|
|
456
|
+
- β
Maximum flexibility
|
|
457
|
+
- β
Consistent code style
|
|
458
|
+
|
|
459
|
+
**Cons**:
|
|
460
|
+
- β Repetitive boilerplate
|
|
461
|
+
- β Easy to miss new endpoints
|
|
462
|
+
- β Slow to keep pace with API changes
|
|
463
|
+
|
|
464
|
+
### Hybrid with Scaffolding (Recommended)
|
|
465
|
+
|
|
466
|
+
**Time per Endpoint**: ~1-2 hours (50% faster)
|
|
467
|
+
- Run generator (1 min)
|
|
468
|
+
- Implement business logic (1-1.5 hours)
|
|
469
|
+
- Tests auto-generated, just fill in (15-30 min)
|
|
470
|
+
- Documentation from OpenAPI extensions (5 min)
|
|
471
|
+
|
|
472
|
+
**Pros**:
|
|
473
|
+
- β
Faster development
|
|
474
|
+
- β
Consistent structure
|
|
475
|
+
- β
Never miss endpoints (automated checks)
|
|
476
|
+
- β
Keeps flexibility where needed
|
|
477
|
+
|
|
478
|
+
**Cons**:
|
|
479
|
+
- β Initial generator development (~1 week)
|
|
480
|
+
- β Maintain generator as patterns evolve
|
|
481
|
+
|
|
482
|
+
## Implementation Roadmap
|
|
483
|
+
|
|
484
|
+
### Phase 1: Manual with Conventions (Week 1-4)
|
|
485
|
+
**Status**: Current approach for v1.0
|
|
486
|
+
|
|
487
|
+
- [x] Use `@memnexus-ai/contracts` for types
|
|
488
|
+
- [ ] Establish command structure conventions
|
|
489
|
+
- [ ] Document command implementation guide
|
|
490
|
+
- [ ] Build first set of commands manually
|
|
491
|
+
|
|
492
|
+
**Goal**: Ship v1.0, learn patterns
|
|
493
|
+
|
|
494
|
+
### Phase 2: Coverage Detection (Week 5-6)
|
|
495
|
+
**Status**: Can be done in parallel with v1.0 development
|
|
496
|
+
|
|
497
|
+
- [ ] Build `check-coverage` script
|
|
498
|
+
- [ ] Add to CI/CD
|
|
499
|
+
- [ ] Create GitHub Action for notifications
|
|
500
|
+
|
|
501
|
+
**Goal**: Never miss API changes
|
|
502
|
+
|
|
503
|
+
### Phase 3: Command Scaffolding (Month 2)
|
|
504
|
+
**Status**: After v1.0 patterns are established
|
|
505
|
+
|
|
506
|
+
- [ ] Build `generate-command` script
|
|
507
|
+
- [ ] Support OpenAPI `x-cli-*` extensions
|
|
508
|
+
- [ ] Generate tests alongside commands
|
|
509
|
+
- [ ] Update generator as patterns evolve
|
|
510
|
+
|
|
511
|
+
**Goal**: 50% faster development for new endpoints
|
|
512
|
+
|
|
513
|
+
### Phase 4: Metadata-Driven (Month 3+)
|
|
514
|
+
**Status**: Future enhancement
|
|
515
|
+
|
|
516
|
+
- [ ] Add `x-cli-*` extensions to OpenAPI spec
|
|
517
|
+
- [ ] Generate help text from extensions
|
|
518
|
+
- [ ] Auto-update CLI when contracts change
|
|
519
|
+
- [ ] Consider runtime command loading
|
|
520
|
+
|
|
521
|
+
**Goal**: Near-automatic CLI updates
|
|
522
|
+
|
|
523
|
+
## Recommendation
|
|
524
|
+
|
|
525
|
+
**For MemNexus v1.0**:
|
|
526
|
+
1. β
Start manual (Phases 1) - Fastest path to v1.0
|
|
527
|
+
2. β
Add coverage detection (Phase 2) - Prevents missing APIs
|
|
528
|
+
3. βΈοΈ Hold on scaffolding (Phase 3) - Wait until patterns stabilize
|
|
529
|
+
4. βΈοΈ Defer metadata-driven (Phase 4) - v2.0 feature
|
|
530
|
+
|
|
531
|
+
**Rationale**:
|
|
532
|
+
- Manual is fine for ~50 endpoints in v1.0
|
|
533
|
+
- Learn patterns before automating
|
|
534
|
+
- Coverage detection gives 80% of benefit with 20% of effort
|
|
535
|
+
- Generator can be built once patterns are proven
|
|
536
|
+
|
|
537
|
+
## Decision Matrix
|
|
538
|
+
|
|
539
|
+
| Approach | Dev Time | Flexibility | Consistency | Maintenance | Recommendation |
|
|
540
|
+
|----------|----------|-------------|-------------|-------------|----------------|
|
|
541
|
+
| **Fully Manual** | π΄ Slow | π’ High | π‘ Medium | π’ Low | βΈοΈ V1.0 only |
|
|
542
|
+
| **Hybrid (Coverage + Manual)** | π‘ Medium | π’ High | π’ High | π‘ Medium | β
**Recommended** |
|
|
543
|
+
| **Hybrid (Scaffold + Manual)** | π’ Fast | π’ High | π’ High | π‘ Medium | βΈοΈ Post-v1.0 |
|
|
544
|
+
| **Fully Generated** | π’ Fastest | π΄ Low | π’ High | π΄ High | β Not viable |
|
|
545
|
+
|
|
546
|
+
## Key Takeaways
|
|
547
|
+
|
|
548
|
+
1. **No magic bullet** - Full automation loses flexibility for developer CLIs
|
|
549
|
+
2. **Hybrid is best** - Generate structure, implement logic manually
|
|
550
|
+
3. **Coverage detection first** - Know when you're out of sync (easy win)
|
|
551
|
+
4. **Scaffolding later** - Build generator after patterns stabilize
|
|
552
|
+
5. **Manual is okay** - For v1.0 with ~50 endpoints, manual is acceptable
|
|
553
|
+
6. **Metadata helps** - OpenAPI extensions reduce duplication
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
**Document Version**: 1.0
|
|
558
|
+
**Last Updated**: 2025-11-13
|
|
559
|
+
**Author**: Claude Code
|
|
560
|
+
**Status**: Proposed Strategy
|