@pellux/goodvibes-agent 1.4.1 → 1.4.2
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/CHANGELOG.md +10 -0
- package/README.md +0 -1
- package/dist/package/main.js +462 -2626
- package/docs/README.md +0 -1
- package/docs/tools-and-commands.md +0 -3
- package/package.json +1 -1
- package/release/release-notes.md +7 -15
- package/src/input/agent-workspace-categories.ts +3 -20
- package/src/input/commands.ts +0 -4
- package/src/input/handler.ts +4 -1
- package/src/main.ts +1 -40
- package/src/panels/builtin/agent.ts +0 -28
- package/src/renderer/agent-workspace.ts +11 -5
- package/src/renderer/help-overlay.ts +0 -2
- package/src/version.ts +1 -1
- package/docs/project-planning.md +0 -81
- package/src/input/commands/planning-runtime.ts +0 -215
- package/src/input/commands/work-plan-runtime.ts +0 -191
- package/src/panels/plan-dashboard-panel.ts +0 -274
- package/src/panels/project-planning-panel.ts +0 -721
- package/src/panels/work-plan-panel.ts +0 -175
- package/src/planning/project-planning-coordinator.ts +0 -543
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import type { Line } from '../types/grid.ts';
|
|
2
|
-
import { UIFactory } from '../renderer/ui-factory.ts';
|
|
3
|
-
import { ScrollableListPanel } from './scrollable-list-panel.ts';
|
|
4
|
-
import type { WorkPlanItem, WorkPlanItemStatus, WorkPlanStore } from '../work-plans/work-plan-store.ts';
|
|
5
|
-
|
|
6
|
-
const STATUS_LABEL: Record<WorkPlanItemStatus, string> = {
|
|
7
|
-
pending: '[ ]',
|
|
8
|
-
in_progress: '[>]',
|
|
9
|
-
blocked: '[!]',
|
|
10
|
-
done: '[x]',
|
|
11
|
-
failed: '[x]',
|
|
12
|
-
cancelled: '[-]',
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const STATUS_COLOR: Record<WorkPlanItemStatus, string> = {
|
|
16
|
-
pending: '#94a3b8',
|
|
17
|
-
in_progress: '#38bdf8',
|
|
18
|
-
blocked: '#f59e0b',
|
|
19
|
-
done: '#22c55e',
|
|
20
|
-
failed: '#ef4444',
|
|
21
|
-
cancelled: '#64748b',
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
function line(text: string, width: number, style: Parameters<typeof UIFactory.stringToLine>[2] = {}): Line {
|
|
25
|
-
return UIFactory.stringToLine(text.padEnd(width).slice(0, width), width, style);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function compactDate(value: number): string {
|
|
29
|
-
return new Date(value).toISOString().replace('T', ' ').slice(0, 16);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function statusName(status: WorkPlanItemStatus): string {
|
|
33
|
-
return status.replace(/_/g, ' ');
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export class WorkPlanPanel extends ScrollableListPanel<WorkPlanItem> {
|
|
37
|
-
private items: readonly WorkPlanItem[] = [];
|
|
38
|
-
private lastPlanUpdatedAt = 0;
|
|
39
|
-
|
|
40
|
-
constructor(private readonly store: WorkPlanStore) {
|
|
41
|
-
super('work-plan', 'Work Plan', 'L', 'agent');
|
|
42
|
-
this.showSelectionGutter = true;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
onActivate(): void {
|
|
46
|
-
super.onActivate();
|
|
47
|
-
this.refresh();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
render(width: number, height: number): Line[] {
|
|
51
|
-
this.refresh();
|
|
52
|
-
return this.renderList(width, height, {
|
|
53
|
-
title: 'Work Plan',
|
|
54
|
-
header: this.renderHeader(width),
|
|
55
|
-
footer: this.renderFooter(width),
|
|
56
|
-
emptyMessage: 'No work plan items yet',
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
handleInput(key: string): boolean {
|
|
61
|
-
if (this.lastError !== null) this.clearError();
|
|
62
|
-
const item = this.items[this.selectedIndex];
|
|
63
|
-
try {
|
|
64
|
-
switch (key) {
|
|
65
|
-
case ' ':
|
|
66
|
-
case 'return':
|
|
67
|
-
case 'enter':
|
|
68
|
-
if (!item) return false;
|
|
69
|
-
this.store.cycleItemStatus(item.id);
|
|
70
|
-
this.refresh();
|
|
71
|
-
return true;
|
|
72
|
-
case '1':
|
|
73
|
-
return this.setSelectedStatus('pending');
|
|
74
|
-
case '2':
|
|
75
|
-
return this.setSelectedStatus('in_progress');
|
|
76
|
-
case '3':
|
|
77
|
-
return this.setSelectedStatus('blocked');
|
|
78
|
-
case '4':
|
|
79
|
-
return this.setSelectedStatus('done');
|
|
80
|
-
case '5':
|
|
81
|
-
return this.setSelectedStatus('failed');
|
|
82
|
-
case '6':
|
|
83
|
-
return this.setSelectedStatus('cancelled');
|
|
84
|
-
case 'd':
|
|
85
|
-
case 'delete':
|
|
86
|
-
if (!item) return false;
|
|
87
|
-
this.store.removeItem(item.id);
|
|
88
|
-
this.refresh();
|
|
89
|
-
return true;
|
|
90
|
-
case 'c':
|
|
91
|
-
this.store.clearCompleted();
|
|
92
|
-
this.refresh();
|
|
93
|
-
return true;
|
|
94
|
-
case 'r':
|
|
95
|
-
this.refresh(true);
|
|
96
|
-
return true;
|
|
97
|
-
default:
|
|
98
|
-
return super.handleInput(key);
|
|
99
|
-
}
|
|
100
|
-
} catch (error) {
|
|
101
|
-
this.setError(error instanceof Error ? error.message : String(error));
|
|
102
|
-
return true;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
protected getItems(): readonly WorkPlanItem[] {
|
|
107
|
-
return this.items;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
protected getEmptyStateActions(): Array<{ command: string; summary: string }> {
|
|
111
|
-
return [
|
|
112
|
-
{ command: '/workplan add <title>', summary: 'add a persistent item' },
|
|
113
|
-
{ command: '/workplan list', summary: 'print the current plan' },
|
|
114
|
-
];
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
protected renderItem(item: WorkPlanItem, _index: number, selected: boolean, width: number): Line {
|
|
118
|
-
const status = STATUS_LABEL[item.status];
|
|
119
|
-
const owner = item.owner ? ` @${item.owner}` : '';
|
|
120
|
-
const source = item.source ? ` (${item.source})` : '';
|
|
121
|
-
const text = `${status} ${item.title}${owner}${source}`;
|
|
122
|
-
return line(text, width, {
|
|
123
|
-
fg: selected ? '#e2e8f0' : STATUS_COLOR[item.status],
|
|
124
|
-
bg: selected ? '#1e293b' : undefined,
|
|
125
|
-
bold: selected || item.status === 'in_progress',
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
private setSelectedStatus(status: WorkPlanItemStatus): boolean {
|
|
130
|
-
const item = this.items[this.selectedIndex];
|
|
131
|
-
if (!item) return false;
|
|
132
|
-
this.store.setItemStatus(item.id, status);
|
|
133
|
-
this.refresh();
|
|
134
|
-
return true;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
private refresh(force = false): void {
|
|
138
|
-
const plan = this.store.getActivePlan();
|
|
139
|
-
if (!force && plan.updatedAt === this.lastPlanUpdatedAt && this.items.length === plan.items.length) return;
|
|
140
|
-
this.items = plan.items;
|
|
141
|
-
this.lastPlanUpdatedAt = plan.updatedAt;
|
|
142
|
-
this.clampSelection();
|
|
143
|
-
this.needsRender = true;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
private renderHeader(width: number): Line[] {
|
|
147
|
-
const plan = this.store.getActivePlan();
|
|
148
|
-
const counts = new Map<WorkPlanItemStatus, number>();
|
|
149
|
-
for (const status of Object.keys(STATUS_LABEL) as WorkPlanItemStatus[]) counts.set(status, 0);
|
|
150
|
-
for (const item of plan.items) counts.set(item.status, (counts.get(item.status) ?? 0) + 1);
|
|
151
|
-
const active = this.items[this.selectedIndex];
|
|
152
|
-
const header = [
|
|
153
|
-
line(`Persistent Work Plan`, width, { fg: '#22d3ee', bold: true }),
|
|
154
|
-
line(`Project ${plan.projectRoot}`, width, { fg: '#cbd5e1' }),
|
|
155
|
-
line(
|
|
156
|
-
`Items ${plan.items.length} pending ${counts.get('pending') ?? 0} active ${counts.get('in_progress') ?? 0} blocked ${counts.get('blocked') ?? 0} done ${counts.get('done') ?? 0}`,
|
|
157
|
-
width,
|
|
158
|
-
{ fg: '#94a3b8' },
|
|
159
|
-
),
|
|
160
|
-
line(`Saved ${this.store.filePath}`, width, { fg: '#64748b' }),
|
|
161
|
-
];
|
|
162
|
-
if (active) {
|
|
163
|
-
header.push(line('', width));
|
|
164
|
-
header.push(line(`Selected ${active.id} ${statusName(active.status)} updated ${compactDate(active.updatedAt)}`, width, { fg: '#a5b4fc' }));
|
|
165
|
-
if (active.notes) header.push(line(`Notes ${active.notes}`, width, { fg: '#cbd5e1' }));
|
|
166
|
-
}
|
|
167
|
-
return header;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
private renderFooter(width: number): Line[] {
|
|
171
|
-
return [
|
|
172
|
-
line('Enter/Space cycle 1 pending 2 active 3 blocked 4 done 5 failed 6 cancelled d delete c clear done r refresh', width, { fg: '#94a3b8' }),
|
|
173
|
-
];
|
|
174
|
-
}
|
|
175
|
-
}
|