flexdesk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +195 -0
  3. package/THIRD_PARTY_LICENSES.md +53 -0
  4. package/css/base.css +3439 -0
  5. package/css/flexdesk.css +5797 -0
  6. package/css/overrides.css +2349 -0
  7. package/css/reset.css +46 -0
  8. package/css/tokens.css +137 -0
  9. package/dist/charts.js +780 -0
  10. package/dist/charts.js.map +7 -0
  11. package/dist/chunk-3PHCPZHT.js +222 -0
  12. package/dist/chunk-3PHCPZHT.js.map +7 -0
  13. package/dist/chunk-CT4YXXLP.js +1770 -0
  14. package/dist/chunk-CT4YXXLP.js.map +7 -0
  15. package/dist/chunk-DRYCDMEG.js +2217 -0
  16. package/dist/chunk-DRYCDMEG.js.map +7 -0
  17. package/dist/chunk-DVU44T77.js +855 -0
  18. package/dist/chunk-DVU44T77.js.map +7 -0
  19. package/dist/chunk-FL5KFNQH.js +640 -0
  20. package/dist/chunk-FL5KFNQH.js.map +7 -0
  21. package/dist/chunk-FOOS3T5L.js +117 -0
  22. package/dist/chunk-FOOS3T5L.js.map +7 -0
  23. package/dist/chunk-JYWURG5T.js +32 -0
  24. package/dist/chunk-JYWURG5T.js.map +7 -0
  25. package/dist/chunk-TLZUUFOE.js +276 -0
  26. package/dist/chunk-TLZUUFOE.js.map +7 -0
  27. package/dist/chunk-UCJ2WD4D.js +625 -0
  28. package/dist/chunk-UCJ2WD4D.js.map +7 -0
  29. package/dist/chunk-WVFGV5FT.js +205 -0
  30. package/dist/chunk-WVFGV5FT.js.map +7 -0
  31. package/dist/core.js +1098 -0
  32. package/dist/core.js.map +7 -0
  33. package/dist/editor.js +1661 -0
  34. package/dist/editor.js.map +7 -0
  35. package/dist/flexdesk.css +5797 -0
  36. package/dist/host.js +132 -0
  37. package/dist/host.js.map +7 -0
  38. package/dist/reset.css +46 -0
  39. package/dist/tile_registry-6WZPTUZV.js +28 -0
  40. package/dist/tile_registry-6WZPTUZV.js.map +7 -0
  41. package/dist/tiles.js +2068 -0
  42. package/dist/tiles.js.map +7 -0
  43. package/dist/tokens.css +137 -0
  44. package/dist/widgets.js +5438 -0
  45. package/dist/widgets.js.map +7 -0
  46. package/dist/wm.js +4830 -0
  47. package/dist/wm.js.map +7 -0
  48. package/package.json +80 -0
  49. package/src/charts/chart_types.js +699 -0
  50. package/src/charts/data_series_plot_window.js +761 -0
  51. package/src/charts/downsample.js +119 -0
  52. package/src/charts/plot_config.js +176 -0
  53. package/src/charts/plot_popout_window.js +1560 -0
  54. package/src/charts/plotly_wrapper.js +432 -0
  55. package/src/core/event_bus.js +230 -0
  56. package/src/core/logging.js +300 -0
  57. package/src/core/settings.js +813 -0
  58. package/src/core/state_guard.js +382 -0
  59. package/src/core/state_guard_config.js +309 -0
  60. package/src/core/state_machine.js +258 -0
  61. package/src/editor/editor_pane.js +264 -0
  62. package/src/editor/monaco_editor_factory.js +449 -0
  63. package/src/editor/monaco_loader.js +74 -0
  64. package/src/editor/notebook_search.js +460 -0
  65. package/src/editor/notebook_tab_bar.js +456 -0
  66. package/src/editor/notebook_undo_manager.js +108 -0
  67. package/src/editor/split_pane_container.js +197 -0
  68. package/src/help/help_modal.js +409 -0
  69. package/src/help/help_registry.js +65 -0
  70. package/src/host/host.js +69 -0
  71. package/src/host/pywebview_host.js +133 -0
  72. package/src/tiles/config_schema.js +256 -0
  73. package/src/tiles/layout_persistence.js +662 -0
  74. package/src/tiles/tile_base.js +785 -0
  75. package/src/tiles/tile_grid.js +905 -0
  76. package/src/tiles/tile_registry.js +136 -0
  77. package/src/tiling/command_palette.js +328 -0
  78. package/src/tiling/content_registry.js +110 -0
  79. package/src/tiling/desktops.js +133 -0
  80. package/src/tiling/entity_sources.js +179 -0
  81. package/src/tiling/keymap.js +156 -0
  82. package/src/tiling/kind_taxonomy.js +172 -0
  83. package/src/tiling/landing_table.js +717 -0
  84. package/src/tiling/loading_overlay.js +33 -0
  85. package/src/tiling/nav_panel.js +142 -0
  86. package/src/tiling/page_factory.js +215 -0
  87. package/src/tiling/panel_keys.js +145 -0
  88. package/src/tiling/shell.js +437 -0
  89. package/src/tiling/tile_breadcrumb.js +222 -0
  90. package/src/tiling/tile_renderer.js +459 -0
  91. package/src/tiling/tile_tab_menu.js +340 -0
  92. package/src/tiling/tile_tree.js +880 -0
  93. package/src/tiling/wm.js +1352 -0
  94. package/src/ui/base/component_base.js +30 -0
  95. package/src/ui/base/controller_base.js +48 -0
  96. package/src/ui/base/page_base.js +102 -0
  97. package/src/ui/components/about_dialog.js +224 -0
  98. package/src/ui/components/action_dropdown.js +389 -0
  99. package/src/ui/components/attribute_list_editor.js +652 -0
  100. package/src/ui/components/autocomplete_field.js +732 -0
  101. package/src/ui/components/computing_status_window.js +81 -0
  102. package/src/ui/components/confirm_dialog.js +307 -0
  103. package/src/ui/components/context_menu.js +87 -0
  104. package/src/ui/components/data_table.js +2228 -0
  105. package/src/ui/components/detail_header.js +177 -0
  106. package/src/ui/components/drag_reorder.js +0 -0
  107. package/src/ui/components/gallery_picker.js +147 -0
  108. package/src/ui/components/inline_renamer.js +129 -0
  109. package/src/ui/components/managed_window.js +804 -0
  110. package/src/ui/components/modal.js +512 -0
  111. package/src/ui/components/notification_history.js +264 -0
  112. package/src/ui/components/slide_out_panel.js +185 -0
  113. package/src/ui/components/slider_field.js +122 -0
  114. package/src/ui/components/sortable_list.js +309 -0
  115. package/src/ui/components/table_state_store.js +81 -0
  116. package/src/ui/components/toast.js +59 -0
  117. package/src/ui/components/tree_view.js +460 -0
  118. package/src/ui/components/window_taskbar.js +143 -0
  119. package/src/ui/controllers/panel_state_machine.js +634 -0
  120. package/src/ui/controllers/window_chrome_controller.js +659 -0
  121. package/src/ui/notification_center.js +576 -0
  122. package/src/ui/utils/overlay_scrollbar.js +492 -0
  123. package/src/ui/utils/raf_resize_observer.js +31 -0
  124. package/src/ui/utils/tooltip_service.js +406 -0
