navcli 0.2.3__py3-none-any.whl → 0.2.4__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.
navcli/server/__init__.py CHANGED
@@ -10,7 +10,7 @@ import uvicorn
10
10
  from uvicorn.config import Config
11
11
 
12
12
  from navcli.server.app import create_app
13
- from navcli.server.browser import start_browser, close_browser
13
+ from navcli.server.browser import start_browser, close_browser, _SNAPSHOT_PATH
14
14
 
15
15
  __version__ = "0.1.0"
16
16
 
@@ -115,6 +115,12 @@ def main():
115
115
  print(' nav load_session <name>')
116
116
  else:
117
117
  print("No saved sessions found.")
118
+
119
+ # Auto-save snapshot info
120
+ print(f"\nAuto-save snapshot: {_SNAPSHOT_PATH}")
121
+ if os.path.exists(_SNAPSHOT_PATH):
122
+ print("Session snapshot: Will be loaded on startup (auto)")
123
+
118
124
  print("\nTo save a session after manual login:")
119
125
  print(' curl -X POST "http://localhost:8765/cmd/session/save?name=<name>"')
120
126
  print(' nav save_session <name>')
navcli/server/browser.py CHANGED
@@ -23,6 +23,8 @@ _dom_version: int = 0
23
23
  _NAVCLI_HOME = os.path.expanduser("~/.navcli")
24
24
  _NAVCLI_SESSIONS_DIR = os.path.join(_NAVCLI_HOME, "sessions")
25
25
  _storage_state_path: str = os.path.join(_NAVCLI_SESSIONS_DIR, "session.json") # Default session file
26
+ # Auto-save snapshot path
27
+ _SNAPSHOT_PATH: str = os.path.join(_NAVCLI_HOME, "session_snapshot.json")
26
28
 
27
29
 
28
30
  async def start_browser(headless: bool = True, args: Optional[list] = None):
@@ -66,6 +68,14 @@ async def start_browser(headless: bool = True, args: Optional[list] = None):
66
68
  _context = await _browser.new_context()
67
69
  _page = await _context.new_page()
68
70
 
71
+ # Auto-load session snapshot on startup
72
+ if os.path.exists(_SNAPSHOT_PATH):
73
+ try:
74
+ await load_session(_SNAPSHOT_PATH)
75
+ print(f"[SESSION] Loaded snapshot from {_SNAPSHOT_PATH}")
76
+ except Exception as e:
77
+ print(f"[SESSION] Failed to load snapshot: {e}")
78
+
69
79
 
70
80
  async def close_browser():
71
81
  """Close the browser."""
@@ -119,6 +129,30 @@ async def save_session(path: str = None) -> Dict[str, Any]:
119
129
  return storage_state
120
130
 
121
131
 
132
+ async def auto_save_snapshot() -> None:
133
+ """Auto-save session snapshot to the snapshot file.
134
+
135
+ This is called automatically after page navigation.
136
+ """
137
+ global _SNAPSHOT_PATH
138
+
139
+ if _context is None:
140
+ return
141
+
142
+ try:
143
+ # Ensure directory exists
144
+ os.makedirs(os.path.dirname(_SNAPSHOT_PATH), exist_ok=True)
145
+
146
+ # Get storage state from Playwright
147
+ storage_state = await _context.storage_state()
148
+
149
+ # Save to snapshot file
150
+ with open(_SNAPSHOT_PATH, "w") as f:
151
+ json.dump(storage_state, f, indent=2)
152
+ except Exception:
153
+ pass # Silently fail - session snapshot is not critical
154
+
155
+
122
156
  async def load_session(path: str = None) -> None:
