basic llm request stream

This commit is contained in:
fabien committed 2026-09-22 21:15:23 +02:00
1 parent f74e4d1043
commit a92cc76a9a
66 files changed
+1496 -158

No files matched your search

+102
View File
@@ -0,0 +1,102 @@
<mxfile host="Electron">
<diagram name="Page-1" id="6ee6LexvoJe0i-CFFPA3">
<mxGraphModel dx="1067" dy="848" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-29" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=light-dark(#FFFFFF,transparent);strokeColor=#7D7D7D;" value="" vertex="1">
<mxGeometry height="270" width="220" x="540" y="140" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-15" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-11">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-1" parent="1" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" value="ChatService" vertex="1">
<mxGeometry height="120" width="140" x="290" y="425" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-2" parent="Nf3PCM6Bg_LUHkPQi3Rq-1" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="NewChat -&amp;gt; Chat" vertex="1">
<mxGeometry height="30" width="140" y="30" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-3" parent="Nf3PCM6Bg_LUHkPQi3Rq-1" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="AddMessage" vertex="1">
<mxGeometry height="30" width="140" y="60" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-22" parent="Nf3PCM6Bg_LUHkPQi3Rq-1" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="getChat" vertex="1">
<mxGeometry height="30" width="140" y="90" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-16" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-11">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-5" parent="1" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" value="BrainHandler" vertex="1">
<mxGeometry height="150" width="140" x="590" y="450" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-6" parent="Nf3PCM6Bg_LUHkPQi3Rq-5" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="ProcessResponse" vertex="1">
<mxGeometry height="30" width="140" y="30" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-24" parent="Nf3PCM6Bg_LUHkPQi3Rq-5" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="subscribe" vertex="1">
<mxGeometry height="30" width="140" y="60" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-7" parent="Nf3PCM6Bg_LUHkPQi3Rq-5" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="Start" vertex="1">
<mxGeometry height="30" width="140" y="90" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-8" parent="Nf3PCM6Bg_LUHkPQi3Rq-5" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="Stop" vertex="1">
<mxGeometry height="30" width="140" y="120" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-10" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-6">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-11" parent="1" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" value="ChatRepository" vertex="1">
<mxGeometry height="90" width="140" x="400" y="710" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-12" parent="Nf3PCM6Bg_LUHkPQi3Rq-11" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="CreateChat" vertex="1">
<mxGeometry height="30" width="140" y="30" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-13" parent="Nf3PCM6Bg_LUHkPQi3Rq-11" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="CreateMessage" vertex="1">
<mxGeometry height="30" width="140" y="60" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-21" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-25" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-23" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-22">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-17" parent="1" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" value="WebHandler" vertex="1">
<mxGeometry height="120" width="140" x="30" y="425" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-18" parent="Nf3PCM6Bg_LUHkPQi3Rq-17" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="NewChat" vertex="1">
<mxGeometry height="30" width="140" y="30" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-25" parent="Nf3PCM6Bg_LUHkPQi3Rq-17" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="NewMessage" vertex="1">
<mxGeometry height="30" width="140" y="60" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-19" parent="Nf3PCM6Bg_LUHkPQi3Rq-17" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="GetChatWithMessages" vertex="1">
<mxGeometry height="30" width="140" y="90" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-26" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-2">
<mxGeometry relative="1" as="geometry">
<mxPoint x="240" y="400" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-27" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-24">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-28" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-6">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-38" parent="1" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" value="RunningSession" vertex="1">
<mxGeometry height="120" width="140" x="570" y="230" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-39" parent="Nf3PCM6Bg_LUHkPQi3Rq-38" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="Item 1" vertex="1">
<mxGeometry height="30" width="140" y="30" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-40" parent="Nf3PCM6Bg_LUHkPQi3Rq-38" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="Item 2" vertex="1">
<mxGeometry height="30" width="140" y="60" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-41" parent="Nf3PCM6Bg_LUHkPQi3Rq-38" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="Item 3" vertex="1">
<mxGeometry height="30" width="140" y="90" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-42" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="Goroutine" vertex="1">
<mxGeometry height="30" width="60" x="560" y="150" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
+108
View File
@@ -0,0 +1,108 @@
<mxfile host="Electron">
<diagram name="Page-1" id="6ee6LexvoJe0i-CFFPA3">
<mxGraphModel dx="1067" dy="848" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-43" parent="1" style="rounded=0;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="250" width="510" x="260" y="380" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-29" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=light-dark(#FFFFFF,transparent);strokeColor=#7D7D7D;" value="" vertex="1">
<mxGeometry height="270" width="220" x="520" y="50" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-15" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-11">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-1" parent="1" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" value="ChatService" vertex="1">
<mxGeometry height="120" width="140" x="290" y="425" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-2" parent="Nf3PCM6Bg_LUHkPQi3Rq-1" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="NewChat -&amp;gt; Chat" vertex="1">
<mxGeometry height="30" width="140" y="30" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-3" parent="Nf3PCM6Bg_LUHkPQi3Rq-1" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="AddMessage" vertex="1">
<mxGeometry height="30" width="140" y="60" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-22" parent="Nf3PCM6Bg_LUHkPQi3Rq-1" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="getChat" vertex="1">
<mxGeometry height="30" width="140" y="90" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-16" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-11">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-5" parent="1" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" value="BrainHandler" vertex="1">
<mxGeometry height="150" width="140" x="590" y="450" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-6" parent="Nf3PCM6Bg_LUHkPQi3Rq-5" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="ProcessResponse" vertex="1">
<mxGeometry height="30" width="140" y="30" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-24" parent="Nf3PCM6Bg_LUHkPQi3Rq-5" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="subscribe" vertex="1">
<mxGeometry height="30" width="140" y="60" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-7" parent="Nf3PCM6Bg_LUHkPQi3Rq-5" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="Start" vertex="1">
<mxGeometry height="30" width="140" y="90" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-8" parent="Nf3PCM6Bg_LUHkPQi3Rq-5" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="Stop" vertex="1">
<mxGeometry height="30" width="140" y="120" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-10" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-6">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-11" parent="1" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" value="ChatRepository" vertex="1">
<mxGeometry height="90" width="140" x="400" y="710" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-12" parent="Nf3PCM6Bg_LUHkPQi3Rq-11" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="CreateChat" vertex="1">
<mxGeometry height="30" width="140" y="30" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-13" parent="Nf3PCM6Bg_LUHkPQi3Rq-11" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="CreateMessage" vertex="1">
<mxGeometry height="30" width="140" y="60" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-21" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-25" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-23" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-22">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-17" parent="1" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" value="WebHandler" vertex="1">
<mxGeometry height="120" width="140" x="30" y="425" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-18" parent="Nf3PCM6Bg_LUHkPQi3Rq-17" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="NewChat" vertex="1">
<mxGeometry height="30" width="140" y="30" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-25" parent="Nf3PCM6Bg_LUHkPQi3Rq-17" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="NewMessage" vertex="1">
<mxGeometry height="30" width="140" y="60" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-19" parent="Nf3PCM6Bg_LUHkPQi3Rq-17" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="GetChatWithMessages" vertex="1">
<mxGeometry height="30" width="140" y="90" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-26" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-2">
<mxGeometry relative="1" as="geometry">
<mxPoint x="240" y="400" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-27" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-24">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-28" edge="1" parent="1" source="Nf3PCM6Bg_LUHkPQi3Rq-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="Nf3PCM6Bg_LUHkPQi3Rq-6">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-38" parent="1" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" value="RunningSession" vertex="1">
<mxGeometry height="120" width="140" x="550" y="140" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-39" parent="Nf3PCM6Bg_LUHkPQi3Rq-38" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="Item 1" vertex="1">
<mxGeometry height="30" width="140" y="30" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-40" parent="Nf3PCM6Bg_LUHkPQi3Rq-38" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="Item 2" vertex="1">
<mxGeometry height="30" width="140" y="60" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-41" parent="Nf3PCM6Bg_LUHkPQi3Rq-38" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" value="Item 3" vertex="1">
<mxGeometry height="30" width="140" y="90" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-42" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="Goroutine" vertex="1">
<mxGeometry height="30" width="60" x="540" y="60" as="geometry" />
</mxCell>
<mxCell id="Nf3PCM6Bg_LUHkPQi3Rq-44" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="Fusionner" vertex="1">
<mxGeometry height="30" width="60" x="480" y="380" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
+21 -12
View File
@@ -16,10 +16,11 @@ import (
"trankilou.fr/lassistanoque/backend/internal/adapter/file"
"trankilou.fr/lassistanoque/backend/internal/adapter/llm"
"trankilou.fr/lassistanoque/backend/internal/adapter/security"
"trankilou.fr/lassistanoque/backend/internal/brain"
"trankilou.fr/lassistanoque/backend/internal/http"
"trankilou.fr/lassistanoque/backend/internal/llmserver"
"trankilou.fr/lassistanoque/backend/internal/service/agent"
"trankilou.fr/lassistanoque/backend/internal/service/auth"
"trankilou.fr/lassistanoque/backend/internal/service/chat"
"trankilou.fr/lassistanoque/backend/internal/service/provider"
"trankilou.fr/lassistanoque/backend/internal/service/storage"
"trankilou.fr/lassistanoque/backend/internal/service/user"
@@ -67,6 +68,10 @@ func runServe() {
tokenManager := security.NewJwtTokenManager(12*time.Hour, 7*24*time.Hour, "lassistanoque")
pwdAuth := password.NewPasswordAuthenticator(tokenManager, db.UserRepository())
llmEngine := llm.NewAnyLLMEngine()
repoUser := db.UserRepository()
repoProvider := db.ProviderRepository()
repoAgent := db.AgentRepository()
repoChat := db.ChatRepository()
// services
authService := auth.NewService(
@@ -76,36 +81,40 @@ func runServe() {
"password": pwdAuth,
},
)
userService := user.NewService(db.UserRepository())
userService := user.NewService(repoUser)
storageService := storage.NewService(store)
providerService := provider.NewService(db.ProviderRepository(), db.UserRepository(), llmEngine)
agentService := agent.NewService(db.AgentRepository(), db.UserRepository())
providerService := provider.NewService(repoProvider, repoUser, llmEngine)
agentService := agent.NewService(repoAgent, repoUser)
chatService := chat.NewService(repoUser, repoAgent, repoProvider, repoChat, llmEngine)
// http server
router := http.NewRouter(http.Dependencies{
httpRouter := http.NewRouter(http.Dependencies{
StorageService: storageService,
AuthService: authService,
UserService: userService,
TokenManager: tokenManager,
ProviderService: providerService,
AgentService: agentService,
ChatService: chatService,
})
llms := llmserver.NewLLMServer(llmserver.Dependencies{})
brainRouter := brain.NewRouter(brain.Dependencies{
ChatRepository: db.ChatRepository(),
})
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
// start LLM service
// start Brain router
go func() {
if err := llms.Start(); err != nil && !errors.Is(err, nethttp.ErrServerClosed) {
if err := brainRouter.Start(); err != nil && !errors.Is(err, nethttp.ErrServerClosed) {
slog.Error("failed to start llm server", "error", err)
}
}()
// start HTTP service
// start HTTP router
go func() {
if err := router.Start(); err != nil && !errors.Is(err, nethttp.ErrServerClosed) {
if err := httpRouter.Start(); err != nil && !errors.Is(err, nethttp.ErrServerClosed) {
slog.Error("failed to start http server", "error", err)
}
}()
@@ -115,7 +124,7 @@ func runServe() {
// stop HTTP service
ctx, cancel1 := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel1()
if err := router.Stop(ctx); err != nil {
if err := httpRouter.Stop(ctx); err != nil {
slog.Error("failed to stop http server", "error", err)
}
slog.Info("HTTP server stopped gracefully")
@@ -123,7 +132,7 @@ func runServe() {
// stop LLM service
ctx, cancel2 := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel2()
if err := llms.Stop(ctx); err != nil {
if err := brainRouter.Stop(ctx); err != nil {
slog.Error("failed to stop llm server", "error", err)
}
slog.Info("LLM server stopped gracefully")
@@ -14,6 +14,7 @@ type Database interface {
FileRepository() domain.FileRepository
ProviderRepository() domain.ProviderRepository
AgentRepository() domain.AgentRepository
ChatRepository() domain.ChatRepository
Migrate() error
Close()
}
+7 -5
View File
@@ -41,12 +41,14 @@ func NewTable[T any](db *sql.DB, dialect Dialect, tablename string) (Table[T], e
fields := make([]dbfield, 0)
for field := range t.Fields() {
f := dbfield{
name: field.Name,
stype: field.Type.String(),
dbname: field.Tag.Get("db"),
if field.Tag.Get("db") != "-" {
f := dbfield{
name: field.Name,
stype: field.Type.String(),
dbname: field.Tag.Get("db"),
}
fields = append(fields, f)
}
fields = append(fields, f)
}
return Table[T]{
@@ -10,24 +10,24 @@ import (
type TursoAgentRepository struct {
db *sql.DB
AgentTable orm.Table[domain.Agent]
agentTable orm.Table[domain.Agent]
}
func NewTursoAgentRepository(db *sql.DB) *TursoAgentRepository {
dialect := orm.NewSqliteDialect()
AgentTable, err := orm.NewTable[domain.Agent](db, dialect, "agents")
agentTable, err := orm.NewTable[domain.Agent](db, dialect, "agents")
if err != nil {
log.Fatalf("error creating lasebuche agent table")
}
return &TursoAgentRepository{
db: db,
AgentTable: AgentTable,
agentTable: agentTable,
}
}
func (r *TursoAgentRepository) ListAgents(userID string, teamID string) ([]*domain.Agent, error) {
return r.AgentTable.Select(
return r.agentTable.Select(
orm.WithWhere(
"team_id=$1 and team_id in (select team_id from user_teams where user_id=$2)",
teamID,
@@ -37,7 +37,7 @@ func (r *TursoAgentRepository) ListAgents(userID string, teamID string) ([]*doma
}
func (r *TursoAgentRepository) GetAgent(userID string, teamID string, id string) (*domain.Agent, error) {
return r.AgentTable.SelectOne(
return r.agentTable.SelectOne(
"id=$1 and team_id=$2 and team_id in (select team_id from user_teams where user_id=$3)",
id,
teamID,
@@ -46,15 +46,15 @@ func (r *TursoAgentRepository) GetAgent(userID string, teamID string, id string)
}
func (r *TursoAgentRepository) CreateAgent(userID string, agent *domain.Agent) (*domain.Agent, error) {
return r.AgentTable.Insert(agent)
return r.agentTable.Insert(agent)
}
func (r *TursoAgentRepository) UpdateAgent(userID string, agent *domain.Agent) (*domain.Agent, error) {
return r.AgentTable.Update(agent)
return r.agentTable.Update(agent)
}
func (r *TursoAgentRepository) DeleteAgent(userID string, teamID string, id string) error {
return r.AgentTable.DeleteWhere(
return r.agentTable.DeleteWhere(
"id=$1 and team_id=$2 and team_id in (select team_id from user_teams where user_id=$3)",
id,
teamID,
@@ -0,0 +1,83 @@
package turso
import (
"database/sql"
"log"
"trankilou.fr/lassistanoque/backend/internal/adapter/database/orm"
"trankilou.fr/lassistanoque/backend/internal/domain"
)
type TursoChatRepository struct {
db *sql.DB
chatTable orm.Table[domain.Chat]
messageTable orm.Table[domain.Message]
}
func NewTursoChatRepository(db *sql.DB) *TursoChatRepository {
dialect := orm.NewSqliteDialect()
chatTable, err := orm.NewTable[domain.Chat](db, dialect, "chats")
messageTable, err := orm.NewTable[domain.Message](db, dialect, "chat_messages")
if err != nil {
log.Fatalf("error creating lasebuche agent table")
}
return &TursoChatRepository{
db: db,
chatTable: chatTable,
messageTable: messageTable,
}
}
func (r *TursoChatRepository) ListChats(userID string, teamID string, page int) ([]*domain.Chat, error) {
return r.chatTable.Select(
orm.WithWhere(
"team_id=$1 and team_id in (select team_id from user_teams where user_id=$2)",
teamID,
userID,
),
orm.WithPagination(page, 50),
)
}
func (r *TursoChatRepository) GetChat(userID string, teamID string, id string) (*domain.Chat, error) {
return r.chatTable.SelectOne(
"id=$1 and team_id=$2 and team_id in (select team_id from user_teams where user_id=$3)",
id,
teamID,
userID,
)
}
func (r *TursoChatRepository) CreateChat(userID string, chat *domain.Chat) (*domain.Chat, error) {
return r.chatTable.Insert(chat)
}
func (r *TursoChatRepository) UpdateChat(userID string, chat *domain.Chat) (*domain.Chat, error) {
return r.chatTable.Update(chat)
}
func (r *TursoChatRepository) DeleteChat(userID string, teamID string, id string) error {
return r.chatTable.DeleteWhere(
"id=$1 and team_id=$2 and team_id in (select team_id from user_teams where user_id=$3)",
id,
teamID,
userID,
)
}
func (r *TursoChatRepository) GetChatMessages(userID string, teamID string, chatID string) ([]*domain.Message, error) {
return r.messageTable.Select(
orm.WithWhere(
"chat_id=$1 and team_id=$2 and team_id in (select team_id from user_teams where user_id=$3)",
chatID,
teamID,
userID,
),
orm.WithOrder("_date_created asc"),
)
}
func (r *TursoChatRepository) CreateChatMessage(userID string, message *domain.Message) (*domain.Message, error) {
return r.messageTable.Insert(message)
}
@@ -75,3 +75,7 @@ func (db *TursoDB) ProviderRepository() domain.ProviderRepository {
func (db *TursoDB) AgentRepository() domain.AgentRepository {
return NewTursoAgentRepository(db.DB)
}
func (db *TursoDB) ChatRepository() domain.ChatRepository {
return NewTursoChatRepository(db.DB)
}
@@ -9,6 +9,7 @@ drop table user_teams;
drop table channels;
drop table tools;
drop table tasks;
drop table history;
drop table chats;
drop table chat_contents;
drop table files;
drop table agents;
@@ -117,14 +117,30 @@ create table tasks (
_version text not null
);
create table history (
create table chats (
id text not null primary key,
task_id text not null,
start_datetime numeric,
team_id text not null,
start_datetime numeric not null,
end_datetime numeric,
prompt text not null,
log text not null,
response text not null,
agent_id text,
user_id text,
task_id text,
title text,
_date_created numeric not null default current_timestamp,
_date_updated numeric,
_version text not null
);
create table chat_messages (
id text not null primary key,
team_id text not null,
chat_id text not null,
content_datetime numeric,
role text not null,
content text,
agent_id text,
tool_call_id text,
tool_calls text,
_date_created numeric not null default current_timestamp,
_date_updated numeric,
_version text not null
+43 -11
View File
@@ -5,6 +5,7 @@ import (
"fmt"
anyllm "github.com/mozilla-ai/any-llm-go"
"github.com/mozilla-ai/any-llm-go/providers"
"github.com/mozilla-ai/any-llm-go/providers/anthropic"
"github.com/mozilla-ai/any-llm-go/providers/ollama"
"github.com/mozilla-ai/any-llm-go/providers/openai"
@@ -79,13 +80,13 @@ func (e *AnyLLMEngine) Stream(
ctx context.Context,
provider *domain.Provider,
modelID string,
params *domain.StreamParams,
params *domain.LLMParams,
messages []*domain.Message,
) error {
) (*domain.Message, error) {
p, err := providerFactory(provider)
if err != nil {
return err
return nil, err
}
anyllmMessages := make([]anyllm.Message, 0)
@@ -96,26 +97,57 @@ func (e *AnyLLMEngine) Stream(
})
}
if params.ReasoningEffort == "" {
params.ReasoningEffort = "none"
}
chunkChan, errChan := p.CompletionStream(ctx, anyllm.CompletionParams{
Model: modelID,
Messages: anyllmMessages,
Stream: true,
Model: modelID,
Messages: anyllmMessages,
Stream: true,
ReasoningEffort: providers.ReasoningEffort(params.ReasoningEffort),
})
fullContent := ""
role := anyllm.RoleAssistant
for chunk := range chunkChan {
if len(chunk.Choices) > 0 {
content := chunk.Choices[0].Delta.Content
reasoning := chunk.Choices[0].Delta.Reasoning
if params.OnChunk != nil {
params.OnChunk(&domain.Chunk{
Content: content,
})
if content != "" {
fullContent += content
params.OnChunk(&domain.Chunk{
Done: false,
Role: role,
Content: content,
Reasoning: false,
})
} else if reasoning != nil {
params.OnChunk(&domain.Chunk{
Done: false,
Role: role,
Content: reasoning.Content,
Reasoning: true,
})
}
}
}
}
params.OnChunk(&domain.Chunk{
Done: true,
Role: role,
Content: "",
})
if err := <-errChan; err != nil {
return err
return nil, err
}
return nil
return &domain.Message{
Role: role,
Content: fullContent,
}, nil
}
@@ -1,17 +1,19 @@
package llmserver
package brain
import (
"context"
"fmt"
"sync"
"trankilou.fr/lassistanoque/backend/internal/domain"
"trankilou.fr/lassistanoque/backend/internal/utility"
)
type Dependencies struct {
ChatRepository domain.ChatRepository
}
type LLMServer struct {
type Router struct {
started bool
mu sync.Mutex
sessions map[string]*Session // running sessions
@@ -19,8 +21,8 @@ type LLMServer struct {
closeChan chan bool
}
func NewLLMServer(deps Dependencies) *LLMServer {
return &LLMServer{
func NewRouter(deps Dependencies) *Router {
return &Router{
started: true,
sessions: make(map[string]*Session),
newSessionChan: make(chan string),
@@ -28,7 +30,7 @@ func NewLLMServer(deps Dependencies) *LLMServer {
}
}
func (s *LLMServer) Start() error {
func (s *Router) Start() error {
for {
select {
@@ -40,13 +42,13 @@ func (s *LLMServer) Start() error {
}
func (s *LLMServer) Stop(ctx context.Context) error {
func (s *Router) Stop(ctx context.Context) error {
s.closeChan <- true
s.started = false
return nil
}
func (s *LLMServer) StartSession() (*Session, error) {
func (s *Router) StartSession() (*Session, error) {
sid := utility.GenID()
session := &Session{}
@@ -56,3 +58,9 @@ func (s *LLMServer) StartSession() (*Session, error) {
return session, nil
}
func (s *Router) Process(ctx context.Context, Chat *domain.ChatWithMessages) error {
s.closeChan <- true
s.started = false
return nil
}
+6
View File
@@ -0,0 +1,6 @@
package brain
type Session struct {
serverID string
chatID string
}
+60 -30
View File
@@ -1,32 +1,47 @@
package domain
import "context"
import (
"context"
"time"
)
type LLMModelDetail struct {
ParentModel string `json:"parent_model"`
Format string `json:"format"`
Family string `json:"family"`
Families []string `json:"families"`
ParameterSize string `json:"parameter_size"`
QuantizationLevel string `json:"quantization_level"`
}
type LLMModel struct {
Name string `json:"name"`
Model string `json:"model"`
ModifiedAt int64 `json:"modified_at"`
Size int64 `json:"size"`
Digest string `json:"digest"`
Detail *LLMModelDetail `json:"detail"`
type Chat struct {
ID string `db:"id" json:"id"`
TeamID string `db:"team_id" json:"teamId"`
StartDatetime *time.Time `db:"start_datetime" json:"startDatetime"`
EndDatetime *time.Time `db:"end_datetime" json:"endDatetime"`
AgentID string `db:"agent_id" json:"agentId"`
UserID string `db:"user_id" json:"userId"`
TaskID string `db:"task_id" json:"taskId,omitempty"`
Title string `db:"title" json:"title"`
DateCreated time.Time `db:"_date_created" json:"_date_created"`
DateUpdated *time.Time `db:"_date_updated" json:"_date_updated"`
VersionId string `db:"_version" json:"_version"`
}
type Message struct {
Role string
Content string
ToolCalls []ToolCall
ToolCallID string
ID string `db:"id" json:"id"`
TeamID string `db:"team_id" json:"teamId"`
ChatID string `db:"chat_id" json:"chatId"`
Role string `db:"role" json:"role"`
Content string `db:"content" json:"content"`
ToolCallID string `db:"tool_call_id" json:"toolCallId"`
ToolCalls []ToolCall `db:"-" json:"toolcalls"`
ToolCallsJson string `db:"tool_calls" json:"-"`
DateCreated time.Time `db:"_date_created" json:"_date_created"`
DateUpdated *time.Time `db:"_date_updated" json:"_date_updated"`
VersionId string `db:"_version" json:"_version"`
}
//Reasoning *Reasoning
type ChatWithMessages struct {
Chat *Chat `json:"chat"`
Messages []*Message `json:"messages"`
}
type ChatParams struct {
ProviderID string
ModelID string
OnChunk StreamCallback
}
type Tool struct {
@@ -36,14 +51,13 @@ type ToolCall struct {
}
type Chunk struct {
Content string
Done bool `json:"done"`
Role string `json:"role"`
Content string `json:"content"`
Reasoning bool
}
type StreamParams struct {
Tools []*Tool
OnChunk func(chunk *Chunk)
OnDebug func()
}
type StreamCallback func(chunk *Chunk)
type Role string
@@ -54,6 +68,12 @@ const (
RoleTool Role = "tool"
)
type LLMParams struct {
Tools []*Tool
OnChunk StreamCallback
ReasoningEffort string
}
type LLMEngine interface {
ListProviderTypes() []Item
ListModelsFromProvider(ctx context.Context, provider *Provider) ([]string, error)
@@ -61,7 +81,17 @@ type LLMEngine interface {
ctx context.Context,
provider *Provider,
modelID string,
params *StreamParams,
params *LLMParams,
messages []*Message,
) error
) (*Message, error)
}
type ChatRepository interface {
ListChats(userID string, teamID string, page int) ([]*Chat, error)
GetChat(userID string, teamID string, id string) (*Chat, error)
CreateChat(userID string, chat *Chat) (*Chat, error)
UpdateChat(userID string, chat *Chat) (*Chat, error)
DeleteChat(userID string, teamID string, id string) error
GetChatMessages(userID string, teamID string, id string) ([]*Message, error)
CreateChatMessage(userID string, message *Message) (*Message, error)
}
+7 -7
View File
@@ -42,7 +42,7 @@ func (h *AgentHandler) ListAgents(c *echo.Context) error {
teamID := c.Param("space")
agents, err := h.agentService.ListAgents(userID, teamID)
if err != nil {
c.Logger().Error("error listing agents", err)
c.Logger().Error("error listing agents", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error listing agents")
}
return c.JSON(http.StatusOK, agents)
@@ -54,7 +54,7 @@ func (h *AgentHandler) GetAgent(c *echo.Context) error {
agentID := c.Param("agent")
agent, err := h.agentService.GetAgent(userID, teamID, agentID)
if err != nil {
c.Logger().Error("error getting agent: %s", err)
c.Logger().Error("error getting agent", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error getting agent")
}
return c.JSON(http.StatusOK, agent)
@@ -66,13 +66,13 @@ func (h *AgentHandler) CreateAgent(c *echo.Context) error {
var agent domain.Agent
err := c.Bind(&agent)
if err != nil {
c.Logger().Error("error binding agent : %s", err)
c.Logger().Error("error binding agent", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error binding agent")
}
agent.TeamID = teamID
updagent, err := h.agentService.CreateAgent(userID, &agent)
if err != nil {
c.Logger().Error("error creating agent: %s", err)
c.Logger().Error("error creating agent", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error creating agent")
}
return c.JSON(http.StatusOK, updagent)
@@ -84,13 +84,13 @@ func (h *AgentHandler) UpdateAgent(c *echo.Context) error {
var agent domain.Agent
err := c.Bind(&agent)
if err != nil {
c.Logger().Error("error binding agent : %s", err)
c.Logger().Error("error binding agent", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error binding agent")
}
agent.TeamID = teamID
updagent, err := h.agentService.UpdateAgent(userID, &agent)
if err != nil {
c.Logger().Error("error updating agent: %s", err)
c.Logger().Error("error updating agent", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error updating agent")
}
return c.JSON(http.StatusOK, updagent)
@@ -102,7 +102,7 @@ func (h *AgentHandler) DeleteAgent(c *echo.Context) error {
agentID := c.Param("agent")
err := h.agentService.DeleteAgent(userID, teamID, agentID)
if err != nil {
c.Logger().Error("error creating agent: %s", err)
c.Logger().Error("error creating agent", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error creating agent")
}
return c.JSON(http.StatusOK, agentID)
+182
View File
@@ -0,0 +1,182 @@
package handlers
import (
"encoding/json"
"log/slog"
"net/http"
"strconv"
"github.com/labstack/echo/v5"
"trankilou.fr/lassistanoque/backend/internal/domain"
"trankilou.fr/lassistanoque/backend/internal/service/auth"
"trankilou.fr/lassistanoque/backend/internal/service/chat"
)
func NewChatGroup(prefix string, e *echo.Group, service *chat.Service, middlewares ...echo.MiddlewareFunc) *echo.Group {
chatHandler := &ChatHandler{
chatService: service,
}
auth := e.Group(prefix, middlewares...)
auth.POST("/:space", chatHandler.NewChat)
auth.POST("/:space/:id", chatHandler.NewChatMessage)
auth.GET("/:space/all/:page", chatHandler.List)
auth.GET("/:space/:id", chatHandler.Get)
auth.GET("/:space/:id/subscribe", chatHandler.Subscribe)
auth.DELETE("/:space/:id", chatHandler.Delete)
return auth
}
type ChatHandler struct {
chatService *chat.Service
}
type ChatRequest struct {
Prompt string `json:"prompt"`
AgentID string `json:"agentID"`
ProviderID string `json:"providerID"`
ModelID string `json:"modelID"`
ReasoningLevel string `json:"reasoningLevel"`
}
func (h *ChatHandler) NewChat(c *echo.Context) error {
userID := c.Get(auth.ContextUserIDKey).(string)
teamID := c.Param("space")
var request ChatRequest
err := c.Bind(&request)
if err != nil {
c.Logger().Error("error binding request", "error", err.Error())
return echo.NewHTTPError(http.StatusBadRequest, "error binding request")
}
chat, err := h.chatService.NewChat(
userID,
teamID,
request.AgentID,
)
if err != nil {
c.Logger().Error("error creating chat", "error", err.Error())
return echo.NewHTTPError(http.StatusBadRequest, "error creating chat")
}
return c.JSON(http.StatusOK, chat)
}
func (h *ChatHandler) NewChatMessage(c *echo.Context) error {
userID := c.Get(auth.ContextUserIDKey).(string)
teamID := c.Param("space")
chatID := c.Param("id")
var request ChatRequest
err := c.Bind(&request)
if err != nil {
c.Logger().Error("error binding request", "error", err.Error())
return echo.NewHTTPError(http.StatusBadRequest, "error binding request")
}
enc := json.NewEncoder(c.Response())
chunkChan := make(chan *domain.Chunk)
_, err = h.chatService.AddChatMessage(
c.Request().Context(),
userID,
teamID,
chatID,
request.AgentID,
request.Prompt,
&domain.ChatParams{
OnChunk: func(chunk *domain.Chunk) {
chunkChan <- chunk
},
},
)
if err != nil {
c.Logger().Error("error creating chat message", "error", err.Error())
return echo.NewHTTPError(http.StatusBadRequest, "error creating chat message")
}
enc.Encode(&domain.Chunk{
Done: false,
Role: string(domain.RoleUser),
Content: request.Prompt,
})
http.NewResponseController(c.Response()).Flush()
for {
chunk := <-chunkChan
slog.Info("Chunk", "role", chunk.Role, "content", chunk.Content, "reasoning", chunk.Reasoning)
if chunk.Done {
return nil
}
enc.Encode(chunk)
http.NewResponseController(c.Response()).Flush()
}
}
func (h *ChatHandler) List(c *echo.Context) error {
userID := c.Get(auth.ContextUserIDKey).(string)
teamID := c.Param("space")
page := c.Param("page")
pageInt, _ := strconv.Atoi(page)
chats, err := h.chatService.ListChats(userID, teamID, pageInt)
if err != nil {
c.Logger().Error("error listing chats", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error listing chats")
}
return c.JSON(http.StatusOK, chats)
}
func (h *ChatHandler) Get(c *echo.Context) error {
userID := c.Get(auth.ContextUserIDKey).(string)
teamID := c.Param("space")
chatID := c.Param("id")
chatWithMessages, err := h.chatService.GetChatWithMessages(userID, teamID, chatID)
if err != nil {
c.Logger().Error("error getting chat with messages", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error getting chat")
}
return c.JSON(http.StatusOK, chatWithMessages)
}
func (h *ChatHandler) Delete(c *echo.Context) error {
userID := c.Get(auth.ContextUserIDKey).(string)
teamID := c.Param("space")
chatID := c.Param("id")
err := h.chatService.DeleteChat(userID, teamID, chatID)
if err != nil {
c.Logger().Error("error deleting chat", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error deleting chat")
}
return c.JSON(http.StatusOK, "chat deleted")
}
func (h *ChatHandler) Subscribe(c *echo.Context) error {
userID := c.Get(auth.ContextUserIDKey).(string)
teamID := c.Param("space")
chatID := c.Param("id")
enc := json.NewEncoder(c.Response())
chunkChan := make(chan *domain.Chunk)
err := h.chatService.Subscribe(
userID,
teamID,
chatID,
func(chunk *domain.Chunk) {
chunkChan <- chunk
},
)
if err != nil {
c.Logger().Error("error subscribing to chat", "error", err.Error())
return echo.NewHTTPError(http.StatusBadRequest, "error creating chat")
}
for {
chunk := <-chunkChan
if chunk.Done {
return nil
}
enc.Encode(chunk)
http.NewResponseController(c.Response()).Flush()
}
}
+10 -10
View File
@@ -40,7 +40,7 @@ func (h *ModelHandler) ListProviders(c *echo.Context) error {
teamID := c.Param("space")
providers, err := h.providerService.ListProviders(userID, teamID)
if err != nil {
c.Logger().Error("error listing providers: %s", err)
c.Logger().Error("error listing providers", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error listing providers")
}
return c.JSON(http.StatusOK, providers)
@@ -52,7 +52,7 @@ func (h *ModelHandler) GetProvider(c *echo.Context) error {
providerID := c.Param("provider")
provider, err := h.providerService.GetProvider(userID, teamID, providerID)
if err != nil {
c.Logger().Error("error getting provider: %s", err)
c.Logger().Error("error getting provider", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error getting provider")
}
return c.JSON(http.StatusOK, provider)
@@ -64,13 +64,13 @@ func (h *ModelHandler) CreateProvider(c *echo.Context) error {
var provider domain.Provider
err := c.Bind(&provider)
if err != nil {
c.Logger().Error("error binding provider: %s", err)
c.Logger().Error("error binding provider", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error binding provider")
}
provider.TeamID = teamID
updprovider, err := h.providerService.CreateProvider(userID, &provider)
if err != nil {
c.Logger().Error("error creating provider: %s", err)
c.Logger().Error("error creating provider", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error creating provider")
}
return c.JSON(http.StatusOK, updprovider)
@@ -82,13 +82,13 @@ func (h *ModelHandler) UpdateProvider(c *echo.Context) error {
var provider domain.Provider
err := c.Bind(&provider)
if err != nil {
c.Logger().Error("error binding provider: %s", err)
c.Logger().Error("error binding provider", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error binding provider")
}
provider.TeamID = teamID
updprovider, err := h.providerService.UpdateProvider(userID, &provider)
if err != nil {
c.Logger().Error("error updating provider: %s", err)
c.Logger().Error("error updating provider", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error creating provider")
}
return c.JSON(http.StatusOK, updprovider)
@@ -100,7 +100,7 @@ func (h *ModelHandler) DeleteProvider(c *echo.Context) error {
providerID := c.Param("provider")
err := h.providerService.DeleteProvider(userID, teamID, providerID)
if err != nil {
c.Logger().Error("error creating provider: %s", err)
c.Logger().Error("error creating provider", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error creating provider")
}
return c.JSON(http.StatusOK, providerID)
@@ -111,13 +111,13 @@ func (h *ModelHandler) ListAvailableModels(c *echo.Context) error {
var provider domain.Provider
err := c.Bind(&provider)
if err != nil {
c.Logger().Error("error binding provider: %s", err)
c.Logger().Error("error binding provider", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error binding provider")
}
provider.TeamID = teamID
list, err := h.providerService.ListAvailableModels(c.Request().Context(), &provider)
if err != nil {
c.Logger().Error("error listing available models: %s", err)
c.Logger().Error("error listing available models", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error listing available models")
}
return c.JSON(http.StatusOK, list)
@@ -128,7 +128,7 @@ func (h *ModelHandler) ListProvidersModels(c *echo.Context) error {
teamID := c.Param("space")
list, err := h.providerService.ListProvidersModels(userID, teamID)
if err != nil {
c.Logger().Error("error listing providers models: %s", err)
c.Logger().Error("error listing providers models", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "error listing providers models")
}
return c.JSON(http.StatusOK, list)
+3
View File
@@ -13,6 +13,7 @@ import (
"trankilou.fr/lassistanoque/backend/internal/http/handlers"
"trankilou.fr/lassistanoque/backend/internal/service/agent"
"trankilou.fr/lassistanoque/backend/internal/service/auth"
"trankilou.fr/lassistanoque/backend/internal/service/chat"
"trankilou.fr/lassistanoque/backend/internal/service/provider"
"trankilou.fr/lassistanoque/backend/internal/service/storage"
"trankilou.fr/lassistanoque/backend/internal/service/user"
@@ -40,6 +41,7 @@ type Dependencies struct {
UserService *user.Service
ProviderService *provider.Service
AgentService *agent.Service
ChatService *chat.Service
TokenManager auth.TokenManager
}
@@ -81,6 +83,7 @@ func NewRouter(deps Dependencies) *Router {
_ = handlers.NewModelGroup("/provider", api, deps.ProviderService, deps.TokenManager.TokenMiddleware)
_ = handlers.NewAgentGroup("/agent", api, deps.AgentService, deps.UserService, deps.TokenManager.TokenMiddleware)
_ = handlers.NewTeamGroup("/team", api, deps.UserService, deps.TokenManager.TokenMiddleware)
_ = handlers.NewChatGroup("/chat", api, deps.ChatService, deps.TokenManager.TokenMiddleware)
server := http.Server{
Addr: fmt.Sprintf(":%d", cfg.HttpPort),
@@ -1,2 +0,0 @@
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-outline-style:solid;--tw-duration:initial;--tw-leading:initial;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-ease:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-700:oklch(50.5% .213 27.518);--color-red-900:oklch(39.6% .141 25.723);--color-green-300:oklch(87.1% .15 154.449);--color-green-700:oklch(52.7% .154 150.069);--color-cyan-600:oklch(60.9% .126 221.723);--color-sky-300:oklch(82.8% .111 230.318);--color-sky-700:oklch(50% .134 242.749);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-900:oklch(37.9% .146 265.522);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-800:oklch(27.8% .033 256.848);--color-stone-50:oklch(98.5% .001 106.423);--color-stone-100:oklch(97% .001 106.424);--color-stone-200:oklch(92.3% .003 48.717);--color-stone-300:oklch(86.9% .005 56.366);--color-stone-400:oklch(70.9% .01 56.259);--color-stone-500:oklch(55.3% .013 58.071);--color-stone-600:oklch(44.4% .011 73.639);--color-stone-700:oklch(37.4% .01 67.558);--color-stone-800:oklch(26.8% .007 34.298);--color-stone-900:oklch(21.6% .006 56.043);--color-stone-950:oklch(14.7% .004 49.25);--color-white:#fff;--spacing:.25rem;--container-3xl:48rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--font-weight-medium:500;--font-weight-bold:700;--radius-sm:.25rem;--radius-lg:.5rem;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variatLine truncated
@@ -0,0 +1,2 @@
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-outline-style:solid;--tw-duration:initial;--tw-leading:initial;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-ease:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-700:oklch(50.5% .213 27.518);--color-red-900:oklch(39.6% .141 25.723);--color-green-300:oklch(87.1% .15 154.449);--color-green-700:oklch(52.7% .154 150.069);--color-cyan-400:oklch(78.9% .154 211.53);--color-cyan-600:oklch(60.9% .126 221.723);--color-sky-300:oklch(82.8% .111 230.318);--color-sky-700:oklch(50% .134 242.749);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-900:oklch(37.9% .146 265.522);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-800:oklch(27.8% .033 256.848);--color-stone-50:oklch(98.5% .001 106.423);--color-stone-100:oklch(97% .001 106.424);--color-stone-200:oklch(92.3% .003 48.717);--color-stone-300:oklch(86.9% .005 56.366);--color-stone-400:oklch(70.9% .01 56.259);--color-stone-500:oklch(55.3% .013 58.071);--color-stone-600:oklch(44.4% .011 73.639);--color-stone-700:oklch(37.4% .01 67.558);--color-stone-800:oklch(26.8% .007 34.298);--color-stone-900:oklch(21.6% .006 56.043);--color-stone-950:oklch(14.7% .004 49.25);--color-white:#fff;--spacing:.25rem;--container-3xl:48rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--font-weight-medium:500;--font-weight-bold:700;--radius-sm:.25rem;--radius-lg:.5rem;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inheritLine truncated
@@ -1 +1 @@
import{F as e,I as t,P as n,Q as r,X as i,nt as a,r as o,t as s}from"./39JK5HWF.js";var c=class{constructor(e,t){this.status=e,this.body=typeof t==`string`?{message:t}:t||{message:`Error: ${e}`}}toString(){return JSON.stringify(this.body)}},l=class{constructor(e,t){try{new Headers({location:t})}catch{throw Error(`Invalid redirect location ${JSON.stringify(t)}: this string contains characters that cannot be used in HTTP headers`)}this.status=e,this.location=t}},u=class extends Error{constructor(e,t,n){super(n),this.status=e,this.text=t}};new URL(`sveltekit-internal://`);function d(e,t){return e===`/`||t===`ignore`?e:t===`never`?e.endsWith(`/`)?e.slice(0,-1):e:t===`always`&&!e.endsWith(`/`)?e+`/`:e}function f(e){return e.split(`%25`).map(decodeURI).join(`%25`)}function p(e){for(let t in e)e[t]=decodeURIComponent(e[t]);return e}function m({href:e}){return e.split(`#`)[0]}function h(e,t,n,r=!1){let i=new URL(e);Object.defineProperty(i,"searchParams",{value:new Proxy(i.searchParams,{get(e,r){if(r===`get`||r===`getAll`||r===`has`)return(t,...i)=>(n(t),e[r](t,...i));t();let i=Reflect.get(e,r);return typeof i==`function`?i.bind(e):i}}),enumerable:!0,configurable:!0});let a=[`href`,`pathname`,`search`,`toString`,`toJSON`];r&&a.push(`hash`);for(let n of a)Object.defineProperty(i,n,{get(){return t(),e[n]},enumerable:!0,configurable:!0});return i}function g(){}function _(...e){let t=5381;for(let n of e)if(typeof n==`string`){let e=n.length;for(;e;)t=t*33^n.charCodeAt(--e)}else if(ArrayBuffer.isView(n)){let e=new Uint8Array(n.buffer,n.byteOffset,n.byteLength),r=e.length;for(;r;)t=t*33^e[--r]}else throw TypeError(`value must be a string or TypedArray`);return(t>>>0).toString(36)}new TextEncoder;function v(e){let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}var ee=window.fetch;window.fetch=(e,t)=>((e instanceof Request?e.method:t?.method||`GET`)!==`GET`&&y.delete(x(e)),ee(e,t));var y=new Map;function b(e,t){let n=x(e,t),r=document.querySelector(n);if(r?.textContent){r.remove();let{body:e,...t}=JSON.parse(r.textContent);r.getAttribute(`data-b64`)!==null&&(e=v(e));let i=r.getAttribute(`data-ttl`);return i&&y.set(n,{body:e,init:t,ttl:1e3*Number(i)}),Promise.resolve(new Response(e,t))}return window.fetch(e,t)}function te(e,t,n){if(y.size>0){let t=x(e,n),r=y.get(t);if(r){if(performance.now()<r.ttl&&[`default`,`force-cache`,`only-if-cached`,void 0].includes(n?.cache))return new Response(r.body,r.init);y.delete(t)}}return window.fetch(t,n)}function x(e,t){let n=`script[data-sveltekit-fetched][data-url=${JSON.stringify(e instanceof Request?e.url:e)}]`;if(t?.headers||t?.body){let e=[];t.headers&&e.push([...new Headers(t.headers)].join(`,`)),t.body&&(typeof t.body==`string`||ArrayBuffer.isView(t.body))&&e.push(t.body),n+=`[data-hash="${_(...e)}"]`}return n}var ne=/^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/,re=/^\/\((?:[^)]+)\)$/;function ie(e){let t=[];return{pattern:e===`/`||re.test(e)?/^\/$/:RegExp(`^${oe(e).map(e=>{let n=/^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(e);if(n)return t.push({name:n[1],matcher:n[2],optional:!1,rest:!0,chained:!0}),`(?:/([^]*))?`;let r=/^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(e);if(r)return t.push({name:r[1],matcher:r[2],optional:!0,rest:!1,chained:!0}),`(?:/([^/]+))?`;if(!e)return;let i=e.split(/\[(.+?)\](?!\])/);return`/`+i.map((e,n)=>{if(n%2){if(e.startsWith(`x+`))return ce(String.fromCharCode(parseInt(e.slice(2),16)));if(e.startsWith(`u+`))return ce(String.fromCharCode(...e.slice(2).split(`-`).map(e=>parseInt(e,16))));let[,r,a,o,s]=ne.exec(e);return t.push({name:o,matcher:s,optional:!!r,rest:!!a,chained:a?n===1&&i[0]===``:!1}),a?`([^]*?)`:r?`([^/]*)?`:`([^/]+?)`}return ce(e)}).join(``)}).join(``)}/?$`),params:t}}function ae(e){return e!==``&&!/^\([^)]+\)$/.test(e)}function oe(e){return e.slice(1).split(`/`).filter(ae)}function se(e,t,n){let r={},i=e.slice(1),a=i.filter(e=>e!==void 0),o=0;for(let e=0;e<t.length;e+=1){let s=t[e],c=i[e-o];if(s.chained&&s.rest&&o&&(c=i.slice(e-o,e+1).filter(e=>e).join(`/`),o=0),c===void 0)if(s.rest)c=``;else continue;if(!s.matcher||n[s.matcher](c)){r[s.name]=c;let n=t[e+1],l=i[e+1];n&&!n.rest&&n.optional&&l&&s.chained&&(o=0),!n&&!l&&Object.keys(r).length===a.length&&(o=0);continue}if(s.optional&&s.chained){o++;continue}return}if(!o)return r}function ce(e){return e.normalize().replace(/[[\]]/g,`\\$&`).replace(/%/g,`%25`).replace(/\//g,`%2[Ff]`).replace(/\?/g,`%3[Ff]`).replace(/#/g,`%23`).replace(/[.*+?^${}()|\\]/g,`\\$&`)}function le({nodes:e,server_loads:t,dictionary:n,matchers:r}){let i=new Set(t);return Object.entries(n).map(([t,[n,i,s]])=>{let{pattern:c,params:l}=ie(t),u={id:t,exec:e=>{let t=c.exec(e);if(t)return se(t,l,r)},errors:[1,...s||[]].map(t=>e[t]),layouts:[0,...i||[]].map(o),leaf:a(n)};return u.errors.length=u.layouts.length=Math.max(u.errors.length,u.layouts.length),u});function a(t){let n=t<0;return n&&(t=~t),[n,e[t]]}function o(t){return t===void 0?t:[i.has(t),e[t]]}}function ue(e,t=JSON.parse){try{return t(sessionStorage[e Line truncated
import{F as e,I as t,P as n,Q as r,X as i,nt as a,r as o,t as s}from"./39JK5HWF.js";var c=class{constructor(e,t){this.status=e,this.body=typeof t==`string`?{message:t}:t||{message:`Error: ${e}`}}toString(){return JSON.stringify(this.body)}},l=class{constructor(e,t){try{new Headers({location:t})}catch{throw Error(`Invalid redirect location ${JSON.stringify(t)}: this string contains characters that cannot be used in HTTP headers`)}this.status=e,this.location=t}},u=class extends Error{constructor(e,t,n){super(n),this.status=e,this.text=t}};new URL(`sveltekit-internal://`);function d(e,t){return e===`/`||t===`ignore`?e:t===`never`?e.endsWith(`/`)?e.slice(0,-1):e:t===`always`&&!e.endsWith(`/`)?e+`/`:e}function f(e){return e.split(`%25`).map(decodeURI).join(`%25`)}function p(e){for(let t in e)e[t]=decodeURIComponent(e[t]);return e}function m({href:e}){return e.split(`#`)[0]}function h(e,t,n,r=!1){let i=new URL(e);Object.defineProperty(i,"searchParams",{value:new Proxy(i.searchParams,{get(e,r){if(r===`get`||r===`getAll`||r===`has`)return(t,...i)=>(n(t),e[r](t,...i));t();let i=Reflect.get(e,r);return typeof i==`function`?i.bind(e):i}}),enumerable:!0,configurable:!0});let a=[`href`,`pathname`,`search`,`toString`,`toJSON`];r&&a.push(`hash`);for(let n of a)Object.defineProperty(i,n,{get(){return t(),e[n]},enumerable:!0,configurable:!0});return i}function g(){}function _(...e){let t=5381;for(let n of e)if(typeof n==`string`){let e=n.length;for(;e;)t=t*33^n.charCodeAt(--e)}else if(ArrayBuffer.isView(n)){let e=new Uint8Array(n.buffer,n.byteOffset,n.byteLength),r=e.length;for(;r;)t=t*33^e[--r]}else throw TypeError(`value must be a string or TypedArray`);return(t>>>0).toString(36)}new TextEncoder;function v(e){let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}var ee=window.fetch;window.fetch=(e,t)=>((e instanceof Request?e.method:t?.method||`GET`)!==`GET`&&y.delete(x(e)),ee(e,t));var y=new Map;function b(e,t){let n=x(e,t),r=document.querySelector(n);if(r?.textContent){r.remove();let{body:e,...t}=JSON.parse(r.textContent);r.getAttribute(`data-b64`)!==null&&(e=v(e));let i=r.getAttribute(`data-ttl`);return i&&y.set(n,{body:e,init:t,ttl:1e3*Number(i)}),Promise.resolve(new Response(e,t))}return window.fetch(e,t)}function te(e,t,n){if(y.size>0){let t=x(e,n),r=y.get(t);if(r){if(performance.now()<r.ttl&&[`default`,`force-cache`,`only-if-cached`,void 0].includes(n?.cache))return new Response(r.body,r.init);y.delete(t)}}return window.fetch(t,n)}function x(e,t){let n=`script[data-sveltekit-fetched][data-url=${JSON.stringify(e instanceof Request?e.url:e)}]`;if(t?.headers||t?.body){let e=[];t.headers&&e.push([...new Headers(t.headers)].join(`,`)),t.body&&(typeof t.body==`string`||ArrayBuffer.isView(t.body))&&e.push(t.body),n+=`[data-hash="${_(...e)}"]`}return n}var ne=/^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/,re=/^\/\((?:[^)]+)\)$/;function ie(e){let t=[];return{pattern:e===`/`||re.test(e)?/^\/$/:RegExp(`^${oe(e).map(e=>{let n=/^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(e);if(n)return t.push({name:n[1],matcher:n[2],optional:!1,rest:!0,chained:!0}),`(?:/([^]*))?`;let r=/^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(e);if(r)return t.push({name:r[1],matcher:r[2],optional:!0,rest:!1,chained:!0}),`(?:/([^/]+))?`;if(!e)return;let i=e.split(/\[(.+?)\](?!\])/);return`/`+i.map((e,n)=>{if(n%2){if(e.startsWith(`x+`))return ce(String.fromCharCode(parseInt(e.slice(2),16)));if(e.startsWith(`u+`))return ce(String.fromCharCode(...e.slice(2).split(`-`).map(e=>parseInt(e,16))));let[,r,a,o,s]=ne.exec(e);return t.push({name:o,matcher:s,optional:!!r,rest:!!a,chained:a?n===1&&i[0]===``:!1}),a?`([^]*?)`:r?`([^/]*)?`:`([^/]+?)`}return ce(e)}).join(``)}).join(``)}/?$`),params:t}}function ae(e){return e!==``&&!/^\([^)]+\)$/.test(e)}function oe(e){return e.slice(1).split(`/`).filter(ae)}function se(e,t,n){let r={},i=e.slice(1),a=i.filter(e=>e!==void 0),o=0;for(let e=0;e<t.length;e+=1){let s=t[e],c=i[e-o];if(s.chained&&s.rest&&o&&(c=i.slice(e-o,e+1).filter(e=>e).join(`/`),o=0),c===void 0)if(s.rest)c=``;else continue;if(!s.matcher||n[s.matcher](c)){r[s.name]=c;let n=t[e+1],l=i[e+1];n&&!n.rest&&n.optional&&l&&s.chained&&(o=0),!n&&!l&&Object.keys(r).length===a.length&&(o=0);continue}if(s.optional&&s.chained){o++;continue}return}if(!o)return r}function ce(e){return e.normalize().replace(/[[\]]/g,`\\$&`).replace(/%/g,`%25`).replace(/\//g,`%2[Ff]`).replace(/\?/g,`%3[Ff]`).replace(/#/g,`%23`).replace(/[.*+?^${}()|\\]/g,`\\$&`)}function le({nodes:e,server_loads:t,dictionary:n,matchers:r}){let i=new Set(t);return Object.entries(n).map(([t,[n,i,s]])=>{let{pattern:c,params:l}=ie(t),u={id:t,exec:e=>{let t=c.exec(e);if(t)return se(t,l,r)},errors:[1,...s||[]].map(t=>e[t]),layouts:[0,...i||[]].map(o),leaf:a(n)};return u.errors.length=u.layouts.length=Math.max(u.errors.length,u.layouts.length),u});function a(t){let n=t<0;return n&&(t=~t),[n,e[t]]}function o(t){return t===void 0?t:[i.has(t),e[t]]}}function ue(e,t=JSON.parse){try{return t(sessionStorage[e Line truncated
@@ -1 +0,0 @@
import"./D3up1JC1.js";
@@ -1 +1 @@
import{J as e}from"./39JK5HWF.js";import{t}from"./D3up1JC1.js";import"./B5isPFOt.js";var n=e({user:null,status:`loading`}),r=()=>{localStorage.removeItem(`accessToken`),n.status=`unauthenticated`},i=()=>localStorage.getItem(`accessToken`),a=e=>{localStorage.setItem(`accessToken`,e)},o=`/api`,s=class extends Error{status;body;constructor(e,t){super(`API Error ${e}`),this.status=e,this.body=t}};async function c(e,n={}){let{auth:a=!0,headers:c,...u}=n,d={"Content-Type":`application/json`,...c},f=new Headers(d);if(a){let e=i();e&&f.append(`Authorization`,`Bearer ${e}`)}let p=await fetch(`${o}${e}`,{...u,headers:f});if(p.status===401&&(r(),t(`/login`)),!p.ok)throw new s(p.status,await l(p));if(p.status!==204)return p.json()}async function l(e){try{return await e.json()}catch{return null}}var u={get:(e,t)=>c(e,{...t,method:`GET`}),post:(e,t,n)=>c(e,{...n,method:`POST`,body:JSON.stringify(t)}),put:(e,t,n)=>c(e,{...n,method:`PUT`,body:JSON.stringify(t)}),delete:(e,t)=>c(e,{...t,method:`DELETE`})};export{a as i,n,r,u as t};
import{J as e}from"./39JK5HWF.js";import{t}from"./B0qrqti_.js";import"./DL7ZyBAF.js";var n=e({user:null,status:`loading`}),r=()=>{localStorage.removeItem(`accessToken`),n.status=`unauthenticated`},i=()=>localStorage.getItem(`accessToken`),a=e=>{localStorage.setItem(`accessToken`,e)},o=`/api`,s=class extends Error{status;body;constructor(e,t){super(`API Error ${e}`),this.status=e,this.body=t}};async function c(e,n={}){let{auth:a=!0,headers:c,...u}=n,d={"Content-Type":`application/json`,...c},f=new Headers(d);if(a){let e=i();e&&f.append(`Authorization`,`Bearer ${e}`)}let p=await fetch(`${o}${e}`,{...u,headers:f});if(p.status===401&&(r(),t(`/login`)),!p.ok)throw new s(p.status,await l(p));if(p.status!==204)return p.json()}async function l(e){try{return await e.json()}catch{return null}}var u={get:(e,t)=>c(e,{...t,method:`GET`}),post:(e,t,n)=>c(e,{...n,method:`POST`,body:JSON.stringify(t)}),put:(e,t,n)=>c(e,{...n,method:`PUT`,body:JSON.stringify(t)}),delete:(e,t)=>c(e,{...t,method:`DELETE`})};export{a as i,n,r,u as t};
@@ -1 +1 @@
import{t as e}from"./BqkZ0BZ5.js";var t={me:()=>e.get(`/user/me`),update:(t,n)=>e.put(`/user/${t}`,n),listAddresses:t=>e.get(`/user/${t}/address`),createAddress:(t,n)=>e.post(`/user/${t}/address`,n),updateAddress:(t,n)=>e.put(`/user/${t}/address`,n),deleteAddress:(t,n)=>e.delete(`/user/${t}/address/${n}`)};export{t};
import{t as e}from"./BC84wEQu.js";var t={me:()=>e.get(`/user/me`),update:(t,n)=>e.put(`/user/${t}`,n),listAddresses:t=>e.get(`/user/${t}/address`),createAddress:(t,n)=>e.post(`/user/${t}/address`,n),updateAddress:(t,n)=>e.put(`/user/${t}/address`,n),deleteAddress:(t,n)=>e.delete(`/user/${t}/address/${n}`)};export{t};
@@ -1,4 +1,4 @@
import{$ as e,A as t,B as n,D as r,E as i,G as a,I as o,J as s,K as c,L as l,M as u,N as d,O as f,P as p,Q as m,S as h,T as g,V as _,W as v,X as y,_ as b,a as x,at as ee,b as S,c as te,d as C,dt as w,f as ne,h as re,it as ie,j as ae,k as oe,l as se,lt as ce,m as le,n as ue,o as de,q as T,r as fe,u as pe,w as E,x as me}from"./39JK5HWF.js";import"./D3up1JC1.js";import"./xihTtKlq.js";var he=Math.min,D=Math.max,ge=Math.round,O=Math.floor,k=e=>({x:e,y:e}),A={left:`right`,right:`left`,bottom:`top`,top:`bottom`};function _e(e,t,n){return D(e,he(t,n))}function j(e,t){return typeof e==`function`?e(t):e}function M(e){return e.split(`-`)[0]}function N(e){return e.split(`-`)[1]}function P(e){return e===`x`?`y`:`x`}function ve(e){return e===`y`?`height`:`width`}function F(e){let t=e[0];return t===`t`||t===`b`?`y`:`x`}function I(e){return P(F(e))}function ye(e,t,n){n===void 0&&(n=!1);let r=N(e),i=I(e),a=ve(i),o=i===`x`?r===(n?`end`:`start`)?`right`:`left`:r===`start`?`bottom`:`top`;return t.reference[a]>t.floating[a]&&(o=Ee(o)),[o,Ee(o)]}function be(e){let t=Ee(e);return[L(e),t,L(t)]}function L(e){return e.includes(`start`)?e.replace(`start`,`end`):e.replace(`end`,`start`)}var xe=[`left`,`right`],Se=[`right`,`left`],R=[`top`,`bottom`],Ce=[`bottom`,`top`];function we(e,t,n){switch(e){case`top`:case`bottom`:return n?t?Se:xe:t?xe:Se;case`left`:case`right`:return t?R:Ce;default:return[]}}function Te(e,t,n,r){let i=N(e),a=we(M(e),n===`start`,r);return i&&(a=a.map(e=>e+`-`+i),t&&(a=a.concat(a.map(L)))),a}function Ee(e){let t=M(e);return A[t]+e.slice(t.length)}function De(e){return{top:e.top??0,right:e.right??0,bottom:e.bottom??0,left:e.left??0}}function Oe(e){return typeof e==`number`?{top:e,right:e,bottom:e,left:e}:De(e)}function ke(e){let{x:t,y:n,width:r,height:i}=e;return{width:r,height:i,top:n,left:t,right:t+r,bottom:n+i,x:t,y:n}}function Ae(e,t,n){let{reference:r,floating:i}=e,a=F(t),o=I(t),s=ve(o),c=M(t),l=a===`y`,u=r.x+r.width/2-i.width/2,d=r.y+r.height/2-i.height/2,f=r[s]/2-i[s]/2,p;switch(c){case`top`:p={x:u,y:r.y-i.height};break;case`bottom`:p={x:u,y:r.y+r.height};break;case`right`:p={x:r.x+r.width,y:d};break;case`left`:p={x:r.x-i.width,y:d};break;default:p={x:r.x,y:r.y}}let m=N(t);return m&&(p[o]+=f*(m===`end`?1:-1)*(n&&l?-1:1)),p}async function je(e,t){t===void 0&&(t={});let{x:n,y:r,platform:i,rects:a,elements:o,strategy:s}=e,{boundary:c=`clippingAncestors`,rootBoundary:l=`viewport`,elementContext:u=`floating`,altBoundary:d=!1,padding:f=0}=j(t,e),p=Oe(f),m=o[d?u===`floating`?`reference`:`floating`:u],h=ke(await i.getClippingRect({element:await(i.isElement==null?void 0:i.isElement(m))??!0?m:m.contextElement||await(i.getDocumentElement==null?void 0:i.getDocumentElement(o.floating)),boundary:c,rootBoundary:l,strategy:s})),g=u===`floating`?{x:n,y:r,width:a.floating.width,height:a.floating.height}:a.reference,_=await(i.getOffsetParent==null?void 0:i.getOffsetParent(o.floating)),v=await(i.isElement==null?void 0:i.isElement(_))&&await(i.getScale==null?void 0:i.getScale(_))||{x:1,y:1},y=ke(i.convertOffsetParentRelativeRectToViewportRelativeRect?await i.convertOffsetParentRelativeRectToViewportRelativeRect({elements:o,rect:g,offsetParent:_,strategy:s}):g);return{top:(h.top-y.top+p.top)/v.y,bottom:(y.bottom-h.bottom+p.bottom)/v.y,left:(h.left-y.left+p.left)/v.x,right:(y.right-h.right+p.right)/v.x}}var Me=50,Ne=async(e,t,n)=>{let{placement:r=`bottom`,strategy:i=`absolute`,middleware:a=[],platform:o}=n,s=o.detectOverflow?o:{...o,detectOverflow:je},c=await(o.isRTL==null?void 0:o.isRTL(t)),l=await o.getElementRects({reference:e,floating:t,strategy:i}),{x:u,y:d}=Ae(l,r,c),f=r,p=0,m={};for(let n=0;n<a.length;n++){let h=a[n];if(!h)continue;let{name:g,fn:_}=h,{x:v,y,data:b,reset:x}=await _({x:u,y:d,initialPlacement:r,placement:f,strategy:i,middlewareData:m,rects:l,platform:s,elements:{reference:e,floating:t}});u=v??u,d=y??d,m[g]={...m[g],...b},x&&p<Me&&(p++,typeof x==`object`&&(x.placement&&(f=x.placement),x.rects&&(l=x.rects===!0?await o.getElementRects({reference:e,floating:t,strategy:i}):x.rects),{x:u,y:d}=Ae(l,f,c)),n=-1)}return{x:u,y:d,placement:f,strategy:i,middlewareData:m}},Pe=function(e){return e===void 0&&(e={}),{name:`flip`,options:e,async fn(t){var n;let{placement:r,middlewareData:i,rects:a,initialPlacement:o,platform:s,elements:c}=t,{mainAxis:l=!0,crossAxis:u=!0,fallbackPlacements:d,fallbackStrategy:f=`bestFit`,fallbackAxisSideDirection:p=`none`,flipAlignment:m=!0,...h}=j(e,t);if((n=i.arrow)!=null&&n.alignmentOffset)return{};let g=M(r),_=F(o),v=M(o)===o,y=await(s.isRTL==null?void 0:s.isRTL(c.floating)),b=d||(v||!m?[Ee(o)]:be(o)),x=p!==`none`;!d&&x&&b.push(...Te(o,m,p,y));let ee=[o,...b],S=await s.detectOverflow(t,h),te=[],C=i.flip?.overflows||[];if(l&&te.push(S[g]),u){let e=ye(r,a,y);te.push(S[e[0]],S[e[1]])}if(C=[...C,{placement:r,overflows:te}],!te.every(e=>e<=0)){let e=(i.flip?.index||0)+1,t=ee[e];if(t&&(u!==`alignment`||_===F(t)||C.every(e=>F(e.placement)!==_||e.overflows[0]>0)))return{data:{index:e,overflows:C},reLine truncated
import{$ as e,A as t,B as n,D as r,E as i,G as a,I as o,J as s,K as c,L as l,M as u,N as d,O as f,P as p,Q as m,S as h,T as g,V as _,W as v,X as y,_ as b,a as x,at as ee,b as S,c as te,d as C,dt as w,f as ne,h as re,it as ie,j as ae,k as oe,l as se,lt as ce,m as le,n as ue,o as de,q as T,r as fe,u as pe,w as E,x as me}from"./39JK5HWF.js";import"./B0qrqti_.js";import"./xihTtKlq.js";var he=Math.min,D=Math.max,ge=Math.round,O=Math.floor,k=e=>({x:e,y:e}),A={left:`right`,right:`left`,bottom:`top`,top:`bottom`};function _e(e,t,n){return D(e,he(t,n))}function j(e,t){return typeof e==`function`?e(t):e}function M(e){return e.split(`-`)[0]}function N(e){return e.split(`-`)[1]}function P(e){return e===`x`?`y`:`x`}function ve(e){return e===`y`?`height`:`width`}function F(e){let t=e[0];return t===`t`||t===`b`?`y`:`x`}function I(e){return P(F(e))}function ye(e,t,n){n===void 0&&(n=!1);let r=N(e),i=I(e),a=ve(i),o=i===`x`?r===(n?`end`:`start`)?`right`:`left`:r===`start`?`bottom`:`top`;return t.reference[a]>t.floating[a]&&(o=Ee(o)),[o,Ee(o)]}function be(e){let t=Ee(e);return[L(e),t,L(t)]}function L(e){return e.includes(`start`)?e.replace(`start`,`end`):e.replace(`end`,`start`)}var xe=[`left`,`right`],Se=[`right`,`left`],R=[`top`,`bottom`],Ce=[`bottom`,`top`];function we(e,t,n){switch(e){case`top`:case`bottom`:return n?t?Se:xe:t?xe:Se;case`left`:case`right`:return t?R:Ce;default:return[]}}function Te(e,t,n,r){let i=N(e),a=we(M(e),n===`start`,r);return i&&(a=a.map(e=>e+`-`+i),t&&(a=a.concat(a.map(L)))),a}function Ee(e){let t=M(e);return A[t]+e.slice(t.length)}function De(e){return{top:e.top??0,right:e.right??0,bottom:e.bottom??0,left:e.left??0}}function Oe(e){return typeof e==`number`?{top:e,right:e,bottom:e,left:e}:De(e)}function ke(e){let{x:t,y:n,width:r,height:i}=e;return{width:r,height:i,top:n,left:t,right:t+r,bottom:n+i,x:t,y:n}}function Ae(e,t,n){let{reference:r,floating:i}=e,a=F(t),o=I(t),s=ve(o),c=M(t),l=a===`y`,u=r.x+r.width/2-i.width/2,d=r.y+r.height/2-i.height/2,f=r[s]/2-i[s]/2,p;switch(c){case`top`:p={x:u,y:r.y-i.height};break;case`bottom`:p={x:u,y:r.y+r.height};break;case`right`:p={x:r.x+r.width,y:d};break;case`left`:p={x:r.x-i.width,y:d};break;default:p={x:r.x,y:r.y}}let m=N(t);return m&&(p[o]+=f*(m===`end`?1:-1)*(n&&l?-1:1)),p}async function je(e,t){t===void 0&&(t={});let{x:n,y:r,platform:i,rects:a,elements:o,strategy:s}=e,{boundary:c=`clippingAncestors`,rootBoundary:l=`viewport`,elementContext:u=`floating`,altBoundary:d=!1,padding:f=0}=j(t,e),p=Oe(f),m=o[d?u===`floating`?`reference`:`floating`:u],h=ke(await i.getClippingRect({element:await(i.isElement==null?void 0:i.isElement(m))??!0?m:m.contextElement||await(i.getDocumentElement==null?void 0:i.getDocumentElement(o.floating)),boundary:c,rootBoundary:l,strategy:s})),g=u===`floating`?{x:n,y:r,width:a.floating.width,height:a.floating.height}:a.reference,_=await(i.getOffsetParent==null?void 0:i.getOffsetParent(o.floating)),v=await(i.isElement==null?void 0:i.isElement(_))&&await(i.getScale==null?void 0:i.getScale(_))||{x:1,y:1},y=ke(i.convertOffsetParentRelativeRectToViewportRelativeRect?await i.convertOffsetParentRelativeRectToViewportRelativeRect({elements:o,rect:g,offsetParent:_,strategy:s}):g);return{top:(h.top-y.top+p.top)/v.y,bottom:(y.bottom-h.bottom+p.bottom)/v.y,left:(h.left-y.left+p.left)/v.x,right:(y.right-h.right+p.right)/v.x}}var Me=50,Ne=async(e,t,n)=>{let{placement:r=`bottom`,strategy:i=`absolute`,middleware:a=[],platform:o}=n,s=o.detectOverflow?o:{...o,detectOverflow:je},c=await(o.isRTL==null?void 0:o.isRTL(t)),l=await o.getElementRects({reference:e,floating:t,strategy:i}),{x:u,y:d}=Ae(l,r,c),f=r,p=0,m={};for(let n=0;n<a.length;n++){let h=a[n];if(!h)continue;let{name:g,fn:_}=h,{x:v,y,data:b,reset:x}=await _({x:u,y:d,initialPlacement:r,placement:f,strategy:i,middlewareData:m,rects:l,platform:s,elements:{reference:e,floating:t}});u=v??u,d=y??d,m[g]={...m[g],...b},x&&p<Me&&(p++,typeof x==`object`&&(x.placement&&(f=x.placement),x.rects&&(l=x.rects===!0?await o.getElementRects({reference:e,floating:t,strategy:i}):x.rects),{x:u,y:d}=Ae(l,f,c)),n=-1)}return{x:u,y:d,placement:f,strategy:i,middlewareData:m}},Pe=function(e){return e===void 0&&(e={}),{name:`flip`,options:e,async fn(t){var n;let{placement:r,middlewareData:i,rects:a,initialPlacement:o,platform:s,elements:c}=t,{mainAxis:l=!0,crossAxis:u=!0,fallbackPlacements:d,fallbackStrategy:f=`bestFit`,fallbackAxisSideDirection:p=`none`,flipAlignment:m=!0,...h}=j(e,t);if((n=i.arrow)!=null&&n.alignmentOffset)return{};let g=M(r),_=F(o),v=M(o)===o,y=await(s.isRTL==null?void 0:s.isRTL(c.floating)),b=d||(v||!m?[Ee(o)]:be(o)),x=p!==`none`;!d&&x&&b.push(...Te(o,m,p,y));let ee=[o,...b],S=await s.detectOverflow(t,h),te=[],C=i.flip?.overflows||[];if(l&&te.push(S[g]),u){let e=ye(r,a,y);te.push(S[e[0]],S[e[1]])}if(C=[...C,{placement:r,overflows:te}],!te.every(e=>e<=0)){let e=(i.flip?.index||0)+1,t=ee[e];if(t&&(u!==`alignment`||_===F(t)||C.every(e=>F(e.placement)!==_||e.overflows[0]>0)))return{data:{index:e,overflows:C},reLine truncated
3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0
1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502
0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0
@@ -1 +1 @@
import{t as e}from"./BqkZ0BZ5.js";var t={register:t=>e.post(`/auth/register`,t),status:()=>e.get(`/auth/status`),login:t=>e.post(`/auth/login`,t)};export{t};
import{t as e}from"./BC84wEQu.js";var t={register:t=>e.post(`/auth/register`,t),status:()=>e.get(`/auth/status`),login:t=>e.post(`/auth/login`,t)};export{t};
@@ -0,0 +1 @@
import"./B0qrqti_.js";
@@ -1 +1 @@
import{t as e}from"./BqkZ0BZ5.js";var t={providerTypes:()=>e.get(`/provider/providerTypes`),getProviders:t=>e.get(`/provider/${t}`),getProvider:(t,n)=>e.get(`/provider/${t}/${n}`),createProvider:(t,n)=>e.post(`/provider/${t}`,n),updateProvider:(t,n)=>e.put(`/provider/${t}`,n),deleteProvider:(t,n)=>e.delete(`/provider/${t}/${n}`),getAvailableModels:(t,n)=>e.post(`/provider/${t}/avalable-models`,n),getProvidersModels:t=>e.get(`/provider/${t}/models`)};export{t};
import{t as e}from"./BC84wEQu.js";var t={providerTypes:()=>e.get(`/provider/providerTypes`),getProviders:t=>e.get(`/provider/${t}`),getProvider:(t,n)=>e.get(`/provider/${t}/${n}`),createProvider:(t,n)=>e.post(`/provider/${t}`,n),updateProvider:(t,n)=>e.put(`/provider/${t}`,n),deleteProvider:(t,n)=>e.delete(`/provider/${t}/${n}`),getAvailableModels:(t,n)=>e.post(`/provider/${t}/avalable-models`,n),getProvidersModels:t=>e.get(`/provider/${t}/models`)};export{t};
@@ -1 +1 @@
import"./39JK5HWF.js";import{a as e,r as t}from"./D3up1JC1.js";var n={get data(){return e.data},get error(){return e.error},get form(){return e.form},get params(){return e.params},get route(){return e.route},get state(){return e.state},get status(){return e.status},get url(){return e.url}};t.updated.check;var r=n;export{r as t};
import"./39JK5HWF.js";import{a as e,r as t}from"./B0qrqti_.js";var n={get data(){return e.data},get error(){return e.error},get form(){return e.form},get params(){return e.params},get route(){return e.route},get state(){return e.state},get status(){return e.status},get url(){return e.url}};t.updated.check;var r=n;export{r as t};
@@ -1,2 +1,2 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["../nodes/0.DNLpy_rd.js","../chunks/39JK5HWF.js","../chunks/xihTtKlq.js","../chunks/DTCALkcP.js","../assets/0.Bdga2HVs.css","../nodes/1.Cvrs0-W0.js","../chunks/D1d5-1oo.js","../chunks/D3up1JC1.js","../nodes/2.Bs3bPWro.js","../chunks/B5isPFOt.js","../chunks/BqkZ0BZ5.js","../chunks/BEgKbVuy.js","../chunks/D8dI9nx6.js","../chunks/BRXBpvt8.js","../nodes/3.BD_oZvMH.js","../nodes/4.Dw1ji0S9.js","../nodes/5.BV8wWprr.js","../nodes/6.iWRSAZEv.js","../nodes/7.CJ-_CrAo.js","../nodes/8.D-K-fxzc.js","../chunks/D35bQ8xD.js","../chunks/DRdGzrsF.js","../chunks/D4uBfDnr.js","../nodes/9.C_kOH_FX.js","../nodes/10.2kRbJUBr.js","../nodes/11.3PxmG5oJ.js","../nodes/12.B5iUSTUw.js","../chunks/D3MDK1zR.js","../nodes/13.CjlegDH_.js","../nodes/14.CFcHzpcm.js","../nodes/15.SpasLkf4.js","../nodes/16.TiX4VGhr.js","../nodes/17.wrIvaz1M.js","../nodes/18.BfPDxxm9.js","../chunks/DNQ6C3zq.js","../nodes/19.Bhx_NIDl.js"])))=>i.map(i=>d[i]);
import{$ as e,A as t,B as n,D as r,E as i,G as a,H as o,I as s,K as c,O as l,P as u,Q as d,T as f,V as p,X as m,a as h,at as g,dt as _,i as v,it as y,o as b,q as x,r as S,w as C,y as w}from"../chunks/39JK5HWF.js";import"../chunks/xihTtKlq.js";var T=`modulepreload`,E=function(e,t){return new URL(e,t).href},D={},O=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=E(t,n),t=s(t),t in D)return;D[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:T,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},k={},A=l(`<div id="svelte-announcer" aria-live="assertive" aria-atomic="true" style="position: absolute; left: 0; top: 0; clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap; width: 1px; height: 1px"><!></div>`),j=l(`<!> <!>`,1);function M(l,v){g(v,!0);let T=h(v,`components`,23,()=>[]),E=h(v,`data_0`,3,null),D=h(v,`data_1`,3,null),O=h(v,`data_2`,3,null);o(()=>v.stores.page.set(v.page)),p(()=>{v.stores,v.page,v.constructors,T(),v.form,E(),D(),O(),v.stores.page.notify()});let k=d(!1),M=d(!1),N=d(null);S(()=>{let e=v.stores.page.subscribe(()=>{u(k)&&(m(M,!0),s().then(()=>{m(N,document.title||`untitled page`,!0)}))});return m(k,!0),e});let P=e(()=>v.constructors[2]);var F=j(),I=c(F),L=t=>{let n=e(()=>v.constructors[0]);var a=r(),o=c(a);w(o,()=>u(n),(t,n)=>{b(n(t,{get data(){return E()},get form(){return v.form},get params(){return v.page.params},children:(t,n)=>{var a=r(),o=c(a),s=t=>{let n=e(()=>v.constructors[1]);var a=r(),o=c(a);w(o,()=>u(n),(e,t)=>{b(t(e,{get data(){return D()},get form(){return v.form},get params(){return v.page.params},children:(e,t)=>{var n=r(),a=c(n);w(a,()=>u(P),(e,t)=>{b(t(e,{get data(){return O()},get form(){return v.form},get params(){return v.page.params}}),e=>T()[2]=e,()=>T()?.[2])}),i(e,n)},$$slots:{default:!0}}),e=>T()[1]=e,()=>T()?.[1])}),i(t,a)},l=t=>{let n=e(()=>v.constructors[1]);var a=r(),o=c(a);w(o,()=>u(n),(e,t)=>{b(t(e,{get data(){return D()},get form(){return v.form},get params(){return v.page.params}}),e=>T()[1]=e,()=>T()?.[1])}),i(t,a)};C(o,e=>{v.constructors[2]?e(s):e(l,-1)}),i(t,a)},$$slots:{default:!0}}),e=>T()[0]=e,()=>T()?.[0])}),i(t,a)},R=t=>{let n=e(()=>v.constructors[0]);var a=r(),o=c(a);w(o,()=>u(n),(e,t)=>{b(t(e,{get data(){return E()},get form(){return v.form},get params(){return v.page.params}}),e=>T()[0]=e,()=>T()?.[0])}),i(t,a)};C(I,e=>{v.constructors[1]?e(L):e(R,-1)});var z=x(I,2),B=e=>{var r=A(),o=a(r),s=e=>{var r=t();n(()=>f(r,u(N))),i(e,r)};C(o,e=>{u(M)&&e(s)}),_(r),i(e,r)};C(z,e=>{u(k)&&e(B)}),i(l,F),y()}var N=v(M),P=[()=>O(()=>import(`../nodes/0.DNLpy_rd.js`),__vite__mapDeps([0,1,2,3,4]),import.meta.url),()=>O(()=>import(`../nodes/1.Cvrs0-W0.js`),__vite__mapDeps([5,1,2,6,7]),import.meta.url),()=>O(()=>import(`../nodes/2.Bs3bPWro.js`),__vite__mapDeps([8,1,7,2,3,6,9,10,11,12,13]),import.meta.url),()=>O(()=>import(`../nodes/3.BD_oZvMH.js`),__vite__mapDeps([14,1,7,2,9,12]),import.meta.url),()=>O(()=>import(`../nodes/4.Dw1ji0S9.js`),__vite__mapDeps([15,1,2]),import.meta.url),()=>O(()=>import(`../nodes/5.BV8wWprr.js`),__vite__mapDeps([16,1,2]),import.meta.url),()=>O(()=>import(`../nodes/6.iWRSAZEv.js`),__vite__mapDeps([17,1,2]),import.meta.url),()=>O(()=>import(`../nodes/7.CJ-_CrAo.js`),__vite__mapDeps([18,1,2]),import.meta.url),()=>O(()=>import(`../nodes/8.D-K-fxzc.js`),__vite__mapDeps([19,1,2,10,7,9,20,21,22]),import.meta.url),()=>O(()=>import(`../nodes/9.C_kOH_FX.js`),__vite__mapDeps([23,1,2]),import.meta.url),()=>O(()=>import(`../nodes/10.2kRbJUBr.js`),__vite__mapDeps([24,1,2]),import.meta.url),()=>O(()=>import(`../nodes/11.3PxmG5oJ.js`),__vite__mapDeps([25,1,2]),import.meta.url),()=>O(()=>import(`../nodes/12.B5iUSTUw.js`),__vite__mapDeps([26,1,2,20,10,7,9,21,22,27]),import.meta.url),()=>O(()=>import(`../nodes/13.CjlegDH_.js`),__vite__mapDeps([28,1,2]),import.meta.url),()=>O(()=>import(`../nodes/14.CFcHzpcm.js`),__vite__mapDeps([29,1,2]),import.meta.url),()=>O(()=>import(`../nodes/15.SpasLkf4.js`),__vite__mapDeps([30,1,2]),import.meta.url),()=>O(()=>import(`../nodes/16.TiX4VGhr.js`),__vite__mapDeps([31,1,Line truncated
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["../nodes/0.WTbeuaG5.js","../chunks/39JK5HWF.js","../chunks/xihTtKlq.js","../chunks/DTCALkcP.js","../assets/0.PdzDvXHc.css","../nodes/1.HToxGbTu.js","../chunks/DtPl1hOB.js","../chunks/B0qrqti_.js","../nodes/2.DJpmXDpd.js","../chunks/DL7ZyBAF.js","../chunks/BC84wEQu.js","../chunks/BDef5Ccs.js","../chunks/D8dI9nx6.js","../chunks/BRXBpvt8.js","../nodes/3.DQ-wAvIJ.js","../nodes/4.Dw1ji0S9.js","../nodes/5.BV8wWprr.js","../nodes/6.iWRSAZEv.js","../nodes/7.CJ-_CrAo.js","../nodes/8.TeTitTKA.js","../chunks/DOY2HMbt.js","../chunks/DRdGzrsF.js","../chunks/BorM6hBh.js","../nodes/9.C_kOH_FX.js","../nodes/10.2kRbJUBr.js","../nodes/11.3PxmG5oJ.js","../nodes/12.DXjVg3KD.js","../chunks/D3MDK1zR.js","../nodes/13.CjlegDH_.js","../nodes/14.CFcHzpcm.js","../nodes/15.SpasLkf4.js","../nodes/16.TiX4VGhr.js","../nodes/17.D_IcqSXn.js","../nodes/18.CljvOcq_.js","../chunks/DFI7Zp3t.js","../nodes/19.B7Etxitc.js"])))=>i.map(i=>d[i]);
import{$ as e,A as t,B as n,D as r,E as i,G as a,H as o,I as s,K as c,O as l,P as u,Q as d,T as f,V as p,X as m,a as h,at as g,dt as _,i as v,it as y,o as b,q as x,r as S,w as C,y as w}from"../chunks/39JK5HWF.js";import"../chunks/xihTtKlq.js";var T=`modulepreload`,E=function(e,t){return new URL(e,t).href},D={},O=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=E(t,n),t=s(t),t in D)return;D[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:T,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},k={},A=l(`<div id="svelte-announcer" aria-live="assertive" aria-atomic="true" style="position: absolute; left: 0; top: 0; clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap; width: 1px; height: 1px"><!></div>`),j=l(`<!> <!>`,1);function M(l,v){g(v,!0);let T=h(v,`components`,23,()=>[]),E=h(v,`data_0`,3,null),D=h(v,`data_1`,3,null),O=h(v,`data_2`,3,null);o(()=>v.stores.page.set(v.page)),p(()=>{v.stores,v.page,v.constructors,T(),v.form,E(),D(),O(),v.stores.page.notify()});let k=d(!1),M=d(!1),N=d(null);S(()=>{let e=v.stores.page.subscribe(()=>{u(k)&&(m(M,!0),s().then(()=>{m(N,document.title||`untitled page`,!0)}))});return m(k,!0),e});let P=e(()=>v.constructors[2]);var F=j(),I=c(F),L=t=>{let n=e(()=>v.constructors[0]);var a=r(),o=c(a);w(o,()=>u(n),(t,n)=>{b(n(t,{get data(){return E()},get form(){return v.form},get params(){return v.page.params},children:(t,n)=>{var a=r(),o=c(a),s=t=>{let n=e(()=>v.constructors[1]);var a=r(),o=c(a);w(o,()=>u(n),(e,t)=>{b(t(e,{get data(){return D()},get form(){return v.form},get params(){return v.page.params},children:(e,t)=>{var n=r(),a=c(n);w(a,()=>u(P),(e,t)=>{b(t(e,{get data(){return O()},get form(){return v.form},get params(){return v.page.params}}),e=>T()[2]=e,()=>T()?.[2])}),i(e,n)},$$slots:{default:!0}}),e=>T()[1]=e,()=>T()?.[1])}),i(t,a)},l=t=>{let n=e(()=>v.constructors[1]);var a=r(),o=c(a);w(o,()=>u(n),(e,t)=>{b(t(e,{get data(){return D()},get form(){return v.form},get params(){return v.page.params}}),e=>T()[1]=e,()=>T()?.[1])}),i(t,a)};C(o,e=>{v.constructors[2]?e(s):e(l,-1)}),i(t,a)},$$slots:{default:!0}}),e=>T()[0]=e,()=>T()?.[0])}),i(t,a)},R=t=>{let n=e(()=>v.constructors[0]);var a=r(),o=c(a);w(o,()=>u(n),(e,t)=>{b(t(e,{get data(){return E()},get form(){return v.form},get params(){return v.page.params}}),e=>T()[0]=e,()=>T()?.[0])}),i(t,a)};C(I,e=>{v.constructors[1]?e(L):e(R,-1)});var z=x(I,2),B=e=>{var r=A(),o=a(r),s=e=>{var r=t();n(()=>f(r,u(N))),i(e,r)};C(o,e=>{u(M)&&e(s)}),_(r),i(e,r)};C(z,e=>{u(k)&&e(B)}),i(l,F),y()}var N=v(M),P=[()=>O(()=>import(`../nodes/0.WTbeuaG5.js`),__vite__mapDeps([0,1,2,3,4]),import.meta.url),()=>O(()=>import(`../nodes/1.HToxGbTu.js`),__vite__mapDeps([5,1,2,6,7]),import.meta.url),()=>O(()=>import(`../nodes/2.DJpmXDpd.js`),__vite__mapDeps([8,1,7,2,3,6,9,10,11,12,13]),import.meta.url),()=>O(()=>import(`../nodes/3.DQ-wAvIJ.js`),__vite__mapDeps([14,1,7,2,9,12]),import.meta.url),()=>O(()=>import(`../nodes/4.Dw1ji0S9.js`),__vite__mapDeps([15,1,2]),import.meta.url),()=>O(()=>import(`../nodes/5.BV8wWprr.js`),__vite__mapDeps([16,1,2]),import.meta.url),()=>O(()=>import(`../nodes/6.iWRSAZEv.js`),__vite__mapDeps([17,1,2]),import.meta.url),()=>O(()=>import(`../nodes/7.CJ-_CrAo.js`),__vite__mapDeps([18,1,2]),import.meta.url),()=>O(()=>import(`../nodes/8.TeTitTKA.js`),__vite__mapDeps([19,1,2,10,7,9,12,20,21,22]),import.meta.url),()=>O(()=>import(`../nodes/9.C_kOH_FX.js`),__vite__mapDeps([23,1,2]),import.meta.url),()=>O(()=>import(`../nodes/10.2kRbJUBr.js`),__vite__mapDeps([24,1,2]),import.meta.url),()=>O(()=>import(`../nodes/11.3PxmG5oJ.js`),__vite__mapDeps([25,1,2]),import.meta.url),()=>O(()=>import(`../nodes/12.DXjVg3KD.js`),__vite__mapDeps([26,1,2,20,10,7,9,21,22,27]),import.meta.url),()=>O(()=>import(`../nodes/13.CjlegDH_.js`),__vite__mapDeps([28,1,2]),import.meta.url),()=>O(()=>import(`../nodes/14.CFcHzpcm.js`),__vite__mapDeps([29,1,2]),import.meta.url),()=>O(()=>import(`../nodes/15.SpasLkf4.js`),__vite__mapDeps([30,1,2]),import.meta.url),()=>O(()=>import(`../nodes/16.TiX4VGhr.js`),__vite__mapDeps([31Line truncated
@@ -1 +0,0 @@
import{n as e,s as t}from"../chunks/D3up1JC1.js";export{t as load_css,e as start};
@@ -0,0 +1 @@
import{n as e,s as t}from"../chunks/B0qrqti_.js";export{t as load_css,e as start};
@@ -1 +1 @@
import{B as e,E as t,G as n,K as r,O as i,T as a,at as o,dt as s,it as c,q as l}from"../chunks/39JK5HWF.js";import"../chunks/xihTtKlq.js";import{t as u}from"../chunks/D1d5-1oo.js";var d=i(`<h1> </h1> <p> </p>`,1);function f(i,f){o(f,!0);var p=d(),m=r(p),h=n(m,!0);s(m);var g=l(m,2),_=n(g,!0);s(g),e(()=>{a(h,u.status),a(_,u.error?.message)}),t(i,p),c()}export{f as component};
import{B as e,E as t,G as n,K as r,O as i,T as a,at as o,dt as s,it as c,q as l}from"../chunks/39JK5HWF.js";import"../chunks/xihTtKlq.js";import{t as u}from"../chunks/DtPl1hOB.js";var d=i(`<h1> </h1> <p> </p>`,1);function f(i,f){o(f,!0);var p=d(),m=r(p),h=n(m,!0);s(m);var g=l(m,2),_=n(g,!0);s(g),e(()=>{a(h,u.status),a(_,u.error?.message)}),t(i,p),c()}export{f as component};
@@ -1 +0,0 @@
import{B as e,C as t,D as n,E as r,G as i,J as a,K as o,M as s,N as c,O as l,P as u,Q as d,T as f,X as p,_ as m,a as h,at as g,c as _,dt as v,ft as y,it as b,j as x,q as S,r as C,s as w,u as T,ut as E,w as D,x as O,z as k}from"../chunks/39JK5HWF.js";import"../chunks/xihTtKlq.js";import{t as A}from"../chunks/D35bQ8xD.js";import{n as j,t as M}from"../chunks/DRdGzrsF.js";import{t as ee}from"../chunks/D4uBfDnr.js";import{n as N}from"../chunks/D3MDK1zR.js";var P=y({load:()=>F}),F=async({params:e})=>({title:`Paramétrage : Modèles`,back:`../settings`,space:e.space,providerTypes:await A.providerTypes()}),I=l(`<li><label><input type="checkbox"/> </label></li>`),L=l(`<div><div class="formgroup my-2"><form><div class="formelement"><label for="name">Nom</label> <input id="name" type="text" class="textinput" placeholder="nom affiché"/> <!></div> <div class="formelement"><label for="type" class="block my-1 flex-1">Type</label> <!> <!></div> <div class="formelement"><label for="baseUrl">URL</label> <input id="baseUrl" type="text" class="textinput" placeholder="http://127.0.0.1:8080/v1" autocomplete="off"/> <!></div> <div class="formelement"><label for="apiKey">Clé API</label> <input id="apiKey" type="password" class="textinput" placeholder="clé API (optionnel)" autocomplete="new-password"/> <!></div> <div class="formelement"><label for="models">Models</label> <button class="bt small">Afficher les modèles disponibles</button> <ol class="ml-2"></ol> <div><!></div></div> <div class="text-right"><button type="button" class="bt">Annuler</button> <button type="submit" class="bt mx-4">Enregistrer</button></div></form></div></div>`);function R(t,l){g(l,!0);let y=h(l,`item`,7),x=d(a(y().models.split(`|`))),C=d(a(y().models.split(`|`).map(e=>({value:e,selected:!0})))),N=new j,P=e=>{e.focus()},F=e=>{e.preventDefault(),y().models=u(x).join(`|`),l.onSave(y())},R=e=>{e.preventDefault(),l.onCancel()},z=e=>{e.preventDefault(),N.clear(),A.getAvailableModels(y().teamId,y()).then(e=>{p(C,e.map(e=>({value:e,selected:u(x).includes(e)})),!0)}).catch(e=>{N.set(`models`,e)})},B=()=>{p(x,u(C).filter(e=>e.selected).map(e=>e.value),!0)};var V=L(),H=i(V),U=i(H),W=i(U),G=S(i(W),2);T(G),k(()=>_(G,()=>y().name,e=>y().name=e)),m(G,e=>P?.(e));var te=S(G,2);M(te,{key:`name`,get errors(){return l.errors}}),v(W);var K=S(W,2),q=S(i(K),2);ee(q,{get items(){return l.providerTypes},valueMode:`id`,get value(){return y().type},set value(e){y().type=e}});var ne=S(q,2);M(ne,{key:`type`,get errors(){return l.errors}}),v(K);var J=S(K,2),Y=S(i(J),2);T(Y);var re=S(Y,2);M(re,{key:`baseUrl`,get errors(){return l.errors}}),v(J);var X=S(J,2),Z=S(i(X),2);T(Z);var ie=S(Z,2);M(ie,{key:`apiKey`,get errors(){return l.errors}}),v(X);var Q=S(X,2),ae=S(i(Q),2),$=S(ae,2);O($,21,()=>u(C),e=>e.value,(t,a,c)=>{var l=n(),d=o(l),p=t=>{var n=I(),o=i(n),c=i(o);T(c);var l=S(c);v(o),v(n),e(()=>f(l,` ${u(a).value??``}`)),s(`change`,c,B),w(c,()=>u(a).selected,e=>u(a).selected=e),r(t,n)};D(d,e=>{u(a).value&&e(p)}),r(t,l)}),v($);var oe=S($,2),se=i(oe);M(se,{key:`models`,get errors(){return N}}),v(oe),v(Q);var ce=S(Q,2),le=i(ce);E(2),v(ce),v(U),v(H),v(V),c(`submit`,U,F),s(`change`,U,()=>{l.errors.clear()}),_(Y,()=>y().baseUrl,e=>y().baseUrl=e),_(Z,()=>y().apiKey,e=>y().apiKey=e),s(`click`,ae,z),s(`click`,le,R),r(t,V),b()}x([`change`,`click`]);var z=l(`<div class="rounded border border-dashed p-2 border-stone-500 cursor-pointer" tabindex="0"><i class="icon-plus"></i> Ajouter un fournisseur</div>`),B=l(`<div class="rounded border p-2 my-2 border-stone-500 flex"><div class="flex-1"><span> </span> <span class="text-stone-500"> </span></div> <button class="bt small mx-1"><i class="icon-edit"></i></button> <button class="bt small mx-1"><i class="icon-trash-empty"></i></button></div>`),V=l(`<div class="container"><!> <!></div>`);function H(c,l){g(l,!0);let m=d(a([])),h=d(!1),_=d(null),y=d(a({})),x=new j;C(async()=>{p(m,await A.getProviders(l.data.space),!0)});let w=()=>{u(_)||(x.clear(),p(y,{},!0),u(y).models=``,p(h,!0))},T=()=>{p(h,!1)},E=e=>{e.name||x.set(`name`,`Le nom est obligatoire !`),e.type||x.set(`type`,`Le type est obligatoire !`),e.baseUrl&&!N(e.baseUrl)&&x.set(`baseUrl`,`Mauvaise URL !`),x.size===0&&A.createProvider(l.data.space,e).then(e=>{u(m).push(e),p(h,!1),p(y,{},!0)}).catch(e=>{console.log(e)})},k=()=>{p(_,null),p(y,{},!0)},M=e=>{e.name||x.set(`name`,`Le nom est obligatoire !`),e.type||x.set(`type`,`Le type est obligatoire !`),e.baseUrl&&!N(e.baseUrl)&&x.set(`baseUrl`,`Mauvaise URL !`),x.size===0&&A.updateProvider(l.data.space,e).then(e=>{p(m,u(m).map(t=>e.id===t.id?e:t),!0),p(_,null),p(y,{},!0)}).catch(e=>{console.log(e)})},ee=async e=>{x.clear(),!u(h)&&A.getProvider(l.data.space,e).then(t=>{p(m,u(m).map(n=>n.id===e?t:n),!0),p(_,e,!0)})},P=e=>{A.deleteProvider(l.data.space,e).then(()=>{p(m,u(m).filter(t=>t.id!==e),!0)}).catch(e=>{console.log(e)})};var F=V(),I=i(F),L=e=>{var i=n(),a=o(i);t(a,()=>`new`,e=>{R(e,{get item(){return u(y)},get errors(){return x},get providerTypes(){rLine truncated
@@ -0,0 +1 @@
import{B as e,C as t,D as n,E as r,G as i,J as a,K as o,L as s,M as c,N as l,O as u,P as d,Q as f,T as p,X as m,_ as h,a as g,at as _,c as v,dt as y,ft as b,it as x,j as S,q as C,s as ee,u as w,ut as T,w as E,x as D,z as O}from"../chunks/39JK5HWF.js";import"../chunks/xihTtKlq.js";import{t as k}from"../chunks/DOY2HMbt.js";import{n as A,t as j}from"../chunks/DRdGzrsF.js";import{t as M}from"../chunks/BorM6hBh.js";import{n as N}from"../chunks/D3MDK1zR.js";var P=b({load:()=>F}),F=async({params:e})=>({title:`Paramétrage : Modèles`,back:`../settings`,space:e.space,providerTypes:await k.providerTypes(),providers:await k.getProviders(e.space)}),I=u(`<li><label><input type="checkbox"/> </label></li>`),L=u(`<div><div class="formgroup my-2"><form><div class="formelement"><label for="name">Nom</label> <input id="name" type="text" class="textinput" placeholder="nom affiché"/> <!></div> <div class="formelement"><label for="type" class="block my-1 flex-1">Type</label> <!> <!></div> <div class="formelement"><label for="baseUrl">URL</label> <input id="baseUrl" type="text" class="textinput" placeholder="http://127.0.0.1:8080/v1" autocomplete="off"/> <!></div> <div class="formelement"><label for="apiKey">Clé API</label> <input id="apiKey" type="password" class="textinput" placeholder="clé API (optionnel)" autocomplete="new-password"/> <!></div> <div class="formelement"><label for="models">Models</label> <button class="bt small">Afficher les modèles disponibles</button> <ol class="ml-2"></ol> <div><!></div></div> <div class="text-right"><button type="button" class="bt">Annuler</button> <button type="submit" class="bt mx-4">Enregistrer</button></div></form></div></div>`);function R(t,s){_(s,!0);let u=g(s,`item`,7),b=f(a(u().models.split(`|`))),S=f(a(u().models.split(`|`).map(e=>({value:e,selected:!0})))),N=new A,P=e=>{e.focus()},F=e=>{e.preventDefault(),u().models=d(b).join(`|`),s.onSave(u())},R=e=>{e.preventDefault(),s.onCancel()},z=e=>{e.preventDefault(),N.clear(),k.getAvailableModels(u().teamId,u()).then(e=>{m(S,e.map(e=>({value:e,selected:d(b).includes(e)})),!0)}).catch(e=>{N.set(`models`,e)})},B=()=>{m(b,d(S).filter(e=>e.selected).map(e=>e.value),!0)};var V=L(),H=i(V),U=i(H),W=i(U),G=C(i(W),2);w(G),O(()=>v(G,()=>u().name,e=>u().name=e)),h(G,e=>P?.(e));var te=C(G,2);j(te,{key:`name`,get errors(){return s.errors}}),y(W);var K=C(W,2),q=C(i(K),2);M(q,{get items(){return s.providerTypes},valueMode:`id`,get value(){return u().type},set value(e){u().type=e}});var ne=C(q,2);j(ne,{key:`type`,get errors(){return s.errors}}),y(K);var J=C(K,2),Y=C(i(J),2);w(Y);var re=C(Y,2);j(re,{key:`baseUrl`,get errors(){return s.errors}}),y(J);var X=C(J,2),Z=C(i(X),2);w(Z);var ie=C(Z,2);j(ie,{key:`apiKey`,get errors(){return s.errors}}),y(X);var Q=C(X,2),ae=C(i(Q),2),$=C(ae,2);D($,21,()=>d(S),e=>e.value,(t,a,s)=>{var l=n(),u=o(l),f=t=>{var n=I(),o=i(n),s=i(o);w(s);var l=C(s);y(o),y(n),e(()=>p(l,` ${d(a).value??``}`)),c(`change`,s,B),ee(s,()=>d(a).selected,e=>d(a).selected=e),r(t,n)};E(u,e=>{d(a).value&&e(f)}),r(t,l)}),y($);var oe=C($,2),se=i(oe);j(se,{key:`models`,get errors(){return N}}),y(oe),y(Q);var ce=C(Q,2),le=i(ce);T(2),y(ce),y(U),y(H),y(V),l(`submit`,U,F),c(`change`,U,()=>{s.errors.clear()}),v(Y,()=>u().baseUrl,e=>u().baseUrl=e),v(Z,()=>u().apiKey,e=>u().apiKey=e),c(`click`,ae,z),c(`click`,le,R),r(t,V),x()}S([`change`,`click`]);var z=u(`<button class="rounded w-full border border-dashed p-2 border-stone-500 cursor-pointer" tabindex="0"><i class="icon-plus"></i> Ajouter un fournisseur</button>`),B=u(`<div class="rounded border p-2 my-2 border-stone-500 flex"><div class="flex-1"><span> </span> <span class="text-stone-500"> </span></div> <button class="bt small mx-1" aria-label="Modifier"><i class="icon-edit"></i></button> <button class="bt small mx-1" aria-label="Supprimer"><i class="icon-trash-empty"></i></button></div>`),V=u(`<div class="container"><!> <!></div>`);function H(l,u){_(u,!0);let h=f(a(s(()=>u.data.providers))),g=f(!1),v=f(null),b=f(a({})),S=new A,ee=()=>{d(v)||(S.clear(),m(b,{},!0),d(b).models=``,m(g,!0))},w=()=>{m(g,!1)},T=e=>{e.name||S.set(`name`,`Le nom est obligatoire !`),e.type||S.set(`type`,`Le type est obligatoire !`),e.baseUrl&&!N(e.baseUrl)&&S.set(`baseUrl`,`Mauvaise URL !`),S.size===0&&k.createProvider(u.data.space,e).then(e=>{d(h).push(e),m(g,!1),m(b,{},!0)}).catch(e=>{console.log(e)})},O=()=>{m(v,null),m(b,{},!0)},j=e=>{e.name||S.set(`name`,`Le nom est obligatoire !`),e.type||S.set(`type`,`Le type est obligatoire !`),e.baseUrl&&!N(e.baseUrl)&&S.set(`baseUrl`,`Mauvaise URL !`),S.size===0&&k.updateProvider(u.data.space,e).then(e=>{m(h,d(h).map(t=>e.id===t.id?e:t),!0),m(v,null),m(b,{},!0)}).catch(e=>{console.log(e)})},M=async e=>{S.clear(),!d(g)&&k.getProvider(u.data.space,e).then(t=>{m(h,d(h).map(n=>n.id===e?t:n),!0),m(v,e,!0)})},P=e=>{k.deleteProvider(u.data.space,e).then(()=>{m(h,d(h).filter(t=>t.id!==e),!0)}).catch(e=>{console.log(e)})};var F=V(),I=i(F),L=e=>{var i=n(),a=o(i);t(a,()=>`new`,e=>{R(e,{get item()Line truncated
@@ -0,0 +1 @@
import{$ as e,A as t,B as n,E as r,G as i,J as a,K as o,L as s,M as c,N as l,O as u,P as d,Q as f,T as p,V as m,X as h,_ as ee,a as g,at as te,c as _,dt as v,ft as y,h as b,it as ne,j as x,p as S,q as C,r as re,u as w,ut as T,w as E,x as ie,z as ae}from"../chunks/39JK5HWF.js";import"../chunks/xihTtKlq.js";import{n as oe,t as se}from"../chunks/DTCALkcP.js";import{t as D}from"../chunks/BC84wEQu.js";import{t as O}from"../chunks/BDef5Ccs.js";import{n as ce,t as k}from"../chunks/DRdGzrsF.js";import{t as le}from"../chunks/BorM6hBh.js";import{t as ue}from"../chunks/D3MDK1zR.js";var de=y({load:()=>fe}),fe=async()=>({title:`Profil`,me:await O.me()}),A=function(e){return e[e.None=0]=`None`,e[e.Changed=1]=`Changed`,e[e.Saving=2]=`Saving`,e[e.Saved=3]=`Saved`,e[e.Error=4]=`Error`,e}({}),pe={listTimezones:()=>D.get(`/misc/timezones`)},me=u(`<i class="incon-spin1 anomate-spin"></i> Enregistrement en cours`,1),he=u(`<i class="incon-ok anomate-spin"></i> Enregistrement réussi`,1),ge=u(`<button><!></button>`);function _e(e,a){te(a,!0);let o=g(a,`state`,7),s=g(a,`disabled`,3,!1);m(()=>{(o()===A.Saved||o()===A.Error)&&setTimeout(()=>{o(A.None)},2e3)});let l=()=>{a.handleClick&&(o()===A.Changed||o()===A.None)&&a.handleClick()};var u=ge();let d;var f=i(u),h=e=>{var i=t();n(()=>p(i,a.label)),r(e,i)},ee=e=>{var t=me();T(),r(e,t)},_=e=>{var t=he();T(),r(e,t)},y=e=>{var n=t(`Echec`);r(e,n)};E(f,e=>{o()==A.None||o()==A.Changed?e(h):o()==A.Saving?e(ee,1):o()==A.Saved?e(_,2):o()==A.Error&&e(y,3)}),v(u),n(()=>{u.disabled=s(),d=b(u,1,`bt`,null,d,{disabled:s(),changed:o()===A.Changed,saving:o()===A.Saving,saved:o()===A.Saved,error:o()===A.Error})}),c(`click`,u,l),r(e,u),ne()}x([`click`]);var ve=u(`<div class="m-2"><div class="dark:bg-stone-700 bg-stone-300 rounded inline px-2 py-1 text-sm"><span class="inline-block w-20"> </span> <span> </span> <button class="ml-4 pointer" title="Annuler"><i class="icon-cancel"></i></button></div></div>`),ye=u(`<div class="mb-4 formgroup container"><h2>Mon compte</h2> <form><div class="formelement"><label for="email" class="my-1 flex-1">Email</label> <input id="email" type="text" class="textinput"/> <!></div> <div class="grid grid-cols-1 gap-x-4 md:grid-cols-2"><div class="formelement"><label for="firstname" class=" my-1 flex-1">Prénom</label> <input id="firstname" type="text" class="textinput"/> <!></div> <div class="formelement"><label for="lastname" class="my-1 flex-1">Nom</label> <input id="lastname" type="text" class="textinput"/> <!></div></div> <div class="grid grid-cols-1 gap-x-4 md:grid-cols-2"><div class="formelement"><label for="lang" class="block my-1 flex-1">Langue</label> <select class="textinput"><option>English</option><option>Français</option></select> <!></div> <div class="formelement"><label for="timezone" class="block my-1 flex-1">Timezone</label> <!> <!></div></div> <div class="formelement"><label for="theme" class="block my-1 flex-1">Thème</label> <select class="textinput"><option>Automatique</option><option>Sombre</option><option>Clair</option></select> <!></div> <!></form></div> <div class="mb-4 formgroup container"><h2>Canaux de communication</h2> <!> <div class="flex gap-2 mt-6"><div><select class="textinput"><option></option><option>Email</option><option>Signal</option><option>Telegram</option><option>Whatsapp</option></select></div> <div class="flex-1"><input type="text" class="textinput"/></div> <div><!></div></div></div>`,1);function j(t,u){te(u,!0);let g=a(s(()=>u.data.me.user)),y=f(a([])),b=f(a({type:``,address:``})),x=f(a([])),T=new ce,E=f(a(A.None)),D=f(a(A.None));re(async()=>{h(y,await O.listAddresses(g.id),!0),h(x,(await pe.listTimezones()).map(e=>({value:e,label:e})),!0)}),m(()=>{oe(g.theme),se()});let de=e=>{e.preventDefault(),h(E,A.Saving,!0),ue(g.email)||T.set(`email`,`Adresse email invalide !`),g.firstname||T.set(`firstname`,`Le prénom est obligatoire !`),g.lastname||T.set(`lastname`,`Le nom est obligatoire !`),T.size==0&&O.update(g.id,g).then(()=>{h(E,A.Saved,!0)}).catch(e=>{h(E,A.Saving,!0),console.error(e)})},fe=()=>{h(D,A.Saving,!0),O.createAddress(g.id,d(b)).then(e=>{d(y).push(e),h(b,{type:``,address:``},!0),h(D,A.Saved,!0)}).catch(e=>{console.log(e)})},me=e=>{O.deleteAddress(g.id,e).then(()=>{h(y,d(y).filter(t=>t.id!=e),!0)}).catch(e=>{console.log(e)})},he=()=>{T.clear(),h(E,A.Changed,!0)},ge=e=>{e.focus()};var j=ye(),M=o(j),N=C(i(M),2),P=i(N),F=C(i(P),2);w(F),ae(()=>_(F,()=>g.email,e=>g.email=e)),ee(F,e=>ge?.(e));var be=C(F,2);k(be,{key:`email`,get errors(){return T}}),v(P);var I=C(P,2),L=i(I),R=C(i(L),2);w(R);var xe=C(R,2);k(xe,{key:`firstname`,get errors(){return T}}),v(L);var Se=C(L,2),z=C(i(Se),2);w(z);var Ce=C(z,2);k(Ce,{key:`lastname`,get errors(){return T}}),v(Se),v(I);var B=C(I,2),V=i(B),H=C(i(V),2),U=i(H);U.value=U.__value=`en`;var we=C(U);we.value=we.__value=`fr`,v(H);var Te=C(H,2);k(Te,{key:`lang`,get errors(){return T}}),v(V);var Ee=C(V,2),De=C(i(Ee),2);le(De,{get items(){return d(x)},valueMode:`id`,get value(){return g.timezone},set valueLine truncated
@@ -1 +0,0 @@
import{$ as e,A as t,B as n,E as r,G as i,J as a,K as o,L as s,M as c,N as l,O as u,P as d,Q as f,T as p,V as m,X as h,_ as ee,a as g,at as te,c as _,dt as v,ft as y,h as b,it as ne,j as x,p as S,q as C,r as re,u as w,ut as T,w as E,x as ie,z as ae}from"../chunks/39JK5HWF.js";import"../chunks/xihTtKlq.js";import{n as oe,t as se}from"../chunks/DTCALkcP.js";import{t as D}from"../chunks/BqkZ0BZ5.js";import{t as O}from"../chunks/BEgKbVuy.js";import{n as ce,t as k}from"../chunks/DRdGzrsF.js";import{t as le}from"../chunks/D4uBfDnr.js";import{t as ue}from"../chunks/D3MDK1zR.js";var de=y({load:()=>fe}),fe=async()=>({title:`Profil`,me:await O.me()}),A=function(e){return e[e.None=0]=`None`,e[e.Changed=1]=`Changed`,e[e.Saving=2]=`Saving`,e[e.Saved=3]=`Saved`,e[e.Error=4]=`Error`,e}({}),pe={listTimezones:()=>D.get(`/misc/timezones`)},me=u(`<i class="incon-spin1 anomate-spin"></i> Enregistrement en cours`,1),he=u(`<i class="incon-ok anomate-spin"></i> Enregistrement réussi`,1),ge=u(`<button><!></button>`);function _e(e,a){te(a,!0);let o=g(a,`state`,7),s=g(a,`disabled`,3,!1);m(()=>{(o()===A.Saved||o()===A.Error)&&setTimeout(()=>{o(A.None)},2e3)});let l=()=>{a.handleClick&&(o()===A.Changed||o()===A.None)&&a.handleClick()};var u=ge();let d;var f=i(u),h=e=>{var i=t();n(()=>p(i,a.label)),r(e,i)},ee=e=>{var t=me();T(),r(e,t)},_=e=>{var t=he();T(),r(e,t)},y=e=>{var n=t(`Echec`);r(e,n)};E(f,e=>{o()==A.None||o()==A.Changed?e(h):o()==A.Saving?e(ee,1):o()==A.Saved?e(_,2):o()==A.Error&&e(y,3)}),v(u),n(()=>{u.disabled=s(),d=b(u,1,`bt`,null,d,{disabled:s(),changed:A.Changed,saving:A.Saving,saved:A.Saved,error:A.Error})}),c(`click`,u,l),r(e,u),ne()}x([`click`]);var ve=u(`<div class="m-2"><div class="dark:bg-stone-700 bg-stone-300 rounded inline px-2 py-1 text-sm"><span class="inline-block w-20"> </span> <span> </span> <button class="ml-4 pointer" title="Annuler"><i class="icon-cancel"></i></button></div></div>`),ye=u(`<div class="mb-4 formgroup container"><h2>Mon compte</h2> <form><div class="formelement"><label for="email" class="my-1 flex-1">Email</label> <input id="email" type="text" class="textinput"/> <!></div> <div class="grid grid-cols-1 gap-x-4 md:grid-cols-2"><div class="formelement"><label for="firstname" class=" my-1 flex-1">Prénom</label> <input id="firstname" type="text" class="textinput"/> <!></div> <div class="formelement"><label for="lastname" class="my-1 flex-1">Nom</label> <input id="lastname" type="text" class="textinput"/> <!></div></div> <div class="grid grid-cols-1 gap-x-4 md:grid-cols-2"><div class="formelement"><label for="lang" class="block my-1 flex-1">Langue</label> <select class="textinput"><option>English</option><option>Français</option></select> <!></div> <div class="formelement"><label for="timezone" class="block my-1 flex-1">Timezone</label> <!> <!></div></div> <div class="formelement"><label for="theme" class="block my-1 flex-1">Thème</label> <select class="textinput"><option>Automatique</option><option>Sombre</option><option>Clair</option></select> <!></div> <!></form></div> <div class="mb-4 formgroup container"><h2>Canaux de communication</h2> <!> <div class="flex gap-2 mt-6"><div><select class="textinput"><option></option><option>Email</option><option>Signal</option><option>Telegram</option><option>Whatsapp</option></select></div> <div class="flex-1"><input type="text" class="textinput"/></div> <div><!></div></div></div>`,1);function j(t,u){te(u,!0);let g=a(s(()=>u.data.me.user)),y=f(a([])),b=f(a({type:``,address:``})),x=f(a([])),T=new ce,E=f(a(A.None)),D=f(a(A.None));re(async()=>{h(y,await O.listAddresses(g.id),!0),h(x,(await pe.listTimezones()).map(e=>({value:e,label:e})),!0)}),m(()=>{oe(g.theme),se()});let de=e=>{e.preventDefault(),h(E,A.Saving,!0),ue(g.email)||T.set(`email`,`Adresse email invalide !`),g.firstname||T.set(`firstname`,`Le prénom est obligatoire !`),g.lastname||T.set(`lastname`,`Le nom est obligatoire !`),T.size==0&&O.update(g.id,g).then(()=>{h(E,A.Saved,!0)}).catch(e=>{h(E,A.Saving,!0),console.error(e)})},fe=()=>{h(D,A.Saving,!0),O.createAddress(g.id,d(b)).then(e=>{d(y).push(e),h(b,{type:``,address:``},!0),h(D,A.Saved,!0)}).catch(e=>{console.log(e)})},me=e=>{O.deleteAddress(g.id,e).then(()=>{h(y,d(y).filter(t=>t.id!=e),!0)}).catch(e=>{console.log(e)})},he=()=>{T.clear(),h(E,A.Changed,!0)},ge=e=>{e.focus()};var j=ye(),M=o(j),N=C(i(M),2),P=i(N),F=C(i(P),2);w(F),ae(()=>_(F,()=>g.email,e=>g.email=e)),ee(F,e=>ge?.(e));var be=C(F,2);k(be,{key:`email`,get errors(){return T}}),v(P);var I=C(P,2),L=i(I),R=C(i(L),2);w(R);var xe=C(R,2);k(xe,{key:`firstname`,get errors(){return T}}),v(L);var Se=C(L,2),z=C(i(Se),2);w(z);var Ce=C(z,2);k(Ce,{key:`lastname`,get errors(){return T}}),v(Se),v(I);var B=C(I,2),V=i(B),H=C(i(V),2),U=i(H);U.value=U.__value=`en`;var we=C(U);we.value=we.__value=`fr`,v(H);var Te=C(H,2);k(Te,{key:`lang`,get errors(){return T}}),v(V);var Ee=C(V,2),De=C(i(Ee),2);le(De,{get items(){return d(x)},valueMode:`id`,get value(){return g.timezone},set value(e){g.timezone=e}});var Line truncated
@@ -1 +1 @@
import{B as e,E as t,G as n,J as r,K as i,M as a,N as o,O as s,at as c,c as l,d as u,dt as d,et as f,it as p,j as m,q as h,u as g,ut as _,w as v}from"../chunks/39JK5HWF.js";import{t as y}from"../chunks/D3up1JC1.js";import"../chunks/xihTtKlq.js";import"../chunks/B5isPFOt.js";import{i as b,n as x}from"../chunks/BqkZ0BZ5.js";import{t as S}from"../chunks/BRXBpvt8.js";import{t as C}from"../chunks/DNQ6C3zq.js";var w=s(`<form><div class="flex"><label for="email" class="block mb-2 flex-1">Email</label> <a href="/recover-password" class="text-xs">Mot de passe oublié ?</a></div> <div class="flex flex-row"><input type="text" class="textinput mr-1"/> <button class="bt" title="page suivante"><i class="icon-right-big"></i></button></div></form> <div class="my-4 text-xs"><a href="/register">Pas encore de compte ? Incrivez-vous.</a></div>`,1),T=s(`<form><div class="flex"><label for="email" class="block mb-2 flex-1">Mot de passe</label></div> <div class="flex flex-row"><input type="password" class="textinput mr-1"/> <button class="bt">Entrer</button></div> <a href="/login" class="text-xs">← Retour</a></form>`),E=s(`<div class="h-full w-full flex items-center public"><div class="m-auto w-96 max-w-full p-4"><img class="h-10 mb-4" alt="logo"/> <h1>Identifiez-vous ...</h1> <!> <hr class="my-4"/> <div class="grid grid-cols-[repeat(auto-fit,minmax(150px,1fr))] gap-4"><button class="bt p-5 text-center" title="Connexion avec Google"><i class="icon-google"></i></button> <button class="bt p-5 text-center" title="Connexion avec Facebook"><i class="icon-facebook"></i></button> <button class="bt p-5 text-center" title="Connexion avec Github"><i class="icon-github"></i></button> <button class="bt p-5 text-center" title="Connexion avec Apple"><i class="icon-apple"></i></button></div></div></div>`);function D(s,m){c(m,!0);let D=r({email:``,password:``,validemail:!1}),O=()=>{D.validemail=!0},k=e=>{e.preventDefault(),C.login(D).then(e=>{x.user=e.user,b(e.accessToken),y(`/`)}).catch(e=>{console.log(e)})};var A=E(),j=n(A),M=n(j),N=h(M,4),P=e=>{var r=w(),a=i(r),s=h(n(a),2),c=n(s);g(c),f(c,!0),_(2),d(s),d(a),_(2),o(`submit`,a,O),l(c,()=>D.email,e=>D.email=e),t(e,r)},F=e=>{var r=T(),i=h(n(r),2),s=n(i);g(s),f(s,!0),_(2),d(i);var c=h(i,2);d(r),o(`submit`,r,k),l(s,()=>D.password,e=>D.password=e),a(`click`,c,()=>{D.validemail=!1}),t(e,r)};v(N,e=>{D.validemail?e(F,-1):e(P)}),_(4),d(j),d(A),e(()=>u(M,`src`,S)),t(s,A),p()}m([`click`]);export{D as component};
import{B as e,E as t,G as n,J as r,K as i,M as a,N as o,O as s,at as c,c as l,d as u,dt as d,et as f,it as p,j as m,q as h,u as g,ut as _,w as v}from"../chunks/39JK5HWF.js";import{t as y}from"../chunks/B0qrqti_.js";import"../chunks/xihTtKlq.js";import"../chunks/DL7ZyBAF.js";import{i as b,n as x}from"../chunks/BC84wEQu.js";import{t as S}from"../chunks/BRXBpvt8.js";import{t as C}from"../chunks/DFI7Zp3t.js";var w=s(`<form><div class="flex"><label for="email" class="block mb-2 flex-1">Email</label> <a href="/recover-password" class="text-xs">Mot de passe oublié ?</a></div> <div class="flex flex-row"><input type="text" class="textinput mr-1"/> <button class="bt" title="page suivante"><i class="icon-right-big"></i></button></div></form> <div class="my-4 text-xs"><a href="/register">Pas encore de compte ? Incrivez-vous.</a></div>`,1),T=s(`<form><div class="flex"><label for="email" class="block mb-2 flex-1">Mot de passe</label></div> <div class="flex flex-row"><input type="password" class="textinput mr-1"/> <button class="bt">Entrer</button></div> <a href="/login" class="text-xs">← Retour</a></form>`),E=s(`<div class="h-full w-full flex items-center public"><div class="m-auto w-96 max-w-full p-4"><img class="h-10 mb-4" alt="logo"/> <h1>Identifiez-vous ...</h1> <!> <hr class="my-4"/> <div class="grid grid-cols-[repeat(auto-fit,minmax(150px,1fr))] gap-4"><button class="bt p-5 text-center" title="Connexion avec Google"><i class="icon-google"></i></button> <button class="bt p-5 text-center" title="Connexion avec Facebook"><i class="icon-facebook"></i></button> <button class="bt p-5 text-center" title="Connexion avec Github"><i class="icon-github"></i></button> <button class="bt p-5 text-center" title="Connexion avec Apple"><i class="icon-apple"></i></button></div></div></div>`);function D(s,m){c(m,!0);let D=r({email:``,password:``,validemail:!1}),O=()=>{D.validemail=!0},k=e=>{e.preventDefault(),C.login(D).then(e=>{x.user=e.user,b(e.accessToken),y(`/`)}).catch(e=>{console.log(e)})};var A=E(),j=n(A),M=n(j),N=h(M,4),P=e=>{var r=w(),a=i(r),s=h(n(a),2),c=n(s);g(c),f(c,!0),_(2),d(s),d(a),_(2),o(`submit`,a,O),l(c,()=>D.email,e=>D.email=e),t(e,r)},F=e=>{var r=T(),i=h(n(r),2),s=n(i);g(s),f(s,!0),_(2),d(i);var c=h(i,2);d(r),o(`submit`,r,k),l(s,()=>D.password,e=>D.password=e),a(`click`,c,()=>{D.validemail=!1}),t(e,r)};v(N,e=>{D.validemail?e(F,-1):e(P)}),_(4),d(j),d(A),e(()=>u(M,`src`,S)),t(s,A),p()}m([`click`]);export{D as component};
@@ -1 +1 @@
import{B as e,E as t,G as n,J as r,M as i,N as a,O as o,at as s,c,d as l,dt as u,et as d,it as f,j as p,q as m,u as h}from"../chunks/39JK5HWF.js";import{t as g}from"../chunks/D3up1JC1.js";import"../chunks/xihTtKlq.js";import"../chunks/B5isPFOt.js";import{t as _}from"../chunks/BRXBpvt8.js";import{n as v,t as y}from"../chunks/DRdGzrsF.js";import{t as b}from"../chunks/D3MDK1zR.js";import{t as x}from"../chunks/DNQ6C3zq.js";var S=o(`<div class="h-full w-full flex items-center public"><div class="m-auto w-96 max-w-full p-4"><img class="h-10 mb-4" alt="logo"/> <h1>Inscription</h1> <form><label for="email" class="block my-1 flex-1">Email</label> <input id="email" type="text" class="textinput"/> <!> <label for="firstname" class="block my-1 flex-1">Prénom</label> <input id="firstname" type="text" class="textinput"/> <!> <label for="lastname" class="block my-1 flex-1">Nom</label> <input id="lastname" type="text" class="textinput"/> <!> <label for="password" class="block my-1 flex-1">Mot de passe</label> <input id="password" type="password" class="textinput"/> <!> <label for="verifpassword" class="block my-1 flex-1">Vérification du mot de passe</label> <input id="verifpassword" type="password" class="textinput"/> <!> <button class="bt my-2 w-full ">Enregistrer</button> <!></form></div></div>`);function C(o,p){s(p,!0);let C=new v,w=r({email:``,firstname:``,lastname:``,password:``,verifPassword:``}),T=e=>{if(e.preventDefault(),C.clear(),b(w.email)||C.set(`email`,`Adresse email invalide !`),w.firstname||C.set(`firstname`,`Le prénom est obligatoire !`),w.lastname||C.set(`lastname`,`Le nom est obligatoire !`),w.password!==w.verifPassword&&C.set(`verifPassword`,`Les mots de pass ne correspondent pas.`),C.size==0){let e={method:`password`,email:w.email,firstname:w.firstname,lastname:w.lastname,password:w.password};x.register(e).then(()=>{g(`/`)}).catch(e=>{C.set(`submit`,`Erreur: `+e)})}};var E=S(),D=n(E),O=n(D),k=m(O,4),A=m(n(k),2);h(A),d(A,!0);var j=m(A,2);y(j,{key:`email`,get errors(){return C}});var M=m(j,4);h(M);var N=m(M,2);y(N,{key:`firstname`,get errors(){return C}});var P=m(N,4);h(P);var F=m(P,2);y(F,{key:`lastname`,get errors(){return C}});var I=m(F,4);h(I);var L=m(I,2);y(L,{key:`password`,get errors(){return C}});var R=m(L,4);h(R);var z=m(R,2);y(z,{key:`verifPassword`,get errors(){return C}});var B=m(z,4);y(B,{key:`submit`,get errors(){return C}}),u(k),u(D),u(E),e(()=>l(O,`src`,_)),a(`submit`,k,T),i(`change`,k,()=>{C.clear()}),c(A,()=>w.email,e=>w.email=e),c(M,()=>w.firstname,e=>w.firstname=e),c(P,()=>w.lastname,e=>w.lastname=e),c(I,()=>w.password,e=>w.password=e),c(R,()=>w.verifPassword,e=>w.verifPassword=e),t(o,E),f()}p([`change`]);export{C as component};
import{B as e,E as t,G as n,J as r,M as i,N as a,O as o,at as s,c,d as l,dt as u,et as d,it as f,j as p,q as m,u as h}from"../chunks/39JK5HWF.js";import{t as g}from"../chunks/B0qrqti_.js";import"../chunks/xihTtKlq.js";import"../chunks/DL7ZyBAF.js";import{t as _}from"../chunks/BRXBpvt8.js";import{n as v,t as y}from"../chunks/DRdGzrsF.js";import{t as b}from"../chunks/D3MDK1zR.js";import{t as x}from"../chunks/DFI7Zp3t.js";var S=o(`<div class="h-full w-full flex items-center public"><div class="m-auto w-96 max-w-full p-4"><img class="h-10 mb-4" alt="logo"/> <h1>Inscription</h1> <form><label for="email" class="block my-1 flex-1">Email</label> <input id="email" type="text" class="textinput"/> <!> <label for="firstname" class="block my-1 flex-1">Prénom</label> <input id="firstname" type="text" class="textinput"/> <!> <label for="lastname" class="block my-1 flex-1">Nom</label> <input id="lastname" type="text" class="textinput"/> <!> <label for="password" class="block my-1 flex-1">Mot de passe</label> <input id="password" type="password" class="textinput"/> <!> <label for="verifpassword" class="block my-1 flex-1">Vérification du mot de passe</label> <input id="verifpassword" type="password" class="textinput"/> <!> <button class="bt my-2 w-full ">Enregistrer</button> <!></form></div></div>`);function C(o,p){s(p,!0);let C=new v,w=r({email:``,firstname:``,lastname:``,password:``,verifPassword:``}),T=e=>{if(e.preventDefault(),C.clear(),b(w.email)||C.set(`email`,`Adresse email invalide !`),w.firstname||C.set(`firstname`,`Le prénom est obligatoire !`),w.lastname||C.set(`lastname`,`Le nom est obligatoire !`),w.password!==w.verifPassword&&C.set(`verifPassword`,`Les mots de pass ne correspondent pas.`),C.size==0){let e={method:`password`,email:w.email,firstname:w.firstname,lastname:w.lastname,password:w.password};x.register(e).then(()=>{g(`/`)}).catch(e=>{C.set(`submit`,`Erreur: `+e)})}};var E=S(),D=n(E),O=n(D),k=m(O,4),A=m(n(k),2);h(A),d(A,!0);var j=m(A,2);y(j,{key:`email`,get errors(){return C}});var M=m(j,4);h(M);var N=m(M,2);y(N,{key:`firstname`,get errors(){return C}});var P=m(N,4);h(P);var F=m(P,2);y(F,{key:`lastname`,get errors(){return C}});var I=m(F,4);h(I);var L=m(I,2);y(L,{key:`password`,get errors(){return C}});var R=m(L,4);h(R);var z=m(R,2);y(z,{key:`verifPassword`,get errors(){return C}});var B=m(z,4);y(B,{key:`submit`,get errors(){return C}}),u(k),u(D),u(E),e(()=>l(O,`src`,_)),a(`submit`,k,T),i(`change`,k,()=>{C.clear()}),c(A,()=>w.email,e=>w.email=e),c(M,()=>w.firstname,e=>w.firstname=e),c(P,()=>w.lastname,e=>w.lastname=e),c(I,()=>w.password,e=>w.password=e),c(R,()=>w.verifPassword,e=>w.verifPassword=e),t(o,E),f()}p([`change`]);export{C as component};
@@ -1 +0,0 @@
import{$ as e,B as t,E as n,G as r,J as i,K as a,M as o,N as s,O as c,P as l,T as u,V as d,W as f,a as p,at as m,b as h,d as g,dt as _,ft as v,g as y,h as b,it as x,j as S,q as C,r as w,w as T,x as E}from"../chunks/39JK5HWF.js";import{t as D}from"../chunks/D3up1JC1.js";import"../chunks/xihTtKlq.js";import{n as O,t as k}from"../chunks/DTCALkcP.js";import{t as A}from"../chunks/D1d5-1oo.js";import"../chunks/B5isPFOt.js";import{n as j,r as M}from"../chunks/BqkZ0BZ5.js";import{t as N}from"../chunks/BEgKbVuy.js";import{t as P}from"../chunks/D8dI9nx6.js";import{t as F}from"../chunks/BRXBpvt8.js";var I=v({load:()=>L}),L=async()=>{let e=await N.me();return P.spaces=e.teams,P.current||(P.current=P.spaces[0].id),{spaceid:P.current,me:e}},R=i({sidebarDesktopOpen:!0,sidebarMobileOpen:!1,menuContentVisible:!0}),z=c(`<span class="ml-4"> </span>`),B=c(`<div class="my-2 block"><a class="p-2 w-full text-left menuitem block"><i></i> <!></a></div>`);function V(e,i){m(i,!0);let a=p(i,`label`,3,``),o=p(i,`icon`,3,``),s=p(i,`link`,3,``);var c=B(),l=r(c),d=r(l),f=C(d,2),h=e=>{var i=z(),o=r(i,!0);_(i),t(()=>u(o,a())),n(e,i)};T(f,e=>{R.menuContentVisible&&e(h)}),_(l),_(c),t(()=>{g(l,`href`,s()),b(d,1,y([o()]))}),n(e,c),x()}var H=c(`<div class="flex-1 p-3 font openonly"><img class="h-5" alt="logo"/></div>`),U=c(`<option> </option>`),W=c(`<div class="m-2"><div class="formelement"><select class="textinput"></select></div></div>`),G=c(`<div class="flex flex-row gap-2 p-2 "><div class="py-1 flex-1 flex flex-row text-xs"><div class="w-6 h-6 rounded-full bg-cyan-600 text-white flex items-center justify-center font-medium">FM</div> <div class="flex-1 ml-2 inline-flex items-center">Fabien Masson</div></div> <a href="/profile" class="bt small inline-flex items-center justify-center" title="Edition profil"><i class="icon-edit"></i></a> <button class="bt small" title="Déconnecter"><i class="icon-logout"></i></button></div>`),K=c(`<div class="flex flex-row italic mb-2"><!> <button id="hamburgerDesktop" title="Open menu"><i class="icon-menu pointer block p-2"></i></button> <button id="hamburgerMobile" title="Open menu"><i class="icon-menu pointer block p-2"></i></button></div> <!> <div id="menu" class="flex-1 overflow-y-scroll"><!> <!> <!> <!> <!></div> <div id="profile" class="w-full items-center border-t border-stone-200 dark:border-stone-800"><!></div>`,1);function q(i,s){m(s,!0);let c=()=>{M()};var d=K(),f=a(d),p=r(f),h=e=>{var i=H(),a=r(i);_(i),t(()=>g(a,`src`,F)),n(e,i)};T(p,e=>{R.menuContentVisible&&e(h)});var v=C(p,2),y=C(v,2);_(f);var b=C(f,2),S=e=>{var i=W(),a=r(i),o=r(a);E(o,21,()=>s.spaces,e=>e.id,(e,i)=>{var a=U(),o=r(a,!0);_(a);var s={};t(()=>{u(o,l(i).label),s!==(s=l(i).id)&&(a.value=(a.__value=l(i).id)??``)}),n(e,a)}),_(o),_(a),_(i),n(e,i)};T(b,e=>{R.menuContentVisible&&e(S)});var w=C(b,2),D=r(w);{let t=e(()=>`/${s.spaceid}`);V(D,{label:`Nouveau chat`,icon:`icon-plus`,get link(){return l(t)}})}var O=C(D,2);{let t=e(()=>`/${s.spaceid}/history`);V(O,{label:`Conversations`,icon:`icon-chat`,get link(){return l(t)}})}var k=C(O,2);{let t=e(()=>`/${s.spaceid}/tasks`);V(k,{label:`Planification`,icon:`icon-tasks`,get link(){return l(t)}})}var A=C(k,2);{let t=e(()=>`/${s.spaceid}/kb`);V(A,{label:`Connaissances`,icon:`icon-graduation-cap`,get link(){return l(t)}})}var j=C(A,2);{let t=e(()=>`/${s.spaceid}/settings`);V(j,{label:`Réglages`,icon:`icon-cog`,get link(){return l(t)}})}_(w);var N=C(w,2),P=r(N),I=e=>{var t=G(),i=C(r(t),4);_(t),o(`click`,i,c),n(e,t)},L=e=>{V(e,{label:`User`,icon:`icon-user`,link:`/profile`})};T(P,e=>{R.menuContentVisible?e(I):e(L,-1)}),_(N),o(`click`,v,function(...e){s.handleMenuDesktop?.apply(this,e)}),o(`click`,y,function(...e){s.handleMenuMobile?.apply(this,e)}),n(i,d),x()}S([`click`]);var J=c(`<span><a title="retour"><i class="icon-left-big"></i></a></span>`),Y=c(`<div id="outer"><div id="sidebar" class="flex flex-col z-10"><!></div> <div id="main"><div class="flex flex-col h-screen "><div class="px-2"><div class="header container"><h1 class="flex"><span class="flex-1"> </span> <!></h1></div></div> <div class="overflow-scroll flex-1 p-2"><!></div></div></div></div>`);function X(e,i){m(i,!0);let a=()=>{R.sidebarDesktopOpen=!R.sidebarDesktopOpen,R.sidebarDesktopOpen?setTimeout(()=>{R.menuContentVisible=R.sidebarDesktopOpen},200):R.menuContentVisible=R.sidebarDesktopOpen},o=()=>{R.sidebarMobileOpen=!R.sidebarMobileOpen,R.sidebarMobileOpen?setTimeout(()=>{R.menuContentVisible=R.sidebarMobileOpen},200):R.menuContentVisible=R.sidebarMobileOpen},c=()=>{R.menuContentVisible=window.innerWidth<640?R.sidebarMobileOpen:R.sidebarDesktopOpen};w(async()=>{c(),i.data.me?(j.user=i.data.me.user,O(j.user.theme),k(),j.status=`authenticated`):j.status=`unauthenticated`}),d(()=>{j.status==`unauthenticated`&&D(`/login`)});var l=Y();s(`resize`,f,c);var p=r(l);q(r(p),{get spaces(){return P.spaces},get spaceid(){return i.data.spaceid},handleMenuDesktop:a,handleMenuMobile:o}),_(p);var v=C(p,2),S=r(v),E=r(S),M=r(E),N=r(M),F=r(N),I=r(F,Line truncated
@@ -0,0 +1 @@
import{$ as e,B as t,E as n,G as r,J as i,K as a,M as o,N as s,O as c,P as l,T as u,V as d,W as f,a as p,at as m,b as h,d as g,dt as _,ft as v,g as y,h as b,it as x,j as S,q as C,r as w,w as T,x as E}from"../chunks/39JK5HWF.js";import{t as D}from"../chunks/B0qrqti_.js";import"../chunks/xihTtKlq.js";import{n as O,t as k}from"../chunks/DTCALkcP.js";import{t as A}from"../chunks/DtPl1hOB.js";import"../chunks/DL7ZyBAF.js";import{n as j,r as M}from"../chunks/BC84wEQu.js";import{t as N}from"../chunks/BDef5Ccs.js";import{t as P}from"../chunks/D8dI9nx6.js";import{t as F}from"../chunks/BRXBpvt8.js";var I=v({load:()=>L}),L=async()=>{let e=await N.me();return P.spaces=e.teams,P.current||(P.current=P.spaces[0].id),{spaceid:P.current,me:e}},R=i({sidebarDesktopOpen:!0,sidebarMobileOpen:!1,menuContentVisible:!0}),z=c(`<span class="ml-4"> </span>`),B=c(`<div class="my-2 block"><a class="p-2 w-full text-left menuitem block"><i></i> <!></a></div>`);function V(e,i){m(i,!0);let a=p(i,`label`,3,``),s=p(i,`icon`,3,``),c=p(i,`link`,3,``),l=e=>{e.preventDefault(),R.sidebarMobileOpen=!1,R.menuContentVisible=!1,D(c())};var d=B(),f=r(d),h=r(f),v=C(h,2),S=e=>{var i=z(),o=r(i,!0);_(i),t(()=>u(o,a())),n(e,i)};T(v,e=>{R.menuContentVisible&&e(S)}),_(f),_(d),t(()=>{g(f,`href`,c()),b(h,1,y([s()]))}),o(`click`,f,l),n(e,d),x()}S([`click`]);var H=c(`<div class="flex-1 p-3 font openonly"><img class="h-5" alt="logo"/></div>`),U=c(`<option> </option>`),W=c(`<div class="m-2"><div class="formelement"><select class="textinput"></select></div></div>`),G=c(`<div class="flex flex-row gap-2 p-2 "><div class="py-1 flex-1 flex flex-row text-xs"><div class="w-6 h-6 rounded-full bg-cyan-600 text-white flex items-center justify-center font-medium">FM</div> <div class="flex-1 ml-2 inline-flex items-center">Fabien Masson</div></div> <a href="/profile" class="bt small inline-flex items-center justify-center" title="Edition profil"><i class="icon-edit"></i></a> <button class="bt small" title="Déconnecter"><i class="icon-logout"></i></button></div>`),K=c(`<div class="flex flex-row italic mb-2"><!> <button id="hamburgerDesktop" title="Open menu"><i class="icon-menu pointer block p-2"></i></button> <button id="hamburgerMobile" title="Open menu"><i class="icon-menu pointer block p-2"></i></button></div> <!> <div id="menu" class="flex-1 overflow-y-scroll"><!> <!> <!> <!> <!></div> <div id="profile" class="w-full items-center border-t border-stone-200 dark:border-stone-800"><!></div>`,1);function q(i,s){m(s,!0);let c=()=>{M()};var d=K(),f=a(d),p=r(f),h=e=>{var i=H(),a=r(i);_(i),t(()=>g(a,`src`,F)),n(e,i)};T(p,e=>{R.menuContentVisible&&e(h)});var v=C(p,2),y=C(v,2);_(f);var b=C(f,2),S=e=>{var i=W(),a=r(i),o=r(a);E(o,21,()=>s.spaces,e=>e.id,(e,i)=>{var a=U(),o=r(a,!0);_(a);var s={};t(()=>{u(o,l(i).label),s!==(s=l(i).id)&&(a.value=(a.__value=l(i).id)??``)}),n(e,a)}),_(o),_(a),_(i),n(e,i)};T(b,e=>{R.menuContentVisible&&e(S)});var w=C(b,2),D=r(w);{let t=e(()=>`/${s.spaceid}`);V(D,{label:`Nouveau chat`,icon:`icon-plus`,get link(){return l(t)}})}var O=C(D,2);{let t=e(()=>`/${s.spaceid}/history`);V(O,{label:`Conversations`,icon:`icon-chat`,get link(){return l(t)}})}var k=C(O,2);{let t=e(()=>`/${s.spaceid}/tasks`);V(k,{label:`Planification`,icon:`icon-tasks`,get link(){return l(t)}})}var A=C(k,2);{let t=e(()=>`/${s.spaceid}/kb`);V(A,{label:`Connaissances`,icon:`icon-graduation-cap`,get link(){return l(t)}})}var j=C(A,2);{let t=e(()=>`/${s.spaceid}/settings`);V(j,{label:`Réglages`,icon:`icon-cog`,get link(){return l(t)}})}_(w);var N=C(w,2),P=r(N),I=e=>{var t=G(),i=C(r(t),4);_(t),o(`click`,i,c),n(e,t)},L=e=>{V(e,{label:`User`,icon:`icon-user`,link:`/profile`})};T(P,e=>{R.menuContentVisible?e(I):e(L,-1)}),_(N),o(`click`,v,function(...e){s.handleMenuDesktop?.apply(this,e)}),o(`click`,y,function(...e){s.handleMenuMobile?.apply(this,e)}),n(i,d),x()}S([`click`]);var J=c(`<span><a title="retour"><i class="icon-left-big"></i></a></span>`),Y=c(`<div id="outer"><div id="sidebar" class="flex flex-col z-10"><!></div> <div id="main"><div class="flex flex-col h-screen "><div class="px-2"><div class="header container"><h1 class="flex"><span class="flex-1"> </span> <!></h1></div></div> <div class="overflow-scroll flex-1 p-2"><!></div></div></div></div>`);function X(e,i){m(i,!0);let a=()=>{R.sidebarDesktopOpen=!R.sidebarDesktopOpen,R.sidebarDesktopOpen?setTimeout(()=>{R.menuContentVisible=R.sidebarDesktopOpen},200):R.menuContentVisible=R.sidebarDesktopOpen},o=()=>{R.sidebarMobileOpen=!R.sidebarMobileOpen,R.sidebarMobileOpen?setTimeout(()=>{R.menuContentVisible=R.sidebarMobileOpen},200):R.menuContentVisible=R.sidebarMobileOpen},c=()=>{R.menuContentVisible=window.innerWidth<640?R.sidebarMobileOpen:R.sidebarDesktopOpen};w(async()=>{c(),i.data.me?(j.user=i.data.me.user,O(j.user.theme),k(),j.status=`authenticated`):j.status=`unauthenticated`}),d(()=>{j.status==`unauthenticated`&&D(`/login`)});var l=Y();s(`resize`,f,c);var p=r(l);q(r(p),{get spaces(){return P.spaces},get spaceid(){return i.data.spacLine truncated
@@ -1 +1 @@
import{at as e,ft as t,it as n}from"../chunks/39JK5HWF.js";import{t as r}from"../chunks/D3up1JC1.js";import"../chunks/xihTtKlq.js";import"../chunks/B5isPFOt.js";import{t as i}from"../chunks/D8dI9nx6.js";var a=t({load:()=>o}),o=async({parent:e})=>{let{me:t}=await e();return{me:t}};function s(t,a){e(a,!0),r(`/${i.current}/`,{replaceState:!0}),n()}export{s as component,a as universal};
import{at as e,ft as t,it as n}from"../chunks/39JK5HWF.js";import{t as r}from"../chunks/B0qrqti_.js";import"../chunks/xihTtKlq.js";import"../chunks/DL7ZyBAF.js";import{t as i}from"../chunks/D8dI9nx6.js";var a=t({load:()=>o}),o=async({parent:e})=>{let{me:t}=await e();return{me:t}};function s(t,a){e(a,!0),r(`/${i.current}/`,{replaceState:!0}),n()}export{s as component,a as universal};
@@ -1 +0,0 @@
import{B as e,C as t,D as n,E as r,G as i,J as a,K as o,M as s,N as c,O as l,P as u,Q as d,T as f,X as p,_ as m,a as h,at as g,c as _,dt as v,ft as y,it as b,j as x,q as S,tt as C,u as w,ut as T,w as E,x as D,z as O}from"../chunks/39JK5HWF.js";import"../chunks/xihTtKlq.js";import{t as k}from"../chunks/BqkZ0BZ5.js";import{t as A}from"../chunks/D35bQ8xD.js";import{n as j,t as M}from"../chunks/DRdGzrsF.js";import{t as N}from"../chunks/D4uBfDnr.js";var P={getAgents:e=>k.get(`/agent/${e}`),getAgent:(e,t)=>k.get(`/agent/${e}/${t}`),createAgent:(e,t)=>k.post(`/agent/${e}`,t),updateAgent:(e,t)=>k.put(`/agent/${e}`,t),deleteAgent:(e,t)=>k.delete(`/agent/${e}/${t}`)},F=y({load:()=>I}),I=async({params:e})=>({title:`Paramétrage : Agents`,back:`../settings`,space:e.space,agents:await P.getAgents(e.space),providersModels:await A.getProvidersModels(e.space)}),L=l(`<div><div class="formgroup my-2"><form><div class="formelement"><label for="name">Nom</label> <input id="name" type="text" class="textinput" placeholder="nom affiché"/> <!></div> <div class="formelement"><label for="systemPrompt">Prompt système</label> <textarea rows="10" id="systemPrompt" class="areainput" placeholder="prompt système"></textarea> <!></div> <div class="formelement"><label for="type" class="block my-1 flex-1">Type</label> <!> <!></div> <div class="text-right"><button type="button" class="bt">Annuler</button> <button type="submit" class="bt mx-4">Enregistrer</button></div></form></div></div>`);function R(e,t){g(t,!0);let n=h(t,`item`,7),a=d(``),o=e=>e.group,l=e=>{e.focus()},f=e=>{e.preventDefault(),t.onSave(n())},y=e=>{e.preventDefault(),t.onCancel()};var x=L(),E=i(x),D=i(E),k=i(D),A=S(i(k),2);w(A),O(()=>_(A,()=>n().name,e=>n().name=e)),m(A,e=>l?.(e));var j=S(A,2);M(j,{key:`name`,get errors(){return t.errors}}),v(k);var P=S(k,2),F=S(i(P),2);C(F);var I=S(F,2);M(I,{key:`baseUrl`,get errors(){return t.errors}}),v(P);var R=S(P,2),z=S(i(R),2);N(z,{get items(){return t.providersModels},valueMode:`id`,groupBy:o,get value(){return u(a)},set value(e){p(a,e,!0)}});var B=S(z,2);M(B,{key:`type`,get errors(){return t.errors}}),v(R);var V=S(R,2),H=i(V);T(2),v(V),v(D),v(E),v(x),c(`submit`,D,f),s(`change`,D,()=>{t.errors.clear()}),_(F,()=>n().systemPrompt,e=>n().systemPrompt=e),s(`click`,H,y),r(e,x),b()}x([`change`,`click`]);var z=l(`<button class="rounded w-full border border-dashed p-2 border-stone-500 cursor-pointer" tabindex="0"><i class="icon-plus"></i> Ajouter un agent</button>`),B=l(`<div class="rounded border p-2 my-2 border-stone-500 flex"><div class="flex-1"><span> </span></div> <button class="bt small mx-1"><i class="icon-edit"></i></button> <button class="bt small mx-1"><i class="icon-trash-empty"></i></button></div>`),V=l(`<div class="container"><!> <!></div>`);function H(c,l){g(l,!0);let m=d(a(l.data.agents)),h=d(!1),_=d(null),y=d(a({})),x=new j,C=()=>{u(_)||(x.clear(),p(y,{},!0),p(h,!0))},w=()=>{p(h,!1)},T=e=>{e.name||x.set(`name`,`Le nom est obligatoire !`),x.size===0&&P.createAgent(l.data.space,e).then(e=>{u(m).push(e),p(h,!1),p(y,{},!0)}).catch(e=>{console.log(e)})},O=()=>{p(_,null),p(y,{},!0)},k=e=>{e.name||x.set(`name`,`Le nom est obligatoire !`),x.size===0&&P.updateAgent(l.data.space,e).then(e=>{p(m,u(m).map(t=>e.id===t.id?e:t),!0),p(_,null),p(y,{},!0)}).catch(e=>{console.log(e)})},A=async e=>{x.clear(),!u(h)&&P.getAgent(l.data.space,e).then(t=>{p(m,u(m).filter(e=>e.id===t.id?t:e),!0),p(_,e,!0)}).catch(e=>console.log(e))},M=e=>{P.deleteAgent(l.data.space,e).then(()=>{p(m,u(m).filter(t=>t.id!==e),!0)}).catch(e=>{console.log(e)})};var N=V(),F=i(N),I=e=>{var i=n(),a=o(i);t(a,()=>`new`,e=>{R(e,{get item(){return u(y)},get errors(){return x},onSave:T,onCancel:w,get providersModels(){return l.data.providersModels}})}),r(e,i)},L=e=>{var t=z();s(`click`,t,C),r(e,t)};E(F,e=>{u(h)?e(I):e(L,-1)});var H=S(F,2);D(H,17,()=>u(m),e=>e.id,(a,c)=>{var d=n(),p=o(d),m=e=>{var i=n(),a=o(i);t(a,()=>u(c).id,e=>{R(e,{get item(){return u(c)},get errors(){return x},onSave:k,onCancel:O,get providersModels(){return l.data.providersModels}})}),r(e,i)},h=t=>{var n=B(),a=i(n),o=i(a),l=i(o,!0);v(o),v(a);var d=S(a,2),p=S(d,2);v(n),e(()=>f(l,u(c).name)),s(`click`,d,()=>A(u(c).id)),s(`click`,p,()=>M(u(c).id)),r(t,n)};E(p,e=>{u(_)===u(c).id?e(m):e(h,-1)}),r(a,d)}),v(N),r(c,N),b()}x([`click`]);export{H as component,F as universal};
@@ -0,0 +1 @@
import{B as e,C as t,D as n,E as r,G as i,J as a,K as o,L as s,M as c,N as l,O as u,P as d,Q as f,T as p,X as m,_ as h,a as g,at as _,c as v,dt as y,ft as b,h as x,it as S,j as C,q as w,tt as T,u as E,ut as D,w as O,x as k,z as A}from"../chunks/39JK5HWF.js";import"../chunks/xihTtKlq.js";import{t as j}from"../chunks/BC84wEQu.js";import{t as M}from"../chunks/D8dI9nx6.js";import{t as N}from"../chunks/DOY2HMbt.js";import{n as P,t as F}from"../chunks/DRdGzrsF.js";import{t as I}from"../chunks/BorM6hBh.js";var L={getAgents:e=>j.get(`/agent/${e}`),getAgent:(e,t)=>j.get(`/agent/${e}/${t}`),createAgent:(e,t)=>j.post(`/agent/${e}`,t),updateAgent:(e,t)=>j.put(`/agent/${e}`,t),deleteAgent:(e,t)=>j.delete(`/agent/${e}/${t}`)},R={getSpace:e=>j.get(`/team/${e}`),updateSpace:(e,t)=>j.put(`/team/${e}`,t)},z=b({load:()=>B}),B=async({params:e})=>({title:`Paramétrage : Agents`,back:`../settings`,space:await R.getSpace(e.space),agents:await L.getAgents(e.space),providersModels:await N.getProvidersModels(e.space)}),V=u(`<div><div class="formgroup my-2"><form><div class="formelement"><label for="name">Nom</label> <input id="name" type="text" class="textinput" placeholder="nom affiché"/> <!></div> <div class="formelement"><label for="systemPrompt">Prompt système</label> <textarea rows="10" id="systemPrompt" class="areainput" placeholder="prompt système"></textarea> <!></div> <div class="formelement"><label for="type" class="block my-1 flex-1">Type</label> <!> <!></div> <div class="text-right"><button type="button" class="bt">Annuler</button> <button type="submit" class="bt mx-4">Enregistrer</button></div></form></div></div>`);function H(e,t){_(t,!0);let n=g(t,`item`,7),o=f(a(s(()=>n().defaultProviderId+`|`+n().defaultModelId))),u=e=>e.group,p=e=>{e.focus()},b=e=>{e.preventDefault();let r=d(o).split(`|`);d(o).length>1?(n().defaultProviderId=r[0],n().defaultModelId=r[1]):(n().defaultProviderId=``,n().defaultModelId=``),t.onSave(n())},x=e=>{e.preventDefault(),t.onCancel()};var C=V(),O=i(C),k=i(O),j=i(k),M=w(i(j),2);E(M),A(()=>v(M,()=>n().name,e=>n().name=e)),h(M,e=>p?.(e));var N=w(M,2);F(N,{key:`name`,get errors(){return t.errors}}),y(j);var P=w(j,2),L=w(i(P),2);T(L);var R=w(L,2);F(R,{key:`baseUrl`,get errors(){return t.errors}}),y(P);var z=w(P,2),B=w(i(z),2);I(B,{get items(){return t.providersModels},valueMode:`id`,groupBy:u,get value(){return d(o)},set value(e){m(o,e,!0)}});var H=w(B,2);F(H,{key:`model`,get errors(){return t.errors}}),y(z);var U=w(z,2),W=i(U);D(2),y(U),y(k),y(O),y(C),l(`submit`,k,b),c(`change`,k,()=>{t.errors.clear()}),v(L,()=>n().systemPrompt,e=>n().systemPrompt=e),c(`click`,W,x),r(e,C),S()}C([`change`,`click`]);var U=u(`<button class="rounded w-full border border-dashed p-2 border-stone-500 cursor-pointer" tabindex="0"><i class="icon-plus"></i> Ajouter un agent</button>`),W=u(`<div class="rounded border p-2 my-2 border-stone-500 flex"><div class="flex-1"><span> </span></div> <button title="Modifier">Agent par défaut</button> <button class="bt small mx-1" title="Modifier"><i class="icon-edit"></i></button> <button class="bt small mx-1" title="Supprimer"><i class="icon-trash-empty"></i></button></div>`),G=u(`<div class="container"><!> <!></div>`);function K(l,u){_(u,!0);let h=f(a(s(()=>u.data.space))),g=f(a(s(()=>u.data.agents))),v=f(!1),b=f(null),C=f(a({})),T=new P,E=()=>{d(b)||(T.clear(),m(C,{},!0),m(v,!0))},D=()=>{m(v,!1)},A=e=>{e.name||T.set(`name`,`Le nom est obligatoire !`),(e.defaultProviderId===``||e.defaultModelId===``)&&T.set(`model`,`Le modèle est obligatoire !`),T.size===0&&L.createAgent(u.data.space.id,e).then(e=>{d(g).push(e),m(v,!1),m(C,{},!0)}).catch(e=>{console.log(e)})},j=()=>{m(b,null),m(C,{},!0)},N=e=>{e.name||T.set(`name`,`Le nom est obligatoire !`),T.size===0&&L.updateAgent(u.data.space.id,e).then(e=>{m(g,d(g).map(t=>e.id===t.id?e:t),!0),m(b,null),m(C,{},!0)}).catch(e=>{console.log(e)})},F=async e=>{T.clear(),!d(v)&&L.getAgent(u.data.space.id,e).then(t=>{m(g,d(g).filter(e=>e.id===t.id?t:e),!0),m(b,e,!0)}).catch(e=>console.log(e))},I=e=>{L.deleteAgent(u.data.space.id,e).then(()=>{m(g,d(g).filter(t=>t.id!==e),!0)}).catch(e=>{console.log(e)})},z=e=>{let t=d(h);t.defaultAgentId=e,R.updateSpace(t.id,t).then(e=>{M.spaces.map(t=>t.id===M.current?e:t),m(h,e,!0)}).catch(e=>{console.log(e)})};var B=G(),V=i(B),K=e=>{var i=n(),a=o(i);t(a,()=>`new`,e=>{H(e,{get item(){return d(C)},get errors(){return T},onSave:A,onCancel:D,get providersModels(){return u.data.providersModels}})}),r(e,i)},q=e=>{var t=U();c(`click`,t,E),r(e,t)};O(V,e=>{d(v)?e(K):e(q,-1)});var J=w(V,2);k(J,17,()=>d(g),e=>e.id,(a,s)=>{var l=n(),f=o(l),m=e=>{var i=n(),a=o(i);t(a,()=>d(s).id,e=>{H(e,{get item(){return d(s)},get errors(){return T},onSave:N,onCancel:j,get providersModels(){return u.data.providersModels}})}),r(e,i)},g=t=>{var n=W(),a=i(n),o=i(a),l=i(o,!0);y(o),y(a);var u=w(a,2);let f;var m=w(u,2),g=w(m,2);y(n),e(()=>{p(l,d(s).name),f=x(u,1,`bt small mx-1`,null,f,{highlight:d(s).id===d(h).defaultAgentId})}),c(`click`,u,()=>z(dLine truncated
+1 -1
View File
@@ -1 +1 @@
{"version":"1788613178637"}
{"version":"1788815336322"}
+8 -8
View File
@@ -4,29 +4,29 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="text-scale" content="scale" />
<link href="/_app/immutable/entry/start.Bxa_xdGb.js" rel="modulepreload">
<link href="/_app/immutable/chunks/D3up1JC1.js" rel="modulepreload">
<link href="/_app/immutable/entry/start.wXD-FaGY.js" rel="modulepreload">
<link href="/_app/immutable/chunks/B0qrqti_.js" rel="modulepreload">
<link href="/_app/immutable/chunks/39JK5HWF.js" rel="modulepreload">
<link href="/_app/immutable/entry/app.DHv_tZ2J.js" rel="modulepreload">
<link href="/_app/immutable/entry/app.DteMb5qC.js" rel="modulepreload">
<link href="/_app/immutable/chunks/xihTtKlq.js" rel="modulepreload">
<link href="/_app/immutable/nodes/0.DNLpy_rd.js" rel="modulepreload">
<link href="/_app/immutable/nodes/0.WTbeuaG5.js" rel="modulepreload">
<link href="/_app/immutable/chunks/DTCALkcP.js" rel="modulepreload">
<link href="/_app/immutable/assets/0.Bdga2HVs.css" rel="stylesheet">
<link href="/_app/immutable/assets/0.PdzDvXHc.css" rel="stylesheet">
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">
<script>
{
__sveltekit_1oispqz = {
__sveltekit_1vzpa2i = {
base: ""
};
const element = document.currentScript.parentElement;
Promise.all([
import("/_app/immutable/entry/start.Bxa_xdGb.js"),
import("/_app/immutable/entry/app.DHv_tZ2J.js")
import("/_app/immutable/entry/start.wXD-FaGY.js"),
import("/_app/immutable/entry/app.DteMb5qC.js")
]).then(([kit, app]) => {
kit.start(app, element);
});
-5
View File
@@ -1,5 +0,0 @@
package llmserver
type Session struct {
server string
}
+246
View File
@@ -0,0 +1,246 @@
package chat
import (
"context"
"fmt"
"log/slog"
"sync"
"time"
"trankilou.fr/lassistanoque/backend/internal/domain"
)
type Service struct {
repoUser domain.UserRepository
repoAgent domain.AgentRepository
repoProvider domain.ProviderRepository
repoChat domain.ChatRepository
llmEngine domain.LLMEngine
runningSessions map[string]*ChatSession
mu sync.Mutex
}
func NewService(
repoUser domain.UserRepository,
repoAgent domain.AgentRepository,
repoProvider domain.ProviderRepository,
repoChat domain.ChatRepository,
llmEngine domain.LLMEngine,
) *Service {
return &Service{
repoUser: repoUser,
repoAgent: repoAgent,
repoProvider: repoProvider,
repoChat: repoChat,
llmEngine: llmEngine,
runningSessions: make(map[string]*ChatSession),
}
}
func (s *Service) NewChat(
userID string,
teamID string,
agentID string,
) (*domain.Chat, error) {
team, err := s.repoUser.FindTeam(userID, teamID)
if err != nil {
return nil, err
}
start := time.Now()
chat := &domain.Chat{
UserID: userID,
AgentID: agentID,
TeamID: team.ID,
StartDatetime: &start,
Title: "Nouvelle conversation",
}
chat, err = s.repoChat.CreateChat(userID, chat)
if err != nil {
return nil, err
}
return chat, nil
}
func (s *Service) AddChatMessage(
ctx context.Context,
userID string,
teamID string,
chatID string,
agentID string,
prompt string,
params *domain.ChatParams,
) (*domain.Message, error) {
team, err := s.repoUser.FindTeam(userID, teamID)
if err != nil {
return nil, err
}
var chatAgentID string
if team.DefaultAgentID != nil {
chatAgentID = *team.DefaultAgentID
} else if agentID != "" {
chatAgentID = agentID
} else {
return nil, fmt.Errorf("no agent defined")
}
agent, err := s.repoAgent.GetAgent(userID, team.ID, chatAgentID)
if err != nil {
return nil, err
}
chatProviderID := agent.DefaultProviderID
chatModelID := agent.DefaultModelID
if params != nil && params.ProviderID != "" {
chatProviderID = params.ProviderID
}
if params != nil && params.ModelID != "" {
chatModelID = params.ModelID
}
provider, err := s.repoProvider.GetProvider(userID, teamID, chatProviderID)
if err != nil {
return nil, err
}
message, err := s.repoChat.CreateChatMessage(userID, &domain.Message{
ChatID: chatID,
TeamID: teamID,
Role: string(domain.RoleUser),
Content: prompt,
})
if err != nil {
return nil, err
}
messages, err := s.repoChat.GetChatMessages(userID, teamID, chatID)
if err != nil {
return nil, err
}
var cb domain.StreamCallback
if params != nil && params.OnChunk != nil {
cb = params.OnChunk
}
s.runQuery(
ctx,
userID,
teamID,
chatID,
agent,
provider,
chatModelID,
messages,
cb,
)
return message, nil
}
func (s *Service) ListChats(userID string, teamID string, page int) ([]*domain.Chat, error) {
return s.repoChat.ListChats(userID, teamID, page)
}
func (s *Service) GetChat(userID string, teamID, chatID string) (*domain.Chat, error) {
return s.repoChat.GetChat(userID, teamID, chatID)
}
func (s *Service) GetChatWithMessages(userID string, teamID, chatID string) (*domain.ChatWithMessages, error) {
chat, err := s.repoChat.GetChat(userID, teamID, chatID)
if err != nil {
return nil, err
}
messages, err := s.repoChat.GetChatMessages(userID, teamID, chatID)
if err != nil {
return nil, err
}
return &domain.ChatWithMessages{
Chat: chat,
Messages: messages,
}, nil
}
func (s *Service) DeleteChat(userID string, teamID, chatID string) error {
return s.repoChat.DeleteChat(userID, teamID, chatID)
}
func (s *Service) runQuery(
ctx context.Context,
userID string,
teamID string,
chatID string,
agent *domain.Agent,
provider *domain.Provider,
modelID string,
messages []*domain.Message,
callback domain.StreamCallback,
) error {
chatSession := &ChatSession{
userID: userID,
teamID: teamID,
chatID: chatID,
agent: agent,
provider: provider,
modelID: modelID,
messages: messages,
llmEngine: s.llmEngine,
subscribers: make([]domain.StreamCallback, 0),
repoChat: s.repoChat,
}
if callback != nil {
chatSession.subscribers = append(chatSession.subscribers, callback)
}
s.mu.Lock()
s.runningSessions[chatID] = chatSession
s.mu.Unlock()
go func() {
_, err := chatSession.run(ctx)
if err != nil {
slog.Info("chat session error", "error", err)
}
delete(s.runningSessions, chatID)
}()
return nil
}
func (s *Service) Subscribe(
userID string,
teamID string,
chatID string,
callback domain.StreamCallback,
) error {
team, err := s.repoUser.FindTeam(userID, teamID)
if err != nil {
return err
}
_, err = s.repoChat.GetChat(userID, team.ID, chatID)
if err != nil {
return err
}
s.mu.Lock()
if chat, ok := s.runningSessions[chatID]; ok {
chat.subscribers = append(chat.subscribers, callback)
}
s.mu.Unlock()
return nil
}
+52
View File
@@ -0,0 +1,52 @@
package chat
import (
"context"
"sync"
"trankilou.fr/lassistanoque/backend/internal/domain"
)
type ChatSession struct {
userID string
teamID string
chatID string
agent *domain.Agent
provider *domain.Provider
modelID string
messages []*domain.Message
llmEngine domain.LLMEngine
repoChat domain.ChatRepository
subscribers []domain.StreamCallback
mu sync.Mutex
}
func (s *ChatSession) run(ctx context.Context) (*domain.Message, error) {
params := &domain.LLMParams{}
s.mu.Lock()
if len(s.subscribers) > 0 {
params.OnChunk = func(chunk *domain.Chunk) {
for _, cb := range s.subscribers {
cb(chunk)
}
}
}
s.mu.Unlock()
msg, err := s.llmEngine.Stream(
ctx,
s.provider,
s.modelID,
params,
s.messages,
)
if err != nil {
return nil, err
}
msg.ChatID = s.chatID
msg.TeamID = s.teamID
return s.repoChat.CreateChatMessage(s.userID, msg)
}
Binary file not shown.
+165
View File
@@ -8,6 +8,7 @@
"name": "web",
"version": "0.0.1",
"dependencies": {
"@humanspeak/svelte-markdown": "^1.9.2",
"oidc-client-ts": "^3.5.0",
"svelte-select": "^6.0.0"
},
@@ -262,6 +263,51 @@
"node": ">=18.18.0"
}
},
"node_modules/@humanspeak/memory-cache": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@humanspeak/memory-cache/-/memory-cache-1.2.0.tgz",
"integrity": "sha512-im7GIIpgjdD6Fx68xCeiXw3XiDv30/WMRAaodMm+ep0ptYfEUd0cdNeTAylHGIRTJIeByKFHdTmPjAktyDM/JQ==",
"license": "MIT",
"engines": {
"node": ">=20.19.0"
}
},
"node_modules/@humanspeak/svelte-markdown": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@humanspeak/svelte-markdown/-/svelte-markdown-1.9.2.tgz",
"integrity": "sha512-sczMB4oNSpADBWT6l9AkIErpJDDzGsamzl2/w3J5yAYBWWofLcmVDCti5KY5l0+Cec2p9xyb73qkkukoNmLPWQ==",
"license": "MIT",
"dependencies": {
"@humanspeak/memory-cache": "^1.1.2",
"github-slugger": "^2.0.0",
"htmlparser2": "^12.0.0",
"marked": "^18.0.9"
},
"engines": {
"node": ">=22"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/humanspeak"
},
"peerDependencies": {
"katex": ">=0.16.0",
"mermaid": ">=10.0.0",
"shiki": ">=4.0.0",
"svelte": "^5.0.0"
},
"peerDependenciesMeta": {
"katex": {
"optional": true
},
"mermaid": {
"optional": true
},
"shiki": {
"optional": true
}
}
},
"node_modules/@humanwhocodes/module-importer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
@@ -1722,6 +1768,73 @@
"integrity": "sha512-RWrqdArjvPbsATEhOPUo6Wndc/iWnkWKlhIrdlF3zMMYo/c3CVtoaVAyLtWxz5h8nSlkHzxnzV2uLydPXmtF+A==",
"license": "MIT"
},
"node_modules/dom-serializer": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-3.1.1.tgz",
"integrity": "sha512-4MEa38/QexBob6gFNwu+EGdWvhJ1OKuNwdYY3Y3NyeWDQfnGeDYQUDfIRzWu5B5gsv03so2Uxd28YC6zrsx3Lw==",
"license": "MIT",
"dependencies": {
"domelementtype": "^3.0.0",
"domhandler": "^6.0.0",
"entities": "^8.0.0"
},
"engines": {
"node": ">=20.19.0"
},
"funding": {
"type": "github",
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/domelementtype": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-3.0.0.tgz",
"integrity": "sha512-umCQid3jKbDmVjx8jGaW7uUykm4DEUeyV21hPxNMo2nV955DhUThwqyOIDtreepP31hl84X7G5U9ZfsWvIB3Pg==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"license": "BSD-2-Clause",
"engines": {
"node": ">=20.19.0"
}
},
"node_modules/domhandler": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-6.0.1.tgz",
"integrity": "sha512-gYzvtM72ZtxQO0T048kd6HWSbbGCNOUwcnfQ01cqIJ4X2IYKFFHZ5mKvrQETcFXxsRObZulDaKmy//R7TPtsBg==",
"license": "BSD-2-Clause",
"dependencies": {
"domelementtype": "^3.0.0"
},
"engines": {
"node": ">=20.19.0"
},
"funding": {
"type": "github",
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/domutils": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-4.0.2.tgz",
"integrity": "sha512-qI4JLRKnSzqFqr7hAlS5xQDusBCjKSEG4t4+7aNrIQMHBcsC2TGEhuyABJdYkgSewL57PNLYEiibY2iPKhKpaA==",
"license": "BSD-2-Clause",
"dependencies": {
"dom-serializer": "^3.0.0",
"domelementtype": "^3.0.0",
"domhandler": "^6.0.0"
},
"engines": {
"node": ">=20.19.0"
},
"funding": {
"type": "github",
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/enhanced-resolve": {
"version": "5.24.5",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz",
@@ -1736,6 +1849,18 @@
"node": ">=10.13.0"
}
},
"node_modules/entities": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-8.1.0.tgz",
"integrity": "sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=20.19.0"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -2095,6 +2220,12 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/github-slugger": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz",
"integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==",
"license": "ISC"
},
"node_modules/glob-parent": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@@ -2128,6 +2259,28 @@
"dev": true,
"license": "ISC"
},
"node_modules/htmlparser2": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-12.0.0.tgz",
"integrity": "sha512-Tz7u1i95/g2x2jz81+x0FBVhBhY5aRTvD3tXXdFaljuNdzDLJ8UGNRrTcj2cgQvAg3iW/h77Fz15nLW0L0CrZw==",
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"license": "MIT",
"dependencies": {
"domelementtype": "^3.0.0",
"domhandler": "^6.0.0",
"domutils": "^4.0.2",
"entities": "^8.0.0"
},
"engines": {
"node": ">=20.19.0"
}
},
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -2632,6 +2785,18 @@
"@jridgewell/sourcemap-codec": "^1.5.5"
}
},
"node_modules/marked": {
"version": "18.0.14",
"resolved": "https://registry.npmjs.org/marked/-/marked-18.0.14.tgz",
"integrity": "sha512-mBHK6FBHuBAlhgRe88w9F0O1AbwwXJUcQibUbC/QcdTbVGAD7aWza+xt3N6oT/jCZx3/OMeS+8rnuiHZcQ9s7A==",
"license": "MIT",
"bin": {
"marked": "bin/marked.js"
},
"engines": {
"node": ">= 20"
}
},
"node_modules/mini-svg-data-uri": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
+1
View File
@@ -48,6 +48,7 @@
"esbuild": "^0.25.0"
},
"dependencies": {
"@humanspeak/svelte-markdown": "^1.9.2",
"oidc-client-ts": "^3.5.0",
"svelte-select": "^6.0.0"
}
+62
View File
@@ -48,15 +48,77 @@ async function request<T>(path: string, options: RequestOptions = {}): Promise<T
return res.json();
}
async function* requestStream<T = unknown>(
path: string,
options: RequestOptions = {}
): AsyncGenerator<T, void, undefined> {
const { auth = true, headers, ...rest } = options;
const requestHeaders: HeadersInit = {
'Content-Type': 'application/json',
...headers,
};
const fetchHeaders = new Headers(requestHeaders)
if (auth) {
const token = getToken()
if (token) {
fetchHeaders.append('Authorization', `Bearer ${token}`)
}
}
const res = await fetch(`${BASE_URL}${path}`, {
...rest,
headers: fetchHeaders,
});
if (res.status === 401 ) {
logout()
goto("/login")
//throw new ApiError(401, await safeJson(res));
}
if (!res.ok || !res.body) throw new Error(`HTTP ${res.status}`);
const reader = res.body!.pipeThrough(new TextDecoderStream()).getReader();
let buffer = '';
try {
while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += value;
const lines = buffer.split('\n');
buffer = lines.pop() ?? ''; // dernière ligne potentiellement incomplète
for (const line of lines) {
if (line.trim()) yield JSON.parse(line) as T;
}
}
if (buffer.trim()) yield JSON.parse(buffer) as T; // reste éventuel
} finally {
reader.releaseLock();
}
return //res.json();
}
async function safeJson(res: Response) {
try { return await res.json(); } catch { return null; }
}
export const api = {
get: <T>(path: string, opts?: RequestOptions) => request<T>(path, { ...opts, method: 'GET' }),
post: <T>(path: string, body?: unknown, opts?: RequestOptions) =>
request<T>(path, { ...opts, method: 'POST', body: JSON.stringify(body) }),
postStream: <T>(path: string, body?: unknown, opts?: RequestOptions) =>
requestStream<T>(path, {...opts, method: 'POST', body: JSON.stringify(body) }),
put: <T>(path: string, body?: unknown, opts?: RequestOptions) =>
request<T>(path, { ...opts, method: 'PUT', body: JSON.stringify(body) }),
delete: <T>(path: string, opts?: RequestOptions) => request<T>(path, { ...opts, method: 'DELETE' }),
};
+11
View File
@@ -0,0 +1,11 @@
import { api } from '../client';
import type { Chat, Chunk, ChatRequest, ChatWithMessages } from "$lib/types/api"
export const chatApi = {
createChat: (space: string, data: Partial<ChatRequest>) => api.post<Chat>(`/chat/${space}`, data),
createChatMessage: (space: string, id: string, data: Partial<ChatRequest>) => api.postStream<Chunk>(`/chat/${space}/${id}`, data),
allChats: (space: string, pageNum: number) => api.get<Chat[]>(`/chat/${space}/all/${pageNum}`),
getChat: (space: string, id: string) => api.get<ChatWithMessages>(`/chat/${space}/${id}`),
subscribe: (space: string, id: string) => api.get<ChatWithMessages>(`/chat/${space}/${id}/subscribe`),
deleteChat: (space: string, id: string) => api.delete(`/chat/${space}/${id}`),
};
+4 -2
View File
@@ -5,8 +5,10 @@
const closeDrawer = (e: Event) => {
e.preventDefault()
uiState.sidebarMobileOpen=false
uiState.menuContentVisible=false
if (uiState.sidebarMobileOpen) {
uiState.sidebarMobileOpen=false
uiState.menuContentVisible=false
}
goto(link)
}
</script>
+50
View File
@@ -78,6 +78,49 @@ export interface Agent {
_version: string
}
export type Chat = {
id: string
teamId: string
startDatetime: string
endDatetime: string
agentId: string
userId: string
taskId: string
title: string
_date_created: string
_date_updated: string
_version: string
}
export type Message = {
id: string
role: string
content: string
toolCallId: string
toolCalls: Array<string>
_date_created: string
_date_updated: string
_version: string
}
export type ChatWithMessages = {
chat: Chat
messages: Message[]
}
export type Chunk = {
done: boolean
role: string
content: string
}
export type ChatRequest = {
agentId: string
providerId: string
modelId: string
prompt: string
}
export enum SaveState {
None,
@@ -86,3 +129,10 @@ export enum SaveState {
Saved,
Error,
}
export type PageRequest = {
pageNum: number
pageSize: number
filters: Map<string, string>
}
+3
View File
@@ -0,0 +1,3 @@
export const autofocus = (node: HTMLElement) => {
node.focus();
}
@@ -1,8 +1,35 @@
<div class="container">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Asperiores, reiciendis quo. Quos animi nisi modi cumque hic illo doloremque totam! Distinctio molestias sint magnam illum nostrum eos, fugit aliquid consequuntur?
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Asperiores, reiciendis quo. Quos animi nisi modi cumque hic illo doloremque totam! Distinctio molestias sint magnam illum nostrum eos, fugit aliquid consequuntur?
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Asperiores, reiciendis quo. Quos animi nisi modi cumque hic illo doloremque totam! Distinctio molestias sint magnam illum nostrum eos, fugit aliquid consequuntur?
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Asperiores, reiciendis quo. Quos animi nisi modi cumque hic illo doloremque totam! Distinctio molestias sint magnam illum nostrum eos, fugit aliquid consequuntur?
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Asperiores, reiciendis quo. Quos animi nisi modi cumque hic illo doloremque totam! Distinctio molestias sint magnam illum nostrum eos, fugit aliquid consequuntur?
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Asperiores, reiciendis quo. Quos animi nisi modi cumque hic illo doloremque totam! Distinctio molestias sint magnam illum nostrum eos, fugit aliquid consequuntur?
<script lang="ts">
import {autofocus} from "$lib/ui/autofocus"
import {chatApi} from "$lib/api/endpoints/chat"
import type {Chat} from "$lib/types/api"
import type { PageProps } from './$types';
import { goto } from "$app/navigation";
let { data }: PageProps = $props();
let chat = $state({} as Chat)
let prompt = $state("")
const handleOnSubmit = async () => {
chatApi.createChat(data.spaceId, chat)
.then((result)=>{
goto(`/${data.spaceId}/${result.id}`, {state: {prompt: prompt }})
}).catch((err)=>console.log(err))
}
</script>
<div class="h-full w-full flex items-center public">
<div class="container">
<form class="request flex w-full" onsubmit={handleOnSubmit}>
<input
class="chatinput w-full flex-1 focus:outline-hidden focus:shadow-none focus:ring-0"
type="text"
placeholder="Demande ce que tu veux"
bind:value={prompt}
use:autofocus
/>
<button class="chatbutton">Go</button>
</form>
</div>
</div>
@@ -1,3 +1,8 @@
export function load() {
return { title: 'Conversation' };
import type { PageLoad } from "./$types";
export const load: PageLoad = ({params}) => {
return {
title: 'Nouvelle conversation',
spaceId : params.space,
};
}
@@ -0,0 +1,75 @@
<script lang="ts">
import {autofocus} from "$lib/ui/autofocus"
import { onMount } from "svelte"
import {page} from "$app/state"
import {chatApi} from "$lib/api/endpoints/chat"
import type { PageProps } from './$types';
import type { Message, Chunk } from "$lib/types/api"
import SvelteMarkdown from '@humanspeak/svelte-markdown'
let prompt = $state("")
let { data }: PageProps = $props();
let messages = $state([] as Message[])
onMount(async ()=>{
if (page.state.prompt) {
console.log(page.state.prompt)
await sendRequest(page.state.prompt)
}
})
let historyDiv: HTMLDivElement;
$effect(() => {
if (historyDiv) {
console.log("effect")
historyDiv.scrollTop = historyDiv.scrollHeight;
}
});
const sendRequest = async(theprompt) => {
prompt = ""
let lastrole=""
for await (const chunk of chatApi.createChatMessage(data.spaceId, data.chatId, { prompt: theprompt })) {
if (chunk.role!=lastrole) {
const currentDate = new Date()
messages.push({
id: currentDate.getTime(),
role: chunk.role,
content: chunk.content,
})
lastrole=chunk.role
} else {
messages[messages.length-1].content += chunk.content
}
historyDiv.scrollTop = historyDiv.scrollHeight;
}
}
const handleOnSubmit = async ()=>{
await sendRequest(prompt)
}
</script>
<div class="h-full w-full flex flex-col">
<div id="history" class="flex-1 container overflow-auto" bind:this={historyDiv}>
{#each messages as message (message.id)}
<div class={["message", "rounded", message.role]}>
<div class="message-content">
<SvelteMarkdown source={message.content} />
</div>
</div>
{/each}
</div>
<div id="prompt" class="container">
<form class="request flex w-full" onsubmit={handleOnSubmit}>
<input
class="chatinput w-full flex-1 focus:outline-hidden focus:shadow-none focus:ring-0"
type="text"
placeholder="..."
bind:value={prompt}
use:autofocus
/>
<button class="chatbutton">Go</button>
</form>
</div>
</div>
@@ -0,0 +1,9 @@
import type { PageLoad } from "./$types";
export const load: PageLoad = ({params}) => {
return {
title: 'Nouvelle conversation',
spaceId: params.space,
chatId: params.conversation,
};
}
@@ -100,7 +100,6 @@
let updSpace = space
updSpace.defaultAgentId = agentId
teamApi.updateSpace(updSpace.id, updSpace).then((newdata)=>{
console.log(newdata)
spaceState.spaces.map((s)=>s.id===spaceState.current?newdata:s)
space=newdata
}).catch((err)=>{
@@ -3,6 +3,7 @@
import { auth, setToken } from '$lib/state/auth.svelte';
import { goto } from '$app/navigation';
import { authApi } from "$lib/api/endpoints/auth"
import { validateEmail } from "$lib/utilities/validators"
type Credentials = {
email: string
@@ -17,7 +18,7 @@
})
const formSubmitEmail = () => {
credentials.validemail = true
credentials.validemail = validateEmail(credentials.email)
}
const formSubmitPass = (e: Event) => {
@@ -43,16 +44,16 @@
<form onsubmit={formSubmitEmail}>
<div class="flex">
<label for="email" class="block mb-2 flex-1">Email</label>
<a href="/recover-password" class="text-xs">Mot de passe oublié ?</a>
<a href="/recover-password" class="text-xs ">Mot de passe oublié ?</a>
</div>
<div class="flex flex-row">
<input
type="text"
bind:value={credentials.email}
class="textinput mr-1"
class="textinput mr-1 flex-1"
autofocus
/>
<button class="bt" title="page suivante">
<button class="bt small" title="page suivante">
<i class="icon-right-big"></i>
</button>
</div>
@@ -72,10 +73,10 @@
<input
type="password"
bind:value={credentials.password}
class="textinput mr-1"
class="textinput mr-1 flex-1"
autofocus
/>
<button class="bt">
<button class="bt small">
Entrer
</button>
</div>
+46 -8
View File
@@ -11,7 +11,7 @@ body {
@apply h-full bg-stone-100 text-stone-950 dark:bg-stone-950 dark:text-stone-100;
}
.formelement > label {
label {
@apply text-xs text-stone-600 uppercase dark:text-stone-400;
}
hr {
@@ -30,9 +30,9 @@ h2 {
}
.bt {
appearance: button;
@apply min-w-40 cursor-pointer rounded bg-stone-300 px-4 py-1 transition-all duration-300 hover:bg-stone-200 dark:bg-stone-800 dark:hover:bg-stone-700;
@apply min-w-40 cursor-pointer rounded bg-stone-300 px-4 py-1 transition-all duration-300 hover:bg-stone-400 dark:bg-stone-800 dark:hover:bg-stone-700;
&.small {
@apply min-w-0 px-2 py-1;
@apply min-w-2 px-2 py-1;
}
&.changed,
&.saving {
@@ -62,10 +62,12 @@ h2 {
.public h1 {
@apply mb-4 text-3xl font-bold;
}
.profile a,
.public a {
.profile a {
@apply bg-sky-300 dark:bg-sky-700;
}
.public a {
@apply text-sky-500 dark:text-sky-500;
}
#outer {
@apply flex h-full flex-row;
@@ -113,10 +115,18 @@ h2 {
}
}
.chatinput {
@apply w-full rounded-l-xl border-stone-300 bg-stone-50 p-2 text-stone-900 dark:border-stone-700 dark:bg-stone-900 dark:text-stone-100;
}
.chatbutton {
@apply min-w-12 cursor-pointer rounded-r-xl bg-stone-300 px-2 py-1 transition-all duration-300 hover:bg-stone-400 dark:bg-stone-700 dark:hover:bg-stone-600;
}
/* form */
.formgroup {
@apply rounded border border-stone-300 bg-stone-100 p-2 text-sm dark:border-stone-700 dark:bg-stone-900;
@apply rounded border border-stone-300 bg-stone-200 p-2 text-sm dark:border-stone-700 dark:bg-stone-900;
}
.formelement {
@@ -124,11 +134,11 @@ h2 {
}
.textinput {
@apply h-8 w-full rounded border-stone-700 bg-stone-50 px-2 py-1 text-sm text-stone-900 dark:bg-stone-950 dark:text-stone-100;
@apply h-8 w-full rounded border-stone-300 bg-stone-50 px-2 py-1 text-sm text-stone-900 dark:border-stone-700 dark:bg-stone-950 dark:text-stone-100;
}
.areainput {
@apply w-full rounded border-stone-700 bg-stone-50 px-2 py-1 text-sm text-stone-900 dark:bg-stone-950 dark:text-stone-100;
@apply w-full rounded border-stone-300 bg-stone-50 px-2 py-1 text-sm text-stone-900 dark:bg-stone-950 dark:text-stone-100;
}
/* svelte select */
@@ -261,3 +271,31 @@ h2 {
.list-item {
@apply list-none;
}
/* chat */
.message {
@apply m-2 rounded p-2;
&.user {
@apply bg-sky-500 dark:text-white;
}
&.assistant {
&.reasoning {
@apply text-white/50;
}
}
}
.message-content {
@apply text-sm;
}
.message-content p {
@apply my-2;
}
.message-content pre {
@apply my-2 whitespace-pre dark:bg-stone-700;
}
+10
View File
@@ -0,0 +1,10 @@
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./src/**/*.{html,js,svelte,ts}",
],
theme: {
extend: {},
},
plugins: [],
}