arrayview 0.41.1__tar.gz → 0.42.1__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.
- {arrayview-0.41.1 → arrayview-0.42.1}/PKG-INFO +1 -1
- {arrayview-0.41.1 → arrayview-0.42.1}/pyproject.toml +1 -1
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_diagnostics.py +5 -1
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_launch_trace.py +59 -2
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_launcher.py +41 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_routes_query.py +32 -8
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_server.py +22 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_viewer.html +449 -102
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_vscode_extension.py +169 -1
- arrayview-0.42.1/src/arrayview/arrayview-opener.vsix +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_launch_diagnostics.py +11 -0
- arrayview-0.42.1/tests/test_launch_trace.py +231 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_lifecycle_contract.py +21 -6
- arrayview-0.41.1/src/arrayview/arrayview-opener.vsix +0 -0
- arrayview-0.41.1/tests/test_launch_trace.py +0 -99
- {arrayview-0.41.1 → arrayview-0.42.1}/.gitignore +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/LICENSE +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/README.md +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/ARCHITECTURE.md +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/__init__.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/__main__.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_analysis.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_app.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_config.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_dicom.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_diff.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_icon.png +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_imaging.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_instance_registry.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_io.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_launch_plan.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_lifecycle.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_overlays.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_platform.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_render.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_routes_analysis.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_routes_drop.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_routes_export.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_routes_loading.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_routes_persistence.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_routes_preferences.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_routes_preload.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_routes_rendering.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_routes_segmentation.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_routes_state.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_routes_vectorfield.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_routes_websocket.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_segmentation.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_session.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_session_spec.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_shell.html +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_source_safety.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_synthetic_mri.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_torch.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_tutorial.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_vectorfield.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_vscode.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_vscode_browser.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_vscode_signal.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/_watch.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/gsap.min.js +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/src/arrayview/todo.md +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/capture_patient_loading.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/capture_v_animation.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/conftest.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/lifecycle_matrix.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/make_vectorfield_test_arrays.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_1d_arrays.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_api.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_backend_shared.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_browser.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_cli.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_colorbar_hover_highlight.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_config.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_dicom.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_display_opener_results.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_doctor_commands.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_drop_import.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_instance_registry.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_invocation_contract_matrix.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_io.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_large_arrays.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_launch_blackbox.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_launch_execution_ownership.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_launch_plan.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_loading_server.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_mode_consistency.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_mode_matrix.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_mode_roundtrip.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_nifti_meta.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_nifti_series.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_preferences_ui.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_public_invocation_regressions.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_render_failure_reporting.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_render_progress.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_rgb_pixel_art.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_safe_server_stop.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_server_identity_status.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_session_spec.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_source_safety.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_spawn_ownership.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_torch.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_tutorial.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_tutorial_browser.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_value_formatting.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_view_handle_lifecycle.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_view_launch_execution.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_vscode_ack_protocol.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/test_window_level_preview.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/ui_audit.py +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/v_anim_frames/.gitkeep +0 -0
- {arrayview-0.41.1 → arrayview-0.42.1}/tests/visual_smoke.py +0 -0
|
@@ -76,7 +76,11 @@ _DIAGNOSES: list[tuple[str, str, str, str]] = [
|
|
|
76
76
|
_RETRY),
|
|
77
77
|
|
|
78
78
|
# ── Timing — slow, not broken ─────────────────────────────────────────
|
|
79
|
-
(r"did not
|
|
79
|
+
(r"did not start the viewer script", ACTION,
|
|
80
|
+
"VS Code opened an integrated-browser tab, but the tab did not navigate "
|
|
81
|
+
"to the ArrayView page.",
|
|
82
|
+
_RETRY + " If it repeats, reload the VS Code window."),
|
|
83
|
+
(r"did not render a frame|did not become ready",
|
|
80
84
|
ACTION,
|
|
81
85
|
"The viewer opened but showed no frame before the deadline — usually a "
|
|
82
86
|
"slow first load.",
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"""Best-effort, opt-in launch event tracing.
|
|
2
2
|
|
|
3
3
|
The trace is deliberately dependency-free and inert unless
|
|
4
|
-
``ARRAYVIEW_LAUNCH_TRACE`` names an absolute JSONL file.
|
|
5
|
-
|
|
4
|
+
``ARRAYVIEW_LAUNCH_TRACE`` names an absolute JSONL file. Integrated-browser
|
|
5
|
+
route tracing can also be enabled explicitly with
|
|
6
|
+
``~/.arrayview/enable-launch-trace``. Launch behavior must never depend on a
|
|
7
|
+
trace write succeeding.
|
|
6
8
|
"""
|
|
7
9
|
|
|
8
10
|
from __future__ import annotations
|
|
@@ -20,6 +22,8 @@ TRACE_PATH_ENV = "ARRAYVIEW_LAUNCH_TRACE"
|
|
|
20
22
|
TRACE_ID_ENV = "ARRAYVIEW_LAUNCH_ID"
|
|
21
23
|
TRACE_ROLE_ENV = "ARRAYVIEW_LAUNCH_ROLE"
|
|
22
24
|
TRACE_SCHEMA = 1
|
|
25
|
+
TRACE_MARKER_NAME = "enable-launch-trace"
|
|
26
|
+
TRACE_DEFAULT_NAME = "launch-trace.jsonl"
|
|
23
27
|
_MAX_EVENT_BYTES = 4096
|
|
24
28
|
|
|
25
29
|
_lock = threading.Lock()
|
|
@@ -70,6 +74,56 @@ def trace_tag(value: object) -> str:
|
|
|
70
74
|
return hashlib.sha256(str(value).encode("utf-8", "replace")).hexdigest()[:12]
|
|
71
75
|
|
|
72
76
|
|
|
77
|
+
def configure_route_launch_trace() -> bool:
|
|
78
|
+
"""Enable route tracing from an explicit environment or marker opt-in.
|
|
79
|
+
|
|
80
|
+
Route handlers call this directly so an already-running server can notice
|
|
81
|
+
the marker even when its process environment never contained the trace
|
|
82
|
+
variable. An explicit environment value always wins, including an invalid
|
|
83
|
+
relative value, which keeps the normal trace contract unambiguous.
|
|
84
|
+
"""
|
|
85
|
+
try:
|
|
86
|
+
explicit = os.environ.get(TRACE_PATH_ENV)
|
|
87
|
+
if explicit is not None:
|
|
88
|
+
if not explicit or not Path(explicit).is_absolute():
|
|
89
|
+
return False
|
|
90
|
+
if _path != explicit:
|
|
91
|
+
configure_launch_trace()
|
|
92
|
+
return _path == explicit
|
|
93
|
+
|
|
94
|
+
trace_dir = Path.home() / ".arrayview"
|
|
95
|
+
if not (trace_dir / TRACE_MARKER_NAME).is_file():
|
|
96
|
+
return False
|
|
97
|
+
candidate = str(trace_dir / TRACE_DEFAULT_NAME)
|
|
98
|
+
if _path != candidate:
|
|
99
|
+
configure_launch_trace(path=candidate, role="server")
|
|
100
|
+
return _path == candidate
|
|
101
|
+
except Exception:
|
|
102
|
+
return False
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def emit_route_launch_event(
|
|
106
|
+
event: str,
|
|
107
|
+
*,
|
|
108
|
+
navigation_key: str,
|
|
109
|
+
tab_key: str | None = None,
|
|
110
|
+
**attrs: object,
|
|
111
|
+
) -> None:
|
|
112
|
+
"""Emit a route event without exposing private route credentials."""
|
|
113
|
+
try:
|
|
114
|
+
if not configure_route_launch_trace():
|
|
115
|
+
return
|
|
116
|
+
safe_attrs = {
|
|
117
|
+
"navigation_key_tag": trace_tag(navigation_key),
|
|
118
|
+
**attrs,
|
|
119
|
+
}
|
|
120
|
+
if tab_key is not None:
|
|
121
|
+
safe_attrs["tab_key_tag"] = trace_tag(tab_key)
|
|
122
|
+
emit_launch_event(event, **safe_attrs)
|
|
123
|
+
except Exception:
|
|
124
|
+
return
|
|
125
|
+
|
|
126
|
+
|
|
73
127
|
def emit_launch_event(event: str, **attrs: object) -> None:
|
|
74
128
|
"""Append one compact event, swallowing every tracing-related failure."""
|
|
75
129
|
try:
|
|
@@ -113,10 +167,13 @@ def _ensure_environment_configuration() -> None:
|
|
|
113
167
|
|
|
114
168
|
__all__ = [
|
|
115
169
|
"TRACE_ID_ENV",
|
|
170
|
+
"TRACE_MARKER_NAME",
|
|
116
171
|
"TRACE_PATH_ENV",
|
|
117
172
|
"TRACE_ROLE_ENV",
|
|
118
173
|
"configure_launch_trace",
|
|
174
|
+
"configure_route_launch_trace",
|
|
119
175
|
"emit_launch_event",
|
|
176
|
+
"emit_route_launch_event",
|
|
120
177
|
"trace_child_environment",
|
|
121
178
|
"trace_tag",
|
|
122
179
|
]
|
|
@@ -5266,15 +5266,56 @@ def _handle_management_command(argv: list[str]) -> bool:
|
|
|
5266
5266
|
),
|
|
5267
5267
|
}
|
|
5268
5268
|
)
|
|
5269
|
+
from arrayview._platform import _in_vscode_terminal # noqa: PLC0415
|
|
5270
|
+
from arrayview._vscode_extension import ( # noqa: PLC0415
|
|
5271
|
+
_describe_window,
|
|
5272
|
+
_opener_version_report,
|
|
5273
|
+
)
|
|
5274
|
+
|
|
5275
|
+
versions = _opener_version_report()
|
|
5276
|
+
if versions["state"] in {"window_older", "window_unversioned"}:
|
|
5277
|
+
remediation.append(
|
|
5278
|
+
{
|
|
5279
|
+
"code": "opener_version_skew",
|
|
5280
|
+
"message": (
|
|
5281
|
+
"Reload this VS Code window to run opener "
|
|
5282
|
+
f"v{versions['bundled_opener']}."
|
|
5283
|
+
),
|
|
5284
|
+
}
|
|
5285
|
+
)
|
|
5269
5286
|
report = {
|
|
5270
5287
|
"snapshot": snapshot_dict,
|
|
5271
5288
|
"plan": plan.to_dict(),
|
|
5272
5289
|
"instances": rows,
|
|
5273
5290
|
"remediation": remediation,
|
|
5291
|
+
"versions": versions,
|
|
5274
5292
|
}
|
|
5275
5293
|
if args.json:
|
|
5276
5294
|
print(json.dumps(report, indent=2, sort_keys=True))
|
|
5277
5295
|
else:
|
|
5296
|
+
print(
|
|
5297
|
+
f"arrayview {versions['package_version']} "
|
|
5298
|
+
f"({versions['package_path']})"
|
|
5299
|
+
)
|
|
5300
|
+
print(f"Opener bundled here: v{versions['bundled_opener']}")
|
|
5301
|
+
if versions["this_window"] is not None:
|
|
5302
|
+
suffix = {
|
|
5303
|
+
"window_older": " ← older than this arrayview; reload this window",
|
|
5304
|
+
"window_newer": " ← newer than this arrayview; kept and used",
|
|
5305
|
+
"window_unversioned": " ← pre-0.15 build; reload this window",
|
|
5306
|
+
}.get(versions["state"], "")
|
|
5307
|
+
print(
|
|
5308
|
+
"Opener live in this window: "
|
|
5309
|
+
f"{_describe_window(versions['this_window'])}{suffix}"
|
|
5310
|
+
)
|
|
5311
|
+
elif _in_vscode_terminal():
|
|
5312
|
+
print(
|
|
5313
|
+
"Opener live in this window: none — no live VS Code window "
|
|
5314
|
+
"claims this terminal"
|
|
5315
|
+
)
|
|
5316
|
+
for index, other in enumerate(versions["other_windows"]):
|
|
5317
|
+
label = "Opener live in other windows:" if index == 0 else " " * 29
|
|
5318
|
+
print(f"{label} {_describe_window(other)}")
|
|
5278
5319
|
print(f"Environment: {plan.environment.value}")
|
|
5279
5320
|
print(
|
|
5280
5321
|
f"Server: {plan.server_owner.value} on port {plan.effective_port} "
|
|
@@ -60,12 +60,11 @@ def register_query_routes(app, *, get_session_or_404, pil_image, pil_imageops) -
|
|
|
60
60
|
raise HTTPException(status_code=400, detail="Invalid viewer phase")
|
|
61
61
|
if phase != "launch-prepared" and not viewer_instance_id:
|
|
62
62
|
raise HTTPException(status_code=400, detail="Incomplete viewer phase identity")
|
|
63
|
-
#
|
|
64
|
-
# to open while a large array is still loading, so
|
|
65
|
-
#
|
|
66
|
-
# timeout.
|
|
67
|
-
|
|
68
|
-
if phase == "launch-prepared":
|
|
63
|
+
# Preparation and script startup are control-plane events. The viewer
|
|
64
|
+
# is meant to open while a large array is still loading, so hiding
|
|
65
|
+
# either event behind Session readiness creates a false pre-script
|
|
66
|
+
# timeout. Data-dependent phases still wait for the real Session.
|
|
67
|
+
if phase in {"launch-prepared", "script-loaded"}:
|
|
69
68
|
if sid not in SESSIONS and sid not in _session_mod.PENDING_SESSIONS:
|
|
70
69
|
raise HTTPException(status_code=404, detail="Session not found")
|
|
71
70
|
else:
|
|
@@ -141,6 +140,20 @@ def register_query_routes(app, *, get_session_or_404, pil_image, pil_imageops) -
|
|
|
141
140
|
previous_navigation_key,
|
|
142
141
|
None,
|
|
143
142
|
)
|
|
143
|
+
try:
|
|
144
|
+
from arrayview._launch_trace import emit_route_launch_event
|
|
145
|
+
|
|
146
|
+
emit_route_launch_event(
|
|
147
|
+
"page.route_retired",
|
|
148
|
+
navigation_key=previous_navigation_key,
|
|
149
|
+
tab_key=previous_journal.get("tab_key"),
|
|
150
|
+
request_id=request_id,
|
|
151
|
+
navigation_attempt=previous_journal.get(
|
|
152
|
+
"navigation_attempt"
|
|
153
|
+
),
|
|
154
|
+
)
|
|
155
|
+
except Exception:
|
|
156
|
+
pass
|
|
144
157
|
journal = journals[request_id] = {
|
|
145
158
|
"token": token,
|
|
146
159
|
"window_id": window_id,
|
|
@@ -160,6 +173,18 @@ def register_query_routes(app, *, get_session_or_404, pil_image, pil_imageops) -
|
|
|
160
173
|
sid,
|
|
161
174
|
request_id,
|
|
162
175
|
)
|
|
176
|
+
try:
|
|
177
|
+
from arrayview._launch_trace import emit_route_launch_event
|
|
178
|
+
|
|
179
|
+
emit_route_launch_event(
|
|
180
|
+
"page.route_prepared",
|
|
181
|
+
navigation_key=navigation_key,
|
|
182
|
+
tab_key=tab_key,
|
|
183
|
+
request_id=request_id,
|
|
184
|
+
navigation_attempt=navigation_attempt,
|
|
185
|
+
)
|
|
186
|
+
except Exception:
|
|
187
|
+
pass
|
|
163
188
|
return {
|
|
164
189
|
"sid": sid,
|
|
165
190
|
"request_id": request_id,
|
|
@@ -208,8 +233,7 @@ def register_query_routes(app, *, get_session_or_404, pil_image, pil_imageops) -
|
|
|
208
233
|
@app.get("/viewer-phase/{sid}/{request_id}")
|
|
209
234
|
async def get_viewer_phases(sid: str, request_id: str, token: str):
|
|
210
235
|
"""Return phases correlated to one browser launch transaction."""
|
|
211
|
-
|
|
212
|
-
if session is None:
|
|
236
|
+
if sid not in SESSIONS and sid not in _session_mod.PENDING_SESSIONS:
|
|
213
237
|
raise HTTPException(status_code=404, detail="Session not found")
|
|
214
238
|
journals = _session_mod.VIEWER_PHASE_JOURNALS.get(sid, {})
|
|
215
239
|
journal = journals.get(request_id, {})
|
|
@@ -422,6 +422,16 @@ def get_short_viewer_ui(
|
|
|
422
422
|
navigation_key: str,
|
|
423
423
|
):
|
|
424
424
|
"""Resolve a private integrated-browser launch without exposing its query."""
|
|
425
|
+
try:
|
|
426
|
+
from arrayview._launch_trace import emit_route_launch_event
|
|
427
|
+
|
|
428
|
+
emit_route_launch_event(
|
|
429
|
+
"page.route_entered",
|
|
430
|
+
navigation_key=navigation_key,
|
|
431
|
+
tab_key=tab_key,
|
|
432
|
+
)
|
|
433
|
+
except Exception:
|
|
434
|
+
pass
|
|
425
435
|
owner = _session_mod.VIEWER_LAUNCH_ROUTES.get(navigation_key)
|
|
426
436
|
if owner is None:
|
|
427
437
|
raise HTTPException(status_code=404, detail="Viewer launch route expired")
|
|
@@ -437,6 +447,18 @@ def get_short_viewer_ui(
|
|
|
437
447
|
or journal.get("navigation_key") != navigation_key
|
|
438
448
|
):
|
|
439
449
|
raise HTTPException(status_code=409, detail="Viewer launch route changed")
|
|
450
|
+
try:
|
|
451
|
+
from arrayview._launch_trace import emit_route_launch_event
|
|
452
|
+
|
|
453
|
+
emit_route_launch_event(
|
|
454
|
+
"page.route_resolved",
|
|
455
|
+
navigation_key=navigation_key,
|
|
456
|
+
tab_key=tab_key,
|
|
457
|
+
request_id=request_id,
|
|
458
|
+
navigation_attempt=journal["navigation_attempt"],
|
|
459
|
+
)
|
|
460
|
+
except Exception:
|
|
461
|
+
pass
|
|
440
462
|
bootstrap_query = journal["viewer_query"] + "&" + urlencode(
|
|
441
463
|
{
|
|
442
464
|
"_av_integrated_browser": "1",
|