django-agent-studio 0.1.8__py3-none-any.whl → 0.2.0__py3-none-any.whl

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.
@@ -1074,6 +1074,34 @@ class AgentFullSchemaView(APIView):
1074
1074
 
1075
1075
  permission_classes = [IsAuthenticated]
1076
1076
 
1077
+ def _get_memory_config(self, version):
1078
+ """Extract memory configuration from version's extra_config."""
1079
+ if not version:
1080
+ return self._default_memory_config()
1081
+
1082
+ extra = version.extra_config or {}
1083
+ return {
1084
+ "enabled": extra.get("memory_enabled", True),
1085
+ "default_scope": extra.get("memory_default_scope", "user"),
1086
+ "allowed_scopes": extra.get("memory_allowed_scopes", ["conversation", "user", "system"]),
1087
+ "auto_recall": extra.get("memory_auto_recall", True),
1088
+ "max_memories_in_prompt": extra.get("memory_max_in_prompt", 50),
1089
+ "include_system_memories": extra.get("memory_include_system", True),
1090
+ "retention_days": extra.get("memory_retention_days", None),
1091
+ }
1092
+
1093
+ def _default_memory_config(self):
1094
+ """Return default memory configuration."""
1095
+ return {
1096
+ "enabled": True,
1097
+ "default_scope": "user",
1098
+ "allowed_scopes": ["conversation", "user", "system"],
1099
+ "auto_recall": True,
1100
+ "max_memories_in_prompt": 50,
1101
+ "include_system_memories": True,
1102
+ "retention_days": None,
1103
+ }
1104
+
1077
1105
  def get(self, request, pk):
1078
1106
  """Get the complete agent schema."""
1079
1107
  agent = get_agent_for_user(request.user, pk)
@@ -1125,6 +1153,20 @@ class AgentFullSchemaView(APIView):
1125
1153
  "embedding_model": "text-embedding-3-small",
1126
1154
  },
1127
1155
 
1156
+ # File upload/processing configuration
1157
+ "file_config": agent.file_config or {
1158
+ "enabled": False,
1159
+ "max_file_size_mb": 100,
1160
+ "allowed_types": ["image/*", "application/pdf", "text/*"],
1161
+ "ocr_provider": None,
1162
+ "vision_provider": None,
1163
+ "enable_thumbnails": True,
1164
+ "storage_path": None,
1165
+ },
1166
+
1167
+ # Memory configuration (from extra_config)
1168
+ "memory_config": self._get_memory_config(active_version),
1169
+
1128
1170
  # Static tools (AgentTool)
1129
1171
  "tools": [
1130
1172
  {
@@ -1241,6 +1283,8 @@ class AgentFullSchemaView(APIView):
1241
1283
  agent.is_active = data['is_active']
1242
1284
  if 'rag_config' in data:
1243
1285
  agent.rag_config = data['rag_config']
1286
+ if 'file_config' in data:
1287
+ agent.file_config = data['file_config']
1244
1288
 
1245
1289
  agent.save()
1246
1290
 
@@ -1262,6 +1306,30 @@ class AgentFullSchemaView(APIView):
1262
1306
  active_version.notes = version_data['notes']
1263
1307
  active_version.save()
1264
1308
 
1309
+ # Update memory configuration
1310
+ if 'memory_config' in data:
1311
+ active_version = agent.versions.filter(is_active=True).first()
1312
+ if active_version:
1313
+ mem_config = data['memory_config']
1314
+ if active_version.extra_config is None:
1315
+ active_version.extra_config = {}
1316
+ # Map memory_config fields to extra_config keys
1317
+ if 'enabled' in mem_config:
1318
+ active_version.extra_config['memory_enabled'] = mem_config['enabled']
1319
+ if 'default_scope' in mem_config:
1320
+ active_version.extra_config['memory_default_scope'] = mem_config['default_scope']
1321
+ if 'allowed_scopes' in mem_config:
1322
+ active_version.extra_config['memory_allowed_scopes'] = mem_config['allowed_scopes']
1323
+ if 'auto_recall' in mem_config:
1324
+ active_version.extra_config['memory_auto_recall'] = mem_config['auto_recall']
1325
+ if 'max_memories_in_prompt' in mem_config:
1326
+ active_version.extra_config['memory_max_in_prompt'] = mem_config['max_memories_in_prompt']
1327
+ if 'include_system_memories' in mem_config:
1328
+ active_version.extra_config['memory_include_system'] = mem_config['include_system_memories']
1329
+ if 'retention_days' in mem_config:
1330
+ active_version.extra_config['memory_retention_days'] = mem_config['retention_days']
1331
+ active_version.save()
1332
+
1265
1333
  # Update tools
1266
1334
  if 'tools' in data:
1267
1335
  for tool_data in data['tools']:
@@ -1925,3 +1993,68 @@ class SpecDocumentRenderView(APIView):
1925
1993
  'root_count': len(parts),
1926
1994
  'roots': [{'id': str(r.id), 'title': r.title} for r in roots],
1927
1995
  })
