From ea17f1cb2df951a96ec37f8e4e1e950795e04aaf Mon Sep 17 00:00:00 2001 From: root Date: Wed, 14 Oct 2026 05:45:52 +0000 Subject: [PATCH] =?UTF-8?q?refactor:=20jsc-mod=20=E6=94=B9=E5=90=8D=20jsc-?= =?UTF-8?q?mod-statusline=E3=80=81jsc-companion=20=E6=94=B9=E5=90=8D=20jsc?= =?UTF-8?q?-mod-companion,=E6=8C=87=E4=BB=A4=E6=8B=86=E6=88=90=E7=8D=A8?= =?UTF-8?q?=E7=AB=8B=E6=8C=87=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - jsc-mod-statusline:/jsc-mod-statusline:enable、compact、disable - jsc-mod-companion:/jsc-mod-companion:status、switch、disable、setup、todo、quiet - 同步更新 plugin.json、marketplace.json 與各 README - 補上 statusline band 測試缺少的 ui.render 底層處理 Co-Authored-By: Claude Sonnet 5.5 --- .claude-plugin/marketplace.json | 8 +- README.md | 16 ++-- plugins/jsc-companion/README.md | 83 ------------------- .../.claude-plugin/plugin.json | 2 +- plugins/jsc-mod-companion/README.md | 83 +++++++++++++++++++ .../hooks/companion/affinity.ts | 0 .../hooks/companion/assert.ts | 0 .../hooks/companion/band.test.ts | 0 .../hooks/companion/band.ts | 0 .../hooks/companion/care.test.ts | 2 +- .../hooks/companion/care.ts | 2 +- .../hooks/companion/companion.test.ts | 0 .../hooks/companion/core.ts | 12 +-- .../hooks/companion/core/apply.ts | 0 .../hooks/companion/core/core.test.ts | 0 .../hooks/companion/core/personality.ts | 0 .../hooks/companion/core/speech.ts | 0 .../hooks/companion/core/store.ts | 0 .../hooks/companion/core/types.ts | 0 .../hooks/companion/defaults.ts | 0 .../hooks/companion/engine-fs.ts | 0 .../hooks/companion/fs.ts | 0 .../hooks/companion/io.ts | 0 .../hooks/companion/memory.test.ts | 0 .../hooks/companion/memory.ts | 0 .../hooks/companion/mood.ts | 0 .../hooks/companion/prompt.ts | 0 .../hooks/companion/seg.ts | 2 +- .../hooks/companion/todo.ts | 0 .../hooks/companion/types.ts | 0 .../hooks/companion/verify.test.ts | 0 .../hooks/companion/verify.ts | 0 .../hooks/hooks.json | 0 .../hooks/register.tsx | 24 ++++-- .../skills/ingest/SKILL.md | 0 .../tsconfig.json | 0 .../.claude-plugin/plugin.json | 2 +- plugins/jsc-mod-statusline/README.md | 27 ++++++ .../hooks/format.ts | 0 .../hooks/hooks.json | 0 .../hooks/hud.test.tsx | 10 ++- .../hooks/register.tsx | 28 +++---- .../tsconfig.json | 0 .../types/index.d.ts | 2 +- plugins/jsc-mod/README.md | 27 ------ 45 files changed, 169 insertions(+), 161 deletions(-) delete mode 100644 plugins/jsc-companion/README.md rename plugins/{jsc-companion => jsc-mod-companion}/.claude-plugin/plugin.json (89%) create mode 100644 plugins/jsc-mod-companion/README.md rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/affinity.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/assert.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/band.test.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/band.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/care.test.ts (99%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/care.ts (99%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/companion.test.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/core.ts (95%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/core/apply.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/core/core.test.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/core/personality.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/core/speech.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/core/store.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/core/types.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/defaults.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/engine-fs.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/fs.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/io.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/memory.test.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/memory.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/mood.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/prompt.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/seg.ts (82%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/todo.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/types.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/verify.test.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/companion/verify.ts (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/hooks.json (100%) rename plugins/{jsc-companion => jsc-mod-companion}/hooks/register.tsx (77%) rename plugins/{jsc-companion => jsc-mod-companion}/skills/ingest/SKILL.md (100%) rename plugins/{jsc-companion => jsc-mod-companion}/tsconfig.json (100%) rename plugins/{jsc-mod => jsc-mod-statusline}/.claude-plugin/plugin.json (88%) create mode 100644 plugins/jsc-mod-statusline/README.md rename plugins/{jsc-mod => jsc-mod-statusline}/hooks/format.ts (100%) rename plugins/{jsc-mod => jsc-mod-statusline}/hooks/hooks.json (100%) rename plugins/{jsc-mod => jsc-mod-statusline}/hooks/hud.test.tsx (91%) rename plugins/{jsc-mod => jsc-mod-statusline}/hooks/register.tsx (85%) rename plugins/{jsc-mod => jsc-mod-statusline}/tsconfig.json (100%) rename plugins/{jsc-mod => jsc-mod-statusline}/types/index.d.ts (95%) delete mode 100644 plugins/jsc-mod/README.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index e397d13..a39ce2d 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -6,13 +6,13 @@ }, "plugins": [ { - "name": "jsc-mod", - "source": "./plugins/jsc-mod", + "name": "jsc-mod-statusline", + "source": "./plugins/jsc-mod-statusline", "description": "輸入框上方單行狀態列:模型、目錄、分支、5h/7d 額度與重置、context、CPU/記憶體/磁碟" }, { - "name": "jsc-companion", - "source": "./plugins/jsc-companion", + "name": "jsc-mod-companion", + "source": "./plugins/jsc-mod-companion", "description": "小說角色陪伴:人設注入、語氣、心情與好感、互動記憶、主動關心與待辦,並可用 ingest skill 解析小說建立角色" }, { diff --git a/README.md b/README.md index e90247b..fda2273 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,11 @@ JSC 自用 Claude Code mods 的 marketplace。每個插件皆可單獨安裝、 ## 插件 -### [jsc-mod](plugins/jsc-mod) `0.0.1` +### [jsc-mod-statusline](plugins/jsc-mod-statusline) `0.0.1` 輸入框上方單行狀態列:模型、目錄、分支、5h/7d 額度與重置、context、CPU/記憶體/磁碟。 -### [jsc-companion](plugins/jsc-companion) `0.0.3` +### [jsc-mod-companion](plugins/jsc-mod-companion) `0.0.3` 小說角色陪伴:人設注入、語氣、心情與好感、互動記憶、主動關心與待辦,並可用 ingest skill 解析小說建立角色。 @@ -38,8 +38,8 @@ Matt Pocock 的工程技能整套(grilling、spec/ticket、TDD、code review ```bash claude plugin marketplace add https://gitea.jsc.idv.tw/jiantw83/jsc-marketplace.git -claude plugin install jsc-mod@jsc-marketplace -claude plugin install jsc-companion@jsc-marketplace +claude plugin install jsc-mod-statusline@jsc-marketplace +claude plugin install jsc-mod-companion@jsc-marketplace claude plugin install jsc-herdr@jsc-marketplace claude plugin install jsc-claude@jsc-marketplace claude plugin install jsc-matt@jsc-marketplace @@ -50,8 +50,8 @@ claude plugin install jsc-wiki@jsc-marketplace ```bash claude plugin marketplace update jsc-marketplace -claude plugin update jsc-mod@jsc-marketplace -claude plugin update jsc-companion@jsc-marketplace +claude plugin update jsc-mod-statusline@jsc-marketplace +claude plugin update jsc-mod-companion@jsc-marketplace claude plugin update jsc-herdr@jsc-marketplace claude plugin update jsc-claude@jsc-marketplace claude plugin update jsc-matt@jsc-marketplace @@ -63,8 +63,8 @@ claude plugin update jsc-wiki@jsc-marketplace ## 移除 ```bash -claude plugin uninstall jsc-mod@jsc-marketplace -claude plugin uninstall jsc-companion@jsc-marketplace +claude plugin uninstall jsc-mod-statusline@jsc-marketplace +claude plugin uninstall jsc-mod-companion@jsc-marketplace claude plugin uninstall jsc-herdr@jsc-marketplace claude plugin uninstall jsc-claude@jsc-marketplace claude plugin uninstall jsc-matt@jsc-marketplace diff --git a/plugins/jsc-companion/README.md b/plugins/jsc-companion/README.md deleted file mode 100644 index f973eaa..0000000 --- a/plugins/jsc-companion/README.md +++ /dev/null @@ -1,83 +0,0 @@ -# jsc-companion - -## 指令 - -### `/jsc-companion:companion status` - -查看目前角色、心情、好感與待辦數量。 - -```text -/jsc-companion:companion status -``` - -### `/jsc-companion:companion switch <角色>` - -切換角色;不給角色會列出可用角色。 - -```text -/jsc-companion:companion switch 小明 -``` - -### `/jsc-companion:companion off` - -關閉陪伴,所有資料保留。 - -```text -/jsc-companion:companion off -``` - -### `/jsc-companion:companion setup [key=value…]` - -不給參數時顯示目前設定;給 key=value 則儲存。可設定:`nickname`、`wake=HH:MM`、`sleep=HH:MM`、`tz=+0800`、`careLimit=N`(每日主動關心上限)、`quietStart=HH:MM`、`quietEnd=HH:MM`。 - -```text -/jsc-companion:companion setup nickname=阿明 wake=07:30 sleep=23:30 tz=+0800 careLimit=3 quietStart=22:00 quietEnd=08:00 -``` - -### `/jsc-companion:companion todo [list]` - -列出未完成的待辦。 - -```text -/jsc-companion:companion todo -``` - -### `/jsc-companion:companion todo add <內容> [due=YYYY-MM-DDTHH:MM]` - -新增待辦,可指定到期時間(依 `tz` 設定換算)。 - -```text -/jsc-companion:companion todo add 買牛奶 due=2026-10-15T18:00 -``` - -### `/jsc-companion:companion todo promise <內容> [due=YYYY-MM-DDTHH:MM]` - -記錄角色答應使用者的事(列表中標示【承諾】),用法同 `todo add`。 - -```text -/jsc-companion:companion todo promise 週末一起討論新章節 due=2026-10-17T10:00 -``` - -### `/jsc-companion:companion todo done <編號>` - -將待辦標為完成。 - -```text -/jsc-companion:companion todo done 1 -``` - -### `/jsc-companion:companion quiet [分鐘]` - -暫時靜音,不主動關心;預設 60 分鐘,`0` 取消靜音。 - -```text -/jsc-companion:companion quiet 30 -``` - -### `/jsc-companion:ingest` - -解析單章小說(txt/md),逐一詢問合併、新建或略過後寫入角色資料;提供章節檔或要求建立角色時也會自動使用。 - -```text -/jsc-companion:ingest chapter1.md 章節編號 1 -``` diff --git a/plugins/jsc-companion/.claude-plugin/plugin.json b/plugins/jsc-mod-companion/.claude-plugin/plugin.json similarity index 89% rename from plugins/jsc-companion/.claude-plugin/plugin.json rename to plugins/jsc-mod-companion/.claude-plugin/plugin.json index 2c23e78..261b6f0 100644 --- a/plugins/jsc-companion/.claude-plugin/plugin.json +++ b/plugins/jsc-mod-companion/.claude-plugin/plugin.json @@ -1,5 +1,5 @@ { - "name": "jsc-companion", + "name": "jsc-mod-companion", "version": "0.0.3", "description": "小說角色陪伴:人設注入、語氣、心情與好感、互動記憶、主動關心與待辦,並可用 ingest skill 解析小說建立角色", "license": "MIT", diff --git a/plugins/jsc-mod-companion/README.md b/plugins/jsc-mod-companion/README.md new file mode 100644 index 0000000..7f488f4 --- /dev/null +++ b/plugins/jsc-mod-companion/README.md @@ -0,0 +1,83 @@ +# jsc-mod-companion + +## 指令 + +### `/jsc-mod-companion:status` + +查看目前角色、心情、好感與待辦數量。 + +```text +/jsc-mod-companion:status +``` + +### `/jsc-mod-companion:switch <角色>` + +切換角色;不給角色會列出可用角色。 + +```text +/jsc-mod-companion:switch 小明 +``` + +### `/jsc-mod-companion:disable` + +關閉陪伴,所有資料保留。 + +```text +/jsc-mod-companion:disable +``` + +### `/jsc-mod-companion:setup [key=value…]` + +不給參數時顯示目前設定;給 key=value 則儲存。可設定:`nickname`、`wake=HH:MM`、`sleep=HH:MM`、`tz=+0800`、`careLimit=N`(每日主動關心上限)、`quietStart=HH:MM`、`quietEnd=HH:MM`。 + +```text +/jsc-mod-companion:setup nickname=阿明 wake=07:30 sleep=23:30 tz=+0800 careLimit=3 quietStart=22:00 quietEnd=08:00 +``` + +### `/jsc-mod-companion:todo [list]` + +列出未完成的待辦。 + +```text +/jsc-mod-companion:todo +``` + +### `/jsc-mod-companion:todo add <內容> [due=YYYY-MM-DDTHH:MM]` + +新增待辦,可指定到期時間(依 `tz` 設定換算)。 + +```text +/jsc-mod-companion:todo add 買牛奶 due=2026-10-15T18:00 +``` + +### `/jsc-mod-companion:todo promise <內容> [due=YYYY-MM-DDTHH:MM]` + +記錄角色答應使用者的事(列表中標示【承諾】),用法同 `todo add`。 + +```text +/jsc-mod-companion:todo promise 週末一起討論新章節 due=2026-10-17T10:00 +``` + +### `/jsc-mod-companion:todo done <編號>` + +將待辦標為完成。 + +```text +/jsc-mod-companion:todo done 1 +``` + +### `/jsc-mod-companion:quiet [分鐘]` + +暫時靜音,不主動關心;預設 60 分鐘,`0` 取消靜音。 + +```text +/jsc-mod-companion:quiet 30 +``` + +### `/jsc-mod-companion:ingest` + +解析單章小說(txt/md),逐一詢問合併、新建或略過後寫入角色資料;提供章節檔或要求建立角色時也會自動使用。 + +```text +/jsc-mod-companion:ingest chapter1.md 章節編號 1 +``` diff --git a/plugins/jsc-companion/hooks/companion/affinity.ts b/plugins/jsc-mod-companion/hooks/companion/affinity.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/affinity.ts rename to plugins/jsc-mod-companion/hooks/companion/affinity.ts diff --git a/plugins/jsc-companion/hooks/companion/assert.ts b/plugins/jsc-mod-companion/hooks/companion/assert.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/assert.ts rename to plugins/jsc-mod-companion/hooks/companion/assert.ts diff --git a/plugins/jsc-companion/hooks/companion/band.test.ts b/plugins/jsc-mod-companion/hooks/companion/band.test.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/band.test.ts rename to plugins/jsc-mod-companion/hooks/companion/band.test.ts diff --git a/plugins/jsc-companion/hooks/companion/band.ts b/plugins/jsc-mod-companion/hooks/companion/band.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/band.ts rename to plugins/jsc-mod-companion/hooks/companion/band.ts diff --git a/plugins/jsc-companion/hooks/companion/care.test.ts b/plugins/jsc-mod-companion/hooks/companion/care.test.ts similarity index 99% rename from plugins/jsc-companion/hooks/companion/care.test.ts rename to plugins/jsc-mod-companion/hooks/companion/care.test.ts index 8656e05..1d26045 100644 --- a/plugins/jsc-companion/hooks/companion/care.test.ts +++ b/plugins/jsc-mod-companion/hooks/companion/care.test.ts @@ -140,7 +140,7 @@ describe('關心:靜音與不打斷', () => { assert.deepEqual((await s.care.tick()).map(c => c.trigger), ['session_start']) }) - test('/companion quiet 在期間內靜音,到期後恢復', async () => { + test('/jsc-mod-companion:quiet 在期間內靜音,到期後恢復', async () => { const s = setup() await s.care.quiet(30) await s.care.onUserTurn() diff --git a/plugins/jsc-companion/hooks/companion/care.ts b/plugins/jsc-mod-companion/hooks/companion/care.ts similarity index 99% rename from plugins/jsc-companion/hooks/companion/care.ts rename to plugins/jsc-mod-companion/hooks/companion/care.ts index 0d5ca94..b71d3ee 100644 --- a/plugins/jsc-companion/hooks/companion/care.ts +++ b/plugins/jsc-mod-companion/hooks/companion/care.ts @@ -393,7 +393,7 @@ export interface CareEngine { onTurnComplete(usedTools: boolean): Promise /** 定時/事件檢查:回傳要立即顯示的 toast 或氣泡 */ tick(signals?: Signals): Promise - /** /companion quiet [分鐘],0 取消靜音 */ + /** /jsc-mod-companion:quiet [分鐘],0 取消靜音 */ quiet(minutes: number): Promise state(): Promise } diff --git a/plugins/jsc-companion/hooks/companion/companion.test.ts b/plugins/jsc-mod-companion/hooks/companion/companion.test.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/companion.test.ts rename to plugins/jsc-mod-companion/hooks/companion/companion.test.ts diff --git a/plugins/jsc-companion/hooks/companion/core.ts b/plugins/jsc-mod-companion/hooks/companion/core.ts similarity index 95% rename from plugins/jsc-companion/hooks/companion/core.ts rename to plugins/jsc-mod-companion/hooks/companion/core.ts index c30a5c4..15369f8 100644 --- a/plugins/jsc-companion/hooks/companion/core.ts +++ b/plugins/jsc-mod-companion/hooks/companion/core.ts @@ -152,7 +152,7 @@ export function createCompanion({ fs, clock, root, builtins = [FUBUKI] }: Compan else if (k === 'quietEnd') u.quiet.end = val else (u as Record)[k] = val } - if (bad.length) return `無法解析:${bad.join(' ')}\n用法:/companion setup nickname=… wake=HH:MM sleep=HH:MM tz=+0800 careLimit=N quietStart=HH:MM quietEnd=HH:MM` + if (bad.length) return `無法解析:${bad.join(' ')}\n用法:/jsc-mod-companion:setup nickname=… wake=HH:MM sleep=HH:MM tz=+0800 careLimit=N quietStart=HH:MM quietEnd=HH:MM` if (args.length) await writeJson(fs, userPath, u) return [ args.length ? '設定已儲存:' : '目前設定(以 key=value 修改):', @@ -165,7 +165,7 @@ export function createCompanion({ fs, clock, root, builtins = [FUBUKI] }: Compan async function command(raw: string): Promise { const [sub = '', ...rest] = raw.trim().split(/\s+/).filter(Boolean) if (sub === 'status') return status() - if (sub === 'switch') return rest[0] ? switchTo(rest[0]) : `用法:/companion switch <角色>。可用:${(await available()).join('、')}` + if (sub === 'switch') return rest[0] ? switchTo(rest[0]) : `用法:/jsc-mod-companion:switch <角色>。可用:${(await available()).join('、')}` if (sub === 'off') { const g = await getGlobal() await writeJson(fs, globalPath, { ...g, active: null, activatedOnce: true }) @@ -174,7 +174,7 @@ export function createCompanion({ fs, clock, root, builtins = [FUBUKI] }: Compan if (sub === 'setup') return setup(rest) if (sub === 'todo') return todoCommand(rest) if (sub === 'quiet') return quietCommand(rest) - return '用法:/companion status | switch <角色> | off | setup [key=value…] | todo … | quiet [分鐘]' + return '用法:/jsc-mod-companion:status | :switch <角色> | :disable | :setup [key=value…] | :todo … | :quiet [分鐘]' } const CARE_STAGES: CareProfile['stage'][] = ['stranger', 'familiar', 'close', 'special'] @@ -300,21 +300,21 @@ export function createCompanion({ fs, clock, root, builtins = [FUBUKI] }: Compan return false }) const title = words.join(' ').trim() - if (!title) return '用法:/companion todo add <內容> [due=YYYY-MM-DDTHH:MM]' + if (!title) return '用法:/jsc-mod-companion:todo add <內容> [due=YYYY-MM-DDTHH:MM]' return `已加入:${fmtTodo(await b.todos.add(title, { promise: sub === 'promise', dueAt }))}` } if (sub === 'done') { const t = await b.todos.complete(Number(args[0])) return t ? `已完成:${fmtTodo(t)}` : `找不到待辦 #${args[0] ?? ''}` } - return '用法:/companion todo [list] | add <內容> [due=YYYY-MM-DDTHH:MM] | promise <內容> | done <編號>' + return '用法:/jsc-mod-companion:todo [list] | add <內容> [due=YYYY-MM-DDTHH:MM] | promise <內容> | done <編號>' } async function quietCommand(rest: string[]): Promise { const b = await bundleFor() if (!b) return '目前沒有啟用角色。' const n = rest[0] === undefined ? 60 : Number(rest[0]) - if (!Number.isFinite(n) || n < 0) return '用法:/companion quiet [分鐘](0 取消靜音)' + if (!Number.isFinite(n) || n < 0) return '用法:/jsc-mod-companion:quiet [分鐘](0 取消靜音)' await b.care.quiet(n) return n > 0 ? `已靜音 ${n} 分鐘。` : '已取消靜音。' } diff --git a/plugins/jsc-companion/hooks/companion/core/apply.ts b/plugins/jsc-mod-companion/hooks/companion/core/apply.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/core/apply.ts rename to plugins/jsc-mod-companion/hooks/companion/core/apply.ts diff --git a/plugins/jsc-companion/hooks/companion/core/core.test.ts b/plugins/jsc-mod-companion/hooks/companion/core/core.test.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/core/core.test.ts rename to plugins/jsc-mod-companion/hooks/companion/core/core.test.ts diff --git a/plugins/jsc-companion/hooks/companion/core/personality.ts b/plugins/jsc-mod-companion/hooks/companion/core/personality.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/core/personality.ts rename to plugins/jsc-mod-companion/hooks/companion/core/personality.ts diff --git a/plugins/jsc-companion/hooks/companion/core/speech.ts b/plugins/jsc-mod-companion/hooks/companion/core/speech.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/core/speech.ts rename to plugins/jsc-mod-companion/hooks/companion/core/speech.ts diff --git a/plugins/jsc-companion/hooks/companion/core/store.ts b/plugins/jsc-mod-companion/hooks/companion/core/store.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/core/store.ts rename to plugins/jsc-mod-companion/hooks/companion/core/store.ts diff --git a/plugins/jsc-companion/hooks/companion/core/types.ts b/plugins/jsc-mod-companion/hooks/companion/core/types.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/core/types.ts rename to plugins/jsc-mod-companion/hooks/companion/core/types.ts diff --git a/plugins/jsc-companion/hooks/companion/defaults.ts b/plugins/jsc-mod-companion/hooks/companion/defaults.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/defaults.ts rename to plugins/jsc-mod-companion/hooks/companion/defaults.ts diff --git a/plugins/jsc-companion/hooks/companion/engine-fs.ts b/plugins/jsc-mod-companion/hooks/companion/engine-fs.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/engine-fs.ts rename to plugins/jsc-mod-companion/hooks/companion/engine-fs.ts diff --git a/plugins/jsc-companion/hooks/companion/fs.ts b/plugins/jsc-mod-companion/hooks/companion/fs.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/fs.ts rename to plugins/jsc-mod-companion/hooks/companion/fs.ts diff --git a/plugins/jsc-companion/hooks/companion/io.ts b/plugins/jsc-mod-companion/hooks/companion/io.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/io.ts rename to plugins/jsc-mod-companion/hooks/companion/io.ts diff --git a/plugins/jsc-companion/hooks/companion/memory.test.ts b/plugins/jsc-mod-companion/hooks/companion/memory.test.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/memory.test.ts rename to plugins/jsc-mod-companion/hooks/companion/memory.test.ts diff --git a/plugins/jsc-companion/hooks/companion/memory.ts b/plugins/jsc-mod-companion/hooks/companion/memory.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/memory.ts rename to plugins/jsc-mod-companion/hooks/companion/memory.ts diff --git a/plugins/jsc-companion/hooks/companion/mood.ts b/plugins/jsc-mod-companion/hooks/companion/mood.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/mood.ts rename to plugins/jsc-mod-companion/hooks/companion/mood.ts diff --git a/plugins/jsc-companion/hooks/companion/prompt.ts b/plugins/jsc-mod-companion/hooks/companion/prompt.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/prompt.ts rename to plugins/jsc-mod-companion/hooks/companion/prompt.ts diff --git a/plugins/jsc-companion/hooks/companion/seg.ts b/plugins/jsc-mod-companion/hooks/companion/seg.ts similarity index 82% rename from plugins/jsc-companion/hooks/companion/seg.ts rename to plugins/jsc-mod-companion/hooks/companion/seg.ts index be6938d..f4cf1ee 100644 --- a/plugins/jsc-companion/hooks/companion/seg.ts +++ b/plugins/jsc-mod-companion/hooks/companion/seg.ts @@ -1,4 +1,4 @@ -// 角色行用的字串片段與寬度計算(與 jsc-mod 外掛各自獨立,不互相依賴) +// 角色行用的字串片段與寬度計算(與 jsc-mod-statusline 外掛各自獨立,不互相依賴) export type Seg = { text: string; color?: string; dim?: boolean; bold?: boolean } export function bar(p: number, cells = 5): string { diff --git a/plugins/jsc-companion/hooks/companion/todo.ts b/plugins/jsc-mod-companion/hooks/companion/todo.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/todo.ts rename to plugins/jsc-mod-companion/hooks/companion/todo.ts diff --git a/plugins/jsc-companion/hooks/companion/types.ts b/plugins/jsc-mod-companion/hooks/companion/types.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/types.ts rename to plugins/jsc-mod-companion/hooks/companion/types.ts diff --git a/plugins/jsc-companion/hooks/companion/verify.test.ts b/plugins/jsc-mod-companion/hooks/companion/verify.test.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/verify.test.ts rename to plugins/jsc-mod-companion/hooks/companion/verify.test.ts diff --git a/plugins/jsc-companion/hooks/companion/verify.ts b/plugins/jsc-mod-companion/hooks/companion/verify.ts similarity index 100% rename from plugins/jsc-companion/hooks/companion/verify.ts rename to plugins/jsc-mod-companion/hooks/companion/verify.ts diff --git a/plugins/jsc-companion/hooks/hooks.json b/plugins/jsc-mod-companion/hooks/hooks.json similarity index 100% rename from plugins/jsc-companion/hooks/hooks.json rename to plugins/jsc-mod-companion/hooks/hooks.json diff --git a/plugins/jsc-companion/hooks/register.tsx b/plugins/jsc-mod-companion/hooks/register.tsx similarity index 77% rename from plugins/jsc-companion/hooks/register.tsx rename to plugins/jsc-mod-companion/hooks/register.tsx index 05ada52..49903ab 100644 --- a/plugins/jsc-companion/hooks/register.tsx +++ b/plugins/jsc-mod-companion/hooks/register.tsx @@ -13,17 +13,22 @@ let timer: { cancel(): void } | undefined const TICK_MS = 60_000 const TYPING_MS = 5_000 +const COMMANDS: Record = { + status: { description: '查看目前角色、心情、好感與待辦數量' }, + switch: { description: '切換角色;不給角色會列出可用角色', argumentHint: '<角色>' }, + disable: { description: '關閉陪伴,所有資料保留' }, + setup: { description: '顯示或儲存使用者設定', argumentHint: '[key=value…]' }, + todo: { description: '待辦:列出、新增、記錄承諾、完成', argumentHint: '[list | add | promise | done] …' }, + quiet: { description: '暫時靜音,不主動關心', argumentHint: '[分鐘]' }, +} + export const register: Register = on => { on('session.start', async ($, e, next) => { - await $.command.register({ - name: 'companion', - description: '角色陪伴控制:狀態、切換角色、關閉、使用者設定', - argumentHint: 'status | switch <角色> | off | setup', - }) + for (const [name, c] of Object.entries(COMMANDS)) await $.command.register({ name, ...c }) const home = await $.env.get('HOME') companion = createCompanion({ fs: engineFs({ read: p => $.fs.read(p), write: (p, t) => $.fs.write(p, t), list: p => $.fs.list(p) }), clock: { now: Date.now }, root: `${home ?? ''}/.companion` }) const first = await companion.ensureActivated() - if (first.first) $.ui.toast(`已啟用 ${first.name}。用 /companion off 可關閉`) + if (first.first) $.ui.toast(`已啟用 ${first.name}。用 /jsc-mod-companion:disable 可關閉`) // 定時檢查 toast 類關心(到期待辦、作息);失敗不影響主流程 timer?.cancel() @@ -37,9 +42,10 @@ export const register: Register = on => { return next(e) }) - on('command.run', { command: 'companion' }, async ($, e) => ({ - text: companion ? await companion.command(e.args) : '尚未就緒。', - })) + for (const command of Object.keys(COMMANDS)) + on('command.run', { command }, async ($, e) => ({ + text: companion ? await companion.command(`${command === 'disable' ? 'off' : command} ${e.args}`.trim()) : '尚未就緒。', + })) // 角色卡附加在 system prompt 尾端(session 區段),語氣才會進到模型 on('prompt.compose', async ($, e, next) => { diff --git a/plugins/jsc-companion/skills/ingest/SKILL.md b/plugins/jsc-mod-companion/skills/ingest/SKILL.md similarity index 100% rename from plugins/jsc-companion/skills/ingest/SKILL.md rename to plugins/jsc-mod-companion/skills/ingest/SKILL.md diff --git a/plugins/jsc-companion/tsconfig.json b/plugins/jsc-mod-companion/tsconfig.json similarity index 100% rename from plugins/jsc-companion/tsconfig.json rename to plugins/jsc-mod-companion/tsconfig.json diff --git a/plugins/jsc-mod/.claude-plugin/plugin.json b/plugins/jsc-mod-statusline/.claude-plugin/plugin.json similarity index 88% rename from plugins/jsc-mod/.claude-plugin/plugin.json rename to plugins/jsc-mod-statusline/.claude-plugin/plugin.json index 2de79bc..b2308e5 100644 --- a/plugins/jsc-mod/.claude-plugin/plugin.json +++ b/plugins/jsc-mod-statusline/.claude-plugin/plugin.json @@ -1,5 +1,5 @@ { - "name": "jsc-mod", + "name": "jsc-mod-statusline", "version": "0.0.1", "description": "輸入框上方的單行狀態列:模型、目錄、分支、5h/7d 額度與重置、context、CPU/記憶體/磁碟", "license": "MIT", diff --git a/plugins/jsc-mod-statusline/README.md b/plugins/jsc-mod-statusline/README.md new file mode 100644 index 0000000..8ddb8b9 --- /dev/null +++ b/plugins/jsc-mod-statusline/README.md @@ -0,0 +1,27 @@ +# jsc-mod-statusline + +## 指令 + +### `/jsc-mod-statusline:enable` + +開啟狀態列。 + +```text +/jsc-mod-statusline:enable +``` + +### `/jsc-mod-statusline:compact` + +改用極窄版狀態列。 + +```text +/jsc-mod-statusline:compact +``` + +### `/jsc-mod-statusline:disable` + +隱藏狀態列。 + +```text +/jsc-mod-statusline:disable +``` diff --git a/plugins/jsc-mod/hooks/format.ts b/plugins/jsc-mod-statusline/hooks/format.ts similarity index 100% rename from plugins/jsc-mod/hooks/format.ts rename to plugins/jsc-mod-statusline/hooks/format.ts diff --git a/plugins/jsc-mod/hooks/hooks.json b/plugins/jsc-mod-statusline/hooks/hooks.json similarity index 100% rename from plugins/jsc-mod/hooks/hooks.json rename to plugins/jsc-mod-statusline/hooks/hooks.json diff --git a/plugins/jsc-mod/hooks/hud.test.tsx b/plugins/jsc-mod-statusline/hooks/hud.test.tsx similarity index 91% rename from plugins/jsc-mod/hooks/hud.test.tsx rename to plugins/jsc-mod-statusline/hooks/hud.test.tsx index 10452b8..dcc4a01 100644 --- a/plugins/jsc-mod/hooks/hud.test.tsx +++ b/plugins/jsc-mod-statusline/hooks/hud.test.tsx @@ -91,9 +91,13 @@ describe('format', () => { }) describe('band', () => { - test('draws one line above the prompt and hides with /statusline off', async ($, on) => { + test('draws one line above the prompt and hides with /jsc-mod-statusline:disable', async ($, on) => { on('session.model', () => ({ value: 'claude-opus-5-5' })) on('session.cwd', () => ({ value: '/home/dev/work/luopan' })) + on('ui.render', ($, e) => { + const { Box } = $.ui.resolve(e) + return + }) const props = { hasSurvey: false, isWorking: false, @@ -103,12 +107,12 @@ describe('band', () => { view: {}, } for (const surface of ['terminal', 'desktop'] as const) { - const ui = await $.ui.mount({ plugin: 'jsc-mod', surface, component: 'AbovePrompt', props }) + const ui = await $.ui.mount({ plugin: 'jsc-mod-statusline', surface, component: 'AbovePrompt', props }) expect(await ui.find({ type: 'Text', text: /◆ Opus 5\.5/ })).toBeDefined() expect(await ui.find({ type: 'Text', text: /5h —/ })).toBeDefined() await ui.unmount() } - const ran = await $.command.run({ command: 'statusline', args: 'off' } as Parameters[0]) + const ran = await $.command.run({ command: 'disable', args: '' } as Parameters[0]) expect(JSON.stringify(ran)).toContain('隱藏') }) }) diff --git a/plugins/jsc-mod/hooks/register.tsx b/plugins/jsc-mod-statusline/hooks/register.tsx similarity index 85% rename from plugins/jsc-mod/hooks/register.tsx rename to plugins/jsc-mod-statusline/hooks/register.tsx index 0eeb1f0..1944c9b 100644 --- a/plugins/jsc-mod/hooks/register.tsx +++ b/plugins/jsc-mod-statusline/hooks/register.tsx @@ -5,12 +5,12 @@ import type { Mode, Sys, Usage, Window } from '../types' import { fit, cpuPercent, parseCpu, parseDf, parseGit, parseMem, parseOffset } from './format' import type { CpuSample } from './format' -const usageAtom = atom({ plugin: 'jsc-mod', key: 'usage' } as const, {}) -const gitAtom = atom({ plugin: 'jsc-mod', key: 'git' } as const, null) -const sysAtom = atom({ plugin: 'jsc-mod', key: 'sys' } as const, {}) -const modeAtom = atom({ plugin: 'jsc-mod', key: 'mode' } as const, 'auto') -const alertedAtom = atom({ plugin: 'jsc-mod', key: 'alerted' } as const, []) -const effortAtom = atom({ plugin: 'jsc-mod', key: 'effort' } as const, null) +const usageAtom = atom({ plugin: 'jsc-mod-statusline', key: 'usage' } as const, {}) +const gitAtom = atom({ plugin: 'jsc-mod-statusline', key: 'git' } as const, null) +const sysAtom = atom({ plugin: 'jsc-mod-statusline', key: 'sys' } as const, {}) +const modeAtom = atom({ plugin: 'jsc-mod-statusline', key: 'mode' } as const, 'auto') +const alertedAtom = atom({ plugin: 'jsc-mod-statusline', key: 'alerted' } as const, []) +const effortAtom = atom({ plugin: 'jsc-mod-statusline', key: 'effort' } as const, null) const SYS_MS = 3000 const GIT_MS = 15_000 @@ -99,9 +99,9 @@ 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' +const MODES: Record = { 'enable': 'auto', 'compact': 'compact', 'disable': 'off' } + +async function runHud($: EngineInterface, mode: Mode) { await update($, modeAtom, () => mode) const said: Record = { auto: '狀態列已開啟。', off: '狀態列已隱藏。', compact: '狀態列改用極窄版。' } @@ -110,11 +110,9 @@ async function runHud($: EngineInterface, args: string) { export const register: Register = on => { on('session.start', async ($, e, next) => { - await $.command.register({ - name: 'statusline', - description: '切換輸入框上方的狀態列', - argumentHint: 'on | off | compact', - }) + await $.command.register({ name: 'enable', description: '開啟輸入框上方的狀態列' }) + await $.command.register({ name: 'compact', description: '輸入框上方的狀態列改用極窄版' }) + await $.command.register({ name: 'disable', description: '隱藏輸入框上方的狀態列' }) home = await $.env.get('HOME') try { const r = await $.process.run(['date', '+%z'], { timeoutMs: 3000 }) @@ -161,7 +159,7 @@ export const register: Register = on => { return ran }) - on('command.run', { command: 'statusline' }, ($, e) => runHud($, e.args)) + for (const [command, mode] of Object.entries(MODES)) on('command.run', { command }, $ => runHud($, mode)) on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => { const mode = await read($, modeAtom) diff --git a/plugins/jsc-mod/tsconfig.json b/plugins/jsc-mod-statusline/tsconfig.json similarity index 100% rename from plugins/jsc-mod/tsconfig.json rename to plugins/jsc-mod-statusline/tsconfig.json diff --git a/plugins/jsc-mod/types/index.d.ts b/plugins/jsc-mod-statusline/types/index.d.ts similarity index 95% rename from plugins/jsc-mod/types/index.d.ts rename to plugins/jsc-mod-statusline/types/index.d.ts index 9460c92..5a49568 100644 --- a/plugins/jsc-mod/types/index.d.ts +++ b/plugins/jsc-mod-statusline/types/index.d.ts @@ -16,7 +16,7 @@ export type Mode = 'auto' | 'compact' | 'off' declare module 'claude-code' { interface PluginState { - 'jsc-mod': { + 'jsc-mod-statusline': { usage: Usage git: Git | null sys: Sys diff --git a/plugins/jsc-mod/README.md b/plugins/jsc-mod/README.md deleted file mode 100644 index 596e63e..0000000 --- a/plugins/jsc-mod/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# jsc-mod - -## 指令 - -### `/jsc-mod:statusline on` - -開啟狀態列。 - -```text -/jsc-mod:statusline on -``` - -### `/jsc-mod:statusline off` - -隱藏狀態列。 - -```text -/jsc-mod:statusline off -``` - -### `/jsc-mod:statusline compact` - -改用極窄版狀態列。 - -```text -/jsc-mod:statusline compact -``` -- 2.53.0