@polpo-ai/react 0.2.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/LICENSE +21 -0
- package/README.md +556 -0
- package/dist/hooks/use-active-delays.d.ts +19 -0
- package/dist/hooks/use-active-delays.d.ts.map +1 -0
- package/dist/hooks/use-active-delays.js +35 -0
- package/dist/hooks/use-active-delays.js.map +1 -0
- package/dist/hooks/use-agent.d.ts +12 -0
- package/dist/hooks/use-agent.d.ts.map +1 -0
- package/dist/hooks/use-agent.js +28 -0
- package/dist/hooks/use-agent.js.map +1 -0
- package/dist/hooks/use-agents.d.ts +16 -0
- package/dist/hooks/use-agents.d.ts.map +1 -0
- package/dist/hooks/use-agents.js +51 -0
- package/dist/hooks/use-agents.js.map +1 -0
- package/dist/hooks/use-approvals.d.ts +19 -0
- package/dist/hooks/use-approvals.d.ts.map +1 -0
- package/dist/hooks/use-approvals.js +51 -0
- package/dist/hooks/use-approvals.js.map +1 -0
- package/dist/hooks/use-assessment-progress.d.ts +11 -0
- package/dist/hooks/use-assessment-progress.d.ts.map +1 -0
- package/dist/hooks/use-assessment-progress.js +10 -0
- package/dist/hooks/use-assessment-progress.js.map +1 -0
- package/dist/hooks/use-auth-status.d.ts +13 -0
- package/dist/hooks/use-auth-status.d.ts.map +1 -0
- package/dist/hooks/use-auth-status.js +28 -0
- package/dist/hooks/use-auth-status.js.map +1 -0
- package/dist/hooks/use-events.d.ts +6 -0
- package/dist/hooks/use-events.d.ts.map +1 -0
- package/dist/hooks/use-events.js +24 -0
- package/dist/hooks/use-events.js.map +1 -0
- package/dist/hooks/use-logs.d.ts +10 -0
- package/dist/hooks/use-logs.d.ts.map +1 -0
- package/dist/hooks/use-logs.js +24 -0
- package/dist/hooks/use-logs.js.map +1 -0
- package/dist/hooks/use-memory.d.ts +30 -0
- package/dist/hooks/use-memory.d.ts.map +1 -0
- package/dist/hooks/use-memory.js +66 -0
- package/dist/hooks/use-memory.js.map +1 -0
- package/dist/hooks/use-mission.d.ts +33 -0
- package/dist/hooks/use-mission.d.ts.map +1 -0
- package/dist/hooks/use-mission.js +78 -0
- package/dist/hooks/use-mission.js.map +1 -0
- package/dist/hooks/use-missions.d.ts +19 -0
- package/dist/hooks/use-missions.d.ts.map +1 -0
- package/dist/hooks/use-missions.js +52 -0
- package/dist/hooks/use-missions.js.map +1 -0
- package/dist/hooks/use-notifications.d.ts +21 -0
- package/dist/hooks/use-notifications.d.ts.map +1 -0
- package/dist/hooks/use-notifications.js +43 -0
- package/dist/hooks/use-notifications.js.map +1 -0
- package/dist/hooks/use-orchestrator-skills.d.ts +13 -0
- package/dist/hooks/use-orchestrator-skills.d.ts.map +1 -0
- package/dist/hooks/use-orchestrator-skills.js +28 -0
- package/dist/hooks/use-orchestrator-skills.js.map +1 -0
- package/dist/hooks/use-playbooks.d.ts +29 -0
- package/dist/hooks/use-playbooks.d.ts.map +1 -0
- package/dist/hooks/use-playbooks.js +49 -0
- package/dist/hooks/use-playbooks.js.map +1 -0
- package/dist/hooks/use-polpo.d.ts +8 -0
- package/dist/hooks/use-polpo.d.ts.map +1 -0
- package/dist/hooks/use-polpo.js +8 -0
- package/dist/hooks/use-polpo.js.map +1 -0
- package/dist/hooks/use-processes.d.ts +9 -0
- package/dist/hooks/use-processes.d.ts.map +1 -0
- package/dist/hooks/use-processes.js +24 -0
- package/dist/hooks/use-processes.js.map +1 -0
- package/dist/hooks/use-schedules.d.ts +9 -0
- package/dist/hooks/use-schedules.d.ts.map +1 -0
- package/dist/hooks/use-schedules.js +35 -0
- package/dist/hooks/use-schedules.js.map +1 -0
- package/dist/hooks/use-sessions.d.ts +14 -0
- package/dist/hooks/use-sessions.d.ts.map +1 -0
- package/dist/hooks/use-sessions.js +49 -0
- package/dist/hooks/use-sessions.js.map +1 -0
- package/dist/hooks/use-skills.d.ts +13 -0
- package/dist/hooks/use-skills.d.ts.map +1 -0
- package/dist/hooks/use-skills.js +28 -0
- package/dist/hooks/use-skills.js.map +1 -0
- package/dist/hooks/use-stable-value.d.ts +6 -0
- package/dist/hooks/use-stable-value.d.ts.map +1 -0
- package/dist/hooks/use-stable-value.js +30 -0
- package/dist/hooks/use-stable-value.js.map +1 -0
- package/dist/hooks/use-stats.d.ts +3 -0
- package/dist/hooks/use-stats.d.ts.map +1 -0
- package/dist/hooks/use-stats.js +7 -0
- package/dist/hooks/use-stats.js.map +1 -0
- package/dist/hooks/use-task-activity.d.ts +21 -0
- package/dist/hooks/use-task-activity.d.ts.map +1 -0
- package/dist/hooks/use-task-activity.js +72 -0
- package/dist/hooks/use-task-activity.js.map +1 -0
- package/dist/hooks/use-task.d.ts +14 -0
- package/dist/hooks/use-task.d.ts.map +1 -0
- package/dist/hooks/use-task.js +58 -0
- package/dist/hooks/use-task.js.map +1 -0
- package/dist/hooks/use-tasks.d.ts +13 -0
- package/dist/hooks/use-tasks.d.ts.map +1 -0
- package/dist/hooks/use-tasks.js +50 -0
- package/dist/hooks/use-tasks.js.map +1 -0
- package/dist/hooks/use-templates.d.ts +21 -0
- package/dist/hooks/use-templates.d.ts.map +1 -0
- package/dist/hooks/use-templates.js +41 -0
- package/dist/hooks/use-templates.js.map +1 -0
- package/dist/hooks/use-vault-entries.d.ts +13 -0
- package/dist/hooks/use-vault-entries.d.ts.map +1 -0
- package/dist/hooks/use-vault-entries.js +32 -0
- package/dist/hooks/use-vault-entries.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/provider/polpo-context.d.ts +9 -0
- package/dist/provider/polpo-context.d.ts.map +1 -0
- package/dist/provider/polpo-context.js +10 -0
- package/dist/provider/polpo-context.js.map +1 -0
- package/dist/provider/polpo-provider.d.ts +12 -0
- package/dist/provider/polpo-provider.d.ts.map +1 -0
- package/dist/provider/polpo-provider.js +62 -0
- package/dist/provider/polpo-provider.js.map +1 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OpenPolpo Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
# @polpo-ai/react
|
|
2
|
+
|
|
3
|
+
Type-safe React hooks for OpenPolpo with real-time Server-Sent Events (SSE) updates.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎣 **Modern React Hooks**: Built with `useSyncExternalStore` for optimal performance
|
|
8
|
+
- 📡 **Real-time Updates**: Push-based SSE, not polling
|
|
9
|
+
- 🔄 **Auto-reconnect**: Exponential backoff with event ID resumption
|
|
10
|
+
- 📦 **Zero Runtime Dependencies**: Only peer dependency is React
|
|
11
|
+
- 🎯 **Type-safe**: Full TypeScript support with inferred types
|
|
12
|
+
- ⚡ **Optimized**: Memoized selectors with WeakMap caching
|
|
13
|
+
- 🔌 **Request Deduplication**: Automatic concurrent request coalescing
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @polpo-ai/react
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Peer Dependencies**:
|
|
22
|
+
- `react`: ^18.0.0 || ^19.0.0
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import { PolpoProvider, useTasks, useAgents, useStats } from '@polpo-ai/react';
|
|
28
|
+
|
|
29
|
+
function App() {
|
|
30
|
+
return (
|
|
31
|
+
<PolpoProvider
|
|
32
|
+
baseUrl="http://localhost:3890"
|
|
33
|
+
apiKey="optional-api-key"
|
|
34
|
+
>
|
|
35
|
+
<Dashboard />
|
|
36
|
+
</PolpoProvider>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function Dashboard() {
|
|
41
|
+
const { tasks } = useTasks();
|
|
42
|
+
const agents = useAgents();
|
|
43
|
+
const stats = useStats();
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div>
|
|
47
|
+
<h1>Polpo Dashboard</h1>
|
|
48
|
+
<p>Tasks: {tasks.length}</p>
|
|
49
|
+
<p>Pending: {stats?.pending ?? 0}</p>
|
|
50
|
+
<ul>
|
|
51
|
+
{tasks.map(task => (
|
|
52
|
+
<li key={task.id}>
|
|
53
|
+
{task.title} - {task.status}
|
|
54
|
+
</li>
|
|
55
|
+
))}
|
|
56
|
+
</ul>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## API Reference
|
|
63
|
+
|
|
64
|
+
### PolpoProvider
|
|
65
|
+
|
|
66
|
+
Root provider component that manages connection and state.
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
<PolpoProvider
|
|
70
|
+
baseUrl="http://localhost:3890"
|
|
71
|
+
apiKey="optional-key"
|
|
72
|
+
autoConnect={true}
|
|
73
|
+
>
|
|
74
|
+
{children}
|
|
75
|
+
</PolpoProvider>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Props**:
|
|
79
|
+
- `baseUrl`: OpenPolpo server URL
|
|
80
|
+
- `apiKey?`: Optional API key for authentication
|
|
81
|
+
- `autoConnect?`: Auto-connect on mount (default: true)
|
|
82
|
+
- `eventFilter?`: Array of SSE event type patterns to subscribe to
|
|
83
|
+
|
|
84
|
+
### Hooks
|
|
85
|
+
|
|
86
|
+
#### usePolpo()
|
|
87
|
+
|
|
88
|
+
Access full Polpo state and methods.
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
const { client, connectionStatus } = usePolpo();
|
|
92
|
+
|
|
93
|
+
// connectionStatus: 'connecting' | 'connected' | 'reconnecting' | 'disconnected' | 'error'
|
|
94
|
+
|
|
95
|
+
// Use the client to call API methods:
|
|
96
|
+
await client.createTask({ title: '...', description: '...', assignTo: 'backend-dev' });
|
|
97
|
+
await client.createMission({ data: '...', name: 'my-mission' });
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### useTasks(filter?)
|
|
101
|
+
|
|
102
|
+
Get all tasks with optional filtering.
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
// All tasks
|
|
106
|
+
const { tasks } = useTasks();
|
|
107
|
+
|
|
108
|
+
// Filtered tasks
|
|
109
|
+
const { tasks: pendingTasks } = useTasks({ status: 'pending' });
|
|
110
|
+
const { tasks: agentTasks } = useTasks({ assignTo: 'backend-dev' });
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Returns**: `UseTasksReturn` (includes `tasks: Task[]`, `isLoading`, `error`, `createTask`, `deleteTask`, `retryTask`, `refetch`)
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
interface Task {
|
|
117
|
+
id: string;
|
|
118
|
+
title: string;
|
|
119
|
+
description: string;
|
|
120
|
+
assignTo: string;
|
|
121
|
+
status: 'draft' | 'pending' | 'awaiting_approval' | 'assigned' | 'in_progress' | 'review' | 'done' | 'failed';
|
|
122
|
+
dependsOn: string[];
|
|
123
|
+
group?: string;
|
|
124
|
+
result?: TaskResult;
|
|
125
|
+
createdAt: string;
|
|
126
|
+
updatedAt: string;
|
|
127
|
+
expectations: TaskExpectation[];
|
|
128
|
+
retries: number;
|
|
129
|
+
maxRetries: number;
|
|
130
|
+
missionGroup?: string;
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### useTask(taskId)
|
|
135
|
+
|
|
136
|
+
Get a single task by ID.
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
const task = useTask('task-123');
|
|
140
|
+
|
|
141
|
+
if (!task) {
|
|
142
|
+
return <div>Task not found</div>;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return <div>{task.title}: {task.status}</div>;
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Returns**: `Task | undefined`
|
|
149
|
+
|
|
150
|
+
#### useMissions()
|
|
151
|
+
|
|
152
|
+
Get all missions with CRUD and execution methods.
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
const {
|
|
156
|
+
missions,
|
|
157
|
+
isLoading,
|
|
158
|
+
error,
|
|
159
|
+
createMission,
|
|
160
|
+
updateMission,
|
|
161
|
+
deleteMission,
|
|
162
|
+
executeMission,
|
|
163
|
+
resumeMission,
|
|
164
|
+
abortMission,
|
|
165
|
+
refetch,
|
|
166
|
+
} = useMissions();
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Returns**: `UseMissionsReturn`
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
interface Mission {
|
|
173
|
+
id: string;
|
|
174
|
+
name: string;
|
|
175
|
+
data: string;
|
|
176
|
+
prompt?: string;
|
|
177
|
+
status: 'draft' | 'active' | 'paused' | 'completed' | 'failed' | 'cancelled';
|
|
178
|
+
deadline?: string;
|
|
179
|
+
schedule?: string;
|
|
180
|
+
recurring?: boolean;
|
|
181
|
+
qualityThreshold?: number;
|
|
182
|
+
createdAt: string;
|
|
183
|
+
updatedAt: string;
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
#### useMission(missionId)
|
|
188
|
+
|
|
189
|
+
Get a single mission by ID.
|
|
190
|
+
|
|
191
|
+
```tsx
|
|
192
|
+
const { mission, report, isLoading, executeMission, abortMission } = useMission('mission-123');
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Returns**: `UseMissionReturn` (includes `mission`, `report: MissionReport | undefined`, and action methods)
|
|
196
|
+
|
|
197
|
+
#### useAgents(filter?)
|
|
198
|
+
|
|
199
|
+
Get all agents.
|
|
200
|
+
|
|
201
|
+
```tsx
|
|
202
|
+
const agents = useAgents();
|
|
203
|
+
const availableAgents = useAgents({ available: true });
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Returns**: `AgentConfig[]`
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
interface AgentConfig {
|
|
210
|
+
name: string;
|
|
211
|
+
role?: string;
|
|
212
|
+
model?: string;
|
|
213
|
+
allowedTools?: string[];
|
|
214
|
+
systemPrompt?: string;
|
|
215
|
+
skills?: string[];
|
|
216
|
+
maxTurns?: number;
|
|
217
|
+
maxConcurrency?: number;
|
|
218
|
+
volatile?: boolean;
|
|
219
|
+
missionGroup?: string;
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
#### useProcesses()
|
|
224
|
+
|
|
225
|
+
Get running agent processes.
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
const processes = useProcesses();
|
|
229
|
+
|
|
230
|
+
return (
|
|
231
|
+
<ul>
|
|
232
|
+
{processes.map(proc => (
|
|
233
|
+
<li key={proc.agentName}>
|
|
234
|
+
{proc.agentName} - PID: {proc.pid} - {proc.alive ? 'Running' : 'Dead'}
|
|
235
|
+
</li>
|
|
236
|
+
))}
|
|
237
|
+
</ul>
|
|
238
|
+
);
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Returns**: `AgentProcess[]`
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
interface AgentProcess {
|
|
245
|
+
agentName: string;
|
|
246
|
+
pid: number;
|
|
247
|
+
taskId: string;
|
|
248
|
+
startedAt: string;
|
|
249
|
+
alive: boolean;
|
|
250
|
+
activity: AgentActivity;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
interface AgentActivity {
|
|
254
|
+
lastTool?: string;
|
|
255
|
+
lastFile?: string;
|
|
256
|
+
filesCreated: string[];
|
|
257
|
+
filesEdited: string[];
|
|
258
|
+
toolCalls: number;
|
|
259
|
+
totalTokens: number;
|
|
260
|
+
lastUpdate: string;
|
|
261
|
+
summary?: string;
|
|
262
|
+
sessionId?: string;
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
#### useEvents(limit?)
|
|
267
|
+
|
|
268
|
+
Get recent events from the event stream.
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
const events = useEvents(50); // Last 50 events
|
|
272
|
+
|
|
273
|
+
return (
|
|
274
|
+
<ul>
|
|
275
|
+
{events.map(event => (
|
|
276
|
+
<li key={event.id}>
|
|
277
|
+
{event.event}: {event.timestamp}
|
|
278
|
+
</li>
|
|
279
|
+
))}
|
|
280
|
+
</ul>
|
|
281
|
+
);
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Returns**: `SSEEvent[]`
|
|
285
|
+
|
|
286
|
+
#### useStats()
|
|
287
|
+
|
|
288
|
+
Get aggregate statistics.
|
|
289
|
+
|
|
290
|
+
```tsx
|
|
291
|
+
const stats = useStats();
|
|
292
|
+
|
|
293
|
+
if (!stats) return null;
|
|
294
|
+
|
|
295
|
+
return (
|
|
296
|
+
<div>
|
|
297
|
+
<p>Pending: {stats.pending}</p>
|
|
298
|
+
<p>Running: {stats.running}</p>
|
|
299
|
+
<p>Queued: {stats.queued}</p>
|
|
300
|
+
<p>Done: {stats.done}</p>
|
|
301
|
+
<p>Failed: {stats.failed}</p>
|
|
302
|
+
</div>
|
|
303
|
+
);
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
**Returns**: `PolpoStats | null`
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
interface PolpoStats {
|
|
310
|
+
pending: number;
|
|
311
|
+
running: number;
|
|
312
|
+
done: number;
|
|
313
|
+
failed: number;
|
|
314
|
+
queued: number;
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
#### useMemory()
|
|
319
|
+
|
|
320
|
+
Get Polpo memory entries.
|
|
321
|
+
|
|
322
|
+
```tsx
|
|
323
|
+
const memory = useMemory();
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
**Returns**: `MemoryEntry[]`
|
|
327
|
+
|
|
328
|
+
#### useLogs(limit?)
|
|
329
|
+
|
|
330
|
+
Get recent log entries.
|
|
331
|
+
|
|
332
|
+
```tsx
|
|
333
|
+
const logs = useLogs(100);
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
**Returns**: `LogEntry[]`
|
|
337
|
+
|
|
338
|
+
### Methods
|
|
339
|
+
|
|
340
|
+
#### createTask(task)
|
|
341
|
+
|
|
342
|
+
Create a new task via the `useTasks` hook or directly via the client.
|
|
343
|
+
|
|
344
|
+
```tsx
|
|
345
|
+
const { createTask } = useTasks();
|
|
346
|
+
|
|
347
|
+
await createTask({
|
|
348
|
+
title: 'Implement feature X',
|
|
349
|
+
description: 'Add authentication to the API',
|
|
350
|
+
assignTo: 'backend-dev',
|
|
351
|
+
});
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
#### retryTask(taskId)
|
|
355
|
+
|
|
356
|
+
Retry a failed task.
|
|
357
|
+
|
|
358
|
+
```tsx
|
|
359
|
+
const { retryTask } = useTasks();
|
|
360
|
+
|
|
361
|
+
await retryTask('task-123');
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
#### createMission(req)
|
|
365
|
+
|
|
366
|
+
Create a new mission.
|
|
367
|
+
|
|
368
|
+
```tsx
|
|
369
|
+
const { createMission } = useMissions();
|
|
370
|
+
|
|
371
|
+
await createMission({
|
|
372
|
+
data: 'tasks:\n - title: Task 1\n assignTo: backend-dev\n description: Do something',
|
|
373
|
+
name: 'new-feature',
|
|
374
|
+
});
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
#### executeMission(missionId)
|
|
378
|
+
|
|
379
|
+
Execute a mission (create tasks and start agents).
|
|
380
|
+
|
|
381
|
+
```tsx
|
|
382
|
+
const { executeMission } = useMissions();
|
|
383
|
+
|
|
384
|
+
await executeMission('mission-123');
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
## Real-time Updates
|
|
388
|
+
|
|
389
|
+
The SDK uses Server-Sent Events (SSE) for push-based real-time updates. All hooks automatically update when the server emits events.
|
|
390
|
+
|
|
391
|
+
**Event Types**:
|
|
392
|
+
- `task:created`, `task:transition`, `task:updated`, `task:removed`, `task:retry`, `task:fix`, `task:timeout`
|
|
393
|
+
- `mission:saved`, `mission:executed`, `mission:completed`, `mission:resumed`, `mission:deleted`
|
|
394
|
+
- `agent:spawned`, `agent:finished`, `agent:activity`, `agent:stale`
|
|
395
|
+
- `assessment:started`, `assessment:progress`, `assessment:complete`, `assessment:corrected`
|
|
396
|
+
- `orchestrator:started`, `orchestrator:tick`, `orchestrator:shutdown`
|
|
397
|
+
|
|
398
|
+
**Auto-reconnect**:
|
|
399
|
+
- Exponential backoff (`reconnectDelay` → `maxReconnectDelay`, defaults 1s → 30s)
|
|
400
|
+
- Resumes from last event ID
|
|
401
|
+
|
|
402
|
+
## Authentication
|
|
403
|
+
|
|
404
|
+
The SDK supports two authentication methods:
|
|
405
|
+
|
|
406
|
+
**Header-based** (preferred):
|
|
407
|
+
```tsx
|
|
408
|
+
<PolpoProvider
|
|
409
|
+
baseUrl="http://localhost:3890"
|
|
410
|
+
apiKey="your-api-key"
|
|
411
|
+
>
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
**Query parameter** (for EventSource):
|
|
415
|
+
The SDK automatically appends `?apiKey=` to SSE requests when an API key is provided, since EventSource doesn't support custom headers.
|
|
416
|
+
|
|
417
|
+
## TypeScript
|
|
418
|
+
|
|
419
|
+
Full TypeScript support with exported types:
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
import type {
|
|
423
|
+
Task,
|
|
424
|
+
Mission,
|
|
425
|
+
MissionReport,
|
|
426
|
+
AgentConfig,
|
|
427
|
+
AgentProcess,
|
|
428
|
+
SSEEvent,
|
|
429
|
+
PolpoStats,
|
|
430
|
+
CreateTaskRequest,
|
|
431
|
+
UpdateTaskRequest,
|
|
432
|
+
CreateMissionRequest,
|
|
433
|
+
UpdateMissionRequest,
|
|
434
|
+
} from '@polpo-ai/react';
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
## Examples
|
|
438
|
+
|
|
439
|
+
### Task List with Retry
|
|
440
|
+
|
|
441
|
+
```tsx
|
|
442
|
+
import { useTasks } from '@polpo-ai/react';
|
|
443
|
+
|
|
444
|
+
function TaskList() {
|
|
445
|
+
const { tasks, retryTask } = useTasks();
|
|
446
|
+
|
|
447
|
+
return (
|
|
448
|
+
<ul>
|
|
449
|
+
{tasks.map(task => (
|
|
450
|
+
<li key={task.id}>
|
|
451
|
+
<span>{task.title} - {task.status}</span>
|
|
452
|
+
{task.status === 'failed' && (
|
|
453
|
+
<button onClick={() => retryTask(task.id)}>
|
|
454
|
+
Retry
|
|
455
|
+
</button>
|
|
456
|
+
)}
|
|
457
|
+
</li>
|
|
458
|
+
))}
|
|
459
|
+
</ul>
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Live Agent Activity
|
|
465
|
+
|
|
466
|
+
```tsx
|
|
467
|
+
import { useProcesses } from '@polpo-ai/react';
|
|
468
|
+
|
|
469
|
+
function AgentActivity() {
|
|
470
|
+
const processes = useProcesses();
|
|
471
|
+
|
|
472
|
+
return (
|
|
473
|
+
<div>
|
|
474
|
+
{processes.filter(p => p.alive).map(proc => (
|
|
475
|
+
<div key={proc.agentName}>
|
|
476
|
+
<h3>{proc.agentName}</h3>
|
|
477
|
+
<p>Task: {proc.taskId}</p>
|
|
478
|
+
{proc.activity && (
|
|
479
|
+
<>
|
|
480
|
+
<p>Tool: {proc.activity.lastTool}</p>
|
|
481
|
+
<p>File: {proc.activity.lastFile}</p>
|
|
482
|
+
</>
|
|
483
|
+
)}
|
|
484
|
+
</div>
|
|
485
|
+
))}
|
|
486
|
+
</div>
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### Mission Progress
|
|
492
|
+
|
|
493
|
+
```tsx
|
|
494
|
+
import { useMission, useTasks } from '@polpo-ai/react';
|
|
495
|
+
|
|
496
|
+
function MissionProgress({ missionId }: { missionId: string }) {
|
|
497
|
+
const { mission, report } = useMission(missionId);
|
|
498
|
+
const { tasks } = useTasks({ group: missionId });
|
|
499
|
+
|
|
500
|
+
if (!mission) return null;
|
|
501
|
+
|
|
502
|
+
const completed = tasks.filter(t => t.status === 'done').length;
|
|
503
|
+
const total = tasks.length;
|
|
504
|
+
const progress = total > 0 ? (completed / total) * 100 : 0;
|
|
505
|
+
|
|
506
|
+
return (
|
|
507
|
+
<div>
|
|
508
|
+
<h2>{mission.name} ({mission.status})</h2>
|
|
509
|
+
<progress value={completed} max={total} />
|
|
510
|
+
<p>{progress.toFixed(0)}% complete ({completed}/{total})</p>
|
|
511
|
+
{report && <p>Score: {report.avgScore?.toFixed(1) ?? 'N/A'}</p>}
|
|
512
|
+
</div>
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Event Stream
|
|
518
|
+
|
|
519
|
+
```tsx
|
|
520
|
+
import { useEvents } from '@polpo-ai/react';
|
|
521
|
+
|
|
522
|
+
function EventFeed() {
|
|
523
|
+
const events = useEvents(20);
|
|
524
|
+
|
|
525
|
+
return (
|
|
526
|
+
<ul>
|
|
527
|
+
{events.map(event => (
|
|
528
|
+
<li key={event.id}>
|
|
529
|
+
<strong>{event.event}</strong>
|
|
530
|
+
{' - '}
|
|
531
|
+
{new Date(event.timestamp).toLocaleTimeString()}
|
|
532
|
+
</li>
|
|
533
|
+
))}
|
|
534
|
+
</ul>
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
## Performance
|
|
540
|
+
|
|
541
|
+
The SDK is optimized for performance:
|
|
542
|
+
|
|
543
|
+
- **Memoized Selectors**: WeakMap caching prevents unnecessary re-renders
|
|
544
|
+
- **Batched Updates**: `queueMicrotask` batching for event processing
|
|
545
|
+
- **Request Deduplication**: Concurrent identical requests are coalesced
|
|
546
|
+
- **Efficient Filtering**: Hooks support filtering without re-computation
|
|
547
|
+
|
|
548
|
+
## Bundle Size
|
|
549
|
+
|
|
550
|
+
- **Zero runtime dependencies** (only React peer)
|
|
551
|
+
- Tree-shakeable ESM exports
|
|
552
|
+
- `sideEffects: false` for optimal bundling
|
|
553
|
+
|
|
554
|
+
## License
|
|
555
|
+
|
|
556
|
+
MIT
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ActiveDelay } from "@polpo-ai/client";
|
|
2
|
+
export interface UseActiveDelaysReturn {
|
|
3
|
+
/** Active delays from SSE events (live, updated by delay:started/delay:expired). */
|
|
4
|
+
activeDelays: ActiveDelay[];
|
|
5
|
+
/** Active delays fetched from the server (initial load). */
|
|
6
|
+
fetchedDelays: ActiveDelay[];
|
|
7
|
+
/** Refetch from server. */
|
|
8
|
+
refetch: () => void;
|
|
9
|
+
loading: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Hook for accessing active delay timers.
|
|
13
|
+
*
|
|
14
|
+
* Combines two sources:
|
|
15
|
+
* 1. SSE events (delay:started / delay:expired) → store.activeDelays (real-time)
|
|
16
|
+
* 2. Initial fetch from GET /missions/delays (catches delays that started before SSE connected)
|
|
17
|
+
*/
|
|
18
|
+
export declare function useActiveDelays(): UseActiveDelaysReturn;
|
|
19
|
+
//# sourceMappingURL=use-active-delays.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-active-delays.d.ts","sourceRoot":"","sources":["../../src/hooks/use-active-delays.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,qBAAqB;IACpC,oFAAoF;IACpF,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,4DAA4D;IAC5D,aAAa,EAAE,WAAW,EAAE,CAAC;IAC7B,2BAA2B;IAC3B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,IAAI,qBAAqB,CAkCvD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useSyncExternalStore, useState, useEffect, useCallback } from "react";
|
|
2
|
+
import { usePolpoContext } from "../provider/polpo-context.js";
|
|
3
|
+
/**
|
|
4
|
+
* Hook for accessing active delay timers.
|
|
5
|
+
*
|
|
6
|
+
* Combines two sources:
|
|
7
|
+
* 1. SSE events (delay:started / delay:expired) → store.activeDelays (real-time)
|
|
8
|
+
* 2. Initial fetch from GET /missions/delays (catches delays that started before SSE connected)
|
|
9
|
+
*/
|
|
10
|
+
export function useActiveDelays() {
|
|
11
|
+
const { client, store } = usePolpoContext();
|
|
12
|
+
// Real-time from store (fed by SSE events via event-reducer)
|
|
13
|
+
const storeDelays = useSyncExternalStore(store.subscribe, () => store.getSnapshot().activeDelays, () => store.getServerSnapshot().activeDelays);
|
|
14
|
+
const [fetchedDelays, setFetchedDelays] = useState([]);
|
|
15
|
+
const [loading, setLoading] = useState(true);
|
|
16
|
+
const [fetchCount, setFetchCount] = useState(0);
|
|
17
|
+
const refetch = useCallback(() => setFetchCount(c => c + 1), []);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
setLoading(true);
|
|
20
|
+
client.listDelays()
|
|
21
|
+
.then((delays) => {
|
|
22
|
+
setFetchedDelays(delays);
|
|
23
|
+
// Also seed the store so SSE events can update from here
|
|
24
|
+
for (const d of delays) {
|
|
25
|
+
store.getSnapshot().activeDelays.set(`${d.group}:${d.delayName}`, d);
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
.catch(() => { })
|
|
29
|
+
.finally(() => setLoading(false));
|
|
30
|
+
}, [client, store, fetchCount]);
|
|
31
|
+
// Merge: store has real-time data, fetched fills in pre-existing delays
|
|
32
|
+
const activeDelays = Array.from(storeDelays.values());
|
|
33
|
+
return { activeDelays, fetchedDelays, refetch, loading };
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=use-active-delays.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-active-delays.js","sourceRoot":"","sources":["../../src/hooks/use-active-delays.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAa/D;;;;;;GAMG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,eAAe,EAAE,CAAC;IAE5C,6DAA6D;IAC7D,MAAM,WAAW,GAAG,oBAAoB,CACtC,KAAK,CAAC,SAAS,EACf,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,YAAY,EACtC,GAAG,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,YAAY,CAC7C,CAAC;IAEF,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAgB,EAAE,CAAC,CAAC;IACtE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEhD,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEjE,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,CAAC,UAAU,EAAE;aAChB,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACf,gBAAgB,CAAC,MAAM,CAAC,CAAC;YACzB,yDAAyD;YACzD,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;gBACvB,KAAK,CAAC,WAAW,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;YACvE,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,GAAqB,CAAC,CAAC;aAClC,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IACtC,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;IAEhC,wEAAwE;IACxE,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;IAEtD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AgentConfig } from "@polpo-ai/client";
|
|
2
|
+
export interface UseAgentReturn {
|
|
3
|
+
agent: AgentConfig | null;
|
|
4
|
+
isLoading: boolean;
|
|
5
|
+
error: Error | null;
|
|
6
|
+
refetch: () => Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Fetch a single agent by name from the `/agents/:name` endpoint.
|
|
10
|
+
*/
|
|
11
|
+
export declare function useAgent(name: string): UseAgentReturn;
|
|
12
|
+
//# sourceMappingURL=use-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent.d.ts","sourceRoot":"","sources":["../../src/hooks/use-agent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAuBrD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from "react";
|
|
2
|
+
import { usePolpoContext } from "../provider/polpo-context.js";
|
|
3
|
+
/**
|
|
4
|
+
* Fetch a single agent by name from the `/agents/:name` endpoint.
|
|
5
|
+
*/
|
|
6
|
+
export function useAgent(name) {
|
|
7
|
+
const { client } = usePolpoContext();
|
|
8
|
+
const [agent, setAgent] = useState(null);
|
|
9
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
10
|
+
const [error, setError] = useState(null);
|
|
11
|
+
const fetchAgent = useCallback(async () => {
|
|
12
|
+
try {
|
|
13
|
+
setError(null);
|
|
14
|
+
const data = await client.getAgent(name);
|
|
15
|
+
setAgent(data);
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
setError(err);
|
|
19
|
+
setAgent(null);
|
|
20
|
+
}
|
|
21
|
+
}, [client, name]);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
setIsLoading(true);
|
|
24
|
+
fetchAgent().finally(() => setIsLoading(false));
|
|
25
|
+
}, [fetchAgent]);
|
|
26
|
+
return { agent, isLoading, error, refetch: fetchAgent };
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=use-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent.js","sourceRoot":"","sources":["../../src/hooks/use-agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAU/D;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,MAAM,EAAE,MAAM,EAAE,GAAG,eAAe,EAAE,CAAC;IACrC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAqB,IAAI,CAAC,CAAC;IAC7D,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAEvD,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACxC,IAAI,CAAC;YACH,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACzC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,GAAY,CAAC,CAAC;YACvB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IAEnB,SAAS,CAAC,GAAG,EAAE;QACb,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,UAAU,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;IAClD,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AgentConfig, Team, AddAgentRequest, UpdateAgentRequest, AddTeamRequest } from "@polpo-ai/client";
|
|
2
|
+
export interface UseAgentsReturn {
|
|
3
|
+
agents: AgentConfig[];
|
|
4
|
+
teams: Team[];
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
error: Error | null;
|
|
7
|
+
addAgent: (req: AddAgentRequest, teamName?: string) => Promise<void>;
|
|
8
|
+
updateAgent: (name: string, req: UpdateAgentRequest) => Promise<AgentConfig>;
|
|
9
|
+
removeAgent: (name: string) => Promise<void>;
|
|
10
|
+
addTeam: (req: AddTeamRequest) => Promise<void>;
|
|
11
|
+
removeTeam: (name: string) => Promise<void>;
|
|
12
|
+
renameTeam: (oldName: string, newName: string) => Promise<Team>;
|
|
13
|
+
refetch: () => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare function useAgents(): UseAgentsReturn;
|
|
16
|
+
//# sourceMappingURL=use-agents.d.ts.map
|