zaturn 0.2.2__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zaturn/studio/agent_wrapper.py +36 -112
- zaturn/studio/app.py +48 -41
- zaturn/studio/storage.py +14 -4
- zaturn/studio/templates/_shell.html +3 -3
- zaturn/studio/templates/ai_message.html +1 -2
- zaturn/studio/templates/c_source_card.html +3 -3
- zaturn/studio/templates/chat.html +27 -19
- zaturn/studio/templates/chat_metadata.html +10 -0
- zaturn/studio/templates/css/style.css +146 -21
- zaturn/studio/templates/function_call.html +5 -4
- zaturn/studio/templates/icons/arrow-left.svg +3 -0
- zaturn/studio/templates/icons/arrow-right.svg +3 -0
- zaturn/studio/templates/icons/chat-bubble.svg +6 -0
- zaturn/studio/templates/icons/check-circle-solid.svg +3 -0
- zaturn/studio/templates/icons/database.svg +5 -0
- zaturn/studio/templates/icons/fire-flame.svg +4 -0
- zaturn/studio/templates/icons/floppy-disk.svg +5 -0
- zaturn/studio/templates/icons/link.svg +4 -0
- zaturn/studio/templates/icons/play.svg +3 -0
- zaturn/studio/templates/icons/settings.svg +4 -0
- zaturn/studio/templates/icons/timer.svg +5 -0
- zaturn/studio/templates/icons/trash.svg +4 -0
- zaturn/studio/templates/icons/upload.svg +4 -0
- zaturn/studio/templates/icons/user.svg +4 -0
- zaturn/studio/templates/icons/warning-triangle.svg +5 -0
- zaturn/studio/templates/icons/wrench.svg +4 -0
- zaturn/studio/templates/loader.html +1 -1
- zaturn/studio/templates/manage_sources.html +5 -5
- zaturn/studio/templates/new_conversation.html +2 -2
- zaturn/studio/templates/settings.html +24 -3
- zaturn/studio/templates/setup_prompt.html +3 -2
- zaturn/studio/templates/user_message.html +2 -2
- {zaturn-0.2.2.dist-info → zaturn-0.3.0.dist-info}/METADATA +4 -3
- zaturn-0.3.0.dist-info/RECORD +55 -0
- zaturn/studio/static/noto_emoji.ttf +0 -0
- zaturn-0.2.2.dist-info/RECORD +0 -39
- {zaturn-0.2.2.dist-info → zaturn-0.3.0.dist-info}/WHEEL +0 -0
- {zaturn-0.2.2.dist-info → zaturn-0.3.0.dist-info}/entry_points.txt +0 -0
- {zaturn-0.2.2.dist-info → zaturn-0.3.0.dist-info}/licenses/LICENSE +0 -0
- {zaturn-0.2.2.dist-info → zaturn-0.3.0.dist-info}/top_level.txt +0 -0
zaturn/studio/agent_wrapper.py
CHANGED
@@ -4,128 +4,52 @@ import json
|
|
4
4
|
from function_schema import get_function_schema
|
5
5
|
import httpx
|
6
6
|
from mcp.types import ImageContent
|
7
|
+
from pydantic_ai import Agent
|
8
|
+
from pydantic_ai.messages import ModelMessagesTypeAdapter
|
9
|
+
from pydantic_ai.models.openai import OpenAIChatModel, OpenAIChatModelSettings
|
10
|
+
from pydantic_ai.providers.openai import OpenAIProvider
|
11
|
+
from pydantic_core import to_jsonable_python
|
7
12
|
|
8
13
|
|
9
|
-
class
|
14
|
+
class ZaturnAgent:
|
10
15
|
|
11
16
|
def __init__(self,
|
12
17
|
endpoint: str,
|
13
18
|
api_key: str,
|
14
|
-
|
19
|
+
model_name: str,
|
15
20
|
tools: list = [],
|
16
21
|
image_input: bool = False,
|
22
|
+
reasoning_effort: str = 'none',
|
23
|
+
system_prompt: str = '',
|
17
24
|
):
|
18
25
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
'role': 'system',
|
25
|
-
'content': """
|
26
|
-
You are a helpful data analysis assistant.
|
27
|
-
Use only the tool provided data sources to process user inputs.
|
28
|
-
Do not use external sources or your own knowledge base.
|
29
|
-
Also, the tool outputs are shown to the user.
|
30
|
-
So, please avoid repeating the tool outputs in the generated text.
|
31
|
-
Use list_sources and describe_table whenever needed,
|
32
|
-
do not prompt the user for source names and column names.
|
33
|
-
""",
|
34
|
-
}
|
35
|
-
|
36
|
-
self._tools = []
|
37
|
-
self._tool_map = {}
|
38
|
-
for tool in tools:
|
39
|
-
tool_schema = get_function_schema(tool)
|
40
|
-
self._tools.append({
|
41
|
-
'type': 'function',
|
42
|
-
'function': tool_schema,
|
43
|
-
})
|
44
|
-
self._tool_map[tool_schema['name']] = tool
|
45
|
-
|
46
|
-
|
47
|
-
def _prepare_input_messages(self, messages):
|
48
|
-
input_messages = [self._system_message]
|
49
|
-
for message in messages:
|
50
|
-
if message['role']!='tool':
|
51
|
-
input_messages.append(message)
|
52
|
-
elif type(message['content']) is not list:
|
53
|
-
input_messages.append(message)
|
54
|
-
else:
|
55
|
-
new_content = []
|
56
|
-
image_content = None
|
57
|
-
for content in message['content']:
|
58
|
-
if content['type']=='image_url':
|
59
|
-
image_content = content
|
60
|
-
new_content.append({
|
61
|
-
'type': 'text',
|
62
|
-
'text': 'Tool call returned an image to the user.',
|
63
|
-
})
|
64
|
-
else:
|
65
|
-
new_content.append(content)
|
66
|
-
input_messages.append({
|
67
|
-
'role': message['role'],
|
68
|
-
'tool_call_id': message['tool_call_id'],
|
69
|
-
'name': message['name'],
|
70
|
-
'content': new_content,
|
71
|
-
})
|
72
|
-
|
73
|
-
return input_messages
|
74
|
-
|
75
|
-
|
76
|
-
def run(self, messages):
|
77
|
-
if type(messages) is str:
|
78
|
-
messages = [{'role': 'user', 'content': messages}]
|
79
|
-
|
80
|
-
while True:
|
81
|
-
res = httpx.post(
|
82
|
-
url = self._post_url,
|
83
|
-
headers = {
|
84
|
-
'Authorization': f'Bearer {self._api_key}'
|
85
|
-
},
|
86
|
-
json = {
|
87
|
-
'model': self._model,
|
88
|
-
'messages': self._prepare_input_messages(messages),
|
89
|
-
'tools': self._tools,
|
90
|
-
'reasoning': {'exclude': True},
|
91
|
-
}
|
26
|
+
model_settings = None
|
27
|
+
reasoning_effort = reasoning_effort.lower()
|
28
|
+
if reasoning_effort in ['low', 'medium', 'high']:
|
29
|
+
model_settings = OpenAIChatModelSettings(
|
30
|
+
openai_reasoning_effort = reasoning_effort,
|
92
31
|
)
|
32
|
+
|
33
|
+
self._agent = Agent(
|
34
|
+
OpenAIChatModel(
|
35
|
+
model_name,
|
36
|
+
provider = OpenAIProvider(
|
37
|
+
api_key = api_key,
|
38
|
+
base_url = endpoint,
|
39
|
+
)
|
40
|
+
),
|
41
|
+
model_settings = model_settings,
|
42
|
+
system_prompt = system_prompt or None,
|
43
|
+
tools = tools,
|
44
|
+
)
|
45
|
+
|
93
46
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
tool_name = tool_call['function']['name']
|
103
|
-
tool_args = json.loads(tool_call['function']['arguments'])
|
104
|
-
tool_response = self._tool_map[tool_name](**tool_args)
|
105
|
-
if type(tool_response) is ImageContent:
|
106
|
-
b64_data = tool_response.data
|
107
|
-
data_url = f'data:image/png;base64,{b64_data}'
|
108
|
-
content = [{
|
109
|
-
'type': 'image_url',
|
110
|
-
'image_url': {
|
111
|
-
"url": data_url,
|
112
|
-
}
|
113
|
-
}]
|
114
|
-
else:
|
115
|
-
content = [{
|
116
|
-
'type': 'text',
|
117
|
-
'text': json.dumps(tool_response)
|
118
|
-
}]
|
119
|
-
|
120
|
-
messages.append({
|
121
|
-
'role': 'tool',
|
122
|
-
'tool_call_id': tool_call['id'],
|
123
|
-
'name': tool_name,
|
124
|
-
'content': content
|
125
|
-
})
|
126
|
-
else:
|
127
|
-
break
|
128
|
-
|
129
|
-
return messages
|
130
|
-
|
47
|
+
def run(self, prompt, message_history = None):
|
48
|
+
if message_history:
|
49
|
+
message_history_obj = ModelMessagesTypeAdapter.validate_python(message_history)
|
50
|
+
result = self._agent.run_sync(prompt, message_history = message_history_obj)
|
51
|
+
return to_jsonable_python(result.all_messages())
|
52
|
+
else:
|
53
|
+
result = self._agent.run_sync(prompt)
|
54
|
+
return to_jsonable_python(result.all_messages())
|
131
55
|
|
zaturn/studio/app.py
CHANGED
@@ -62,6 +62,8 @@ def save_settings() -> str:
|
|
62
62
|
app.config['state']['api_model'] = api_model
|
63
63
|
app.config['state']['api_endpoint'] = api_endpoint
|
64
64
|
app.config['state']['api_image_input'] = False
|
65
|
+
app.config['state']['reasoning_effort'] = request.form.get('reasoning_effort', 'none')
|
66
|
+
app.config['state']['system_prompt'] = request.form.get('system_prompt').strip('\n')
|
65
67
|
|
66
68
|
try:
|
67
69
|
model_info = httpx.get(
|
@@ -195,31 +197,34 @@ def get_active_sources():
|
|
195
197
|
|
196
198
|
def prepare_chat_for_render(chat):
|
197
199
|
fn_calls = {}
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
200
|
+
|
201
|
+
for message in chat['messages']:
|
202
|
+
for part in message['parts']:
|
203
|
+
if part['part_kind']=='text' and message['kind']=='response':
|
204
|
+
part['html_content'] = mistune.html(part['content'])
|
205
|
+
elif part['part_kind']=='tool-call':
|
206
|
+
fn_calls[part['tool_call_id']] = part
|
207
|
+
fn_calls[part['tool_call_id']]['timestamp'] = message['timestamp']
|
208
|
+
elif part['part_kind']=='tool-return':
|
209
|
+
fn_call = fn_calls[part['tool_call_id']]
|
210
|
+
part['call_details'] = {}
|
211
|
+
part['call_details']['name'] = fn_call['tool_name']
|
212
|
+
|
213
|
+
t1 = datetime.fromisoformat(fn_call['timestamp'])
|
214
|
+
t2 = datetime.fromisoformat(part['timestamp'])
|
215
|
+
part['call_details']['exec_time'] = (t2 - t1).seconds
|
216
|
+
|
217
|
+
part['call_details']['args_html'] = tomli_w.dumps(
|
218
|
+
json.loads(fn_call['args'])
|
219
|
+
).replace('\n', '<br>')
|
220
|
+
|
221
|
+
if type(part['content']) is str:
|
222
|
+
part['html_content'] = mistune.html(part['content'])
|
223
|
+
elif type(part['content']) is dict and part['content']['type']=='image':
|
224
|
+
data_url = f"data:{part['content']['mimeType']};base64,{part['content']['data']}"
|
225
|
+
part['html_content'] = f'<img src="{data_url}">'
|
226
|
+
|
227
|
+
|
223
228
|
return chat
|
224
229
|
|
225
230
|
|
@@ -230,22 +235,23 @@ def create_new_chat():
|
|
230
235
|
chat = storage.load_chat(slug)
|
231
236
|
|
232
237
|
state = app.config['state']
|
233
|
-
agent = agent_wrapper.
|
238
|
+
agent = agent_wrapper.ZaturnAgent(
|
234
239
|
endpoint = state['api_endpoint'],
|
235
240
|
api_key = state['api_key'],
|
236
|
-
|
241
|
+
model_name = state['api_model'],
|
237
242
|
tools = ZaturnTools(get_active_sources()).tools,
|
238
243
|
image_input = state['api_image_input'],
|
244
|
+
reasoning_effort = state['reasoning_effort'],
|
245
|
+
system_prompt = state['system_prompt'],
|
239
246
|
)
|
240
|
-
chat['messages'] = agent.run(
|
247
|
+
chat['messages'] = agent.run(question)
|
241
248
|
storage.save_chat(slug, chat)
|
242
|
-
chat = prepare_chat_for_render(chat)
|
243
249
|
|
244
250
|
return boost(
|
245
251
|
''.join([
|
246
252
|
render_template('nav.html', slugs=storage.list_chats()),
|
247
253
|
'<main id="main">',
|
248
|
-
render_template('chat.html', chat=chat),
|
254
|
+
render_template('chat.html', chat=prepare_chat_for_render(chat)),
|
249
255
|
'</main>'
|
250
256
|
]),
|
251
257
|
reswap = 'multi:#sidebar,#main',
|
@@ -264,25 +270,26 @@ def show_chat(slug: str):
|
|
264
270
|
def follow_up_message():
|
265
271
|
slug = request.form['slug']
|
266
272
|
chat = storage.load_chat(slug)
|
267
|
-
|
268
|
-
'role': 'user',
|
269
|
-
'content': request.form['question'],
|
270
|
-
})
|
271
|
-
|
273
|
+
|
272
274
|
state = app.config['state']
|
273
|
-
agent = agent_wrapper.
|
275
|
+
agent = agent_wrapper.ZaturnAgent(
|
274
276
|
endpoint = state['api_endpoint'],
|
275
277
|
api_key = state['api_key'],
|
276
|
-
|
278
|
+
model_name = state['api_model'],
|
277
279
|
tools = ZaturnTools(get_active_sources()).tools,
|
278
280
|
image_input = state['api_image_input'],
|
281
|
+
reasoning_effort = state['reasoning_effort'],
|
282
|
+
system_prompt = state['system_prompt'],
|
283
|
+
)
|
284
|
+
|
285
|
+
chat['messages'] = agent.run(
|
286
|
+
prompt = request.form['question'],
|
287
|
+
message_history = chat['messages'],
|
279
288
|
)
|
280
|
-
chat['messages'] = agent.run(chat['messages'])
|
281
289
|
storage.save_chat(slug, chat)
|
282
|
-
|
283
|
-
|
290
|
+
|
284
291
|
return boost(
|
285
|
-
render_template('chat.html', chat=chat),
|
292
|
+
render_template('chat.html', chat=prepare_chat_for_render(chat)),
|
286
293
|
push_url = 'false',
|
287
294
|
reswap = 'innerHTML scroll:bottom',
|
288
295
|
)
|
zaturn/studio/storage.py
CHANGED
@@ -14,12 +14,24 @@ STATE_FILE = USER_DATA_DIR / 'studio.json'
|
|
14
14
|
CHATS_DIR = USER_DATA_DIR / 'chats'
|
15
15
|
os.makedirs(CHATS_DIR, exist_ok=True)
|
16
16
|
|
17
|
+
DEFAULT_PROMPT = """
|
18
|
+
You are a helpful data analysis assistant.
|
19
|
+
Use only the tool provided data sources to process user inputs.
|
20
|
+
Do not use external sources or your own knowledge base.
|
21
|
+
Also, the tool outputs are shown to the user.
|
22
|
+
So, please avoid repeating the tool outputs in the generated text.
|
23
|
+
Use list_data_sources and describe_table whenever needed,
|
24
|
+
do not prompt the user for source names and column names.
|
25
|
+
""".strip('\n')
|
26
|
+
|
17
27
|
|
18
28
|
def load_state() -> dict:
|
19
29
|
if os.path.exists(STATE_FILE):
|
20
30
|
with open(STATE_FILE) as f:
|
21
31
|
state = json.loads(f.read())
|
22
32
|
state['sources'] = state.get('sources', {})
|
33
|
+
state['system_prompt'] = state.get('system_prompt', DEFAULT_PROMPT)
|
34
|
+
state['reasoning_effort'] = state.get('reasoning_effort', 'none')
|
23
35
|
return state
|
24
36
|
else:
|
25
37
|
return {}
|
@@ -51,10 +63,8 @@ def create_chat(question: str):
|
|
51
63
|
|
52
64
|
chat = {
|
53
65
|
'slug': slug,
|
54
|
-
'messages': [
|
55
|
-
|
56
|
-
'content': question,
|
57
|
-
}]
|
66
|
+
'messages': [],
|
67
|
+
'schema_version': 1
|
58
68
|
}
|
59
69
|
|
60
70
|
filename = CHATS_DIR / f'{slug}.json'
|
@@ -19,13 +19,13 @@
|
|
19
19
|
<img src="/static/logo.svg" class="logo">
|
20
20
|
</a>
|
21
21
|
<a href="/">
|
22
|
-
|
22
|
+
{% include('icons/chat-bubble.svg') %}
|
23
23
|
</a>
|
24
24
|
<a href="/sources/manage" title="Manage Sources">
|
25
|
-
|
25
|
+
{% include('icons/database.svg') %}
|
26
26
|
</a>
|
27
27
|
<a href="/settings" title="Settings">
|
28
|
-
|
28
|
+
{% include('icons/settings.svg') %}
|
29
29
|
</a>
|
30
30
|
</header>
|
31
31
|
{% with slugs=slugs %}
|
@@ -5,15 +5,15 @@
|
|
5
5
|
<input type="hidden" name="key" value="{{key}}">
|
6
6
|
{% if active %}
|
7
7
|
<input type="hidden" name="new_status" value="inactive">
|
8
|
-
<button class="active" title="Currently visible to LLM, Click to Toggle">Active
|
8
|
+
<button class="active" title="Currently visible to LLM, Click to Toggle">Active {% include('icons/check-circle-solid.svg') %}</button>
|
9
9
|
{% else %}
|
10
10
|
<input type="hidden" name="new_status" value="active">
|
11
|
-
<button class="inactive" title="Currently invisible to LLM, Click to Toggle">Inactive
|
11
|
+
<button class="inactive" title="Currently invisible to LLM, Click to Toggle">Inactive {% include('icons/warning-triangle.svg') %}</button>
|
12
12
|
{% endif %}
|
13
13
|
</form>
|
14
14
|
|
15
15
|
<form action="/source/delete" method="POST">
|
16
16
|
<input type="hidden" name="key" value="{{key}}">
|
17
|
-
<button class="danger">Delete
|
17
|
+
<button class="danger">Delete {% include('icons/trash.svg') %}</button>
|
18
18
|
</form>
|
19
19
|
</div>
|
@@ -1,22 +1,30 @@
|
|
1
1
|
<section id="chat">
|
2
|
-
{%
|
3
|
-
{%
|
4
|
-
{%
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
2
|
+
{% if chat.get('schema_version', 0) >= 1 %}
|
3
|
+
{% for message in chat['messages'] %}
|
4
|
+
{% for part in message['parts'] %}
|
5
|
+
{% if part['part_kind']=='system-prompt' %}
|
6
|
+
{% include('chat_metadata.html') %}
|
7
|
+
{% elif part['part_kind']=='user-prompt' %}
|
8
|
+
{% include('user_message.html') %}
|
9
|
+
{% elif part['part_kind']=='text' and message['kind']=='response' %}
|
10
|
+
{% include('ai_message.html') %}
|
11
|
+
{% elif part['part_kind']=='tool-return' %}
|
12
|
+
{% include('function_call.html') %}
|
13
|
+
{% endif %}
|
14
|
+
{% endfor %}
|
15
|
+
{% endfor %}
|
11
16
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
<form action="/follow_up_message" method="POST">
|
18
|
+
<input type="hidden" name="slug" value="{{chat['slug']}}">
|
19
|
+
<textarea
|
20
|
+
required
|
21
|
+
name="question"
|
22
|
+
placeholder="Type a follow up question here."
|
23
|
+
></textarea>
|
24
|
+
<button>{% include('icons/arrow-right.svg') %}</button>
|
25
|
+
</form>
|
26
|
+
{% include('loader.html') %}
|
27
|
+
{% else %}
|
28
|
+
<pre><code>{{chat | tojson(indent=2)}}</code></pre>
|
29
|
+
{% endif %}
|
22
30
|
</section>
|
@@ -15,11 +15,6 @@
|
|
15
15
|
src: url('/static/fira_code.ttf');
|
16
16
|
}
|
17
17
|
|
18
|
-
@font-face {
|
19
|
-
font-family: "Noto Emoji";
|
20
|
-
src: url('/static/noto_emoji.ttf');
|
21
|
-
}
|
22
|
-
|
23
18
|
/* Global Styles */
|
24
19
|
* {
|
25
20
|
box-sizing: border-box;
|
@@ -37,7 +32,7 @@
|
|
37
32
|
--red: #d43a3a;
|
38
33
|
--fg2: #3a4d74;
|
39
34
|
--fg1: #182030;
|
40
|
-
--base-size: clamp(16px, 1.
|
35
|
+
--base-size: clamp(16px, 1.3vw, 32px);
|
41
36
|
--max-width: calc(var(--base-size)*36);
|
42
37
|
font-size: var(--base-size);
|
43
38
|
letter-spacing: 0.02rem;
|
@@ -55,6 +50,7 @@ body {
|
|
55
50
|
align-content: stretch;
|
56
51
|
height: 99vh;
|
57
52
|
line-height: 170%;
|
53
|
+
overflow-y: hidden;
|
58
54
|
}
|
59
55
|
|
60
56
|
a {
|
@@ -80,6 +76,11 @@ header .logo {
|
|
80
76
|
height: 2rem;
|
81
77
|
}
|
82
78
|
|
79
|
+
header svg {
|
80
|
+
width: 1.25rem;
|
81
|
+
height: 1.25rem;
|
82
|
+
}
|
83
|
+
|
83
84
|
#sidebar {
|
84
85
|
grid-area: 2 / 1 / 3 / 2;
|
85
86
|
background: var(--bg0);
|
@@ -120,12 +121,22 @@ section {
|
|
120
121
|
|
121
122
|
section h1 {
|
122
123
|
margin-bottom: 2rem;
|
124
|
+
display: flex;
|
125
|
+
align-items: center;
|
126
|
+
gap: 0.5rem;
|
127
|
+
}
|
128
|
+
|
129
|
+
section h1 svg {
|
130
|
+
width: 1.5rem;
|
131
|
+
height: 1.5rem;
|
123
132
|
}
|
124
133
|
|
125
134
|
.btn, button {
|
126
135
|
text-decoration: none;
|
127
136
|
background: var(--bg2);
|
128
|
-
display: inline-
|
137
|
+
display: inline-flex;
|
138
|
+
align-items: center;
|
139
|
+
gap: 0.5rem;
|
129
140
|
padding: 0.5rem 1rem;
|
130
141
|
border-radius: 0.2rem;
|
131
142
|
color: var(--t1);
|
@@ -145,6 +156,11 @@ section h1 {
|
|
145
156
|
opacity: 0.8;
|
146
157
|
}
|
147
158
|
|
159
|
+
.btn svg {
|
160
|
+
width: 1rem;
|
161
|
+
height: 1rem;
|
162
|
+
}
|
163
|
+
|
148
164
|
code {
|
149
165
|
font-family: "Fira Code", monospace;
|
150
166
|
font-size: 0.8rem;
|
@@ -160,6 +176,14 @@ code {
|
|
160
176
|
background: var(--bg0);
|
161
177
|
padding: 0.5rem;
|
162
178
|
border: 1px solid var(--bg2);
|
179
|
+
display: flex;
|
180
|
+
align-items: center;
|
181
|
+
gap: 0.5rem;
|
182
|
+
}
|
183
|
+
|
184
|
+
.alert svg {
|
185
|
+
width: 1rem;
|
186
|
+
height: 1rem;
|
163
187
|
}
|
164
188
|
|
165
189
|
|
@@ -178,6 +202,9 @@ form label {
|
|
178
202
|
|
179
203
|
form small {
|
180
204
|
font-size: 0.8rem;
|
205
|
+
}
|
206
|
+
|
207
|
+
form small:first-child {
|
181
208
|
font-weight: bold;
|
182
209
|
}
|
183
210
|
|
@@ -196,8 +223,32 @@ form input:focus {
|
|
196
223
|
border-bottom: 1px solid var(--t1);
|
197
224
|
}
|
198
225
|
|
226
|
+
form select {
|
227
|
+
border: none;
|
228
|
+
outline: none;
|
229
|
+
background: none;
|
230
|
+
font-family: "Fira Code", monospace;
|
231
|
+
border-bottom: 1px solid var(--fg1);
|
232
|
+
color: var(--fg1);
|
233
|
+
font-size: 0.8rem;
|
234
|
+
padding: 0.2rem;
|
235
|
+
}
|
236
|
+
|
237
|
+
form select:focus {
|
238
|
+
color: var(--t1);
|
239
|
+
border-bottom: 1px solid var(--t1);
|
240
|
+
}
|
241
|
+
|
199
242
|
form button {
|
200
243
|
justify-self: start;
|
244
|
+
display: inline-flex;
|
245
|
+
align-items: center;
|
246
|
+
gap: 0.5rem;
|
247
|
+
}
|
248
|
+
|
249
|
+
form button svg {
|
250
|
+
width: 1.25rem;
|
251
|
+
height: 1.25rem;
|
201
252
|
}
|
202
253
|
|
203
254
|
form progress[value="0"] {
|
@@ -205,12 +256,17 @@ form progress[value="0"] {
|
|
205
256
|
}
|
206
257
|
|
207
258
|
form textarea {
|
208
|
-
font-
|
259
|
+
font-family: "Fira Code", monospace;
|
260
|
+
font-size: 0.8rem;
|
209
261
|
padding: 0.5rem;
|
210
262
|
border: none;
|
211
263
|
outline: none;
|
212
264
|
}
|
213
265
|
|
266
|
+
form textarea.large {
|
267
|
+
height: 7rem;
|
268
|
+
}
|
269
|
+
|
214
270
|
form.htmx-request {
|
215
271
|
display: none;
|
216
272
|
}
|
@@ -224,7 +280,14 @@ form ~ .loader {
|
|
224
280
|
}
|
225
281
|
|
226
282
|
form.htmx-request + .loader {
|
227
|
-
display:
|
283
|
+
display: flex;
|
284
|
+
align-items: center;
|
285
|
+
gap: 0.5rem;
|
286
|
+
}
|
287
|
+
|
288
|
+
form ~ .loader svg {
|
289
|
+
width: 1.2rem;
|
290
|
+
height: 1.2rem;
|
228
291
|
}
|
229
292
|
|
230
293
|
@keyframes loadanim {
|
@@ -265,12 +328,19 @@ form.htmx-request + .loader {
|
|
265
328
|
#manage-sources .source-card button {
|
266
329
|
font-size: 0.75rem;
|
267
330
|
padding: 0.25rem 0.5rem;
|
331
|
+
display: inline-flex;
|
332
|
+
align-items: center;
|
268
333
|
}
|
269
334
|
|
270
335
|
#manage-sources .source-card button.inactive {
|
271
336
|
filter: grayscale(100%);
|
272
337
|
}
|
273
338
|
|
339
|
+
#manage-sources .source-card button svg {
|
340
|
+
width: 0.75rem;
|
341
|
+
height: 0.75rem;
|
342
|
+
}
|
343
|
+
|
274
344
|
#manage-sources .row-c2 {
|
275
345
|
margin-top: 1.5rem;
|
276
346
|
}
|
@@ -301,10 +371,29 @@ form.htmx-request + .loader {
|
|
301
371
|
padding: 1.5rem 0.5rem;
|
302
372
|
}
|
303
373
|
|
304
|
-
#chat ul {
|
374
|
+
#chat ul, #chat ol {
|
305
375
|
list-style-position: inside;
|
306
376
|
}
|
307
377
|
|
378
|
+
#chat .chat-metadata * {
|
379
|
+
font-family: "Fira Code", monospace;
|
380
|
+
font-size: 0.9rem;
|
381
|
+
}
|
382
|
+
|
383
|
+
#chat dt, #chat dd {
|
384
|
+
display: inline-block;
|
385
|
+
}
|
386
|
+
|
387
|
+
#chat dt {
|
388
|
+
font-weight: 700;
|
389
|
+
}
|
390
|
+
|
391
|
+
|
392
|
+
#chat .system-prompt-message summary {
|
393
|
+
cursor: pointer;
|
394
|
+
margin: 1rem 0;
|
395
|
+
}
|
396
|
+
|
308
397
|
#chat .user-message {
|
309
398
|
display: grid;
|
310
399
|
grid-template-columns: auto 1fr;
|
@@ -314,13 +403,26 @@ form.htmx-request + .loader {
|
|
314
403
|
}
|
315
404
|
|
316
405
|
#chat .user-message .sender {
|
406
|
+
font-size: 75%;
|
407
|
+
display: inline-flex;
|
408
|
+
align-items: center;
|
409
|
+
gap: 0.5rem;
|
410
|
+
background: none;
|
411
|
+
border: 0.1rem solid var(--t1);
|
412
|
+
padding: 0.125rem 0.75rem;
|
413
|
+
border-radius: 2rem;
|
317
414
|
color: var(--t1);
|
318
|
-
|
319
|
-
padding: 0.125rem 0.5rem;
|
320
|
-
font-size: 70%;
|
415
|
+
margin-right: 0.5rem;
|
321
416
|
}
|
322
417
|
|
418
|
+
#chat .user-message .sender svg {
|
419
|
+
width: 1rem;
|
420
|
+
height: 1rem;
|
421
|
+
}
|
323
422
|
|
423
|
+
#chat .user-message>p {
|
424
|
+
padding-top: 0.25rem;
|
425
|
+
}
|
324
426
|
|
325
427
|
#chat .ai-message {
|
326
428
|
display: grid;
|
@@ -332,30 +434,51 @@ form.htmx-request + .loader {
|
|
332
434
|
font-size: 70%;
|
333
435
|
}
|
334
436
|
|
437
|
+
#chat .ai-message>div>* {
|
438
|
+
margin: 0.25rem 0;
|
439
|
+
}
|
440
|
+
|
335
441
|
|
336
442
|
#chat .function-call {
|
337
443
|
display: grid;
|
338
444
|
gap: 0.75rem;
|
339
445
|
align-items: center;
|
446
|
+
grid-template-columns: auto 1fr;
|
340
447
|
}
|
341
448
|
|
342
|
-
#chat .function-name
|
449
|
+
#chat .function-name {
|
343
450
|
font-size: 75%;
|
344
|
-
|
451
|
+
justify-self: start;
|
452
|
+
display: inline-flex;
|
453
|
+
align-items: center;
|
454
|
+
gap: 0.5rem;
|
345
455
|
background: var(--t1);
|
346
|
-
|
456
|
+
border: 0.1rem solid var(--t1);
|
457
|
+
padding: 0.125rem 0.75rem;
|
347
458
|
border-radius: 2rem;
|
348
459
|
color: var(--bg0);
|
349
460
|
margin-right: 0.5rem;
|
350
461
|
}
|
351
462
|
|
352
|
-
#chat .function-
|
353
|
-
|
463
|
+
#chat .function-name svg {
|
464
|
+
width: 1rem;
|
465
|
+
height: 1rem;
|
354
466
|
}
|
355
467
|
|
356
|
-
#chat .function-
|
357
|
-
|
358
|
-
|
468
|
+
#chat .function-call .exec-time {
|
469
|
+
display: inline-flex;
|
470
|
+
align-items: center;
|
471
|
+
gap: 0.5rem;
|
472
|
+
font-size: 0.8rem;
|
473
|
+
}
|
474
|
+
|
475
|
+
#chat .function-call .exec-time svg {
|
476
|
+
width: 0.8rem;
|
477
|
+
height: 0.8rem;
|
478
|
+
}
|
479
|
+
|
480
|
+
#chat .function-call pre {
|
481
|
+
overflow-x: auto;
|
359
482
|
}
|
360
483
|
|
361
484
|
#chat .function-call .args {
|
@@ -365,10 +488,12 @@ form.htmx-request + .loader {
|
|
365
488
|
font-family: Fira Code, monospace;
|
366
489
|
font-size: 75%;
|
367
490
|
line-height: 180%;
|
491
|
+
grid-column: 1 / -1;
|
368
492
|
}
|
369
493
|
|
370
494
|
#chat .function-output {
|
371
495
|
overflow-x: auto;
|
496
|
+
grid-column: 1 / -1;
|
372
497
|
}
|
373
498
|
|
374
499
|
#chat table {
|
@@ -1,7 +1,8 @@
|
|
1
1
|
<div class="function-call">
|
2
|
-
<
|
3
|
-
{%
|
4
|
-
|
2
|
+
<b class="function-name">{% include('icons/wrench.svg') %} {{part['call_details']['name']}}</b>
|
3
|
+
<b class="exec-time">{% include('icons/timer.svg') %} {{part['call_details']['exec_time']}}s</b>
|
4
|
+
{% if part['call_details']['args_html'] %}
|
5
|
+
<p class="args">{{part['call_details']['args_html'] | safe}}</p>
|
5
6
|
{% endif %}
|
6
|
-
<div class="function-output">{{
|
7
|
+
<div class="function-output">{{ part['html_content'] | safe}}</div>
|
7
8
|
</div>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none">
|
2
|
+
<path d="M17 12.5C17.2761 12.5 17.5 12.2761 17.5 12C17.5 11.7239 17.2761 11.5 17 11.5C16.7239 11.5 16.5 11.7239 16.5 12C16.5 12.2761 16.7239 12.5 17 12.5Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
3
|
+
<path d="M12 12.5C12.2761 12.5 12.5 12.2761 12.5 12C12.5 11.7239 12.2761 11.5 12 11.5C11.7239 11.5 11.5 11.7239 11.5 12C11.5 12.2761 11.7239 12.5 12 12.5Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
4
|
+
<path d="M7 12.5C7.27614 12.5 7.5 12.2761 7.5 12C7.5 11.7239 7.27614 11.5 7 11.5C6.72386 11.5 6.5 11.7239 6.5 12C6.5 12.2761 6.72386 12.5 7 12.5Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
5
|
+
<path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 13.8214 2.48697 15.5291 3.33782 17L2.5 21.5L7 20.6622C8.47087 21.513 10.1786 22 12 22Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
6
|
+
</svg>
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg viewBox="0 0 24 24" fill="none">
|
2
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 1.25C6.06294 1.25 1.25 6.06294 1.25 12C1.25 17.9371 6.06294 22.75 12 22.75C17.9371 22.75 22.75 17.9371 22.75 12C22.75 6.06294 17.9371 1.25 12 1.25ZM7.53044 11.9697C7.23755 11.6768 6.76268 11.6768 6.46978 11.9697C6.17689 12.2626 6.17689 12.7374 6.46978 13.0303L9.46978 16.0303C9.76268 16.3232 10.2376 16.3232 10.5304 16.0303L17.5304 9.03033C17.8233 8.73744 17.8233 8.26256 17.5304 7.96967C17.2375 7.67678 16.7627 7.67678 16.4698 7.96967L10.0001 14.4393L7.53044 11.9697Z" fill="currentColor" stroke-width="1.5"></path>
|
3
|
+
</svg>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<svg width="24px" height="24px" viewBox="0 0 24 24" fill="none">
|
2
|
+
<path d="M5 12V18C5 18 5 21 12 21C19 21 19 18 19 18V12" stroke="currentColor" stroke-width="1.5"></path>
|
3
|
+
<path d="M5 6V12C5 12 5 15 12 15C19 15 19 12 19 12V6" stroke="currentColor" stroke-width="1.5"></path>
|
4
|
+
<path d="M12 3C19 3 19 6 19 6C19 6 19 9 12 9C5 9 5 6 5 6C5 6 5 3 12 3Z" stroke="currentColor" stroke-width="1.5"></path>
|
5
|
+
</svg>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg stroke-width="1.5" viewBox="0 0 24 24" fill="none">
|
2
|
+
<path d="M8 18C8 20.4148 9.79086 21 12 21C15.7587 21 17 18.5 14.5 13.5C11 18 10.5 11 11 9C9.5 12 8 14.8177 8 18Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
3
|
+
<path d="M12 21C17.0495 21 20 18.0956 20 13.125C20 8.15444 12 3 12 3C12 3 4 8.15444 4 13.125C4 18.0956 6.95054 21 12 21Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
4
|
+
</svg>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<svg stroke-width="1.5" viewBox="0 0 24 24" fill="none">
|
2
|
+
<path d="M3 19V5C3 3.89543 3.89543 3 5 3H16.1716C16.702 3 17.2107 3.21071 17.5858 3.58579L20.4142 6.41421C20.7893 6.78929 21 7.29799 21 7.82843V19C21 20.1046 20.1046 21 19 21H5C3.89543 21 3 20.1046 3 19Z" stroke="currentColor" stroke-width="1.5"></path>
|
3
|
+
<path d="M8.6 9H15.4C15.7314 9 16 8.73137 16 8.4V3.6C16 3.26863 15.7314 3 15.4 3H8.6C8.26863 3 8 3.26863 8 3.6V8.4C8 8.73137 8.26863 9 8.6 9Z" stroke="currentColor" stroke-width="1.5"></path>
|
4
|
+
<path d="M6 13.6V21H18V13.6C18 13.2686 17.7314 13 17.4 13H6.6C6.26863 13 6 13.2686 6 13.6Z" stroke="currentColor" stroke-width="1.5"></path>
|
5
|
+
</svg>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg viewBox="0 0 24 24" fill="none">
|
2
|
+
<path d="M14 11.9976C14 9.5059 11.683 7 8.85714 7C8.52241 7 7.41904 7.00001 7.14286 7.00001C4.30254 7.00001 2 9.23752 2 11.9976C2 14.376 3.70973 16.3664 6 16.8714C6.36756 16.9525 6.75006 16.9952 7.14286 16.9952" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
3
|
+
<path d="M10 11.9976C10 14.4893 12.317 16.9952 15.1429 16.9952C15.4776 16.9952 16.581 16.9952 16.8571 16.9952C19.6975 16.9952 22 14.7577 22 11.9976C22 9.6192 20.2903 7.62884 18 7.12383C17.6324 7.04278 17.2499 6.99999 16.8571 6.99999" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
4
|
+
</svg>
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<path d="M6.90588 4.53682C6.50592 4.2998 6 4.58808 6 5.05299V18.947C6 19.4119 6.50592 19.7002 6.90588 19.4632L18.629 12.5162C19.0211 12.2838 19.0211 11.7162 18.629 11.4838L6.90588 4.53682Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
3
|
+
</svg>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg viewBox="0 0 24 24" fill="none">
|
2
|
+
<path d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
3
|
+
<path d="M19.6224 10.3954L18.5247 7.7448L20 6L18 4L16.2647 5.48295L13.5578 4.36974L12.9353 2H10.981L10.3491 4.40113L7.70441 5.51596L6 4L4 6L5.45337 7.78885L4.3725 10.4463L2 11V13L4.40111 13.6555L5.51575 16.2997L4 18L6 20L7.79116 18.5403L10.397 19.6123L11 22H13L13.6045 19.6132L16.2551 18.5155C16.6969 18.8313 18 20 18 20L20 18L18.5159 16.2494L19.6139 13.598L21.9999 12.9772L22 11L19.6224 10.3954Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
4
|
+
</svg>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<svg stroke-width="1.5" viewBox="0 0 24 24" fill="none">
|
2
|
+
<path d="M9 2L15 2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
3
|
+
<path d="M12 10L12 14" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
4
|
+
<path d="M12 22C16.4183 22 20 18.4183 20 14C20 9.58172 16.4183 6 12 6C7.58172 6 4 9.58172 4 14C4 18.4183 7.58172 22 12 22Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
5
|
+
</svg>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<path d="M20 9L18.005 20.3463C17.8369 21.3026 17.0062 22 16.0353 22H7.96474C6.99379 22 6.1631 21.3026 5.99496 20.3463L4 9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
3
|
+
<path d="M21 6L15.375 6M3 6L8.625 6M8.625 6V4C8.625 2.89543 9.52043 2 10.625 2H13.375C14.4796 2 15.375 2.89543 15.375 4V6M8.625 6L15.375 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
4
|
+
</svg>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg viewBox="0 0 24 24" fill="none">
|
2
|
+
<path d="M6 20L18 20" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
3
|
+
<path d="M12 16V4M12 4L15.5 7.5M12 4L8.5 7.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
4
|
+
</svg>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg stroke-width="1.5" viewBox="0 0 24 24" fill="none">
|
2
|
+
<path d="M5 20V19C5 15.134 8.13401 12 12 12V12C15.866 12 19 15.134 19 19V20" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
3
|
+
<path d="M12 12C14.2091 12 16 10.2091 16 8C16 5.79086 14.2091 4 12 4C9.79086 4 8 5.79086 8 8C8 10.2091 9.79086 12 12 12Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
4
|
+
</svg>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<svg stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<path d="M20.0429 21H3.95705C2.41902 21 1.45658 19.3364 2.22324 18.0031L10.2662 4.01533C11.0352 2.67792 12.9648 2.67791 13.7338 4.01532L21.7768 18.0031C22.5434 19.3364 21.581 21 20.0429 21Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path>
|
3
|
+
<path d="M12 9V13" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path>
|
4
|
+
<path d="M12 17.01L12.01 16.9989" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
5
|
+
</svg>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg viewBox="0 0 24 24" stroke-width="1.5" fill="none">
|
2
|
+
<path d="M10.0503 10.6066L2.97923 17.6777C2.19818 18.4587 2.19818 19.725 2.97923 20.5061V20.5061C3.76027 21.2871 5.0266 21.2871 5.80765 20.5061L12.8787 13.435" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
3
|
+
<path d="M10.0502 10.6066C9.20638 8.45358 9.37134 5.6286 11.1109 3.88909C12.8504 2.14957 16.0606 1.76777 17.8284 2.82843L14.7877 5.8691L14.5051 8.98014L17.6161 8.69753L20.6568 5.65685C21.7175 7.42462 21.3357 10.6349 19.5961 12.3744C17.8566 14.1139 15.0316 14.2789 12.8786 13.435" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
|
4
|
+
</svg>
|
@@ -1 +1 @@
|
|
1
|
-
<p class="loader"
|
1
|
+
<p class="loader">{% include('icons/play.svg') %} Relax, Zaturn is running...</p>
|
@@ -1,13 +1,13 @@
|
|
1
1
|
<section id="manage-sources">
|
2
2
|
{% if sources %}
|
3
|
-
<h1
|
3
|
+
<h1>{% include('icons/database.svg') %} Your Data Sources</h1>
|
4
4
|
{% for key in sources %}
|
5
5
|
{% with key=key, active=sources[key]['active'] %}
|
6
6
|
{% include('c_source_card.html') %}
|
7
7
|
{% endwith %}
|
8
8
|
{% endfor %}
|
9
9
|
{% else %}
|
10
|
-
<h1
|
10
|
+
<h1>{% include('icons/database.svg') %} Add Some Data</h1>
|
11
11
|
{% endif %}
|
12
12
|
|
13
13
|
<div class="row-c2">
|
@@ -22,7 +22,7 @@
|
|
22
22
|
<input type="file" name="datafile" accept=".csv,.db,.sqlite,.sqlite3,.duckdb,.parquet,.pq" placeholder="" required>
|
23
23
|
<small><em>CSV / SQLite / DuckDB / Parquet</em></small>
|
24
24
|
</label>
|
25
|
-
<button
|
25
|
+
<button>{% include('icons/upload.svg') %} Upload</button>
|
26
26
|
<progress value='0' max='100'></progress>
|
27
27
|
</form>
|
28
28
|
|
@@ -36,9 +36,9 @@
|
|
36
36
|
<label>
|
37
37
|
<small>Or Link A Database Using URL</small>
|
38
38
|
<input type="text" name="db_url" required>
|
39
|
-
<small><em>PostgreSQL / MySQL / Clickhouse</em></small>
|
39
|
+
<small><em>PostgreSQL / MySQL / Clickhouse / MSSQL</em></small>
|
40
40
|
</label>
|
41
|
-
<button
|
41
|
+
<button>{% include('icons/link.svg') %} Connect</button>
|
42
42
|
</form>
|
43
43
|
</div>
|
44
44
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<section id="new-conversation">
|
2
|
-
<h1>Vamos
|
2
|
+
<h1>Vamos!</h1>
|
3
3
|
<p>An AMA Session With Your Data</p>
|
4
4
|
<form action="/create_new_chat" method="POST">
|
5
5
|
<textarea
|
@@ -7,7 +7,7 @@
|
|
7
7
|
name="question"
|
8
8
|
placeholder="Type your question here...
E.g.: Explore the linked data and tell me something useful."
|
9
9
|
></textarea>
|
10
|
-
<button
|
10
|
+
<button>{% include('icons/arrow-right.svg') %}</button>
|
11
11
|
</form>
|
12
12
|
{% include('loader.html') %}
|
13
13
|
</section>
|
@@ -1,13 +1,13 @@
|
|
1
1
|
<section id="settings">
|
2
2
|
<h1>
|
3
|
-
<a href="/"
|
3
|
+
<a href="/">{% include('icons/arrow-left.svg') %}</a>
|
4
4
|
Settings
|
5
5
|
</h1>
|
6
6
|
|
7
7
|
{% if updated %}
|
8
8
|
<p class="alert">
|
9
9
|
<code>{{updated}}</code>
|
10
|
-
|
10
|
+
{% include('icons/check-circle-solid.svg') %} Settings Updated!
|
11
11
|
</p>
|
12
12
|
{% endif %}
|
13
13
|
|
@@ -24,6 +24,27 @@
|
|
24
24
|
<small>OPENAI API ENDPOINT (Leave blank to use default)</small>
|
25
25
|
<input type="text" name="api_endpoint" value="{{current['api_endpoint']}}">
|
26
26
|
</label>
|
27
|
-
<
|
27
|
+
<label>
|
28
|
+
<small>REASONING EFFORT</small>
|
29
|
+
<select name="reasoning_effort">
|
30
|
+
<option value="none" {% if current['reasoning_effort']=='none' %}selected{% endif %}>
|
31
|
+
none
|
32
|
+
</option>
|
33
|
+
<option value="low" {% if current['reasoning_effort']=='low' %}selected{% endif %}>
|
34
|
+
low
|
35
|
+
</option>
|
36
|
+
<option value="medium" {% if current['reasoning_effort']=='medium' %}selected{% endif %}>
|
37
|
+
medium
|
38
|
+
</option>
|
39
|
+
<option value="high" {% if current['reasoning_effort']=='high' %}selected{% endif %}>
|
40
|
+
high
|
41
|
+
</option>
|
42
|
+
</select>
|
43
|
+
</label>
|
44
|
+
<label>
|
45
|
+
<small>SYSTEM PROMPT</small>
|
46
|
+
<textarea name="system_prompt" class="large" required>{{current['system_prompt']}}</textarea>
|
47
|
+
</label>
|
48
|
+
<button>{% include('icons/floppy-disk.svg') %} Save</button>
|
28
49
|
</form>
|
29
50
|
</section>
|
@@ -1,6 +1,7 @@
|
|
1
1
|
<section id="setup-prompt">
|
2
|
-
<h1>Are You Ready?
|
2
|
+
<h1>Are You Ready? {% include('icons/fire-flame.svg') %}</h1>
|
3
3
|
<p>We need to set you up though.</p>
|
4
4
|
<p>Head over to <a href="/settings">settings</a> and add your LLM API Key.</p>
|
5
|
-
<
|
5
|
+
<br>
|
6
|
+
<p><a href="/settings" class="btn">{% include('icons/settings.svg') %} Open Settings</a>
|
6
7
|
</section>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: zaturn
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.3.0
|
4
4
|
Summary: AI Data Analysis MCP & Studio
|
5
5
|
Author-email: Karthik Devan <krtdvn@gmail.com>
|
6
6
|
Maintainer-email: Karthik Devan <krtdvn@gmail.com>
|
@@ -18,13 +18,14 @@ Requires-Dist: function-schema>=0.4.5
|
|
18
18
|
Requires-Dist: kaleido==0.2.1
|
19
19
|
Requires-Dist: mistune>=3.1.3
|
20
20
|
Requires-Dist: openai>=1.82.1
|
21
|
-
Requires-Dist: openai-agents>=0.0.16
|
22
21
|
Requires-Dist: pandas>=2.2.3
|
23
22
|
Requires-Dist: pillow>=11.2.1
|
24
23
|
Requires-Dist: platformdirs>=4.3.7
|
25
24
|
Requires-Dist: plotly[express]>=6.0.1
|
26
25
|
Requires-Dist: psycopg2-binary>=2.9.10
|
27
26
|
Requires-Dist: pyarrow>=19.0.1
|
27
|
+
Requires-Dist: pydantic-ai>=0.8.0
|
28
|
+
Requires-Dist: pydantic-core>=2.33.2
|
28
29
|
Requires-Dist: pymssql>=2.3.7
|
29
30
|
Requires-Dist: pymysql>=1.1.1
|
30
31
|
Requires-Dist: python-lsp-server>=1.12.2
|
@@ -43,7 +44,7 @@ Dynamic: license-file
|
|
43
44
|
</h1>
|
44
45
|
|
45
46
|
<a href="https://discord.gg/K8mECeVzpQ">
|
46
|
-
|
47
|
+
Join the Discord
|
47
48
|
</a>
|
48
49
|
|
49
50
|
## Just Chat With Your Data! No SQL, No Python.
|
@@ -0,0 +1,55 @@
|
|
1
|
+
zaturn/mcp/__init__.py,sha256=8pTcOyJ3tK7TJcP4HBDVQA_MVuMrfYJwa8sWKfCvXIE,3466
|
2
|
+
zaturn/studio/__init__.py,sha256=A1QxWydtsE0VmsJlvF7O9Fx1-WKjV3MBPje7knFSDzw,83
|
3
|
+
zaturn/studio/agent_wrapper.py,sha256=HjWieqZkTWhei41c1SfLzNK-UcZwxy-jedcHUk31Vt4,1771
|
4
|
+
zaturn/studio/app.py,sha256=GtlxapusQCPk4fmUAkxemnytqk3BGkg6Oc0bQmlET0c,9747
|
5
|
+
zaturn/studio/storage.py,sha256=YsE98yQ3hPsYvbuWPyc_MqvjzbNT8kv8HqhCOSbC5bA,2588
|
6
|
+
zaturn/studio/static/fira_code.ttf,sha256=mqZDedYDyifatZw-V4E2gnkwNfVs5GgvudgTKEd_0UQ,264848
|
7
|
+
zaturn/studio/static/inter_ital_var.ttf,sha256=YTb3M3L-3De4D9Go7D4hc0Bz_xc3bzZycY8YZ3lnLno,904532
|
8
|
+
zaturn/studio/static/inter_var.ttf,sha256=C-I5nqkl8fg_-XR2R2HamGDsUHQu0ppdTB_9DFx6w6g,874708
|
9
|
+
zaturn/studio/static/logo.png,sha256=QNyNJSy_KFdPmHoocqkynN8yp73vFqqcMthPmNGLPg8,20916
|
10
|
+
zaturn/studio/static/logo.svg,sha256=UH5m-H2YZy54eJYKd_zM8xeEWntOaYLfrs4MmGw2MUI,588
|
11
|
+
zaturn/studio/static/js/htmx-multi-swap.js,sha256=It1Qs3c1QcnlBLN0kwbMAE0U_Ww5oxeUdMJFdIqbRwU,1480
|
12
|
+
zaturn/studio/static/js/htmx.min.js,sha256=acrv0NqSJpBm5yXX_hdeJrnVDJYuMFZFnAxHcVTNudM,50918
|
13
|
+
zaturn/studio/templates/_shell.html,sha256=reh4GSnR64jwlMe9iT4bknddl-pvTcPkThFsT2CTJNU,1157
|
14
|
+
zaturn/studio/templates/ai_message.html,sha256=fSskULhMrGiPHYQHC4dkyZjUYqmP8zAl3Tq4WUG17ME,77
|
15
|
+
zaturn/studio/templates/c_settings_updated.html,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
16
|
+
zaturn/studio/templates/c_source_card.html,sha256=14Mer1f_7l5uRGcqtxnaocBZCy4uVFGsxdLpcUUwzn4,836
|
17
|
+
zaturn/studio/templates/chat.html,sha256=c2hDmNsuQwvOrvd9Y2BWHA1813takHE7kG4VidYFaxw,1071
|
18
|
+
zaturn/studio/templates/chat_metadata.html,sha256=mWh506QnVc8sltonspXuG_Ld-K2J4eJKfHSmhY0WBHA,245
|
19
|
+
zaturn/studio/templates/function_call.html,sha256=4tOqFBs6agLSzh2l54cfpWMbRA4V0-mqhgb0S9hC5Yw,430
|
20
|
+
zaturn/studio/templates/loader.html,sha256=8rx0RjAmhJXCcjrtComCkAdZ6_13-Yjf17K-fdpRaQk,82
|
21
|
+
zaturn/studio/templates/manage_sources.html,sha256=JtyYZ_cO_Da2pcvMjpmA4WfG1z9-G6h3_NA74r9WBdg,1478
|
22
|
+
zaturn/studio/templates/nav.html,sha256=6wB7zO-DEsJn_-ZUujq8iIoYi5fFeYUJoMPnix320Q8,104
|
23
|
+
zaturn/studio/templates/new_conversation.html,sha256=UU7X7Mrj_qltrSUJWhuUPlGEjjmiY3Ihjd8FvjuEWoc,431
|
24
|
+
zaturn/studio/templates/settings.html,sha256=x3P8U6hSD5tj-qY__7Lc0kZ5GZZ94Modnytl3IzTDjs,1659
|
25
|
+
zaturn/studio/templates/setup_prompt.html,sha256=W9ZCizvSHllMub_SBvib24MhNIDh-DWEbaY-2Q4t7I0,321
|
26
|
+
zaturn/studio/templates/user_message.html,sha256=ZeV6Lw776xNsnCzm2--cEtOil1slrOPLvwpTq7bSMmo,124
|
27
|
+
zaturn/studio/templates/css/style.css,sha256=M3s1HTR_137i_FSiLRHMzvCPRjds8MppcZHevBTV0JY,8217
|
28
|
+
zaturn/studio/templates/icons/arrow-left.svg,sha256=S-ecMUbtLs-WFklwKQRQDJMDZZ4tZTKZ2AElGiigCNs,213
|
29
|
+
zaturn/studio/templates/icons/arrow-right.svg,sha256=FtNCDvdmCLq7lPm9IvgA8iZbVJqHQfzyTWx0zg-aFqA,215
|
30
|
+
zaturn/studio/templates/icons/chat-bubble.svg,sha256=kJ4jMNTjWbJNS1kGVcM6Haz0uG_eDQ7Pjp0u6aX2uEo,1116
|
31
|
+
zaturn/studio/templates/icons/check-circle-solid.svg,sha256=0YulODKxiD2iPyXpjoBCAo0wNOX1TrRW3sVVGMBYjb0,617
|
32
|
+
zaturn/studio/templates/icons/database.svg,sha256=xYO7a-qFwITKuTcbE8bNvFDPGfF4ZOfMjUdRp_hu5os,407
|
33
|
+
zaturn/studio/templates/icons/fire-flame.svg,sha256=V7t9todUvxl4A5AwLAAVsiIFBRwodGnWbtHgUBSzis4,496
|
34
|
+
zaturn/studio/templates/icons/floppy-disk.svg,sha256=-rsUVlP_iiJT4XYfckGuPgWq1XRclK4LZSrQq43xRgE,657
|
35
|
+
zaturn/studio/templates/icons/link.svg,sha256=K3XPHp-e9TnjFqJU0bS8vgTXX8lHkzStgDh2wjqMbf4,687
|
36
|
+
zaturn/studio/templates/icons/play.svg,sha256=zRuQPv2bO7qABFpM8Yesfh-k66Y4a4R3qsrpz71L7iw,387
|
37
|
+
zaturn/studio/templates/icons/settings.svg,sha256=30EYP16HjWxDWWm73FiCl2ak-e0Dso-sQkIX07VlnU8,763
|
38
|
+
zaturn/studio/templates/icons/timer.svg,sha256=-X6UYIG6iWLLPyMP1t7WgLFtdSZD6a3hSFah12uVit0,525
|
39
|
+
zaturn/studio/templates/icons/trash.svg,sha256=_10g_X4vqTt677KyAJtXXQD1FbuH95iQ-MqhcGhEvfE,558
|
40
|
+
zaturn/studio/templates/icons/upload.svg,sha256=dJsJOF9-Xtv7d8nTOL17kWAb6YrAE2qUrEOYEBGgfV8,309
|
41
|
+
zaturn/studio/templates/icons/user.svg,sha256=vtj4RtCtxW5WaMmlBhtMCollHJe-VpFGfLmBlGYSm8k,459
|
42
|
+
zaturn/studio/templates/icons/warning-triangle.svg,sha256=3K1lMfgIKFQ7Y1uJbORzVnzaou1jwmVcdeAmtGe_zQg,589
|
43
|
+
zaturn/studio/templates/icons/wrench.svg,sha256=275gpXZNLEuzZpUgp6oNTBvl7LzWX-xfTPrcDVxIv1g,700
|
44
|
+
zaturn/tools/__init__.py,sha256=vOcHneRuZll9k-2e3sra7m8qfdc4IoAFYc2g_xK79HE,262
|
45
|
+
zaturn/tools/config.py,sha256=Ia-WzK_G6vQqB7norvaffb3fKLjtmXupVqAWsxdu6Gs,354
|
46
|
+
zaturn/tools/core.py,sha256=4fHxSIbO22cTIejJk02GzUBfWimh1Ql9mZ3JgI1qLBY,2893
|
47
|
+
zaturn/tools/query_utils.py,sha256=OnXbONmEgsHcScrJ76b7P3BRLOKgi8TMkhxBcLQK9cY,5306
|
48
|
+
zaturn/tools/visualizations.py,sha256=aPXCN1YIjCz6uiwJjduKCiLLtnBFX92hTvjy5EqQYk8,9509
|
49
|
+
zaturn/tools/example_data/all_pokemon_data.csv,sha256=SUlGHHWbehuLg-ch1YUrQ6-xBtqHGw6rIkyn70fAgCk,130893
|
50
|
+
zaturn-0.3.0.dist-info/licenses/LICENSE,sha256=mZSuFlbEBZGl0-8ULRMLdRDbhau5hrWRNQOjytYeaug,1070
|
51
|
+
zaturn-0.3.0.dist-info/METADATA,sha256=K_PMEFwYGg1FHelUgTkLrGd4uV4uAqQX5sa3rdxO4ak,3931
|
52
|
+
zaturn-0.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
53
|
+
zaturn-0.3.0.dist-info/entry_points.txt,sha256=MWMWX0dE_ZQM4StGKCLxJym_D91F82RcBi2LBj0hEho,82
|
54
|
+
zaturn-0.3.0.dist-info/top_level.txt,sha256=KLUnwQwVZkfd5YCnnqR35MOOs8KLhanPGelvmRo2MVA,7
|
55
|
+
zaturn-0.3.0.dist-info/RECORD,,
|
Binary file
|
zaturn-0.2.2.dist-info/RECORD
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
zaturn/mcp/__init__.py,sha256=8pTcOyJ3tK7TJcP4HBDVQA_MVuMrfYJwa8sWKfCvXIE,3466
|
2
|
-
zaturn/studio/__init__.py,sha256=A1QxWydtsE0VmsJlvF7O9Fx1-WKjV3MBPje7knFSDzw,83
|
3
|
-
zaturn/studio/agent_wrapper.py,sha256=4mEMRfE1Tfv63D7OIabqUbEJdIgO2yo8UXO6PKvNrmI,4603
|
4
|
-
zaturn/studio/app.py,sha256=LEoSjs5wpZGX1B7pcJ2e_6CaxOFjbO6JitxlkJv__30,9208
|
5
|
-
zaturn/studio/storage.py,sha256=4fZ_pwc8goe_tKZcYSxHg0lOy79OFn8TgxTroxBmbLs,2041
|
6
|
-
zaturn/studio/static/fira_code.ttf,sha256=mqZDedYDyifatZw-V4E2gnkwNfVs5GgvudgTKEd_0UQ,264848
|
7
|
-
zaturn/studio/static/inter_ital_var.ttf,sha256=YTb3M3L-3De4D9Go7D4hc0Bz_xc3bzZycY8YZ3lnLno,904532
|
8
|
-
zaturn/studio/static/inter_var.ttf,sha256=C-I5nqkl8fg_-XR2R2HamGDsUHQu0ppdTB_9DFx6w6g,874708
|
9
|
-
zaturn/studio/static/logo.png,sha256=QNyNJSy_KFdPmHoocqkynN8yp73vFqqcMthPmNGLPg8,20916
|
10
|
-
zaturn/studio/static/logo.svg,sha256=UH5m-H2YZy54eJYKd_zM8xeEWntOaYLfrs4MmGw2MUI,588
|
11
|
-
zaturn/studio/static/noto_emoji.ttf,sha256=tX7Yla6dCbp7SxnDQ6dc85qtVxVsNFDjOdnRFVbX7cE,890608
|
12
|
-
zaturn/studio/static/js/htmx-multi-swap.js,sha256=It1Qs3c1QcnlBLN0kwbMAE0U_Ww5oxeUdMJFdIqbRwU,1480
|
13
|
-
zaturn/studio/static/js/htmx.min.js,sha256=acrv0NqSJpBm5yXX_hdeJrnVDJYuMFZFnAxHcVTNudM,50918
|
14
|
-
zaturn/studio/templates/_shell.html,sha256=4WxTSo8OoqEtyoUJoeb0BlP3j4ZSpVxunPNndVa7yYc,1061
|
15
|
-
zaturn/studio/templates/ai_message.html,sha256=-lFJmjxs5QHeIQLfx1-he4zamMO5U7enco8DPGoOItE,114
|
16
|
-
zaturn/studio/templates/c_settings_updated.html,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
17
|
-
zaturn/studio/templates/c_source_card.html,sha256=TOFssoWHc9pJEWW-GpUGWu4_wZMfJFoFWNtIj3x_LtQ,727
|
18
|
-
zaturn/studio/templates/chat.html,sha256=29I8R8bti_qMzU9FjBOGiLVEh-g1Es1VbaN6Dj_OMBA,660
|
19
|
-
zaturn/studio/templates/function_call.html,sha256=5NBzHE9KYlOgmNqv_Nz2PwsNVVhpSVM9NebhTMpAttg,316
|
20
|
-
zaturn/studio/templates/loader.html,sha256=jkrpmPA3_P0aL0ZrE_wkoGlnK12Go-OI2xtUyCDRikQ,64
|
21
|
-
zaturn/studio/templates/manage_sources.html,sha256=mLyNAYNu-u0mjTH8ybYO8HCYhHP6NVao20jNyqevu9g,1350
|
22
|
-
zaturn/studio/templates/nav.html,sha256=6wB7zO-DEsJn_-ZUujq8iIoYi5fFeYUJoMPnix320Q8,104
|
23
|
-
zaturn/studio/templates/new_conversation.html,sha256=p0e8D7b_riARS6xmqGk-g5tITd_ikgggVWWWlZ8MN5E,403
|
24
|
-
zaturn/studio/templates/settings.html,sha256=ZmukMbTsGGsVauEg9EtyyiR2_fOYvO5fAEAiJL0CJnU,760
|
25
|
-
zaturn/studio/templates/setup_prompt.html,sha256=K8l3ewlEyrUFiMmw2qPyDFbFNkq1RCBksrw9eL2tkIs,249
|
26
|
-
zaturn/studio/templates/user_message.html,sha256=WbvdVr4AVzVx6MG0eQ_ulMeHB9rpScZc-EZlCoYFEgw,90
|
27
|
-
zaturn/studio/templates/css/style.css,sha256=cKImLAjLp6XjHdT16v9yJS0DHG2wWx8djR18SHfMqvE,6264
|
28
|
-
zaturn/tools/__init__.py,sha256=vOcHneRuZll9k-2e3sra7m8qfdc4IoAFYc2g_xK79HE,262
|
29
|
-
zaturn/tools/config.py,sha256=Ia-WzK_G6vQqB7norvaffb3fKLjtmXupVqAWsxdu6Gs,354
|
30
|
-
zaturn/tools/core.py,sha256=4fHxSIbO22cTIejJk02GzUBfWimh1Ql9mZ3JgI1qLBY,2893
|
31
|
-
zaturn/tools/query_utils.py,sha256=OnXbONmEgsHcScrJ76b7P3BRLOKgi8TMkhxBcLQK9cY,5306
|
32
|
-
zaturn/tools/visualizations.py,sha256=aPXCN1YIjCz6uiwJjduKCiLLtnBFX92hTvjy5EqQYk8,9509
|
33
|
-
zaturn/tools/example_data/all_pokemon_data.csv,sha256=SUlGHHWbehuLg-ch1YUrQ6-xBtqHGw6rIkyn70fAgCk,130893
|
34
|
-
zaturn-0.2.2.dist-info/licenses/LICENSE,sha256=mZSuFlbEBZGl0-8ULRMLdRDbhau5hrWRNQOjytYeaug,1070
|
35
|
-
zaturn-0.2.2.dist-info/METADATA,sha256=BSnrqH9k7MNfqmRVPEO6q3884y-8Ym1X6ctklZz6NZc,3978
|
36
|
-
zaturn-0.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
37
|
-
zaturn-0.2.2.dist-info/entry_points.txt,sha256=MWMWX0dE_ZQM4StGKCLxJym_D91F82RcBi2LBj0hEho,82
|
38
|
-
zaturn-0.2.2.dist-info/top_level.txt,sha256=KLUnwQwVZkfd5YCnnqR35MOOs8KLhanPGelvmRo2MVA,7
|
39
|
-
zaturn-0.2.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|