alissa-tools-github-devloop 0.8.5__tar.gz → 0.8.7__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.
- {alissa_tools_github_devloop-0.8.5/src/main/alissa_tools_github_devloop.egg-info → alissa_tools_github_devloop-0.8.7}/PKG-INFO +1 -1
- alissa_tools_github_devloop-0.8.7/src/main/alissa/tools/github/devloop/version +1 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/webui/sources.py +62 -13
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7/src/main/alissa_tools_github_devloop.egg-info}/PKG-INFO +1 -1
- alissa_tools_github_devloop-0.8.5/src/main/alissa/tools/github/devloop/version +0 -1
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/LICENSE +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/MANIFEST.in +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/NOTICE +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/README.md +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/requirements.txt +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/setup.cfg +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/setup.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/__init__.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/__main__.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/alissa.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/config.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/ghclient.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/janitor.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/loop.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/proc.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/state.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/version.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/webui/__init__.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/webui/__main__.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/webui/auth.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/webui/page.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/webui/server.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa/tools/github/devloop/webui/sysinfo.py +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa_tools_github_devloop.egg-info/SOURCES.txt +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa_tools_github_devloop.egg-info/dependency_links.txt +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa_tools_github_devloop.egg-info/entry_points.txt +0 -0
- {alissa_tools_github_devloop-0.8.5 → alissa_tools_github_devloop-0.8.7}/src/main/alissa_tools_github_devloop.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.8.7
|
|
@@ -8,10 +8,12 @@ in strict budget order:
|
|
|
8
8
|
call: the daemon already wrote everything down.
|
|
9
9
|
2. **Local process state** -- `alissa tmux ls --json` for the session list, and
|
|
10
10
|
a `/proc` walk (sysinfo) of each session's pane-PID tree for CPU%/RSS.
|
|
11
|
-
3. **
|
|
12
|
-
meter,
|
|
13
|
-
chip
|
|
14
|
-
|
|
11
|
+
3. **Three cached remote checks** -- `gh api rate_limit` (60s cache) for the
|
|
12
|
+
rate meter, the PyPI version JSON (10m cache) for the running-vs-latest
|
|
13
|
+
drift chip, and `alissa task list` (5m cache, self-scoped where the CLI
|
|
14
|
+
allows it) for the tasks pane. These are the *only* network calls, and all
|
|
15
|
+
three are cached so a room full of refreshing operators cannot move the
|
|
16
|
+
daemon's rate budget -- nor the sponsor's.
|
|
15
17
|
4. **Config echo + log tail** -- the effective config the daemon resolved, and
|
|
16
18
|
the tail of its log file.
|
|
17
19
|
|
|
@@ -49,7 +51,14 @@ RATE_CACHE_TTL = 60.0
|
|
|
49
51
|
VERSION_CACHE_TTL = 600.0
|
|
50
52
|
# `alissa task list` rides the shared ALISSA_API_TOKEN, so it is cached like the
|
|
51
53
|
# other remote checks to keep a room of open tabs off the daemon's rate budget.
|
|
52
|
-
|
|
54
|
+
# Five minutes rather than the rate meter's sixty seconds: the pane is a
|
|
55
|
+
# monitoring glance, not a live feed, and every uncached read is served
|
|
56
|
+
# sponsor-scoped -- a tab left open on the 60s TTL paid the sponsor's entire
|
|
57
|
+
# non-terminal task corpus 1,440x/day.
|
|
58
|
+
TASKS_CACHE_TTL = 300.0
|
|
59
|
+
# The flag that narrows `alissa task list` to the calling actor's own rows
|
|
60
|
+
# instead of the sponsor's corpus. Newer CLIs only -- see `_supports_self_scope`.
|
|
61
|
+
TASKS_SELF_FLAG = "--self"
|
|
53
62
|
# PyPI JSON endpoint for the running-vs-latest drift chip.
|
|
54
63
|
PYPI_URL = "https://pypi.org/pypi/alissa-tools-github-devloop/json"
|
|
55
64
|
# How many minutes past the stale window retry-now ages a row: the daemon
|
|
@@ -132,6 +141,8 @@ class Sources:
|
|
|
132
141
|
self._rate_cache = _Cache(RATE_CACHE_TTL, clock)
|
|
133
142
|
self._version_cache = _Cache(VERSION_CACHE_TTL, clock)
|
|
134
143
|
self._tasks_cache = _Cache(TASKS_CACHE_TTL, clock)
|
|
144
|
+
# Tri-state: None = not probed yet (see `_supports_self_scope`).
|
|
145
|
+
self._self_scope: "bool | None" = None
|
|
135
146
|
self.boot_wall = int(wall_clock())
|
|
136
147
|
|
|
137
148
|
# -- thin, failure-tolerant subprocess helpers -------------------------
|
|
@@ -160,9 +171,9 @@ class Sources:
|
|
|
160
171
|
with a daemon write and raise `sqlite3.OperationalError` (State's
|
|
161
172
|
default 5s busy_timeout narrows this window but does not close it, and
|
|
162
173
|
a corrupt db raises regardless). Catching here honors this module's
|
|
163
|
-
contract (
|
|
164
|
-
blank the dashboard or 500 the retry
|
|
165
|
-
other source."""
|
|
174
|
+
failure-tolerance contract (the module docstring): a state access never
|
|
175
|
+
raises an exception that would blank the dashboard or 500 the retry
|
|
176
|
+
action -- it degrades like every other source."""
|
|
166
177
|
try:
|
|
167
178
|
with State(self.config.state_db) as st:
|
|
168
179
|
return fn(st)
|
|
@@ -239,19 +250,57 @@ class Sources:
|
|
|
239
250
|
)
|
|
240
251
|
return out
|
|
241
252
|
|
|
253
|
+
def _supports_self_scope(self) -> bool:
|
|
254
|
+
"""Whether the installed `alissa` CLI understands `task list --self`.
|
|
255
|
+
|
|
256
|
+
Read off the CLI's own `--help`, which is local, tokenless and free.
|
|
257
|
+
The alternative -- send the flag and fall back when the call fails --
|
|
258
|
+
cannot tell an unknown flag from an auth hiccup, so it would spend a
|
|
259
|
+
second sponsor-scoped call on every unlucky refresh, which is the cost
|
|
260
|
+
this whole path exists to avoid.
|
|
261
|
+
|
|
262
|
+
A probe that *answers* is memoized for the process (the CLI cannot
|
|
263
|
+
change under a running console). A probe that fails is deliberately
|
|
264
|
+
NOT memoized: a transient `alissa` failure then degrades this refresh
|
|
265
|
+
only, instead of pinning the console to the expensive unscoped call
|
|
266
|
+
until someone restarts it."""
|
|
267
|
+
if self._self_scope is None:
|
|
268
|
+
helptext = self._safe_run(
|
|
269
|
+
["alissa", "task", "list", "--help"], timeout=20
|
|
270
|
+
)
|
|
271
|
+
if helptext is None:
|
|
272
|
+
return False
|
|
273
|
+
self._self_scope = TASKS_SELF_FLAG in helptext
|
|
274
|
+
return self._self_scope
|
|
275
|
+
|
|
242
276
|
def worker_tasks(self, limit: int = 25) -> "list[dict]":
|
|
243
277
|
"""The worker actor's own tasks via `alissa task list` -- the
|
|
244
278
|
actor-partition bridge (the console runs as the operator, whose actor
|
|
245
279
|
owns the implementation tasks the dev sessions created). Best-effort:
|
|
246
280
|
an old CLI or an auth hiccup just yields an empty list.
|
|
247
281
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
282
|
+
Self-scoped (`--self`) wherever the installed CLI offers it, so a poll
|
|
283
|
+
reads the console actor's own rows rather than the sponsor's whole
|
|
284
|
+
non-terminal corpus -- the pane only ever displays the former. An
|
|
285
|
+
older CLI, or a `--self` call that comes back empty-handed, degrades to
|
|
286
|
+
the unflagged call: a slower, larger read beats a blank pane.
|
|
287
|
+
|
|
288
|
+
Cached (TASKS_CACHE_TTL) exactly like the two other remote checks: this
|
|
289
|
+
call rides the shared ALISSA_API_TOKEN the daemon uses, so on the ~10s
|
|
290
|
+
poll an unbounded call per open tab would contend with the daemon for
|
|
291
|
+
the API budget. A fetch that fails returns None and keeps the last good
|
|
252
292
|
list (the _Cache contract), never overwriting it with junk."""
|
|
253
293
|
def fetch() -> "list[dict] | None":
|
|
254
|
-
|
|
294
|
+
unscoped = ["alissa", "task", "list", "--json"]
|
|
295
|
+
self_scoped = self._supports_self_scope()
|
|
296
|
+
argv = (unscoped + [TASKS_SELF_FLAG]) if self_scoped else unscoped
|
|
297
|
+
raw = self._safe_json(argv, timeout=45)
|
|
298
|
+
if raw is None and self_scoped:
|
|
299
|
+
# The CLI advertised the flag but the call brought nothing
|
|
300
|
+
# back -- an API that does not serve the scope yet, say. One
|
|
301
|
+
# unflagged retry keeps the pane populated. A valid but empty
|
|
302
|
+
# `[]` is a real answer, not a failure, and is never retried.
|
|
303
|
+
raw = self._safe_json(unscoped, timeout=45)
|
|
255
304
|
if not isinstance(raw, list):
|
|
256
305
|
return None
|
|
257
306
|
rows = [t for t in raw if isinstance(t, dict)]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.8.5
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|