langgraph-agent-common 2.0.0__tar.gz → 2.0.2__tar.gz
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.
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/PKG-INFO +1 -1
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/pyproject.toml +1 -1
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/adaptor/agent_executor.py +24 -14
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/langgraph/validator.py +4 -1
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/resources/static/css/style.css +137 -49
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/resources/static/index.html +7 -24
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/resources/static/js/app.js +212 -104
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_agent_common.egg-info/PKG-INFO +1 -1
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/README.md +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/setup.cfg +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/__init__.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/adaptor/__init__.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/adaptor/conversion.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/adaptor/sanitize_messages_for_llm.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/fastapi_application.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/langgraph/__init__.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/langgraph/checkpointer.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/langgraph/graph.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/langgraph/store.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/resources/openapi_schema.json +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/server.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/tasks/__init__.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/tasks/push_notification_config_store.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/tasks/task_store.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/utils/__init__.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/utils/lock.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/utils/types.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_agent_common.egg-info/SOURCES.txt +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_agent_common.egg-info/dependency_links.txt +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_agent_common.egg-info/requires.txt +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_agent_common.egg-info/top_level.txt +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_aux/__init__.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_aux/callbacks/__init__.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_aux/callbacks/talos_callback_handler.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_aux/utils/__init__.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_aux/utils/stream_output.py +0 -0
- {langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/test/test_deepagents_a2a_server.py +0 -0
|
@@ -4,6 +4,7 @@ from typing import Any, Union
|
|
|
4
4
|
from pydantic import BaseModel
|
|
5
5
|
import asyncio
|
|
6
6
|
import uuid
|
|
7
|
+
from dataclasses import asdict
|
|
7
8
|
from datetime import datetime, timezone
|
|
8
9
|
|
|
9
10
|
from google.protobuf.json_format import MessageToDict
|
|
@@ -91,13 +92,8 @@ class GraphAgentExecutor(AgentExecutor):
|
|
|
91
92
|
if current_interrupts:
|
|
92
93
|
current_interrupt_ids = [c.id for c in current_interrupts]
|
|
93
94
|
if isinstance(langgraph_message.content, list) and len(current_interrupts) == len(langgraph_message.content) and all([isinstance(part, dict) and part.get("type") == "non_standard" and validate_HITLResponse(part.get("value")) for part in langgraph_message.content]):
|
|
94
|
-
|
|
95
|
-
if set(current_interrupt_ids)
|
|
96
|
-
resume_decisions = []
|
|
97
|
-
for hitl_id in current_interrupt_ids:
|
|
98
|
-
resume_decisions.append(decisions[hitl_id])
|
|
99
|
-
resume_content = {"decisions": resume_decisions}
|
|
100
|
-
else:
|
|
95
|
+
resume_content = {part.get("value", {}).get("hitl_id"): {"decisions": part.get("value", {}).get("decisions")} for part in langgraph_message.content}
|
|
96
|
+
if set(current_interrupt_ids) != set(resume_content.keys()):
|
|
101
97
|
raise ValueError(f"Interrupt resume content: {langgraph_message.content}. Must contain overall original decision ids {current_interrupt_ids}.")
|
|
102
98
|
else:
|
|
103
99
|
raise ValueError(f"Invalid interrupt resume content: {langgraph_message.content}. Must be a list with the same length as interrupt ids: {current_interrupt_ids}. Each item in the list must be a data with HITLResponse schema: {HITLResponseModel.schema()}.")
|
|
@@ -123,7 +119,9 @@ class GraphAgentExecutor(AgentExecutor):
|
|
|
123
119
|
finally:
|
|
124
120
|
self.run_controls.pop(task_id, None)
|
|
125
121
|
|
|
126
|
-
async def _get_interrupts(self, state: StateSnapshot, subgraphs: bool, seen_ids: set[str] =
|
|
122
|
+
async def _get_interrupts(self, state: StateSnapshot, subgraphs: bool, seen_ids: set[str] = None) -> list[Interrupt]:
|
|
123
|
+
if seen_ids is None:
|
|
124
|
+
seen_ids = set()
|
|
127
125
|
interrupts = []
|
|
128
126
|
for interrupt in state.interrupts:
|
|
129
127
|
if interrupt.id not in seen_ids:
|
|
@@ -175,6 +173,10 @@ class GraphAgentExecutor(AgentExecutor):
|
|
|
175
173
|
parts.append(langgraph_part_to_a2a({"type": "non_standard", "value": part}))
|
|
176
174
|
elif isinstance(part, BaseModel):
|
|
177
175
|
parts.append(langgraph_part_to_a2a({"type": "non_standard", "value": part.model_dump()}))
|
|
176
|
+
elif hasattr(part, "DESCRIPTOR"):
|
|
177
|
+
parts.append(langgraph_part_to_a2a({"type": "non_standard", "value": MessageToDict(part)}))
|
|
178
|
+
elif hasattr(type(part), "__dataclass_fields__"):
|
|
179
|
+
parts.append(langgraph_part_to_a2a({"type": "non_standard", "value": asdict(part)}))
|
|
178
180
|
else:
|
|
179
181
|
raise ValueError(f"Unsupported type of artifact part {part}.")
|
|
180
182
|
if k in appended_artifacts:
|
|
@@ -185,6 +187,10 @@ class GraphAgentExecutor(AgentExecutor):
|
|
|
185
187
|
parts = [langgraph_part_to_a2a({"type": "non_standard", "value": v})]
|
|
186
188
|
elif isinstance(v, BaseModel):
|
|
187
189
|
parts = [langgraph_part_to_a2a({"type": "non_standard", "value": v.model_dump()})]
|
|
190
|
+
elif hasattr(v, "DESCRIPTOR"):
|
|
191
|
+
parts = [langgraph_part_to_a2a({"type": "non_standard", "value": MessageToDict(v)})]
|
|
192
|
+
elif hasattr(type(v), "__dataclass_fields__"):
|
|
193
|
+
parts = [langgraph_part_to_a2a({"type": "non_standard", "value": asdict(v)})]
|
|
188
194
|
else:
|
|
189
195
|
raise ValueError(f"Unsupported type of artifact: {k}:{v}")
|
|
190
196
|
|
|
@@ -226,11 +232,6 @@ class GraphAgentExecutor(AgentExecutor):
|
|
|
226
232
|
yield pre_yield
|
|
227
233
|
pre_yield = None
|
|
228
234
|
if step == "__interrupt__":
|
|
229
|
-
graph_status = TASK_STATE_INPUT_REQUIRED
|
|
230
|
-
pre_yield = {
|
|
231
|
-
"messages": [AIMessage(content=any_content_to_langgraph([{"hitl_id": interrupt.id, "content": interrupt.value} for interrupt in update]))],
|
|
232
|
-
"graph_status": graph_status,
|
|
233
|
-
}
|
|
234
235
|
break_out = True
|
|
235
236
|
else:
|
|
236
237
|
messages = self._normalize_messages(update.get("messages"))
|
|
@@ -247,7 +248,16 @@ class GraphAgentExecutor(AgentExecutor):
|
|
|
247
248
|
"graph_status": graph_status,
|
|
248
249
|
}
|
|
249
250
|
else:
|
|
250
|
-
|
|
251
|
+
current_state_after = await self.graph_with_ck.aget_state(config, subgraphs=subgraphs)
|
|
252
|
+
current_interrupts_after = await self._get_interrupts(current_state_after, subgraphs)
|
|
253
|
+
if not current_interrupts_after:
|
|
254
|
+
raise RuntimeError(f"__interrupt__ step encountered but no pending interrupts found in state.")
|
|
255
|
+
graph_status = TASK_STATE_INPUT_REQUIRED
|
|
256
|
+
yield {
|
|
257
|
+
"messages": [AIMessage(content=any_content_to_langgraph([{"hitl_id": interrupt.id, "content": interrupt.value} for interrupt in current_interrupts_after]))],
|
|
258
|
+
"graph_status": graph_status,
|
|
259
|
+
}
|
|
260
|
+
|
|
251
261
|
|
|
252
262
|
except GraphRecursionError as e:
|
|
253
263
|
if pre_yield is not None:
|
|
@@ -27,11 +27,14 @@ class RespondDecision(BaseModel):
|
|
|
27
27
|
message: str
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
Decision = ApproveDecision | EditDecision | RejectDecision | RespondDecision
|
|
31
|
+
|
|
32
|
+
|
|
30
33
|
class HITLResponseModel(BaseModel):
|
|
31
34
|
model_config = ConfigDict(extra="forbid")
|
|
32
35
|
|
|
33
36
|
hitl_id: str
|
|
34
|
-
|
|
37
|
+
decisions: list[Decision]
|
|
35
38
|
|
|
36
39
|
|
|
37
40
|
def validate_HITLResponse(payload: Any) -> bool:
|
|
@@ -310,68 +310,172 @@ textarea:focus {
|
|
|
310
310
|
color: var(--warning);
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
-
.hitl-
|
|
313
|
+
.hitl-header-actions {
|
|
314
|
+
display: flex;
|
|
315
|
+
align-items: center;
|
|
316
|
+
gap: 8px;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.hitl-progress-label {
|
|
320
|
+
font-size: 12px;
|
|
321
|
+
color: var(--text-secondary);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.hitl-cards-container {
|
|
314
325
|
display: flex;
|
|
315
326
|
flex-direction: column;
|
|
316
327
|
gap: 12px;
|
|
317
328
|
}
|
|
318
329
|
|
|
319
|
-
.hitl-
|
|
320
|
-
|
|
330
|
+
.hitl-card {
|
|
331
|
+
background: var(--bg-tertiary);
|
|
332
|
+
border: 1px solid var(--border);
|
|
333
|
+
border-radius: 8px;
|
|
334
|
+
padding: 12px;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.hitl-card-header {
|
|
338
|
+
display: flex;
|
|
339
|
+
align-items: center;
|
|
340
|
+
gap: 10px;
|
|
341
|
+
margin-bottom: 10px;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
.hitl-card-title {
|
|
345
|
+
font-size: 14px;
|
|
346
|
+
font-weight: 600;
|
|
347
|
+
color: var(--warning);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.hitl-card-id {
|
|
351
|
+
font-size: 11px;
|
|
352
|
+
font-family: monospace;
|
|
321
353
|
color: var(--text-secondary);
|
|
322
|
-
|
|
354
|
+
background: var(--bg-primary);
|
|
355
|
+
padding: 2px 6px;
|
|
356
|
+
border-radius: 3px;
|
|
323
357
|
}
|
|
324
358
|
|
|
325
|
-
.
|
|
359
|
+
.hitl-card-status {
|
|
360
|
+
margin-left: auto;
|
|
361
|
+
font-size: 12px;
|
|
362
|
+
color: var(--text-secondary);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.hitl-card-status.decided {
|
|
366
|
+
color: var(--success);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.hitl-card-actions {
|
|
370
|
+
margin-bottom: 10px;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.hitl-card-actions h6 {
|
|
374
|
+
font-size: 12px;
|
|
375
|
+
color: var(--text-secondary);
|
|
376
|
+
margin-bottom: 6px;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.hitl-action-block {
|
|
380
|
+
padding: 10px 0;
|
|
381
|
+
border-bottom: 1px solid var(--border);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
.hitl-action-block:last-child {
|
|
385
|
+
border-bottom: none;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.hitl-action-item {
|
|
326
389
|
background: var(--bg-primary);
|
|
327
|
-
padding: 12px;
|
|
328
390
|
border-radius: 4px;
|
|
391
|
+
padding: 8px;
|
|
392
|
+
margin-bottom: 6px;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.hitl-action-name {
|
|
396
|
+
font-size: 13px;
|
|
397
|
+
font-weight: 500;
|
|
398
|
+
color: var(--accent);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
.hitl-action-args {
|
|
329
402
|
font-family: 'Monaco', 'Menlo', monospace;
|
|
330
|
-
font-size:
|
|
331
|
-
|
|
332
|
-
|
|
403
|
+
font-size: 11px;
|
|
404
|
+
color: var(--text-secondary);
|
|
405
|
+
margin-top: 4px;
|
|
333
406
|
white-space: pre-wrap;
|
|
334
407
|
word-break: break-word;
|
|
335
408
|
}
|
|
336
409
|
|
|
337
|
-
.hitl-decisions {
|
|
410
|
+
.hitl-card-decisions {
|
|
338
411
|
display: flex;
|
|
339
412
|
gap: 8px;
|
|
340
413
|
margin-bottom: 8px;
|
|
414
|
+
flex-wrap: wrap;
|
|
341
415
|
}
|
|
342
416
|
|
|
343
|
-
.hitl-
|
|
344
|
-
|
|
345
|
-
align-items: center;
|
|
346
|
-
justify-content: space-between;
|
|
347
|
-
margin-bottom: 12px;
|
|
348
|
-
padding: 8px;
|
|
349
|
-
background: var(--bg-primary);
|
|
350
|
-
border-radius: 4px;
|
|
417
|
+
.hitl-card-form {
|
|
418
|
+
margin-top: 8px;
|
|
351
419
|
}
|
|
352
420
|
|
|
353
|
-
.hitl-
|
|
354
|
-
|
|
355
|
-
|
|
421
|
+
.hitl-card-form.hidden {
|
|
422
|
+
display: none;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.hitl-card-input {
|
|
426
|
+
width: 100%;
|
|
427
|
+
padding: 8px;
|
|
428
|
+
background: var(--bg-secondary);
|
|
356
429
|
border: 1px solid var(--border);
|
|
357
430
|
border-radius: 4px;
|
|
358
431
|
color: var(--text-primary);
|
|
359
|
-
|
|
432
|
+
font-family: 'Monaco', 'Menlo', monospace;
|
|
360
433
|
font-size: 12px;
|
|
434
|
+
resize: vertical;
|
|
361
435
|
}
|
|
362
436
|
|
|
363
|
-
.hitl-
|
|
364
|
-
|
|
437
|
+
.hitl-card-edit {
|
|
438
|
+
margin-top: 8px;
|
|
365
439
|
}
|
|
366
440
|
|
|
367
|
-
.hitl-
|
|
368
|
-
|
|
369
|
-
cursor: not-allowed;
|
|
441
|
+
.hitl-card-edit.hidden {
|
|
442
|
+
display: none;
|
|
370
443
|
}
|
|
371
444
|
|
|
372
|
-
.hitl-
|
|
373
|
-
font-size:
|
|
445
|
+
.hitl-card-edit h6 {
|
|
446
|
+
font-size: 12px;
|
|
374
447
|
color: var(--text-secondary);
|
|
448
|
+
margin-bottom: 4px;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.hitl-card-edit-input {
|
|
452
|
+
width: 100%;
|
|
453
|
+
padding: 8px;
|
|
454
|
+
background: var(--bg-secondary);
|
|
455
|
+
border: 1px solid var(--border);
|
|
456
|
+
border-radius: 4px;
|
|
457
|
+
color: var(--text-primary);
|
|
458
|
+
font-family: 'Monaco', 'Menlo', monospace;
|
|
459
|
+
font-size: 12px;
|
|
460
|
+
resize: vertical;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
.json-display {
|
|
464
|
+
background: var(--bg-primary);
|
|
465
|
+
padding: 12px;
|
|
466
|
+
border-radius: 4px;
|
|
467
|
+
font-family: 'Monaco', 'Menlo', monospace;
|
|
468
|
+
font-size: 12px;
|
|
469
|
+
max-height: 200px;
|
|
470
|
+
overflow: auto;
|
|
471
|
+
white-space: pre-wrap;
|
|
472
|
+
word-break: break-word;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
.hitl-decisions {
|
|
476
|
+
display: flex;
|
|
477
|
+
gap: 8px;
|
|
478
|
+
margin-bottom: 8px;
|
|
375
479
|
}
|
|
376
480
|
|
|
377
481
|
.hitl-btn {
|
|
@@ -395,6 +499,10 @@ textarea:focus {
|
|
|
395
499
|
background: var(--accent);
|
|
396
500
|
}
|
|
397
501
|
|
|
502
|
+
.hitl-btn.edit-btn {
|
|
503
|
+
background: var(--warning);
|
|
504
|
+
}
|
|
505
|
+
|
|
398
506
|
.hitl-btn:hover {
|
|
399
507
|
opacity: 0.9;
|
|
400
508
|
}
|
|
@@ -403,27 +511,7 @@ textarea:focus {
|
|
|
403
511
|
box-shadow: 0 0 0 2px white;
|
|
404
512
|
}
|
|
405
513
|
|
|
406
|
-
#hitlResponseForm {
|
|
407
|
-
margin-top: 8px;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
#hitlResponseForm.hidden {
|
|
411
|
-
display: none;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
#hitlEditSection {
|
|
415
|
-
margin-top: 8px;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
#hitlEditSection.hidden {
|
|
419
|
-
display: none;
|
|
420
|
-
}
|
|
421
514
|
|
|
422
|
-
#hitlEditSection h6 {
|
|
423
|
-
font-size: 12px;
|
|
424
|
-
color: var(--text-secondary);
|
|
425
|
-
margin-bottom: 4px;
|
|
426
|
-
}
|
|
427
515
|
|
|
428
516
|
.chat-input-container {
|
|
429
517
|
padding: 12px 16px;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>A2A Chat UI</title>
|
|
7
|
-
<link rel="stylesheet" href="static/css/style.css?v=
|
|
7
|
+
<link rel="stylesheet" href="static/css/style.css?v=6">
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
10
10
|
<div class="app-container">
|
|
@@ -69,30 +69,13 @@
|
|
|
69
69
|
<div id="hitlPanel" class="hitl-panel hidden">
|
|
70
70
|
<div class="hitl-header">
|
|
71
71
|
<h4>Input Required (HITL)</h4>
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
<h5>Agent Response Parts:</h5>
|
|
77
|
-
<pre id="hitlPartsJson" class="json-display"></pre>
|
|
78
|
-
</div>
|
|
79
|
-
<div class="hitl-section">
|
|
80
|
-
<h5>HITL Response:</h5>
|
|
81
|
-
<div class="hitl-decisions">
|
|
82
|
-
<button class="hitl-btn approve-btn" data-type="approve">Approve</button>
|
|
83
|
-
<button class="hitl-btn reject-btn" data-type="reject">Reject</button>
|
|
84
|
-
<button class="hitl-btn respond-btn" data-type="respond">Respond</button>
|
|
85
|
-
</div>
|
|
86
|
-
<div id="hitlResponseForm" class="hidden">
|
|
87
|
-
<textarea id="hitlResponseInput" rows="3" placeholder="Enter response message..."></textarea>
|
|
88
|
-
<div id="hitlEditSection" class="hidden">
|
|
89
|
-
<h6>Edited Action (JSON):</h6>
|
|
90
|
-
<textarea id="hitlEditInput" rows="4" placeholder='{"name": "tool_name", "args": {}}'></textarea>
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
93
|
-
<button id="submitHitlBtn" class="btn-primary hidden">Submit Response</button>
|
|
72
|
+
<div class="hitl-header-actions">
|
|
73
|
+
<span id="hitlProgressLabel" class="hitl-progress-label"></span>
|
|
74
|
+
<button id="submitAllHitlBtn" class="btn-primary" disabled>Submit All</button>
|
|
75
|
+
<button id="closeHitlBtn" class="btn-small">Close</button>
|
|
94
76
|
</div>
|
|
95
77
|
</div>
|
|
78
|
+
<div id="hitlCardsContainer" class="hitl-cards-container"></div>
|
|
96
79
|
</div>
|
|
97
80
|
|
|
98
81
|
<div class="chat-input-container">
|
|
@@ -102,6 +85,6 @@
|
|
|
102
85
|
</main>
|
|
103
86
|
</div>
|
|
104
87
|
|
|
105
|
-
<script src="static/js/app.js?v=
|
|
88
|
+
<script src="static/js/app.js?v=6"></script>
|
|
106
89
|
</body>
|
|
107
90
|
</html>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
currentTaskId: null,
|
|
8
8
|
isSending: false,
|
|
9
9
|
hitlState: null,
|
|
10
|
-
|
|
10
|
+
hitlDecisions: {},
|
|
11
11
|
abortController: null,
|
|
12
12
|
};
|
|
13
13
|
|
|
@@ -42,12 +42,9 @@
|
|
|
42
42
|
elements.clearChatBtn = document.getElementById('clearChatBtn');
|
|
43
43
|
elements.exportChatBtn = document.getElementById('exportChatBtn');
|
|
44
44
|
elements.hitlPanel = document.getElementById('hitlPanel');
|
|
45
|
-
elements.
|
|
46
|
-
elements.
|
|
47
|
-
elements.
|
|
48
|
-
elements.hitlEditSection = document.getElementById('hitlEditSection');
|
|
49
|
-
elements.hitlEditInput = document.getElementById('hitlEditInput');
|
|
50
|
-
elements.submitHitlBtn = document.getElementById('submitHitlBtn');
|
|
45
|
+
elements.hitlCardsContainer = document.getElementById('hitlCardsContainer');
|
|
46
|
+
elements.submitAllHitlBtn = document.getElementById('submitAllHitlBtn');
|
|
47
|
+
elements.hitlProgressLabel = document.getElementById('hitlProgressLabel');
|
|
51
48
|
elements.closeHitlBtn = document.getElementById('closeHitlBtn');
|
|
52
49
|
}
|
|
53
50
|
|
|
@@ -67,11 +64,7 @@
|
|
|
67
64
|
elements.clearChatBtn.addEventListener('click', clearChat);
|
|
68
65
|
elements.exportChatBtn.addEventListener('click', exportChat);
|
|
69
66
|
elements.closeHitlBtn.addEventListener('click', () => elements.hitlPanel.classList.add('hidden'));
|
|
70
|
-
|
|
71
|
-
document.querySelectorAll('.hitl-btn').forEach(btn => {
|
|
72
|
-
btn.addEventListener('click', () => selectHitlType(btn.dataset.type));
|
|
73
|
-
});
|
|
74
|
-
elements.submitHitlBtn.addEventListener('click', submitHitlResponse);
|
|
67
|
+
elements.submitAllHitlBtn.addEventListener('click', submitAllHitlResponses);
|
|
75
68
|
}
|
|
76
69
|
|
|
77
70
|
function setApiBaseUrl() {
|
|
@@ -116,6 +109,7 @@
|
|
|
116
109
|
renderChatHistory();
|
|
117
110
|
elements.hitlPanel.classList.add('hidden');
|
|
118
111
|
state.hitlState = null;
|
|
112
|
+
state.hitlDecisions = {};
|
|
119
113
|
}
|
|
120
114
|
}
|
|
121
115
|
|
|
@@ -232,6 +226,7 @@
|
|
|
232
226
|
removeLoadingMessage();
|
|
233
227
|
elements.hitlPanel.classList.add('hidden');
|
|
234
228
|
state.hitlState = null;
|
|
229
|
+
state.hitlDecisions = {};
|
|
235
230
|
state.isSending = false;
|
|
236
231
|
state.currentTaskId = null;
|
|
237
232
|
const context = getCurrentContext();
|
|
@@ -290,6 +285,9 @@
|
|
|
290
285
|
}
|
|
291
286
|
const status = event.statusUpdate?.status || event.task?.status;
|
|
292
287
|
if (status?.message?.parts) {
|
|
288
|
+
if (status.message.role === 'ROLE_USER') {
|
|
289
|
+
return event;
|
|
290
|
+
}
|
|
293
291
|
const displayParts = status.message.parts.filter(p => !(p.data && p.data.type === 'tool_result') && !p.url && !p.raw);
|
|
294
292
|
const text = displayParts.map(p => p.text || (p.data && JSON.stringify(p.data, null, 2)) || '').filter(Boolean).join('\n');
|
|
295
293
|
if (text) updateLoadingMessage(text);
|
|
@@ -430,6 +428,7 @@
|
|
|
430
428
|
context.taskId = null;
|
|
431
429
|
elements.hitlPanel.classList.add('hidden');
|
|
432
430
|
state.hitlState = null;
|
|
431
|
+
state.hitlDecisions = {};
|
|
433
432
|
}
|
|
434
433
|
|
|
435
434
|
updateContextDisplay();
|
|
@@ -446,137 +445,243 @@
|
|
|
446
445
|
|
|
447
446
|
function showHitlPanel(task) {
|
|
448
447
|
state.hitlState = task;
|
|
449
|
-
state.
|
|
448
|
+
state.hitlDecisions = {}; // Map: hitl_id -> decision object
|
|
450
449
|
|
|
451
450
|
const parts = task.status?.message?.parts || task.artifacts?.flatMap(a => a.parts) || [];
|
|
452
451
|
const interruptParts = parts.filter(p => p.data && p.data.hitl_id);
|
|
453
452
|
|
|
454
453
|
state.hitlState.interruptParts = interruptParts;
|
|
455
|
-
state.hitlState.currentInterruptIndex = 0;
|
|
456
454
|
|
|
457
|
-
elements.
|
|
455
|
+
elements.hitlCardsContainer.innerHTML = '';
|
|
458
456
|
|
|
459
|
-
if (interruptParts.length
|
|
460
|
-
|
|
457
|
+
if (interruptParts.length === 0) {
|
|
458
|
+
// Fallback: show raw parts JSON
|
|
459
|
+
const fallbackCard = document.createElement('div');
|
|
460
|
+
fallbackCard.className = 'hitl-card';
|
|
461
|
+
fallbackCard.innerHTML = `
|
|
462
|
+
<div class="hitl-card-header"><span class="hitl-card-title">Raw Parts</span></div>
|
|
463
|
+
<pre class="json-display">${JSON.stringify(parts, null, 2)}</pre>
|
|
464
|
+
`;
|
|
465
|
+
elements.hitlCardsContainer.appendChild(fallbackCard);
|
|
466
|
+
} else {
|
|
467
|
+
interruptParts.forEach((part, index) => {
|
|
468
|
+
const card = createHitlCard(part, index);
|
|
469
|
+
elements.hitlCardsContainer.appendChild(card);
|
|
470
|
+
});
|
|
461
471
|
}
|
|
462
472
|
|
|
473
|
+
updateHitlProgress();
|
|
463
474
|
elements.hitlPanel.classList.remove('hidden');
|
|
464
|
-
elements.hitlResponseForm.classList.add('hidden');
|
|
465
|
-
elements.submitHitlBtn.classList.add('hidden');
|
|
466
|
-
elements.hitlEditSection.classList.add('hidden');
|
|
467
|
-
|
|
468
|
-
document.querySelectorAll('.hitl-btn').forEach(btn => btn.classList.remove('active'));
|
|
469
475
|
}
|
|
470
476
|
|
|
471
|
-
function
|
|
472
|
-
const
|
|
473
|
-
const
|
|
477
|
+
function createHitlCard(part, index) {
|
|
478
|
+
const hitlId = part.data.hitl_id;
|
|
479
|
+
const content = part.data.content || {};
|
|
480
|
+
const actionRequests = content.action_requests || [];
|
|
481
|
+
const reviewConfigs = content.review_configs || [];
|
|
474
482
|
|
|
475
|
-
|
|
483
|
+
const card = document.createElement('div');
|
|
484
|
+
card.className = 'hitl-card';
|
|
485
|
+
card.dataset.hitlId = hitlId;
|
|
486
|
+
card.dataset.index = index;
|
|
476
487
|
|
|
477
|
-
const
|
|
478
|
-
|
|
479
|
-
|
|
488
|
+
const header = document.createElement('div');
|
|
489
|
+
header.className = 'hitl-card-header';
|
|
490
|
+
header.innerHTML = `
|
|
491
|
+
<span class="hitl-card-title">HITL #${index + 1}</span>
|
|
492
|
+
<span class="hitl-card-id">${hitlId}</span>
|
|
493
|
+
<span class="hitl-card-status" id="cardStatus_${index}">⏳ 0/${actionRequests.length || 1}</span>
|
|
494
|
+
`;
|
|
495
|
+
card.appendChild(header);
|
|
480
496
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
497
|
+
if (actionRequests.length === 0) {
|
|
498
|
+
const allowedDecisions = ['approve', 'reject', 'respond'];
|
|
499
|
+
const actionBlock = createActionBlock(hitlId, index, 0, null, allowedDecisions);
|
|
500
|
+
card.appendChild(actionBlock);
|
|
501
|
+
} else {
|
|
502
|
+
actionRequests.forEach((action, actionIdx) => {
|
|
503
|
+
const config = reviewConfigs[actionIdx] || reviewConfigs[0] || {};
|
|
504
|
+
const allowedDecisions = config.allowed_decisions || ['approve', 'reject', 'respond'];
|
|
505
|
+
const actionBlock = createActionBlock(hitlId, index, actionIdx, action, allowedDecisions);
|
|
506
|
+
card.appendChild(actionBlock);
|
|
507
|
+
});
|
|
508
|
+
}
|
|
484
509
|
|
|
485
|
-
|
|
510
|
+
return card;
|
|
511
|
+
}
|
|
486
512
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
<button class="hitl-nav-btn" id="nextInterruptBtn" ${currentIndex === interruptParts.length - 1 ? 'disabled' : ''}>Next</button>
|
|
492
|
-
</div>
|
|
493
|
-
`;
|
|
513
|
+
function createActionBlock(hitlId, cardIndex, actionIdx, action, allowedDecisions) {
|
|
514
|
+
const blockId = `${cardIndex}_${actionIdx}`;
|
|
515
|
+
const block = document.createElement('div');
|
|
516
|
+
block.className = 'hitl-action-block';
|
|
494
517
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
518
|
+
if (action) {
|
|
519
|
+
block.innerHTML += `
|
|
520
|
+
<div class="hitl-action-item">
|
|
521
|
+
<span class="hitl-action-name">${action.name}</span>
|
|
522
|
+
<pre class="hitl-action-args">${JSON.stringify(action.args, null, 2)}</pre>
|
|
523
|
+
</div>
|
|
524
|
+
`;
|
|
501
525
|
}
|
|
502
526
|
|
|
503
|
-
document.
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
}
|
|
527
|
+
const decisionsDiv = document.createElement('div');
|
|
528
|
+
decisionsDiv.className = 'hitl-card-decisions';
|
|
529
|
+
allowedDecisions.forEach(type => {
|
|
530
|
+
const btn = document.createElement('button');
|
|
531
|
+
btn.className = `hitl-btn ${type}-btn`;
|
|
532
|
+
btn.dataset.type = type;
|
|
533
|
+
btn.dataset.blockId = blockId;
|
|
534
|
+
btn.textContent = type.charAt(0).toUpperCase() + type.slice(1);
|
|
535
|
+
btn.addEventListener('click', () => selectActionDecision(hitlId, cardIndex, actionIdx, type, block));
|
|
536
|
+
decisionsDiv.appendChild(btn);
|
|
508
537
|
});
|
|
538
|
+
block.appendChild(decisionsDiv);
|
|
539
|
+
|
|
540
|
+
const formDiv = document.createElement('div');
|
|
541
|
+
formDiv.className = 'hitl-card-form hidden';
|
|
542
|
+
formDiv.id = `actionForm_${blockId}`;
|
|
543
|
+
formDiv.innerHTML = `
|
|
544
|
+
<textarea class="hitl-card-input" id="actionInput_${blockId}" rows="2" placeholder="Enter message..."></textarea>
|
|
545
|
+
<div class="hitl-card-edit hidden" id="actionEdit_${blockId}">
|
|
546
|
+
<h6>Edited Action (JSON):</h6>
|
|
547
|
+
<textarea class="hitl-card-edit-input" id="actionEditInput_${blockId}" rows="3" placeholder='{"name": "tool_name", "args": {}}'></textarea>
|
|
548
|
+
</div>
|
|
549
|
+
`;
|
|
550
|
+
block.appendChild(formDiv);
|
|
509
551
|
|
|
510
|
-
|
|
511
|
-
if (state.hitlState.currentInterruptIndex < interruptParts.length - 1) {
|
|
512
|
-
state.hitlState.currentInterruptIndex++;
|
|
513
|
-
updateInterruptDisplay();
|
|
514
|
-
}
|
|
515
|
-
});
|
|
552
|
+
return block;
|
|
516
553
|
}
|
|
517
554
|
|
|
518
|
-
function
|
|
519
|
-
|
|
520
|
-
document.querySelectorAll('.hitl-btn').forEach(btn => {
|
|
555
|
+
function selectActionDecision(hitlId, cardIndex, actionIdx, type, block) {
|
|
556
|
+
block.querySelectorAll('.hitl-btn').forEach(btn => {
|
|
521
557
|
btn.classList.toggle('active', btn.dataset.type === type);
|
|
522
558
|
});
|
|
523
559
|
|
|
524
|
-
|
|
525
|
-
|
|
560
|
+
const blockId = `${cardIndex}_${actionIdx}`;
|
|
561
|
+
const form = document.getElementById(`actionForm_${blockId}`);
|
|
562
|
+
const input = document.getElementById(`actionInput_${blockId}`);
|
|
563
|
+
const editSection = document.getElementById(`actionEdit_${blockId}`);
|
|
526
564
|
|
|
527
565
|
if (type === 'approve') {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
elements.hitlEditSection.classList.add('hidden');
|
|
566
|
+
form.classList.add('hidden');
|
|
567
|
+
editSection.classList.add('hidden');
|
|
531
568
|
} else if (type === 'reject') {
|
|
532
|
-
|
|
533
|
-
|
|
569
|
+
form.classList.remove('hidden');
|
|
570
|
+
input.placeholder = 'Rejection reason (optional)...';
|
|
571
|
+
editSection.classList.add('hidden');
|
|
534
572
|
} else if (type === 'respond') {
|
|
535
|
-
|
|
536
|
-
|
|
573
|
+
form.classList.remove('hidden');
|
|
574
|
+
input.placeholder = 'Response message...';
|
|
575
|
+
editSection.classList.add('hidden');
|
|
576
|
+
} else if (type === 'edit') {
|
|
577
|
+
form.classList.remove('hidden');
|
|
578
|
+
input.placeholder = 'Edit message (optional)...';
|
|
579
|
+
editSection.classList.remove('hidden');
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
if (!state.hitlDecisions[hitlId]) {
|
|
583
|
+
state.hitlDecisions[hitlId] = {};
|
|
584
|
+
}
|
|
585
|
+
state.hitlDecisions[hitlId][actionIdx] = { type, blockId };
|
|
586
|
+
|
|
587
|
+
const interruptPart = state.hitlState.interruptParts.find(p => p.data.hitl_id === hitlId);
|
|
588
|
+
const totalActions = (interruptPart.data.content?.action_requests || []).length || 1;
|
|
589
|
+
const decidedCount = Object.keys(state.hitlDecisions[hitlId]).length;
|
|
590
|
+
const statusEl = document.getElementById(`cardStatus_${cardIndex}`);
|
|
591
|
+
if (statusEl) {
|
|
592
|
+
if (decidedCount >= totalActions) {
|
|
593
|
+
statusEl.textContent = `✓ ${decidedCount}/${totalActions}`;
|
|
594
|
+
statusEl.className = 'hitl-card-status decided';
|
|
595
|
+
} else {
|
|
596
|
+
statusEl.textContent = `⏳ ${decidedCount}/${totalActions}`;
|
|
597
|
+
statusEl.className = 'hitl-card-status';
|
|
598
|
+
}
|
|
537
599
|
}
|
|
600
|
+
|
|
601
|
+
updateHitlProgress();
|
|
538
602
|
}
|
|
539
603
|
|
|
540
|
-
function
|
|
541
|
-
|
|
604
|
+
function updateHitlProgress() {
|
|
605
|
+
const interruptParts = state.hitlState?.interruptParts || [];
|
|
606
|
+
let totalActions = 0;
|
|
607
|
+
let decidedActions = 0;
|
|
608
|
+
interruptParts.forEach(p => {
|
|
609
|
+
const actions = (p.data.content?.action_requests || []).length || 1;
|
|
610
|
+
totalActions += actions;
|
|
611
|
+
const cardDecisions = state.hitlDecisions[p.data.hitl_id];
|
|
612
|
+
if (cardDecisions) {
|
|
613
|
+
decidedActions += Object.keys(cardDecisions).length;
|
|
614
|
+
}
|
|
615
|
+
});
|
|
542
616
|
|
|
543
|
-
|
|
544
|
-
|
|
617
|
+
elements.hitlProgressLabel.textContent = `${decidedActions}/${totalActions} decided`;
|
|
618
|
+
elements.submitAllHitlBtn.disabled = decidedActions < totalActions;
|
|
619
|
+
}
|
|
545
620
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
621
|
+
function submitAllHitlResponses() {
|
|
622
|
+
if (!state.hitlState) return;
|
|
550
623
|
|
|
551
|
-
const
|
|
552
|
-
const currentPart = interruptParts[currentIndex];
|
|
553
|
-
const hitlId = currentPart.data.hitl_id;
|
|
624
|
+
const interruptParts = state.hitlState.interruptParts || [];
|
|
554
625
|
|
|
555
|
-
|
|
626
|
+
const responseParts = interruptParts.map((part, idx) => {
|
|
627
|
+
const hitlId = part.data.hitl_id;
|
|
628
|
+
const cardDecisions = state.hitlDecisions[hitlId] || {};
|
|
629
|
+
const actionRequests = part.data.content?.action_requests || [];
|
|
630
|
+
const totalActions = actionRequests.length || 1;
|
|
631
|
+
|
|
632
|
+
const decisions = [];
|
|
633
|
+
for (let actionIdx = 0; actionIdx < totalActions; actionIdx++) {
|
|
634
|
+
const decisionInfo = cardDecisions[actionIdx];
|
|
635
|
+
if (!decisionInfo) {
|
|
636
|
+
addSystemMessage(`Decision missing for HITL #${idx + 1}, action #${actionIdx + 1}`);
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
556
639
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
640
|
+
let decision = { type: decisionInfo.type };
|
|
641
|
+
const blockId = decisionInfo.blockId;
|
|
642
|
+
const inputEl = document.getElementById(`actionInput_${blockId}`);
|
|
643
|
+
const editInputEl = document.getElementById(`actionEditInput_${blockId}`);
|
|
644
|
+
const message = inputEl ? inputEl.value.trim() : '';
|
|
645
|
+
const editJson = editInputEl ? editInputEl.value.trim() : '';
|
|
646
|
+
|
|
647
|
+
if (decisionInfo.type === 'reject' && message) {
|
|
648
|
+
decision.message = message;
|
|
649
|
+
} else if (decisionInfo.type === 'respond') {
|
|
650
|
+
if (!message) {
|
|
651
|
+
addSystemMessage(`Response message is required for HITL #${idx + 1}, action #${actionIdx + 1}`);
|
|
652
|
+
return null;
|
|
653
|
+
}
|
|
654
|
+
decision.message = message;
|
|
655
|
+
} else if (decisionInfo.type === 'edit') {
|
|
656
|
+
if (editJson) {
|
|
657
|
+
try {
|
|
658
|
+
decision.edited_action = JSON.parse(editJson);
|
|
659
|
+
} catch (e) {
|
|
660
|
+
addSystemMessage(`Invalid JSON in edited action for HITL #${idx + 1}, action #${actionIdx + 1}`);
|
|
661
|
+
return null;
|
|
662
|
+
}
|
|
663
|
+
} else {
|
|
664
|
+
addSystemMessage(`Edited action JSON is required for HITL #${idx + 1}, action #${actionIdx + 1}`);
|
|
665
|
+
return null;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
decisions.push(decision);
|
|
568
670
|
}
|
|
569
|
-
decision = { type: 'respond', message: message };
|
|
570
|
-
}
|
|
571
671
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
672
|
+
return {
|
|
673
|
+
data: {
|
|
674
|
+
hitl_id: hitlId,
|
|
675
|
+
decisions: decisions,
|
|
676
|
+
}
|
|
677
|
+
};
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
// Check if any part failed validation
|
|
681
|
+
if (responseParts.some(p => p === null)) return;
|
|
576
682
|
|
|
577
683
|
const messageMeta = getJsonInput('messageMeta') || {};
|
|
578
684
|
const config = getJsonInput('config') || {};
|
|
579
|
-
|
|
580
685
|
const taskId = state.hitlState.id;
|
|
581
686
|
const messageId = generateId();
|
|
582
687
|
|
|
@@ -586,20 +691,23 @@
|
|
|
586
691
|
contextId: state.currentContextId,
|
|
587
692
|
taskId: taskId,
|
|
588
693
|
role: 'ROLE_USER',
|
|
589
|
-
parts:
|
|
590
|
-
data: hitlResponse,
|
|
591
|
-
}],
|
|
694
|
+
parts: responseParts,
|
|
592
695
|
metadata: messageMeta,
|
|
593
696
|
},
|
|
594
697
|
configuration: config,
|
|
595
698
|
metadata: getJsonInput('taskMeta') || {},
|
|
596
699
|
};
|
|
597
700
|
|
|
701
|
+
// Clean up HITL panel
|
|
598
702
|
elements.hitlPanel.classList.add('hidden');
|
|
703
|
+
const decisionSummary = interruptParts.map(p => {
|
|
704
|
+
const d = state.hitlDecisions[p.data.hitl_id];
|
|
705
|
+
return `${p.data.hitl_id}: ${d.type}`;
|
|
706
|
+
}).join(', ');
|
|
599
707
|
state.hitlState = null;
|
|
600
|
-
state.
|
|
708
|
+
state.hitlDecisions = {};
|
|
601
709
|
|
|
602
|
-
addUserMessage(`[HITL Response]
|
|
710
|
+
addUserMessage(`[HITL Response] ${decisionSummary}`);
|
|
603
711
|
addLoadingMessage();
|
|
604
712
|
|
|
605
713
|
state.isSending = true;
|
|
File without changes
|
|
File without changes
|
{langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/server.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/utils/lock.py
RENAMED
|
File without changes
|
{langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_a2a_api/utils/types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/src/langgraph_aux/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{langgraph_agent_common-2.0.0 → langgraph_agent_common-2.0.2}/test/test_deepagents_a2a_server.py
RENAMED
|
File without changes
|