aline-ai 0.5.10__py3-none-any.whl → 0.5.12__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.
- {aline_ai-0.5.10.dist-info → aline_ai-0.5.12.dist-info}/METADATA +1 -1
- {aline_ai-0.5.10.dist-info → aline_ai-0.5.12.dist-info}/RECORD +13 -13
- realign/__init__.py +1 -1
- realign/claude_hooks/terminal_state.py +14 -6
- realign/commands/init.py +16 -7
- realign/context.py +15 -11
- realign/dashboard/tmux_manager.py +2 -5
- realign/db/migrate_agents.py +15 -9
- realign/db/schema.py +55 -5
- {aline_ai-0.5.10.dist-info → aline_ai-0.5.12.dist-info}/WHEEL +0 -0
- {aline_ai-0.5.10.dist-info → aline_ai-0.5.12.dist-info}/entry_points.txt +0 -0
- {aline_ai-0.5.10.dist-info → aline_ai-0.5.12.dist-info}/licenses/LICENSE +0 -0
- {aline_ai-0.5.10.dist-info → aline_ai-0.5.12.dist-info}/top_level.txt +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
aline_ai-0.5.
|
|
2
|
-
realign/__init__.py,sha256=
|
|
1
|
+
aline_ai-0.5.12.dist-info/licenses/LICENSE,sha256=H8wTqV5IF1oHw_HbBtS1PSDU8G_q81yblEIL_JfV8Vo,1077
|
|
2
|
+
realign/__init__.py,sha256=6cJg0KmEft8KkD6TMW5-Lib2T9w9w105TIzIZ8mfEao,1624
|
|
3
3
|
realign/claude_detector.py,sha256=ZLSJacMo6zzQclXByABKA70UNpstxqIv3fPGqdpA934,2792
|
|
4
4
|
realign/cli.py,sha256=9VS3WbysZ78NRK5EvkJVg8s6Uh2TQjsGX1E9Pl81pHc,31234
|
|
5
5
|
realign/codex_detector.py,sha256=N9ulgMgvTzDfXE4s4vLd6OoS0hT7R6h2bDFFXWa-2hE,4183
|
|
6
6
|
realign/config.py,sha256=lIKZqeOwYc_gHo760lYYX6PnapuKrCWGqT5SA8-PbeA,12044
|
|
7
|
-
realign/context.py,sha256=
|
|
7
|
+
realign/context.py,sha256=8hzgNOg-7_eMW22wt7OM5H9IsmMveKXCv0epG7E0G7w,13917
|
|
8
8
|
realign/file_lock.py,sha256=kLNm1Rra4TCrTMyPM5fwjVascq-CUz2Bzh9HHKtCKOE,3444
|
|
9
9
|
realign/hooks.py,sha256=NR4LgWgkA6npW_B68I7OdCaZNWseYSP7ZbK4Sl5nnTo,74692
|
|
10
10
|
realign/llm_client.py,sha256=KPfJScQvqse-Tm-VpqnZ6C5jvajPl2n4Ddz9sUp7WIY,24564
|
|
@@ -28,7 +28,7 @@ realign/claude_hooks/permission_request_hook.py,sha256=jMN7UtL6bMqHObUCP5A5ysvFr
|
|
|
28
28
|
realign/claude_hooks/permission_request_hook_installer.py,sha256=_8Wr_L5MES7iGukJzcaj4bqR0BH8kFL44U_X4iKtw2Y,7791
|
|
29
29
|
realign/claude_hooks/stop_hook.py,sha256=2nzF2aF1p5teMJ0eV0ALEHD1K-yVj5sSh7UE8xL54ZE,12025
|
|
30
30
|
realign/claude_hooks/stop_hook_installer.py,sha256=uyqKOqpix7CQP64ERBvvh7viSPp_wx_JVGNAX18rKh0,7228
|
|
31
|
-
realign/claude_hooks/terminal_state.py,sha256=
|
|
31
|
+
realign/claude_hooks/terminal_state.py,sha256=i8B6b_2_9ttPEemp7SrGdFRJSa-vm5lc7YSTRTvAWNg,5397
|
|
32
32
|
realign/claude_hooks/user_prompt_submit_hook.py,sha256=WD-UavhBTueN2TPfnZrnPC7DFYGEeptjUEF21EJn7Qo,10312
|
|
33
33
|
realign/claude_hooks/user_prompt_submit_hook_installer.py,sha256=2xLF8yZcE7Iwib9gU-xCkA1NWxNH9Nc5CFKPYK7rtXw,5371
|
|
34
34
|
realign/commands/__init__.py,sha256=sx_ck55oxaoiF4N3LugG0ZXwonUDxeEZ5uHbBKCC7K8,89
|
|
@@ -37,7 +37,7 @@ realign/commands/config.py,sha256=nYnu_h2pk7GODcrzrV04K51D-s7v06FlRXHJ0HJ-gvU,67
|
|
|
37
37
|
realign/commands/context.py,sha256=pM2KfZHVkB-ou4nBhFvKSwnYliLBzwN3zerLyBAbhfE,7095
|
|
38
38
|
realign/commands/export_shares.py,sha256=Djy1aO7MoU1_ewzn6CZ43oNhSEEonV3sTkSQbHgiaKI,135806
|
|
39
39
|
realign/commands/import_shares.py,sha256=ukX8huvLvEM5g0qEIoqrV1-imz1g-r0Jj2FqD-ojrIA,25297
|
|
40
|
-
realign/commands/init.py,sha256=
|
|
40
|
+
realign/commands/init.py,sha256=tQyOX7csS8t9Ils3FKla41pS8_0Kd7I1Y1rz58a83aU,33511
|
|
41
41
|
realign/commands/restore.py,sha256=s2BxQZHxQw9r12NzRVsK20KlGafy5AIoSjWMo5PcnHY,11173
|
|
42
42
|
realign/commands/search.py,sha256=QJrC0hln9sCDFxXbpo0nPGMHXrud18qA5QfRyD0z6fQ,25926
|
|
43
43
|
realign/commands/upgrade.py,sha256=L3PLOUIN5qAQTbkfoVtSsIbbzEezA_xjjk9F1GMVfjw,12781
|
|
@@ -45,7 +45,7 @@ realign/commands/watcher.py,sha256=fWL3kaRkqE03-NtFLaXlx93hJAQrAuNPSoYhOyQZfq8,1
|
|
|
45
45
|
realign/commands/worker.py,sha256=K1DG1uZ--ebKwklHCyIFdN_axoLjL9Onx8Naq-DOZBs,23078
|
|
46
46
|
realign/dashboard/__init__.py,sha256=QZkHTsGityH8UkF8rmvA3xW7dMXNe0swEWr443qfgCM,128
|
|
47
47
|
realign/dashboard/app.py,sha256=jyW6mqmItTy253CPSqInxctkWzkrGEikdy-ikuShQ14,13299
|
|
48
|
-
realign/dashboard/tmux_manager.py,sha256
|
|
48
|
+
realign/dashboard/tmux_manager.py,sha256=Vt_30WNtDg7c_9SEh8xdDtBLJ8kNq6bGSPh5r3VXpg0,26276
|
|
49
49
|
realign/dashboard/screens/__init__.py,sha256=US6sAmQs5VVkH2tFkH_z0WDT4H8cVhLL-JckfSR1yQY,446
|
|
50
50
|
realign/dashboard/screens/create_agent.py,sha256=lpcT1zLq_p02codtHTE8KdbEzCEaNLnk1lqU3QLcXCg,10057
|
|
51
51
|
realign/dashboard/screens/create_event.py,sha256=oiQY1zKpUYnQU-5fQLeuZH9BV5NClE5B5XZIVBYG5A8,5506
|
|
@@ -67,9 +67,9 @@ realign/dashboard/widgets/worker_panel.py,sha256=F_jKWABuCNmjQgeeuCr4KnFRKdY4CLT
|
|
|
67
67
|
realign/db/__init__.py,sha256=65LsNdsq_rkwNC1eg1OAr3HC0ORXtelOh0I8MhNGr-g,3288
|
|
68
68
|
realign/db/base.py,sha256=MIqu08uG8i5atjZ9uF-uc0Rx35ondxCtUPK92hMoHx4,13179
|
|
69
69
|
realign/db/locks.py,sha256=yzCiPJZ4eOQX-Q4mXB6s76U2U7lXAzIBBy1t59w-AVU,1698
|
|
70
|
-
realign/db/migrate_agents.py,sha256=
|
|
70
|
+
realign/db/migrate_agents.py,sha256=cDeVUzKW950dJ0lV74QObHuONqKwErSrXI5akU2vBmQ,9633
|
|
71
71
|
realign/db/migration.py,sha256=af1QFEfIh_qX0pFyXzm5gWFVbQn0sKOUNLSJHlr__FU,13405
|
|
72
|
-
realign/db/schema.py,sha256=
|
|
72
|
+
realign/db/schema.py,sha256=93dfMtw3LgkBMpiUlCQ0EscY9RFsuS8sEBDckH8lGws,25864
|
|
73
73
|
realign/db/sqlite_db.py,sha256=sZXcvEaSu4C_MQ8pF20RUhwsPtBlNr6ANqf8suM5X8E,102660
|
|
74
74
|
realign/events/__init__.py,sha256=IM-NxF4Zk2hYFD07k4WrfNRuuiC9ihGjf4GBpJhjd2E,35
|
|
75
75
|
realign/events/debouncer.py,sha256=U3Q7dYpnMsAgWsW_E_IbSC4lrdEoi6H_SFLGLOAazs4,3062
|
|
@@ -89,8 +89,8 @@ realign/triggers/next_turn_trigger.py,sha256=BpP0PWn4mU1MZd6mv89jWcjs8Jtv0zEWapW
|
|
|
89
89
|
realign/triggers/registry.py,sha256=cb-AVLbYB2pqwfWL3q1DQxLv4kOw7g7m-GshTdfFESc,3827
|
|
90
90
|
realign/triggers/turn_status.py,sha256=wAZEhXDAmDoX5F-ohWfSnZZ0eA6DAJ9svSPiSv_f6sg,6041
|
|
91
91
|
realign/triggers/turn_summary.py,sha256=f3hEUshgv9skJ9AbfWpoYs417lsv_HK2A_vpPjgryO4,4467
|
|
92
|
-
aline_ai-0.5.
|
|
93
|
-
aline_ai-0.5.
|
|
94
|
-
aline_ai-0.5.
|
|
95
|
-
aline_ai-0.5.
|
|
96
|
-
aline_ai-0.5.
|
|
92
|
+
aline_ai-0.5.12.dist-info/METADATA,sha256=bMuapdLKzuZXb45akvIB6w7uhc5jXl31onpetDCEAxQ,1598
|
|
93
|
+
aline_ai-0.5.12.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
94
|
+
aline_ai-0.5.12.dist-info/entry_points.txt,sha256=TvYELpMoWsUTcQdMV8tBHxCbEf_LbK4sESqK3r8PM6Y,78
|
|
95
|
+
aline_ai-0.5.12.dist-info/top_level.txt,sha256=yIL3s2xv9nf1GwD5n71Aq_JEIV4AfzCIDNKBzewuRm4,8
|
|
96
|
+
aline_ai-0.5.12.dist-info/RECORD,,
|
realign/__init__.py
CHANGED
|
@@ -34,6 +34,16 @@ def _read_json(path: Path) -> dict[str, Any]:
|
|
|
34
34
|
return {}
|
|
35
35
|
|
|
36
36
|
|
|
37
|
+
def _get_db():
|
|
38
|
+
"""Get database connection (lazy import to avoid circular deps in hooks)."""
|
|
39
|
+
try:
|
|
40
|
+
from ..db import get_database
|
|
41
|
+
|
|
42
|
+
return get_database(read_only=False)
|
|
43
|
+
except Exception:
|
|
44
|
+
return None
|
|
45
|
+
|
|
46
|
+
|
|
37
47
|
def _write_to_db(
|
|
38
48
|
*,
|
|
39
49
|
terminal_id: str,
|
|
@@ -52,11 +62,9 @@ def _write_to_db(
|
|
|
52
62
|
Returns True if successful, False otherwise.
|
|
53
63
|
"""
|
|
54
64
|
try:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
db = SQLiteDatabase(str(db_path))
|
|
59
|
-
db.initialize()
|
|
65
|
+
db = _get_db()
|
|
66
|
+
if not db:
|
|
67
|
+
return False
|
|
60
68
|
|
|
61
69
|
# Check if agent exists
|
|
62
70
|
existing = db.get_agent_by_id(terminal_id)
|
|
@@ -88,7 +96,7 @@ def _write_to_db(
|
|
|
88
96
|
source=source if source else None,
|
|
89
97
|
attention=attention,
|
|
90
98
|
)
|
|
91
|
-
|
|
99
|
+
# Note: Don't close - get_database() returns a singleton
|
|
92
100
|
return True
|
|
93
101
|
except Exception:
|
|
94
102
|
return False
|
realign/commands/init.py
CHANGED
|
@@ -19,7 +19,7 @@ console = Console()
|
|
|
19
19
|
# tmux config template for Aline-managed dashboard sessions.
|
|
20
20
|
# Stored at ~/.aline/tmux/tmux.conf and sourced by the dashboard tmux bootstrap.
|
|
21
21
|
# Bump this version when the tmux config changes to trigger auto-update on `aline init`.
|
|
22
|
-
_TMUX_CONFIG_VERSION =
|
|
22
|
+
_TMUX_CONFIG_VERSION = 8
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def _get_tmux_config() -> str:
|
|
@@ -53,16 +53,25 @@ set -s escape-time 0
|
|
|
53
53
|
# Better scrolling: enter copy-mode with -e so scrolling to bottom exits it.
|
|
54
54
|
bind-key -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'copy-mode -e -t ='"
|
|
55
55
|
|
|
56
|
-
# macOS clipboard
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
' ''
|
|
56
|
+
# macOS clipboard: copy selection to clipboard when drag ends.
|
|
57
|
+
# Use copy-pipe-no-clear to preserve selection highlight after copying.
|
|
58
|
+
bind -T copy-mode-vi MouseDragEnd1Pane send -X copy-pipe-no-clear "pbcopy"
|
|
59
|
+
bind -T copy-mode MouseDragEnd1Pane send -X copy-pipe-no-clear "pbcopy"
|
|
61
60
|
|
|
62
|
-
#
|
|
61
|
+
# MouseDrag1Pane: Clear old selection and start new one when dragging begins.
|
|
62
|
+
# This ensures selection only clears when starting a NEW drag, not on click.
|
|
63
|
+
bind -T copy-mode-vi MouseDrag1Pane select-pane \; send -X clear-selection \; send -X begin-selection
|
|
64
|
+
bind -T copy-mode MouseDrag1Pane select-pane \; send -X clear-selection \; send -X begin-selection
|
|
65
|
+
|
|
66
|
+
# MouseDown1Pane: Click clears selection but stays in copy-mode (no scroll).
|
|
67
|
+
# To exit copy-mode: scroll to bottom (auto-exit) or press q/Escape.
|
|
63
68
|
bind -T copy-mode-vi MouseDown1Pane select-pane \; send -X clear-selection
|
|
64
69
|
bind -T copy-mode MouseDown1Pane select-pane \; send -X clear-selection
|
|
65
70
|
|
|
71
|
+
# Escape key: exit copy-mode (also use this before Cmd+V paste in copy-mode).
|
|
72
|
+
bind -T copy-mode-vi Escape send -X cancel
|
|
73
|
+
bind -T copy-mode Escape send -X cancel
|
|
74
|
+
|
|
66
75
|
# Type-to-Exit: Typing any alphanumeric character exits copy-mode and sends the key.
|
|
67
76
|
"""
|
|
68
77
|
def _tmux_quote(value: str) -> str:
|
realign/context.py
CHANGED
|
@@ -23,12 +23,19 @@ CONTEXT_ID_ENV_VAR = "ALINE_CONTEXT_ID"
|
|
|
23
23
|
def _get_db():
|
|
24
24
|
"""Get database connection (lazy import to avoid circular deps)."""
|
|
25
25
|
try:
|
|
26
|
-
from .db
|
|
26
|
+
from .db import get_database
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
return get_database(read_only=False)
|
|
29
|
+
except Exception:
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _get_db_readonly():
|
|
34
|
+
"""Get read-only database connection."""
|
|
35
|
+
try:
|
|
36
|
+
from .db import get_database
|
|
37
|
+
|
|
38
|
+
return get_database(read_only=True)
|
|
32
39
|
except Exception:
|
|
33
40
|
return None
|
|
34
41
|
|
|
@@ -95,13 +102,12 @@ class ContextConfig:
|
|
|
95
102
|
def _load_context_config_from_db() -> Optional[ContextConfig]:
|
|
96
103
|
"""Load context configuration from database (best-effort)."""
|
|
97
104
|
try:
|
|
98
|
-
db =
|
|
105
|
+
db = _get_db_readonly()
|
|
99
106
|
if not db:
|
|
100
107
|
return None
|
|
101
108
|
|
|
102
109
|
db_contexts = db.list_agent_contexts(limit=100)
|
|
103
110
|
if not db_contexts:
|
|
104
|
-
db.close()
|
|
105
111
|
return None
|
|
106
112
|
|
|
107
113
|
contexts = []
|
|
@@ -115,7 +121,6 @@ def _load_context_config_from_db() -> Optional[ContextConfig]:
|
|
|
115
121
|
)
|
|
116
122
|
contexts.append(entry)
|
|
117
123
|
|
|
118
|
-
db.close()
|
|
119
124
|
return ContextConfig(contexts=contexts)
|
|
120
125
|
except Exception:
|
|
121
126
|
return None
|
|
@@ -190,7 +195,7 @@ def _sync_context_to_db(entry: ContextEntry) -> bool:
|
|
|
190
195
|
else:
|
|
191
196
|
db.set_agent_context_events(entry.context_id, [])
|
|
192
197
|
|
|
193
|
-
|
|
198
|
+
# Note: Don't close - get_database() returns a singleton
|
|
194
199
|
return True
|
|
195
200
|
except Exception:
|
|
196
201
|
return False
|
|
@@ -439,10 +444,9 @@ def get_context_by_id(
|
|
|
439
444
|
"""
|
|
440
445
|
# Phase 1: Try to load from database
|
|
441
446
|
try:
|
|
442
|
-
db =
|
|
447
|
+
db = _get_db_readonly()
|
|
443
448
|
if db:
|
|
444
449
|
ctx = db.get_agent_context_by_id(context_id)
|
|
445
|
-
db.close()
|
|
446
450
|
if ctx:
|
|
447
451
|
return ContextEntry(
|
|
448
452
|
context_sessions=ctx.session_ids or [],
|
|
@@ -194,13 +194,10 @@ def _session_id_from_transcript_path(transcript_path: str | None) -> str | None:
|
|
|
194
194
|
def _load_terminal_state_from_db() -> dict[str, dict[str, str]]:
|
|
195
195
|
"""Load terminal state from database (best-effort)."""
|
|
196
196
|
try:
|
|
197
|
-
from ..db
|
|
198
|
-
|
|
199
|
-
db_path = Path.home() / ".aline" / "realign.db"
|
|
200
|
-
db = SQLiteDatabase(str(db_path), read_only=True)
|
|
197
|
+
from ..db import get_database
|
|
201
198
|
|
|
199
|
+
db = get_database(read_only=True)
|
|
202
200
|
agents = db.list_agents(status="active", limit=100)
|
|
203
|
-
db.close()
|
|
204
201
|
|
|
205
202
|
out: dict[str, dict[str, str]] = {}
|
|
206
203
|
for agent in agents:
|
realign/db/migrate_agents.py
CHANGED
|
@@ -240,8 +240,8 @@ def main():
|
|
|
240
240
|
parser.add_argument(
|
|
241
241
|
"--db-path",
|
|
242
242
|
type=str,
|
|
243
|
-
default=
|
|
244
|
-
help="Path to SQLite database",
|
|
243
|
+
default=None,
|
|
244
|
+
help="Path to SQLite database (uses config default if not specified)",
|
|
245
245
|
)
|
|
246
246
|
|
|
247
247
|
args = parser.parse_args()
|
|
@@ -262,13 +262,19 @@ def main():
|
|
|
262
262
|
|
|
263
263
|
# Initialize database
|
|
264
264
|
if not args.dry_run:
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
265
|
+
if args.db_path:
|
|
266
|
+
from .sqlite_db import SQLiteDatabase
|
|
267
|
+
|
|
268
|
+
print(f"\n[step] Initializing database at {args.db_path}")
|
|
269
|
+
db = SQLiteDatabase(args.db_path)
|
|
270
|
+
if not db.initialize():
|
|
271
|
+
print("[error] Database initialization failed")
|
|
272
|
+
sys.exit(1)
|
|
273
|
+
else:
|
|
274
|
+
from . import get_database
|
|
275
|
+
|
|
276
|
+
print("\n[step] Using configured database path")
|
|
277
|
+
db = get_database(read_only=False)
|
|
272
278
|
else:
|
|
273
279
|
db = None
|
|
274
280
|
|
realign/db/schema.py
CHANGED
|
@@ -58,9 +58,13 @@ Schema V15: Agents and contexts tables (replaces terminal.json and load.json).
|
|
|
58
58
|
- agent_contexts table: context definitions (replaces load.json)
|
|
59
59
|
- agent_context_sessions table: M2M context-session links
|
|
60
60
|
- agent_context_events table: M2M context-event links
|
|
61
|
+
|
|
62
|
+
Schema V16: Remove FK constraints from agent_context_sessions/events.
|
|
63
|
+
- Context may reference sessions/events not yet imported to DB
|
|
64
|
+
- Recreate M2M tables without FK constraints on session_id/event_id
|
|
61
65
|
"""
|
|
62
66
|
|
|
63
|
-
SCHEMA_VERSION =
|
|
67
|
+
SCHEMA_VERSION = 16
|
|
64
68
|
|
|
65
69
|
FTS_EVENTS_SCRIPTS = [
|
|
66
70
|
# Full Text Search for Events
|
|
@@ -288,10 +292,11 @@ INIT_SCRIPTS = [
|
|
|
288
292
|
""",
|
|
289
293
|
"CREATE INDEX IF NOT EXISTS idx_agent_contexts_workspace ON agent_contexts(workspace);",
|
|
290
294
|
# Agent context sessions (M2M)
|
|
295
|
+
# Note: No FK on session_id - context may reference sessions not yet imported
|
|
291
296
|
"""
|
|
292
297
|
CREATE TABLE IF NOT EXISTS agent_context_sessions (
|
|
293
298
|
context_id TEXT NOT NULL REFERENCES agent_contexts(id) ON DELETE CASCADE,
|
|
294
|
-
session_id TEXT NOT NULL
|
|
299
|
+
session_id TEXT NOT NULL,
|
|
295
300
|
added_at TEXT DEFAULT (datetime('now')),
|
|
296
301
|
PRIMARY KEY (context_id, session_id)
|
|
297
302
|
);
|
|
@@ -299,10 +304,11 @@ INIT_SCRIPTS = [
|
|
|
299
304
|
"CREATE INDEX IF NOT EXISTS idx_agent_context_sessions_context ON agent_context_sessions(context_id);",
|
|
300
305
|
"CREATE INDEX IF NOT EXISTS idx_agent_context_sessions_session ON agent_context_sessions(session_id);",
|
|
301
306
|
# Agent context events (M2M)
|
|
307
|
+
# Note: No FK on event_id - context may reference events not yet created
|
|
302
308
|
"""
|
|
303
309
|
CREATE TABLE IF NOT EXISTS agent_context_events (
|
|
304
310
|
context_id TEXT NOT NULL REFERENCES agent_contexts(id) ON DELETE CASCADE,
|
|
305
|
-
event_id TEXT NOT NULL
|
|
311
|
+
event_id TEXT NOT NULL,
|
|
306
312
|
added_at TEXT DEFAULT (datetime('now')),
|
|
307
313
|
PRIMARY KEY (context_id, event_id)
|
|
308
314
|
);
|
|
@@ -503,10 +509,11 @@ MIGRATION_V14_TO_V15 = [
|
|
|
503
509
|
""",
|
|
504
510
|
"CREATE INDEX IF NOT EXISTS idx_agent_contexts_workspace ON agent_contexts(workspace);",
|
|
505
511
|
# Agent context sessions (M2M)
|
|
512
|
+
# Note: No FK on session_id - context may reference sessions not yet imported
|
|
506
513
|
"""
|
|
507
514
|
CREATE TABLE IF NOT EXISTS agent_context_sessions (
|
|
508
515
|
context_id TEXT NOT NULL REFERENCES agent_contexts(id) ON DELETE CASCADE,
|
|
509
|
-
session_id TEXT NOT NULL
|
|
516
|
+
session_id TEXT NOT NULL,
|
|
510
517
|
added_at TEXT DEFAULT (datetime('now')),
|
|
511
518
|
PRIMARY KEY (context_id, session_id)
|
|
512
519
|
);
|
|
@@ -514,14 +521,51 @@ MIGRATION_V14_TO_V15 = [
|
|
|
514
521
|
"CREATE INDEX IF NOT EXISTS idx_agent_context_sessions_context ON agent_context_sessions(context_id);",
|
|
515
522
|
"CREATE INDEX IF NOT EXISTS idx_agent_context_sessions_session ON agent_context_sessions(session_id);",
|
|
516
523
|
# Agent context events (M2M)
|
|
524
|
+
# Note: No FK on event_id - context may reference events not yet created
|
|
517
525
|
"""
|
|
518
526
|
CREATE TABLE IF NOT EXISTS agent_context_events (
|
|
519
527
|
context_id TEXT NOT NULL REFERENCES agent_contexts(id) ON DELETE CASCADE,
|
|
520
|
-
event_id TEXT NOT NULL
|
|
528
|
+
event_id TEXT NOT NULL,
|
|
529
|
+
added_at TEXT DEFAULT (datetime('now')),
|
|
530
|
+
PRIMARY KEY (context_id, event_id)
|
|
531
|
+
);
|
|
532
|
+
""",
|
|
533
|
+
"CREATE INDEX IF NOT EXISTS idx_agent_context_events_context ON agent_context_events(context_id);",
|
|
534
|
+
"CREATE INDEX IF NOT EXISTS idx_agent_context_events_event ON agent_context_events(event_id);",
|
|
535
|
+
]
|
|
536
|
+
|
|
537
|
+
# V15 to V16: Remove FK constraints from agent_context_sessions/events
|
|
538
|
+
# Context may reference sessions/events not yet in the database
|
|
539
|
+
MIGRATION_V15_TO_V16 = [
|
|
540
|
+
# Step 1: Rename old tables
|
|
541
|
+
"ALTER TABLE agent_context_sessions RENAME TO agent_context_sessions_old;",
|
|
542
|
+
"ALTER TABLE agent_context_events RENAME TO agent_context_events_old;",
|
|
543
|
+
# Step 2: Create new tables without FK constraints on session_id/event_id
|
|
544
|
+
"""
|
|
545
|
+
CREATE TABLE agent_context_sessions (
|
|
546
|
+
context_id TEXT NOT NULL REFERENCES agent_contexts(id) ON DELETE CASCADE,
|
|
547
|
+
session_id TEXT NOT NULL,
|
|
548
|
+
added_at TEXT DEFAULT (datetime('now')),
|
|
549
|
+
PRIMARY KEY (context_id, session_id)
|
|
550
|
+
);
|
|
551
|
+
""",
|
|
552
|
+
"""
|
|
553
|
+
CREATE TABLE agent_context_events (
|
|
554
|
+
context_id TEXT NOT NULL REFERENCES agent_contexts(id) ON DELETE CASCADE,
|
|
555
|
+
event_id TEXT NOT NULL,
|
|
521
556
|
added_at TEXT DEFAULT (datetime('now')),
|
|
522
557
|
PRIMARY KEY (context_id, event_id)
|
|
523
558
|
);
|
|
524
559
|
""",
|
|
560
|
+
# Step 3: Copy data from old tables
|
|
561
|
+
"INSERT INTO agent_context_sessions SELECT * FROM agent_context_sessions_old;",
|
|
562
|
+
"INSERT INTO agent_context_events SELECT * FROM agent_context_events_old;",
|
|
563
|
+
# Step 4: Drop old tables
|
|
564
|
+
"DROP TABLE agent_context_sessions_old;",
|
|
565
|
+
"DROP TABLE agent_context_events_old;",
|
|
566
|
+
# Step 5: Recreate indexes
|
|
567
|
+
"CREATE INDEX IF NOT EXISTS idx_agent_context_sessions_context ON agent_context_sessions(context_id);",
|
|
568
|
+
"CREATE INDEX IF NOT EXISTS idx_agent_context_sessions_session ON agent_context_sessions(session_id);",
|
|
525
569
|
"CREATE INDEX IF NOT EXISTS idx_agent_context_events_context ON agent_context_events(context_id);",
|
|
526
570
|
"CREATE INDEX IF NOT EXISTS idx_agent_context_events_event ON agent_context_events(event_id);",
|
|
527
571
|
]
|
|
@@ -579,4 +623,10 @@ def get_migration_scripts(from_version: int, to_version: int) -> list:
|
|
|
579
623
|
if from_version < 15 and to_version >= 15:
|
|
580
624
|
scripts.extend(MIGRATION_V14_TO_V15)
|
|
581
625
|
|
|
626
|
+
if from_version < 16 and to_version >= 16:
|
|
627
|
+
# Only run V15->V16 if coming from exactly V15 (tables exist with FK)
|
|
628
|
+
# For V14 or earlier, V14_TO_V15 now creates tables without FK
|
|
629
|
+
if from_version == 15:
|
|
630
|
+
scripts.extend(MIGRATION_V15_TO_V16)
|
|
631
|
+
|
|
582
632
|
return scripts
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|