1996
+
1997
+
1998
+ class AgentSpecDocumentView(APIView):
1999
+ """Get or create the spec document linked to an agent."""
2000
+ permission_classes = [IsAuthenticated]
2001
+
2002
+ def get(self, request, agent_id):
2003
+ """Get the spec document linked to this agent, or return empty if none exists."""
2004
+ from django_agent_runtime.models import SpecDocument
2005
+
2006
+ agent = get_agent_for_user(request.user, agent_id)
2007
+
2008
+ spec_doc = SpecDocument.objects.filter(linked_agent=agent).first()
2009
+
2010
+ if spec_doc:
2011
+ return Response({
2012
+ 'id': str(spec_doc.id),
2013
+ 'title': spec_doc.title,
2014
+ 'content': spec_doc.content,
2015
+ 'current_version': spec_doc.current_version,
2016
+ 'has_spec': bool(spec_doc.content),
2017
+ 'created_at': spec_doc.created_at.isoformat(),
2018
+ 'updated_at': spec_doc.updated_at.isoformat(),
2019
+ })
2020
+ else:
2021
+ return Response({
2022
+ 'id': None,
2023
+ 'title': None,
2024
+ 'content': '',
2025
+ 'current_version': 0,
2026
+ 'has_spec': False,
2027
+ })
2028
+
2029
+ def put(self, request, agent_id):
2030
+ """Update or create the spec document for this agent."""
2031
+ from django_agent_runtime.models import SpecDocument
2032
+
2033
+ agent = get_agent_for_user(request.user, agent_id)
2034
+ content = request.data.get('content', '')
2035
+
2036
+ spec_doc = SpecDocument.objects.filter(linked_agent=agent).first()
2037
+
2038
+ if spec_doc:
2039
+ # Update existing
2040
+ spec_doc.content = content
2041
+ spec_doc.save() # Auto-creates version
2042
+ created = False
2043
+ else:
2044
+ # Create new
2045
+ spec_doc = SpecDocument.objects.create(
2046
+ title=f"{agent.name} Specification",
2047
+ content=content,
2048
+ linked_agent=agent,
2049
+ owner=request.user if request.user.is_authenticated else None,
2050
+ )
2051
+ created = True
2052
+
2053
+ return Response({
2054
+ 'id': str(spec_doc.id),
2055
+ 'title': spec_doc.title,
2056
+ 'content': spec_doc.content,
2057
+ 'current_version': spec_doc.current_version,
2058
+ 'created': created,
2059
+ 'message': f"Spec {'created' if created else 'updated'} for {agent.name}",
2060
+ })
@@ -1447,3 +1447,225 @@
1447
1447
  max-height: 300px;
1448
1448
  overflow-y: auto;
1449
1449
  }