@@ -0,0 +1,300 @@
1
+ /**
2
+ * Logging + Telemetry Hub (js_new)
3
+ *
4
+ * Purpose
5
+ * -------
6
+ * Single sink for structured logs, metrics, and telemetry forwarding from all modules.
7
+ *
8
+ * Responsibilities
9
+ * - Normalize log payloads (level, namespace, metadata) before dispatching to host.
10
+ * - Publish `log:*` events for in-app diagnostics dashboards.
11
+ * - Replace scattered console/notify usage with a deterministic API.
12
+ *
13
+ * Source Material
14
+ * - html/js/logger.js (log formatting + transports).
15
+ * - html/js/debug_utils.js (runtime diagnostics + indicators).
16
+ *
17
+ */
18
+
19
+ const LEVELS = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];
20
+ const LEVEL_INDEX = new Map(LEVELS.map((level, idx) => [level, idx]));
21
+
22
+ const DEFAULT_NAMESPACE = 'app';
23
+
24
+ // Quiet mode level - only warn and above during simulation
25
+ const QUIET_MODE_LEVEL = 'warn';
26
+
27
+ export class LoggingService {
28
+ constructor({
29
+ name = 'ecosim',
30
+ eventBus = null,
31
+ minLevel = 'info',
32
+ historyLimit = 500,
33
+ transports = [],
34
+ enableConsole = false,
35
+ namespaceLevels = null,
36
+ } = {}) {
37
+ this.name = name;
38
+ this.eventBus = eventBus;
39
+ this.historyLimit = historyLimit;
40
+ this.entries = [];
41
+ this.sequence = 0;
42
+ this.transports = new Set();
43
+ this.namespaceLevels = { ...(namespaceLevels || {}) };
44
+ this._quietMode = false;
45
+ this._savedLevel = null;
46
+ this.setLevel(minLevel);
47
+
48
+ transports.forEach((transport) => this.addTransport(transport));
49
+ if (enableConsole) {
50
+ this.addTransport(this._consoleTransport.bind(this));
51
+ }
52
+ }
53
+
54
+ setLevel(level) {
55
+ const normalized = this._normalizeLevel(level);
56
+ this.minLevel = normalized;
57
+ }
58
+
59
+ getLevel() {
60
+ return this.minLevel;
61
+ }
62
+
63
+ /**
64
+ * Enter quiet mode - suppresses DEBUG/INFO logs during simulation.
65
+ * Only WARNING and above are logged.
66
+ */
67
+ enterQuietMode() {
68
+ if (this._quietMode) return;
69
+ this._quietMode = true;
70
+ this._savedLevel = this.minLevel;
71
+ if (LEVEL_INDEX.get(this.minLevel) < LEVEL_INDEX.get(QUIET_MODE_LEVEL)) {
72
+ this.minLevel = QUIET_MODE_LEVEL;
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Exit quiet mode - restores previous log level.
78
+ */
79
+ exitQuietMode() {
80
+ if (!this._quietMode) return;
81
+ this._quietMode = false;
82
+ if (this._savedLevel !== null) {
83
+ this.minLevel = this._savedLevel;
84
+ this._savedLevel = null;
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Check if quiet mode is active.
90
+ */
91
+ isQuietMode() {
92
+ return this._quietMode;
93
+ }
94
+
95
+ setNamespaceLevel(namespace, level) {
96
+ if (!namespace) return;
97
+ this.namespaceLevels[namespace] = this._normalizeLevel(level);
98
+ }
99
+
100
+ setNamespaceLevels(map) {
101
+ if (!map || typeof map !== 'object') return;
102
+ Object.entries(map).forEach(([ns, lvl]) => {
103
+ if (ns) {
104
+ this.namespaceLevels[ns] = this._normalizeLevel(lvl);
105
+ }
106
+ });
107
+ }
108
+
109
+ getNamespaceLevel(namespace) {
110
+ if (!namespace) return undefined;
111
+ return this.namespaceLevels[namespace];
112
+ }
113
+
114
+ addTransport(transport) {
115
+ if (typeof transport !== 'function') {
116
+ throw new TypeError('Logging transport must be a function');
117
+ }
118
+ this.transports.add(transport);
119
+ }
120
+
121
+ removeTransport(transport) {
122
+ this.transports.delete(transport);
123
+ }
124
+
125
+ log(level, message, metadata = null, options = {}) {
126
+ const normalizedLevel = this._normalizeLevel(level);
127
+ const namespace = options.namespace || DEFAULT_NAMESPACE;
128
+ if (!this._shouldLog(normalizedLevel, namespace)) {
129
+ return null;
130
+ }
131
+
132
+ const entry = this._buildEntry(normalizedLevel, message, metadata, options);
133
+ this._recordHistory(entry);
134
+ this._emit(entry);
135
+ this._dispatch(entry);
136
+ return entry;
137
+ }
138
+
139
+ trace(message, metadata, options) {
140
+ return this.log('trace', message, metadata, options);
141
+ }
142
+
143
+ debug(message, metadata, options) {
144
+ return this.log('debug', message, metadata, options);
145
+ }
146
+
147
+ info(message, metadata, options) {
148
+ return this.log('info', message, metadata, options);
149
+ }
150
+
151
+ warn(message, metadata, options) {
152
+ return this.log('warn', message, metadata, options);
153
+ }
154
+
155
+ error(message, metadata, options) {
156
+ return this.log('error', message, metadata, options);
157
+ }
158
+
159
+ fatal(message, metadata, options) {
160
+ return this.log('fatal', message, metadata, options);
161
+ }
162
+
163
+ scoped(namespace) {
164
+ const ns = namespace || DEFAULT_NAMESPACE;
165
+ // Codebase convention: callers pass (subcategory, message, meta?) where
166
+ // subcategory is a short kebab-case tag and message is the human-readable
167
+ // string. Detect this pattern (two leading string args) and use the second
168
+ // string as the log message, discarding the subcategory (the scoped
169
+ // namespace already provides sufficient context).
170
+ // Also supports the standard (message, meta?) single-string form.
171
+ const make = (level) => (first, second, third) => {
172
+ if (typeof second === 'string') {
173
+ return this.log(level, second, third ?? null, { namespace: ns });
174
+ }
175
+ return this.log(level, first, second ?? null, { namespace: ns });
176
+ };
177
+ return {
178
+ trace: make('trace'),
179
+ debug: make('debug'),
180
+ info: make('info'),
181
+ warn: make('warn'),
182
+ error: make('error'),
183
+ fatal: make('fatal'),
184
+ };
185
+ }
186
+
187
+ getHistory() {
188
+ return [...this.entries];
189
+ }
190
+
191
+ clearHistory() {
192
+ this.entries.length = 0;
193
+ }
194
+
195
+ _normalizeLevel(level) {
196
+ const normalized = typeof level === 'string' ? level.toLowerCase() : '';
197
+ if (!LEVEL_INDEX.has(normalized)) {
198
+ throw new Error(`Unknown log level "${level}"`);
199
+ }
200
+ return normalized;
201
+ }
202
+
203
+ _shouldLog(level, namespace) {
204
+ const effectiveLevel = this._resolveEffectiveLevel(namespace);
205
+ return LEVEL_INDEX.get(level) >= LEVEL_INDEX.get(effectiveLevel);
206
+ }
207
+
208
+ _resolveEffectiveLevel(namespace) {
209
+ if (namespace && this.namespaceLevels?.[namespace]) {
210
+ return this.namespaceLevels[namespace];
211
+ }
212
+ return this.minLevel;
213
+ }
214
+
215
+ _buildEntry(level, message, metadata, options) {
216
+ const namespace = options.namespace || DEFAULT_NAMESPACE;
217
+ const tags = options.tags || [];
218
+ const context = options.context || null;
219
+ const data = this._sanitizeMetadata(metadata);
220
+
221
+ return {
222
+ id: ++this.sequence,
223
+ timestamp: Date.now(),
224
+ service: this.name,
225
+ level,
226
+ namespace,
227
+ message,
228
+ data,
229
+ tags,
230
+ context,
231
+ };
232
+ }
233
+
234
+ _sanitizeMetadata(metadata) {
235
+ if (!metadata) {
236
+ return null;
237
+ }
238
+ if (metadata instanceof Error) {
239
+ return this._errorToObject(metadata);
240
+ }
241
+ if (typeof metadata === 'object') {
242
+ const clone = { ...metadata };
243
+ if (metadata.error instanceof Error) {
244
+ clone.error = this._errorToObject(metadata.error);
245
+ }
246
+ return clone;
247
+ }
248
+ return { value: metadata };
249
+ }
250
+
251
+ _errorToObject(error) {
252
+ return {
253
+ name: error.name,
254
+ message: error.message,
255
+ stack: error.stack,
256
+ };
257
+ }
258
+
259
+ _recordHistory(entry) {
260
+ this.entries.push(entry);
261
+ if (this.entries.length > this.historyLimit) {
262
+ this.entries.shift();
263
+ }
264
+ }
265
+
266
+ _emit(entry) {
267
+ if (!this.eventBus) {
268
+ return;
269
+ }
270
+ try {
271
+ this.eventBus.emit('log:entry', entry);
272
+ } catch (err) {
273
+ this._consoleTransport({ ...entry, level: 'warn', message: `Failed to emit log entry: ${err.message}` });
274
+ }
275
+ }
276
+
277
+ _dispatch(entry) {
278
+ for (const transport of this.transports) {
279
+ try {
280
+ transport(entry);
281
+ } catch (err) {
282
+ this._consoleTransport({
283
+ ...entry,
284
+ level: 'warn',
285
+ namespace: 'logging',
286
+ message: `Logging transport failed: ${err.message}`,
287
+ data: { transportError: this._errorToObject(err) },
288
+ });
289
+ }
290
+ }
291
+ }
292
+
293
+ _consoleTransport(entry) {
294
+ const prefix = `[${entry.service}][${entry.namespace}]`;
295
+ const method = (entry.level === 'trace' || entry.level === 'debug')
296
+ ? console.log // eslint-disable-line no-console
297
+ : (console[entry.level] || console.log); // eslint-disable-line no-console
298
+ method(`${prefix} ${entry.message}`, entry.data ?? ''); // eslint-disable-line no-console
299
+ }
300
+ }