elsabro 2.3.0 → 3.7.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 +668 -20
- package/bin/install.js +0 -0
- package/flows/development-flow.json +452 -0
- package/flows/quick-flow.json +118 -0
- package/package.json +3 -2
- package/references/SYSTEM_INDEX.md +379 -5
- package/references/agent-marketplace.md +2274 -0
- package/references/agent-protocol.md +1126 -0
- package/references/ai-code-suggestions.md +2413 -0
- package/references/checkpointing.md +595 -0
- package/references/collaboration-patterns.md +851 -0
- package/references/collaborative-sessions.md +1081 -0
- package/references/configuration-management.md +1810 -0
- package/references/cost-tracking.md +1095 -0
- package/references/enterprise-sso.md +2001 -0
- package/references/error-contracts-v2.md +968 -0
- package/references/event-driven.md +1031 -0
- package/references/flow-orchestration.md +940 -0
- package/references/flow-visualization.md +1557 -0
- package/references/ide-integrations.md +3513 -0
- package/references/interrupt-system.md +681 -0
- package/references/kubernetes-deployment.md +3099 -0
- package/references/memory-system.md +683 -0
- package/references/mobile-companion.md +3236 -0
- package/references/multi-llm-providers.md +2494 -0
- package/references/multi-project-memory.md +1182 -0
- package/references/observability.md +793 -0
- package/references/output-schemas.md +858 -0
- package/references/performance-profiler.md +955 -0
- package/references/plugin-system.md +1526 -0
- package/references/prompt-management.md +292 -0
- package/references/sandbox-execution.md +303 -0
- package/references/security-system.md +1253 -0
- package/references/streaming.md +696 -0
- package/references/testing-framework.md +1151 -0
- package/references/time-travel.md +802 -0
- package/references/tool-registry.md +886 -0
- package/references/voice-commands.md +3296 -0
- package/templates/agent-marketplace-config.json +220 -0
- package/templates/agent-protocol-config.json +136 -0
- package/templates/ai-suggestions-config.json +100 -0
- package/templates/checkpoint-state.json +61 -0
- package/templates/collaboration-config.json +157 -0
- package/templates/collaborative-sessions-config.json +153 -0
- package/templates/configuration-config.json +245 -0
- package/templates/cost-tracking-config.json +148 -0
- package/templates/enterprise-sso-config.json +438 -0
- package/templates/events-config.json +148 -0
- package/templates/flow-visualization-config.json +196 -0
- package/templates/ide-integrations-config.json +442 -0
- package/templates/kubernetes-config.json +764 -0
- package/templates/memory-state.json +84 -0
- package/templates/mobile-companion-config.json +600 -0
- package/templates/multi-llm-config.json +544 -0
- package/templates/multi-project-memory-config.json +145 -0
- package/templates/observability-config.json +109 -0
- package/templates/performance-profiler-config.json +125 -0
- package/templates/plugin-config.json +170 -0
- package/templates/prompt-management-config.json +86 -0
- package/templates/sandbox-config.json +185 -0
- package/templates/schemas-config.json +65 -0
- package/templates/security-config.json +120 -0
- package/templates/streaming-config.json +72 -0
- package/templates/testing-config.json +81 -0
- package/templates/timetravel-config.json +62 -0
- package/templates/tool-registry-config.json +109 -0
- package/templates/voice-commands-config.json +658 -0
|
@@ -0,0 +1,1126 @@
|
|
|
1
|
+
# Agent Protocol REST API (v3.2)
|
|
2
|
+
|
|
3
|
+
Sistema de interoperabilidad basado en el estándar Agent Protocol para comunicación con otros frameworks de agentes.
|
|
4
|
+
|
|
5
|
+
## Arquitectura
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────────────────────────────────────────┐
|
|
9
|
+
│ AGENT PROTOCOL LAYER │
|
|
10
|
+
├─────────────────────────────────────────────────────────────────────────┤
|
|
11
|
+
│ │
|
|
12
|
+
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
|
13
|
+
│ │ REST API SERVER │ │
|
|
14
|
+
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────────────┐ │ │
|
|
15
|
+
│ │ │ /tasks │ │ /steps │ │/artifacts│ │ /agent-info │ │ │
|
|
16
|
+
│ │ │ CRUD │ │ CRUD │ │ CRUD │ │ metadata │ │ │
|
|
17
|
+
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────────────┘ │ │
|
|
18
|
+
│ └─────────────────────────────────────────────────────────────────┘ │
|
|
19
|
+
│ │ │
|
|
20
|
+
│ ▼ │
|
|
21
|
+
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
|
22
|
+
│ │ PROTOCOL ADAPTER │ │
|
|
23
|
+
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌────────────────┐ │ │
|
|
24
|
+
│ │ │ Task Mapper │ │ Step Mapper │ │ Artifact Store │ │ │
|
|
25
|
+
│ │ │ Protocol↔ELSABRO│ │ Protocol↔Flow │ │ File-based │ │ │
|
|
26
|
+
│ │ └─────────────────┘ └─────────────────┘ └────────────────┘ │ │
|
|
27
|
+
│ └─────────────────────────────────────────────────────────────────┘ │
|
|
28
|
+
│ │ │
|
|
29
|
+
│ ▼ │
|
|
30
|
+
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
|
31
|
+
│ │ ELSABRO CORE SYSTEMS │ │
|
|
32
|
+
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────────────┐ │ │
|
|
33
|
+
│ │ │ Tasks │ │ Flows │ │ Agents │ │ Checkpoints │ │ │
|
|
34
|
+
│ │ │ API │ │ Engine │ │ Pool │ │ System │ │ │
|
|
35
|
+
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────────────┘ │ │
|
|
36
|
+
│ └─────────────────────────────────────────────────────────────────┘ │
|
|
37
|
+
│ │
|
|
38
|
+
└─────────────────────────────────────────────────────────────────────────┘
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Especificación OpenAPI
|
|
44
|
+
|
|
45
|
+
```yaml
|
|
46
|
+
openapi: 3.1.0
|
|
47
|
+
info:
|
|
48
|
+
title: ELSABRO Agent Protocol API
|
|
49
|
+
version: 1.0.0
|
|
50
|
+
description: Agent Protocol implementation for ELSABRO framework interoperability
|
|
51
|
+
|
|
52
|
+
servers:
|
|
53
|
+
- url: http://localhost:8080/api/v1
|
|
54
|
+
description: Local development server
|
|
55
|
+
|
|
56
|
+
paths:
|
|
57
|
+
/agent:
|
|
58
|
+
get:
|
|
59
|
+
summary: Get agent information
|
|
60
|
+
operationId: getAgentInfo
|
|
61
|
+
responses:
|
|
62
|
+
'200':
|
|
63
|
+
description: Agent information
|
|
64
|
+
content:
|
|
65
|
+
application/json:
|
|
66
|
+
schema:
|
|
67
|
+
$ref: '#/components/schemas/AgentInfo'
|
|
68
|
+
|
|
69
|
+
/tasks:
|
|
70
|
+
get:
|
|
71
|
+
summary: List all tasks
|
|
72
|
+
operationId: listTasks
|
|
73
|
+
parameters:
|
|
74
|
+
- name: status
|
|
75
|
+
in: query
|
|
76
|
+
schema:
|
|
77
|
+
type: string
|
|
78
|
+
enum: [pending, in_progress, completed, failed]
|
|
79
|
+
- name: limit
|
|
80
|
+
in: query
|
|
81
|
+
schema:
|
|
82
|
+
type: integer
|
|
83
|
+
default: 50
|
|
84
|
+
- name: offset
|
|
85
|
+
in: query
|
|
86
|
+
schema:
|
|
87
|
+
type: integer
|
|
88
|
+
default: 0
|
|
89
|
+
responses:
|
|
90
|
+
'200':
|
|
91
|
+
description: List of tasks
|
|
92
|
+
content:
|
|
93
|
+
application/json:
|
|
94
|
+
schema:
|
|
95
|
+
$ref: '#/components/schemas/TaskList'
|
|
96
|
+
|
|
97
|
+
post:
|
|
98
|
+
summary: Create a new task
|
|
99
|
+
operationId: createTask
|
|
100
|
+
requestBody:
|
|
101
|
+
required: true
|
|
102
|
+
content:
|
|
103
|
+
application/json:
|
|
104
|
+
schema:
|
|
105
|
+
$ref: '#/components/schemas/TaskCreate'
|
|
106
|
+
responses:
|
|
107
|
+
'201':
|
|
108
|
+
description: Task created
|
|
109
|
+
content:
|
|
110
|
+
application/json:
|
|
111
|
+
schema:
|
|
112
|
+
$ref: '#/components/schemas/Task'
|
|
113
|
+
|
|
114
|
+
/tasks/{taskId}:
|
|
115
|
+
get:
|
|
116
|
+
summary: Get task details
|
|
117
|
+
operationId: getTask
|
|
118
|
+
parameters:
|
|
119
|
+
- name: taskId
|
|
120
|
+
in: path
|
|
121
|
+
required: true
|
|
122
|
+
schema:
|
|
123
|
+
type: string
|
|
124
|
+
responses:
|
|
125
|
+
'200':
|
|
126
|
+
description: Task details
|
|
127
|
+
content:
|
|
128
|
+
application/json:
|
|
129
|
+
schema:
|
|
130
|
+
$ref: '#/components/schemas/Task'
|
|
131
|
+
'404':
|
|
132
|
+
description: Task not found
|
|
133
|
+
|
|
134
|
+
/tasks/{taskId}/steps:
|
|
135
|
+
get:
|
|
136
|
+
summary: List task steps
|
|
137
|
+
operationId: listSteps
|
|
138
|
+
parameters:
|
|
139
|
+
- name: taskId
|
|
140
|
+
in: path
|
|
141
|
+
required: true
|
|
142
|
+
schema:
|
|
143
|
+
type: string
|
|
144
|
+
responses:
|
|
145
|
+
'200':
|
|
146
|
+
description: List of steps
|
|
147
|
+
content:
|
|
148
|
+
application/json:
|
|
149
|
+
schema:
|
|
150
|
+
$ref: '#/components/schemas/StepList'
|
|
151
|
+
|
|
152
|
+
post:
|
|
153
|
+
summary: Execute next step
|
|
154
|
+
operationId: executeStep
|
|
155
|
+
parameters:
|
|
156
|
+
- name: taskId
|
|
157
|
+
in: path
|
|
158
|
+
required: true
|
|
159
|
+
schema:
|
|
160
|
+
type: string
|
|
161
|
+
requestBody:
|
|
162
|
+
content:
|
|
163
|
+
application/json:
|
|
164
|
+
schema:
|
|
165
|
+
$ref: '#/components/schemas/StepRequest'
|
|
166
|
+
responses:
|
|
167
|
+
'200':
|
|
168
|
+
description: Step executed
|
|
169
|
+
content:
|
|
170
|
+
application/json:
|
|
171
|
+
schema:
|
|
172
|
+
$ref: '#/components/schemas/Step'
|
|
173
|
+
|
|
174
|
+
/tasks/{taskId}/steps/{stepId}:
|
|
175
|
+
get:
|
|
176
|
+
summary: Get step details
|
|
177
|
+
operationId: getStep
|
|
178
|
+
parameters:
|
|
179
|
+
- name: taskId
|
|
180
|
+
in: path
|
|
181
|
+
required: true
|
|
182
|
+
schema:
|
|
183
|
+
type: string
|
|
184
|
+
- name: stepId
|
|
185
|
+
in: path
|
|
186
|
+
required: true
|
|
187
|
+
schema:
|
|
188
|
+
type: string
|
|
189
|
+
responses:
|
|
190
|
+
'200':
|
|
191
|
+
description: Step details
|
|
192
|
+
content:
|
|
193
|
+
application/json:
|
|
194
|
+
schema:
|
|
195
|
+
$ref: '#/components/schemas/Step'
|
|
196
|
+
|
|
197
|
+
/tasks/{taskId}/artifacts:
|
|
198
|
+
get:
|
|
199
|
+
summary: List task artifacts
|
|
200
|
+
operationId: listArtifacts
|
|
201
|
+
parameters:
|
|
202
|
+
- name: taskId
|
|
203
|
+
in: path
|
|
204
|
+
required: true
|
|
205
|
+
schema:
|
|
206
|
+
type: string
|
|
207
|
+
responses:
|
|
208
|
+
'200':
|
|
209
|
+
description: List of artifacts
|
|
210
|
+
content:
|
|
211
|
+
application/json:
|
|
212
|
+
schema:
|
|
213
|
+
$ref: '#/components/schemas/ArtifactList'
|
|
214
|
+
|
|
215
|
+
post:
|
|
216
|
+
summary: Upload artifact
|
|
217
|
+
operationId: uploadArtifact
|
|
218
|
+
parameters:
|
|
219
|
+
- name: taskId
|
|
220
|
+
in: path
|
|
221
|
+
required: true
|
|
222
|
+
schema:
|
|
223
|
+
type: string
|
|
224
|
+
requestBody:
|
|
225
|
+
required: true
|
|
226
|
+
content:
|
|
227
|
+
multipart/form-data:
|
|
228
|
+
schema:
|
|
229
|
+
type: object
|
|
230
|
+
properties:
|
|
231
|
+
file:
|
|
232
|
+
type: string
|
|
233
|
+
format: binary
|
|
234
|
+
relative_path:
|
|
235
|
+
type: string
|
|
236
|
+
responses:
|
|
237
|
+
'201':
|
|
238
|
+
description: Artifact uploaded
|
|
239
|
+
content:
|
|
240
|
+
application/json:
|
|
241
|
+
schema:
|
|
242
|
+
$ref: '#/components/schemas/Artifact'
|
|
243
|
+
|
|
244
|
+
/tasks/{taskId}/artifacts/{artifactId}:
|
|
245
|
+
get:
|
|
246
|
+
summary: Download artifact
|
|
247
|
+
operationId: downloadArtifact
|
|
248
|
+
parameters:
|
|
249
|
+
- name: taskId
|
|
250
|
+
in: path
|
|
251
|
+
required: true
|
|
252
|
+
schema:
|
|
253
|
+
type: string
|
|
254
|
+
- name: artifactId
|
|
255
|
+
in: path
|
|
256
|
+
required: true
|
|
257
|
+
schema:
|
|
258
|
+
type: string
|
|
259
|
+
responses:
|
|
260
|
+
'200':
|
|
261
|
+
description: Artifact content
|
|
262
|
+
content:
|
|
263
|
+
application/octet-stream:
|
|
264
|
+
schema:
|
|
265
|
+
type: string
|
|
266
|
+
format: binary
|
|
267
|
+
|
|
268
|
+
components:
|
|
269
|
+
schemas:
|
|
270
|
+
AgentInfo:
|
|
271
|
+
type: object
|
|
272
|
+
required:
|
|
273
|
+
- name
|
|
274
|
+
- version
|
|
275
|
+
- protocol_version
|
|
276
|
+
properties:
|
|
277
|
+
name:
|
|
278
|
+
type: string
|
|
279
|
+
example: "ELSABRO"
|
|
280
|
+
version:
|
|
281
|
+
type: string
|
|
282
|
+
example: "3.2.0"
|
|
283
|
+
protocol_version:
|
|
284
|
+
type: string
|
|
285
|
+
example: "1.0.0"
|
|
286
|
+
description:
|
|
287
|
+
type: string
|
|
288
|
+
capabilities:
|
|
289
|
+
type: array
|
|
290
|
+
items:
|
|
291
|
+
type: string
|
|
292
|
+
example:
|
|
293
|
+
- "checkpointing"
|
|
294
|
+
- "memory"
|
|
295
|
+
- "flows"
|
|
296
|
+
- "time-travel"
|
|
297
|
+
- "streaming"
|
|
298
|
+
|
|
299
|
+
TaskCreate:
|
|
300
|
+
type: object
|
|
301
|
+
required:
|
|
302
|
+
- input
|
|
303
|
+
properties:
|
|
304
|
+
input:
|
|
305
|
+
type: string
|
|
306
|
+
description: Task input/prompt
|
|
307
|
+
additional_input:
|
|
308
|
+
type: object
|
|
309
|
+
description: Additional parameters
|
|
310
|
+
|
|
311
|
+
Task:
|
|
312
|
+
type: object
|
|
313
|
+
required:
|
|
314
|
+
- task_id
|
|
315
|
+
- input
|
|
316
|
+
- status
|
|
317
|
+
- created_at
|
|
318
|
+
properties:
|
|
319
|
+
task_id:
|
|
320
|
+
type: string
|
|
321
|
+
input:
|
|
322
|
+
type: string
|
|
323
|
+
additional_input:
|
|
324
|
+
type: object
|
|
325
|
+
status:
|
|
326
|
+
type: string
|
|
327
|
+
enum: [pending, in_progress, completed, failed]
|
|
328
|
+
output:
|
|
329
|
+
type: string
|
|
330
|
+
additional_output:
|
|
331
|
+
type: object
|
|
332
|
+
artifacts:
|
|
333
|
+
type: array
|
|
334
|
+
items:
|
|
335
|
+
$ref: '#/components/schemas/Artifact'
|
|
336
|
+
created_at:
|
|
337
|
+
type: string
|
|
338
|
+
format: date-time
|
|
339
|
+
updated_at:
|
|
340
|
+
type: string
|
|
341
|
+
format: date-time
|
|
342
|
+
|
|
343
|
+
TaskList:
|
|
344
|
+
type: object
|
|
345
|
+
properties:
|
|
346
|
+
tasks:
|
|
347
|
+
type: array
|
|
348
|
+
items:
|
|
349
|
+
$ref: '#/components/schemas/Task'
|
|
350
|
+
total:
|
|
351
|
+
type: integer
|
|
352
|
+
has_more:
|
|
353
|
+
type: boolean
|
|
354
|
+
|
|
355
|
+
StepRequest:
|
|
356
|
+
type: object
|
|
357
|
+
properties:
|
|
358
|
+
input:
|
|
359
|
+
type: string
|
|
360
|
+
additional_input:
|
|
361
|
+
type: object
|
|
362
|
+
|
|
363
|
+
Step:
|
|
364
|
+
type: object
|
|
365
|
+
required:
|
|
366
|
+
- step_id
|
|
367
|
+
- task_id
|
|
368
|
+
- status
|
|
369
|
+
- created_at
|
|
370
|
+
properties:
|
|
371
|
+
step_id:
|
|
372
|
+
type: string
|
|
373
|
+
task_id:
|
|
374
|
+
type: string
|
|
375
|
+
name:
|
|
376
|
+
type: string
|
|
377
|
+
status:
|
|
378
|
+
type: string
|
|
379
|
+
enum: [pending, running, completed, failed]
|
|
380
|
+
input:
|
|
381
|
+
type: string
|
|
382
|
+
output:
|
|
383
|
+
type: string
|
|
384
|
+
additional_output:
|
|
385
|
+
type: object
|
|
386
|
+
artifacts:
|
|
387
|
+
type: array
|
|
388
|
+
items:
|
|
389
|
+
$ref: '#/components/schemas/Artifact'
|
|
390
|
+
is_last:
|
|
391
|
+
type: boolean
|
|
392
|
+
created_at:
|
|
393
|
+
type: string
|
|
394
|
+
format: date-time
|
|
395
|
+
completed_at:
|
|
396
|
+
type: string
|
|
397
|
+
format: date-time
|
|
398
|
+
|
|
399
|
+
StepList:
|
|
400
|
+
type: object
|
|
401
|
+
properties:
|
|
402
|
+
steps:
|
|
403
|
+
type: array
|
|
404
|
+
items:
|
|
405
|
+
$ref: '#/components/schemas/Step'
|
|
406
|
+
total:
|
|
407
|
+
type: integer
|
|
408
|
+
|
|
409
|
+
Artifact:
|
|
410
|
+
type: object
|
|
411
|
+
required:
|
|
412
|
+
- artifact_id
|
|
413
|
+
- file_name
|
|
414
|
+
- created_at
|
|
415
|
+
properties:
|
|
416
|
+
artifact_id:
|
|
417
|
+
type: string
|
|
418
|
+
file_name:
|
|
419
|
+
type: string
|
|
420
|
+
relative_path:
|
|
421
|
+
type: string
|
|
422
|
+
content_type:
|
|
423
|
+
type: string
|
|
424
|
+
size_bytes:
|
|
425
|
+
type: integer
|
|
426
|
+
created_at:
|
|
427
|
+
type: string
|
|
428
|
+
format: date-time
|
|
429
|
+
|
|
430
|
+
ArtifactList:
|
|
431
|
+
type: object
|
|
432
|
+
properties:
|
|
433
|
+
artifacts:
|
|
434
|
+
type: array
|
|
435
|
+
items:
|
|
436
|
+
$ref: '#/components/schemas/Artifact'
|
|
437
|
+
total:
|
|
438
|
+
type: integer
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## Implementación del Servidor
|
|
444
|
+
|
|
445
|
+
### AgentProtocolServer
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
class AgentProtocolServer {
|
|
449
|
+
private port: number;
|
|
450
|
+
private taskMapper: TaskMapper;
|
|
451
|
+
private stepMapper: StepMapper;
|
|
452
|
+
private artifactStore: ArtifactStore;
|
|
453
|
+
|
|
454
|
+
constructor(config: AgentProtocolConfig) {
|
|
455
|
+
this.port = config.port || 8080;
|
|
456
|
+
this.taskMapper = new TaskMapper();
|
|
457
|
+
this.stepMapper = new StepMapper();
|
|
458
|
+
this.artifactStore = new ArtifactStore(config.artifactsDir);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// GET /agent
|
|
462
|
+
async getAgentInfo(): Promise<AgentInfo> {
|
|
463
|
+
return {
|
|
464
|
+
name: "ELSABRO",
|
|
465
|
+
version: "3.2.0",
|
|
466
|
+
protocol_version: "1.0.0",
|
|
467
|
+
description: "AI-powered development orchestration framework",
|
|
468
|
+
capabilities: [
|
|
469
|
+
"checkpointing",
|
|
470
|
+
"multi-level-memory",
|
|
471
|
+
"flow-orchestration",
|
|
472
|
+
"error-contracts",
|
|
473
|
+
"interrupts",
|
|
474
|
+
"observability",
|
|
475
|
+
"streaming",
|
|
476
|
+
"output-schemas",
|
|
477
|
+
"time-travel",
|
|
478
|
+
"agent-protocol"
|
|
479
|
+
]
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// POST /tasks
|
|
484
|
+
async createTask(request: TaskCreate): Promise<Task> {
|
|
485
|
+
// Map to ELSABRO task
|
|
486
|
+
const elsabroTask = await this.taskMapper.fromProtocol(request);
|
|
487
|
+
|
|
488
|
+
// Create in Tasks API
|
|
489
|
+
const taskId = await TaskCreate({
|
|
490
|
+
subject: this.extractSubject(request.input),
|
|
491
|
+
description: request.input,
|
|
492
|
+
metadata: {
|
|
493
|
+
protocol: "agent-protocol",
|
|
494
|
+
additional_input: request.additional_input
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
return this.taskMapper.toProtocol(elsabroTask, taskId);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// GET /tasks
|
|
502
|
+
async listTasks(options: ListOptions): Promise<TaskList> {
|
|
503
|
+
const tasks = await TaskList();
|
|
504
|
+
|
|
505
|
+
// Filter by status if provided
|
|
506
|
+
let filtered = tasks;
|
|
507
|
+
if (options.status) {
|
|
508
|
+
filtered = tasks.filter(t =>
|
|
509
|
+
this.mapStatus(t.status) === options.status
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Pagination
|
|
514
|
+
const offset = options.offset || 0;
|
|
515
|
+
const limit = options.limit || 50;
|
|
516
|
+
const paginated = filtered.slice(offset, offset + limit);
|
|
517
|
+
|
|
518
|
+
return {
|
|
519
|
+
tasks: paginated.map(t => this.taskMapper.toProtocol(t)),
|
|
520
|
+
total: filtered.length,
|
|
521
|
+
has_more: offset + limit < filtered.length
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// GET /tasks/:taskId
|
|
526
|
+
async getTask(taskId: string): Promise<Task | null> {
|
|
527
|
+
const task = await TaskGet({ taskId });
|
|
528
|
+
if (!task) return null;
|
|
529
|
+
return this.taskMapper.toProtocol(task);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// POST /tasks/:taskId/steps
|
|
533
|
+
async executeStep(taskId: string, request: StepRequest): Promise<Step> {
|
|
534
|
+
const task = await TaskGet({ taskId });
|
|
535
|
+
if (!task) throw new NotFoundError('Task not found');
|
|
536
|
+
|
|
537
|
+
// Get current flow state
|
|
538
|
+
const flowState = await this.getFlowState(taskId);
|
|
539
|
+
|
|
540
|
+
// Execute next node in flow
|
|
541
|
+
const result = await FlowEngine.executeNext(flowState, {
|
|
542
|
+
input: request.input,
|
|
543
|
+
additional_input: request.additional_input
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
// Map to protocol step
|
|
547
|
+
const step = this.stepMapper.toProtocol(result, taskId);
|
|
548
|
+
|
|
549
|
+
// Create checkpoint after step
|
|
550
|
+
await CheckpointManager.save({
|
|
551
|
+
type: 'auto',
|
|
552
|
+
reason: `Step ${step.step_id} completed`
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
return step;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// GET /tasks/:taskId/steps
|
|
559
|
+
async listSteps(taskId: string): Promise<StepList> {
|
|
560
|
+
const task = await TaskGet({ taskId });
|
|
561
|
+
if (!task) throw new NotFoundError('Task not found');
|
|
562
|
+
|
|
563
|
+
// Get flow execution history
|
|
564
|
+
const history = await this.getFlowHistory(taskId);
|
|
565
|
+
|
|
566
|
+
return {
|
|
567
|
+
steps: history.map((h, i) => this.stepMapper.toProtocol(h, taskId, i)),
|
|
568
|
+
total: history.length
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// GET /tasks/:taskId/steps/:stepId
|
|
573
|
+
async getStep(taskId: string, stepId: string): Promise<Step | null> {
|
|
574
|
+
const history = await this.getFlowHistory(taskId);
|
|
575
|
+
const step = history.find(h => h.id === stepId);
|
|
576
|
+
if (!step) return null;
|
|
577
|
+
return this.stepMapper.toProtocol(step, taskId);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// POST /tasks/:taskId/artifacts
|
|
581
|
+
async uploadArtifact(
|
|
582
|
+
taskId: string,
|
|
583
|
+
file: Buffer,
|
|
584
|
+
filename: string,
|
|
585
|
+
relativePath?: string
|
|
586
|
+
): Promise<Artifact> {
|
|
587
|
+
const artifact = await this.artifactStore.save(taskId, file, filename, relativePath);
|
|
588
|
+
return artifact;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// GET /tasks/:taskId/artifacts
|
|
592
|
+
async listArtifacts(taskId: string): Promise<ArtifactList> {
|
|
593
|
+
const artifacts = await this.artifactStore.list(taskId);
|
|
594
|
+
return {
|
|
595
|
+
artifacts,
|
|
596
|
+
total: artifacts.length
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// GET /tasks/:taskId/artifacts/:artifactId
|
|
601
|
+
async downloadArtifact(taskId: string, artifactId: string): Promise<Buffer> {
|
|
602
|
+
return this.artifactStore.get(taskId, artifactId);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Helper methods
|
|
606
|
+
private mapStatus(elsabroStatus: string): string {
|
|
607
|
+
const mapping: Record<string, string> = {
|
|
608
|
+
'pending': 'pending',
|
|
609
|
+
'in_progress': 'in_progress',
|
|
610
|
+
'completed': 'completed',
|
|
611
|
+
'failed': 'failed',
|
|
612
|
+
'blocked': 'pending'
|
|
613
|
+
};
|
|
614
|
+
return mapping[elsabroStatus] || 'pending';
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
private extractSubject(input: string): string {
|
|
618
|
+
// Extract first line or first 100 chars
|
|
619
|
+
const firstLine = input.split('\n')[0];
|
|
620
|
+
return firstLine.length > 100 ? firstLine.slice(0, 100) + '...' : firstLine;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
private async getFlowState(taskId: string): Promise<FlowState> {
|
|
624
|
+
// Load flow state from checkpoint or create new
|
|
625
|
+
const checkpoint = await CheckpointManager.getLatest(taskId);
|
|
626
|
+
if (checkpoint?.flow_state) {
|
|
627
|
+
return checkpoint.flow_state;
|
|
628
|
+
}
|
|
629
|
+
return FlowEngine.createState('development-flow');
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
private async getFlowHistory(taskId: string): Promise<FlowHistoryEntry[]> {
|
|
633
|
+
// Load execution history from checkpoints
|
|
634
|
+
const checkpoints = await CheckpointManager.list({ taskId });
|
|
635
|
+
return checkpoints.flatMap(cp => cp.history || []);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
---
|
|
641
|
+
|
|
642
|
+
## Mappers
|
|
643
|
+
|
|
644
|
+
### TaskMapper
|
|
645
|
+
|
|
646
|
+
```typescript
|
|
647
|
+
class TaskMapper {
|
|
648
|
+
// Convert Protocol Task to ELSABRO format
|
|
649
|
+
fromProtocol(protocolTask: TaskCreate): ElsabroTask {
|
|
650
|
+
return {
|
|
651
|
+
subject: this.extractSubject(protocolTask.input),
|
|
652
|
+
description: protocolTask.input,
|
|
653
|
+
metadata: {
|
|
654
|
+
type: 'protocol_task',
|
|
655
|
+
source: 'agent-protocol',
|
|
656
|
+
additional_input: protocolTask.additional_input || {}
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// Convert ELSABRO Task to Protocol format
|
|
662
|
+
toProtocol(elsabroTask: ElsabroTask, taskId?: string): Task {
|
|
663
|
+
return {
|
|
664
|
+
task_id: taskId || elsabroTask.id,
|
|
665
|
+
input: elsabroTask.description,
|
|
666
|
+
additional_input: elsabroTask.metadata?.additional_input || {},
|
|
667
|
+
status: this.mapStatus(elsabroTask.status),
|
|
668
|
+
output: elsabroTask.result || null,
|
|
669
|
+
additional_output: elsabroTask.metadata?.output || {},
|
|
670
|
+
artifacts: [], // Populated separately
|
|
671
|
+
created_at: elsabroTask.created_at,
|
|
672
|
+
updated_at: elsabroTask.updated_at
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
private mapStatus(status: string): TaskStatus {
|
|
677
|
+
const mapping: Record<string, TaskStatus> = {
|
|
678
|
+
'pending': 'pending',
|
|
679
|
+
'in_progress': 'in_progress',
|
|
680
|
+
'completed': 'completed',
|
|
681
|
+
'failed': 'failed',
|
|
682
|
+
'blocked': 'pending',
|
|
683
|
+
'deleted': 'failed'
|
|
684
|
+
};
|
|
685
|
+
return mapping[status] || 'pending';
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
private extractSubject(input: string): string {
|
|
689
|
+
const firstLine = input.split('\n')[0].trim();
|
|
690
|
+
return firstLine.length > 100 ? firstLine.slice(0, 97) + '...' : firstLine;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
### StepMapper
|
|
696
|
+
|
|
697
|
+
```typescript
|
|
698
|
+
class StepMapper {
|
|
699
|
+
// Convert Flow node execution to Protocol Step
|
|
700
|
+
toProtocol(
|
|
701
|
+
flowResult: FlowNodeResult,
|
|
702
|
+
taskId: string,
|
|
703
|
+
index?: number
|
|
704
|
+
): Step {
|
|
705
|
+
return {
|
|
706
|
+
step_id: flowResult.node_id || `step_${index}`,
|
|
707
|
+
task_id: taskId,
|
|
708
|
+
name: flowResult.node_name || `Step ${index + 1}`,
|
|
709
|
+
status: this.mapStatus(flowResult.status),
|
|
710
|
+
input: flowResult.input || '',
|
|
711
|
+
output: flowResult.output || '',
|
|
712
|
+
additional_output: {
|
|
713
|
+
agent: flowResult.agent,
|
|
714
|
+
model: flowResult.model,
|
|
715
|
+
duration_ms: flowResult.duration_ms,
|
|
716
|
+
tokens: flowResult.tokens
|
|
717
|
+
},
|
|
718
|
+
artifacts: flowResult.artifacts || [],
|
|
719
|
+
is_last: flowResult.is_terminal || false,
|
|
720
|
+
created_at: flowResult.started_at,
|
|
721
|
+
completed_at: flowResult.completed_at
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
private mapStatus(status: string): StepStatus {
|
|
726
|
+
const mapping: Record<string, StepStatus> = {
|
|
727
|
+
'pending': 'pending',
|
|
728
|
+
'running': 'running',
|
|
729
|
+
'completed': 'completed',
|
|
730
|
+
'failed': 'failed',
|
|
731
|
+
'skipped': 'completed'
|
|
732
|
+
};
|
|
733
|
+
return mapping[status] || 'pending';
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
---
|
|
739
|
+
|
|
740
|
+
## Artifact Store
|
|
741
|
+
|
|
742
|
+
```typescript
|
|
743
|
+
class ArtifactStore {
|
|
744
|
+
private baseDir: string;
|
|
745
|
+
|
|
746
|
+
constructor(baseDir: string = '.elsabro/artifacts') {
|
|
747
|
+
this.baseDir = baseDir;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
async save(
|
|
751
|
+
taskId: string,
|
|
752
|
+
content: Buffer,
|
|
753
|
+
filename: string,
|
|
754
|
+
relativePath?: string
|
|
755
|
+
): Promise<Artifact> {
|
|
756
|
+
const artifactId = this.generateId();
|
|
757
|
+
const taskDir = path.join(this.baseDir, taskId);
|
|
758
|
+
|
|
759
|
+
// Ensure directory exists
|
|
760
|
+
await fs.mkdir(taskDir, { recursive: true });
|
|
761
|
+
|
|
762
|
+
// Determine final path
|
|
763
|
+
const finalPath = relativePath
|
|
764
|
+
? path.join(taskDir, relativePath, filename)
|
|
765
|
+
: path.join(taskDir, filename);
|
|
766
|
+
|
|
767
|
+
// Ensure subdirectory exists if relativePath provided
|
|
768
|
+
if (relativePath) {
|
|
769
|
+
await fs.mkdir(path.dirname(finalPath), { recursive: true });
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
// Write file
|
|
773
|
+
await fs.writeFile(finalPath, content);
|
|
774
|
+
|
|
775
|
+
// Get content type
|
|
776
|
+
const contentType = this.getContentType(filename);
|
|
777
|
+
|
|
778
|
+
// Create artifact record
|
|
779
|
+
const artifact: Artifact = {
|
|
780
|
+
artifact_id: artifactId,
|
|
781
|
+
file_name: filename,
|
|
782
|
+
relative_path: relativePath || '',
|
|
783
|
+
content_type: contentType,
|
|
784
|
+
size_bytes: content.length,
|
|
785
|
+
created_at: new Date().toISOString()
|
|
786
|
+
};
|
|
787
|
+
|
|
788
|
+
// Save artifact metadata
|
|
789
|
+
await this.saveMetadata(taskId, artifact);
|
|
790
|
+
|
|
791
|
+
return artifact;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
async get(taskId: string, artifactId: string): Promise<Buffer> {
|
|
795
|
+
const metadata = await this.getMetadata(taskId);
|
|
796
|
+
const artifact = metadata.find(a => a.artifact_id === artifactId);
|
|
797
|
+
|
|
798
|
+
if (!artifact) {
|
|
799
|
+
throw new NotFoundError('Artifact not found');
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
const filePath = path.join(
|
|
803
|
+
this.baseDir,
|
|
804
|
+
taskId,
|
|
805
|
+
artifact.relative_path,
|
|
806
|
+
artifact.file_name
|
|
807
|
+
);
|
|
808
|
+
|
|
809
|
+
return fs.readFile(filePath);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
async list(taskId: string): Promise<Artifact[]> {
|
|
813
|
+
return this.getMetadata(taskId);
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
async delete(taskId: string, artifactId: string): Promise<void> {
|
|
817
|
+
const metadata = await this.getMetadata(taskId);
|
|
818
|
+
const artifact = metadata.find(a => a.artifact_id === artifactId);
|
|
819
|
+
|
|
820
|
+
if (!artifact) {
|
|
821
|
+
throw new NotFoundError('Artifact not found');
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
const filePath = path.join(
|
|
825
|
+
this.baseDir,
|
|
826
|
+
taskId,
|
|
827
|
+
artifact.relative_path,
|
|
828
|
+
artifact.file_name
|
|
829
|
+
);
|
|
830
|
+
|
|
831
|
+
await fs.unlink(filePath);
|
|
832
|
+
await this.removeMetadata(taskId, artifactId);
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
private generateId(): string {
|
|
836
|
+
return `art_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
private getContentType(filename: string): string {
|
|
840
|
+
const ext = path.extname(filename).toLowerCase();
|
|
841
|
+
const types: Record<string, string> = {
|
|
842
|
+
'.json': 'application/json',
|
|
843
|
+
'.md': 'text/markdown',
|
|
844
|
+
'.txt': 'text/plain',
|
|
845
|
+
'.ts': 'text/typescript',
|
|
846
|
+
'.js': 'text/javascript',
|
|
847
|
+
'.py': 'text/x-python',
|
|
848
|
+
'.html': 'text/html',
|
|
849
|
+
'.css': 'text/css',
|
|
850
|
+
'.png': 'image/png',
|
|
851
|
+
'.jpg': 'image/jpeg',
|
|
852
|
+
'.gif': 'image/gif',
|
|
853
|
+
'.pdf': 'application/pdf',
|
|
854
|
+
'.zip': 'application/zip'
|
|
855
|
+
};
|
|
856
|
+
return types[ext] || 'application/octet-stream';
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
private async getMetadataPath(taskId: string): Promise<string> {
|
|
860
|
+
return path.join(this.baseDir, taskId, '.artifacts.json');
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
private async getMetadata(taskId: string): Promise<Artifact[]> {
|
|
864
|
+
const metaPath = await this.getMetadataPath(taskId);
|
|
865
|
+
try {
|
|
866
|
+
const content = await fs.readFile(metaPath, 'utf-8');
|
|
867
|
+
return JSON.parse(content);
|
|
868
|
+
} catch {
|
|
869
|
+
return [];
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
private async saveMetadata(taskId: string, artifact: Artifact): Promise<void> {
|
|
874
|
+
const metadata = await this.getMetadata(taskId);
|
|
875
|
+
metadata.push(artifact);
|
|
876
|
+
const metaPath = await this.getMetadataPath(taskId);
|
|
877
|
+
await fs.writeFile(metaPath, JSON.stringify(metadata, null, 2));
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
private async removeMetadata(taskId: string, artifactId: string): Promise<void> {
|
|
881
|
+
const metadata = await this.getMetadata(taskId);
|
|
882
|
+
const filtered = metadata.filter(a => a.artifact_id !== artifactId);
|
|
883
|
+
const metaPath = await this.getMetadataPath(taskId);
|
|
884
|
+
await fs.writeFile(metaPath, JSON.stringify(filtered, null, 2));
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
---
|
|
890
|
+
|
|
891
|
+
## Integración con ELSABRO
|
|
892
|
+
|
|
893
|
+
### Uso desde Comandos
|
|
894
|
+
|
|
895
|
+
```typescript
|
|
896
|
+
// En /elsabro:start - exponer API opcional
|
|
897
|
+
if (config.agentProtocol?.enabled) {
|
|
898
|
+
const server = new AgentProtocolServer(config.agentProtocol);
|
|
899
|
+
await server.start();
|
|
900
|
+
console.log(`Agent Protocol API running on port ${config.agentProtocol.port}`);
|
|
901
|
+
}
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
### Uso como Cliente
|
|
905
|
+
|
|
906
|
+
```typescript
|
|
907
|
+
// Conectar a otro agente que implemente Agent Protocol
|
|
908
|
+
class AgentProtocolClient {
|
|
909
|
+
private baseUrl: string;
|
|
910
|
+
|
|
911
|
+
constructor(baseUrl: string) {
|
|
912
|
+
this.baseUrl = baseUrl;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
async createTask(input: string): Promise<Task> {
|
|
916
|
+
const response = await fetch(`${this.baseUrl}/tasks`, {
|
|
917
|
+
method: 'POST',
|
|
918
|
+
headers: { 'Content-Type': 'application/json' },
|
|
919
|
+
body: JSON.stringify({ input })
|
|
920
|
+
});
|
|
921
|
+
return response.json();
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
async executeStep(taskId: string, input?: string): Promise<Step> {
|
|
925
|
+
const response = await fetch(`${this.baseUrl}/tasks/${taskId}/steps`, {
|
|
926
|
+
method: 'POST',
|
|
927
|
+
headers: { 'Content-Type': 'application/json' },
|
|
928
|
+
body: JSON.stringify({ input })
|
|
929
|
+
});
|
|
930
|
+
return response.json();
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
async runToCompletion(taskId: string): Promise<Task> {
|
|
934
|
+
let step: Step;
|
|
935
|
+
do {
|
|
936
|
+
step = await this.executeStep(taskId);
|
|
937
|
+
} while (!step.is_last);
|
|
938
|
+
|
|
939
|
+
return this.getTask(taskId);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
async getTask(taskId: string): Promise<Task> {
|
|
943
|
+
const response = await fetch(`${this.baseUrl}/tasks/${taskId}`);
|
|
944
|
+
return response.json();
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
async getAgentInfo(): Promise<AgentInfo> {
|
|
948
|
+
const response = await fetch(`${this.baseUrl}/agent`);
|
|
949
|
+
return response.json();
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
```
|
|
953
|
+
|
|
954
|
+
---
|
|
955
|
+
|
|
956
|
+
## WebSocket Streaming (Extensión)
|
|
957
|
+
|
|
958
|
+
Para soporte de streaming en tiempo real:
|
|
959
|
+
|
|
960
|
+
```typescript
|
|
961
|
+
// WebSocket endpoint para streaming de steps
|
|
962
|
+
// ws://localhost:8080/ws/tasks/{taskId}/steps
|
|
963
|
+
|
|
964
|
+
interface StepStreamMessage {
|
|
965
|
+
type: 'step_started' | 'step_progress' | 'step_completed' | 'step_failed';
|
|
966
|
+
task_id: string;
|
|
967
|
+
step_id: string;
|
|
968
|
+
data: {
|
|
969
|
+
progress?: number;
|
|
970
|
+
output_chunk?: string;
|
|
971
|
+
error?: string;
|
|
972
|
+
step?: Step;
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
class AgentProtocolWebSocket {
|
|
977
|
+
private wss: WebSocketServer;
|
|
978
|
+
private connections: Map<string, Set<WebSocket>>;
|
|
979
|
+
|
|
980
|
+
constructor(server: http.Server) {
|
|
981
|
+
this.wss = new WebSocketServer({ server, path: '/ws' });
|
|
982
|
+
this.connections = new Map();
|
|
983
|
+
|
|
984
|
+
this.wss.on('connection', (ws, req) => {
|
|
985
|
+
const taskId = this.extractTaskId(req.url);
|
|
986
|
+
if (taskId) {
|
|
987
|
+
this.subscribe(taskId, ws);
|
|
988
|
+
ws.on('close', () => this.unsubscribe(taskId, ws));
|
|
989
|
+
}
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
subscribe(taskId: string, ws: WebSocket): void {
|
|
994
|
+
if (!this.connections.has(taskId)) {
|
|
995
|
+
this.connections.set(taskId, new Set());
|
|
996
|
+
}
|
|
997
|
+
this.connections.get(taskId)!.add(ws);
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
unsubscribe(taskId: string, ws: WebSocket): void {
|
|
1001
|
+
this.connections.get(taskId)?.delete(ws);
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
broadcast(taskId: string, message: StepStreamMessage): void {
|
|
1005
|
+
const sockets = this.connections.get(taskId);
|
|
1006
|
+
if (sockets) {
|
|
1007
|
+
const data = JSON.stringify(message);
|
|
1008
|
+
sockets.forEach(ws => {
|
|
1009
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
1010
|
+
ws.send(data);
|
|
1011
|
+
}
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
// Emit from StreamManager integration
|
|
1017
|
+
emitProgress(taskId: string, stepId: string, progress: number): void {
|
|
1018
|
+
this.broadcast(taskId, {
|
|
1019
|
+
type: 'step_progress',
|
|
1020
|
+
task_id: taskId,
|
|
1021
|
+
step_id: stepId,
|
|
1022
|
+
data: { progress }
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
emitChunk(taskId: string, stepId: string, chunk: string): void {
|
|
1027
|
+
this.broadcast(taskId, {
|
|
1028
|
+
type: 'step_progress',
|
|
1029
|
+
task_id: taskId,
|
|
1030
|
+
step_id: stepId,
|
|
1031
|
+
data: { output_chunk: chunk }
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
private extractTaskId(url: string | undefined): string | null {
|
|
1036
|
+
if (!url) return null;
|
|
1037
|
+
const match = url.match(/\/tasks\/([^/]+)/);
|
|
1038
|
+
return match ? match[1] : null;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
```
|
|
1042
|
+
|
|
1043
|
+
---
|
|
1044
|
+
|
|
1045
|
+
## Configuración
|
|
1046
|
+
|
|
1047
|
+
```json
|
|
1048
|
+
{
|
|
1049
|
+
"agentProtocol": {
|
|
1050
|
+
"enabled": true,
|
|
1051
|
+
"port": 8080,
|
|
1052
|
+
"host": "localhost",
|
|
1053
|
+
"basePath": "/api/v1",
|
|
1054
|
+
"artifactsDir": ".elsabro/artifacts",
|
|
1055
|
+
"cors": {
|
|
1056
|
+
"enabled": true,
|
|
1057
|
+
"origins": ["*"]
|
|
1058
|
+
},
|
|
1059
|
+
"auth": {
|
|
1060
|
+
"enabled": false,
|
|
1061
|
+
"type": "bearer",
|
|
1062
|
+
"token": null
|
|
1063
|
+
},
|
|
1064
|
+
"websocket": {
|
|
1065
|
+
"enabled": true,
|
|
1066
|
+
"path": "/ws"
|
|
1067
|
+
},
|
|
1068
|
+
"rateLimit": {
|
|
1069
|
+
"enabled": true,
|
|
1070
|
+
"windowMs": 60000,
|
|
1071
|
+
"maxRequests": 100
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
```
|
|
1076
|
+
|
|
1077
|
+
---
|
|
1078
|
+
|
|
1079
|
+
## Compatibilidad
|
|
1080
|
+
|
|
1081
|
+
### Frameworks Compatibles
|
|
1082
|
+
|
|
1083
|
+
| Framework | Versión | Notas |
|
|
1084
|
+
|-----------|---------|-------|
|
|
1085
|
+
| Auto-GPT | 0.5+ | Full compatibility |
|
|
1086
|
+
| BabyAGI | Latest | Full compatibility |
|
|
1087
|
+
| AgentGPT | Latest | Full compatibility |
|
|
1088
|
+
| SuperAGI | Latest | Full compatibility |
|
|
1089
|
+
| Custom Agents | N/A | Implement protocol |
|
|
1090
|
+
|
|
1091
|
+
### Limitaciones Conocidas
|
|
1092
|
+
|
|
1093
|
+
1. **Streaming**: WebSocket es extensión, no parte del protocol estándar
|
|
1094
|
+
2. **Authentication**: No definida en protocol base
|
|
1095
|
+
3. **Batch operations**: No soportadas en protocol estándar
|
|
1096
|
+
4. **Cancellation**: Task cancellation es custom extension
|
|
1097
|
+
|
|
1098
|
+
---
|
|
1099
|
+
|
|
1100
|
+
## Testing
|
|
1101
|
+
|
|
1102
|
+
```bash
|
|
1103
|
+
# Test agent info
|
|
1104
|
+
curl http://localhost:8080/api/v1/agent
|
|
1105
|
+
|
|
1106
|
+
# Create task
|
|
1107
|
+
curl -X POST http://localhost:8080/api/v1/tasks \
|
|
1108
|
+
-H "Content-Type: application/json" \
|
|
1109
|
+
-d '{"input": "Build a login page"}'
|
|
1110
|
+
|
|
1111
|
+
# Execute steps until completion
|
|
1112
|
+
curl -X POST http://localhost:8080/api/v1/tasks/{taskId}/steps
|
|
1113
|
+
|
|
1114
|
+
# List artifacts
|
|
1115
|
+
curl http://localhost:8080/api/v1/tasks/{taskId}/artifacts
|
|
1116
|
+
```
|
|
1117
|
+
|
|
1118
|
+
---
|
|
1119
|
+
|
|
1120
|
+
## Changelog
|
|
1121
|
+
|
|
1122
|
+
- **v3.2.0**: Initial Agent Protocol implementation
|
|
1123
|
+
- Full OpenAPI 3.1 spec
|
|
1124
|
+
- Task/Step/Artifact CRUD
|
|
1125
|
+
- WebSocket streaming extension
|
|
1126
|
+
- Integration with ELSABRO core systems
|