swiftgate-cli 1.0.2__tar.gz → 1.0.4__tar.gz

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.
@@ -0,0 +1 @@
1
+ __pycache__/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: swiftgate-cli
3
- Version: 1.0.2
3
+ Version: 1.0.4
4
4
  Summary: SwiftGate CLI — autonomous bidirectional agent bridge for SwiftGate OS
5
5
  Project-URL: Homepage, https://swiftgate.ai
6
6
  Project-URL: Repository, https://github.com/thetaroot/swiftgate
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "swiftgate-cli"
7
- version = "1.0.2"
7
+ version = "1.0.4"
8
8
  description = "SwiftGate CLI — autonomous bidirectional agent bridge for SwiftGate OS"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -9,11 +9,13 @@ from __future__ import annotations
9
9
 
10
10
  import asyncio
11
11
  import errno
12
+ import fcntl
12
13
  import json
13
14
  import logging
14
15
  import os
15
16
  import pty
16
17
  import signal
18
+ import struct
17
19
  import sys
18
20
  import tty
19
21
  from pathlib import Path
@@ -90,6 +92,18 @@ class AgentBridge:
90
92
  logger.error("Failed to open pty: %s", exc)
91
93
  return False
92
94
 
95
+ # 2.5 Set pty window size to match parent terminal
96
+ try:
97
+ term_size = os.get_terminal_size()
98
+ winsize = struct.pack("HHHH", term_size.lines, term_size.columns, 0, 0)
99
+ fcntl.ioctl(master_fd, termios.TIOCSWINSZ, winsize)
100
+ os.environ["COLUMNS"] = str(term_size.columns)
101
+ os.environ["LINES"] = str(term_size.lines)
102
+ logger.debug("Pty window size set: %dx%d",
103
+ term_size.columns, term_size.lines)
104
+ except (OSError, AttributeError):
105
+ pass
106
+
93
107
  # 3. Fork
94
108
  pid = os.fork()
95
109
  if pid == 0:
@@ -132,7 +146,7 @@ class AgentBridge:
132
146
  if not self._running or self._master_fd is None:
133
147
  return
134
148
 
135
- msg = f"\n# SwiftGate: {count} pending tasks. Run swiftgate_agent_get_task\n"
149
+ msg = f"\nSwiftGate: You have {count} pending tasks. Call swiftgate_agent_get_task\n"
136
150
  try:
137
151
  os.write(self._master_fd, msg.encode("utf-8"))
138
152
  logger.debug("Wake injected for %s (%d pending)", self._slug, count)
@@ -165,6 +179,24 @@ class AgentBridge:
165
179
  except (termios.error, OSError):
166
180
  pass
167
181
 
182
+ # SIGWINCH handler: propagate terminal resize to pty
183
+ old_winch = signal.SIG_DFL
184
+
185
+ def _resize_pty(_sig: int, _frame) -> None:
186
+ try:
187
+ cols, rows = os.get_terminal_size()
188
+ winsize = struct.pack("HHHH", rows, cols, 0, 0)
189
+ fcntl.ioctl(master_fd, termios.TIOCSWINSZ, winsize)
190
+ os.environ["COLUMNS"] = str(cols)
191
+ os.environ["LINES"] = str(rows)
192
+ except OSError:
193
+ pass
194
+
195
+ try:
196
+ old_winch = signal.signal(signal.SIGWINCH, _resize_pty)
197
+ except OSError:
198
+ pass
199
+
168
200
  stop_event = asyncio.Event()
169
201
 
170
202
  def _stdin_to_pty():
@@ -215,6 +247,13 @@ class AgentBridge:
215
247
  except (termios.error, OSError):
216
248
  pass
217
249
 
250
+ # Restore SIGWINCH handler
251
+ if old_winch != signal.SIG_DFL:
252
+ try:
253
+ signal.signal(signal.SIGWINCH, old_winch)
254
+ except OSError:
255
+ pass
256
+
218
257
  # ── Lifecycle ────────────────────────────────────────────────────────────
219
258
 
220
259
  async def wait(self) -> int:
@@ -33,6 +33,12 @@ def _ensure_config_dir() -> None:
33
33
  pass
34
34
 
35
35
 
36
+ def ensure_config_dir() -> Path:
37
+ """Ensure ~/.swiftgate/ exists and return its path."""
38
+ _ensure_config_dir()
39
+ return _CONFIG_DIR
40
+
41
+
36
42
  def _set_permissions(path: Path) -> None:
37
43
  """Set file permissions to 0600 (owner read/write only)."""
38
44
  try:
@@ -18,6 +18,7 @@ from typing import Optional
18
18
  import click
19
19
 
20
20
  from swiftgate_cli.config import (
21
+ ensure_config_dir,
21
22
  is_setup, set_setup, get_server, list_agents as cfg_list_agents,
22
23
  add_agent as cfg_add_agent, remove_agent as cfg_remove_agent,
23
24
  get_agent as cfg_get_agent,
@@ -26,16 +27,19 @@ from swiftgate_cli.api_client import APIClient
26
27
  from swiftgate_cli.sse_listener import SSEWakeListener
27
28
  from swiftgate_cli.agent_bridge import AgentBridge
28
29
 
30
+ _log_dir = ensure_config_dir()
29
31
  logging.basicConfig(
30
32
  level=logging.INFO,
31
33
  format="%(asctime)s [%(name)s] %(levelname)s: %(message)s",
32
34
  datefmt="%H:%M:%S",
35
+ filename=str(_log_dir / "swiftgate-cli.log"),
36
+ filemode="a",
33
37
  )
34
38
  logger = logging.getLogger("swiftgate")
35
39
 
36
40
 
37
41
  @click.group()
38
- @click.version_option(version="1.0.2", prog_name="swiftgate-cli")
42
+ @click.version_option(version="1.0.4", prog_name="swiftgate-cli")
39
43
  def cli():
40
44
  """swiftgate-cli — Autonomous bidirectional agent bridge for SwiftGate OS.
41
45
 
File without changes
File without changes