metaflow 2.18.8__py2.py3-none-any.whl → 2.18.10__py2.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.
- metaflow/cards.py +3 -0
- metaflow/includefile.py +25 -3
- metaflow/parameters.py +4 -0
- metaflow/plugins/__init__.py +1 -0
- metaflow/plugins/argo/argo_workflows.py +6 -7
- metaflow/plugins/cards/card_modules/bundle.css +1 -1
- metaflow/plugins/cards/card_modules/components.py +341 -0
- metaflow/plugins/cards/card_modules/json_viewer.py +232 -0
- metaflow/plugins/cards/card_modules/main.js +54 -39
- metaflow/plugins/datatools/s3/s3op.py +14 -2
- metaflow/plugins/parsers.py +16 -0
- metaflow/runner/click_api.py +12 -0
- metaflow/version.py +1 -1
- {metaflow-2.18.8.data → metaflow-2.18.10.data}/data/share/metaflow/devtools/Tiltfile +77 -2
- {metaflow-2.18.8.data → metaflow-2.18.10.data}/data/share/metaflow/devtools/pick_services.sh +1 -0
- {metaflow-2.18.8.dist-info → metaflow-2.18.10.dist-info}/METADATA +2 -2
- {metaflow-2.18.8.dist-info → metaflow-2.18.10.dist-info}/RECORD +22 -20
- {metaflow-2.18.8.data → metaflow-2.18.10.data}/data/share/metaflow/devtools/Makefile +0 -0
- {metaflow-2.18.8.dist-info → metaflow-2.18.10.dist-info}/WHEEL +0 -0
- {metaflow-2.18.8.dist-info → metaflow-2.18.10.dist-info}/entry_points.txt +0 -0
- {metaflow-2.18.8.dist-info → metaflow-2.18.10.dist-info}/licenses/LICENSE +0 -0
- {metaflow-2.18.8.dist-info → metaflow-2.18.10.dist-info}/top_level.txt +0 -0
metaflow/cards.py
CHANGED
metaflow/includefile.py
CHANGED
@@ -7,9 +7,10 @@ import json
|
|
7
7
|
import os
|
8
8
|
|
9
9
|
from hashlib import sha1
|
10
|
-
from typing import Any, Callable, Dict, Optional
|
10
|
+
from typing import Any, Callable, Dict, Optional, Union
|
11
11
|
|
12
12
|
from metaflow._vendor import click
|
13
|
+
from metaflow._vendor import yaml
|
13
14
|
|
14
15
|
from .exception import MetaflowException
|
15
16
|
from .parameters import (
|
@@ -20,7 +21,7 @@ from .parameters import (
|
|
20
21
|
)
|
21
22
|
|
22
23
|
from .plugins import DATACLIENTS
|
23
|
-
from .user_configs.
|
24
|
+
from .user_configs.config_options import ConfigInput
|
24
25
|
from .util import get_username
|
25
26
|
|
26
27
|
import functools
|
@@ -261,6 +262,12 @@ class IncludeFile(Parameter):
|
|
261
262
|
show_default : bool, default True
|
262
263
|
If True, show the default value in the help text. A value of None is equivalent
|
263
264
|
to True.
|
265
|
+
parser : Union[str, Callable[[str], Any]], optional, default None
|
266
|
+
If a callable, it is a function that can parse the file contents
|
267
|
+
into any desired format. If a string, the string should refer to
|
268
|
+
a function (like "my_parser_package.my_parser.my_parser_function") which should
|
269
|
+
be able to parse the file contents. If the name starts with a ".", it is assumed
|
270
|
+
to be relative to "metaflow".
|
264
271
|
"""
|
265
272
|
|
266
273
|
def __init__(
|
@@ -270,6 +277,7 @@ class IncludeFile(Parameter):
|
|
270
277
|
is_text: Optional[bool] = None,
|
271
278
|
encoding: Optional[str] = None,
|
272
279
|
help: Optional[str] = None,
|
280
|
+
parser: Optional[Union[str, Callable[[str], Any]]] = None,
|
273
281
|
**kwargs: Dict[str, str]
|
274
282
|
):
|
275
283
|
self._includefile_overrides = {}
|
@@ -277,6 +285,7 @@ class IncludeFile(Parameter):
|
|
277
285
|
self._includefile_overrides["is_text"] = is_text
|
278
286
|
if encoding is not None:
|
279
287
|
self._includefile_overrides["encoding"] = encoding
|
288
|
+
self._parser = parser
|
280
289
|
# NOTA: Right now, there is an issue where these can't be overridden by config
|
281
290
|
# in all circumstances. Ignoring for now.
|
282
291
|
super(IncludeFile, self).__init__(
|
@@ -336,7 +345,20 @@ class IncludeFile(Parameter):
|
|
336
345
|
def load_parameter(self, v):
|
337
346
|
if v is None:
|
338
347
|
return v
|
339
|
-
|
348
|
+
|
349
|
+
# Get the raw content from the file
|
350
|
+
content = v.decode(self.name, var_type="Parameter")
|
351
|
+
# If a parser is specified, use it to parse the content
|
352
|
+
if self._parser is not None:
|
353
|
+
try:
|
354
|
+
return ConfigInput._call_parser(self._parser, content)
|
355
|
+
except Exception as e:
|
356
|
+
raise MetaflowException(
|
357
|
+
"Failed to parse content in parameter '%s' using parser: %s"
|
358
|
+
% (self.name, str(e))
|
359
|
+
) from e
|
360
|
+
|
361
|
+
return content
|
340
362
|
|
341
363
|
@staticmethod
|
342
364
|
def _eval_default(is_text, encoding, default_path):
|
metaflow/parameters.py
CHANGED
@@ -495,6 +495,10 @@ def add_custom_parameters(deploy_mode=False):
|
|
495
495
|
# deploy_mode determines whether deploy-time functions should or should
|
496
496
|
# not be evaluated for this command
|
497
497
|
def wrapper(cmd):
|
498
|
+
# Save the original params once, if they haven't been saved before.
|
499
|
+
if not hasattr(cmd, "original_params"):
|
500
|
+
cmd.original_params = list(cmd.params)
|
501
|
+
|
498
502
|
cmd.has_flow_params = True
|
499
503
|
# Iterate over parameters in reverse order so cmd.params lists options
|
500
504
|
# in the order they are defined in the FlowSpec subclass
|
metaflow/plugins/__init__.py
CHANGED
@@ -170,6 +170,7 @@ DEPLOYER_IMPL_PROVIDERS_DESC = [
|
|
170
170
|
]
|
171
171
|
|
172
172
|
TL_PLUGINS_DESC = [
|
173
|
+
("yaml_parser", ".parsers.yaml_parser"),
|
173
174
|
("requirements_txt_parser", ".pypi.parsers.requirements_txt_parser"),
|
174
175
|
("pyproject_toml_parser", ".pypi.parsers.pyproject_toml_parser"),
|
175
176
|
("conda_environment_yml_parser", ".pypi.parsers.conda_environment_yml_parser"),
|
@@ -1423,11 +1423,7 @@ class ArgoWorkflows(object):
|
|
1423
1423
|
dag_tasks.append(dag_task)
|
1424
1424
|
# End the workflow if we have reached the end of the flow
|
1425
1425
|
if node.type == "end":
|
1426
|
-
return
|
1427
|
-
Template(self.flow.name).dag(
|
1428
|
-
DAGTemplate().fail_fast().tasks(dag_tasks)
|
1429
|
-
)
|
1430
|
-
] + templates, dag_tasks
|
1426
|
+
return templates, dag_tasks
|
1431
1427
|
# For split nodes traverse all the children
|
1432
1428
|
if node.type == "split":
|
1433
1429
|
for n in node.out_funcs:
|
@@ -1550,7 +1546,6 @@ class ArgoWorkflows(object):
|
|
1550
1546
|
parent_foreach,
|
1551
1547
|
seen,
|
1552
1548
|
)
|
1553
|
-
|
1554
1549
|
return _visit(
|
1555
1550
|
self.graph[self._matching_conditional_join(node)],
|
1556
1551
|
exit_node,
|
@@ -1806,7 +1801,11 @@ class ArgoWorkflows(object):
|
|
1806
1801
|
for daemon_template in self._daemon_templates()
|
1807
1802
|
]
|
1808
1803
|
|
1809
|
-
templates,
|
1804
|
+
templates, dag_tasks = _visit(node=self.graph["start"], dag_tasks=daemon_tasks)
|
1805
|
+
# Add the DAG template only after fully traversing the graph so we are guaranteed to have all the dag_tasks collected.
|
1806
|
+
templates.append(
|
1807
|
+
Template(self.flow.name).dag(DAGTemplate().fail_fast().tasks(dag_tasks))
|
1808
|
+
)
|
1810
1809
|
return templates
|
1811
1810
|
|
1812
1811
|
# Visit every node and yield ContainerTemplates.
|
@@ -1 +1 @@
|
|
1
|
-
@import"https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap";code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:#ffffff80}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}:root{--bg: #ffffff;--black: #333;--blue: #0c66de;--dk-grey: #767676;--dk-primary: #ef863b;--dk-secondary: #13172d;--dk-tertiary: #0f426e;--error: #cf483e;--grey: rgba(0, 0, 0, .125);--highlight: #f8d9d8;--lt-blue: #4fa7ff;--lt-grey: #f3f3f3;--lt-lt-grey: #f9f9f9;--lt-primary: #ffcb8b;--lt-secondary: #434d81;--lt-tertiary: #4189c9;--primary: #faab4a;--quadrary: #f8d9d8;--secondary: #2e3454;--tertiary: #2a679d;--white: #ffffff;--component-spacer: 3rem;--aside-width: 20rem;--embed-card-min-height: 12rem;--mono-font: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", monospace}html,body{margin:0;min-height:100vh;overflow-y:visible;padding:0;width:100%}.card_app{width:100%;min-height:100vh}.embed .card_app{min-height:var(--embed-card-min-height)}.mf-card *{box-sizing:border-box}.mf-card{background:var(--bg);color:var(--black);font-family:Roboto,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:14px;font-weight:400;line-height:1.5;text-size-adjust:100%;margin:0;min-height:100vh;overflow-y:visible;padding:0;text-align:left;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;width:100%}.embed .mf-card{min-height:var(--embed-card-min-height)}.mf-card :is(.mono,code.mono,pre.mono){font-family:var(--mono-font);font-weight:lighter}.mf-card :is(table,th,td){border-spacing:1px;text-align:center;color:var(--black)}.mf-card table{position:relative;min-width:100%;table-layout:inherit!important}.mf-card td{padding:.66rem 1.25rem;background:var(--lt-lt-grey);border:none}.mf-card th{border:none;color:var(--dk-grey);font-weight:400;padding:.5rem}.mf-card :is(h1,h2,h3,h4,h5){font-weight:700;margin:.5rem 0}.mf-card ul{margin:0;padding:0}.mf-card p{margin:0 0 1rem}.mf-card p:last-of-type{margin:0}.mf-card button{font-size:1rem}.mf-card .textButton{cursor:pointer;text-align:left;background:none;border:1px solid transparent;outline:none;padding:0}.mf-card :is(button.textButton:focus,a:focus,button.textButton:active){border:1px dashed var(--grey);background:transparent}.mf-card button.textButton:hover{color:var(--blue);text-decoration:none}.mf-card :is(:not(pre)>code[class*=language-],pre[class*=language-]){background:transparent!important;text-shadow:none;-webkit-user-select:auto;user-select:auto}aside.svelte-1okdv0e{display:none;line-height:2;text-align:left}@media (min-width: 60rem){aside.svelte-1okdv0e{display:flex;flex-direction:column;height:100vh;justify-content:space-between;padding:2.5rem 0 1.5rem 1.5rem;position:fixed;width:var(--aside-width)}}.embed aside{display:none}aside ul{list-style-type:none}aside a,aside button,aside a:visited{text-decoration:none;cursor:pointer;font-weight:700;color:var(--black)}aside a:hover,aside button:hover{text-decoration:underline}.logoContainer svg{width:100%;max-width:140px;margin-bottom:3.75rem;height:auto}.idCell.svelte-pt8vzv{font-weight:700;text-align:right;background:var(--lt-grey);width:12%}.codeCell.svelte-pt8vzv{text-align:left;-webkit-user-select:all;user-select:all}.container.svelte-ubs992{width:100%;overflow:auto}table.svelte-ubs992{width:100%}:root{--dag-border: #282828;--dag-bg-static: var(--lt-grey);--dag-bg-success: #a5d46a;--dag-bg-running: #ffdf80;--dag-bg-error: #ffa080;--dag-connector: #cccccc;--dag-gap: 5rem;--dag-step-height: 6.25rem;--dag-step-width: 11.25rem;--dag-selected: #ffd700}.connectorwrapper.svelte-19jpdwh{transform-origin:0 0;position:absolute;z-index:0;min-width:var(--strokeWidth)}.flip.svelte-19jpdwh{transform:scaleX(-1)}.path.svelte-19jpdwh{--strokeWidth:.5rem;--strokeColor:var(--dag-connector);--borderRadius:1.25rem;box-sizing:border-box}.straightLine.svelte-19jpdwh{position:absolute;top:0;bottom:0;left:0;right:0;border-left:var(--strokeWidth) solid var(--strokeColor)}.loop.svelte-19jpdwh{position:absolute;top:-50%;left:0;width:100%;height:100%;border-radius:var(--borderRadius);border:var(--strokeWidth) solid var(--strokeColor)}.topLeft.svelte-19jpdwh{position:absolute;top:0;left:0;right:50%;bottom:calc(var(--dag-gap) / 2 - var(--strokeWidth) / 2);border-radius:0 0 0 var(--borderRadius);border-left:var(--strokeWidth) solid var(--strokeColor);border-bottom:var(--strokeWidth) solid var(--strokeColor)}.bottomRight.svelte-19jpdwh{position:absolute;top:calc(100% - (var(--dag-gap) / 2 + var(--strokeWidth) / 2));left:50%;right:0;bottom:0;border-radius:0 var(--borderRadius) 0 0;border-top:var(--strokeWidth) solid var(--strokeColor);border-right:var(--strokeWidth) solid var(--strokeColor)}.wrapper.svelte-117ceti.svelte-117ceti{position:relative;z-index:1}.step.svelte-117ceti.svelte-117ceti{font-size:.75rem;padding:.5rem;color:var(--dk-grey)}.rectangle.svelte-117ceti.svelte-117ceti{background-color:var(--dag-bg-static);border:1px solid var(--dag-border);box-sizing:border-box;position:relative;height:var(--dag-step-height);width:var(--dag-step-width)}.rectangle.error.svelte-117ceti.svelte-117ceti{background-color:var(--dag-bg-error)}.rectangle.success.svelte-117ceti.svelte-117ceti{background-color:var(--dag-bg-success)}.rectangle.running.svelte-117ceti.svelte-117ceti{background-color:var(--dag-bg-running)}.level.svelte-117ceti.svelte-117ceti{z-index:-1;filter:contrast(.5);position:absolute}.inner.svelte-117ceti.svelte-117ceti{position:relative;height:100%;width:100%}.name.svelte-117ceti.svelte-117ceti{font-weight:700;overflow:hidden;text-overflow:ellipsis;display:block}.description.svelte-117ceti.svelte-117ceti{position:absolute;max-height:4rem;bottom:0;left:0;right:0;overflow:hidden;-webkit-line-clamp:4;line-clamp:4;display:-webkit-box;-webkit-box-orient:vertical}.overflown.description.svelte-117ceti.svelte-117ceti{cursor:help}.current.svelte-117ceti .rectangle.svelte-117ceti{box-shadow:0 0 10px var(--dag-selected)}.levelstoshow.svelte-117ceti.svelte-117ceti{position:absolute;bottom:100%;right:0;font-size:.75rem;font-weight:100;text-align:right}.stepwrapper.svelte-18aex7a{display:flex;align-items:center;flex-direction:column;width:100%;position:relative;min-width:var(--dag-step-width)}.childwrapper.svelte-18aex7a{display:flex;width:100%}.gap.svelte-18aex7a{height:var(--dag-gap)}.title.svelte-117s0ws{text-align:left}.subtitle.svelte-lu9pnn{font-size:1rem;text-align:left}header.svelte-1ugmt5d{margin-bottom:var(--component-spacer)}figure.svelte-1x96yvr{background:var(--lt-grey);padding:1rem;border-radius:5px;text-align:center;margin:0 auto var(--component-spacer)}@media (min-width: 60rem){figure.svelte-1x96yvr{margin-bottom:0}}img.svelte-1x96yvr{max-width:100%;max-height:500px}.label.svelte-1x96yvr{font-weight:700;margin:.5rem 0}.description.svelte-1x96yvr{font-size:.9rem;font-style:italic;text-align:center;margin:.5rem 0}.log.svelte-1jhmsu{background:var(--lt-grey)!important;font-size:.9rem;padding:2rem}.page.svelte-v7ihqd:last-of-type{margin-bottom:var(--component-spacer)}.page:last-of-type section:last-of-type hr{display:none}progress.svelte-ljrmzp::-webkit-progress-bar{background-color:#fff!important;min-width:100%}progress.svelte-ljrmzp{background-color:#fff;color:#326cded9!important}progress.svelte-ljrmzp::-moz-progress-bar{background-color:#326cde!important}table .container{background:transparent!important;font-size:10px!important;padding:0!important}table progress{height:4px!important}.container.svelte-ljrmzp{display:flex;align-items:center;justify-content:center;font-size:12px;border-radius:3px;background:#edf5ff;padding:3rem}.inner.svelte-ljrmzp{max-width:410px;width:100%;text-align:center}.info.svelte-ljrmzp{display:flex;justify-content:space-between}table .info{text-align:left;flex-direction:column}label.svelte-ljrmzp{font-weight:700}.labelValue.svelte-ljrmzp{border-left:1px solid rgba(0,0,0,.1);margin-left:.25rem;padding-left:.5rem}.details.svelte-ljrmzp{font-family:var(--mono-font);font-size:8px;color:#333433;line-height:18px;overflow:hidden;white-space:nowrap}progress.svelte-ljrmzp{width:100%;border:none;border-radius:5px;height:8px;background:#fff}.heading.svelte-17n0qr8{margin-bottom:1.5rem}.sectionItems.svelte-17n0qr8{display:block}.sectionItems .imageContainer{max-height:500px}.container.svelte-17n0qr8{scroll-margin:var(--component-spacer)}hr.svelte-17n0qr8{background:var(--grey);border:none;height:1px;margin:var(--component-spacer) 0;padding:0}@media (min-width: 60rem){.sectionItems.svelte-17n0qr8{display:grid;grid-gap:2rem}}.value-box.svelte-175x1n5.svelte-175x1n5{border-radius:.5rem;padding:1.5rem;box-shadow:0 1px 3px #0000001a,0 1px 2px #0000000f;border:1px solid #e5e7eb;background:#fff;min-height:120px;display:flex;align-items:center}.value-box-content.svelte-175x1n5.svelte-175x1n5{width:100%}.value-box-title.svelte-175x1n5.svelte-175x1n5{font-size:.875rem;font-weight:500;color:#6b7280;margin:0 0 .5rem;text-transform:uppercase;letter-spacing:.025em}.value-box-value.svelte-175x1n5.svelte-175x1n5{font-size:2rem;font-weight:700;color:#111827;line-height:1.2;margin:0 0 .5rem}.value-box-subtitle.svelte-175x1n5.svelte-175x1n5{font-size:.875rem;color:#6b7280;margin:0 0 .5rem}.value-box-change.svelte-175x1n5.svelte-175x1n5{font-size:.75rem;font-weight:500;color:#059669;text-transform:uppercase;letter-spacing:.025em}.value-box.default.svelte-175x1n5.svelte-175x1n5{background:#fff;border-color:#e5e7eb}.value-box.bg-gradient-indigo-purple.svelte-175x1n5.svelte-175x1n5{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none}.value-box.bg-gradient-indigo-purple.svelte-175x1n5 .value-box-title.svelte-175x1n5,.value-box.bg-gradient-indigo-purple.svelte-175x1n5 .value-box-subtitle.svelte-175x1n5{color:#fffc}.value-box.bg-gradient-indigo-purple.svelte-175x1n5 .value-box-value.svelte-175x1n5{color:#fff}.value-box.bg-gradient-indigo-purple.svelte-175x1n5 .value-box-change.svelte-175x1n5{color:#ffffffe6}.value-box.success.svelte-175x1n5.svelte-175x1n5{background:#f0fdf4;border-color:#bbf7d0}.value-box.success.svelte-175x1n5 .value-box-value.svelte-175x1n5{color:#065f46}.value-box.success.svelte-175x1n5 .value-box-change.svelte-175x1n5{color:#059669}.value-box.warning.svelte-175x1n5.svelte-175x1n5{background:#fffbeb;border-color:#fed7aa}.value-box.warning.svelte-175x1n5 .value-box-value.svelte-175x1n5{color:#92400e}.value-box.warning.svelte-175x1n5 .value-box-change.svelte-175x1n5{color:#d97706}.value-box.danger.svelte-175x1n5.svelte-175x1n5{background:#fef2f2;border-color:#fecaca}.value-box.danger.svelte-175x1n5 .value-box-value.svelte-175x1n5{color:#991b1b}.value-box.danger.svelte-175x1n5 .value-box-change.svelte-175x1n5{color:#dc2626}@media (max-width: 640px){.value-box.svelte-175x1n5.svelte-175x1n5{padding:1rem;min-height:100px}.value-box-value.svelte-175x1n5.svelte-175x1n5{font-size:1.5rem}}table .value-box{min-height:auto;padding:.75rem;margin:.25rem 0}table .value-box-value{font-size:1.25rem}td.svelte-gl9h79{text-align:left}td.labelColumn.svelte-gl9h79{text-align:right;background-color:var(--lt-grey);font-weight:700;width:12%;white-space:nowrap}.tableContainer.svelte-q3hq57{overflow:auto}th.svelte-q3hq57{position:sticky;top:-1px;z-index:2;white-space:nowrap;background:var(--white)}.mainContainer.svelte-mqeomk{max-width:110rem}main.svelte-mqeomk{flex:0 1 auto;max-width:100rem;padding:1.5rem}@media (min-width: 60rem){main.svelte-mqeomk{margin-left:var(--aside-width)}}.embed main{margin:0 auto;min-width:80%}.modal.svelte-1hhf5ym{align-items:center;background:#00000080;bottom:0;cursor:pointer;display:flex;height:100%;justify-content:center;left:0;overflow:hidden;position:fixed;right:0;top:0;width:100%;z-index:100}.modalContainer>*{background-color:#fff;border-radius:5px;cursor:default;flex:0 1 auto;padding:1rem;position:relative}.modal img{max-height:80vh!important}.cancelButton.svelte-1hhf5ym{color:#fff;cursor:pointer;font-size:2rem;position:absolute;right:1rem;top:1rem}.cancelButton.svelte-1hhf5ym:hover{color:var(--blue)}.nav.svelte-1kdpgko.svelte-1kdpgko{border-radius:0 0 5px;display:none;margin:0;top:0}ul.navList.svelte-1kdpgko.svelte-1kdpgko{list-style-type:none}ul.navList.svelte-1kdpgko ul.svelte-1kdpgko{margin:.5rem 1rem 2rem}.navList.svelte-1kdpgko li.svelte-1kdpgko{display:block;margin:0}.navItem.svelte-1kdpgko li.svelte-1kdpgko:hover{color:var(--blue)}.pageId.svelte-1kdpgko.svelte-1kdpgko{display:block;border-bottom:1px solid var(--grey);padding:0 .5rem;margin-bottom:1rem}@media (min-width: 60rem){.nav.svelte-1kdpgko.svelte-1kdpgko{display:block}ul.navList.svelte-1kdpgko.svelte-1kdpgko{text-align:left}.navList.svelte-1kdpgko li.svelte-1kdpgko{display:block;margin:.5rem 0}}.container.svelte-teyund{width:100%;display:flex;flex-direction:column;position:relative}
|
1
|
+
@import"https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap";code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:#ffffff80}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}:root{--bg: #ffffff;--black: #333;--blue: #0c66de;--dk-grey: #767676;--dk-primary: #ef863b;--dk-secondary: #13172d;--dk-tertiary: #0f426e;--error: #cf483e;--grey: rgba(0, 0, 0, .125);--highlight: #f8d9d8;--lt-blue: #4fa7ff;--lt-grey: #f3f3f3;--lt-lt-grey: #f9f9f9;--lt-primary: #ffcb8b;--lt-secondary: #434d81;--lt-tertiary: #4189c9;--primary: #faab4a;--quadrary: #f8d9d8;--secondary: #2e3454;--tertiary: #2a679d;--white: #ffffff;--component-spacer: 3rem;--aside-width: 20rem;--embed-card-min-height: 12rem;--mono-font: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", monospace}html,body{margin:0;min-height:100vh;overflow-y:visible;padding:0;width:100%}.card_app{width:100%;min-height:100vh}.embed .card_app{min-height:var(--embed-card-min-height)}.mf-card *{box-sizing:border-box}.mf-card{background:var(--bg);color:var(--black);font-family:Roboto,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:14px;font-weight:400;line-height:1.5;text-size-adjust:100%;margin:0;min-height:100vh;overflow-y:visible;padding:0;text-align:left;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;width:100%}.embed .mf-card{min-height:var(--embed-card-min-height)}.mf-card :is(.mono,code.mono,pre.mono){font-family:var(--mono-font);font-weight:lighter}.mf-card :is(table,th,td){border-spacing:1px;text-align:center;color:var(--black)}.mf-card table{position:relative;min-width:100%;table-layout:inherit!important}.mf-card td{padding:.66rem 1.25rem;background:var(--lt-lt-grey);border:none}.mf-card th{border:none;color:var(--dk-grey);font-weight:400;padding:.5rem}.mf-card :is(h1,h2,h3,h4,h5){font-weight:700;margin:.5rem 0}.mf-card ul{margin:0;padding:0}.mf-card p{margin:0 0 1rem}.mf-card p:last-of-type{margin:0}.mf-card button{font-size:1rem}.mf-card .textButton{cursor:pointer;text-align:left;background:none;border:1px solid transparent;outline:none;padding:0}.mf-card :is(button.textButton:focus,a:focus,button.textButton:active){border:1px dashed var(--grey);background:transparent}.mf-card button.textButton:hover{color:var(--blue);text-decoration:none}.mf-card :is(:not(pre)>code[class*=language-],pre[class*=language-]){background:transparent!important;text-shadow:none;-webkit-user-select:auto;user-select:auto}aside.svelte-1okdv0e{display:none;line-height:2;text-align:left}@media (min-width: 60rem){aside.svelte-1okdv0e{display:flex;flex-direction:column;height:100vh;justify-content:space-between;padding:2.5rem 0 1.5rem 1.5rem;position:fixed;width:var(--aside-width)}}.embed aside{display:none}aside ul{list-style-type:none}aside a,aside button,aside a:visited{text-decoration:none;cursor:pointer;font-weight:700;color:var(--black)}aside a:hover,aside button:hover{text-decoration:underline}.logoContainer svg{width:100%;max-width:140px;margin-bottom:3.75rem;height:auto}.idCell.svelte-pt8vzv{font-weight:700;text-align:right;background:var(--lt-grey);width:12%}.codeCell.svelte-pt8vzv{text-align:left;-webkit-user-select:all;user-select:all}.container.svelte-ubs992{width:100%;overflow:auto}table.svelte-ubs992{width:100%}:root{--dag-border: #282828;--dag-bg-static: var(--lt-grey);--dag-bg-success: #a5d46a;--dag-bg-running: #ffdf80;--dag-bg-error: #ffa080;--dag-connector: #cccccc;--dag-gap: 5rem;--dag-step-height: 6.25rem;--dag-step-width: 11.25rem;--dag-selected: #ffd700}.connectorwrapper.svelte-19jpdwh{transform-origin:0 0;position:absolute;z-index:0;min-width:var(--strokeWidth)}.flip.svelte-19jpdwh{transform:scaleX(-1)}.path.svelte-19jpdwh{--strokeWidth:.5rem;--strokeColor:var(--dag-connector);--borderRadius:1.25rem;box-sizing:border-box}.straightLine.svelte-19jpdwh{position:absolute;top:0;bottom:0;left:0;right:0;border-left:var(--strokeWidth) solid var(--strokeColor)}.loop.svelte-19jpdwh{position:absolute;top:-50%;left:0;width:100%;height:100%;border-radius:var(--borderRadius);border:var(--strokeWidth) solid var(--strokeColor)}.topLeft.svelte-19jpdwh{position:absolute;top:0;left:0;right:50%;bottom:calc(var(--dag-gap) / 2 - var(--strokeWidth) / 2);border-radius:0 0 0 var(--borderRadius);border-left:var(--strokeWidth) solid var(--strokeColor);border-bottom:var(--strokeWidth) solid var(--strokeColor)}.bottomRight.svelte-19jpdwh{position:absolute;top:calc(100% - (var(--dag-gap) / 2 + var(--strokeWidth) / 2));left:50%;right:0;bottom:0;border-radius:0 var(--borderRadius) 0 0;border-top:var(--strokeWidth) solid var(--strokeColor);border-right:var(--strokeWidth) solid var(--strokeColor)}.wrapper.svelte-117ceti.svelte-117ceti{position:relative;z-index:1}.step.svelte-117ceti.svelte-117ceti{font-size:.75rem;padding:.5rem;color:var(--dk-grey)}.rectangle.svelte-117ceti.svelte-117ceti{background-color:var(--dag-bg-static);border:1px solid var(--dag-border);box-sizing:border-box;position:relative;height:var(--dag-step-height);width:var(--dag-step-width)}.rectangle.error.svelte-117ceti.svelte-117ceti{background-color:var(--dag-bg-error)}.rectangle.success.svelte-117ceti.svelte-117ceti{background-color:var(--dag-bg-success)}.rectangle.running.svelte-117ceti.svelte-117ceti{background-color:var(--dag-bg-running)}.level.svelte-117ceti.svelte-117ceti{z-index:-1;filter:contrast(.5);position:absolute}.inner.svelte-117ceti.svelte-117ceti{position:relative;height:100%;width:100%}.name.svelte-117ceti.svelte-117ceti{font-weight:700;overflow:hidden;text-overflow:ellipsis;display:block}.description.svelte-117ceti.svelte-117ceti{position:absolute;max-height:4rem;bottom:0;left:0;right:0;overflow:hidden;-webkit-line-clamp:4;line-clamp:4;display:-webkit-box;-webkit-box-orient:vertical}.overflown.description.svelte-117ceti.svelte-117ceti{cursor:help}.current.svelte-117ceti .rectangle.svelte-117ceti{box-shadow:0 0 10px var(--dag-selected)}.levelstoshow.svelte-117ceti.svelte-117ceti{position:absolute;bottom:100%;right:0;font-size:.75rem;font-weight:100;text-align:right}.stepwrapper.svelte-18aex7a{display:flex;align-items:center;flex-direction:column;width:100%;position:relative;min-width:var(--dag-step-width)}.childwrapper.svelte-18aex7a{display:flex;width:100%}.gap.svelte-18aex7a{height:var(--dag-gap)}.title.svelte-117s0ws{text-align:left}.subtitle.svelte-lu9pnn{font-size:1rem;text-align:left}header.svelte-1ugmt5d{margin-bottom:var(--component-spacer)}figure.svelte-1x96yvr{background:var(--lt-grey);padding:1rem;border-radius:5px;text-align:center;margin:0 auto var(--component-spacer)}@media (min-width: 60rem){figure.svelte-1x96yvr{margin-bottom:0}}img.svelte-1x96yvr{max-width:100%;max-height:500px}.label.svelte-1x96yvr{font-weight:700;margin:.5rem 0}.description.svelte-1x96yvr{font-size:.9rem;font-style:italic;text-align:center;margin:.5rem 0}.log.svelte-1jhmsu{background:var(--lt-grey)!important;font-size:.9rem;padding:2rem}.page.svelte-v7ihqd:last-of-type{margin-bottom:var(--component-spacer)}.page:last-of-type section:last-of-type hr{display:none}progress.svelte-ljrmzp::-webkit-progress-bar{background-color:#fff!important;min-width:100%}progress.svelte-ljrmzp{background-color:#fff;color:#326cded9!important}progress.svelte-ljrmzp::-moz-progress-bar{background-color:#326cde!important}table .container{background:transparent!important;font-size:10px!important;padding:0!important}table progress{height:4px!important}.container.svelte-ljrmzp{display:flex;align-items:center;justify-content:center;font-size:12px;border-radius:3px;background:#edf5ff;padding:3rem}.inner.svelte-ljrmzp{max-width:410px;width:100%;text-align:center}.info.svelte-ljrmzp{display:flex;justify-content:space-between}table .info{text-align:left;flex-direction:column}label.svelte-ljrmzp{font-weight:700}.labelValue.svelte-ljrmzp{border-left:1px solid rgba(0,0,0,.1);margin-left:.25rem;padding-left:.5rem}.details.svelte-ljrmzp{font-family:var(--mono-font);font-size:8px;color:#333433;line-height:18px;overflow:hidden;white-space:nowrap}progress.svelte-ljrmzp{width:100%;border:none;border-radius:5px;height:8px;background:#fff}.heading.svelte-17n0qr8{margin-bottom:1.5rem}.sectionItems.svelte-17n0qr8{display:block}.sectionItems .imageContainer{max-height:500px}.container.svelte-17n0qr8{scroll-margin:var(--component-spacer)}hr.svelte-17n0qr8{background:var(--grey);border:none;height:1px;margin:var(--component-spacer) 0;padding:0}@media (min-width: 60rem){.sectionItems.svelte-17n0qr8{display:grid;grid-gap:2rem}}.value-box.svelte-175x1n5.svelte-175x1n5{border-radius:.5rem;padding:1.5rem;box-shadow:0 1px 3px #0000001a,0 1px 2px #0000000f;border:1px solid #e5e7eb;background:#fff;min-height:120px;display:flex;align-items:center}.value-box-content.svelte-175x1n5.svelte-175x1n5{width:100%}.value-box-title.svelte-175x1n5.svelte-175x1n5{font-size:.875rem;font-weight:500;color:#6b7280;margin:0 0 .5rem;text-transform:uppercase;letter-spacing:.025em}.value-box-value.svelte-175x1n5.svelte-175x1n5{font-size:2rem;font-weight:700;color:#111827;line-height:1.2;margin:0 0 .5rem}.value-box-subtitle.svelte-175x1n5.svelte-175x1n5{font-size:.875rem;color:#6b7280;margin:0 0 .5rem}.value-box-change.svelte-175x1n5.svelte-175x1n5{font-size:.75rem;font-weight:500;color:#059669;text-transform:uppercase;letter-spacing:.025em}.value-box.default.svelte-175x1n5.svelte-175x1n5{background:#fff;border-color:#e5e7eb}.value-box.bg-gradient-indigo-purple.svelte-175x1n5.svelte-175x1n5{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none}.value-box.bg-gradient-indigo-purple.svelte-175x1n5 .value-box-title.svelte-175x1n5,.value-box.bg-gradient-indigo-purple.svelte-175x1n5 .value-box-subtitle.svelte-175x1n5{color:#fffc}.value-box.bg-gradient-indigo-purple.svelte-175x1n5 .value-box-value.svelte-175x1n5{color:#fff}.value-box.bg-gradient-indigo-purple.svelte-175x1n5 .value-box-change.svelte-175x1n5{color:#ffffffe6}.value-box.success.svelte-175x1n5.svelte-175x1n5{background:#f0fdf4;border-color:#bbf7d0}.value-box.success.svelte-175x1n5 .value-box-value.svelte-175x1n5{color:#065f46}.value-box.success.svelte-175x1n5 .value-box-change.svelte-175x1n5{color:#059669}.value-box.warning.svelte-175x1n5.svelte-175x1n5{background:#fffbeb;border-color:#fed7aa}.value-box.warning.svelte-175x1n5 .value-box-value.svelte-175x1n5{color:#92400e}.value-box.warning.svelte-175x1n5 .value-box-change.svelte-175x1n5{color:#d97706}.value-box.danger.svelte-175x1n5.svelte-175x1n5{background:#fef2f2;border-color:#fecaca}.value-box.danger.svelte-175x1n5 .value-box-value.svelte-175x1n5{color:#991b1b}.value-box.danger.svelte-175x1n5 .value-box-change.svelte-175x1n5{color:#dc2626}@media (max-width: 640px){.value-box.svelte-175x1n5.svelte-175x1n5{padding:1rem;min-height:100px}.value-box-value.svelte-175x1n5.svelte-175x1n5{font-size:1.5rem}}table .value-box{min-height:auto;padding:.75rem;margin:.25rem 0}table .value-box-value{font-size:1.25rem}.events-container.svelte-11m3hns.svelte-11m3hns{border:1px solid #e5e7eb;border-radius:.5rem;background:#fff;padding:1rem;margin-bottom:1rem}.events-title.svelte-11m3hns.svelte-11m3hns{font-size:1.25rem;font-weight:600;color:#111827;margin:0 0 1rem;padding-bottom:.5rem;border-bottom:2px solid #e5e7eb}.stats-header.svelte-11m3hns.svelte-11m3hns{display:flex;justify-content:space-between;align-items:center;padding:.5rem .75rem;margin-bottom:1rem;border-radius:.375rem;font-size:.875rem;border:1px solid #e5e7eb}.stats-header.live.svelte-11m3hns.svelte-11m3hns{background:#f0fdf4;border-color:#bbf7d0}.stats-header.recent.svelte-11m3hns.svelte-11m3hns{background:#fffbeb;border-color:#fed7aa}.stats-header.stale.svelte-11m3hns.svelte-11m3hns{background:#fef2f2;border-color:#fecaca}.stats-indicator.svelte-11m3hns.svelte-11m3hns{display:flex;align-items:center;gap:.5rem}.live-dot.svelte-11m3hns.svelte-11m3hns{width:10px;height:10px;border-radius:50%;background:#10b981;box-shadow:0 0 0 2px #10b98133;transition:all .3s ease}.stats-header.live.svelte-11m3hns .live-dot.svelte-11m3hns{background:#10b981;box-shadow:0 0 0 2px #10b9814d,0 0 8px #10b98166;animation:svelte-11m3hns-livePulse 2s infinite}.stats-header.recent.svelte-11m3hns .live-dot.svelte-11m3hns{background:#f59e0b;box-shadow:0 0 0 2px #f59e0b33}.stats-header.stale.svelte-11m3hns .live-dot.svelte-11m3hns{background:#ef4444;box-shadow:0 0 0 2px #ef444433}.stats-header.finished.svelte-11m3hns.svelte-11m3hns{background:#f0f9ff;border-color:#bae6fd}.stats-header.finished.svelte-11m3hns .live-dot.svelte-11m3hns{background:#0ea5e9;box-shadow:0 0 0 2px #0ea5e933}.status-text.svelte-11m3hns.svelte-11m3hns{font-weight:500;color:#374151}.stats-info.svelte-11m3hns.svelte-11m3hns{display:flex;gap:1rem;font-size:.8125rem;color:#6b7280}.stat-item.svelte-11m3hns.svelte-11m3hns{white-space:nowrap}.no-events.svelte-11m3hns.svelte-11m3hns{text-align:center;padding:2rem;color:#6b7280;font-style:italic}.events-timeline.svelte-11m3hns.svelte-11m3hns{position:relative;padding-left:2rem}.events-timeline.svelte-11m3hns.svelte-11m3hns:before{content:"";position:absolute;left:.75rem;top:0;bottom:0;width:2px;background:linear-gradient(to bottom,#3b82f6,#e5e7eb)}.event-item.svelte-11m3hns.svelte-11m3hns{position:relative;margin-bottom:1.5rem;padding-left:1rem}.event-item.svelte-11m3hns.svelte-11m3hns:last-child{margin-bottom:0}.event-marker.svelte-11m3hns.svelte-11m3hns{position:absolute;left:-1.525rem;top:0;width:.75rem;height:.75rem;border-radius:50%;background:#3b82f6;border:2px solid white;box-shadow:0 0 0 2px #3b82f6;z-index:1}.event-item.latest.svelte-11m3hns .event-marker.svelte-11m3hns{background:#10b981;box-shadow:0 0 0 2px #10b9814d;animation:svelte-11m3hns-markerPulse 2s infinite}@keyframes svelte-11m3hns-livePulse{0%,to{transform:scale(1);box-shadow:0 0 0 2px #10b9814d,0 0 8px #10b98166}50%{transform:scale(1.1);box-shadow:0 0 0 4px #10b98133,0 0 12px #10b98199}}@keyframes svelte-11m3hns-markerPulse{0%,to{box-shadow:0 0 0 2px #10b9814d}50%{box-shadow:0 0 0 4px #10b98180}}.event-content.svelte-11m3hns.svelte-11m3hns{background:#f9fafb;border:1px solid #e5e7eb;border-radius:.375rem;padding:.75rem;box-shadow:0 1px 2px #0000000d}.event-item.latest.svelte-11m3hns .event-content.svelte-11m3hns{background:#f0f9ff;border-color:#3b82f6}.event-item.theme-success.svelte-11m3hns .event-content.svelte-11m3hns{background:#f0fdf4;border-color:#bbf7d0}.event-item.theme-success.svelte-11m3hns .event-marker.svelte-11m3hns{background:#10b981;box-shadow:0 0 0 2px #10b981}.event-item.theme-error.svelte-11m3hns .event-content.svelte-11m3hns{background:#fef2f2;border-color:#fecaca}.event-item.theme-error.svelte-11m3hns .event-marker.svelte-11m3hns{background:#ef4444;box-shadow:0 0 0 2px #ef4444}.event-item.theme-warning.svelte-11m3hns .event-content.svelte-11m3hns{background:#fffbeb;border-color:#fed7aa}.event-item.theme-warning.svelte-11m3hns .event-marker.svelte-11m3hns{background:#f59e0b;box-shadow:0 0 0 2px #f59e0b}.event-item.theme-info.svelte-11m3hns .event-content.svelte-11m3hns{background:#eff6ff;border-color:#bfdbfe}.event-item.theme-info.svelte-11m3hns .event-marker.svelte-11m3hns{background:#3b82f6;box-shadow:0 0 0 2px #3b82f6}.event-item.theme-tool_call.svelte-11m3hns .event-content.svelte-11m3hns{background:#f3e8ff;border-color:#c4b5fd}.event-item.theme-tool_call.svelte-11m3hns .event-marker.svelte-11m3hns{background:#8b5cf6;box-shadow:0 0 0 2px #8b5cf6}.event-item.theme-ai_response.svelte-11m3hns .event-content.svelte-11m3hns{background:#fdf4ff;border-color:#e9d5ff}.event-item.theme-ai_response.svelte-11m3hns .event-marker.svelte-11m3hns{background:#a855f7;box-shadow:0 0 0 2px #a855f7}.event-item.priority-high.svelte-11m3hns.svelte-11m3hns{border-left:4px solid #f59e0b}.event-item.priority-critical.svelte-11m3hns.svelte-11m3hns{border-left:4px solid #ef4444}.event-meta.svelte-11m3hns.svelte-11m3hns{display:flex;justify-content:space-between;align-items:center;margin-bottom:.5rem;padding-bottom:.5rem;border-bottom:1px solid #e5e7eb;font-size:.75rem;color:#6b7280}.event-time.svelte-11m3hns.svelte-11m3hns{font-weight:500}.event-id.svelte-11m3hns.svelte-11m3hns{font-family:Monaco,Menlo,Ubuntu Mono,monospace;opacity:.7}.event-metadata.svelte-11m3hns.svelte-11m3hns{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:.5rem}.event-payloads.svelte-11m3hns.svelte-11m3hns{margin-top:1rem;border-top:1px solid #e5e7eb;padding-top:.75rem}.payload-section.svelte-11m3hns.svelte-11m3hns{margin-bottom:.75rem;border:1px solid #e5e7eb;border-radius:.375rem;overflow:hidden}.payload-section.svelte-11m3hns.svelte-11m3hns:last-child{margin-bottom:0}.payload-header.svelte-11m3hns.svelte-11m3hns{display:flex;justify-content:space-between;align-items:center;padding:.75rem 1rem;background:#f9fafb;cursor:pointer;-webkit-user-select:none;user-select:none;border-bottom:1px solid #e5e7eb;font-weight:500}.payload-header.svelte-11m3hns.svelte-11m3hns:hover{background:#f3f4f6}.payload-title.svelte-11m3hns.svelte-11m3hns{font-size:.875rem;color:#374151}.payload-type.svelte-11m3hns.svelte-11m3hns{font-size:.75rem;color:#6b7280;background:#e5e7eb;padding:.125rem .5rem;border-radius:.25rem;text-transform:uppercase;letter-spacing:.025em}.payload-content.svelte-11m3hns.svelte-11m3hns{padding:1rem;background:#fff;font-size:inherit;line-height:inherit;color:inherit}.payload-content.svelte-11m3hns>*{margin-bottom:0}.payload-content.svelte-11m3hns>*:not(:last-child){margin-bottom:1rem}.payload-content.svelte-11m3hns pre[data-component=pythonCode]{margin:0;overflow-x:auto}.payload-content.svelte-11m3hns pre[data-component=pythonCode] code{display:block}.payload-content.svelte-11m3hns code:not(pre code){font-family:Monaco,Menlo,Ubuntu Mono,monospace;font-size:.875rem;background:#f1f5f9;padding:.125rem .25rem;border-radius:.25rem}.event-field.svelte-11m3hns.svelte-11m3hns{display:flex;flex-direction:column;gap:.125rem}.field-key.svelte-11m3hns.svelte-11m3hns{font-size:.75rem;font-weight:500;color:#6b7280;text-transform:uppercase;letter-spacing:.025em}.field-value.svelte-11m3hns.svelte-11m3hns{font-size:.875rem;font-weight:400;color:#111827;word-break:break-word;display:inline-block;width:auto}.field-value.timestamp.svelte-11m3hns.svelte-11m3hns{font-family:Monaco,Menlo,Ubuntu Mono,monospace;font-size:.8125rem;color:#6366f1}.field-value.number.svelte-11m3hns.svelte-11m3hns{font-family:Monaco,Menlo,Ubuntu Mono,monospace;color:#059669}.field-value.status.svelte-11m3hns.svelte-11m3hns,.field-value.status-success.svelte-11m3hns.svelte-11m3hns,.field-value.status-error.svelte-11m3hns.svelte-11m3hns,.field-value.status-warning.svelte-11m3hns.svelte-11m3hns,.field-value.status-milestone.svelte-11m3hns.svelte-11m3hns,.field-value.status-completed.svelte-11m3hns.svelte-11m3hns,.field-value.status-finished.svelte-11m3hns.svelte-11m3hns{font-weight:500;text-transform:uppercase;font-size:.75rem;letter-spacing:.025em;padding:.125rem .375rem;border-radius:.25rem;display:inline-flex!important;align-items:center;justify-content:center;background:#f3f4f6;color:#374151;width:fit-content!important;max-width:fit-content!important;min-width:auto!important;flex-shrink:0;white-space:nowrap}.field-value.status-success.svelte-11m3hns.svelte-11m3hns{color:#059669;background:#d1fae5}.field-value.status-error.svelte-11m3hns.svelte-11m3hns{color:#dc2626;background:#fee2e2}.field-value.status-warning.svelte-11m3hns.svelte-11m3hns{color:#d97706;background:#fef3c7}.field-value.status-milestone.svelte-11m3hns.svelte-11m3hns{color:#7c3aed;background:#ede9fe}.field-value.status-completed.svelte-11m3hns.svelte-11m3hns{color:#059669;background:#d1fae5}.field-value.status-finished.svelte-11m3hns.svelte-11m3hns{color:#0ea5e9;background:#e0f2fe}@media (max-width: 640px){.events-container.svelte-11m3hns.svelte-11m3hns{padding:.75rem}.events-timeline.svelte-11m3hns.svelte-11m3hns{padding-left:1.5rem}.stats-info.svelte-11m3hns.svelte-11m3hns{flex-direction:column;gap:.25rem;align-items:flex-end}.event-metadata.svelte-11m3hns.svelte-11m3hns{grid-template-columns:1fr;gap:.375rem}.event-field.svelte-11m3hns.svelte-11m3hns{flex-direction:row;align-items:flex-start;gap:.5rem}.field-key.svelte-11m3hns.svelte-11m3hns{min-width:80px;flex-shrink:0}}table .events-container{margin:.25rem 0;border:none;background:transparent;padding:.5rem}table .events-timeline{padding-left:1rem}table .event-content{padding:.5rem}table .stats-header{font-size:.75rem;padding:.375rem .5rem}.json-viewer.svelte-1b8g4ty.svelte-1b8g4ty{border:1px solid #e5e7eb;border-radius:.375rem;background:#f9fafb;margin:.5rem 0;overflow:hidden}.json-header.svelte-1b8g4ty.svelte-1b8g4ty{display:flex;justify-content:space-between;align-items:center;padding:.5rem .75rem;background:#f3f4f6;border-bottom:1px solid #e5e7eb;font-size:.875rem;font-weight:500}.collapse-button.svelte-1b8g4ty.svelte-1b8g4ty{display:flex;align-items:center;gap:.5rem;background:none;border:none;color:#374151;cursor:pointer;font-size:.875rem;font-weight:500}.collapse-button.svelte-1b8g4ty.svelte-1b8g4ty:hover{color:#111827}.collapse-icon.svelte-1b8g4ty.svelte-1b8g4ty{transition:transform .2s ease;font-size:.75rem}.collapse-icon.collapsed.svelte-1b8g4ty.svelte-1b8g4ty{transform:rotate(-90deg)}.json-label.svelte-1b8g4ty.svelte-1b8g4ty{color:#374151;font-weight:500}.copy-button.svelte-1b8g4ty.svelte-1b8g4ty{background:#3b82f6;color:#fff;border:none;border-radius:.25rem;padding:.25rem .5rem;font-size:.75rem;cursor:pointer;transition:all .2s ease}.copy-button.svelte-1b8g4ty.svelte-1b8g4ty:hover{background:#2563eb}.copy-button.success.svelte-1b8g4ty.svelte-1b8g4ty{background:#10b981}.json-content.svelte-1b8g4ty.svelte-1b8g4ty{overflow:auto;max-height:400px}.json-code.svelte-1b8g4ty.svelte-1b8g4ty{margin:0;padding:0;background:transparent;border:none;overflow:visible}.json-code.svelte-1b8g4ty code.svelte-1b8g4ty{display:block;padding:1rem;font-family:Monaco,Menlo,Ubuntu Mono,monospace;font-size:.8125rem;line-height:1.5;background:transparent;color:#374151;white-space:pre-wrap;word-break:break-word;border:none}@media (max-width: 640px){.json-header.svelte-1b8g4ty.svelte-1b8g4ty{padding:.375rem .5rem;font-size:.8125rem}.json-code.svelte-1b8g4ty.svelte-1b8g4ty{padding:.75rem .5rem;font-size:.75rem}.copy-button.svelte-1b8g4ty.svelte-1b8g4ty{padding:.1875rem .375rem;font-size:.6875rem}}table .json-viewer{margin:.25rem 0;font-size:.75rem}table .json-content{max-height:200px}table .json-code{padding:.5rem;font-size:.6875rem}.yaml-viewer.svelte-yn00t6.svelte-yn00t6{border:1px solid #e5e7eb;border-radius:.375rem;background:#f9fafb;margin:.5rem 0;overflow:hidden}.yaml-header.svelte-yn00t6.svelte-yn00t6{display:flex;justify-content:space-between;align-items:center;padding:.5rem .75rem;background:#f3f4f6;border-bottom:1px solid #e5e7eb;font-size:.875rem;font-weight:500}.collapse-button.svelte-yn00t6.svelte-yn00t6{display:flex;align-items:center;gap:.5rem;background:none;border:none;color:#374151;cursor:pointer;font-size:.875rem;font-weight:500}.collapse-button.svelte-yn00t6.svelte-yn00t6:hover{color:#111827}.collapse-icon.svelte-yn00t6.svelte-yn00t6{transition:transform .2s ease;font-size:.75rem}.collapse-icon.collapsed.svelte-yn00t6.svelte-yn00t6{transform:rotate(-90deg)}.yaml-label.svelte-yn00t6.svelte-yn00t6{color:#374151;font-weight:500}.copy-button.svelte-yn00t6.svelte-yn00t6{background:#3b82f6;color:#fff;border:none;border-radius:.25rem;padding:.25rem .5rem;font-size:.75rem;cursor:pointer;transition:all .2s ease}.copy-button.svelte-yn00t6.svelte-yn00t6:hover{background:#2563eb}.copy-button.success.svelte-yn00t6.svelte-yn00t6{background:#10b981}.yaml-content.svelte-yn00t6.svelte-yn00t6{overflow:auto;max-height:400px}.yaml-code.svelte-yn00t6.svelte-yn00t6{margin:0;padding:0;background:transparent;border:none;overflow:visible}.yaml-code.svelte-yn00t6 code.svelte-yn00t6{display:block;padding:1rem;font-family:Monaco,Menlo,Ubuntu Mono,monospace;font-size:.8125rem;line-height:1.6;background:transparent;color:#374151;white-space:pre-wrap;word-break:break-word;border:none}@media (max-width: 640px){.yaml-header.svelte-yn00t6.svelte-yn00t6{padding:.375rem .5rem;font-size:.8125rem}.yaml-code.svelte-yn00t6.svelte-yn00t6{padding:.75rem .5rem;font-size:.75rem}.copy-button.svelte-yn00t6.svelte-yn00t6{padding:.1875rem .375rem;font-size:.6875rem}}table .yaml-viewer{margin:.25rem 0;font-size:.75rem}table .yaml-content{max-height:200px}table .yaml-code{padding:.5rem;font-size:.6875rem}td.svelte-gl9h79{text-align:left}td.labelColumn.svelte-gl9h79{text-align:right;background-color:var(--lt-grey);font-weight:700;width:12%;white-space:nowrap}.tableContainer.svelte-q3hq57{overflow:auto}th.svelte-q3hq57{position:sticky;top:-1px;z-index:2;white-space:nowrap;background:var(--white)}.mainContainer.svelte-mqeomk{max-width:110rem}main.svelte-mqeomk{flex:0 1 auto;max-width:100rem;padding:1.5rem}@media (min-width: 60rem){main.svelte-mqeomk{margin-left:var(--aside-width)}}.embed main{margin:0 auto;min-width:80%}.modal.svelte-1hhf5ym{align-items:center;background:#00000080;bottom:0;cursor:pointer;display:flex;height:100%;justify-content:center;left:0;overflow:hidden;position:fixed;right:0;top:0;width:100%;z-index:100}.modalContainer>*{background-color:#fff;border-radius:5px;cursor:default;flex:0 1 auto;padding:1rem;position:relative}.modal img{max-height:80vh!important}.cancelButton.svelte-1hhf5ym{color:#fff;cursor:pointer;font-size:2rem;position:absolute;right:1rem;top:1rem}.cancelButton.svelte-1hhf5ym:hover{color:var(--blue)}.nav.svelte-1kdpgko.svelte-1kdpgko{border-radius:0 0 5px;display:none;margin:0;top:0}ul.navList.svelte-1kdpgko.svelte-1kdpgko{list-style-type:none}ul.navList.svelte-1kdpgko ul.svelte-1kdpgko{margin:.5rem 1rem 2rem}.navList.svelte-1kdpgko li.svelte-1kdpgko{display:block;margin:0}.navItem.svelte-1kdpgko li.svelte-1kdpgko:hover{color:var(--blue)}.pageId.svelte-1kdpgko.svelte-1kdpgko{display:block;border-bottom:1px solid var(--grey);padding:0 .5rem;margin-bottom:1rem}@media (min-width: 60rem){.nav.svelte-1kdpgko.svelte-1kdpgko{display:block}ul.navList.svelte-1kdpgko.svelte-1kdpgko{text-align:left}.navList.svelte-1kdpgko li.svelte-1kdpgko{display:block;margin:.5rem 0}}.container.svelte-teyund{width:100%;display:flex;flex-direction:column;position:relative}
|
@@ -12,6 +12,7 @@ from .basic import (
|
|
12
12
|
from .card import MetaflowCardComponent, with_default_component_id
|
13
13
|
from .convert_to_native_type import TaskToDict, _full_classname
|
14
14
|
from .renderer_tools import render_safely
|
15
|
+
from .json_viewer import JSONViewer as _JSONViewer, YAMLViewer as _YAMLViewer
|
15
16
|
import uuid
|
16
17
|
import inspect
|
17
18
|
|
@@ -1099,3 +1100,343 @@ class PythonCode(UserComponent):
|
|
1099
1100
|
_code_component = PythonCodeComponent(self._code_string)
|
1100
1101
|
_code_component.component_id = self.component_id
|
1101
1102
|
return _code_component.render()
|
1103
|
+
|
1104
|
+
|
1105
|
+
class EventsTimeline(UserComponent):
|
1106
|
+
"""
|
1107
|
+
An events timeline component for displaying structured log messages in real-time.
|
1108
|
+
|
1109
|
+
This component displays events in a timeline format with the latest events at the top.
|
1110
|
+
Each event can contain structured data including other UserComponents for rich display.
|
1111
|
+
|
1112
|
+
Example: Basic usage
|
1113
|
+
```python
|
1114
|
+
@card
|
1115
|
+
@step
|
1116
|
+
def my_step(self):
|
1117
|
+
from metaflow.cards import EventsTimeline
|
1118
|
+
from metaflow import current
|
1119
|
+
|
1120
|
+
# Create an events component
|
1121
|
+
events = EventsTimeline(title="Processing Events")
|
1122
|
+
current.card.append(events)
|
1123
|
+
|
1124
|
+
# Add events during processing
|
1125
|
+
for i in range(10):
|
1126
|
+
events.update(
|
1127
|
+
event_data={
|
1128
|
+
"timestamp": datetime.now().isoformat(),
|
1129
|
+
"event_type": "processing",
|
1130
|
+
"item_id": i,
|
1131
|
+
"status": "completed",
|
1132
|
+
"duration_ms": random.randint(100, 500)
|
1133
|
+
}
|
1134
|
+
)
|
1135
|
+
time.sleep(1)
|
1136
|
+
```
|
1137
|
+
|
1138
|
+
Example: With styling and rich components
|
1139
|
+
```python
|
1140
|
+
from metaflow.cards import EventsTimeline, Markdown, PythonCode
|
1141
|
+
|
1142
|
+
events = EventsTimeline(title="Agent Actions")
|
1143
|
+
current.card.append(events)
|
1144
|
+
|
1145
|
+
# Event with styling
|
1146
|
+
events.update(
|
1147
|
+
event_data={
|
1148
|
+
"action": "tool_call",
|
1149
|
+
"function": "get_weather",
|
1150
|
+
"result": "Success"
|
1151
|
+
},
|
1152
|
+
style_theme="success"
|
1153
|
+
)
|
1154
|
+
|
1155
|
+
# Event with rich components
|
1156
|
+
events.update(
|
1157
|
+
event_data={
|
1158
|
+
"action": "code_execution",
|
1159
|
+
"status": "completed"
|
1160
|
+
},
|
1161
|
+
payloads={
|
1162
|
+
"code": PythonCode(code_string="print('Hello World')"),
|
1163
|
+
"notes": Markdown("**Important**: This ran successfully")
|
1164
|
+
},
|
1165
|
+
style_theme="info"
|
1166
|
+
)
|
1167
|
+
```
|
1168
|
+
|
1169
|
+
Parameters
|
1170
|
+
----------
|
1171
|
+
title : str, optional
|
1172
|
+
Title for the events timeline.
|
1173
|
+
max_events : int, default 100
|
1174
|
+
Maximum number of events to display. Older events are removed from display
|
1175
|
+
but total count is still tracked. Stats and relative time display are always enabled.
|
1176
|
+
"""
|
1177
|
+
|
1178
|
+
type = "eventsTimeline"
|
1179
|
+
|
1180
|
+
REALTIME_UPDATABLE = True
|
1181
|
+
|
1182
|
+
# Valid style themes
|
1183
|
+
VALID_THEMES = {
|
1184
|
+
"default",
|
1185
|
+
"success",
|
1186
|
+
"warning",
|
1187
|
+
"error",
|
1188
|
+
"info",
|
1189
|
+
"primary",
|
1190
|
+
"secondary",
|
1191
|
+
"tool_call",
|
1192
|
+
"ai_response",
|
1193
|
+
}
|
1194
|
+
|
1195
|
+
def __init__(
|
1196
|
+
self,
|
1197
|
+
title: Optional[str] = None,
|
1198
|
+
max_events: int = 100,
|
1199
|
+
):
|
1200
|
+
self._title = title
|
1201
|
+
self._max_events = max_events
|
1202
|
+
self._events = []
|
1203
|
+
|
1204
|
+
# Metadata tracking
|
1205
|
+
self._total_events_count = 0
|
1206
|
+
self._first_event_time = None
|
1207
|
+
self._last_update_time = None
|
1208
|
+
self._finished = False
|
1209
|
+
|
1210
|
+
def update(
|
1211
|
+
self,
|
1212
|
+
event_data: dict,
|
1213
|
+
style_theme: Optional[str] = None,
|
1214
|
+
priority: Optional[str] = None,
|
1215
|
+
payloads: Optional[dict] = None,
|
1216
|
+
finished: Optional[bool] = None,
|
1217
|
+
):
|
1218
|
+
"""
|
1219
|
+
Add a new event to the timeline.
|
1220
|
+
|
1221
|
+
Parameters
|
1222
|
+
----------
|
1223
|
+
event_data : dict
|
1224
|
+
Basic event metadata (strings, numbers, simple values only).
|
1225
|
+
This appears in the main event display area.
|
1226
|
+
style_theme : str, optional
|
1227
|
+
Visual theme for this event. Valid values: 'default', 'success', 'warning',
|
1228
|
+
'error', 'info', 'primary', 'secondary', 'tool_call', 'ai_response'.
|
1229
|
+
priority : str, optional
|
1230
|
+
Priority level for the event ('low', 'normal', 'high', 'critical').
|
1231
|
+
Affects visual prominence.
|
1232
|
+
payloads : dict, optional
|
1233
|
+
Rich payload components that will be displayed in collapsible sections.
|
1234
|
+
Values must be UserComponent instances: ValueBox, Image, Markdown,
|
1235
|
+
Artifact, JSONViewer, YAMLViewer. VegaChart is not supported inside EventsTimeline.
|
1236
|
+
finished : bool, optional
|
1237
|
+
Mark the timeline as finished. When True, the status indicator will show
|
1238
|
+
"Finished" in the header.
|
1239
|
+
"""
|
1240
|
+
import time
|
1241
|
+
|
1242
|
+
# Validate style_theme
|
1243
|
+
if style_theme is not None and style_theme not in self.VALID_THEMES:
|
1244
|
+
import re
|
1245
|
+
|
1246
|
+
if not re.match(r"^[a-zA-Z][a-zA-Z0-9_-]*$", style_theme):
|
1247
|
+
raise ValueError(
|
1248
|
+
f"Invalid style_theme '{style_theme}'. Must be a valid CSS class name."
|
1249
|
+
)
|
1250
|
+
|
1251
|
+
# Validate payloads contain only allowed UserComponents
|
1252
|
+
if payloads is not None:
|
1253
|
+
allowed_components = (
|
1254
|
+
ValueBox,
|
1255
|
+
Image,
|
1256
|
+
Markdown,
|
1257
|
+
Artifact,
|
1258
|
+
PythonCode,
|
1259
|
+
_JSONViewer,
|
1260
|
+
_YAMLViewer,
|
1261
|
+
)
|
1262
|
+
for key, payload in payloads.items():
|
1263
|
+
if not isinstance(payload, allowed_components):
|
1264
|
+
raise TypeError(
|
1265
|
+
f"Payload '{key}' must be one of: ValueBox, Image, Markdown, "
|
1266
|
+
f"Artifact, JSONViewer, YAMLViewer. Got {type(payload).__name__}"
|
1267
|
+
)
|
1268
|
+
|
1269
|
+
# Add timestamp if not provided
|
1270
|
+
if "timestamp" not in event_data:
|
1271
|
+
event_data["timestamp"] = time.time()
|
1272
|
+
|
1273
|
+
# Create event object with metadata and payloads
|
1274
|
+
event = {
|
1275
|
+
"metadata": event_data,
|
1276
|
+
"payloads": payloads or {},
|
1277
|
+
"event_id": f"event_{self._total_events_count}",
|
1278
|
+
"received_at": time.time(),
|
1279
|
+
}
|
1280
|
+
|
1281
|
+
# Add styling metadata if provided
|
1282
|
+
if style_theme is not None:
|
1283
|
+
event["style_theme"] = style_theme
|
1284
|
+
if priority is not None:
|
1285
|
+
event["priority"] = priority
|
1286
|
+
|
1287
|
+
# Update metadata
|
1288
|
+
self._total_events_count += 1
|
1289
|
+
self._last_update_time = time.time()
|
1290
|
+
if self._first_event_time is None:
|
1291
|
+
self._first_event_time = time.time()
|
1292
|
+
|
1293
|
+
# Update finished status if provided
|
1294
|
+
if finished is not None:
|
1295
|
+
self._finished = finished
|
1296
|
+
|
1297
|
+
# Add the event to the beginning of the list (latest first)
|
1298
|
+
self._events.insert(0, event)
|
1299
|
+
|
1300
|
+
# Trim displayed events if we exceed max_events
|
1301
|
+
if len(self._events) > self._max_events:
|
1302
|
+
self._events = self._events[: self._max_events]
|
1303
|
+
|
1304
|
+
def get_stats(self) -> dict:
|
1305
|
+
"""
|
1306
|
+
Get timeline statistics.
|
1307
|
+
|
1308
|
+
Returns
|
1309
|
+
-------
|
1310
|
+
dict
|
1311
|
+
Statistics including total events, display count, timing info, etc.
|
1312
|
+
"""
|
1313
|
+
import time
|
1314
|
+
|
1315
|
+
current_time = time.time()
|
1316
|
+
|
1317
|
+
stats = {
|
1318
|
+
"total_events": self._total_events_count,
|
1319
|
+
"displayed_events": len(self._events),
|
1320
|
+
"last_update": self._last_update_time,
|
1321
|
+
"first_event": self._first_event_time,
|
1322
|
+
}
|
1323
|
+
|
1324
|
+
# seconds_since_last_update removed; UI derives recency from last event timestamp
|
1325
|
+
|
1326
|
+
# Add finished status
|
1327
|
+
stats["finished"] = self._finished
|
1328
|
+
|
1329
|
+
if self._first_event_time and self._total_events_count > 1:
|
1330
|
+
runtime = self._last_update_time - self._first_event_time
|
1331
|
+
if runtime > 0:
|
1332
|
+
stats["events_per_minute"] = round(
|
1333
|
+
(self._total_events_count / runtime) * 60, 1
|
1334
|
+
)
|
1335
|
+
stats["total_runtime_seconds"] = round(runtime, 1)
|
1336
|
+
|
1337
|
+
return stats
|
1338
|
+
|
1339
|
+
def _render_subcomponents(self):
|
1340
|
+
"""
|
1341
|
+
Render any UserComponents within event payloads.
|
1342
|
+
"""
|
1343
|
+
rendered_events = []
|
1344
|
+
|
1345
|
+
for event in self._events:
|
1346
|
+
rendered_event = dict(event) # Copy event metadata
|
1347
|
+
|
1348
|
+
# Event metadata should only contain simple values (no components)
|
1349
|
+
rendered_event["metadata"] = event["metadata"]
|
1350
|
+
|
1351
|
+
# Render payload components
|
1352
|
+
rendered_payloads = {}
|
1353
|
+
for key, payload in event["payloads"].items():
|
1354
|
+
if isinstance(payload, MetaflowCardComponent):
|
1355
|
+
# Render the component
|
1356
|
+
rendered_payloads[key] = payload.render()
|
1357
|
+
else:
|
1358
|
+
# This shouldn't happen due to validation, but handle gracefully
|
1359
|
+
rendered_payloads[key] = str(payload)
|
1360
|
+
|
1361
|
+
rendered_event["payloads"] = rendered_payloads
|
1362
|
+
rendered_events.append(rendered_event)
|
1363
|
+
|
1364
|
+
return rendered_events
|
1365
|
+
|
1366
|
+
@with_default_component_id
|
1367
|
+
@render_safely
|
1368
|
+
def render(self):
|
1369
|
+
data = {
|
1370
|
+
"type": self.type,
|
1371
|
+
"id": self.component_id,
|
1372
|
+
"events": self._render_subcomponents(),
|
1373
|
+
"config": {
|
1374
|
+
"show_stats": True,
|
1375
|
+
"show_relative_time": True,
|
1376
|
+
"max_events": self._max_events,
|
1377
|
+
},
|
1378
|
+
}
|
1379
|
+
|
1380
|
+
if self._title is not None:
|
1381
|
+
data["title"] = self._title
|
1382
|
+
|
1383
|
+
# Always include stats
|
1384
|
+
data["stats"] = self.get_stats()
|
1385
|
+
|
1386
|
+
return data
|
1387
|
+
|
1388
|
+
|
1389
|
+
# Rich viewer components
|
1390
|
+
class JSONViewer(_JSONViewer, UserComponent):
|
1391
|
+
"""
|
1392
|
+
A component for displaying JSON data with syntax highlighting and collapsible sections.
|
1393
|
+
|
1394
|
+
This component provides a rich view of JSON data with proper formatting, syntax highlighting,
|
1395
|
+
and the ability to collapse/expand sections for better readability.
|
1396
|
+
|
1397
|
+
Example:
|
1398
|
+
```python
|
1399
|
+
from metaflow.cards import JSONViewer, EventsTimeline
|
1400
|
+
from metaflow import current
|
1401
|
+
|
1402
|
+
# Use in events timeline
|
1403
|
+
events = EventsTimeline(title="API Calls")
|
1404
|
+
events.update({
|
1405
|
+
"action": "api_request",
|
1406
|
+
"endpoint": "/users",
|
1407
|
+
"payload": JSONViewer({"user_id": 123, "fields": ["name", "email"]})
|
1408
|
+
})
|
1409
|
+
|
1410
|
+
# Use standalone
|
1411
|
+
data = {"config": {"debug": True, "timeout": 30}}
|
1412
|
+
current.card.append(JSONViewer(data, collapsible=True))
|
1413
|
+
```
|
1414
|
+
"""
|
1415
|
+
|
1416
|
+
pass
|
1417
|
+
|
1418
|
+
|
1419
|
+
class YAMLViewer(_YAMLViewer, UserComponent):
|
1420
|
+
"""
|
1421
|
+
A component for displaying YAML data with syntax highlighting and collapsible sections.
|
1422
|
+
|
1423
|
+
This component provides a rich view of YAML data with proper formatting and syntax highlighting.
|
1424
|
+
|
1425
|
+
Example:
|
1426
|
+
```python
|
1427
|
+
from metaflow.cards import YAMLViewer, EventsTimeline
|
1428
|
+
from metaflow import current
|
1429
|
+
|
1430
|
+
# Use in events timeline
|
1431
|
+
events = EventsTimeline(title="Configuration Changes")
|
1432
|
+
events.update({
|
1433
|
+
"action": "config_update",
|
1434
|
+
"config": YAMLViewer({
|
1435
|
+
"database": {"host": "localhost", "port": 5432},
|
1436
|
+
"features": ["auth", "logging"]
|
1437
|
+
})
|
1438
|
+
})
|
1439
|
+
```
|
1440
|
+
"""
|
1441
|
+
|
1442
|
+
pass
|