1450
+
1451
+ /* ========================================
1452
+ File Upload Styles
1453
+ ======================================== */
1454
+
1455
+ /* Attach button in input form */
1456
+ .cw-attach-btn {
1457
+ display: flex;
1458
+ align-items: center;
1459
+ justify-content: center;
1460
+ width: 36px;
1461
+ height: 36px;
1462
+ padding: 0;
1463
+ border: none;
1464
+ background: transparent;
1465
+ color: #666;
1466
+ font-size: 18px;
1467
+ cursor: pointer;
1468
+ border-radius: 6px;
1469
+ transition: background 0.15s, color 0.15s;
1470
+ flex-shrink: 0;
1471
+ }
1472
+
1473
+ .cw-attach-btn:hover {
1474
+ background: rgba(0, 0, 0, 0.05);
1475
+ color: #333;
1476
+ }
1477
+
1478
+ .cw-attach-btn:disabled {
1479
+ opacity: 0.5;
1480
+ cursor: not-allowed;
1481
+ }
1482
+
1483
+ /* File chips container (preview of selected files) */
1484
+ .cw-file-chips {
1485
+ display: flex;
1486
+ flex-wrap: wrap;
1487
+ gap: 6px;
1488
+ padding: 8px 12px;
1489
+ border-bottom: 1px solid #e0e0e0;
1490
+ background: #fafafa;
1491
+ }
1492
+
1493
+ /* Individual file chip */
1494
+ .cw-file-chip {
1495
+ display: flex;
1496
+ align-items: center;
1497
+ gap: 6px;
1498
+ padding: 4px 8px;
1499
+ background: #fff;
1500
+ border: 1px solid #ddd;
1501
+ border-radius: 16px;
1502
+ font-size: 12px;
1503
+ max-width: 200px;
1504
+ }
1505
+
1506
+ .cw-file-chip-icon {
1507
+ font-size: 14px;
1508
+ flex-shrink: 0;
1509
+ }
1510
+
1511
+ .cw-file-chip-name {
1512
+ overflow: hidden;
1513
+ text-overflow: ellipsis;
1514
+ white-space: nowrap;
1515
+ color: #333;
1516
+ }
1517
+
1518
+ .cw-file-chip-size {
1519
+ color: #888;
1520
+ font-size: 11px;
1521
+ flex-shrink: 0;
1522
+ }
1523
+
1524
+ .cw-file-chip-remove {
1525
+ display: flex;
1526
+ align-items: center;
1527
+ justify-content: center;
1528
+ width: 16px;
1529
+ height: 16px;
1530
+ padding: 0;
1531
+ border: none;
1532
+ background: #e0e0e0;
1533
+ color: #666;
1534
+ font-size: 12px;
1535
+ line-height: 1;
1536
+ border-radius: 50%;
1537
+ cursor: pointer;
1538
+ flex-shrink: 0;
1539
+ }
1540
+
1541
+ .cw-file-chip-remove:hover {
1542
+ background: #d32f2f;
1543
+ color: #fff;
1544
+ }
1545
+
1546
+ /* Message attachments container */
1547
+ .cw-message-attachments {
1548
+ display: flex;
1549
+ flex-wrap: wrap;
1550
+ gap: 8px;
1551
+ margin-bottom: 8px;
1552
+ }
1553
+
1554
+ /* Image thumbnail attachment */
1555
+ .cw-attachment-thumbnail {
1556
+ display: block;
1557
+ width: 120px;
1558
+ height: 90px;
1559
+ border-radius: 8px;
1560
+ overflow: hidden;
1561
+ border: 1px solid #ddd;
1562
+ transition: transform 0.15s, box-shadow 0.15s;
1563
+ }
1564
+
1565
+ .cw-attachment-thumbnail:hover {
1566
+ transform: scale(1.02);
1567
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
1568
+ }
1569
+
1570
+ .cw-attachment-thumbnail img {
1571
+ width: 100%;
1572
+ height: 100%;
1573
+ object-fit: cover;
1574
+ }
1575
+
1576
+ /* File attachment (non-image) */
1577
+ .cw-attachment-file {
1578
+ display: flex;
1579
+ align-items: center;
1580
+ gap: 8px;
1581
+ padding: 8px 12px;
1582
+ background: #f5f5f5;
1583
+ border: 1px solid #ddd;
1584
+ border-radius: 8px;
1585
+ text-decoration: none;
1586
+ color: inherit;
1587
+ transition: background 0.15s;
1588
+ max-width: 200px;
1589
+ }
1590
+
1591
+ .cw-attachment-file:hover {
1592
+ background: #eee;
1593
+ }
1594
+
1595
+ .cw-attachment-icon {
1596
+ font-size: 20px;
1597
+ flex-shrink: 0;
1598
+ }
1599
+
1600
+ .cw-attachment-info {
1601
+ display: flex;
1602
+ flex-direction: column;
1603
+ overflow: hidden;
1604
+ }
1605
+
1606
+ .cw-attachment-name {
1607
+ font-size: 13px;
1608
+ font-weight: 500;
1609
+ color: #333;
1610
+ overflow: hidden;
1611
+ text-overflow: ellipsis;
1612
+ white-space: nowrap;
1613
+ }
1614
+
1615
+ .cw-attachment-size {
1616
+ font-size: 11px;
1617
+ color: #888;
1618
+ }
1619
+
1620
+ /* Dark mode adjustments for file upload */
1621
+ @media (prefers-color-scheme: dark) {
1622
+ .cw-attach-btn {
1623
+ color: #999;
1624
+ }
1625
+
1626
+ .cw-attach-btn:hover {
1627
+ background: rgba(255, 255, 255, 0.1);
1628
+ color: #fff;
1629
+ }
1630
+
1631
+ .cw-file-chips {
1632
+ background: #1a1a1a;
1633
+ border-bottom-color: #333;
1634
+ }
1635
+
1636
+ .cw-file-chip {
1637
+ background: #2a2a2a;
1638
+ border-color: #444;
1639
+ }
1640
+
1641
+ .cw-file-chip-name {
1642
+ color: #e0e0e0;
1643
+ }
1644
+
1645
+ .cw-file-chip-remove {
1646
+ background: #444;
1647
+ color: #999;
1648
+ }
1649
+
1650
+ .cw-file-chip-remove:hover {
1651
+ background: #d32f2f;
1652
+ color: #fff;
1653
+ }
1654
+
1655
+ .cw-attachment-thumbnail {
1656
+ border-color: #444;
1657
+ }
1658
+
1659
+ .cw-attachment-file {
1660
+ background: #2a2a2a;
1661
+ border-color: #444;
1662
+ }
1663
+
1664
+ .cw-attachment-file:hover {
1665
+ background: #333;
1666
+ }
1667
+
1668
+ .cw-attachment-name {
1669
+ color: #e0e0e0;
1670
+ }
1671
+ }