@miphamai/cli 0.2.3 → 0.3.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 +1 -1
- package/bin/mipham.ts +26 -2
- package/package.json +4 -3
- package/skills/mipham/om-model-optimize.mipham-skill.md +55 -9
- package/skills/mipham/om-security.mipham-skill.md +82 -10
- package/skills/standard/doc-generator.SKILL.md +67 -11
- package/skills/standard/github-ops.SKILL.md +89 -13
- package/skills/standard/memory.SKILL.md +71 -11
- package/skills/standard/mipham-code-setup.SKILL.md +1 -1
- package/skills/standard/self-review.SKILL.md +49 -10
- package/skills/standard/superpower.SKILL.md +46 -8
- package/skills/standard/tdd.SKILL.md +85 -12
- package/skills/standard/web-search.SKILL.md +62 -13
- package/src/core/context.ts +73 -13
- package/src/core/engine.ts +159 -44
- package/src/core/permission.ts +31 -5
- package/src/core/session-store.ts +5 -1
- package/src/index.tsx +25 -0
- package/src/providers/anthropic.ts +2 -1
- package/src/providers/fetch-utils.ts +103 -0
- package/src/providers/openai-compat.ts +55 -8
- package/src/providers/registry.ts +1 -0
- package/src/ui/app.tsx +117 -14
- package/src/ui/chat.tsx +25 -7
- package/src/ui/commands.ts +43 -13
- package/src/ui/input.tsx +56 -35
package/src/ui/commands.ts
CHANGED
|
@@ -7,6 +7,15 @@
|
|
|
7
7
|
import type { QueryEngine } from '../core/engine'
|
|
8
8
|
import type { MiphamConfig } from '../shared/index.ts'
|
|
9
9
|
import type { SkillsLoader } from '../skills/loader'
|
|
10
|
+
import { McpClient } from '../mcp/client'
|
|
11
|
+
import {
|
|
12
|
+
PACKAGE_NAME,
|
|
13
|
+
NPM_INSTALL_COMMAND,
|
|
14
|
+
NPM_UPDATE_COMMAND,
|
|
15
|
+
NPM_URL,
|
|
16
|
+
PRODUCT_URL_INTERNATIONAL,
|
|
17
|
+
PRODUCT_URL_CHINA,
|
|
18
|
+
} from '@mipham/shared'
|
|
10
19
|
|
|
11
20
|
export interface CommandContext {
|
|
12
21
|
engine: QueryEngine
|
|
@@ -1139,7 +1148,7 @@ To upgrade:
|
|
|
1139
1148
|
curl -fsSL https://mipham.ai/install.sh | bash
|
|
1140
1149
|
|
|
1141
1150
|
Or if installed via npm:
|
|
1142
|
-
|
|
1151
|
+
${NPM_UPDATE_COMMAND}
|
|
1143
1152
|
|
|
1144
1153
|
Release channels:
|
|
1145
1154
|
• stable — recommended for most users
|
|
@@ -1819,7 +1828,7 @@ JetBrains (IntelliJ / WebStorm / PyCharm):
|
|
|
1819
1828
|
Terminal (any):
|
|
1820
1829
|
alias mipham='cd your-project && bun run path/to/mipham'
|
|
1821
1830
|
|
|
1822
|
-
Or install globally:
|
|
1831
|
+
Or install globally: ${NPM_INSTALL_COMMAND}
|
|
1823
1832
|
|
|
1824
1833
|
Coming soon: dedicated VS Code & JetBrains plugin extensions.`,
|
|
1825
1834
|
})
|
|
@@ -1832,7 +1841,7 @@ const terminalSetupCmd: CommandHandler = () => ({
|
|
|
1832
1841
|
content: `── Terminal Setup ──
|
|
1833
1842
|
|
|
1834
1843
|
Install globally:
|
|
1835
|
-
|
|
1844
|
+
${NPM_INSTALL_COMMAND}
|
|
1836
1845
|
mipham
|
|
1837
1846
|
|
|
1838
1847
|
One-liner install:
|
|
@@ -1846,7 +1855,7 @@ Add to shell profile (~/.zshrc or ~/.bashrc):
|
|
|
1846
1855
|
|
|
1847
1856
|
Upgrade:
|
|
1848
1857
|
curl -fsSL https://mipham.ai/install.sh | bash
|
|
1849
|
-
# or:
|
|
1858
|
+
# or: ${NPM_UPDATE_COMMAND}
|
|
1850
1859
|
|
|
1851
1860
|
Verify installation:
|
|
1852
1861
|
mipham --version
|
|
@@ -1860,18 +1869,40 @@ Works with: Bash, Zsh, Fish, PowerShell, Windows Terminal`,
|
|
|
1860
1869
|
// ═══════════════════════════════════════════════════════════════
|
|
1861
1870
|
|
|
1862
1871
|
const mcpCmd: CommandHandler = (ctx) => {
|
|
1863
|
-
const
|
|
1872
|
+
const configuredServers = ctx.config.skills?.mcpServers ?? []
|
|
1873
|
+
const liveConnections = McpClient.getInstance().listConnections()
|
|
1864
1874
|
|
|
1865
1875
|
const lines: string[] = ['── MCP Servers ──', '']
|
|
1866
1876
|
|
|
1867
|
-
if (
|
|
1868
|
-
lines.push(`Configured servers (${
|
|
1877
|
+
if (configuredServers.length > 0) {
|
|
1878
|
+
lines.push(`Configured servers (${configuredServers.length}):`)
|
|
1869
1879
|
lines.push('')
|
|
1870
|
-
for (const s of
|
|
1880
|
+
for (const s of configuredServers) {
|
|
1881
|
+
const live = liveConnections.find((c) => c.config.name === s.name)
|
|
1882
|
+
const statusIcon = live
|
|
1883
|
+
? live.status === 'connected'
|
|
1884
|
+
? '🟢'
|
|
1885
|
+
: live.status === 'connecting'
|
|
1886
|
+
? '🟡'
|
|
1887
|
+
: live.status === 'error'
|
|
1888
|
+
? '🔴'
|
|
1889
|
+
: '⚪'
|
|
1890
|
+
: '⚪'
|
|
1891
|
+
const statusLabel = live ? live.status : 'not started'
|
|
1871
1892
|
const envKeys = s.env ? Object.keys(s.env).join(', ') : '(none)'
|
|
1872
|
-
|
|
1893
|
+
|
|
1894
|
+
lines.push(` ${statusIcon} ${s.name} [${statusLabel}]`)
|
|
1873
1895
|
lines.push(` Command: ${s.command} ${s.args.join(' ')}`)
|
|
1874
1896
|
lines.push(` Env vars: ${envKeys}`)
|
|
1897
|
+
if (live?.tools && live.tools.length > 0) {
|
|
1898
|
+
lines.push(` Tools: ${live.tools.map((t) => t.name).join(', ')}`)
|
|
1899
|
+
}
|
|
1900
|
+
if (live?.error) {
|
|
1901
|
+
lines.push(` Error: ${live.error}`)
|
|
1902
|
+
}
|
|
1903
|
+
if (live?.serverInfo) {
|
|
1904
|
+
lines.push(` Server: ${live.serverInfo.name} v${live.serverInfo.version}`)
|
|
1905
|
+
}
|
|
1875
1906
|
lines.push('')
|
|
1876
1907
|
}
|
|
1877
1908
|
} else {
|
|
@@ -1900,11 +1931,10 @@ const mcpCmd: CommandHandler = (ctx) => {
|
|
|
1900
1931
|
}
|
|
1901
1932
|
|
|
1902
1933
|
lines.push('')
|
|
1903
|
-
lines.push('──
|
|
1904
|
-
lines.push('MCP stdio
|
|
1905
|
-
lines.push('
|
|
1934
|
+
lines.push('── Protocol ──')
|
|
1935
|
+
lines.push('MCP stdio transport (JSON-RPC 2.0) — fully implemented.')
|
|
1936
|
+
lines.push('Servers auto-connect on startup when configured.')
|
|
1906
1937
|
lines.push('')
|
|
1907
|
-
lines.push('MCP enables AI to interact with external tools via standardized servers.')
|
|
1908
1938
|
lines.push('Learn more: https://modelcontextprotocol.io')
|
|
1909
1939
|
|
|
1910
1940
|
return { content: lines.join('\n') }
|
package/src/ui/input.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react'
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react'
|
|
2
2
|
import { Box, Text } from 'ink'
|
|
3
3
|
import TextInput from 'ink-text-input'
|
|
4
4
|
|
|
@@ -7,32 +7,37 @@ interface InputBarProps {
|
|
|
7
7
|
isLoading: boolean
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
// ──
|
|
10
|
+
// ── Status verbs — English (Claude Code-aligned) + Chinese (Mipham originals) ──
|
|
11
11
|
|
|
12
|
-
const
|
|
13
|
-
'
|
|
14
|
-
'
|
|
15
|
-
'
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
'
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
'融汇中', // Fusing
|
|
27
|
-
'觉照中', // Illuminating
|
|
28
|
-
'运转中', // Operating
|
|
29
|
-
'参详中', // Studying
|
|
30
|
-
'化合中', // Synthesizing
|
|
31
|
-
'浸润中', // Infusing
|
|
32
|
-
'焙烤中', // Baking
|
|
12
|
+
const STATUS_EN = [
|
|
13
|
+
'Doodling', 'Forging', 'Germinating', 'Mosmosing', 'Cerebrating',
|
|
14
|
+
'Boogieing', 'Finagling', 'Misting', 'Recombobulating', 'Slithering',
|
|
15
|
+
'Effecting', 'Roosting', 'Crystallizing', 'Canoodling', 'Billowing',
|
|
16
|
+
'Warping', 'Improvising', 'Metamorphing', 'Gusting', 'Whiring',
|
|
17
|
+
'Topsy-turvying', 'Flibbertigibetting', 'Wibbling', 'Thundering',
|
|
18
|
+
'Moseying', 'Julienning', 'Evaporating', 'Ruminating', 'Whisking',
|
|
19
|
+
'Scampering', 'Meandering', 'Concoting', 'Gesticulating', 'Flamebeing',
|
|
20
|
+
'Quantumizing', 'Waddling', 'Fluttering', 'Sprouting', 'Elucidating',
|
|
21
|
+
'Embellishing', 'Razzmatizing', 'Pondering', 'Cogitating', 'Garnishing',
|
|
22
|
+
'Actualizing', 'Zigzagging', 'Mustering', 'Frolicking', 'Hullaballooing',
|
|
23
|
+
'Doing', 'Fermenting', 'Considering', 'Skedaddling', 'Actioning',
|
|
24
|
+
'Orbiting', 'Perambulating', 'Drizzling', 'Schlepping', 'Ionizing',
|
|
25
|
+
'Scurrying',
|
|
33
26
|
]
|
|
34
27
|
|
|
35
|
-
const
|
|
28
|
+
const STATUS_CN = [
|
|
29
|
+
'思忖中', '推演中', '凝炼中', '熬煮中', '锻造中',
|
|
30
|
+
'研磨中', '解构中', '冥思中', '编织中', '萃取中',
|
|
31
|
+
'烹制中', '淬火中', '雕琢中', '融汇中', '觉照中',
|
|
32
|
+
'运转中', '参详中', '化合中', '浸润中', '焙烤中',
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
// Merge both — bilingual status verbs
|
|
36
|
+
const STATUS_GERUNDS = [...STATUS_EN, ...STATUS_CN]
|
|
37
|
+
|
|
38
|
+
const STATUS_PAST = [
|
|
39
|
+
'Brewed', 'Churned', 'Cooked', 'Sautéed', 'Cogitated', 'Crunched',
|
|
40
|
+
]
|
|
36
41
|
|
|
37
42
|
function pick<T>(arr: T[]): T {
|
|
38
43
|
return arr[Math.floor(Math.random() * arr.length)]!
|
|
@@ -40,25 +45,35 @@ function pick<T>(arr: T[]): T {
|
|
|
40
45
|
|
|
41
46
|
export function InputBar({ onSubmit, isLoading }: InputBarProps) {
|
|
42
47
|
const [value, setValue] = useState('')
|
|
43
|
-
const [verb, setVerb] = useState(() => pick(
|
|
44
|
-
const [
|
|
48
|
+
const [verb, setVerb] = useState(() => pick(STATUS_GERUNDS))
|
|
49
|
+
const [completionVerb, setCompletionVerb] = useState<string | null>(null)
|
|
50
|
+
const prevLoading = useRef(isLoading)
|
|
45
51
|
|
|
46
|
-
// Rotate
|
|
52
|
+
// Rotate gerunds while loading
|
|
47
53
|
useEffect(() => {
|
|
48
54
|
if (!isLoading) return
|
|
49
55
|
const interval = setInterval(() => {
|
|
50
|
-
setVerb(pick(
|
|
51
|
-
|
|
52
|
-
}, 2000)
|
|
56
|
+
setVerb(pick(STATUS_GERUNDS))
|
|
57
|
+
}, 1200)
|
|
53
58
|
return () => clearInterval(interval)
|
|
54
59
|
}, [isLoading])
|
|
55
60
|
|
|
56
|
-
//
|
|
61
|
+
// Pick a fresh gerund when loading starts
|
|
57
62
|
useEffect(() => {
|
|
58
63
|
if (isLoading) {
|
|
59
|
-
setVerb(pick(
|
|
60
|
-
|
|
64
|
+
setVerb(pick(STATUS_GERUNDS))
|
|
65
|
+
setCompletionVerb(null)
|
|
66
|
+
}
|
|
67
|
+
}, [isLoading])
|
|
68
|
+
|
|
69
|
+
// Flash a past participle when loading stops
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
if (prevLoading.current === true && isLoading === false) {
|
|
72
|
+
setCompletionVerb(pick(STATUS_PAST))
|
|
73
|
+
const timer = setTimeout(() => setCompletionVerb(null), 1500)
|
|
74
|
+
return () => clearTimeout(timer)
|
|
61
75
|
}
|
|
76
|
+
prevLoading.current = isLoading
|
|
62
77
|
}, [isLoading])
|
|
63
78
|
|
|
64
79
|
const handleSubmit = (val: string) => {
|
|
@@ -70,13 +85,19 @@ export function InputBar({ onSubmit, isLoading }: InputBarProps) {
|
|
|
70
85
|
return (
|
|
71
86
|
<Box marginTop={1}>
|
|
72
87
|
<Box marginRight={1}>
|
|
73
|
-
<Text color={isLoading ? 'yellow' : 'cyan'}>{
|
|
88
|
+
<Text color={isLoading ? 'yellow' : 'cyan'}>{'>'}</Text>
|
|
74
89
|
</Box>
|
|
75
90
|
<TextInput
|
|
76
91
|
value={value}
|
|
77
92
|
onChange={setValue}
|
|
78
93
|
onSubmit={handleSubmit}
|
|
79
|
-
placeholder={
|
|
94
|
+
placeholder={
|
|
95
|
+
isLoading
|
|
96
|
+
? `${verb}...`
|
|
97
|
+
: completionVerb
|
|
98
|
+
? completionVerb
|
|
99
|
+
: 'Type a message (Esc to cancel)...'
|
|
100
|
+
}
|
|
80
101
|
/>
|
|
81
102
|
</Box>
|
|
82
103
|
)
|