flowent 0.1.3 → 0.1.5
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.
- package/backend/pyproject.toml +1 -1
- package/backend/src/flowent/__pycache__/__init__.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/_version.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/agent.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/approval.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/channels.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/cli.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/compact.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/context.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/llm.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/logging.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/main.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/mcp.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/mcp_import.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/patch.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/paths.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/permissions.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/sandbox.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/skills.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/storage.cpython-313.pyc +0 -0
- package/backend/src/flowent/__pycache__/tools.cpython-313.pyc +0 -0
- package/backend/src/flowent/agent.py +23 -1
- package/backend/src/flowent/approval.py +148 -0
- package/backend/src/flowent/cli.py +16 -2
- package/backend/src/flowent/compact.py +183 -0
- package/backend/src/flowent/context.py +19 -1
- package/backend/src/flowent/llm.py +51 -11
- package/backend/src/flowent/logging.py +60 -0
- package/backend/src/flowent/main.py +696 -192
- package/backend/src/flowent/mcp.py +3 -1
- package/backend/src/flowent/patch.py +55 -31
- package/backend/src/flowent/paths.py +12 -0
- package/backend/src/flowent/permissions.py +185 -42
- package/backend/src/flowent/sandbox.py +146 -13
- package/backend/src/flowent/static/assets/index-Cl20cARb.css +2 -0
- package/backend/src/flowent/static/assets/index-dsDDsEym.js +81 -0
- package/backend/src/flowent/static/index.html +2 -2
- package/backend/src/flowent/storage.py +257 -9
- package/backend/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_agent_tools.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_approval.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_channels.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_health.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_llm_providers.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_logging.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_mcp.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_patch.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_permissions.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_persistence.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_skills.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_startup_requirements.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/__pycache__/test_workspace_chat.cpython-313-pytest-9.0.3.pyc +0 -0
- package/backend/tests/test_agent_tools.py +312 -1
- package/backend/tests/test_approval.py +283 -0
- package/backend/tests/test_llm_providers.py +216 -0
- package/backend/tests/test_logging.py +30 -0
- package/backend/tests/test_mcp.py +76 -10
- package/backend/tests/test_patch.py +112 -0
- package/backend/tests/test_permissions.py +198 -53
- package/backend/tests/test_persistence.py +78 -0
- package/backend/tests/test_startup_requirements.py +96 -0
- package/backend/tests/test_workspace_chat.py +1265 -144
- package/backend/uv.lock +1 -1
- package/dist/frontend/assets/index-Cl20cARb.css +2 -0
- package/dist/frontend/assets/index-dsDDsEym.js +81 -0
- package/dist/frontend/index.html +2 -2
- package/package.json +2 -2
- package/backend/src/flowent/static/assets/index-DjF2KBwE.js +0 -81
- package/backend/src/flowent/static/assets/index-P-bBpJG8.css +0 -2
- package/dist/frontend/assets/index-DjF2KBwE.js +0 -81
- package/dist/frontend/assets/index-P-bBpJG8.css +0 -2
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>Flowent</title>
|
|
8
8
|
<meta name="description" content="Flowent application" />
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
10
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-dsDDsEym.js"></script>
|
|
10
|
+
<link rel="stylesheet" crossorigin href="/assets/index-Cl20cARb.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
13
13
|
<div id="root"></div>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import sqlite3
|
|
3
3
|
from pathlib import Path
|
|
4
|
+
from typing import Annotated, Literal
|
|
4
5
|
|
|
5
6
|
from pydantic import BaseModel, ConfigDict, Field
|
|
6
7
|
|
|
7
|
-
from flowent.llm import ProviderFormat, ReasoningEffort
|
|
8
|
+
from flowent.llm import ChatMessage, ProviderFormat, ReasoningEffort
|
|
8
9
|
from flowent.paths import data_directory
|
|
9
10
|
|
|
10
11
|
|
|
@@ -89,6 +90,7 @@ class StoredProvider(BaseModel):
|
|
|
89
90
|
class StoredSettings(BaseModel):
|
|
90
91
|
model_config = ConfigDict(extra="forbid")
|
|
91
92
|
|
|
93
|
+
agent_prompt: str = Field(default="", exclude_if=lambda value: value == "")
|
|
92
94
|
reasoning_effort: ReasoningEffort = ReasoningEffort.DEFAULT
|
|
93
95
|
selected_model: str
|
|
94
96
|
selected_provider_id: str
|
|
@@ -106,11 +108,64 @@ class StoredToolItem(BaseModel):
|
|
|
106
108
|
data: dict[str, object] | None = None
|
|
107
109
|
|
|
108
110
|
|
|
111
|
+
class StoredThinkingOutputItem(BaseModel):
|
|
112
|
+
model_config = ConfigDict(extra="forbid")
|
|
113
|
+
|
|
114
|
+
content: str
|
|
115
|
+
id: str
|
|
116
|
+
type: Literal["thinking"]
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class StoredTextOutputItem(BaseModel):
|
|
120
|
+
model_config = ConfigDict(extra="forbid")
|
|
121
|
+
|
|
122
|
+
content: str
|
|
123
|
+
id: str
|
|
124
|
+
type: Literal["text"]
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class StoredErrorOutputItem(BaseModel):
|
|
128
|
+
model_config = ConfigDict(extra="forbid")
|
|
129
|
+
|
|
130
|
+
detail: str = Field(default="", exclude_if=lambda value: value == "")
|
|
131
|
+
id: str
|
|
132
|
+
message: str
|
|
133
|
+
title: str
|
|
134
|
+
type: Literal["error"]
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class StoredToolOutputItem(BaseModel):
|
|
138
|
+
model_config = ConfigDict(extra="forbid")
|
|
139
|
+
|
|
140
|
+
id: str
|
|
141
|
+
tool: StoredToolItem
|
|
142
|
+
type: Literal["tool"]
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
StoredOutputItem = Annotated[
|
|
146
|
+
StoredThinkingOutputItem
|
|
147
|
+
| StoredTextOutputItem
|
|
148
|
+
| StoredErrorOutputItem
|
|
149
|
+
| StoredToolOutputItem,
|
|
150
|
+
Field(discriminator="type"),
|
|
151
|
+
]
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class StoredAssistantOutputGroup(BaseModel):
|
|
155
|
+
model_config = ConfigDict(extra="forbid")
|
|
156
|
+
|
|
157
|
+
id: str
|
|
158
|
+
items: list[StoredOutputItem]
|
|
159
|
+
|
|
160
|
+
|
|
109
161
|
class StoredMessage(BaseModel):
|
|
110
162
|
model_config = ConfigDict(extra="forbid")
|
|
111
163
|
|
|
112
164
|
author: str
|
|
113
165
|
content: str
|
|
166
|
+
groups: list[StoredAssistantOutputGroup] = Field(
|
|
167
|
+
default_factory=list, exclude_if=lambda value: value == []
|
|
168
|
+
)
|
|
114
169
|
id: str
|
|
115
170
|
status: str = Field(
|
|
116
171
|
default="completed", exclude_if=lambda value: value == "completed"
|
|
@@ -119,6 +174,20 @@ class StoredMessage(BaseModel):
|
|
|
119
174
|
tools: list[StoredToolItem] = Field(default_factory=list)
|
|
120
175
|
|
|
121
176
|
|
|
177
|
+
class StoredCompactionCheckpoint(BaseModel):
|
|
178
|
+
model_config = ConfigDict(extra="forbid")
|
|
179
|
+
|
|
180
|
+
created_at: int = 0
|
|
181
|
+
id: str
|
|
182
|
+
method: str
|
|
183
|
+
replacement_history: list[ChatMessage]
|
|
184
|
+
source_message_id: str | None = None
|
|
185
|
+
summary: str
|
|
186
|
+
token_after: int = 0
|
|
187
|
+
token_before: int = 0
|
|
188
|
+
trigger: str
|
|
189
|
+
|
|
190
|
+
|
|
122
191
|
class StoredState(BaseModel):
|
|
123
192
|
model_config = ConfigDict(extra="forbid")
|
|
124
193
|
|
|
@@ -172,7 +241,7 @@ class StateStore:
|
|
|
172
241
|
]
|
|
173
242
|
settings_row = connection.execute(
|
|
174
243
|
"""
|
|
175
|
-
SELECT selected_provider_id, selected_model, reasoning_effort
|
|
244
|
+
SELECT selected_provider_id, selected_model, reasoning_effort, agent_prompt
|
|
176
245
|
FROM settings
|
|
177
246
|
WHERE id = 1
|
|
178
247
|
"""
|
|
@@ -181,6 +250,10 @@ class StateStore:
|
|
|
181
250
|
StoredMessage(
|
|
182
251
|
author=row["author"],
|
|
183
252
|
content=row["content"],
|
|
253
|
+
groups=[
|
|
254
|
+
StoredAssistantOutputGroup.model_validate(group)
|
|
255
|
+
for group in json.loads(row["groups"] or "[]")
|
|
256
|
+
],
|
|
184
257
|
id=row["id"],
|
|
185
258
|
status=row["status"],
|
|
186
259
|
thinking=row["thinking"],
|
|
@@ -191,7 +264,7 @@ class StateStore:
|
|
|
191
264
|
)
|
|
192
265
|
for row in connection.execute(
|
|
193
266
|
"""
|
|
194
|
-
SELECT id, author, content, tools, thinking, status
|
|
267
|
+
SELECT id, author, content, tools, thinking, groups, status
|
|
195
268
|
FROM messages
|
|
196
269
|
ORDER BY position, id
|
|
197
270
|
"""
|
|
@@ -203,6 +276,7 @@ class StateStore:
|
|
|
203
276
|
messages=messages,
|
|
204
277
|
providers=providers,
|
|
205
278
|
settings=StoredSettings(
|
|
279
|
+
agent_prompt=settings_row["agent_prompt"] if settings_row else "",
|
|
206
280
|
reasoning_effort=settings_row["reasoning_effort"]
|
|
207
281
|
if settings_row
|
|
208
282
|
else ReasoningEffort.DEFAULT,
|
|
@@ -503,19 +577,22 @@ class StateStore:
|
|
|
503
577
|
id,
|
|
504
578
|
selected_provider_id,
|
|
505
579
|
selected_model,
|
|
506
|
-
reasoning_effort
|
|
580
|
+
reasoning_effort,
|
|
581
|
+
agent_prompt
|
|
507
582
|
)
|
|
508
|
-
VALUES (1, ?, ?, ?)
|
|
583
|
+
VALUES (1, ?, ?, ?, ?)
|
|
509
584
|
ON CONFLICT(id) DO UPDATE SET
|
|
510
585
|
selected_provider_id = excluded.selected_provider_id,
|
|
511
586
|
selected_model = excluded.selected_model,
|
|
512
587
|
reasoning_effort = excluded.reasoning_effort,
|
|
588
|
+
agent_prompt = excluded.agent_prompt,
|
|
513
589
|
updated_at = unixepoch()
|
|
514
590
|
""",
|
|
515
591
|
(
|
|
516
592
|
settings.selected_provider_id,
|
|
517
593
|
settings.selected_model,
|
|
518
594
|
settings.reasoning_effort.value,
|
|
595
|
+
settings.agent_prompt,
|
|
519
596
|
),
|
|
520
597
|
)
|
|
521
598
|
return settings
|
|
@@ -525,8 +602,17 @@ class StateStore:
|
|
|
525
602
|
connection.execute("DELETE FROM messages")
|
|
526
603
|
connection.executemany(
|
|
527
604
|
"""
|
|
528
|
-
INSERT INTO messages (
|
|
529
|
-
|
|
605
|
+
INSERT INTO messages (
|
|
606
|
+
id,
|
|
607
|
+
author,
|
|
608
|
+
content,
|
|
609
|
+
tools,
|
|
610
|
+
thinking,
|
|
611
|
+
groups,
|
|
612
|
+
status,
|
|
613
|
+
position
|
|
614
|
+
)
|
|
615
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
530
616
|
""",
|
|
531
617
|
[
|
|
532
618
|
(
|
|
@@ -540,6 +626,13 @@ class StateStore:
|
|
|
540
626
|
]
|
|
541
627
|
),
|
|
542
628
|
message.thinking,
|
|
629
|
+
json.dumps(
|
|
630
|
+
[
|
|
631
|
+
group.model_dump(exclude_none=True)
|
|
632
|
+
for group in message.groups
|
|
633
|
+
],
|
|
634
|
+
ensure_ascii=False,
|
|
635
|
+
),
|
|
543
636
|
message.status,
|
|
544
637
|
position,
|
|
545
638
|
)
|
|
@@ -564,13 +657,23 @@ class StateStore:
|
|
|
564
657
|
position = position_row["position"]
|
|
565
658
|
connection.execute(
|
|
566
659
|
"""
|
|
567
|
-
INSERT INTO messages (
|
|
568
|
-
|
|
660
|
+
INSERT INTO messages (
|
|
661
|
+
id,
|
|
662
|
+
author,
|
|
663
|
+
content,
|
|
664
|
+
tools,
|
|
665
|
+
thinking,
|
|
666
|
+
groups,
|
|
667
|
+
status,
|
|
668
|
+
position
|
|
669
|
+
)
|
|
670
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
569
671
|
ON CONFLICT(id) DO UPDATE SET
|
|
570
672
|
author = excluded.author,
|
|
571
673
|
content = excluded.content,
|
|
572
674
|
tools = excluded.tools,
|
|
573
675
|
thinking = excluded.thinking,
|
|
676
|
+
groups = excluded.groups,
|
|
574
677
|
status = excluded.status,
|
|
575
678
|
position = excluded.position
|
|
576
679
|
""",
|
|
@@ -582,6 +685,13 @@ class StateStore:
|
|
|
582
685
|
[tool.model_dump(exclude_none=True) for tool in message.tools]
|
|
583
686
|
),
|
|
584
687
|
message.thinking,
|
|
688
|
+
json.dumps(
|
|
689
|
+
[
|
|
690
|
+
group.model_dump(exclude_none=True)
|
|
691
|
+
for group in message.groups
|
|
692
|
+
],
|
|
693
|
+
ensure_ascii=False,
|
|
694
|
+
),
|
|
585
695
|
message.status,
|
|
586
696
|
position,
|
|
587
697
|
),
|
|
@@ -607,12 +717,120 @@ class StateStore:
|
|
|
607
717
|
VALUES (1, ?)
|
|
608
718
|
ON CONFLICT(id) DO UPDATE SET
|
|
609
719
|
compacted_summary = excluded.compacted_summary,
|
|
720
|
+
active_compaction_id = NULL,
|
|
610
721
|
updated_at = unixepoch()
|
|
611
722
|
""",
|
|
612
723
|
(summary,),
|
|
613
724
|
)
|
|
614
725
|
return summary
|
|
615
726
|
|
|
727
|
+
def read_active_compaction_checkpoint(
|
|
728
|
+
self,
|
|
729
|
+
) -> StoredCompactionCheckpoint | None:
|
|
730
|
+
with self.connect() as connection:
|
|
731
|
+
row = connection.execute(
|
|
732
|
+
"""
|
|
733
|
+
SELECT
|
|
734
|
+
checkpoint.id,
|
|
735
|
+
checkpoint.trigger,
|
|
736
|
+
checkpoint.method,
|
|
737
|
+
checkpoint.summary,
|
|
738
|
+
checkpoint.replacement_history,
|
|
739
|
+
checkpoint.source_message_id,
|
|
740
|
+
checkpoint.token_before,
|
|
741
|
+
checkpoint.token_after,
|
|
742
|
+
checkpoint.created_at
|
|
743
|
+
FROM workspace_context context
|
|
744
|
+
JOIN compaction_checkpoints checkpoint
|
|
745
|
+
ON checkpoint.id = context.active_compaction_id
|
|
746
|
+
WHERE context.id = 1
|
|
747
|
+
"""
|
|
748
|
+
).fetchone()
|
|
749
|
+
if row is None:
|
|
750
|
+
return None
|
|
751
|
+
return StoredCompactionCheckpoint(
|
|
752
|
+
created_at=row["created_at"],
|
|
753
|
+
id=row["id"],
|
|
754
|
+
method=row["method"],
|
|
755
|
+
replacement_history=[
|
|
756
|
+
ChatMessage.model_validate(message)
|
|
757
|
+
for message in json.loads(row["replacement_history"] or "[]")
|
|
758
|
+
],
|
|
759
|
+
source_message_id=row["source_message_id"],
|
|
760
|
+
summary=row["summary"],
|
|
761
|
+
token_after=row["token_after"],
|
|
762
|
+
token_before=row["token_before"],
|
|
763
|
+
trigger=row["trigger"],
|
|
764
|
+
)
|
|
765
|
+
|
|
766
|
+
def save_compaction_checkpoint(
|
|
767
|
+
self, checkpoint: StoredCompactionCheckpoint
|
|
768
|
+
) -> StoredCompactionCheckpoint:
|
|
769
|
+
with self.connect() as connection:
|
|
770
|
+
connection.execute(
|
|
771
|
+
"""
|
|
772
|
+
INSERT INTO compaction_checkpoints (
|
|
773
|
+
id,
|
|
774
|
+
trigger,
|
|
775
|
+
method,
|
|
776
|
+
summary,
|
|
777
|
+
replacement_history,
|
|
778
|
+
source_message_id,
|
|
779
|
+
token_before,
|
|
780
|
+
token_after
|
|
781
|
+
)
|
|
782
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
783
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
784
|
+
trigger = excluded.trigger,
|
|
785
|
+
method = excluded.method,
|
|
786
|
+
summary = excluded.summary,
|
|
787
|
+
replacement_history = excluded.replacement_history,
|
|
788
|
+
source_message_id = excluded.source_message_id,
|
|
789
|
+
token_before = excluded.token_before,
|
|
790
|
+
token_after = excluded.token_after
|
|
791
|
+
""",
|
|
792
|
+
(
|
|
793
|
+
checkpoint.id,
|
|
794
|
+
checkpoint.trigger,
|
|
795
|
+
checkpoint.method,
|
|
796
|
+
checkpoint.summary,
|
|
797
|
+
json.dumps(
|
|
798
|
+
[
|
|
799
|
+
message.model_dump()
|
|
800
|
+
for message in checkpoint.replacement_history
|
|
801
|
+
],
|
|
802
|
+
ensure_ascii=False,
|
|
803
|
+
),
|
|
804
|
+
checkpoint.source_message_id,
|
|
805
|
+
checkpoint.token_before,
|
|
806
|
+
checkpoint.token_after,
|
|
807
|
+
),
|
|
808
|
+
)
|
|
809
|
+
connection.execute(
|
|
810
|
+
"""
|
|
811
|
+
INSERT INTO workspace_context (
|
|
812
|
+
id,
|
|
813
|
+
compacted_summary,
|
|
814
|
+
active_compaction_id
|
|
815
|
+
)
|
|
816
|
+
VALUES (1, ?, ?)
|
|
817
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
818
|
+
compacted_summary = excluded.compacted_summary,
|
|
819
|
+
active_compaction_id = excluded.active_compaction_id,
|
|
820
|
+
updated_at = unixepoch()
|
|
821
|
+
""",
|
|
822
|
+
(checkpoint.summary, checkpoint.id),
|
|
823
|
+
)
|
|
824
|
+
row = connection.execute(
|
|
825
|
+
"""
|
|
826
|
+
SELECT created_at
|
|
827
|
+
FROM compaction_checkpoints
|
|
828
|
+
WHERE id = ?
|
|
829
|
+
""",
|
|
830
|
+
(checkpoint.id,),
|
|
831
|
+
).fetchone()
|
|
832
|
+
return checkpoint.model_copy(update={"created_at": row["created_at"]})
|
|
833
|
+
|
|
616
834
|
def _provider_models(
|
|
617
835
|
self, connection: sqlite3.Connection, provider_id: str
|
|
618
836
|
) -> list[str]:
|
|
@@ -793,6 +1011,7 @@ class StateStore:
|
|
|
793
1011
|
selected_provider_id TEXT NOT NULL DEFAULT '',
|
|
794
1012
|
selected_model TEXT NOT NULL DEFAULT '',
|
|
795
1013
|
reasoning_effort TEXT NOT NULL DEFAULT 'default',
|
|
1014
|
+
agent_prompt TEXT NOT NULL DEFAULT '',
|
|
796
1015
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
797
1016
|
);
|
|
798
1017
|
|
|
@@ -807,9 +1026,22 @@ class StateStore:
|
|
|
807
1026
|
CREATE TABLE IF NOT EXISTS workspace_context (
|
|
808
1027
|
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
809
1028
|
compacted_summary TEXT NOT NULL DEFAULT '',
|
|
1029
|
+
active_compaction_id TEXT,
|
|
810
1030
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
811
1031
|
);
|
|
812
1032
|
|
|
1033
|
+
CREATE TABLE IF NOT EXISTS compaction_checkpoints (
|
|
1034
|
+
id TEXT PRIMARY KEY,
|
|
1035
|
+
trigger TEXT NOT NULL,
|
|
1036
|
+
method TEXT NOT NULL,
|
|
1037
|
+
summary TEXT NOT NULL,
|
|
1038
|
+
replacement_history TEXT NOT NULL DEFAULT '[]',
|
|
1039
|
+
source_message_id TEXT,
|
|
1040
|
+
token_before INTEGER NOT NULL DEFAULT 0,
|
|
1041
|
+
token_after INTEGER NOT NULL DEFAULT 0,
|
|
1042
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
1043
|
+
);
|
|
1044
|
+
|
|
813
1045
|
CREATE TABLE IF NOT EXISTS skill_settings (
|
|
814
1046
|
id TEXT PRIMARY KEY,
|
|
815
1047
|
enabled INTEGER NOT NULL DEFAULT 1,
|
|
@@ -853,6 +1085,10 @@ class StateStore:
|
|
|
853
1085
|
connection.execute(
|
|
854
1086
|
"ALTER TABLE messages ADD COLUMN status TEXT NOT NULL DEFAULT 'completed'"
|
|
855
1087
|
)
|
|
1088
|
+
if "groups" not in columns:
|
|
1089
|
+
connection.execute(
|
|
1090
|
+
"ALTER TABLE messages ADD COLUMN groups TEXT NOT NULL DEFAULT '[]'"
|
|
1091
|
+
)
|
|
856
1092
|
settings_columns = {
|
|
857
1093
|
row["name"] for row in connection.execute("PRAGMA table_info(settings)")
|
|
858
1094
|
}
|
|
@@ -861,3 +1097,15 @@ class StateStore:
|
|
|
861
1097
|
"ALTER TABLE settings "
|
|
862
1098
|
"ADD COLUMN reasoning_effort TEXT NOT NULL DEFAULT 'default'"
|
|
863
1099
|
)
|
|
1100
|
+
if "agent_prompt" not in settings_columns:
|
|
1101
|
+
connection.execute(
|
|
1102
|
+
"ALTER TABLE settings ADD COLUMN agent_prompt TEXT NOT NULL DEFAULT ''"
|
|
1103
|
+
)
|
|
1104
|
+
workspace_context_columns = {
|
|
1105
|
+
row["name"]
|
|
1106
|
+
for row in connection.execute("PRAGMA table_info(workspace_context)")
|
|
1107
|
+
}
|
|
1108
|
+
if "active_compaction_id" not in workspace_context_columns:
|
|
1109
|
+
connection.execute(
|
|
1110
|
+
"ALTER TABLE workspace_context ADD COLUMN active_compaction_id TEXT"
|
|
1111
|
+
)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|