linkgravity 1.9.0 → 1.9.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linkgravity",
3
- "version": "1.9.0",
3
+ "version": "1.9.1",
4
4
  "description": "Discord/Telegram bot bridge for the Antigravity (agy) CLI, with voice interaction support",
5
5
  "scripts": {
6
6
  "start": "node npm-scripts/run-dev.js",
@@ -344,7 +344,7 @@ async def agy_new_conversation(
344
344
  args = ["--dangerously-skip-permissions", "--print", content, "--print-timeout", "24h"]
345
345
  if model:
346
346
  args.extend(["--model", clean_model_name(model)])
347
- result_text = await run_agy(*args, stream_queue=stream_queue, thread_id=thread_id, cwd=cwd)
347
+ result_text = await run_agy(*args, timeout=86400, stream_queue=stream_queue, thread_id=thread_id, cwd=cwd)
348
348
  conv_id = await _get_latest_conversation_id()
349
349
  return result_text, conv_id
350
350
 
@@ -360,7 +360,7 @@ async def agy_send_message(
360
360
  args = ["--dangerously-skip-permissions", "--print", content, "--conversation", conv_id, "--print-timeout", "24h"]
361
361
  if model:
362
362
  args.extend(["--model", clean_model_name(model)])
363
- return await run_agy(*args, stream_queue=stream_queue, thread_id=thread_id, cwd=cwd)
363
+ return await run_agy(*args, timeout=86400, stream_queue=stream_queue, thread_id=thread_id, cwd=cwd)
364
364
 
365
365
 
366
366
  def get_current_model() -> str:
@@ -14,6 +14,7 @@ class SessionManager:
14
14
  self.sessions: dict[str, dict] = self._load_sessions()
15
15
  self.active_queues: dict[str, asyncio.Queue] = {}
16
16
  self.active_tts_tasks: dict[str, asyncio.Task] = {}
17
+ self.active_handler_tasks: dict[str, asyncio.Task] = {}
17
18
  self.pending_approvals: dict[str, asyncio.Future] = {}
18
19
  self.pending_approval_types: dict[str, str] = {}
19
20
  self.pending_approval_messages: dict[str, Any] = {}
@@ -121,6 +122,15 @@ class SessionManager:
121
122
  def remove_tts_task(self, thread_id: str):
122
123
  self.active_tts_tasks.pop(str(thread_id), None)
123
124
 
125
+ def get_handler_task(self, thread_id: str) -> asyncio.Task | None:
126
+ return self.active_handler_tasks.get(str(thread_id))
127
+
128
+ def set_handler_task(self, thread_id: str, task: asyncio.Task):
129
+ self.active_handler_tasks[str(thread_id)] = task
130
+
131
+ def remove_handler_task(self, thread_id: str):
132
+ self.active_handler_tasks.pop(str(thread_id), None)
133
+
124
134
  def set_pending_approval(
125
135
  self,
126
136
  approval_key: str,
@@ -133,6 +133,17 @@ async def handle_existing_session(
133
133
  cleanup_images(image_paths)
134
134
 
135
135
 
136
+ async def _run_tracked(thread_id: str, coro) -> None:
137
+ # Registered so /stop can cancel the whole turn, not just the agy process.
138
+ task = asyncio.current_task()
139
+ session_manager.set_handler_task(thread_id, task)
140
+ try:
141
+ await coro
142
+ finally:
143
+ if session_manager.get_handler_task(thread_id) is task:
144
+ session_manager.remove_handler_task(thread_id)
145
+
146
+
136
147
  async def handle_thread_reply(bot, incoming: IncomingMessage):
137
148
  session = session_manager.get_session(incoming.conversation_id)
138
149
  if not session:
@@ -202,10 +213,16 @@ async def handle_thread_reply(bot, incoming: IncomingMessage):
202
213
 
203
214
  if not conv_id:
204
215
  if session.get("status") == "pending":
205
- await handle_pending_session(bot, incoming, session, agy_content, content, image_paths)
216
+ await _run_tracked(
217
+ incoming.conversation_id,
218
+ handle_pending_session(bot, incoming, session, agy_content, content, image_paths),
219
+ )
206
220
  return
207
221
  else:
208
222
  await adapter.send_message(thread, "⚠️ Session ID not found. Start a new session with `/new`.")
209
223
  return
210
224
 
211
- await handle_existing_session(bot, incoming, session, conv_id, agy_content, image_paths)
225
+ await _run_tracked(
226
+ incoming.conversation_id,
227
+ handle_existing_session(bot, incoming, session, conv_id, agy_content, image_paths),
228
+ )