123
157
  """Load session (cookies, localStorage, sessionStorage) from file.
124
158
 
@@ -5,7 +5,7 @@ from typing import Optional
5
5
  from fastapi import APIRouter, HTTPException, Query
6
6
 
7
7
  from navcli.core.models import CommandResult, Feedback
8
- from navcli.server.browser import get_page, get_current_state, start_browser, wait_for_network_idle
8
+ from navcli.server.browser import get_page, get_current_state, start_browser, wait_for_network_idle, auto_save_snapshot
9
9
  from navcli.utils import normalize_url
10
10
 
11
11
  router = APIRouter()
@@ -47,6 +47,9 @@ async def goto(
47
47
  state = await get_current_state()
48
48
  log_progress(f"Page title: {state.title}")
49
49
 
50
+ # Auto-save session snapshot
51
+ await auto_save_snapshot()
52
+
50
53
  return CommandResult(
51
54
  success=True,
52
55
  command="goto",
@@ -77,6 +80,9 @@ async def back() -> CommandResult:
77
80
  state = await get_current_state()
78
81
  log_progress(f"Back to: {state.url}")
79
82
 
83
+ # Auto-save session snapshot
84
+ await auto_save_snapshot()
85
+
80
86
  return CommandResult(
81
87
  success=True,
82
88
  command="back",
@@ -107,6 +113,9 @@ async def forward() -> CommandResult:
107
113
  state = await get_current_state()
108
114
  log_progress(f"Forward to: {state.url}")
109
115
 
116
+ # Auto-save session snapshot
117
+ await auto_save_snapshot()
118
+
110
119
  return CommandResult(
111
120
  success=True,
112
121
  command="forward",
@@ -137,6 +146,9 @@ async def reload() -> CommandResult:
137
146
  state = await get_current_state()
138
147
  log_progress(f"Reloaded: {state.url}")
139
148
 
149
+ # Auto-save session snapshot
150
+ await auto_save_snapshot()
151
+
140
152
  return CommandResult(
141
153
  success=True,
142
154
  command="reload",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: navcli
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: 可交互、可探索的浏览器命令行工具,专为 AI Agent 设计
5
5
  Author: NavCLI Team
6
6
  License: MIT
@@ -14,15 +14,15 @@ navcli/core/models/dom.py,sha256=vZzEpzLEOlCnUJWBWx0-gmHj8WBxorsnPsZJgUW3UOE,116
14
14
  navcli/core/models/element.py,sha256=6L8PnY7h_-_MFweq6NU6gdG1g5_r_AHlW1bYTuUBNoM,747
15
15
  navcli/core/models/feedback.py,sha256=K67nc7fCiAAfeYKDppNEnHtM41fSdF-Ai7IMhvAv7PY,689
16
16
  navcli/core/models/state.py,sha256=6TBh6zMX8uhBcFICNLFgJhPKLRbET47fjZTjvt3n0Hw,1002
17
- navcli/server/__init__.py,sha256=eyUU2kDdtwRwHqhBTJ3vpqp86WAMpBpsnhbniALSa3E,4299
17
+ navcli/server/__init__.py,sha256=oA7KQ_LAClRAwm9ViXuTwpVpuGUTS-6kyNcw1XK0T7I,4523
18
18
  navcli/server/app.py,sha256=lMMXuJzB-7FOGfCXJosoMRV0mP51O2pF24KZDdC4p20,2015
19
- navcli/server/browser.py,sha256=OneOVyd3yQnVSGiY0EU6WZ2RrR0QJa8FbZlWAF6eTF8,12244
19
+ navcli/server/browser.py,sha256=EyRCmvMvYRav9wu9RlWvVHr1wG5un9dTXb-9PAJbzF8,13307
20
20
  navcli/server/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  navcli/server/routes/__init__.py,sha256=LCd1lCcBCqJmFchr9OTvKJvCTQNLETAljdPaou-fd3I,180
22
22
  navcli/server/routes/control.py,sha256=Hn1giy5H-PdpiwY-AiKsFWDNfIYk0erDxbMeksBGqEY,1337
23
23
  navcli/server/routes/explore.py,sha256=3OwNp8vx2fwTdcAXeI2NqBXJ1R9fxQWqoLYPQawS-3Y,13734
24
24
  navcli/server/routes/interaction.py,sha256=8FYGA5yqsJ045oMtsVCJpCsj4ANlcOCTs0Xs8oM4pvA,10194
25
- navcli/server/routes/navigation.py,sha256=U23EtgUFy6FWacwWovrXgwb1PRhp5u1txn1Mt0o7o6I,4277
25
+ navcli/server/routes/navigation.py,sha256=1zZEOkahvGTvshu0yR3FhdV0FOXLPa_BfMp08YWc06c,4589
26
26
  navcli/server/routes/query.py,sha256=icjQoBFGvsbM4PHfejYT15or4YdxlSR0IBYlWHcD9K8,15291
27
27
  navcli/server/routes/session.py,sha256=GgJOem4p-YFqDiITWFC89t1pq9SQ0guY6AI9lMFBFZs,6307
28
28
  navcli/utils/__init__.py,sha256=g3CIjq_xybpmanja9A7oyQMtf9emS6qdHJIJ6BJx6t0,521
@@ -32,8 +32,8 @@ navcli/utils/selector.py,sha256=E_8E5bjjL1gDn524l3bH3XzK3egn9IyoYEb7zXsTwTQ,2146
32
32
  navcli/utils/text.py,sha256=wCFCKCn6Ibi8GjAeGXBHT5CfS8BCs7X9qVxDq4eR1tE,389
33
33
  navcli/utils/time.py,sha256=bAjJ59rp02MkIfoCT1TzmFd_oGaGlOI-5RPiKSqT-kI,1181
34
34
  navcli/utils/url.py,sha256=UG71w8ArYJlqjl2XslwAN-Kk9GJOPK3k5fg6CxXE5js,301
35
- navcli-0.2.3.dist-info/METADATA,sha256=2P48jfzjZt4soPHSXEpsp4EZTyiyaxwvnLsA-wlTVPo,2837
36
- navcli-0.2.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
37
- navcli-0.2.3.dist-info/entry_points.txt,sha256=J26RwbEYUO5UbuhH0aXF_tvQFCOCatAR80blaSn5oWk,72
38
- navcli-0.2.3.dist-info/top_level.txt,sha256=dwTN5Lw7STNP3zhL2-RDElX3EslzM2sbYYLfuszQSO4,7
39
- navcli-0.2.3.dist-info/RECORD,,
35
+ navcli-0.2.4.dist-info/METADATA,sha256=owd7Rt-xmZiO4xNQXOWhc51V5wGCIy5SEYvVk7oykBs,2837
36
+ navcli-0.2.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
37
+ navcli-0.2.4.dist-info/entry_points.txt,sha256=J26RwbEYUO5UbuhH0aXF_tvQFCOCatAR80blaSn5oWk,72
38
+ navcli-0.2.4.dist-info/top_level.txt,sha256=dwTN5Lw7STNP3zhL2-RDElX3EslzM2sbYYLfuszQSO4,7
39
+ navcli-0.2.4.dist-info/RECORD,,
File without changes