@leviyuan/lodestar 0.2.4 → 0.2.5
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 +3 -3
- package/daemon.ts +0 -3
- package/package.json +1 -1
- package/src/cards.ts +1 -8
- package/src/session.ts +14 -14
package/README.md
CHANGED
|
@@ -50,9 +50,9 @@ AI 不是帮手,是倍率。它放大的不是体力,是你——你的直觉、
|
|
|
50
50
|
| --- | --- |
|
|
51
51
|
| `hi` | 未运行时启动;运行中弹一张**状态卡片** |
|
|
52
52
|
| `stop` | 软打断当前 turn + 清空 type-ahead 排队;子进程保活,刚排队中的消息会被打 `CrossMark` 反应表示取消 |
|
|
53
|
-
| `kill` | 优雅关闭 Claude
|
|
54
|
-
| `restart` | 用上一次的 `sessionId` 重启会话(保留上下文) |
|
|
55
|
-
| `clear` |
|
|
53
|
+
| `kill` | 优雅关闭 Claude 进程;`sessionId` 仍记在磁盘,下次 `restart` 还能 resume |
|
|
54
|
+
| `restart` | 用上一次的 `sessionId` 重启会话(保留上下文);无进程时也能用,等于"恢复上一会话" |
|
|
55
|
+
| `clear` | 杀掉当前进程并启动一个全新 session(等价于 Claude Code 的 `/clear`);**无进程时无效** |
|
|
56
56
|
|
|
57
57
|
> 这五个词被全局保留:在群里发 "hi" 当问候也会触发控制台卡片,不会到 Claude 那边。换来的是手机上单手打字的便利。
|
|
58
58
|
|
package/daemon.ts
CHANGED
|
@@ -192,9 +192,6 @@ async function handleCardAction(data: any): Promise<any> {
|
|
|
192
192
|
case 'permission':
|
|
193
193
|
await session.onPermissionDecision(value.request_id, value.decision, userId)
|
|
194
194
|
return { toast: { type: value.decision === 'deny' ? 'error' : 'success', content: '已处理' } }
|
|
195
|
-
case 'console':
|
|
196
|
-
await session.onConsoleAction(value.action)
|
|
197
|
-
return { toast: { type: 'info', content: value.action } }
|
|
198
195
|
case 'menu':
|
|
199
196
|
await session.onUserMessage(`(menu choice ${value.choice + 1})`)
|
|
200
197
|
return { toast: { type: 'success', content: 'OK' } }
|
package/package.json
CHANGED
package/src/cards.ts
CHANGED
|
@@ -550,7 +550,6 @@ interface ConsoleOpts {
|
|
|
550
550
|
cumStats?: { tokens: number; costUsd: number; turns: number }
|
|
551
551
|
lastTurn?: { tokens: number; costUsd: number; durationMs: number }
|
|
552
552
|
sessionId?: string | null
|
|
553
|
-
hasSession: boolean
|
|
554
553
|
}
|
|
555
554
|
|
|
556
555
|
/** Format token counts as a compact human-readable string: 1,234 → 1.2K. */
|
|
@@ -656,7 +655,7 @@ export function consoleUsageContent(
|
|
|
656
655
|
export function consoleCard(opts: ConsoleOpts): object {
|
|
657
656
|
const {
|
|
658
657
|
sessionName, status, model, effort, uptimeMs, peers, usage,
|
|
659
|
-
contextTokens, contextLimit, cumStats, lastTurn, sessionId,
|
|
658
|
+
contextTokens, contextLimit, cumStats, lastTurn, sessionId,
|
|
660
659
|
} = opts
|
|
661
660
|
const statusEmoji = {
|
|
662
661
|
idle: '🟢 闲', working: '⚙️ 工作中', awaiting_permission: '🔐 等审批',
|
|
@@ -698,12 +697,6 @@ export function consoleCard(opts: ConsoleOpts): object {
|
|
|
698
697
|
lines.push(`**🆔 session** \`${sessionId.slice(0, 8)}…\``)
|
|
699
698
|
}
|
|
700
699
|
|
|
701
|
-
void hasSession // accept the field for caller compat; lifecycle is now
|
|
702
|
-
// driven by bare-word commands (`hi` / `kill` / `restart` / `clear`),
|
|
703
|
-
// not buttons — keeps the panel pure-readout and one-handed mobile-
|
|
704
|
-
// friendly. The 'refresh' / 'ls' actions stay in onConsoleAction for
|
|
705
|
-
// backward compat with any still-floating older cards in chat history.
|
|
706
|
-
|
|
707
700
|
const template = status === 'working' ? 'blue'
|
|
708
701
|
: status === 'awaiting_permission' ? 'orange'
|
|
709
702
|
: status === 'stopped' ? 'grey'
|
package/src/session.ts
CHANGED
|
@@ -398,9 +398,23 @@ export class Session {
|
|
|
398
398
|
await this.stop()
|
|
399
399
|
return true
|
|
400
400
|
case 'restart':
|
|
401
|
+
// resume the prior conversation — kills the current proc (if
|
|
402
|
+
// any) and spawns a new one with `--resume <lastSessionId>`.
|
|
403
|
+
// If no process is running, this is how the user gets back the
|
|
404
|
+
// previous conversation after a `kill` or a daemon crash.
|
|
401
405
|
await this.restart(true)
|
|
402
406
|
return true
|
|
403
407
|
case 'clear':
|
|
408
|
+
// "throw away current conversation, start a new one". By design
|
|
409
|
+
// this only makes sense when there IS a current conversation:
|
|
410
|
+
// calling clear from stopped state is a no-op (user-confirmed
|
|
411
|
+
// 2026-05-16) — we don't want a stray `clear` to silently spawn
|
|
412
|
+
// a fresh session the user didn't ask for. To start from cold,
|
|
413
|
+
// use `hi`.
|
|
414
|
+
if (!this.isRunning()) {
|
|
415
|
+
await feishu.sendText(this.chatId, `⚪ session "${this.sessionName}" 当前未运行,clear 无效;用 \`hi\` 启动或 \`restart\` 恢复上一会话`)
|
|
416
|
+
return true
|
|
417
|
+
}
|
|
404
418
|
await this.restart(false)
|
|
405
419
|
return true
|
|
406
420
|
}
|
|
@@ -438,7 +452,6 @@ export class Session {
|
|
|
438
452
|
}
|
|
439
453
|
: undefined,
|
|
440
454
|
sessionId: this.proc?.sessionId ?? this.lastSessionId,
|
|
441
|
-
hasSession: this.isRunning(),
|
|
442
455
|
})
|
|
443
456
|
const messageId = await feishu.sendCard(this.chatId, card)
|
|
444
457
|
if (!messageId) return
|
|
@@ -777,19 +790,6 @@ export class Session {
|
|
|
777
790
|
}
|
|
778
791
|
}
|
|
779
792
|
|
|
780
|
-
async onConsoleAction(action: string): Promise<void> {
|
|
781
|
-
log(`session "${this.sessionName}": console action=${action}`)
|
|
782
|
-
switch (action) {
|
|
783
|
-
case 'interrupt': this.interrupt(); break
|
|
784
|
-
case 'clear': await this.restart(false); break
|
|
785
|
-
case 'stop': await this.stop(); break
|
|
786
|
-
case 'start': await this.start(); break
|
|
787
|
-
case 'resume': await this.restart(true); break
|
|
788
|
-
case 'refresh': await this.showConsole(); break
|
|
789
|
-
case 'ls': await feishu.sendText(this.chatId, `📁 ${this.workDir}`); break
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
|
|
793
793
|
// ── Wiring Claude → Feishu ─────────────────────────────────────────
|
|
794
794
|
private wireProc(p: ClaudeProcess): void {
|
|
795
795
|
p.on('init', () => {
|