@agimon-ai/doompi-task 0.0.1-alpha.40 → 0.0.1-alpha.42
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 +1 -1
- package/package.json +10 -10
- package/web/TasksActivitySection.tsx +69 -31
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/doompi-task",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.42",
|
|
4
4
|
"description": "Persistent, dependency-aware task graphs and subagent delegation for Pi coding sessions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -165,15 +165,15 @@
|
|
|
165
165
|
"dependencies": {
|
|
166
166
|
"@deepseek-ai/cordis": "4.0.1",
|
|
167
167
|
"typebox": "1.3.16",
|
|
168
|
-
"@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.
|
|
169
|
-
"@agimon-ai/doompi-
|
|
170
|
-
"@agimon-ai/doompi-
|
|
171
|
-
"@agimon-ai/doompi-web-
|
|
172
|
-
"@agimon-ai/doompi-web-
|
|
168
|
+
"@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.42",
|
|
169
|
+
"@agimon-ai/doompi-telemetry": "0.0.1-alpha.42",
|
|
170
|
+
"@agimon-ai/doompi-ui": "0.0.1-alpha.42",
|
|
171
|
+
"@agimon-ai/doompi-web-contracts": "0.0.1-alpha.5",
|
|
172
|
+
"@agimon-ai/doompi-web-components": "0.0.1-alpha.3"
|
|
173
173
|
},
|
|
174
174
|
"devDependencies": {
|
|
175
|
-
"@earendil-works/pi-coding-agent": "0.84.
|
|
176
|
-
"@earendil-works/pi-tui": "0.84.
|
|
175
|
+
"@earendil-works/pi-coding-agent": "0.84.4",
|
|
176
|
+
"@earendil-works/pi-tui": "0.84.4",
|
|
177
177
|
"@tanstack/react-store": "0.11.1",
|
|
178
178
|
"@tanstack/store": "0.11.1",
|
|
179
179
|
"@types/node": "26.2.0",
|
|
@@ -185,8 +185,8 @@
|
|
|
185
185
|
"vitest": "4.1.11"
|
|
186
186
|
},
|
|
187
187
|
"peerDependencies": {
|
|
188
|
-
"@earendil-works/pi-coding-agent": "0.84.
|
|
189
|
-
"@earendil-works/pi-tui": "0.84.
|
|
188
|
+
"@earendil-works/pi-coding-agent": "0.84.4",
|
|
189
|
+
"@earendil-works/pi-tui": "0.84.4"
|
|
190
190
|
},
|
|
191
191
|
"peerDependenciesMeta": {
|
|
192
192
|
"@earendil-works/pi-coding-agent": {
|
|
@@ -3,12 +3,20 @@ import {
|
|
|
3
3
|
ChevronDownIcon,
|
|
4
4
|
ChevronRightIcon,
|
|
5
5
|
Dot,
|
|
6
|
+
DropdownMenu,
|
|
7
|
+
DropdownMenuContent,
|
|
8
|
+
DropdownMenuItem,
|
|
9
|
+
DropdownMenuTrigger,
|
|
10
|
+
EditIcon,
|
|
11
|
+
KebabIcon,
|
|
12
|
+
MessageIcon,
|
|
6
13
|
Textarea,
|
|
14
|
+
TrashIcon,
|
|
7
15
|
type DotTone,
|
|
8
16
|
} from '@agimon-ai/doompi-web-components';
|
|
9
17
|
import type { WebPluginSlotProps } from '@agimon-ai/doompi-web-contracts';
|
|
10
18
|
import { useStore } from '@tanstack/react-store';
|
|
11
|
-
import { useState } from 'react';
|
|
19
|
+
import { useRef, useState } from 'react';
|
|
12
20
|
import type { WebTask } from '../src/types/webTasks.ts';
|
|
13
21
|
import { requestTaskInstruction, requestTaskRemoval, tasks, type TaskInstructionKind } from './tasksStore.ts';
|
|
14
22
|
|
|
@@ -40,6 +48,8 @@ function TaskRow({
|
|
|
40
48
|
setEditor: (editor: EditorState | undefined) => void;
|
|
41
49
|
}) {
|
|
42
50
|
const editing = editor?.taskId === task.id;
|
|
51
|
+
const editorRequested = useRef(false);
|
|
52
|
+
const editorInput = useRef<HTMLTextAreaElement>(null);
|
|
43
53
|
const detail = task.status === 'in_progress' ? task.activeForm : task.description;
|
|
44
54
|
return (
|
|
45
55
|
<div
|
|
@@ -47,14 +57,69 @@ function TaskRow({
|
|
|
47
57
|
data-task-status={task.status}
|
|
48
58
|
className="flex flex-col gap-1 rounded-[5px] px-1 py-1"
|
|
49
59
|
>
|
|
50
|
-
<div className="
|
|
60
|
+
<div className="grid min-w-0 grid-cols-[auto_minmax(0,1fr)_auto_auto] items-center gap-x-1.5">
|
|
51
61
|
<Dot tone={STATUS_TONE[task.status]} pulse={task.status === 'in_progress'} />
|
|
52
62
|
<span
|
|
53
|
-
|
|
63
|
+
data-testid={`activity-task-title-${task.id}`}
|
|
64
|
+
className={`min-w-0 truncate text-[10px] font-bold ${task.status === 'failed' ? 'text-doom-red' : task.status === 'completed' ? 'text-doom-dim' : 'text-doom-hi'}`}
|
|
54
65
|
>
|
|
55
66
|
<span className="text-doom-faint">#{task.id}</span> {task.subject}
|
|
56
67
|
</span>
|
|
57
68
|
<span className="shrink-0 text-[8px] text-doom-faint">{task.status.replace('_', ' ')}</span>
|
|
69
|
+
{task.status !== 'completed' && task.status !== 'deleted' ? (
|
|
70
|
+
<DropdownMenu>
|
|
71
|
+
<DropdownMenuTrigger asChild>
|
|
72
|
+
<Button
|
|
73
|
+
variant="ghost"
|
|
74
|
+
size="icon"
|
|
75
|
+
data-testid={`activity-task-menu-${task.id}`}
|
|
76
|
+
aria-label={`task #${task.id} actions`}
|
|
77
|
+
title={`task #${task.id} actions`}
|
|
78
|
+
className="self-center shrink-0 text-doom-faint hover:bg-doom-deep hover:text-doom-hi data-[state=open]:bg-doom-deep data-[state=open]:text-doom-hi"
|
|
79
|
+
>
|
|
80
|
+
<KebabIcon className="h-3 w-3" />
|
|
81
|
+
</Button>
|
|
82
|
+
</DropdownMenuTrigger>
|
|
83
|
+
<DropdownMenuContent
|
|
84
|
+
data-testid={`activity-task-menu-list-${task.id}`}
|
|
85
|
+
onCloseAutoFocus={(event) => {
|
|
86
|
+
if (!editorRequested.current) return;
|
|
87
|
+
editorRequested.current = false;
|
|
88
|
+
event.preventDefault();
|
|
89
|
+
editorInput.current?.focus();
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
<DropdownMenuItem
|
|
93
|
+
data-testid={`activity-task-edit-${task.id}`}
|
|
94
|
+
onSelect={() => {
|
|
95
|
+
editorRequested.current = true;
|
|
96
|
+
setEditor({ taskId: task.id, kind: 'edit', value: '' });
|
|
97
|
+
}}
|
|
98
|
+
>
|
|
99
|
+
<EditIcon className="h-3 w-3" />
|
|
100
|
+
Edit
|
|
101
|
+
</DropdownMenuItem>
|
|
102
|
+
<DropdownMenuItem
|
|
103
|
+
data-testid={`activity-task-note-${task.id}`}
|
|
104
|
+
onSelect={() => {
|
|
105
|
+
editorRequested.current = true;
|
|
106
|
+
setEditor({ taskId: task.id, kind: 'note', value: '' });
|
|
107
|
+
}}
|
|
108
|
+
>
|
|
109
|
+
<MessageIcon className="h-3 w-3" />
|
|
110
|
+
Note
|
|
111
|
+
</DropdownMenuItem>
|
|
112
|
+
<DropdownMenuItem
|
|
113
|
+
variant="destructive"
|
|
114
|
+
data-testid={`activity-task-remove-${task.id}`}
|
|
115
|
+
onSelect={() => requestTaskRemoval(sendSessionFrame, sessionId, task.id)}
|
|
116
|
+
>
|
|
117
|
+
<TrashIcon className="h-3 w-3" />
|
|
118
|
+
Remove
|
|
119
|
+
</DropdownMenuItem>
|
|
120
|
+
</DropdownMenuContent>
|
|
121
|
+
</DropdownMenu>
|
|
122
|
+
) : null}
|
|
58
123
|
</div>
|
|
59
124
|
{detail || task.delegation?.agent || task.blockedBy.length > 0 ? (
|
|
60
125
|
<span className="truncate pl-3 text-[9px] text-doom-faint">
|
|
@@ -63,34 +128,6 @@ function TaskRow({
|
|
|
63
128
|
{task.blockedBy.length > 0 ? ` · blocked by ${task.blockedBy.map((id) => `#${id}`).join(', ')}` : ''}
|
|
64
129
|
</span>
|
|
65
130
|
) : null}
|
|
66
|
-
{task.status !== 'completed' && task.status !== 'deleted' ? (
|
|
67
|
-
<div className="flex items-center gap-2 pl-3">
|
|
68
|
-
<Button
|
|
69
|
-
variant="link"
|
|
70
|
-
size="xs"
|
|
71
|
-
className="h-auto px-0 text-[8px]"
|
|
72
|
-
onClick={() => setEditor({ taskId: task.id, kind: 'edit', value: '' })}
|
|
73
|
-
>
|
|
74
|
-
edit
|
|
75
|
-
</Button>
|
|
76
|
-
<Button
|
|
77
|
-
variant="link"
|
|
78
|
-
size="xs"
|
|
79
|
-
className="h-auto px-0 text-[8px]"
|
|
80
|
-
onClick={() => setEditor({ taskId: task.id, kind: 'note', value: '' })}
|
|
81
|
-
>
|
|
82
|
-
note
|
|
83
|
-
</Button>
|
|
84
|
-
<Button
|
|
85
|
-
variant="link"
|
|
86
|
-
size="xs"
|
|
87
|
-
className="h-auto px-0 text-[8px] text-doom-red"
|
|
88
|
-
onClick={() => requestTaskRemoval(sendSessionFrame, sessionId, task.id)}
|
|
89
|
-
>
|
|
90
|
-
remove
|
|
91
|
-
</Button>
|
|
92
|
-
</div>
|
|
93
|
-
) : null}
|
|
94
131
|
{editing ? (
|
|
95
132
|
<form
|
|
96
133
|
className="flex flex-col gap-1 pl-3"
|
|
@@ -102,6 +139,7 @@ function TaskRow({
|
|
|
102
139
|
}}
|
|
103
140
|
>
|
|
104
141
|
<Textarea
|
|
142
|
+
ref={editorInput}
|
|
105
143
|
autoFocus
|
|
106
144
|
rows={2}
|
|
107
145
|
size="sm"
|