pythinker-code 0.45.0__py3-none-any.whl → 0.46.0__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.
- pythinker_code/CHANGELOG.md +8 -0
- pythinker_code/ui/shell/__init__.py +57 -3
- pythinker_code/ui/shell/prompt.py +21 -0
- pythinker_code/ui/shell/update.py +7 -1
- pythinker_code/web/static/assets/architecture-7EHR7CIX-DuYWmQ8n.js +1 -0
- pythinker_code/web/static/assets/{architectureDiagram-3BPJPVTR-Cmrv4t4A.js → architectureDiagram-3BPJPVTR-UoU1nAk7.js} +1 -1
- pythinker_code/web/static/assets/{blockDiagram-GPEHLZMM-DJtt-l4b.js → blockDiagram-GPEHLZMM-71KoIQeZ.js} +1 -1
- pythinker_code/web/static/assets/{bootstrap-GQDZdCZn.js → bootstrap-B_vGg5Ny.js} +5 -5
- pythinker_code/web/static/assets/{c4Diagram-AAUBKEIU-o0KsSeIT.js → c4Diagram-AAUBKEIU-BuO74dDT.js} +1 -1
- pythinker_code/web/static/assets/channel-6SKWVwR3.js +1 -0
- pythinker_code/web/static/assets/{chunk-2J33WTMH-CVPDc3uI.js → chunk-2J33WTMH-B7JEo7lz.js} +1 -1
- pythinker_code/web/static/assets/{chunk-3OPIFGDE-Tu9TJ8FO.js → chunk-3OPIFGDE-DmL9lwRX.js} +1 -1
- pythinker_code/web/static/assets/{chunk-5ZQYHXKU-CoBmhCur.js → chunk-5ZQYHXKU-CBmTeQHC.js} +1 -1
- pythinker_code/web/static/assets/{chunk-727SXJPM-DByzCodm.js → chunk-727SXJPM-D62jKCyv.js} +1 -1
- pythinker_code/web/static/assets/{chunk-AQP2D5EJ-DclqBNWp.js → chunk-AQP2D5EJ-BynCmQVm.js} +1 -1
- pythinker_code/web/static/assets/{chunk-CSCIHK7Q-CUIX1-rb.js → chunk-CSCIHK7Q-QrY277S-.js} +1 -1
- pythinker_code/web/static/assets/{chunk-JAPRZBRM-gOR8tSRc.js → chunk-JAPRZBRM-DyAuAcwd.js} +4 -4
- pythinker_code/web/static/assets/{chunk-KSCS5N6A-hta5hym2.js → chunk-KSCS5N6A-B-L96nEP.js} +1 -1
- pythinker_code/web/static/assets/{chunk-L5ZTLDWV-cj__FNrg.js → chunk-L5ZTLDWV-Dx2O-osv.js} +1 -1
- pythinker_code/web/static/assets/{chunk-LZXEDZCA-CSHDE7c1.js → chunk-LZXEDZCA-Ud8JWymF.js} +2 -2
- pythinker_code/web/static/assets/{chunk-ND2GUHAM-DMFQO6Cb.js → chunk-ND2GUHAM-D309EoC7.js} +1 -1
- pythinker_code/web/static/assets/{chunk-NZK2D7GU-Cjm014we.js → chunk-NZK2D7GU-CRryXTBY.js} +1 -1
- pythinker_code/web/static/assets/{chunk-O5CBEL6O-BSr1l1Fd.js → chunk-O5CBEL6O-CG1Ia2Dd.js} +1 -1
- pythinker_code/web/static/assets/{chunk-WU5MYG2G-veNzkohb.js → chunk-WU5MYG2G-CufdHSG9.js} +1 -1
- pythinker_code/web/static/assets/classDiagram-4FO5ZUOK-CLfRoPJH.js +1 -0
- pythinker_code/web/static/assets/classDiagram-v2-Q7XG4LA2-CLfRoPJH.js +1 -0
- pythinker_code/web/static/assets/{code-block-IT6T5CEO-DTgIHAkQ.js → code-block-IT6T5CEO-DMzMTNsT.js} +1 -1
- pythinker_code/web/static/assets/{dagre-BM42HDAG-D-_HCbAC.js → dagre-BM42HDAG-DmUINU6q.js} +1 -1
- pythinker_code/web/static/assets/{diagram-2AECGRRQ-CvX58Rpg.js → diagram-2AECGRRQ-P5YMGdQ8.js} +1 -1
- pythinker_code/web/static/assets/{diagram-5GNKFQAL-CsRaiNkg.js → diagram-5GNKFQAL-BaimYqgQ.js} +1 -1
- pythinker_code/web/static/assets/{diagram-KO2AKTUF-Dn6aiXG5.js → diagram-KO2AKTUF-DgpITRK9.js} +1 -1
- pythinker_code/web/static/assets/{diagram-LMA3HP47-DXQlab3r.js → diagram-LMA3HP47-CMnhE9ZH.js} +1 -1
- pythinker_code/web/static/assets/{diagram-OG6HWLK6-BWB_FmTS.js → diagram-OG6HWLK6-BhLWHvOg.js} +1 -1
- pythinker_code/web/static/assets/{dist-C8Q1EY4S.js → dist-DPNOCkje.js} +1 -1
- pythinker_code/web/static/assets/{erDiagram-TEJ5UH35-BrQiudEc.js → erDiagram-TEJ5UH35-CHSdb2VU.js} +1 -1
- pythinker_code/web/static/assets/eventmodeling-FCH6USID-j7ey84Sq.js +1 -0
- pythinker_code/web/static/assets/{flowDiagram-I6XJVG4X-C6jARfsw.js → flowDiagram-I6XJVG4X-FNGh8ANR.js} +1 -1
- pythinker_code/web/static/assets/{ganttDiagram-6RSMTGT7-DH-i7Wci.js → ganttDiagram-6RSMTGT7-BLTimgS0.js} +1 -1
- pythinker_code/web/static/assets/{gitGraph-WXDBUCRP-lU8PeAwh.js → gitGraph-WXDBUCRP-C3Dg6N-n.js} +1 -1
- pythinker_code/web/static/assets/{gitGraphDiagram-PVQCEYII-JOoIM40T.js → gitGraphDiagram-PVQCEYII-BbiwVf9S.js} +1 -1
- pythinker_code/web/static/assets/{index-BJIE96ev.js → index-uSUCKoSL.js} +2 -2
- pythinker_code/web/static/assets/{info-J43DQDTF-B9a8E9HF.js → info-J43DQDTF-BeSMeh6p.js} +1 -1
- pythinker_code/web/static/assets/{infoDiagram-5YYISTIA-D5wmE10q.js → infoDiagram-5YYISTIA-BQxCJcq4.js} +1 -1
- pythinker_code/web/static/assets/{ishikawaDiagram-YF4QCWOH-DzNdTJqt.js → ishikawaDiagram-YF4QCWOH-KaeLGrsH.js} +1 -1
- pythinker_code/web/static/assets/{journeyDiagram-JHISSGLW-CwevEltw.js → journeyDiagram-JHISSGLW-Kk2DXiQI.js} +1 -1
- pythinker_code/web/static/assets/{kanban-definition-UN3LZRKU-BAmLyJgC.js → kanban-definition-UN3LZRKU-zn_6z8FY.js} +1 -1
- pythinker_code/web/static/assets/{line-CktbshjS.js → line-DCLS_X1f.js} +1 -1
- pythinker_code/web/static/assets/mermaid-VLURNSYL-BOvErqSv.js +1 -0
- pythinker_code/web/static/assets/{mermaid-parser.core-B1Hc3VHx.js → mermaid-parser.core-C_SVA4S7.js} +2 -2
- pythinker_code/web/static/assets/{mermaid.core-zqRnwN3B.js → mermaid.core-ZgyZych2.js} +3 -3
- pythinker_code/web/static/assets/{mindmap-definition-RKZ34NQL-CamoLUlD.js → mindmap-definition-RKZ34NQL-DoPx6yXo.js} +1 -1
- pythinker_code/web/static/assets/{packet-YPE3B663-s78KeeiS.js → packet-YPE3B663-DsBVFF3b.js} +1 -1
- pythinker_code/web/static/assets/{pie-LRSECV5Y-DSusaq_V.js → pie-LRSECV5Y-BqvyMS-y.js} +1 -1
- pythinker_code/web/static/assets/{pieDiagram-4H26LBE5-BcJSWsmz.js → pieDiagram-4H26LBE5-C0o5b8QE.js} +1 -1
- pythinker_code/web/static/assets/{quadrantDiagram-W4KKPZXB-Cxp3MYGY.js → quadrantDiagram-W4KKPZXB-BeArUQAv.js} +1 -1
- pythinker_code/web/static/assets/{radar-GUYGQ44K-sZyAfli_.js → radar-GUYGQ44K-B2ISte2b.js} +1 -1
- pythinker_code/web/static/assets/{requirementDiagram-4Y6WPE33-DSaeIAHw.js → requirementDiagram-4Y6WPE33-DZ5btT5r.js} +1 -1
- pythinker_code/web/static/assets/{sankeyDiagram-5OEKKPKP-BI87xNZ8.js → sankeyDiagram-5OEKKPKP-DEe_JEz3.js} +1 -1
- pythinker_code/web/static/assets/{sequenceDiagram-3UESZ5HK-B3mOEaPg.js → sequenceDiagram-3UESZ5HK-BVRh_UVj.js} +1 -1
- pythinker_code/web/static/assets/{stateDiagram-AJRCARHV-CloKSCZq.js → stateDiagram-AJRCARHV-DAwizi72.js} +1 -1
- pythinker_code/web/static/assets/stateDiagram-v2-BHNVJYJU-BQ53hC4E.js +1 -0
- pythinker_code/web/static/assets/{timeline-definition-PNZ67QCA-dy1xxojp.js → timeline-definition-PNZ67QCA-CLIYK9Jz.js} +1 -1
- pythinker_code/web/static/assets/{treeView-BLDUP644-CouMM8Ld.js → treeView-BLDUP644-DXcWQpz4.js} +1 -1
- pythinker_code/web/static/assets/{treemap-LRROVOQU-BurOGxmB.js → treemap-LRROVOQU-D4DQ9pO_.js} +1 -1
- pythinker_code/web/static/assets/{vennDiagram-CIIHVFJN-ceoQfI8-.js → vennDiagram-CIIHVFJN-ChlhzFNb.js} +1 -1
- pythinker_code/web/static/assets/{wardley-L42UT6IY-DQIeshOY.js → wardley-L42UT6IY-B0oYxi6O.js} +1 -1
- pythinker_code/web/static/assets/{wardleyDiagram-YWT4CUSO-yJgnjbxz.js → wardleyDiagram-YWT4CUSO-Cr6wIf4f.js} +1 -1
- pythinker_code/web/static/assets/{xychartDiagram-2RQKCTM6-jMkhXWCc.js → xychartDiagram-2RQKCTM6-VwJzwioB.js} +1 -1
- pythinker_code/web/static/index.html +1 -1
- {pythinker_code-0.45.0.dist-info → pythinker_code-0.46.0.dist-info}/METADATA +23 -24
- {pythinker_code-0.45.0.dist-info → pythinker_code-0.46.0.dist-info}/RECORD +75 -75
- pythinker_code/web/static/assets/architecture-7EHR7CIX-CxeoRZcL.js +0 -1
- pythinker_code/web/static/assets/channel-CzOfc6qg.js +0 -1
- pythinker_code/web/static/assets/classDiagram-4FO5ZUOK-Cl__vhhZ.js +0 -1
- pythinker_code/web/static/assets/classDiagram-v2-Q7XG4LA2-Cl__vhhZ.js +0 -1
- pythinker_code/web/static/assets/eventmodeling-FCH6USID-1z7xo-Al.js +0 -1
- pythinker_code/web/static/assets/mermaid-VLURNSYL-B9qVFSXg.js +0 -1
- pythinker_code/web/static/assets/stateDiagram-v2-BHNVJYJU-bwtGCtLW.js +0 -1
- {pythinker_code-0.45.0.dist-info → pythinker_code-0.46.0.dist-info}/WHEEL +0 -0
- {pythinker_code-0.45.0.dist-info → pythinker_code-0.46.0.dist-info}/entry_points.txt +0 -0
- {pythinker_code-0.45.0.dist-info → pythinker_code-0.46.0.dist-info}/licenses/LICENSE +0 -0
- {pythinker_code-0.45.0.dist-info → pythinker_code-0.46.0.dist-info}/licenses/NOTICE +0 -0
pythinker_code/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,14 @@ GitHub Releases page; `0.8.0` is the new starting line.
|
|
|
15
15
|
|
|
16
16
|
## Unreleased
|
|
17
17
|
|
|
18
|
+
## 0.46.0 (2026-06-14)
|
|
19
|
+
|
|
20
|
+
- **Startup auto-update now picks up new releases within half an hour instead of up to a day.** The background update check was throttled to once every 24h, so a freshly published release could go unnoticed for a full day after the last check; the interval is now 30 minutes. The silent installer also no longer marks the throttle *before* the network call — a transient startup network error returns `FAILED` and is retried on the next launch instead of suppressing updates for the whole window.
|
|
21
|
+
- **The welcome banner now keeps the robot mark visible in compact terminals.** Below ~68 columns the robot was dropped (it could not sit beside the welcome copy); it now stacks centered above the copy instead, so the mark stays on screen at any width that can render its Unicode glyphs. ASCII-only terminals are unaffected.
|
|
22
|
+
- **A persistent update notice now sits directly under the prompt input.** When a newer release is available the footer shows a yellow `↑ Update available — vX · /update` line; once a release has been installed in the background it switches to a restart-to-apply message instead of pointing at `/update`, and it clears after you restart onto the new version. The line is suppressed for dismissed versions, disabled auto-update, and source checkouts.
|
|
23
|
+
|
|
24
|
+
Upgrade with `pythinker update`, `pip install --upgrade pythinker-code==0.46.0`, or use the native installer for your platform from the [Releases page](https://github.com/Pythoughts-labs/pythinker-code/releases/latest).
|
|
25
|
+
|
|
18
26
|
## 0.45.0 (2026-06-14)
|
|
19
27
|
|
|
20
28
|
- **Agent-tracing dashboard.** Added `pythinker dashboard` — a local web UI for inspecting sessions, wire events, context messages, tool statistics, and usage over time. It is also reachable from the interactive shell via the `/reports` slash command (aliased `/dashboard`).
|
|
@@ -81,6 +81,7 @@ from pythinker_code.ui.shell.update import (
|
|
|
81
81
|
)
|
|
82
82
|
from pythinker_code.ui.shell.update_orchestrator import (
|
|
83
83
|
SMOKE_CHECK_FAILED_PREFIX,
|
|
84
|
+
UpdateJobState,
|
|
84
85
|
read_update_status,
|
|
85
86
|
run_update_job,
|
|
86
87
|
)
|
|
@@ -565,6 +566,10 @@ class Shell:
|
|
|
565
566
|
self._prefill_text = prefill_text
|
|
566
567
|
self._background_tasks: set[asyncio.Task[Any]] = set()
|
|
567
568
|
self._prompt_session: CustomPromptSession | None = None
|
|
569
|
+
# (timestamp, text) memo for the under-input update line; refreshed on a
|
|
570
|
+
# short TTL so the hot toolbar render path does not stat the update
|
|
571
|
+
# cache on every repaint (mirrors the footer's git-branch TTL).
|
|
572
|
+
self._update_notice_cache: tuple[float, str | None] = (0.0, None)
|
|
568
573
|
self._running_input_handler: Callable[[UserInput], None] | None = None
|
|
569
574
|
self._running_interrupt_handler: Callable[[], None] | None = None
|
|
570
575
|
self._active_approval_sink: Any | None = None
|
|
@@ -916,6 +921,7 @@ class Shell:
|
|
|
916
921
|
status_block_provider=_mcp_status_block,
|
|
917
922
|
fast_refresh_provider=_mcp_status_loading,
|
|
918
923
|
background_task_count_provider=_bg_task_counts,
|
|
924
|
+
update_notice_provider=self._update_notice_text,
|
|
919
925
|
model_capabilities=self.soul.model_capabilities or set(),
|
|
920
926
|
model_name=model_display_name(
|
|
921
927
|
self.soul.model_name,
|
|
@@ -2110,9 +2116,13 @@ class Shell:
|
|
|
2110
2116
|
"""Install a newer release silently in the background at startup."""
|
|
2111
2117
|
if not _should_auto_check_for_updates():
|
|
2112
2118
|
return
|
|
2113
|
-
_mark_auto_update_check_attempt()
|
|
2114
2119
|
|
|
2115
2120
|
result = await self._run_silent_update_job()
|
|
2121
|
+
# Throttle only after a completed round-trip. Marking before the network
|
|
2122
|
+
# call (or after a FAILED one) would suppress updates for the whole
|
|
2123
|
+
# interval on a transient startup blip — mirrors _refresh_update_cache.
|
|
2124
|
+
if result is not None and result is not UpdateResult.FAILED:
|
|
2125
|
+
_mark_auto_update_check_attempt()
|
|
2116
2126
|
if result is UpdateResult.UPDATED:
|
|
2117
2127
|
self._surface_installed_update_notice()
|
|
2118
2128
|
elif result is UpdateResult.UPDATE_AVAILABLE:
|
|
@@ -2180,6 +2190,42 @@ class Shell:
|
|
|
2180
2190
|
if self._prompt_session is not None:
|
|
2181
2191
|
self._prompt_session.invalidate()
|
|
2182
2192
|
|
|
2193
|
+
def _update_notice_text(self) -> str | None:
|
|
2194
|
+
"""Persistent under-input update line, or None when up to date.
|
|
2195
|
+
|
|
2196
|
+
Memoized on a short TTL (5s) so the hot toolbar render path doesn't stat
|
|
2197
|
+
the update cache on every repaint; the background updater invalidates the
|
|
2198
|
+
prompt when it changes the cache, so the line still appears promptly.
|
|
2199
|
+
"""
|
|
2200
|
+
now = time.monotonic()
|
|
2201
|
+
cached_at, cached = self._update_notice_cache
|
|
2202
|
+
if now - cached_at < 5.0:
|
|
2203
|
+
return cached
|
|
2204
|
+
text = self._compute_update_notice()
|
|
2205
|
+
self._update_notice_cache = (now, text)
|
|
2206
|
+
return text
|
|
2207
|
+
|
|
2208
|
+
def _compute_update_notice(self) -> str | None:
|
|
2209
|
+
target = welcome_update_target()
|
|
2210
|
+
if not target:
|
|
2211
|
+
return None
|
|
2212
|
+
# A release already installed this session needs a restart, not /update —
|
|
2213
|
+
# keep this line in agreement with the install toast instead of telling
|
|
2214
|
+
# the user to re-run an update that has already landed.
|
|
2215
|
+
status = read_update_status()
|
|
2216
|
+
installed = (
|
|
2217
|
+
status is not None
|
|
2218
|
+
and status.state is UpdateJobState.UPDATED
|
|
2219
|
+
and status.target_version == target
|
|
2220
|
+
)
|
|
2221
|
+
if installed and not self._installed_update_smoke_check_failed():
|
|
2222
|
+
text = self._installed_update_restart_notice()
|
|
2223
|
+
else:
|
|
2224
|
+
text = f"↑ Update available — v{target} · /update"
|
|
2225
|
+
if ascii_glyphs_enabled():
|
|
2226
|
+
text = text.translate(_WELCOME_ASCII_FALLBACKS)
|
|
2227
|
+
return text
|
|
2228
|
+
|
|
2183
2229
|
def _schedule_startup_update_task(self) -> None:
|
|
2184
2230
|
"""Pick the startup update behavior and schedule it (non-blocking).
|
|
2185
2231
|
|
|
@@ -2559,7 +2605,11 @@ def _print_welcome_info(
|
|
|
2559
2605
|
|
|
2560
2606
|
show_logo = not ascii_mode
|
|
2561
2607
|
use_columns = bool(tips) and content_width >= _WELCOME_COLUMNS_MIN_WIDTH
|
|
2562
|
-
|
|
2608
|
+
# The robot sits beside the copy when there's room (~68 cells); in a compact
|
|
2609
|
+
# terminal it stacks centered above the copy instead of being dropped, so the
|
|
2610
|
+
# mark stays visible at any width that can render its Unicode glyphs.
|
|
2611
|
+
logo_beside_copy = show_logo and not use_columns and content_width >= 68
|
|
2612
|
+
logo_rendered = show_logo # columns-centered, beside, or stacked — only ASCII hides it
|
|
2563
2613
|
|
|
2564
2614
|
version_title = Text.assemble(
|
|
2565
2615
|
("Pythinker Code", tui_rich_style("muted")),
|
|
@@ -2608,7 +2658,7 @@ def _print_welcome_info(
|
|
|
2608
2658
|
columns.add_row(Group(*left_rows), _tips_block(tips_width, with_rule=True))
|
|
2609
2659
|
rows.append(columns)
|
|
2610
2660
|
else:
|
|
2611
|
-
if
|
|
2661
|
+
if logo_beside_copy:
|
|
2612
2662
|
# Logo on the left; the text block centers vertically against
|
|
2613
2663
|
# the robot so the lines sit beside the face while the antenna
|
|
2614
2664
|
# floats above.
|
|
@@ -2617,6 +2667,10 @@ def _print_welcome_info(
|
|
|
2617
2667
|
table.add_column(justify="left", vertical="middle", no_wrap=True)
|
|
2618
2668
|
table.add_row(_logo_text(), Group(head, strapline, help_text))
|
|
2619
2669
|
rows.append(table)
|
|
2670
|
+
elif show_logo:
|
|
2671
|
+
# Compact terminal: too narrow to seat the robot beside the
|
|
2672
|
+
# copy, so stack it centered above instead of dropping it.
|
|
2673
|
+
rows.extend([Align.center(_logo_text()), Text(""), head, strapline, help_text])
|
|
2620
2674
|
else:
|
|
2621
2675
|
rows.extend([head, strapline, help_text])
|
|
2622
2676
|
|
|
@@ -2126,6 +2126,7 @@ class CustomPromptSession:
|
|
|
2126
2126
|
status_block_provider: Callable[[int], AnyFormattedText | None] | None = None,
|
|
2127
2127
|
fast_refresh_provider: Callable[[], bool] | None = None,
|
|
2128
2128
|
background_task_count_provider: Callable[[], BgTaskCounts] | None = None,
|
|
2129
|
+
update_notice_provider: Callable[[], str | None] | None = None,
|
|
2129
2130
|
model_capabilities: set[ModelCapability],
|
|
2130
2131
|
model_name: str | None,
|
|
2131
2132
|
thinking: bool,
|
|
@@ -2173,6 +2174,7 @@ class CustomPromptSession:
|
|
|
2173
2174
|
self._status_block_provider = status_block_provider
|
|
2174
2175
|
self._fast_refresh_provider = fast_refresh_provider
|
|
2175
2176
|
self._background_task_count_provider = background_task_count_provider
|
|
2177
|
+
self._update_notice_provider = update_notice_provider
|
|
2176
2178
|
self._editor_command_provider = editor_command_provider
|
|
2177
2179
|
self._turn_recaps_provider = turn_recaps_provider
|
|
2178
2180
|
self._plan_mode_toggle_callback = plan_mode_toggle_callback
|
|
@@ -3711,6 +3713,23 @@ class CustomPromptSession:
|
|
|
3711
3713
|
error=exc,
|
|
3712
3714
|
)
|
|
3713
3715
|
|
|
3716
|
+
def _prepend_update_notice(self, fragments: list[tuple[str, str]], columns: int) -> None:
|
|
3717
|
+
"""Prepend a persistent yellow 'update available' line above the footer
|
|
3718
|
+
separator, so it renders directly under the prompt input. No-op when no
|
|
3719
|
+
update is pending; style-agnostic across both toolbar layouts."""
|
|
3720
|
+
provider = getattr(self, "_update_notice_provider", None)
|
|
3721
|
+
if provider is None:
|
|
3722
|
+
return
|
|
3723
|
+
text = provider()
|
|
3724
|
+
if not text:
|
|
3725
|
+
return
|
|
3726
|
+
line = _truncate_right(text, max(0, columns - 1))
|
|
3727
|
+
if not line:
|
|
3728
|
+
return
|
|
3729
|
+
tokens = _get_tui_tokens()
|
|
3730
|
+
style = f"fg:{tokens.warning or 'ansiyellow'} bold"
|
|
3731
|
+
fragments[:0] = [(style, line), ("", "\n")]
|
|
3732
|
+
|
|
3714
3733
|
def _render_bottom_toolbar(self) -> FormattedText:
|
|
3715
3734
|
if (
|
|
3716
3735
|
hasattr(self, "_session")
|
|
@@ -3733,6 +3752,7 @@ class CustomPromptSession:
|
|
|
3733
3752
|
fragments: list[tuple[str, str]] = []
|
|
3734
3753
|
tc = get_toolbar_colors()
|
|
3735
3754
|
|
|
3755
|
+
self._prepend_update_notice(fragments, columns)
|
|
3736
3756
|
fragments.append((self._prompt_separator_style(tc.separator), _prompt_rule(columns)))
|
|
3737
3757
|
fragments.append(("", "\n"))
|
|
3738
3758
|
|
|
@@ -3963,6 +3983,7 @@ class CustomPromptSession:
|
|
|
3963
3983
|
secondary_style = f"fg:{tokens.muted}"
|
|
3964
3984
|
|
|
3965
3985
|
fragments: list[tuple[str, str]] = []
|
|
3986
|
+
self._prepend_update_notice(fragments, columns)
|
|
3966
3987
|
fragments.append((self._prompt_separator_style(tc.separator), _prompt_rule(columns)))
|
|
3967
3988
|
fragments.append(("", "\n"))
|
|
3968
3989
|
|
|
@@ -64,7 +64,13 @@ LATEST_VERSION_ETAG_FILE = get_share_dir() / "latest_version.etag"
|
|
|
64
64
|
LAST_UPDATE_CHECK_FILE = get_share_dir() / "last_update_check.txt"
|
|
65
65
|
DISMISSED_VERSION_FILE = get_share_dir() / "dismissed_update_version.txt"
|
|
66
66
|
LAST_SEEN_VERSION_FILE = get_share_dir() / "last_seen_version.txt"
|
|
67
|
-
|
|
67
|
+
# ponytail: 30m throttle so a freshly-pushed release is picked up on the next
|
|
68
|
+
# restart instead of up to a day later. The check is unauthenticated, so each
|
|
69
|
+
# poll costs one of GitHub's 60 req/hr/IP budget regardless of the cached ETag
|
|
70
|
+
# (304s are only rate-limit-free when authenticated) — at ~2 polls/hr/startup
|
|
71
|
+
# that is a wide margin. A throttle miss fails safe: a transient error returns
|
|
72
|
+
# FAILED, which skips the mark and retries next launch.
|
|
73
|
+
AUTO_UPDATE_CHECK_INTERVAL_SECONDS = 30 * 60
|
|
68
74
|
PROMPT_UPDATE_REFRESH_TIMEOUT_SECONDS = 2.0
|
|
69
75
|
WINDOWS_UPDATE_STAGING_MAX_AGE_SECONDS = 7 * 24 * 60 * 60
|
|
70
76
|
UPGRADE_COMMAND_TIMEOUT_SECONDS = 30 * 60
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./chunk-NNHCCRGN-DmZbXBJw.js";import{x as e}from"./mermaid-parser.core-C_SVA4S7.js";export{e as createArchitectureServices};
|