Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
736ec41d92 | ||
|
|
38686f01c6 | ||
|
|
3db55c6c5a |
@@ -6,9 +6,9 @@
|
|||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
"name": "hud",
|
"name": "cockpit",
|
||||||
"source": "./plugins/hud",
|
"source": "./plugins/cockpit",
|
||||||
"description": "輸入框上方單行 HUD:模型、目錄、分支、5h/7d 額度與重置、context、CPU/記憶體/磁碟"
|
"description": "Cockpit 外掛,內含 hud 模組(輸入框上方單行 HUD):模型、目錄、分支、5h/7d 額度與重置、context、CPU/記憶體/磁碟"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ JSC 自用 Claude Code mods。
|
|||||||
|
|
||||||
| Mod | 說明 |
|
| Mod | 說明 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| [hud](plugins/hud) | 輸入框上方單行 HUD:模型、目錄、分支、5h/7d 額度與重置、context、CPU/記憶體/磁碟 |
|
| [cockpit](plugins/cockpit) | Cockpit 外掛,內含 hud 模組(輸入框上方單行 HUD):模型、目錄、分支、5h/7d 額度與重置、context、CPU/記憶體/磁碟 |
|
||||||
|
|
||||||
## 安裝
|
## 安裝
|
||||||
|
|
||||||
@@ -12,16 +12,21 @@ JSC 自用 Claude Code mods。
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
claude plugin marketplace add /root/jsc-marketplace
|
claude plugin marketplace add /root/jsc-marketplace
|
||||||
claude plugin install hud@jsc-marketplace
|
claude plugin install cockpit@jsc-marketplace
|
||||||
```
|
```
|
||||||
|
|
||||||
或透過 Gitea 遠端:
|
或透過 Gitea 遠端:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
claude plugin marketplace add https://gitea.jsc.idv.tw/jiantw83/jsc-marketplace.git
|
claude plugin marketplace add https://gitea.jsc.idv.tw/jiantw83/jsc-marketplace.git
|
||||||
claude plugin install hud@jsc-marketplace
|
claude plugin install cockpit@jsc-marketplace
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 指令
|
||||||
|
|
||||||
|
- `/cockpit hud on | off | compact`:切換狀態列
|
||||||
|
- `/hud on | off | compact`:上述指令的別名
|
||||||
|
|
||||||
## 授權
|
## 授權
|
||||||
|
|
||||||
[MIT License](LICENSE)
|
[MIT License](LICENSE)
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "cockpit",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Cockpit 外掛,內含 hud 模組(輸入框上方單行 HUD):模型、目錄、分支、5h/7d 額度與重置、context、CPU/記憶體/磁碟",
|
||||||
|
"license": "MIT",
|
||||||
|
"types": "./types/index.d.ts",
|
||||||
|
"author": {
|
||||||
|
"name": "JSC"
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
import { describe, expect, test } from 'claude-code/testing'
|
import { describe, expect, test } from 'claude-code/testing'
|
||||||
|
|
||||||
import { bandLines, fit, lineWidth } from '../format'
|
import { bandLines, fit, lineWidth } from '../hud/format'
|
||||||
import type { HudData } from '../format'
|
import type { HudData } from '../hud/format'
|
||||||
import { fitCompanion } from './band'
|
import { fitCompanion } from './band'
|
||||||
import type { View } from './core'
|
import type { View } from './core'
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { bar, lineWidth } from '../format'
|
import { bar, lineWidth } from '../hud/format'
|
||||||
import type { Seg } from '../format'
|
import type { Seg } from '../hud/format'
|
||||||
import type { View } from './core'
|
import type { View } from './core'
|
||||||
|
|
||||||
const axis = (v: number) => bar(((v + 1) / 2) * 100, 3)
|
const axis = (v: number) => bar(((v + 1) / 2) * 100, 3)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import type { Register } from 'claude-code'
|
||||||
|
|
||||||
|
// companion 模組:目前為空殼,之後的階段再補內容
|
||||||
|
export const register: Register = () => {}
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
import { atom, read, update } from 'claude-code'
|
import { atom, read, update } from 'claude-code'
|
||||||
import type { EngineInterface, Register, SessionContextUsage, SessionRateLimit } from 'claude-code'
|
import type { EngineInterface, Register, SessionContextUsage, SessionRateLimit } from 'claude-code'
|
||||||
|
|
||||||
import type { Mode, Sys, Usage } from '../types'
|
import type { Mode, Sys, Usage } from '../../types'
|
||||||
import { fitCompanion } from './companion/band'
|
import { fitCompanion } from '../companion/band'
|
||||||
import { createCompanion } from './companion/core'
|
import { createCompanion } from '../companion/core'
|
||||||
import { nodeFs } from './companion/node-fs'
|
import { nodeFs } from '../companion/node-fs'
|
||||||
import { bandLines, cpuPercent, parseCpu, parseDf, parseGit, parseMem, parseOffset } from './format'
|
import { bandLines, cpuPercent, parseCpu, parseDf, parseGit, parseMem, parseOffset } from './format'
|
||||||
import type { CpuSample } from './format'
|
import type { CpuSample } from './format'
|
||||||
|
|
||||||
const usageAtom = atom({ plugin: 'hud', key: 'usage' } as const, {})
|
const usageAtom = atom({ plugin: 'cockpit', key: 'usage' } as const, {})
|
||||||
const gitAtom = atom({ plugin: 'hud', key: 'git' } as const, null)
|
const gitAtom = atom({ plugin: 'cockpit', key: 'git' } as const, null)
|
||||||
const sysAtom = atom({ plugin: 'hud', key: 'sys' } as const, {})
|
const sysAtom = atom({ plugin: 'cockpit', key: 'sys' } as const, {})
|
||||||
const modeAtom = atom({ plugin: 'hud', key: 'mode' } as const, 'auto')
|
const modeAtom = atom({ plugin: 'cockpit', key: 'mode' } as const, 'auto')
|
||||||
const alertedAtom = atom({ plugin: 'hud', key: 'alerted' } as const, [])
|
const alertedAtom = atom({ plugin: 'cockpit', key: 'alerted' } as const, [])
|
||||||
const effortAtom = atom({ plugin: 'hud', key: 'effort' } as const, null)
|
const effortAtom = atom({ plugin: 'cockpit', key: 'effort' } as const, null)
|
||||||
|
|
||||||
const SYS_MS = 3000
|
const SYS_MS = 3000
|
||||||
const GIT_MS = 15_000
|
const GIT_MS = 15_000
|
||||||
@@ -86,20 +86,30 @@ async function alert($: EngineInterface, rateLimits: SessionRateLimit[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function runHud($: EngineInterface, args: string) {
|
||||||
|
const arg = args.trim()
|
||||||
|
const mode: Mode = arg === 'off' ? 'off' : arg === 'compact' ? 'compact' : 'auto'
|
||||||
|
await update($, modeAtom, () => mode)
|
||||||
|
const said: Record<Mode, string> = { auto: '狀態列已開啟。', off: '狀態列已隱藏。', compact: '狀態列改用極窄版。' }
|
||||||
|
|
||||||
|
return { text: said[mode] }
|
||||||
|
}
|
||||||
|
|
||||||
export const register: Register = on => {
|
export const register: Register = on => {
|
||||||
on('session.start', async ($, e, next) => {
|
on('session.start', async ($, e, next) => {
|
||||||
|
await $.command.register({
|
||||||
|
name: 'cockpit',
|
||||||
|
description: 'Cockpit 控制:助理(status、switch、companion off、setup)與 hud 狀態列',
|
||||||
|
argumentHint: 'status | switch <角色> | companion off | setup | hud on | off | compact',
|
||||||
|
})
|
||||||
|
// 別名:/hud <arg> 等同 /cockpit hud <arg>
|
||||||
await $.command.register({
|
await $.command.register({
|
||||||
name: 'hud',
|
name: 'hud',
|
||||||
description: '切換輸入框上方的狀態列',
|
description: '切換輸入框上方的狀態列(/cockpit hud 的別名)',
|
||||||
argumentHint: 'on | off | compact',
|
argumentHint: 'on | off | compact',
|
||||||
})
|
})
|
||||||
home = await $.env.get('HOME')
|
home = await $.env.get('HOME')
|
||||||
companion = createCompanion({ fs: nodeFs, clock: { now: Date.now }, root: `${home ?? ''}/.cockpit` })
|
companion = createCompanion({ fs: nodeFs, clock: { now: Date.now }, root: `${home ?? ''}/.cockpit` })
|
||||||
await $.command.register({
|
|
||||||
name: 'cockpit',
|
|
||||||
description: '助理與儀表:status、switch、companion off、setup',
|
|
||||||
argumentHint: 'status | switch <角色> | companion off | setup',
|
|
||||||
})
|
|
||||||
const first = await companion.ensureActivated()
|
const first = await companion.ensureActivated()
|
||||||
if (first.first) $.ui.toast(`已啟用 ${first.name}。用 /cockpit companion off 可關閉`)
|
if (first.first) $.ui.toast(`已啟用 ${first.name}。用 /cockpit companion off 可關閉`)
|
||||||
try {
|
try {
|
||||||
@@ -140,17 +150,15 @@ export const register: Register = on => {
|
|||||||
return ran
|
return ran
|
||||||
})
|
})
|
||||||
|
|
||||||
on('command.run', { command: 'hud' }, async ($, e) => {
|
on('command.run', { command: 'hud' }, ($, e) => runHud($, e.args))
|
||||||
const arg = e.args.trim()
|
|
||||||
const mode: Mode = arg === 'off' ? 'off' : arg === 'compact' ? 'compact' : 'auto'
|
|
||||||
await update($, modeAtom, () => mode)
|
|
||||||
const said: Record<Mode, string> = { auto: '狀態列已開啟。', off: '狀態列已隱藏。', compact: '狀態列改用極窄版。' }
|
|
||||||
|
|
||||||
return { text: said[mode] }
|
on('command.run', { command: 'cockpit' }, async ($, e, next) => {
|
||||||
|
const [sub, ...rest] = e.args.trim().split(/\s+/)
|
||||||
|
if (sub === 'hud') return runHud($, rest.join(' '))
|
||||||
|
|
||||||
|
return { text: companion ? await companion.command(e.args) : '尚未就緒。' }
|
||||||
})
|
})
|
||||||
|
|
||||||
on('command.run', { command: 'cockpit' }, async (_$, e) => ({ text: companion ? await companion.command(e.args) : '尚未就緒。' }))
|
|
||||||
|
|
||||||
on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
|
on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
|
||||||
const mode = await read($, modeAtom)
|
const mode = await read($, modeAtom)
|
||||||
if (e.props.hasSurvey || mode === 'off') return next(e)
|
if (e.props.hasSurvey || mode === 'off') return next(e)
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import type { Register } from 'claude-code'
|
||||||
|
|
||||||
|
import { register as companion } from './companion'
|
||||||
|
import { register as hud } from './hud'
|
||||||
|
|
||||||
|
export const register: Register = on => {
|
||||||
|
hud(on)
|
||||||
|
companion(on)
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ export type Mode = 'auto' | 'compact' | 'off'
|
|||||||
|
|
||||||
declare module 'claude-code' {
|
declare module 'claude-code' {
|
||||||
interface PluginState {
|
interface PluginState {
|
||||||
hud: {
|
cockpit: {
|
||||||
usage: Usage
|
usage: Usage
|
||||||
git: Git | null
|
git: Git | null
|
||||||
sys: Sys
|
sys: Sys
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "hud",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"description": "輸入框上方單行 HUD:模型、目錄、分支、5h/7d 額度與重置、context、CPU/記憶體/磁碟",
|
|
||||||
"license": "MIT",
|
|
||||||
"types": "./types/index.d.ts",
|
|
||||||
"author": {
|
|
||||||
"name": "JSC"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user