@ryan_nookpi/pi-extension-todo-write-overlay 0.1.1 → 0.2.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 +12 -0
- package/index.ts +60 -5
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -20,6 +20,7 @@ pi install npm:@ryan_nookpi/pi-extension-todo-write-overlay
|
|
|
20
20
|
- 세션 단위 todo 상태 저장 및 복원
|
|
21
21
|
- 우측 상단 오버레이 렌더링
|
|
22
22
|
- 입력 포커스를 뺏지 않는 `nonCapturing` overlay 사용
|
|
23
|
+
- `/todo-overlay show` / `/todo-overlay hide` 명령으로 오버레이 표시 토글
|
|
23
24
|
- 진행 중 작업 스피너 표시
|
|
24
25
|
- 완료/진행/대기 상태별 색상과 아이콘 표시
|
|
25
26
|
- `notes`는 상태에는 보존하지만 오버레이에는 표시하지 않음
|
|
@@ -37,6 +38,17 @@ pi install npm:@ryan_nookpi/pi-extension-todo-write-overlay
|
|
|
37
38
|
|
|
38
39
|
기존 `todo-write`의 `완료 +2` 같은 완료 항목 접기 로직은 사용하지 않습니다. 완료된 항목도 모두 그대로 표시합니다.
|
|
39
40
|
|
|
41
|
+
## 명령어
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
/todo-overlay show
|
|
45
|
+
/todo-overlay hide
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- 기본값은 `show`입니다.
|
|
49
|
+
- `hide`는 todo 상태와 reminder 주입은 유지하고, 우측 상단 오버레이 UI만 숨깁니다.
|
|
50
|
+
- 인자 없이 `/todo-overlay`를 실행하면 현재 표시 상태를 알려줍니다.
|
|
51
|
+
|
|
40
52
|
## 사용 예
|
|
41
53
|
|
|
42
54
|
```json
|
package/index.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
3
|
-
import
|
|
4
|
-
import { Text, truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
|
|
1
|
+
import type { ExtensionAPI, ExtensionContext, Theme } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { OverlayHandle, TUI } from "@earendil-works/pi-tui";
|
|
3
|
+
import { Text, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
5
4
|
import { type Static, Type } from "@sinclair/typebox";
|
|
6
5
|
|
|
7
6
|
type TodoStatus = "pending" | "in_progress" | "completed";
|
|
@@ -25,7 +24,7 @@ type TodoOverlayRecord = {
|
|
|
25
24
|
close?: () => void;
|
|
26
25
|
};
|
|
27
26
|
|
|
28
|
-
const StatusEnum =
|
|
27
|
+
const StatusEnum = Type.Union([Type.Literal("pending"), Type.Literal("in_progress"), Type.Literal("completed")], {
|
|
29
28
|
description: "작업 상태",
|
|
30
29
|
});
|
|
31
30
|
|
|
@@ -53,6 +52,7 @@ const todoStateStore = new Map<string, TodoState>();
|
|
|
53
52
|
const todoOverlayStore = new Map<string, TodoOverlayRecord>();
|
|
54
53
|
const todoOverlayMetaStore = new Map<string, { completedAt?: number; completedTurn?: number }>();
|
|
55
54
|
const todoOverlayAgentRunningStore = new Map<string, boolean>();
|
|
55
|
+
const todoOverlayHiddenStore = new Map<string, boolean>();
|
|
56
56
|
const todoTurnStore = new Map<string, number>();
|
|
57
57
|
const TODO_SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"] as const;
|
|
58
58
|
const TODO_SPINNER_INTERVAL_MS = 120;
|
|
@@ -327,6 +327,23 @@ function setTodoOverlayAgentRunning(ctx: Pick<ExtensionContext, "cwd" | "session
|
|
|
327
327
|
todoOverlayAgentRunningStore.set(key, running);
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
+
export type TodoOverlayCommandAction = "show" | "hide" | "status" | "invalid";
|
|
331
|
+
|
|
332
|
+
export function parseTodoOverlayCommand(args: string): TodoOverlayCommandAction {
|
|
333
|
+
const action = args.trim().toLowerCase();
|
|
334
|
+
if (action === "") return "status";
|
|
335
|
+
if (action === "show" || action === "hide") return action;
|
|
336
|
+
return "invalid";
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function isTodoOverlayHidden(key: string): boolean {
|
|
340
|
+
return todoOverlayHiddenStore.get(key) ?? false;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function setTodoOverlayHidden(key: string, hidden: boolean): void {
|
|
344
|
+
todoOverlayHiddenStore.set(key, hidden);
|
|
345
|
+
}
|
|
346
|
+
|
|
330
347
|
function hideTodoOverlay(key: string): void {
|
|
331
348
|
const record = todoOverlayStore.get(key);
|
|
332
349
|
if (!record) return;
|
|
@@ -510,10 +527,47 @@ async function syncTodoOverlay(ctx: ExtensionContext, pi: Pick<ExtensionAPI, "ap
|
|
|
510
527
|
return;
|
|
511
528
|
}
|
|
512
529
|
|
|
530
|
+
if (isTodoOverlayHidden(key)) {
|
|
531
|
+
hideTodoOverlay(key);
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
|
|
513
535
|
showOrUpdateTodoOverlay(ctx, key, state);
|
|
514
536
|
}
|
|
515
537
|
|
|
516
538
|
export default function todoWriteOverlayExtension(pi: ExtensionAPI): void {
|
|
539
|
+
pi.registerCommand("todo-overlay", {
|
|
540
|
+
description: "Show or hide the todo overlay. Usage: /todo-overlay show|hide",
|
|
541
|
+
getArgumentCompletions(prefix: string) {
|
|
542
|
+
const filtered = ["show", "hide"].filter((value) => value.startsWith(prefix.trim().toLowerCase()));
|
|
543
|
+
return filtered.length > 0 ? filtered.map((value) => ({ value, label: value })) : null;
|
|
544
|
+
},
|
|
545
|
+
async handler(args, ctx) {
|
|
546
|
+
const key = getTodoStateKey(ctx);
|
|
547
|
+
const action = parseTodoOverlayCommand(args);
|
|
548
|
+
|
|
549
|
+
if (action === "invalid") {
|
|
550
|
+
ctx.ui.notify("사용법: /todo-overlay show 또는 /todo-overlay hide", "warning");
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
if (action === "status") {
|
|
555
|
+
ctx.ui.notify(`todo overlay: ${isTodoOverlayHidden(key) ? "hidden" : "shown"}`, "info");
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
setTodoOverlayHidden(key, action === "hide");
|
|
560
|
+
if (action === "hide") {
|
|
561
|
+
hideTodoOverlay(key);
|
|
562
|
+
ctx.ui.notify("todo overlay를 숨겼습니다. /todo-overlay show로 다시 표시할 수 있습니다.", "info");
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
await syncTodoOverlay(ctx, pi);
|
|
567
|
+
ctx.ui.notify("todo overlay를 표시합니다.", "info");
|
|
568
|
+
},
|
|
569
|
+
});
|
|
570
|
+
|
|
517
571
|
pi.registerTool({
|
|
518
572
|
name: "todo_write",
|
|
519
573
|
label: "할 일 관리",
|
|
@@ -642,6 +696,7 @@ export default function todoWriteOverlayExtension(pi: ExtensionAPI): void {
|
|
|
642
696
|
hideTodoOverlay(key);
|
|
643
697
|
todoOverlayMetaStore.delete(key);
|
|
644
698
|
todoOverlayAgentRunningStore.delete(key);
|
|
699
|
+
todoOverlayHiddenStore.delete(key);
|
|
645
700
|
todoTurnStore.delete(key);
|
|
646
701
|
});
|
|
647
702
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ryan_nookpi/pi-extension-todo-write-overlay",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Top-right overlay todo_write tool extension for pi.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
]
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
33
|
-
"@
|
|
31
|
+
"@earendil-works/pi-ai": "*",
|
|
32
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
33
|
+
"@earendil-works/pi-tui": "*",
|
|
34
34
|
"@sinclair/typebox": "*"
|
|
35
35
|
},
|
|
36
36
|
"publishConfig": {
|