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.
Files changed (82) hide show
  1. pythinker_code/CHANGELOG.md +8 -0
  2. pythinker_code/ui/shell/__init__.py +57 -3
  3. pythinker_code/ui/shell/prompt.py +21 -0
  4. pythinker_code/ui/shell/update.py +7 -1
  5. pythinker_code/web/static/assets/architecture-7EHR7CIX-DuYWmQ8n.js +1 -0
  6. pythinker_code/web/static/assets/{architectureDiagram-3BPJPVTR-Cmrv4t4A.js → architectureDiagram-3BPJPVTR-UoU1nAk7.js} +1 -1
  7. pythinker_code/web/static/assets/{blockDiagram-GPEHLZMM-DJtt-l4b.js → blockDiagram-GPEHLZMM-71KoIQeZ.js} +1 -1
  8. pythinker_code/web/static/assets/{bootstrap-GQDZdCZn.js → bootstrap-B_vGg5Ny.js} +5 -5
  9. pythinker_code/web/static/assets/{c4Diagram-AAUBKEIU-o0KsSeIT.js → c4Diagram-AAUBKEIU-BuO74dDT.js} +1 -1
  10. pythinker_code/web/static/assets/channel-6SKWVwR3.js +1 -0
  11. pythinker_code/web/static/assets/{chunk-2J33WTMH-CVPDc3uI.js → chunk-2J33WTMH-B7JEo7lz.js} +1 -1
  12. pythinker_code/web/static/assets/{chunk-3OPIFGDE-Tu9TJ8FO.js → chunk-3OPIFGDE-DmL9lwRX.js} +1 -1
  13. pythinker_code/web/static/assets/{chunk-5ZQYHXKU-CoBmhCur.js → chunk-5ZQYHXKU-CBmTeQHC.js} +1 -1
  14. pythinker_code/web/static/assets/{chunk-727SXJPM-DByzCodm.js → chunk-727SXJPM-D62jKCyv.js} +1 -1
  15. pythinker_code/web/static/assets/{chunk-AQP2D5EJ-DclqBNWp.js → chunk-AQP2D5EJ-BynCmQVm.js} +1 -1
  16. pythinker_code/web/static/assets/{chunk-CSCIHK7Q-CUIX1-rb.js → chunk-CSCIHK7Q-QrY277S-.js} +1 -1
  17. pythinker_code/web/static/assets/{chunk-JAPRZBRM-gOR8tSRc.js → chunk-JAPRZBRM-DyAuAcwd.js} +4 -4
  18. pythinker_code/web/static/assets/{chunk-KSCS5N6A-hta5hym2.js → chunk-KSCS5N6A-B-L96nEP.js} +1 -1
  19. pythinker_code/web/static/assets/{chunk-L5ZTLDWV-cj__FNrg.js → chunk-L5ZTLDWV-Dx2O-osv.js} +1 -1
  20. pythinker_code/web/static/assets/{chunk-LZXEDZCA-CSHDE7c1.js → chunk-LZXEDZCA-Ud8JWymF.js} +2 -2
  21. pythinker_code/web/static/assets/{chunk-ND2GUHAM-DMFQO6Cb.js → chunk-ND2GUHAM-D309EoC7.js} +1 -1
  22. pythinker_code/web/static/assets/{chunk-NZK2D7GU-Cjm014we.js → chunk-NZK2D7GU-CRryXTBY.js} +1 -1
  23. pythinker_code/web/static/assets/{chunk-O5CBEL6O-BSr1l1Fd.js → chunk-O5CBEL6O-CG1Ia2Dd.js} +1 -1
  24. pythinker_code/web/static/assets/{chunk-WU5MYG2G-veNzkohb.js → chunk-WU5MYG2G-CufdHSG9.js} +1 -1
  25. pythinker_code/web/static/assets/classDiagram-4FO5ZUOK-CLfRoPJH.js +1 -0
  26. pythinker_code/web/static/assets/classDiagram-v2-Q7XG4LA2-CLfRoPJH.js +1 -0
  27. pythinker_code/web/static/assets/{code-block-IT6T5CEO-DTgIHAkQ.js → code-block-IT6T5CEO-DMzMTNsT.js} +1 -1
  28. pythinker_code/web/static/assets/{dagre-BM42HDAG-D-_HCbAC.js → dagre-BM42HDAG-DmUINU6q.js} +1 -1
  29. pythinker_code/web/static/assets/{diagram-2AECGRRQ-CvX58Rpg.js → diagram-2AECGRRQ-P5YMGdQ8.js} +1 -1
  30. pythinker_code/web/static/assets/{diagram-5GNKFQAL-CsRaiNkg.js → diagram-5GNKFQAL-BaimYqgQ.js} +1 -1
  31. pythinker_code/web/static/assets/{diagram-KO2AKTUF-Dn6aiXG5.js → diagram-KO2AKTUF-DgpITRK9.js} +1 -1
  32. pythinker_code/web/static/assets/{diagram-LMA3HP47-DXQlab3r.js → diagram-LMA3HP47-CMnhE9ZH.js} +1 -1
  33. pythinker_code/web/static/assets/{diagram-OG6HWLK6-BWB_FmTS.js → diagram-OG6HWLK6-BhLWHvOg.js} +1 -1
  34. pythinker_code/web/static/assets/{dist-C8Q1EY4S.js → dist-DPNOCkje.js} +1 -1
  35. pythinker_code/web/static/assets/{erDiagram-TEJ5UH35-BrQiudEc.js → erDiagram-TEJ5UH35-CHSdb2VU.js} +1 -1
  36. pythinker_code/web/static/assets/eventmodeling-FCH6USID-j7ey84Sq.js +1 -0
  37. pythinker_code/web/static/assets/{flowDiagram-I6XJVG4X-C6jARfsw.js → flowDiagram-I6XJVG4X-FNGh8ANR.js} +1 -1
  38. pythinker_code/web/static/assets/{ganttDiagram-6RSMTGT7-DH-i7Wci.js → ganttDiagram-6RSMTGT7-BLTimgS0.js} +1 -1
  39. pythinker_code/web/static/assets/{gitGraph-WXDBUCRP-lU8PeAwh.js → gitGraph-WXDBUCRP-C3Dg6N-n.js} +1 -1
  40. pythinker_code/web/static/assets/{gitGraphDiagram-PVQCEYII-JOoIM40T.js → gitGraphDiagram-PVQCEYII-BbiwVf9S.js} +1 -1
  41. pythinker_code/web/static/assets/{index-BJIE96ev.js → index-uSUCKoSL.js} +2 -2
  42. pythinker_code/web/static/assets/{info-J43DQDTF-B9a8E9HF.js → info-J43DQDTF-BeSMeh6p.js} +1 -1
  43. pythinker_code/web/static/assets/{infoDiagram-5YYISTIA-D5wmE10q.js → infoDiagram-5YYISTIA-BQxCJcq4.js} +1 -1
  44. pythinker_code/web/static/assets/{ishikawaDiagram-YF4QCWOH-DzNdTJqt.js → ishikawaDiagram-YF4QCWOH-KaeLGrsH.js} +1 -1
  45. pythinker_code/web/static/assets/{journeyDiagram-JHISSGLW-CwevEltw.js → journeyDiagram-JHISSGLW-Kk2DXiQI.js} +1 -1
  46. pythinker_code/web/static/assets/{kanban-definition-UN3LZRKU-BAmLyJgC.js → kanban-definition-UN3LZRKU-zn_6z8FY.js} +1 -1
  47. pythinker_code/web/static/assets/{line-CktbshjS.js → line-DCLS_X1f.js} +1 -1
  48. pythinker_code/web/static/assets/mermaid-VLURNSYL-BOvErqSv.js +1 -0
  49. pythinker_code/web/static/assets/{mermaid-parser.core-B1Hc3VHx.js → mermaid-parser.core-C_SVA4S7.js} +2 -2
  50. pythinker_code/web/static/assets/{mermaid.core-zqRnwN3B.js → mermaid.core-ZgyZych2.js} +3 -3
  51. pythinker_code/web/static/assets/{mindmap-definition-RKZ34NQL-CamoLUlD.js → mindmap-definition-RKZ34NQL-DoPx6yXo.js} +1 -1
  52. pythinker_code/web/static/assets/{packet-YPE3B663-s78KeeiS.js → packet-YPE3B663-DsBVFF3b.js} +1 -1
  53. pythinker_code/web/static/assets/{pie-LRSECV5Y-DSusaq_V.js → pie-LRSECV5Y-BqvyMS-y.js} +1 -1
  54. pythinker_code/web/static/assets/{pieDiagram-4H26LBE5-BcJSWsmz.js → pieDiagram-4H26LBE5-C0o5b8QE.js} +1 -1
  55. pythinker_code/web/static/assets/{quadrantDiagram-W4KKPZXB-Cxp3MYGY.js → quadrantDiagram-W4KKPZXB-BeArUQAv.js} +1 -1
  56. pythinker_code/web/static/assets/{radar-GUYGQ44K-sZyAfli_.js → radar-GUYGQ44K-B2ISte2b.js} +1 -1
  57. pythinker_code/web/static/assets/{requirementDiagram-4Y6WPE33-DSaeIAHw.js → requirementDiagram-4Y6WPE33-DZ5btT5r.js} +1 -1
  58. pythinker_code/web/static/assets/{sankeyDiagram-5OEKKPKP-BI87xNZ8.js → sankeyDiagram-5OEKKPKP-DEe_JEz3.js} +1 -1
  59. pythinker_code/web/static/assets/{sequenceDiagram-3UESZ5HK-B3mOEaPg.js → sequenceDiagram-3UESZ5HK-BVRh_UVj.js} +1 -1
  60. pythinker_code/web/static/assets/{stateDiagram-AJRCARHV-CloKSCZq.js → stateDiagram-AJRCARHV-DAwizi72.js} +1 -1
  61. pythinker_code/web/static/assets/stateDiagram-v2-BHNVJYJU-BQ53hC4E.js +1 -0
  62. pythinker_code/web/static/assets/{timeline-definition-PNZ67QCA-dy1xxojp.js → timeline-definition-PNZ67QCA-CLIYK9Jz.js} +1 -1
  63. pythinker_code/web/static/assets/{treeView-BLDUP644-CouMM8Ld.js → treeView-BLDUP644-DXcWQpz4.js} +1 -1
  64. pythinker_code/web/static/assets/{treemap-LRROVOQU-BurOGxmB.js → treemap-LRROVOQU-D4DQ9pO_.js} +1 -1
  65. pythinker_code/web/static/assets/{vennDiagram-CIIHVFJN-ceoQfI8-.js → vennDiagram-CIIHVFJN-ChlhzFNb.js} +1 -1
  66. pythinker_code/web/static/assets/{wardley-L42UT6IY-DQIeshOY.js → wardley-L42UT6IY-B0oYxi6O.js} +1 -1
  67. pythinker_code/web/static/assets/{wardleyDiagram-YWT4CUSO-yJgnjbxz.js → wardleyDiagram-YWT4CUSO-Cr6wIf4f.js} +1 -1
  68. pythinker_code/web/static/assets/{xychartDiagram-2RQKCTM6-jMkhXWCc.js → xychartDiagram-2RQKCTM6-VwJzwioB.js} +1 -1
  69. pythinker_code/web/static/index.html +1 -1
  70. {pythinker_code-0.45.0.dist-info → pythinker_code-0.46.0.dist-info}/METADATA +23 -24
  71. {pythinker_code-0.45.0.dist-info → pythinker_code-0.46.0.dist-info}/RECORD +75 -75
  72. pythinker_code/web/static/assets/architecture-7EHR7CIX-CxeoRZcL.js +0 -1
  73. pythinker_code/web/static/assets/channel-CzOfc6qg.js +0 -1
  74. pythinker_code/web/static/assets/classDiagram-4FO5ZUOK-Cl__vhhZ.js +0 -1
  75. pythinker_code/web/static/assets/classDiagram-v2-Q7XG4LA2-Cl__vhhZ.js +0 -1
  76. pythinker_code/web/static/assets/eventmodeling-FCH6USID-1z7xo-Al.js +0 -1
  77. pythinker_code/web/static/assets/mermaid-VLURNSYL-B9qVFSXg.js +0 -1
  78. pythinker_code/web/static/assets/stateDiagram-v2-BHNVJYJU-bwtGCtLW.js +0 -1
  79. {pythinker_code-0.45.0.dist-info → pythinker_code-0.46.0.dist-info}/WHEEL +0 -0
  80. {pythinker_code-0.45.0.dist-info → pythinker_code-0.46.0.dist-info}/entry_points.txt +0 -0
  81. {pythinker_code-0.45.0.dist-info → pythinker_code-0.46.0.dist-info}/licenses/LICENSE +0 -0
  82. {pythinker_code-0.45.0.dist-info → pythinker_code-0.46.0.dist-info}/licenses/NOTICE +0 -0
@@ -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
- logo_rendered = show_logo and (use_columns or content_width >= 68)
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 logo_rendered:
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
- AUTO_UPDATE_CHECK_INTERVAL_SECONDS = 24 * 60 * 60
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};