fastapi-fullstack 0.2.13__py3-none-any.whl → 0.2.15__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.
Files changed (38) hide show
  1. {fastapi_fullstack-0.2.13.dist-info → fastapi_fullstack-0.2.15.dist-info}/METADATA +1 -1
  2. {fastapi_fullstack-0.2.13.dist-info → fastapi_fullstack-0.2.15.dist-info}/RECORD +38 -27
  3. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/0023_add_is_demo_conversations.py +30 -0
  4. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/0024_create_webhook_tables.py +89 -0
  5. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/prompts.py +4 -0
  6. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/__init__.py +2 -1
  7. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/admin_conversations.py +19 -1
  8. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/public_demos.py +41 -0
  9. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/conversation.py +1 -0
  10. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/conversation.py +44 -0
  11. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/conversation.py +20 -0
  12. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/conversation_share.py +1 -0
  13. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/agent_session.py +1 -1
  14. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/conversation.py +34 -0
  15. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/file_upload.py +2 -1
  16. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/organization.py +2 -1
  17. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/user.py +2 -1
  18. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/pyproject.toml +3 -0
  19. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.dev.yml +2 -2
  20. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.prod.yml +2 -2
  21. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.yml +2 -2
  22. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/admin/conversations/page.tsx +72 -2
  23. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/demo/[id]/page.tsx +74 -0
  24. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/demo/page.tsx +156 -0
  25. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/admin/conversations/[id]/demo/route.ts +35 -0
  26. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/globals.css +43 -0
  27. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-call-card.tsx +66 -20
  28. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/demo/demo-replay.tsx +189 -0
  29. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/marketing/brand-icon.tsx +2 -3
  30. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-conversation-replay.ts +118 -0
  31. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-conversations.ts +2 -0
  32. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-step-replay.ts +183 -0
  33. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/agent-step-captions.ts +51 -0
  34. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/conversation-to-chat.ts +77 -0
  35. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/conversation.ts +2 -0
  36. {fastapi_fullstack-0.2.13.dist-info → fastapi_fullstack-0.2.15.dist-info}/WHEEL +0 -0
  37. {fastapi_fullstack-0.2.13.dist-info → fastapi_fullstack-0.2.15.dist-info}/entry_points.txt +0 -0
  38. {fastapi_fullstack-0.2.13.dist-info → fastapi_fullstack-0.2.15.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-fullstack
3
- Version: 0.2.13
3
+ Version: 0.2.15
4
4
  Summary: Full-stack FastAPI + Next.js template generator with PydanticAI/LangChain agents, WebSocket streaming, 20+ enterprise integrations, and Logfire/LangSmith observability. Ship AI apps fast. CLI tool to generate production-ready FastAPI + Next.js projects with AI agents, auth, and observability.
5
5
  Project-URL: Homepage, https://github.com/vstorm-co/full-stack-ai-agent-template
6
6
  Project-URL: Documentation, https://github.com/vstorm-co/full-stack-ai-agent-template#readme
@@ -16,10 +16,10 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/MANUAL_STEPS.md,sha256=6HJW2W
16
16
  fastapi_gen/template/{{cookiecutter.project_slug}}/Makefile,sha256=QD3Wv03COXT7GsOB_0nSvz6fG8hG0bt3de_uQUgjLJk,17172
17
17
  fastapi_gen/template/{{cookiecutter.project_slug}}/README.md,sha256=faY_FSgHSMc5PhrHFbJGmJpRa0gxUwZLF6JZ4Qn7Ac4,13878
18
18
  fastapi_gen/template/{{cookiecutter.project_slug}}/SECURITY.md,sha256=7X5u7feq2AXxWv2CMMNQZf5QQ5QkwBnzKlrcLz3RJ_Q,4735
19
- fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.dev.yml,sha256=zY4wm7oui3UREfoxibrt0PuWwpnWH3J6GkUs3KDdREc,12348
19
+ fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.dev.yml,sha256=kYdJ9uMuN7BDTqymxULxRo71qeIAQ7vue5Gc-0gt3do,12348
20
20
  fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.frontend.yml,sha256=nmMjmzmyVudK9vZoFBmHNv4q4-ydq_lW5X4YrxEpP8E,2052
21
- fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.prod.yml,sha256=nu3BmFIZUI4LYtYP7Eo6s2AgGs7XkzoYHQCnqPp4nVw,22283
22
- fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.yml,sha256=S7DNL4Bz7SFzt5V2vKBvqIo6bHDVIJytufGoapixfmU,13635
21
+ fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.prod.yml,sha256=a7o95f5BDXd-hJJtpA-n0AqB2n2mrGbtiGddk00t9OQ,22283
22
+ fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.yml,sha256=LBlsC40VLrYRzu-kbngvMnQxJXSJgNLKMAVOEI0eNX4,13635
23
23
  fastapi_gen/template/{{cookiecutter.project_slug}}/.claude/settings.json,sha256=i6XfBDlx6N1AXg4-MrjmIzPhxRXvQC9PRXJFZyfNs1Y,363
24
24
  fastapi_gen/template/{{cookiecutter.project_slug}}/.claude/commands/add-endpoint.md,sha256=p0EsXDvW23v4uOSPRlwA84nVrB7_VVL_FnKFEE442AQ,1648
25
25
  fastapi_gen/template/{{cookiecutter.project_slug}}/.claude/commands/fix-issue.md,sha256=3bcQwYzf_EXTit9nlkplUd0-G5T9-gGranogIDS_kjU,800
@@ -45,7 +45,7 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.env.example,sha256=o
45
45
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.pre-commit-config.yaml,sha256=22sYeJOrYywl_5PWgPzCyIwhpqmymIDIzx2hlBRQ-yI,681
46
46
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/Dockerfile,sha256=CKyuUKwt41LHIH9VB28TEzes5_TQkUEo9rIBjE3v8a8,2184
47
47
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic.ini,sha256=vncO8XHTAW1ospWsdvtXD5PyMhp91CJmdVfv-6TakAY,737
48
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/pyproject.toml,sha256=wJB8vOWi7zqK26M3mF_BaY6jt7e4bh6Xr6mmElYofuY,13740
48
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/pyproject.toml,sha256=X_dPJBsitGofJiauOpz2lKZV4gPvFRf_NOfuQUL9QFQ,13785
49
49
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/env.py,sha256=ifDazpmfYDUI0KGxaGcAgJbz6HNzu9bQYB6li88OMcU,3163
50
50
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/script.py.mako,sha256=ZCfgWrEMJRDF_WF_GRGptwAIJI6YnAditBG1axwAP9Q,700
51
51
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -72,6 +72,8 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/0019
72
72
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/0020_conversation_external_user_id.py,sha256=OXTdBSlyZ0kcxqRZ_oz3YftUk4fuWMvTpCVLLLbmhAI,1098
73
73
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/0021_create_items.py,sha256=loQ6vypHJI0SAN7o5_iGNcEH7Ga6b4TwXgnwRl2nlfs,1905
74
74
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/0022_sync_source_org_scope.py,sha256=p6FtNMfqVQZtG7ollDrl7CaTOuhVwxqqSazvglVbRXU,2079
75
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/0023_add_is_demo_conversations.py,sha256=VCVhhwyvbuuSiGKwXmw4rIgZ8x811AeCQgsDTaxsVCQ,793
76
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/0024_create_webhook_tables.py,sha256=HExnIhQAJXNCe1vxhagIhUr0BeBBv2MTBadQEY4GtY8,3233
75
77
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/__init__.py,sha256=vNnuyVXC5oZ3yq46meWLNhkUYlMgod70TgvWyvgNhBk,68
76
78
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/admin.py,sha256=QxVibclQNYtROGtf00Lsb5dlskvs4yLZ7SaEz6vf-IA,12990
77
79
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/main.py,sha256=CcUQKjWvANuNCRIS_vEry6ZglCs1wIwD76HkbMa3BHw,18948
@@ -80,7 +82,7 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/assistant.
80
82
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/deepagents_assistant.py,sha256=DDNw13jlftfntPsM2ZVdJQyWqc2FFPcEXFo6wyZttbM,30208
81
83
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/langchain_assistant.py,sha256=sX9dbzwR-X-HQvPWLgEunbzEv-DcJp7Db6VsCYwf0eY,13158
82
84
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/langgraph_assistant.py,sha256=uSDnHa7VvbPwQ_csqjMpmTlv_RTym4GkHUasbWlQdpU,15363
83
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/prompts.py,sha256=ZuoTG6qODmoGqVnEU-EaJdk1VbU7Dd1vA55eq3-wyls,12409
85
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/prompts.py,sha256=jc4VHuVLdi-5f0oiZVqJ-8qkAtVKbO8TEQuMv1c4nL0,12523
84
86
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/pydantic_deep_assistant.py,sha256=7zqyaa9vpNprDFj-Lnie8-e-Gv6O4-DO-NK_Ko01SNE,16544
85
87
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/utils.py,sha256=nV5ScbK7TH4LAaiP3zx2pi8FmGHJ6ElHyhLjGbB_PMs,348
86
88
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/__init__.py,sha256=BuDkvOBAShFc1dAk6c_Jk_MWAozW_WA0SJOMbFNbu9I,933
@@ -97,8 +99,8 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/exception_han
97
99
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/router.py,sha256=8E0e0Oef6KrB6raDgrV0Lj-tPKRiQ-5UlGM3yGnz50Q,233
98
100
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/versioning.py,sha256=O5FQre_y1hwJGsbREeKbRKoxEWUVhGNg7gIC76FqyPo,5906
99
101
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/__init__.py,sha256=wIJD_xpViBStOBb4iWBX_hxdPfSKJyAGlcOw81NTWXo,207
100
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/__init__.py,sha256=rs1ci0eHVCvOY5ISB7MbO8IzwTLgZQLJIzcFFODbaLs,6923
101
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/admin_conversations.py,sha256=5Y_p1WzXtlzSefBGVW_Uxw3Uz4CUuLj_vRn1XlEtHCw,1945
102
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/__init__.py,sha256=i77ftuXWLO9w5g2hJph2HMHYdh8ifdJEdCHlT-nw_hU,7016
103
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/admin_conversations.py,sha256=Kmzwl-ve6jbukTa5WNQIydOOR1cmIvXWLtamXS9Oj4E,2612
102
104
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/admin_ratings.py,sha256=IbCCteKLbwsj8bp1znBQ2zdGPTePNtIaULmO3eSschg,2540
103
105
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/admin_stats.py,sha256=z6xVC9yac5jcGpt5QK91VdzpgYap9ETWgCx2M6yKITM,1177
104
106
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/admin_users.py,sha256=dcg36c-q-1qb7H1m7gQOF52SHclfeEyCqbqUpjUrxMw,3924
@@ -120,6 +122,7 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/oau
120
122
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/org_integrations.py,sha256=misA4_Jll5QUyHUBT6RaBgjkWe24vEK9bL-r3EZjznI,3972
121
123
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/organizations.py,sha256=Zl3bJPy-RfpluSgadeStrp_KodVpLQKmUPkoFkXiXxU,4992
122
124
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/projects.py,sha256=d9l5HZ5wJl_MGnIvEJss_gXomxUR3XYLXB-grLV_81s,4565
125
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/public_demos.py,sha256=XP6KDu2U6LaJKydkuE5fYjO1PgggGrQVU9j1a9VRq9M,1538
123
126
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/rag.py,sha256=pZ-JmhZaa6sVz0Oy8lcF6XdhUJPZiIXly1ejvO-IUaA,16452
124
127
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/sessions.py,sha256=7LrDMVy8DYhriAAL4QTL8YtXDmOwhjltvjBOanYkkUk,1235
125
128
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/slack_webhook.py,sha256=PWRzZGD_zUOKf_BeYelQxl_G25hzoF3Dahs0-PtvFmY,2058
@@ -161,7 +164,7 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/channel
161
164
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/channel_identity.py,sha256=RL8g8D8srDkvsyIZdKQClazuQXct_oj5VTaiRkaoHNM,3739
162
165
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/channel_session.py,sha256=3JlOn96T8g4o8xAfklxZJNx-OCJ0mJ_Va1aVQhBhLR8,4652
163
166
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/chat_file.py,sha256=yaGlDbt0FWBN3W8C4NKgFyBHJJDjlsfxGXmZrAcMY4U,2992
164
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/conversation.py,sha256=_O41um9vW9AlpUIR1VXPSV2EGbFudHvyx7to_ihim_U,13053
167
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/conversation.py,sha256=QeWPp8OHV07UHk4OBfTfiA0oBCEF2h3si5-ujJxuCzo,13147
165
168
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/conversation_share.py,sha256=hOY9XL9pf4-VyqhyBZapqs6XP0G9B7uRaaoy1fLBY_k,4305
166
169
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/credit_transaction.py,sha256=BerBTIwkbf-e2OKZQOYFJd-gmrPEP7Zuwn0CJOGXtG4,6475
167
170
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/item.py,sha256=2z8g1K4Q1gFdycP2ZthFpb984Y1zqjWyajCO5Flh2Dw,1532
@@ -184,7 +187,7 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/chan
184
187
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/channel_identity.py,sha256=diP-iIg-D1By77eiJg6LDdw2cmKdK6Qi33L7hUtTc9E,2812
185
188
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/channel_session.py,sha256=E-4ThRDfqu41BsFxRMNCWH_4jklSq-Cf6eAPtl45u2A,3675
186
189
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/chat_file.py,sha256=zyBGqHCl2C2jzsz8u-3ra4nHh0Oh-dlyS8kxwSTSlhM,2055
187
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/conversation.py,sha256=Wq4xEudtNoblew_UdJ5k88DiS-kHf2B_xJYrN9D8li4,16241
190
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/conversation.py,sha256=_qozZOLAeNgtzevu6Q4iCo5kO-lghySMI7yiL0VOrQw,17620
188
191
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/conversation_share.py,sha256=PknNwwbngerOSgifXbbKiYAPvah4xbL9MIFxWgJ3pVc,3954
189
192
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/credit_transaction.py,sha256=CgQi3l9JYI-lTVeLcnK3G_fBsU4FYOxpxy5Hx00p_wc,1708
190
193
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/invitation.py,sha256=ZrHX2UuCtFXndKBVcyT871yPGa4-7OPzrI3mymwn4R0,3332
@@ -211,8 +214,8 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/base.py,s
211
214
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/billing.py,sha256=RvPxtX_dbmkF0LKbh-bZGoZcD29uzhmHfV5rH58FaHc,4047
212
215
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/channel_bot.py,sha256=gYlfAkHbsTK3oiYO3LklaO5Dr9VYiuAfzFk861MO8NE,3309
213
216
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/contact.py,sha256=0kN4rtNr80-dl5uhVwfbnQDc4WXNbWSxxqfuLQNW4_4,990
214
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/conversation.py,sha256=0RzcUNgCjIqEGBwe6gAKPODZIU8cyOkjBR5vDynMv2Q,6832
215
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/conversation_share.py,sha256=QBFCUpEFbCtVfr04BLBxEpjNutO80Bp9YXoVmJ8jsts,2243
217
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/conversation.py,sha256=tGHgKQtuAfbDehzlxbz7vLX1AcVR_XuHC3eroV-8Ds8,7382
218
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/conversation_share.py,sha256=PFt1XIipbX7y7YM4j3ZieJx254gQpwSIW90vw-cHSsM,2269
216
219
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/file.py,sha256=UNiB0dAYKtRrlKR-301jRsIEaq4n0MvHhSO5iaDMuoE,421
217
220
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/item.py,sha256=Z3YhlaGPPrSNUMw3IdC4Y86HZoeEJgS-D-S-I16E0cM,1064
218
221
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/knowledge_base.py,sha256=Fyswu3d83PmdM_iQ3e-yhis29O0T-5H0ow0lBmjplvs,1633
@@ -232,14 +235,14 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/__init__
232
235
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/admin.py,sha256=FzwzW6FpIx1Ciwj_9lCbWMzi-EWv3v2-J8Sopi9LiZU,5576
233
236
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/agent.py,sha256=cHPy4xDuttdZDPMJhZDdQBB5dUOb4yx2sW5VWEyweVY,11974
234
237
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/agent_invocation.py,sha256=u3OxIMVO4Q0rbouCKlW38YPjUrRNoydK2euoMT8mSR0,15919
235
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/agent_session.py,sha256=JlHGP1Hh-bS_D1HpAJXYix8Te41dfBrF5MG5ynQW8zg,109375
238
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/agent_session.py,sha256=K7e_NiGT7rjZc5JNdkj8ViNR00mw9W5NiEQHaUn09tc,109353
236
239
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/anomaly_detection.py,sha256=uKPCzzdeyDSUbgkD7VwFIubEHhoU1LEoOp3R1_F0SlE,3112
237
240
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/channel_bot.py,sha256=R1tfQQcNxHKZ9C3yOD6Hh4TANY77FL4XNic4Rf40qWo,6383
238
241
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/contact.py,sha256=AuML8RHIozZkchZlNMjHsZhLWpTMxukfy1xk6mak3Bk,1697
239
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/conversation.py,sha256=CMHeXONotgbE8cpCItqmSIqHtvcMrSh6CUV-WZnZi_w,19685
242
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/conversation.py,sha256=v6zyIjd6cvPbvuoCWu_6CmdgdQGOq5yBi6J81rOD3Sk,21062
240
243
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/conversation_share.py,sha256=JQHy636d7NI058yBlFyQ-17VQzau-Z6G2FIp4E0XOIg,6711
241
244
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/file_storage.py,sha256=EOl8jrSN5yxMgBb9eN-BElSsRfpEyFC_eF6qR3eRPYc,4618
242
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/file_upload.py,sha256=XZ40ggYj1ckhiHpzxQ_vDIKLUcqBJyGaUffoUEcKAfA,10952
245
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/file_upload.py,sha256=oFS-voZyGA0OH_yLM8XgvjenOTRV3W9deeg9bJ6sPcE,11022
243
246
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/health.py,sha256=FLMt3mgCuXhZS077bxpUoxu_ruNFvYVOBEGXS6B1T3o,587
244
247
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/invitation.py,sha256=-kEZ5mIHYnvQOsQAr7_N-xa5Ce4nFsb9K07n3FlMINc,7700
245
248
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/item.py,sha256=9cEPv90_o2hpLpNFzT0gi7vEt6MuZ5qCbXOGplluzNg,2302
@@ -247,7 +250,7 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/knowledg
247
250
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/member.py,sha256=BCjetJzFEfiudoXAz36ktJrritDIZBfWHUyP7K1Eeoc,7255
248
251
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/message_rating.py,sha256=2CWFqNDyaFTaXAgk1AIPS2gC_6AVFAwjfjUXY4IHCSI,13129
249
252
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/newsletter.py,sha256=LaT0bLcI5FG-ISdat06Ci1e3QT-1QHLrimcWwR5-Kl8,1545
250
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/organization.py,sha256=KBvlGE0So8Nci4oAVkDJawnnzBSpg9PZc1-P-Ck0ujs,7278
253
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/organization.py,sha256=qAjP5CciI5_7b9YeqfZCrAkE5Ax37Xj9GAuVxdq_TZg,7348
251
254
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/project.py,sha256=jzHyoxbRJ9bKSHnSznKLjgul2m2bsKgERdDzQkG6xyk,11131
252
255
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/rag_document.py,sha256=0fXbrtZGnIz166Sbx-KKzQQyzDmG2HeLmrYu-qGgCnA,12844
253
256
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/rag_status.py,sha256=rdVLTuCtfHvrhq9p5qZpdyOfm7zzalW5lxvAzDCQapI,2435
@@ -256,7 +259,7 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/research
256
259
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/session.py,sha256=mABDVV3lMvmJsprr-y_XSMQ8hTb4PIEnK_bn5jasUUw,4103
257
260
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/sync_source.py,sha256=59RUGb_Gl3J6fy2wQpXD2T2RyUG7lp4Mpkcv-fQxN9E,11319
258
261
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/usage.py,sha256=SUNAEnnOZjXr_PXoFGjfkMjAw7aB5FvIHReeAVI4wx8,3756
259
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/user.py,sha256=iVrzhHKgMkXCjuGyD9uzHlDBSiED9P0V-KX_PEAqEZo,13204
262
+ fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/user.py,sha256=y50P1A2CoQplNCFddxc7npWmY-aDuKJnWsWOf9CUTbY,13274
260
263
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/user_slash_command.py,sha256=t1-IIExupr-pvhCt_JjmiLrWfzMEzR2cDcLfhfPVRCQ,5427
261
264
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/webhook.py,sha256=RCT96wAQDnr8CUG9_gzXYxi-Av3BXzjbl0BnxNY1qWw,7500
262
265
  fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/billing/__init__.py,sha256=t953_p9xlo9jNiflpiQBBiht-wWXV-RJAHi75Dp7w-0,448
@@ -434,7 +437,7 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/i18n.ts,sha256=N
434
437
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/middleware.ts,sha256=GHlwWtD6i7CtbWGVZlotlkN7sHgh7CUQAABKFSV8cVE,1162
435
438
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/apple-icon.tsx,sha256=MCiMbtWcBan1YmO-hb_yWrAMGt8VLBcDntAQ_DfL3Tg,747
436
439
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/global-error.tsx,sha256=rKSgs3mTGYyd7HsamSbYmS2I5rhleDEZtY59vCyYWX0,2838
437
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/globals.css,sha256=C-GJiy9b6s6nOvoN6w7A57GIJeQDboX86XXleZQ_DrA,27648
440
+ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/globals.css,sha256=prs17z9mSZ3P8Omb9CV8jPaaTTbnBAP1O5O0ZMWn5dA,29217
438
441
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/icon.tsx,sha256=2MB9MxViJK_lYPcLqE_cvUEBzAJt_teCxm400z4MlGs,763
439
442
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/layout.tsx,sha256=HZyvPmPQqfnNwhpz2dEMQ2DYCggO3XA9rr_vRnu55KI,2747
440
443
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/manifest.ts,sha256=x01jq7V9HttUhO_Kz8YKGUS5KKXPrjo_GpKptD3cJ20,621
@@ -456,7 +459,7 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(da
456
459
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/layout.tsx,sha256=aUdoZKTPr_6vYZjuItzd2j43xygHpeUiXV8hV73Wd2g,855
457
460
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/admin/layout.tsx,sha256=mlF8rZ0HEoNVFZ2DB_qzkfhJQawVaR1_Claxewn-QIs,1322
458
461
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/admin/page.tsx,sha256=evip8MS8Z7nEPtT_vHBtZh4VmWKgJneCcUV4Y2_tM54,7446
459
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/admin/conversations/page.tsx,sha256=iouvY0Z7xS9ANJtOxZKZZ-6fj-1Jsr3zeeeidYNCEro,10548
462
+ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/admin/conversations/page.tsx,sha256=XsFIsgpAnFtlxuMuA0ZYyIsD6u52TuTRCKHG-8EzCc0,12959
460
463
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/admin/ratings/page.tsx,sha256=YUg4tyAfVLEkt2gynJ8PYxzUzZ1zdZHOWHEFrhSFmSI,10865
461
464
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/admin/ratings/ratings-chart.tsx,sha256=ghvRrVZzJ5F8se35cjyVq1r0NVQ8uRRc1w4Qwzd_bO4,2893
462
465
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/admin/stripe-events/page.tsx,sha256=wJTxW3EukR4aHrX85IowLmNTjJ8fRuLlYt5vACyEWjA,15072
@@ -498,6 +501,8 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/blo
498
501
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/changelog/page.tsx,sha256=yfoEug93QmMWx2-YtfcpR1ivkUd1MDnIOkVZqriOHac,4768
499
502
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/community/page.tsx,sha256=Gsk1kl9fJszqfaNNTx8HfbIWed6637h9uK6QwdXsDSE,4376
500
503
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/contact/page.tsx,sha256=eyqfBMKv2CyNHkK-3uUw1tCFTFXiD6vt9E8w-Tx5OH0,5041
504
+ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/demo/page.tsx,sha256=L_0eR9qHlrkrCgkblZ-WMVk5TKCzSu6-PsjNFMgdJkE,5798
505
+ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/demo/[id]/page.tsx,sha256=wYO6vdTlUBTYoMAHCHjGhE3Xfm5q5cYR-Qw1UN8dct8,2521
501
506
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/help/page.tsx,sha256=exGH7IZaJ4ZtIzrUm3dFEar6zhJaB6bwJU5lQNDIkGk,4047
502
507
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/legal/cookies/page.tsx,sha256=QQXfgjnilT-BrUCsHo0ELx53Rw-E-utcy5Y7HRqE1uQ,1123
503
508
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/legal/privacy/page.tsx,sha256=e-ml6_OAgiG4bcodWHaIiPfPi-ID6w75VG4acSeFW5k,1177
@@ -510,6 +515,7 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/sec
510
515
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/shared/[token]/page.tsx,sha256=9rVe_WeC1fqhIXbhIcGsT7YxqREMSuhXToIszMPBPs4,2644
511
516
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/admin/conversations/route.ts,sha256=rzBk93JkMSXe1EUGLD9yVblwub7zcd67Rf2wxDBouIc,1519
512
517
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/admin/conversations/[id]/route.ts,sha256=uToRQeUCQ-sR0EsSlMN2QASGe3yF31QZpbCK-bUM6vA,982
518
+ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/admin/conversations/[id]/demo/route.ts,sha256=DqUk1zx-DmAKyivchFo2i_uAoKDpQp2sABaez65ZDSc,1248
513
519
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/admin/conversations/users/route.ts,sha256=y8WurCMixJKA8AKuvD7JBC5quhv6_kJh_TFDsBgK_TA,1191
514
520
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/admin/ratings/route.ts,sha256=mWjX4yTeJahcpjyHWoraBvGHlXJn6e4muTcpLdnkuJQ,1352
515
521
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/admin/ratings/export/route.ts,sha256=3SLfuT9I96vjOeHJubk0D3rbmkaxfIInEKFM2xwGMLU,1886
@@ -639,7 +645,7 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/
639
645
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/subagent-feed.tsx,sha256=HeOmoSxjvIazSGCHyFvULEQrRA8NaIeXPj5x7oKLlHY,3519
640
646
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/subagent-panel.tsx,sha256=ObR1ACPfOLUllCZmrwCcYV0vFhyms7yOtYYNkZ2Duk8,6268
641
647
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-approval-dialog.tsx,sha256=TIwATvTCIB-NQMEay0KvKrsk1bfjnvX-8IdhOBK0L9I,3814
642
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-call-card.tsx,sha256=YU1XNXvGkGgmoLVC3hdMg58KXXW5HxjhSOgbTcgWvms,9431
648
+ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-call-card.tsx,sha256=QBKbPuCEuHg_X-4Ii5bXKHeI5LfDTsXHMmQRQ0mv5i8,11496
643
649
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-results/ask-user.tsx,sha256=0WDPIa2VfVCCZAD9ErSDm8k_obQ-6Jzk8NUEju-U3P4,1850
644
650
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-results/datetime.tsx,sha256=8QD9Goqr0LQSUJZ8YBxX03tFfXBpSr_0UxDLbgAuK_s,1124
645
651
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-results/generic.tsx,sha256=NeZhU7C30jrXdsaabpU3wl0140zmrsbSGBi5vya0Blw,4648
@@ -663,6 +669,7 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/dashb
663
669
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/dashboard/top-models.tsx,sha256=SCF6Km4k-6vZ1PJ34_-I1HI_kOtWG6LPRUZZP7mbiG0,5378
664
670
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/dashboard/usage-timeline-chart.tsx,sha256=5qOWHGrRL1RowATqM6dnL4Fpp17QZemQQHy40WOHr3Y,2996
665
671
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/dashboard/usage-timeline.tsx,sha256=9UTnbjkAJxpoJddtJ-LC8znxNTatrUb9RxZvy4aLqak,4878
672
+ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/demo/demo-replay.tsx,sha256=EYHtPsNwWHmu9BMETquVuwQc_GiP239uDm_hVflIWWw,7903
666
673
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/google-icon.tsx,sha256=c_mbeTuAWdBIqIIi4eQkhdBIu3EwxjjCf8oQCsPYwwA,45
667
674
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/index.ts,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
668
675
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/kb/create-kb-dialog.tsx,sha256=FmM1SgExL8FopJ08tL49dXc06Bm3iooQtE8EQvhRgQU,3396
@@ -683,7 +690,7 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/legal
683
690
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/legal/privacy-content.tsx,sha256=IZnc4FTQOoWi-n_eNVJwk_8Hghmpm5voyIFCmdM7Psw,9296
684
691
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/legal/terms-content.tsx,sha256=Ms1kWErgMVD86x0F2w8y29CumZ9vG4ZztILRCyKR5BU,11285
685
692
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/marketing/animated-number.tsx,sha256=vHe8epQ72s9q219ZxEtvZlU0QujpfcebtAJRt-QBZ1I,2012
686
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/marketing/brand-icon.tsx,sha256=BSXBhJJgAXhCS-URWBe3duuvejJmKb1IGJxentR3V7k,1679
693
+ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/marketing/brand-icon.tsx,sha256=oKSqWgCOw6cudkEeFpQ3FPPXDWBVNfv3O35WfvDVNKM,1677
687
694
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/marketing/case-study.tsx,sha256=GdgsBTnUb0gl8hGhC6TC0_ztWDAV6eG7Z5M_ShQzTpA,2653
688
695
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/marketing/code-preview.tsx,sha256=3DEvdKSVCtpUACVfVawvpmpXyru3gebJoGcwHr9CKpE,4145
689
696
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/marketing/comparison-table.tsx,sha256=peH3Iez6vOsrdr4xWUNpKG96TE9srtOs3YiJu2rMrC4,3081
@@ -784,8 +791,9 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-admin-
784
791
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-auth.ts,sha256=t_ty2PTLpxhY4UDMop9-Qm21n6Ne8swEPwDhlPzUPOA,4936
785
792
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-billing.ts,sha256=XosrZfGWIg5u7Nkg4oP4iSIwPf2B-jM9hntryppQ8rU,5193
786
793
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-chat.ts,sha256=1ySt4t1O_DaLw9vQ-3Y1EfyXTrFSo6nKaS1IhDhWTmQ,21791
794
+ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-conversation-replay.ts,sha256=WtHU_lMxPt33E55luBV6_I8X811KRFxsJKcpcWRaXWM,4111
787
795
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-conversation-shares.ts,sha256=zBDtX_8Y7y7prGgvluG9snsd76THpwpAz6Svc4BY2qY,4828
788
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-conversations.ts,sha256=MVksSdeKHmfHkFyR__IHvQCGftqn4tGfF3GJ826K7jg,10759
796
+ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-conversations.ts,sha256=GaIjfll-yJDVlP0-5-7dbkiuPsy8mW6sKCzYC5q_vvs,10826
789
797
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-copy-to-clipboard.ts,sha256=PKdzoWMTTthOqzC9Fj_paf42EkaFpFjl1LO-8Pj8tE0,437
790
798
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-invitations.ts,sha256=lYO8cPB7JhIroICQ91z-yNitpwhnTw6lTQ9HSVMoLPo,2611
791
799
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-knowledge-bases.ts,sha256=ClQL-ylG6QvoYWMvSB91ihD5WHk9bwSVUscPHdvtbaw,12779
@@ -794,15 +802,18 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-org-in
794
802
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-organizations.ts,sha256=YxxH4Kv4RrMeAXhcddZHXYxUSJkZis_aHD4fMh50SMM,3814
795
803
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-projects.ts,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
796
804
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-slash-commands.ts,sha256=Ld7DgSNXY7NoJBvYq86SNBJPkbv-oR1KfLk-UZAX60E,4352
805
+ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-step-replay.ts,sha256=i5OyeW3reN0B8Gj55qaP_cZCwJb9OYl--o6zh5a8V3A,6265
797
806
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-websocket.ts,sha256=UtuIGl4sl6ykDkRrosdBXg2EwiQmNYxdaUWF6Bt1t2o,6967
798
807
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/active-route.ts,sha256=WuHpNgE_Vc4CaAX__rD-cQLASL-O0_x7SB0TDRoRiyI,1305
799
808
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/admin-auth.ts,sha256=2K09o5o8Q24yn1dn1uAfqIIlrCgQQDz4tTFFdJVSCTU,904
809
+ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/agent-step-captions.ts,sha256=G7axXhQ0ju341KwYqqOU-pPEGcu-S6X2lcN3Lvxdznk,1755
800
810
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/api-client.ts,sha256=v9qO6pac2VH5j-o0oMhawpOUXDKqGQNrPo4KPUlLFX4,4107
801
811
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/blog.ts,sha256=xaVKtXjwO53zzvVSPEfaifwfVXQzHnpNvpM8zDfElns,4304
802
812
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/changelog.ts,sha256=1z3pSuUEks_KmO-E9u5VUt1yXqQFDOrsXeJ-RvUHB0s,4340
803
813
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/chat-sources.ts,sha256=P7P2-8OvQQTvAzSaRiqRvOb3IkFF6CDgBnRdEAsL9rU,2035
804
814
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/constants.ts,sha256=eesSDW2Oubtjtpzhw4SQhQun5U1UpHSR_hzS4m2XFzE,2286
805
815
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/contact-info.ts,sha256=oTIbswuq-RlSXv-z08jlZTOp2pyPazwcOoRN9PjfjtE,1168
816
+ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/conversation-to-chat.ts,sha256=_dBgZCouqzplmw9i40qn5aMhEvZcn1xG0yfHzJheNhw,2424
806
817
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/file-api.ts,sha256=t7uOB7xdIh4K1Jt5kcyWro_oEfnrh2hxi52xsPEZRw8,787
807
818
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/query-keys.ts,sha256=UK1jzUwj6y7bxSIetYY1oP_CeDN2p1n6P30KNKhhdNI,2405
808
819
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/rag-api.ts,sha256=fSr_Zeus_FULCZvtkWrPHIKHbX4A45yL0w1NzDv21zc,9702
@@ -832,7 +843,7 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/api.ts,sha
832
843
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/auth.ts,sha256=2sMcucSTN-8d4zk1Lql30DElfizApr_fHtOsQ3DvTmE,1369
833
844
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/billing.ts,sha256=71NnQ9xs6G3LC_H-eA7mCSbDfUbWD3leyntmid_AWpI,2517
834
845
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/chat.ts,sha256=m3HlMSF7ji9-zuiB9UL3Gezq2ij2SF2n4RMce2Zdgko,6597
835
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/conversation.ts,sha256=2A129xRNtpOQQFPABwmnsATNuuUetY-bGeRjxEz7mOc,2870
846
+ fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/conversation.ts,sha256=laFw5_5gG5_tEsprAXyrhXVGGLLxdFHkSgV1lcZX3vU,2910
836
847
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/index.ts,sha256=ujKK1JNdTCrKisVTeaUCgq23Dxv6nVBVgYM3L9aEFyY,373
837
848
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/knowledge-base.ts,sha256=xkCES2rU51ei-pdqwxMNsZuoTfmaT7fWteoJrOMQGzw,1053
838
849
  fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/organization.ts,sha256=-Dsw9FGzZAqbclJwnc7l3PqVJYqEehw8Kj7z7kmFYsc,1204
@@ -847,8 +858,8 @@ fastapi_gen/template/{{cookiecutter.project_slug}}/kubernetes/secret.yaml,sha256
847
858
  fastapi_gen/template/{{cookiecutter.project_slug}}/kubernetes/service.yaml,sha256=o3bCXguj8E5aQ0H1o3cBD3z_iZ_RA_Pmx1bc0sVzK28,682
848
859
  fastapi_gen/template/{{cookiecutter.project_slug}}/nginx/nginx.conf,sha256=gJWUMMqNvr9TwNZOcc_WPPGZvdAlRUH3jLhbllOb_YY,7359
849
860
  fastapi_gen/template/{{cookiecutter.project_slug}}/nginx/ssl/.gitkeep,sha256=o_WQQOgVGOLttT48x0EXSC4BbbDFemApFpmwhybcVUU,617
850
- fastapi_fullstack-0.2.13.dist-info/METADATA,sha256=eHKBe1ghpv-oLCfsrED9tl05SoqROY-2aOObdTcW8TE,59043
851
- fastapi_fullstack-0.2.13.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
852
- fastapi_fullstack-0.2.13.dist-info/entry_points.txt,sha256=s9JXrISZp8LMYJGeVofOAd1wPTzpq-jwjSgSf4hWzjs,59
853
- fastapi_fullstack-0.2.13.dist-info/licenses/LICENSE,sha256=bL4JuK_rcA8y__Gg7PEuTs3g2Qf6VvSz2w2Jajd6nVU,1063
854
- fastapi_fullstack-0.2.13.dist-info/RECORD,,
861
+ fastapi_fullstack-0.2.15.dist-info/METADATA,sha256=cUV7-TJgE9zjN2dWk8eTSypHf2UHnZR1lRK6Izkr5DY,59043
862
+ fastapi_fullstack-0.2.15.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
863
+ fastapi_fullstack-0.2.15.dist-info/entry_points.txt,sha256=s9JXrISZp8LMYJGeVofOAd1wPTzpq-jwjSgSf4hWzjs,59
864
+ fastapi_fullstack-0.2.15.dist-info/licenses/LICENSE,sha256=bL4JuK_rcA8y__Gg7PEuTs3g2Qf6VvSz2w2Jajd6nVU,1063
865
+ fastapi_fullstack-0.2.15.dist-info/RECORD,,
@@ -0,0 +1,30 @@
1
+ """conversations: add is_demo flag for public demo gallery
2
+
3
+ Revision ID: 0023
4
+ Revises: 0022
5
+ Create Date: 2026-06-22
6
+
7
+ Adds ``is_demo`` boolean column to conversations so admins can flag curated
8
+ agent runs for the public demo replay gallery (served without authentication).
9
+ """
10
+
11
+ from alembic import op
12
+ import sqlalchemy as sa
13
+
14
+ revision = "0023"
15
+ down_revision = "0022"
16
+ branch_labels = None
17
+ depends_on = None
18
+
19
+
20
+ def upgrade() -> None:
21
+ op.add_column(
22
+ "conversations",
23
+ sa.Column("is_demo", sa.Boolean(), nullable=False, server_default=sa.false()),
24
+ )
25
+ op.create_index("ix_conversations_is_demo", "conversations", ["is_demo"])
26
+
27
+
28
+ def downgrade() -> None:
29
+ op.drop_index("ix_conversations_is_demo", table_name="conversations")
30
+ op.drop_column("conversations", "is_demo")
@@ -0,0 +1,89 @@
1
+ {%- if cookiecutter.enable_webhooks %}
2
+ """create webhook tables
3
+
4
+ Revision ID: 0024_create_webhook_tables
5
+ Revises: 0023
6
+ Create Date: {{ cookiecutter.generated_at }}
7
+
8
+ Creates:
9
+ - webhooks (outbound webhook subscriptions)
10
+ - webhook_deliveries (per-attempt delivery log)
11
+ """
12
+
13
+ import sqlalchemy as sa
14
+ from sqlalchemy.dialects.postgresql import ARRAY, UUID as PG_UUID
15
+ from alembic import op
16
+
17
+ revision = "0024_create_webhook_tables"
18
+ down_revision = "0023"
19
+ branch_labels = None
20
+ depends_on = None
21
+
22
+
23
+ def upgrade() -> None:
24
+ op.create_table(
25
+ "webhooks",
26
+ sa.Column("id", PG_UUID(as_uuid=True), primary_key=True),
27
+ sa.Column("name", sa.String(255), nullable=False),
28
+ sa.Column("url", sa.String(2048), nullable=False),
29
+ sa.Column("secret", sa.String(255), nullable=False),
30
+ sa.Column("events", ARRAY(sa.String()), nullable=False),
31
+ sa.Column("is_active", sa.Boolean(), server_default=sa.text("true"), nullable=False),
32
+ sa.Column("description", sa.Text(), nullable=True),
33
+ {%- if cookiecutter.use_jwt %}
34
+ sa.Column("user_id", PG_UUID(as_uuid=True), sa.ForeignKey("users.id"), nullable=True),
35
+ {%- endif %}
36
+ sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
37
+ sa.Column("updated_at", sa.DateTime(timezone=True), nullable=True),
38
+ )
39
+ {%- if cookiecutter.use_jwt %}
40
+ op.create_index("ix_webhooks_user_id", "webhooks", ["user_id"])
41
+ {%- endif %}
42
+
43
+ op.create_table(
44
+ "webhook_deliveries",
45
+ sa.Column("id", PG_UUID(as_uuid=True), primary_key=True),
46
+ sa.Column("webhook_id", PG_UUID(as_uuid=True), sa.ForeignKey("webhooks.id"), nullable=False),
47
+ sa.Column("event_type", sa.String(100), nullable=False),
48
+ sa.Column("payload", sa.Text(), nullable=False),
49
+ sa.Column("response_status", sa.Integer(), nullable=True),
50
+ sa.Column("response_body", sa.Text(), nullable=True),
51
+ sa.Column("error_message", sa.Text(), nullable=True),
52
+ sa.Column("attempt_count", sa.Integer(), server_default=sa.text("1"), nullable=False),
53
+ sa.Column("success", sa.Boolean(), server_default=sa.text("false"), nullable=False),
54
+ sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
55
+ sa.Column("delivered_at", sa.DateTime(), nullable=True),
56
+ )
57
+ op.create_index("ix_webhook_deliveries_webhook_id", "webhook_deliveries", ["webhook_id"])
58
+ op.create_index("ix_webhook_deliveries_created_at", "webhook_deliveries", ["created_at"])
59
+
60
+
61
+ def downgrade() -> None:
62
+ op.drop_index("ix_webhook_deliveries_created_at", table_name="webhook_deliveries")
63
+ op.drop_index("ix_webhook_deliveries_webhook_id", table_name="webhook_deliveries")
64
+ op.drop_table("webhook_deliveries")
65
+ {%- if cookiecutter.use_jwt %}
66
+ op.drop_index("ix_webhooks_user_id", table_name="webhooks")
67
+ {%- endif %}
68
+ op.drop_table("webhooks")
69
+
70
+
71
+ {%- else %}
72
+ """create webhook tables — skipped (enable_webhooks=false or no SQL DB)
73
+
74
+ Revision ID: 0024_create_webhook_tables
75
+ """
76
+
77
+ revision = "0024_create_webhook_tables"
78
+ down_revision = "0023"
79
+ branch_labels = None
80
+ depends_on = None
81
+
82
+
83
+ def upgrade() -> None:
84
+ pass
85
+
86
+
87
+ def downgrade() -> None:
88
+ pass
89
+ {%- endif %}
@@ -124,6 +124,7 @@ Citations: when you use retrieved documents, attach numbered references like [1]
124
124
  Missing evidence is not automatically a "no". If the documents don't cover the question, say briefly what you couldn't find, then still help: answer from general knowledge where that's appropriate (and note that you're doing so), or ask for the specific document or detail you'd need."""
125
125
 
126
126
 
127
+ {%- if cookiecutter.enable_deep_research %}
127
128
  RESEARCH_SYSTEM_PROMPT = """You are a deep-research agent. You answer a research question by planning the work, delegating it to specialist subagents in parallel, and composing a well-sourced report. Work as a project lead, not a lone writer.
128
129
 
129
130
  # How to run a research task
@@ -144,11 +145,13 @@ The user has explicitly switched on deep research, so ALWAYS run the full resear
144
145
 
145
146
  # Cost discipline
146
147
  Keep the plan tight (3 to 6 steps), give each subagent one clear job, and don't spawn more researchers than the question needs — parallel subagents multiply token cost. Prefer one focused web pass per sub-question over many rephrasings."""
148
+ {%- endif %}
147
149
 
148
150
 
149
151
  DEFAULT_SYSTEM_PROMPT = get_default_system_prompt()
150
152
 
151
153
 
154
+ {%- if cookiecutter.enable_deep_research %}
152
155
  def get_research_prompt() -> str:
153
156
  """Return the deep-research system prompt, or the default prompt when the
154
157
  feature is disabled at runtime.
@@ -157,3 +160,4 @@ def get_research_prompt() -> str:
157
160
  if not settings.ENABLE_DEEP_RESEARCH:
158
161
  return get_system_prompt_with_rag()
159
162
  return RESEARCH_SYSTEM_PROMPT
163
+ {%- endif %}
@@ -19,7 +19,7 @@ from app.api.routes.v1 import oauth
19
19
  from app.api.routes.v1 import sessions
20
20
  {%- endif %}
21
21
  {%- if cookiecutter.use_ai %}
22
- from app.api.routes.v1 import conversations
22
+ from app.api.routes.v1 import conversations, public_demos
23
23
  {%- endif %}
24
24
  {%- if cookiecutter.use_jwt and cookiecutter.use_ai %}
25
25
  from app.api.routes.v1 import admin_conversations
@@ -104,6 +104,7 @@ v1_router.include_router(sessions.router, prefix="/sessions", tags=["sessions"])
104
104
  {%- if cookiecutter.use_ai %}
105
105
 
106
106
  v1_router.include_router(conversations.router, prefix="/conversations", tags=["conversations"])
107
+ v1_router.include_router(public_demos.router, prefix="/demos", tags=["demos"])
107
108
  {%- endif %}
108
109
 
109
110
  {%- if cookiecutter.use_pydantic_deep and cookiecutter.use_jwt %}
@@ -5,7 +5,7 @@ from uuid import UUID
5
5
  from fastapi import APIRouter, Query
6
6
 
7
7
  from app.api.deps import ConversationSvc, CurrentAdmin
8
- from app.schemas.conversation import ConversationReadWithMessages
8
+ from app.schemas.conversation import ConversationRead, ConversationReadWithMessages, ConversationUpdate
9
9
  from app.schemas.conversation_share import AdminConversationList
10
10
 
11
11
  router = APIRouter()
@@ -50,6 +50,24 @@ async def admin_get_conversation(
50
50
  return await service.get_conversation_with_messages(conversation_id)
51
51
 
52
52
 
53
+ @router.patch("/{conversation_id}/demo", response_model=ConversationRead)
54
+ async def admin_set_demo_flag(
55
+ conversation_id: UUID,
56
+ service: ConversationSvc,
57
+ _: CurrentAdmin,
58
+ is_demo: bool = Query(..., description="Mark (true) or unmark (false) as a public demo"),
59
+ ) -> Any:
60
+ """Toggle a conversation's public-demo flag (admin only).
61
+
62
+ Demo conversations are served without auth on the public demo gallery for replay.
63
+ """
64
+ return await service.update_conversation(
65
+ conversation_id,
66
+ ConversationUpdate(is_demo=is_demo),
67
+ user_id=None, # admin bypass — no ownership check
68
+ )
69
+
70
+
53
71
  {%- else %}
54
72
  """Admin conversation routes — requires JWT authentication (use_jwt)."""
55
73
  router = APIRouter()
@@ -0,0 +1,41 @@
1
+ """Public demo conversation routes (no authentication).
2
+
3
+ Serves conversations an admin has flagged ``is_demo=True`` so unauthenticated
4
+ visitors can browse and replay curated agent runs on the public demo page.
5
+ Only demo-flagged conversations are ever exposed here — regular user conversations
6
+ are never reachable through these endpoints.
7
+
8
+ Endpoints:
9
+ GET /demos — List demo conversations (gallery cards)
10
+ GET /demos/{id} — Get one demo conversation with messages + tool calls
11
+ """
12
+
13
+ from typing import Any
14
+ from uuid import UUID
15
+
16
+ from fastapi import APIRouter, Query
17
+
18
+ from app.api.deps import ConversationSvc
19
+ from app.schemas.conversation import ConversationReadWithMessages, DemoConversationList
20
+
21
+ router = APIRouter()
22
+
23
+
24
+ @router.get("", response_model=DemoConversationList)
25
+ async def list_demo_conversations(
26
+ service: ConversationSvc,
27
+ skip: int = Query(0, ge=0, description="Items to skip"),
28
+ limit: int = Query(50, ge=1, le=100, description="Max items to return"),
29
+ ) -> Any:
30
+ """List admin-curated demo conversations (public, no auth)."""
31
+ items, total = await service.list_demo_conversations(skip=skip, limit=limit)
32
+ return DemoConversationList(items=items, total=total)
33
+
34
+
35
+ @router.get("/{conversation_id}", response_model=ConversationReadWithMessages)
36
+ async def get_demo_conversation(
37
+ conversation_id: UUID,
38
+ service: ConversationSvc,
39
+ ) -> Any:
40
+ """Get a single demo conversation with all messages (public, no auth)."""
41
+ return await service.get_demo_conversation(conversation_id)
@@ -247,6 +247,7 @@ class Conversation(Base, TimestampMixin):
247
247
  {%- endif %}
248
248
  title: Mapped[str | None] = mapped_column(String(255), nullable=True)
249
249
  is_archived: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
250
+ is_demo: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False, index=True)
250
251
  {%- if cookiecutter.enable_teams and cookiecutter.enable_rag and cookiecutter.use_jwt %}
251
252
  active_knowledge_base_ids: Mapped[list[str] | None] = mapped_column(JSONB, nullable=True)
252
253
  {%- endif %}
@@ -143,6 +143,50 @@ async def export_chunk(
143
143
  return list(result.scalars().all())
144
144
 
145
145
 
146
+ async def get_demo_conversations_with_count(
147
+ db: AsyncSession,
148
+ *,
149
+ skip: int = 0,
150
+ limit: int = 50,
151
+ ) -> tuple[list[tuple[Conversation, int, str | None]], int]:
152
+ """Get admin-curated demo conversations with message count + first user prompt preview."""
153
+ message_count_subq = (
154
+ select(func.count(Message.id))
155
+ .where(Message.conversation_id == Conversation.id)
156
+ .correlate(Conversation)
157
+ .scalar_subquery()
158
+ )
159
+ preview_subq = (
160
+ select(Message.content)
161
+ .where(Message.conversation_id == Conversation.id, Message.role == "user")
162
+ .correlate(Conversation)
163
+ .order_by(Message.created_at.asc())
164
+ .limit(1)
165
+ .scalar_subquery()
166
+ )
167
+ query = (
168
+ select(
169
+ Conversation,
170
+ message_count_subq.label("message_count"),
171
+ preview_subq.label("preview"),
172
+ )
173
+ .where(Conversation.is_demo.is_(True))
174
+ .order_by(func.coalesce(Conversation.updated_at, Conversation.created_at).desc())
175
+ .offset(skip)
176
+ .limit(limit)
177
+ )
178
+ result = await db.execute(query)
179
+ rows = result.all()
180
+
181
+ total: int = (
182
+ await db.execute(
183
+ select(func.count(Conversation.id)).where(Conversation.is_demo.is_(True))
184
+ )
185
+ ).scalar() or 0
186
+
187
+ return [tuple(row) for row in rows], total # type: ignore[return-value]
188
+
189
+
146
190
  async def admin_list_with_users(
147
191
  db: AsyncSession,
148
192
  *,
@@ -154,6 +154,7 @@ class ConversationUpdate(BaseSchema):
154
154
 
155
155
  title: str | None = Field(default=None, max_length=255)
156
156
  is_archived: bool | None = None
157
+ is_demo: bool | None = None
157
158
  {%- if cookiecutter.enable_teams and cookiecutter.enable_rag and cookiecutter.use_jwt %}
158
159
  active_knowledge_base_ids: list[UUID] | None = Field(
159
160
  default=None,
@@ -193,6 +194,7 @@ class ConversationRead(ConversationBase, TimestampSchema):
193
194
  organization_id: UUID | None = None
194
195
  {%- endif %}
195
196
  is_archived: bool = False
197
+ is_demo: bool = False
196
198
  {%- if cookiecutter.enable_teams and cookiecutter.enable_rag and cookiecutter.use_jwt %}
197
199
  active_knowledge_base_ids: list[str] | None = None
198
200
  {%- endif %}
@@ -239,3 +241,21 @@ class ConversationAdminList(BaseSchema):
239
241
  class ConversationExport(BaseSchema):
240
242
  conversations: list[Any]
241
243
  total: int
244
+
245
+
246
+ class DemoConversationSummary(BaseSchema):
247
+ """Lightweight card for the public demo gallery."""
248
+
249
+ id: UUID
250
+ title: str | None = None
251
+ message_count: int = 0
252
+ preview: str | None = Field(default=None, description="First user prompt, truncated to 200 chars")
253
+ created_at: datetime
254
+ updated_at: datetime | None = None
255
+
256
+
257
+ class DemoConversationList(BaseSchema):
258
+ """Paginated list of public demo conversations."""
259
+
260
+ items: list[DemoConversationSummary]
261
+ total: int
@@ -62,6 +62,7 @@ class AdminConversationRead(BaseSchema):
62
62
  {%- endif %}
63
63
  title: str | None = None
64
64
  is_archived: bool = False
65
+ is_demo: bool = False
65
66
  message_count: int = 0
66
67
  user_email: str | None = None
67
68
  created_at: datetime