@miphamai/cli 0.7.6 → 0.7.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miphamai/cli",
3
- "version": "0.7.6",
3
+ "version": "0.7.8",
4
4
  "description": "Mipham Code — Multi-model open-core intelligent coding terminal by MiphamAI",
5
5
  "keywords": [
6
6
  "ai",
package/src/ui/app.tsx CHANGED
@@ -175,9 +175,12 @@ export function App({
175
175
  return
176
176
  }
177
177
 
178
+ let forwardToAI: string | undefined
179
+
178
180
  const handler = getCommand(command)
179
181
  if (handler) {
180
182
  const result = await handler(mkCtx(), args)
183
+ forwardToAI = result.forwardToAI
181
184
  setMessages((prev) => [
182
185
  ...prev,
183
186
  { role: 'user', content: input },
@@ -202,8 +205,15 @@ export function App({
202
205
  }
203
206
  }
204
207
  }
205
- // Unknown slash command or handler returned: proceed to normal AI processing
206
- return
208
+
209
+ // Bridge: if command set forwardToAI, route the message to AI processing
210
+ if (forwardToAI) {
211
+ input = forwardToAI
212
+ // fall through to normal AI processing below
213
+ } else {
214
+ // No handler matched or handler didn't request AI routing — stop here
215
+ return
216
+ }
207
217
  }
208
218
 
209
219
  // ── Normal message processing (AI chat) ──
@@ -40,6 +40,9 @@ export interface CommandResult {
40
40
  clearMessages?: boolean
41
41
  /** Content to copy to clipboard (handled by caller) */
42
42
  copyContent?: string
43
+ /** If set, route this message to the AI engine — bridges slash commands → skill/agent invocation.
44
+ * The app layer replaces the user input with this string and falls through to AI processing. */
45
+ forwardToAI?: string
43
46
  }
44
47
 
45
48
  type CommandHandler = (
@@ -1088,6 +1091,18 @@ const branchCmd: CommandHandler = (ctx, args) => {
1088
1091
  }
1089
1092
  }
1090
1093
 
1094
+ /** Parse human-readable interval to seconds. Returns null if invalid. */
1095
+ function parseInterval(raw: string): number | null {
1096
+ const m = raw.trim().match(/^(\d+)\s*(s|sec|m|min|h|hr|hour)$/i)
1097
+ if (!m) return null
1098
+ const n = parseInt(m[1]!, 10)
1099
+ const unit = m[2]!.toLowerCase()
1100
+ if (unit === 's' || unit === 'sec') return n
1101
+ if (unit === 'm' || unit === 'min') return n * 60
1102
+ if (unit === 'h' || unit === 'hr' || unit === 'hour') return n * 3600
1103
+ return null
1104
+ }
1105
+
1091
1106
  const loopCmd: CommandHandler = async (_ctx, args) => {
1092
1107
  const sub = args[0]
1093
1108
 
@@ -1166,24 +1181,23 @@ const loopCmd: CommandHandler = async (_ctx, args) => {
1166
1181
  /loop 5m check the deploy status
1167
1182
  /loop init Create vault in current directory
1168
1183
  /loop init ~/my-project Create vault in specific directory
1169
-
1170
- Note: Continuous looping requires session persistence, coming in a future release.
1171
1184
  `,
1172
1185
  }
1173
1186
  }
1174
1187
 
1175
1188
  const interval = args[0]!
1176
1189
  const prompt = args.slice(1).join(' ')
1190
+ const seconds = parseInterval(interval)
1177
1191
 
1178
- return {
1179
- content: stripIndent`
1180
- ── Loop Configured ──
1181
- Interval: ${interval}
1182
- Prompt: "${prompt}"
1192
+ if (seconds === null) {
1193
+ return {
1194
+ content: `── Invalid Interval ──\n\n"${interval}" is not a recognised interval.\n\nUse formats like: 10s, 5m, 1h, 30min, 2hr`,
1195
+ }
1196
+ }
1183
1197
 
1184
- Loop scheduling infrastructure is being built.
1185
- For now, manually re-run: /loop ${interval} ${prompt}
1186
- `,
1198
+ return {
1199
+ content: `── Loop Started ──\n\nInterval: ${interval} (${seconds}s)\nPrompt: "${prompt}"\n\nScheduling via ScheduleWakeup — the prompt will re-schedule itself each cycle.\nUse /schedule to view active loops.`,
1200
+ forwardToAI: `use ScheduleWakeup to set up a recurring loop. delaySeconds=${seconds}, prompt: "${prompt}". Include at the end of the prompt: "Then call ScheduleWakeup again with delaySeconds=${seconds} and the same prompt to continue the loop."`,
1187
1201
  }
1188
1202
  }
1189
1203
 
@@ -1191,14 +1205,15 @@ const scheduleCmd: CommandHandler = (_ctx) => ({
1191
1205
  content: stripIndent`
1192
1206
  ── Scheduled Tasks ──
1193
1207
 
1194
- No scheduled tasks configured.
1208
+ Active loops are managed via ScheduleWakeup (in-session) and
1209
+ CronCreate (durable, survives restarts).
1195
1210
 
1196
- Schedule infrastructure is being built. Coming features:
1197
- • Cron-based scheduling (CronCreate tool)
1198
- • One-shot and recurring tasks
1199
- • Durable persistence across sessions
1211
+ Use /loop <interval> <prompt> to start a recurring task.
1212
+ Use CronList to view all scheduled jobs.
1213
+ Use CronDelete <id> to cancel a durable job.
1200
1214
 
1201
- Use /loop for simple repetition in the current session.
1215
+ The ScheduleWakeup mechanism automatically re-schedules on
1216
+ each wake, creating a self-perpetuating loop within the session.
1202
1217
  `,
1203
1218
  })
1204
1219
 
@@ -1417,42 +1432,70 @@ const issueCmd: CommandHandler = async () => {
1417
1432
  }
1418
1433
 
1419
1434
  // ═══════════════════════════════════════════════════════════════
1420
- // Code Quality Commands (Claude Code parity)
1435
+ // Code Quality — bridge slash commands to skills (Claude Code parity)
1421
1436
  // ═══════════════════════════════════════════════════════════════
1422
1437
 
1423
- const simplifyCmd: CommandHandler = async () => {
1424
- try {
1425
- const { execSync } = await import('node:child_process')
1426
- const diff = execSync('git diff --stat', { encoding: 'utf-8', timeout: 5000 }).trim()
1427
- const changed = execSync('git diff --name-only', { encoding: 'utf-8', timeout: 3000 }).trim()
1428
-
1429
- if (!diff) {
1438
+ /** Factory for git-diff-based commands that bridge to AI skills via forwardToAI. */
1439
+ function gitDiffBridgeCmd(opts: {
1440
+ label: string
1441
+ noChangesHint: string
1442
+ runningMsg: string
1443
+ forwardToAI: string
1444
+ }): CommandHandler {
1445
+ return async () => {
1446
+ try {
1447
+ const { execSync } = await import('node:child_process')
1448
+ const diff = execSync('git diff --stat', { encoding: 'utf-8', timeout: 5000 }).trim()
1449
+ if (!diff) {
1450
+ return { content: `─ ${opts.label} ─\n\n${opts.noChangesHint}` }
1451
+ }
1430
1452
  return {
1431
- content:
1432
- '── Simplify ──\n\nNo uncommitted changes to review.\n\nRun /simplify after making changes to review for reuse, simplification, and quality improvements.',
1453
+ content: `─ ${opts.label} ─\n\n${opts.runningMsg}\n\nChanged files:\n${diff}`,
1454
+ forwardToAI: opts.forwardToAI,
1455
+ }
1456
+ } catch {
1457
+ return {
1458
+ content: `─ ${opts.label} ─\n\nCould not detect changes. Are you in a git repository?`,
1433
1459
  }
1434
1460
  }
1461
+ }
1462
+ }
1435
1463
 
1436
- return {
1437
- content: [
1438
- '── Simplify Review ──',
1439
- '',
1440
- 'Changed files:',
1441
- diff,
1442
- '',
1443
- 'To run simplification review, type: "review these changes for simplification and quality"',
1444
- '',
1445
- 'This will check for:',
1446
- ' • Code reuse opportunities',
1447
- ' • Overly complex logic',
1448
- ' • Dead code removal',
1449
- ' • Style and consistency',
1450
- '',
1451
- `Files to review: ${changed.split('\n').length}`,
1452
- ].join('\n'),
1453
- }
1454
- } catch {
1455
- return { content: '── Simplify ──\n\nCould not detect changes. Are you in a git repository?' }
1464
+ const codeReviewCmd = gitDiffBridgeCmd({
1465
+ label: 'Code Review',
1466
+ noChangesHint:
1467
+ 'No uncommitted changes to review.\n\nTo review a specific file: /code-review path/to/file.ts',
1468
+ runningMsg:
1469
+ 'Reviewing uncommitted changes with the code-review skill (7 dimensions: correctness, security, performance, code quality, architecture, testing, language-specific)...',
1470
+ forwardToAI:
1471
+ 'use the code-review skill to review all uncommitted changes. Check all 7 dimensions: correctness, security, performance, code quality, architecture & design, testing, and language-specific issues.',
1472
+ })
1473
+
1474
+ const simplifyCmd = gitDiffBridgeCmd({
1475
+ label: 'Simplify',
1476
+ noChangesHint:
1477
+ 'No uncommitted changes to simplify.\n\nMake changes first, then run /simplify for cleanup review.',
1478
+ runningMsg:
1479
+ 'Running cleanup review — 4 passes: reuse, simplification, efficiency, abstraction level...',
1480
+ forwardToAI:
1481
+ 'use the self-review skill to review these uncommitted changes. Focus on 4 cleanup passes: 1) Reuse — find duplicated logic, replace with existing helpers; 2) Simplification — flatten nesting, remove redundant state and dead code; 3) Efficiency — fix repeated object creation, unnecessary I/O, memory issues; 4) Abstraction Level — ensure code sits at the right architectural layer. Apply equivalent transformations only — do NOT change logic or fix bugs.',
1482
+ })
1483
+
1484
+ const verifyCmd = gitDiffBridgeCmd({
1485
+ label: 'Verify',
1486
+ noChangesHint:
1487
+ 'No uncommitted changes to verify.\n\nMake changes first, then run /verify for runtime verification.',
1488
+ runningMsg:
1489
+ 'Running runtime verification — observing actual execution behavior (not tests, not typecheck)...',
1490
+ forwardToAI:
1491
+ 'verify these uncommitted changes through runtime observation only. For each change: 1) Find the user-facing surface (CLI command, API endpoint, UI interaction); 2) Drive the changed code to execute; 3) Push boundaries — pass null, repeated values, wrong types, interrupt mid-flow (Ctrl-C), resize window; 4) Report verdict per change: PASS (works as expected), FAIL (does not work or breaks something), BLOCKED (cannot reach observable state), SKIP (no runtime surface, e.g. pure documentation). Do NOT run the test suite — observe real execution behavior only.',
1492
+ })
1493
+
1494
+ const designCmd: CommandHandler = (_ctx, args) => {
1495
+ const topic = args.join(' ') || 'the current task'
1496
+ return {
1497
+ content: `─ Design ─\n\nStarting architectural design session for: ${topic}\n\nExploring approaches, trade-offs, component breakdown, data flow...`,
1498
+ forwardToAI: `help me design the architecture for ${topic}. Explore 2-3 approaches with trade-offs, then present a design covering: component breakdown, data flow, interfaces between components, error handling strategy, and testing approach. Use the plan sub-agent if deeper analysis would help. Prefer simplicity — YAGNI.`,
1456
1499
  }
1457
1500
  }
1458
1501
 
@@ -3495,8 +3538,11 @@ const commandsListCmd: CommandHandler = () => {
3495
3538
  '/push': 'Workflow',
3496
3539
  '/pr': 'Workflow',
3497
3540
  '/issue': 'Workflow',
3498
- '/simplify': 'Workflow',
3499
- '/lint': 'Workflow',
3541
+ '/code-review': 'Code Quality',
3542
+ '/simplify': 'Code Quality',
3543
+ '/verify': 'Code Quality',
3544
+ '/design': 'Code Quality',
3545
+ '/lint': 'Code Quality',
3500
3546
  '/files': 'Session & Identity',
3501
3547
  '/stats': 'Session & Identity',
3502
3548
  '/summary': 'Session & Identity',
@@ -3634,7 +3680,10 @@ registry.set('/pr', prCmd)
3634
3680
  registry.set('/issue', issueCmd)
3635
3681
 
3636
3682
  // Code Quality (Claude Code parity)
3683
+ registry.set('/code-review', codeReviewCmd)
3637
3684
  registry.set('/simplify', simplifyCmd)
3685
+ registry.set('/verify', verifyCmd)
3686
+ registry.set('/design', designCmd)
3638
3687
  registry.set('/lint', lintCmd)
3639
3688
 
3640
3689
  // Session Enhancement (Claude Code parity)
@@ -3741,7 +3790,10 @@ const COMMAND_DESCRIPTIONS: Record<string, string> = {
3741
3790
  '/push': 'Push the current branch',
3742
3791
  '/pr': 'Create a pull request',
3743
3792
  '/issue': 'File a GitHub issue',
3744
- '/simplify': 'Review code for reuse, simplification, and quality',
3793
+ '/code-review': 'Review code for bugs, security, performance (7 dimensions)',
3794
+ '/simplify': 'Cleanup-only review: reuse, simplification, efficiency, abstraction',
3795
+ '/verify': 'Runtime verification — observe actual execution, not tests',
3796
+ '/design': 'Start architectural design session — explore approaches and trade-offs',
3745
3797
  '/lint': 'Run linting on the project',
3746
3798
  '/files': 'List files in current working directory',
3747
3799
  '/stats': 'Show session usage statistics',
package/dist/mipham DELETED
Binary file