synapse-sdk 1.0.0a98__py3-none-any.whl → 1.0.0b1__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.

Potentially problematic release.


This version of synapse-sdk might be problematic. Click here for more details.

Files changed (64) hide show
  1. synapse_sdk/cli/__init__.py +139 -84
  2. synapse_sdk/cli/code_server.py +169 -0
  3. synapse_sdk/cli/config.py +105 -4
  4. synapse_sdk/cli/devtools.py +54 -34
  5. synapse_sdk/clients/base.py +3 -4
  6. synapse_sdk/devtools/server.py +24 -791
  7. synapse_sdk/devtools/streamlit_app/__init__.py +5 -0
  8. synapse_sdk/devtools/streamlit_app/app.py +128 -0
  9. synapse_sdk/devtools/streamlit_app/services/__init__.py +11 -0
  10. synapse_sdk/devtools/streamlit_app/services/job_service.py +233 -0
  11. synapse_sdk/devtools/streamlit_app/services/plugin_service.py +236 -0
  12. synapse_sdk/devtools/streamlit_app/services/serve_service.py +95 -0
  13. synapse_sdk/devtools/streamlit_app/ui/__init__.py +15 -0
  14. synapse_sdk/devtools/streamlit_app/ui/config_tab.py +76 -0
  15. synapse_sdk/devtools/streamlit_app/ui/deployment_tab.py +66 -0
  16. synapse_sdk/devtools/streamlit_app/ui/http_tab.py +125 -0
  17. synapse_sdk/devtools/streamlit_app/ui/jobs_tab.py +573 -0
  18. synapse_sdk/devtools/streamlit_app/ui/serve_tab.py +346 -0
  19. synapse_sdk/devtools/streamlit_app/ui/status_bar.py +118 -0
  20. synapse_sdk/devtools/streamlit_app/utils/__init__.py +40 -0
  21. synapse_sdk/devtools/streamlit_app/utils/json_viewer.py +197 -0
  22. synapse_sdk/devtools/streamlit_app/utils/log_formatter.py +38 -0
  23. synapse_sdk/devtools/streamlit_app/utils/styles.py +241 -0
  24. synapse_sdk/devtools/streamlit_app/utils/ui_components.py +289 -0
  25. synapse_sdk/devtools/streamlit_app.py +10 -0
  26. synapse_sdk/plugins/categories/upload/actions/upload.py +2 -1
  27. synapse_sdk/utils/converters/dm/__init__.py +0 -1
  28. {synapse_sdk-1.0.0a98.dist-info → synapse_sdk-1.0.0b1.dist-info}/METADATA +4 -6
  29. {synapse_sdk-1.0.0a98.dist-info → synapse_sdk-1.0.0b1.dist-info}/RECORD +33 -44
  30. synapse_sdk/devtools/models.py +0 -55
  31. synapse_sdk/devtools/utils.py +0 -52
  32. synapse_sdk/devtools/web/.gitignore +0 -2
  33. synapse_sdk/devtools/web/README.md +0 -34
  34. synapse_sdk/devtools/web/dist/index.html +0 -17
  35. synapse_sdk/devtools/web/index.html +0 -16
  36. synapse_sdk/devtools/web/jsconfig.json +0 -15
  37. synapse_sdk/devtools/web/package-lock.json +0 -2609
  38. synapse_sdk/devtools/web/package.json +0 -27
  39. synapse_sdk/devtools/web/pnpm-lock.yaml +0 -1055
  40. synapse_sdk/devtools/web/src/App.jsx +0 -14
  41. synapse_sdk/devtools/web/src/App.module.css +0 -33
  42. synapse_sdk/devtools/web/src/assets/favicon.ico +0 -0
  43. synapse_sdk/devtools/web/src/components/Breadcrumbs.jsx +0 -42
  44. synapse_sdk/devtools/web/src/components/Layout.jsx +0 -12
  45. synapse_sdk/devtools/web/src/components/LogViewer.jsx +0 -280
  46. synapse_sdk/devtools/web/src/components/MessageViewer.jsx +0 -150
  47. synapse_sdk/devtools/web/src/components/NavigationSidebar.jsx +0 -128
  48. synapse_sdk/devtools/web/src/components/ServerStatusBar.jsx +0 -245
  49. synapse_sdk/devtools/web/src/components/icons.jsx +0 -325
  50. synapse_sdk/devtools/web/src/index.css +0 -470
  51. synapse_sdk/devtools/web/src/index.jsx +0 -15
  52. synapse_sdk/devtools/web/src/logo.svg +0 -1
  53. synapse_sdk/devtools/web/src/router.jsx +0 -34
  54. synapse_sdk/devtools/web/src/utils/api.js +0 -442
  55. synapse_sdk/devtools/web/src/views/ApplicationDetailView.jsx +0 -241
  56. synapse_sdk/devtools/web/src/views/ApplicationsView.jsx +0 -224
  57. synapse_sdk/devtools/web/src/views/HomeView.jsx +0 -197
  58. synapse_sdk/devtools/web/src/views/JobDetailView.jsx +0 -310
  59. synapse_sdk/devtools/web/src/views/PluginView.jsx +0 -914
  60. synapse_sdk/devtools/web/vite.config.js +0 -13
  61. {synapse_sdk-1.0.0a98.dist-info → synapse_sdk-1.0.0b1.dist-info}/WHEEL +0 -0
  62. {synapse_sdk-1.0.0a98.dist-info → synapse_sdk-1.0.0b1.dist-info}/entry_points.txt +0 -0
  63. {synapse_sdk-1.0.0a98.dist-info → synapse_sdk-1.0.0b1.dist-info}/licenses/LICENSE +0 -0
  64. {synapse_sdk-1.0.0a98.dist-info → synapse_sdk-1.0.0b1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,197 @@
1
+ """Professional JSON viewer component."""
2
+
3
+ import json
4
+ from typing import Any, Dict, List, Union
5
+
6
+ import streamlit as st
7
+ from streamlit_ace import st_ace
8
+
9
+
10
+ def format_json_value(value: Any, indent: int = 0) -> str:
11
+ """Format a JSON value for display."""
12
+ if isinstance(value, (dict, list)):
13
+ return json.dumps(value, indent=2)
14
+ elif isinstance(value, str):
15
+ return f'"{value}"'
16
+ elif value is None:
17
+ return 'null'
18
+ elif isinstance(value, bool):
19
+ return 'true' if value else 'false'
20
+ else:
21
+ return str(value)
22
+
23
+
24
+ def render_json_compact(data: Union[Dict, List], title: str = None, expanded: bool = True):
25
+ """Render JSON data in a compact, professional format."""
26
+ if not data:
27
+ return
28
+
29
+ if title:
30
+ st.markdown(f'### {title}')
31
+
32
+ # Use code editor for better JSON display
33
+ json_str = json.dumps(data, indent=2, ensure_ascii=False)
34
+
35
+ # Calculate appropriate height based on content
36
+ lines = json_str.count('\n') + 1
37
+ height = min(max(100, lines * 20), 600) # Min 100px, max 600px
38
+
39
+ st_ace(
40
+ value=json_str,
41
+ language='json',
42
+ theme='monokai',
43
+ key=f'json_viewer_{title}_{hash(json_str)}',
44
+ height=height,
45
+ auto_update=False,
46
+ font_size=13,
47
+ show_gutter=True,
48
+ show_print_margin=False,
49
+ wrap=False,
50
+ annotations=None,
51
+ readonly=True,
52
+ )
53
+
54
+
55
+ def render_json_as_table(data: Dict, title: str = None):
56
+ """Render JSON data as a formatted table for key-value pairs."""
57
+ if not data:
58
+ return
59
+
60
+ if title:
61
+ st.markdown(f'### {title}')
62
+
63
+ # Create HTML table - use compact string to avoid rendering issues
64
+ html = ( # noqa: E501
65
+ '<style>'
66
+ '.json-table { width: 100%; border-collapse: collapse; font-family: "SF Mono", Monaco, "Cascadia Code", "Roboto Mono", monospace; font-size: 13px; margin: 10px 0; }' # noqa: E501
67
+ '.json-table th { background-color: #2d2d2d; color: #f0f0f0; text-align: left; padding: 10px 15px; border-bottom: 2px solid #444; font-weight: 600; }' # noqa: E501
68
+ '.json-table td { padding: 8px 15px; border-bottom: 1px solid #e0e0e0; vertical-align: top; }'
69
+ '.json-table tr:hover { background-color: #f8f9fa; }'
70
+ '.json-key { color: #0066cc; font-weight: 500; white-space: nowrap; width: 30%; }'
71
+ '.json-value { color: #333; word-break: break-word; }'
72
+ '.json-value-null { color: #999; font-style: italic; }'
73
+ '.json-value-bool { color: #d73a49; }'
74
+ '.json-value-number { color: #005cc5; }'
75
+ '.json-value-string { color: #032f62; }'
76
+ '.json-value-object { color: #6f42c1; font-family: "SF Mono", Monaco, monospace; font-size: 12px; background-color: #f6f8fa; padding: 4px 8px; border-radius: 3px; display: inline-block; max-width: 500px; overflow-x: auto; }' # noqa: E501
77
+ '</style>'
78
+ '<table class="json-table">'
79
+ '<thead><tr><th>Key</th><th>Value</th></tr></thead>'
80
+ '<tbody>'
81
+ )
82
+
83
+ for key, value in data.items():
84
+ value_class = 'json-value'
85
+ value_str = ''
86
+
87
+ if value is None:
88
+ value_class = 'json-value-null'
89
+ value_str = 'null'
90
+ elif isinstance(value, bool):
91
+ value_class = 'json-value-bool'
92
+ value_str = str(value).lower()
93
+ elif isinstance(value, (int, float)):
94
+ value_class = 'json-value-number'
95
+ value_str = str(value)
96
+ elif isinstance(value, str):
97
+ value_class = 'json-value-string'
98
+ value_str = value
99
+ elif isinstance(value, (dict, list)):
100
+ value_class = 'json-value-object'
101
+ value_str = json.dumps(value, ensure_ascii=False)
102
+ if len(value_str) > 100:
103
+ value_str = json.dumps(value, indent=2, ensure_ascii=False)
104
+ else:
105
+ value_str = str(value)
106
+
107
+ html += f'<tr><td class="json-key">{key}</td><td class="{value_class}">{value_str}</td></tr>'
108
+
109
+ html += '</tbody></table>'
110
+
111
+ st.markdown(html, unsafe_allow_html=True)
112
+
113
+
114
+ def render_json_tree(data: Union[Dict, List], title: str = None, max_depth: int = 3):
115
+ """Render JSON data as an expandable tree view."""
116
+ if not data:
117
+ return
118
+
119
+ if title:
120
+ st.markdown(f'### {title}')
121
+
122
+ def render_node(obj: Any, key: str = '', depth: int = 0):
123
+ """Recursively render JSON nodes."""
124
+ indent = '&nbsp;' * (depth * 20)
125
+
126
+ if isinstance(obj, dict):
127
+ if depth < max_depth:
128
+ with st.expander(f'{key or "Object"} ({len(obj)} items)', expanded=depth == 0):
129
+ for k, v in obj.items():
130
+ if isinstance(v, (dict, list)):
131
+ render_node(v, k, depth + 1)
132
+ else:
133
+ st.markdown(
134
+ f"<div style='font-family: monospace; font-size: 13px; padding: 2px 0;'>"
135
+ f"<span style='color: #0066cc; font-weight: 500;'>{k}:</span> "
136
+ f"<span style='color: #333;'>{format_json_value(v)}</span></div>",
137
+ unsafe_allow_html=True,
138
+ )
139
+ else:
140
+ st.code(json.dumps(obj, indent=2), language='json')
141
+
142
+ elif isinstance(obj, list):
143
+ if depth < max_depth:
144
+ with st.expander(f'{key or "Array"} [{len(obj)} items]', expanded=depth == 0):
145
+ for i, item in enumerate(obj):
146
+ render_node(item, f'[{i}]', depth + 1)
147
+ else:
148
+ st.code(json.dumps(obj, indent=2), language='json')
149
+
150
+ else:
151
+ st.markdown(
152
+ f"<div style='font-family: monospace; font-size: 13px; padding: 2px 0;'>"
153
+ f"{indent}<span style='color: #333;'>{format_json_value(obj)}</span></div>",
154
+ unsafe_allow_html=True,
155
+ )
156
+
157
+ render_node(data)
158
+
159
+
160
+ def render_metrics_grid(metrics: Dict, title: str = 'Metrics'):
161
+ """Render metrics in a professional grid layout."""
162
+ if not metrics:
163
+ return
164
+
165
+ st.markdown(f'### {title}')
166
+
167
+ # Create columns based on number of metrics
168
+ num_metrics = len(metrics)
169
+ if num_metrics <= 3:
170
+ cols = st.columns(num_metrics)
171
+ elif num_metrics <= 6:
172
+ cols = st.columns(3)
173
+ else:
174
+ cols = st.columns(4)
175
+
176
+ for i, (key, value) in enumerate(metrics.items()):
177
+ col_idx = i % len(cols)
178
+ with cols[col_idx]:
179
+ # Format the value
180
+ if isinstance(value, float):
181
+ if value < 1:
182
+ formatted_value = f'{value:.4f}'
183
+ else:
184
+ formatted_value = f'{value:.2f}'
185
+ elif isinstance(value, dict):
186
+ formatted_value = f'{len(value)} items'
187
+ elif isinstance(value, list):
188
+ formatted_value = f'{len(value)} items'
189
+ else:
190
+ formatted_value = str(value)
191
+
192
+ # Display as metric
193
+ st.metric(
194
+ label=key.replace('_', ' ').title(),
195
+ value=formatted_value,
196
+ delta=None,
197
+ )
@@ -0,0 +1,38 @@
1
+ """Log formatting utilities."""
2
+
3
+ import html
4
+ import re
5
+
6
+
7
+ def format_log_line(line: str, line_number: int) -> str:
8
+ """Format a log line with syntax highlighting and line numbers."""
9
+ # Clean the line
10
+ line = line.strip()
11
+ if not line:
12
+ return (
13
+ f'<div class="log-line"><span class="log-line-number">{line_number}</span>'
14
+ f'<div class="log-line-content"></div></div>'
15
+ )
16
+
17
+ # Escape HTML first
18
+ line = html.escape(line)
19
+
20
+ # Check for different log levels and patterns
21
+ if re.search(r'\b(error|exception|fail|fatal)\b', line, re.IGNORECASE):
22
+ css_class = 'log-error'
23
+ elif re.search(r'\b(warn|warning)\b', line, re.IGNORECASE):
24
+ css_class = 'log-warning'
25
+ elif re.search(r'\b(info|information)\b', line, re.IGNORECASE):
26
+ css_class = 'log-info'
27
+ elif re.search(r'\b(debug|trace)\b', line, re.IGNORECASE):
28
+ css_class = 'log-debug'
29
+ else:
30
+ css_class = ''
31
+
32
+ # Highlight timestamps (common patterns)
33
+ line = re.sub(r'(\d{4}-\d{2}-\d{2}[\sT]\d{2}:\d{2}:\d{2})', r'<span class="log-timestamp">\1</span>', line)
34
+
35
+ return (
36
+ f'<div class="log-line"><span class="log-line-number">{line_number}</span>'
37
+ f'<div class="log-line-content {css_class}">{line}</div></div>'
38
+ )
@@ -0,0 +1,241 @@
1
+ """Styling constants and CSS for the Streamlit app."""
2
+
3
+ CUSTOM_CSS = """
4
+ <style>
5
+ /* Global typography and spacing */
6
+ * {
7
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;
8
+ }
9
+
10
+ /* Consistent button styling */
11
+ .stButton > button {
12
+ border-radius: 6px;
13
+ font-weight: 500;
14
+ transition: all 0.2s ease;
15
+ padding: 0.5rem 1rem;
16
+ }
17
+
18
+ .stButton > button:hover {
19
+ transform: translateY(-1px);
20
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
21
+ }
22
+
23
+ /* Tab styling */
24
+ .stTabs [data-baseweb="tab-list"] button [data-testid="stMarkdownContainer"] p {
25
+ font-size: 14px;
26
+ font-weight: 500;
27
+ letter-spacing: 0.3px;
28
+ }
29
+ .success-box {
30
+ padding: 1rem;
31
+ border-radius: 0.5rem;
32
+ background-color: #d4edda;
33
+ border: 1px solid #c3e6cb;
34
+ color: #155724;
35
+ margin: 1rem 0;
36
+ }
37
+ .error-box {
38
+ padding: 1rem;
39
+ border-radius: 0.5rem;
40
+ background-color: #f8d7da;
41
+ border: 1px solid #f5c6cb;
42
+ color: #721c24;
43
+ margin: 1rem 0;
44
+ }
45
+ .info-box {
46
+ padding: 1rem;
47
+ border-radius: 0.5rem;
48
+ background-color: #d1ecf1;
49
+ border: 1px solid #bee5eb;
50
+ color: #0c5460;
51
+ margin: 1rem 0;
52
+ }
53
+ .status-bar {
54
+ background-color: #f8f9fa;
55
+ border-radius: 0.5rem;
56
+ padding: 1rem;
57
+ margin: 1rem 0;
58
+ border: 1px solid #dee2e6;
59
+ }
60
+ .log-container {
61
+ background-color: #1e1e1e;
62
+ color: #d4d4d4;
63
+ font-family: 'Fira Code', 'Consolas', 'Monaco', 'Courier New', monospace;
64
+ font-size: 14px;
65
+ line-height: 1.4;
66
+ padding: 0;
67
+ border-radius: 0.5rem;
68
+ overflow-x: auto;
69
+ overflow-y: auto;
70
+ max-height: 400px;
71
+ white-space: pre-wrap;
72
+ word-wrap: break-word;
73
+ border: 1px solid #3c3c3c;
74
+ display: flex;
75
+ flex-direction: column;
76
+ }
77
+ .log-line {
78
+ margin: 0;
79
+ padding: 0.2rem 1rem;
80
+ display: flex;
81
+ align-items: flex-start;
82
+ border-bottom: 1px solid #2a2a2a;
83
+ }
84
+ .log-line:hover {
85
+ background-color: #2a2a2a;
86
+ }
87
+ .log-line-number {
88
+ color: #858585;
89
+ font-size: 12px;
90
+ min-width: 40px;
91
+ text-align: right;
92
+ padding-right: 12px;
93
+ user-select: none;
94
+ flex-shrink: 0;
95
+ }
96
+ .log-line-content {
97
+ flex: 1;
98
+ word-break: break-word;
99
+ }
100
+ .log-error {
101
+ color: #f48771;
102
+ font-weight: bold;
103
+ }
104
+ .log-warning {
105
+ color: #dcdcaa;
106
+ }
107
+ .log-info {
108
+ color: #9cdcfe;
109
+ }
110
+ .log-debug {
111
+ color: #608b4e;
112
+ }
113
+ .log-timestamp {
114
+ color: #569cd6;
115
+ }
116
+ .stJson {
117
+ max-width: 100%;
118
+ overflow-x: auto;
119
+ }
120
+ /* Professional styling for code blocks */
121
+ .stCodeBlock {
122
+ background-color: #1e1e1e !important;
123
+ border: 1px solid #3c3c3c !important;
124
+ border-radius: 6px !important;
125
+ }
126
+ /* Enhanced headers */
127
+ h1, h2, h3 {
128
+ font-weight: 600 !important;
129
+ color: #1a1a1a !important;
130
+ }
131
+ /* Professional section spacing */
132
+ .section-divider {
133
+ margin: 2rem 0;
134
+ border-bottom: 1px solid #e0e0e0;
135
+ }
136
+ /* Hide the Streamlit toolbar */
137
+ .stAppToolbar {
138
+ visibility: hidden;
139
+ }
140
+ /* Alternative method to hide toolbar */
141
+ [data-testid="stToolbar"] {
142
+ display: none !important;
143
+ }
144
+ /* Reduce top padding of main container */
145
+ .stMainBlockContainer,
146
+ .block-container {
147
+ padding-top: 1rem !important;
148
+ max-width: 100%;
149
+ }
150
+ /* Better tab styling */
151
+ .stTabs [data-baseweb="tab-list"] {
152
+ gap: 4px;
153
+ background-color: transparent;
154
+ border-bottom: 2px solid #e9ecef;
155
+ padding: 0;
156
+ }
157
+ .stTabs [data-baseweb="tab"] {
158
+ padding: 10px 20px;
159
+ border-radius: 0;
160
+ background-color: transparent;
161
+ border-bottom: 3px solid transparent;
162
+ margin-bottom: -2px;
163
+ }
164
+ .stTabs [data-baseweb="tab-list"] button[aria-selected="true"] {
165
+ background-color: transparent;
166
+ border-bottom: 3px solid #007bff;
167
+ color: #007bff;
168
+ }
169
+ .stTabs [data-baseweb="tab"]:hover {
170
+ background-color: #f8f9fa;
171
+ }
172
+
173
+ /* Form styling */
174
+ .stSelectbox > div > div {
175
+ border-radius: 6px;
176
+ }
177
+ .stTextInput > div > div > input {
178
+ border-radius: 6px;
179
+ }
180
+ .stTextArea > div > div > textarea {
181
+ border-radius: 6px;
182
+ }
183
+
184
+ /* Checkbox and radio styling */
185
+ .stCheckbox > label > span {
186
+ font-size: 14px;
187
+ }
188
+ .stRadio > label {
189
+ font-size: 14px;
190
+ }
191
+
192
+ /* Metrics styling */
193
+ .metric-container .metric-label {
194
+ font-size: 12px;
195
+ font-weight: 500;
196
+ text-transform: uppercase;
197
+ letter-spacing: 0.5px;
198
+ color: #6c757d;
199
+ }
200
+
201
+ /* Consistent spacing */
202
+ .row-widget.stButton {
203
+ margin-top: 0.5rem;
204
+ margin-bottom: 0.5rem;
205
+ }
206
+ /* Also adjust the header spacing */
207
+ .stAppHeader {
208
+ height: 0rem !important;
209
+ }
210
+ </style>
211
+ """
212
+
213
+
214
+ def get_status_badge_html(status: str) -> str:
215
+ """Generate HTML for status badge with outline style."""
216
+ status = status.upper() if status else 'UNKNOWN'
217
+
218
+ color_map = {
219
+ 'SUCCEEDED': '#28a745',
220
+ 'RUNNING': '#007bff',
221
+ 'PENDING': '#6c757d',
222
+ 'FAILED': '#dc3545',
223
+ 'STOPPED': '#6c757d',
224
+ 'UNKNOWN': '#6c757d',
225
+ }
226
+
227
+ color = color_map.get(status, '#6c757d')
228
+
229
+ return f"""
230
+ <span style="
231
+ border: 1px solid {color};
232
+ color: {color};
233
+ padding: 4px 10px;
234
+ border-radius: 4px;
235
+ font-size: 12px;
236
+ font-weight: 500;
237
+ display: inline-block;
238
+ text-align: center;
239
+ min-width: 70px;
240
+ ">{status}</span>
241
+ """