@nac3/forge-cli 0.2.0-alpha.34 → 0.2.0-alpha.36

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.
@@ -1 +1 @@
1
- {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/chat/panel.ts"],"names":[],"mappings":"AAkBA,OAAO,EAEL,KAAK,iBAAiB,EAEvB,MAAM,kBAAkB,CAAC;AAG1B,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb;;;;;2BAKuB;IACvB,IAAI,CAAC,EAAE,iBAAiB,CAAC;CAC1B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAm+ExD"}
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/chat/panel.ts"],"names":[],"mappings":"AAkBA,OAAO,EAEL,KAAK,iBAAiB,EAEvB,MAAM,kBAAkB,CAAC;AAG1B,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb;;;;;2BAKuB;IACvB,IAAI,CAAC,EAAE,iBAAiB,CAAC;CAC1B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAi9FxD"}
@@ -150,6 +150,135 @@ body {
150
150
  #yf-full .body .pizarra .pizarra-empty .kanji-big {
151
151
  font-size: 96px; opacity: 0.4;
152
152
  }
153
+ /* alpha.35 -- multi-tab pizarron (VS Code-style). */
154
+ #yf-full .pz-tabs {
155
+ display: flex; gap: 2px; background: var(--bg-2);
156
+ border-bottom: 1px solid var(--border);
157
+ padding: 0 6px; overflow-x: auto; flex-shrink: 0;
158
+ }
159
+ #yf-full .pz-tab {
160
+ display: flex; align-items: center; gap: 6px;
161
+ padding: 6px 8px 6px 12px;
162
+ background: var(--bg-1); color: var(--ink-2);
163
+ border: 1px solid var(--border); border-bottom: none;
164
+ border-radius: 4px 4px 0 0;
165
+ font-size: 11px; cursor: pointer; white-space: nowrap;
166
+ position: relative; top: 1px;
167
+ }
168
+ #yf-full .pz-tab:hover { color: var(--ink); }
169
+ #yf-full .pz-tab.active {
170
+ background: var(--bg-0, white); color: var(--ink);
171
+ font-weight: 500;
172
+ }
173
+ #yf-full .pz-tab.dirty .pz-tab-name::after {
174
+ content: ' •'; color: #e88a3c;
175
+ }
176
+ #yf-full .pz-tab-name { max-width: 200px; overflow: hidden; text-overflow: ellipsis; }
177
+ #yf-full .pz-tab-close {
178
+ background: transparent; border: 0; color: inherit;
179
+ font-size: 13px; padding: 0 2px; cursor: pointer; line-height: 1;
180
+ border-radius: 2px;
181
+ }
182
+ #yf-full .pz-tab-close:hover { background: rgba(0,0,0,0.1); }
183
+ #yf-full .pz-tab-body {
184
+ flex: 1; overflow: hidden; min-height: 0;
185
+ display: flex; flex-direction: column;
186
+ background: var(--bg-0, white);
187
+ }
188
+ #yf-full .pz-card {
189
+ display: flex; flex-direction: column;
190
+ flex: 1; min-height: 0;
191
+ }
192
+ #yf-full .pz-card-head {
193
+ display: flex; align-items: center; gap: 8px;
194
+ padding: 6px 10px; background: var(--bg-2);
195
+ border-bottom: 1px solid var(--border-subtle);
196
+ font-size: 11px; flex-shrink: 0;
197
+ }
198
+ #yf-full .pz-kind {
199
+ text-transform: uppercase; letter-spacing: 0.5px;
200
+ font-size: 9px; color: var(--ink-2); font-weight: 600;
201
+ padding: 2px 6px; background: var(--bg-1); border-radius: 3px;
202
+ }
203
+ #yf-full .pz-title { flex: 1; font-weight: 500; color: var(--ink); }
204
+ #yf-full .pz-file-path { font-family: monospace; font-size: 10px; color: var(--ink-2); }
205
+ #yf-full .pz-actions { display: flex; gap: 4px; }
206
+ #yf-full .pz-actions button {
207
+ background: transparent; border: 1px solid transparent;
208
+ color: var(--ink-2); padding: 2px 8px; border-radius: 3px;
209
+ font-size: 11px; cursor: pointer;
210
+ }
211
+ #yf-full .pz-actions button:hover {
212
+ background: rgba(0,0,0,0.05); color: var(--ink);
213
+ border-color: var(--border);
214
+ }
215
+ #yf-full .pz-body {
216
+ flex: 1; min-height: 0;
217
+ padding: 10px; overflow: auto;
218
+ font-size: 12px; background: var(--bg-0, white);
219
+ }
220
+ #yf-full .pz-body pre {
221
+ margin: 0; font-family: ui-monospace, "Cascadia Code", "JetBrains Mono", monospace;
222
+ font-size: 11px; line-height: 1.5; white-space: pre;
223
+ }
224
+ #yf-full .pz-body.pz-markdown { line-height: 1.6; }
225
+ #yf-full .pz-body table {
226
+ width: 100%; border-collapse: collapse; font-size: 11px;
227
+ }
228
+ #yf-full .pz-body th, #yf-full .pz-body td {
229
+ text-align: left; padding: 4px 6px; border-bottom: 1px solid var(--border-subtle);
230
+ }
231
+ #yf-full .pz-body th { font-weight: 600; background: var(--bg-2); }
232
+ #yf-full .pz-edit-wrap {
233
+ flex: 1; min-height: 0;
234
+ display: flex; flex-direction: column;
235
+ }
236
+ #yf-full .pz-edit-area {
237
+ flex: 1; min-height: 0; width: 100%; box-sizing: border-box;
238
+ font-family: ui-monospace, "Cascadia Code", monospace;
239
+ font-size: 12px; line-height: 1.6;
240
+ background: var(--bg-1); color: var(--ink);
241
+ border: none; outline: none;
242
+ padding: 12px; resize: none;
243
+ tab-size: 2;
244
+ }
245
+ #yf-full .pz-edit-actions {
246
+ display: flex; gap: 6px; padding: 6px 10px; align-items: center;
247
+ border-top: 1px solid var(--border-subtle); background: var(--bg-2);
248
+ flex-shrink: 0;
249
+ }
250
+ #yf-full .pz-edit-actions button {
251
+ font-size: 11px; padding: 4px 10px; border-radius: 3px;
252
+ cursor: pointer; border: 1px solid var(--border);
253
+ background: var(--bg-1); color: var(--ink);
254
+ }
255
+ #yf-full .pz-edit-actions .pz-save {
256
+ background: var(--ink); color: var(--bg-1); font-weight: 500;
257
+ }
258
+ #yf-full .pz-edit-actions .pz-save:disabled {
259
+ opacity: 0.4; cursor: not-allowed;
260
+ }
261
+ #yf-full .pz-edit-msg { flex: 1; font-size: 11px; text-align: right; }
262
+ #yf-full .pz-edit-msg.error { color: #c53030; }
263
+ #yf-full .pz-edit-msg.success { color: #2e7d32; }
264
+ #yf-full .pizarron-trace {
265
+ border-top: 1px solid var(--border);
266
+ background: var(--bg-2);
267
+ flex-shrink: 0;
268
+ }
269
+ #yf-full .pizarron-trace summary {
270
+ cursor: pointer; padding: 6px 16px; font-size: 11px;
271
+ color: var(--ink-2); list-style: none;
272
+ display: flex; gap: 10px; align-items: center;
273
+ }
274
+ #yf-full .pizarron-trace summary::-webkit-details-marker { display: none; }
275
+ #yf-full .pizarron-trace[open] summary { border-bottom: 1px solid var(--border-subtle); }
276
+ #yf-full .pizarron-trace .pizarra-body { max-height: 200px; overflow-y: auto; }
277
+ #yf-full .pz-clear {
278
+ background: transparent; border: 0; color: var(--ink-2);
279
+ font-size: 16px; cursor: pointer; padding: 0 4px;
280
+ }
281
+ #yf-full .pz-clear:hover { color: var(--ink); }
153
282
  #yf-full .body .pizarra .pizarra-empty p {
154
283
  color: var(--ink-muted); max-width: 440px;
155
284
  }
@@ -623,17 +752,40 @@ body {
623
752
  <button type="submit" class="send">${escapeHtml(tr.sendButton)}</button>
624
753
  </form>
625
754
  </div>
626
- <div class="pizarra">
755
+ <div class="pizarra" data-nac-id="yujin.pizarron" data-nac-role="region">
756
+ <!-- Pizarron multi-tab: cada item de
757
+ forge_show_in_pizarron es una pestaña. La activa
758
+ ocupa el body completo. Las inactivas quedan
759
+ dormidas (preservan state, ej. textarea edit value).
760
+ NO se lee automatico por TTS -- solo cuando el
761
+ user dice 'leemelo'. -->
627
762
  <div class="pizarra-header">
628
- <h3>Action trace</h3>
629
- <span class="count" id="trace-count" data-nac-id="yujin.pizarra.trace-count">0 tool calls</span>
763
+ <h3>Pizarrón</h3>
764
+ <span class="count" id="pizarron-count" data-nac-id="yujin.pizarron.count">0 pestañas</span>
765
+ <button type="button" class="pz-clear"
766
+ data-pizarron-clear
767
+ data-nac-id="yujin.pizarron.clear-all"
768
+ data-nac-role="action"
769
+ data-nac-action="clear_pizarron"
770
+ aria-label="cerrar todo" title="Cerrar todo el pizarrón">×</button>
630
771
  </div>
631
- <div class="pizarra-body" id="pizarra-body" data-nac-id="yujin.pizarra.body">
632
- <div class="pizarra-empty">
633
- <div class="kanji-big">${escapeHtml(tForLang(lang, 'panel.trace.empty.kanji'))}</div>
634
- <p>${escapeHtml(tForLang(lang, 'panel.trace.empty.body'))}</p>
772
+ <div class="pz-tabs" id="pizarron-tabs"
773
+ data-nac-id="yujin.pizarron.tabs"
774
+ data-nac-role="tablist"></div>
775
+ <div class="pz-tab-body" id="pizarron-body"
776
+ data-nac-id="yujin.pizarron.body"
777
+ data-nac-role="region">
778
+ <div class="pizarra-empty" id="pizarron-empty">
779
+ <div class="kanji-big">板</div>
780
+ <p>Aquí se muestra contenido estructurado: código, tablas, documentos. Pedile a Yujin que escriba o edite algo.</p>
635
781
  </div>
636
782
  </div>
783
+ <!-- Action trace (tool calls log) -- siempre visible
784
+ para inspeccionar pero compacto. -->
785
+ <details class="pizarron-trace" id="pizarron-trace-section">
786
+ <summary>Action trace <span class="count" id="trace-count" data-nac-id="yujin.pizarra.trace-count">0 tool calls</span></summary>
787
+ <div class="pizarra-body" id="pizarra-body" data-nac-id="yujin.pizarra.body"></div>
788
+ </details>
637
789
  </div>
638
790
  </div>
639
791
  </div>
@@ -671,6 +823,11 @@ let state = {
671
823
  matcher can resolve commands that need a target ("siguiente",
672
824
  "buscar X", etc). Updated on every forge.reader.open. */
673
825
  activeReaderDocId: '',
826
+ /* alpha.35 -- multi-tab pizarron. Each item:
827
+ { id, title, kind, content, language?, file_path?,
828
+ isEditing?, editValue?, dirty? }
829
+ activeId picks which tab body to render. */
830
+ pizarron: { items: [], activeId: null },
674
831
  };
675
832
 
676
833
  function loadMode() {
@@ -785,6 +942,255 @@ function renderStream() {
785
942
  }
786
943
  }
787
944
 
945
+ /* =========================================================================
946
+ * Pizarron multi-tab (alpha.35). Items live in state.pizarron.items;
947
+ * the active one is rendered in the body. NAC3-compliant: every
948
+ * interactive element carries data-nac-id + data-nac-role + data-
949
+ * nac-action so Forge can auto-navigate the panel via the NAC3
950
+ * manifest exposed at /api/forge/pizarron-manifest. */
951
+ function pizarronAddItem(item) {
952
+ const list = state.pizarron.items;
953
+ /* Dedup by file_path when editing the same file twice. */
954
+ if (item.file_path) {
955
+ const existing = list.find((x) => x.file_path === item.file_path);
956
+ if (existing) {
957
+ Object.assign(existing, item, { id: existing.id });
958
+ pizarronSetActive(existing.id);
959
+ renderPizarron();
960
+ return existing.id;
961
+ }
962
+ }
963
+ list.push(item);
964
+ /* Auto-switch only when the user is NOT editing another tab.
965
+ Preserves their context. */
966
+ const cur = pizarronGetActive();
967
+ if (!cur || !cur.isEditing) {
968
+ state.pizarron.activeId = item.id;
969
+ }
970
+ renderPizarron();
971
+ return item.id;
972
+ }
973
+
974
+ function pizarronGetActive() {
975
+ if (!state.pizarron.activeId) return null;
976
+ return state.pizarron.items.find((x) => x.id === state.pizarron.activeId) || null;
977
+ }
978
+
979
+ function pizarronSetActive(id) {
980
+ if (state.pizarron.items.find((x) => x.id === id)) {
981
+ state.pizarron.activeId = id;
982
+ renderPizarron();
983
+ }
984
+ }
985
+
986
+ function pizarronCloseItem(id) {
987
+ const idx = state.pizarron.items.findIndex((x) => x.id === id);
988
+ if (idx < 0) return;
989
+ const it = state.pizarron.items[idx];
990
+ if (it.dirty) {
991
+ if (!confirm('La pestaña "' + it.title + '" tiene cambios sin guardar. ¿Cerrar igual?')) return;
992
+ }
993
+ state.pizarron.items.splice(idx, 1);
994
+ if (state.pizarron.activeId === id) {
995
+ const next = state.pizarron.items[state.pizarron.items.length - 1];
996
+ state.pizarron.activeId = next ? next.id : null;
997
+ }
998
+ renderPizarron();
999
+ }
1000
+
1001
+ function pizarronClearAll() {
1002
+ const dirty = state.pizarron.items.find((x) => x.dirty);
1003
+ if (dirty && !confirm('Hay pestañas con cambios sin guardar. ¿Cerrar todo igual?')) return;
1004
+ state.pizarron.items = [];
1005
+ state.pizarron.activeId = null;
1006
+ renderPizarron();
1007
+ }
1008
+
1009
+ function pizarronStartEdit(id) {
1010
+ const it = state.pizarron.items.find((x) => x.id === id);
1011
+ if (!it) return;
1012
+ if (it.kind !== 'code' && it.kind !== 'markdown' && it.kind !== 'document') {
1013
+ setStatus('Este tipo de contenido no es editable.', true);
1014
+ return;
1015
+ }
1016
+ it.isEditing = true;
1017
+ it.editValue = it.content;
1018
+ it.dirty = false;
1019
+ renderPizarron();
1020
+ }
1021
+
1022
+ async function pizarronSave(id) {
1023
+ const it = state.pizarron.items.find((x) => x.id === id);
1024
+ if (!it || !it.isEditing) return;
1025
+ if (!it.file_path) {
1026
+ /* Snippet-only edit: persist back to the in-memory item. */
1027
+ it.content = it.editValue;
1028
+ it.dirty = false;
1029
+ setStatus('Cambios guardados en la pestaña (no en disco -- sin file_path).');
1030
+ renderPizarron();
1031
+ return;
1032
+ }
1033
+ /* File-backed edit: write to disk via /api/forge/file. */
1034
+ try {
1035
+ const r = await fetch('/api/forge/file', {
1036
+ method: 'POST',
1037
+ headers: { 'content-type': 'application/json' },
1038
+ body: JSON.stringify({ path: it.file_path, content: it.editValue }),
1039
+ });
1040
+ const data = await r.json();
1041
+ if (!r.ok || !data.ok) {
1042
+ setStatus('Error al guardar: ' + (data.error || r.status), true);
1043
+ return;
1044
+ }
1045
+ it.content = it.editValue;
1046
+ it.dirty = false;
1047
+ setStatus('Guardado: ' + it.file_path + ' (' + data.bytes_written + ' bytes)');
1048
+ renderPizarron();
1049
+ } catch (err) {
1050
+ setStatus('Error de red: ' + (err && err.message ? err.message : err), true);
1051
+ }
1052
+ }
1053
+
1054
+ function pizarronDiscard(id) {
1055
+ const it = state.pizarron.items.find((x) => x.id === id);
1056
+ if (!it) return;
1057
+ if (it.dirty && !confirm('Descartar los cambios sin guardar?')) return;
1058
+ it.isEditing = false;
1059
+ it.editValue = it.content;
1060
+ it.dirty = false;
1061
+ renderPizarron();
1062
+ }
1063
+
1064
+ function pizarronReadAloud(id) {
1065
+ const it = state.pizarron.items.find((x) => x.id === id);
1066
+ if (!it) return;
1067
+ /* Strip markdown structure to make it readable, then TTS. */
1068
+ let txt = it.content;
1069
+ if (it.kind === 'code') {
1070
+ txt = 'Código' + (it.language ? ' en ' + it.language : '') + '. '
1071
+ + (it.file_path ? 'Archivo ' + it.file_path + '. ' : '')
1072
+ + 'Contenido: ' + txt;
1073
+ }
1074
+ playTtsForText(txt);
1075
+ }
1076
+
1077
+ function pizarronCopy(id) {
1078
+ const it = state.pizarron.items.find((x) => x.id === id);
1079
+ if (!it) return;
1080
+ const value = it.isEditing ? it.editValue : it.content;
1081
+ if (navigator.clipboard && navigator.clipboard.writeText) {
1082
+ navigator.clipboard.writeText(value)
1083
+ .then(() => setStatus('Copiado al portapapeles.'))
1084
+ .catch(() => setStatus('No se pudo copiar.', true));
1085
+ }
1086
+ }
1087
+
1088
+ function renderPizarronCardBody(it) {
1089
+ if (it.isEditing) {
1090
+ const dirtyTag = it.dirty ? '<span style="color:#e88a3c;">●&nbsp;Sin guardar</span>' : '';
1091
+ return '<div class="pz-edit-wrap" data-nac-id="yujin.pizarron.editor.' + it.id + '" data-nac-role="region">'
1092
+ + '<textarea class="pz-edit-area" data-pz-edit-input data-pz-item-id="' + it.id + '"'
1093
+ + ' data-nac-id="yujin.pizarron.editor.' + it.id + '.input"'
1094
+ + ' data-nac-role="field" data-nac-action="edit_content"'
1095
+ + ' spellcheck="false">' + escapeHtml(it.editValue || '') + '</textarea>'
1096
+ + '<div class="pz-edit-actions">'
1097
+ + ' <button type="button" class="pz-save" data-pz-save data-pz-item-id="' + it.id + '"'
1098
+ + ' data-nac-id="yujin.pizarron.editor.' + it.id + '.save"'
1099
+ + ' data-nac-role="action" data-nac-action="save_file">Guardar</button>'
1100
+ + ' <button type="button" data-pz-discard data-pz-item-id="' + it.id + '"'
1101
+ + ' data-nac-id="yujin.pizarron.editor.' + it.id + '.discard"'
1102
+ + ' data-nac-role="action" data-nac-action="discard_changes">Descartar</button>'
1103
+ + ' <span class="pz-edit-msg">' + dirtyTag + '</span>'
1104
+ + '</div>'
1105
+ + '</div>';
1106
+ }
1107
+ /* View mode by kind. */
1108
+ if (it.kind === 'code') {
1109
+ return '<div class="pz-body" data-nac-id="yujin.pizarron.item.' + it.id + '.body" data-nac-role="region">'
1110
+ + '<pre>' + escapeHtml(it.content) + '</pre>'
1111
+ + '</div>';
1112
+ }
1113
+ if (it.kind === 'markdown' || it.kind === 'document') {
1114
+ return '<div class="pz-body pz-markdown" data-nac-id="yujin.pizarron.item.' + it.id + '.body" data-nac-role="region">'
1115
+ + renderMd(it.content) + '</div>';
1116
+ }
1117
+ if (it.kind === 'table') {
1118
+ return '<div class="pz-body" data-nac-id="yujin.pizarron.item.' + it.id + '.body" data-nac-role="region">'
1119
+ + renderMd(it.content) + '</div>';
1120
+ }
1121
+ if (it.kind === 'tree') {
1122
+ return '<div class="pz-body" data-nac-id="yujin.pizarron.item.' + it.id + '.body" data-nac-role="region">'
1123
+ + '<pre>' + escapeHtml(it.content) + '</pre></div>';
1124
+ }
1125
+ if (it.kind === 'bpmn' || it.kind === 'flow') {
1126
+ /* Trust SVG content from the LLM only when it starts with
1127
+ <svg ... otherwise treat as text (mermaid syntax etc). */
1128
+ const trimmed = it.content.trim();
1129
+ if (trimmed.startsWith('<svg')) {
1130
+ return '<div class="pz-body" data-nac-id="yujin.pizarron.item.' + it.id + '.body" data-nac-role="region">'
1131
+ + trimmed + '</div>';
1132
+ }
1133
+ return '<div class="pz-body" data-nac-id="yujin.pizarron.item.' + it.id + '.body" data-nac-role="region">'
1134
+ + '<pre>' + escapeHtml(it.content) + '</pre></div>';
1135
+ }
1136
+ return '<div class="pz-body" data-nac-id="yujin.pizarron.item.' + it.id + '.body" data-nac-role="region"><pre>'
1137
+ + escapeHtml(it.content) + '</pre></div>';
1138
+ }
1139
+
1140
+ function renderPizarron() {
1141
+ const tabs = $('#pizarron-tabs');
1142
+ const body = $('#pizarron-body');
1143
+ const empty = $('#pizarron-empty');
1144
+ const count = $('#pizarron-count');
1145
+ if (!tabs || !body || !count) return;
1146
+ count.textContent = state.pizarron.items.length + (state.pizarron.items.length === 1 ? ' pestaña' : ' pestañas');
1147
+ /* Render tabs */
1148
+ tabs.innerHTML = state.pizarron.items.map((it) => {
1149
+ const isActive = it.id === state.pizarron.activeId;
1150
+ return '<div class="pz-tab' + (isActive ? ' active' : '') + (it.dirty ? ' dirty' : '') + '"'
1151
+ + ' data-pz-tab data-pz-item-id="' + it.id + '"'
1152
+ + ' data-nac-id="yujin.pizarron.tab.' + it.id + '"'
1153
+ + ' data-nac-role="tab" data-nac-action="activate_tab">'
1154
+ + '<span class="pz-tab-name">' + escapeHtml(it.title) + '</span>'
1155
+ + '<button type="button" class="pz-tab-close" data-pz-close data-pz-item-id="' + it.id + '"'
1156
+ + ' data-nac-id="yujin.pizarron.tab.' + it.id + '.close"'
1157
+ + ' data-nac-role="action" data-nac-action="close_tab"'
1158
+ + ' title="Cerrar pestaña" aria-label="cerrar">×</button>'
1159
+ + '</div>';
1160
+ }).join('');
1161
+ /* Render active body */
1162
+ if (state.pizarron.items.length === 0) {
1163
+ if (empty) empty.style.display = '';
1164
+ body.innerHTML = '<div class="pizarra-empty" id="pizarron-empty"><div class="kanji-big">板</div>'
1165
+ + '<p>Aquí se muestra contenido estructurado: código, tablas, documentos. Pedile a Yujin que escriba o edite algo.</p></div>';
1166
+ return;
1167
+ }
1168
+ const it = pizarronGetActive() || state.pizarron.items[state.pizarron.items.length - 1];
1169
+ if (it && state.pizarron.activeId !== it.id) state.pizarron.activeId = it.id;
1170
+ const canEdit = (it.kind === 'code' || it.kind === 'markdown' || it.kind === 'document') && !it.isEditing;
1171
+ body.innerHTML = '<div class="pz-card" data-nac-id="yujin.pizarron.item.' + it.id + '" data-nac-role="region">'
1172
+ + '<div class="pz-card-head">'
1173
+ + ' <span class="pz-kind">' + escapeHtml(it.kind) + (it.language ? ' / ' + escapeHtml(it.language) : '') + '</span>'
1174
+ + ' <span class="pz-title">' + escapeHtml(it.title) + '</span>'
1175
+ + (it.file_path ? ' <span class="pz-file-path">' + escapeHtml(it.file_path) + '</span>' : '')
1176
+ + ' <div class="pz-actions">'
1177
+ + (canEdit
1178
+ ? '<button type="button" data-pz-edit data-pz-item-id="' + it.id + '"'
1179
+ + ' data-nac-id="yujin.pizarron.item.' + it.id + '.edit"'
1180
+ + ' data-nac-role="action" data-nac-action="edit_item">Editar</button>'
1181
+ : '')
1182
+ + ' <button type="button" data-pz-read data-pz-item-id="' + it.id + '"'
1183
+ + ' data-nac-id="yujin.pizarron.item.' + it.id + '.read"'
1184
+ + ' data-nac-role="action" data-nac-action="read_aloud">Leerme</button>'
1185
+ + ' <button type="button" data-pz-copy data-pz-item-id="' + it.id + '"'
1186
+ + ' data-nac-id="yujin.pizarron.item.' + it.id + '.copy"'
1187
+ + ' data-nac-role="action" data-nac-action="copy_content">Copiar</button>'
1188
+ + ' </div>'
1189
+ + '</div>'
1190
+ + renderPizarronCardBody(it)
1191
+ + '</div>';
1192
+ }
1193
+
788
1194
  function renderTrace() {
789
1195
  const body = $('#pizarra-body');
790
1196
  const count = $('#trace-count');
@@ -883,6 +1289,27 @@ async function send(text) {
883
1289
  rounds: data.tool_rounds,
884
1290
  });
885
1291
  renderTrace();
1292
+ /* alpha.35 -- pizarron intercept. Any forge_show_in_pizarron
1293
+ tool round emitted by the LLM becomes a tab in the
1294
+ pizarron side panel. */
1295
+ for (const round of data.tool_rounds) {
1296
+ if (round.tool === 'forge_show_in_pizarron' && !round.is_error && round.result) {
1297
+ const r = round.result;
1298
+ if (r.item_id && r.title && r.kind && typeof r.content === 'string') {
1299
+ pizarronAddItem({
1300
+ id: r.item_id,
1301
+ title: r.title,
1302
+ kind: r.kind,
1303
+ content: r.content,
1304
+ language: r.language || null,
1305
+ file_path: r.file_path || null,
1306
+ isEditing: false,
1307
+ editValue: r.content,
1308
+ dirty: false,
1309
+ });
1310
+ }
1311
+ }
1312
+ }
886
1313
  }
887
1314
  } catch (err) {
888
1315
  setStatus(String(err && err.message ? err.message : err), true);
@@ -2352,6 +2779,73 @@ document.addEventListener('DOMContentLoaded', () => {
2352
2779
  attachBar($('#bar-full'));
2353
2780
  renderStream();
2354
2781
  renderTrace();
2782
+ renderPizarron();
2783
+
2784
+ /* alpha.35 -- pizarron event delegation. Single document
2785
+ listener catches tab clicks, close, edit, save, etc.
2786
+ Avoids re-binding every render. */
2787
+ const pzRoot = $('#yf-full');
2788
+ if (pzRoot) {
2789
+ pzRoot.addEventListener('click', (e) => {
2790
+ const t = e.target;
2791
+ if (!t || !t.closest) return;
2792
+ const tabEl = t.closest('[data-pz-tab]');
2793
+ const closeEl = t.closest('[data-pz-close]');
2794
+ const editEl = t.closest('[data-pz-edit]');
2795
+ const saveEl = t.closest('[data-pz-save]');
2796
+ const discardEl = t.closest('[data-pz-discard]');
2797
+ const readEl = t.closest('[data-pz-read]');
2798
+ const copyEl = t.closest('[data-pz-copy]');
2799
+ const clearAllEl = t.closest('[data-pizarron-clear]');
2800
+ if (closeEl) {
2801
+ e.stopPropagation();
2802
+ pizarronCloseItem(closeEl.getAttribute('data-pz-item-id'));
2803
+ } else if (tabEl) {
2804
+ pizarronSetActive(tabEl.getAttribute('data-pz-item-id'));
2805
+ } else if (editEl) {
2806
+ pizarronStartEdit(editEl.getAttribute('data-pz-item-id'));
2807
+ } else if (saveEl) {
2808
+ pizarronSave(saveEl.getAttribute('data-pz-item-id'));
2809
+ } else if (discardEl) {
2810
+ pizarronDiscard(discardEl.getAttribute('data-pz-item-id'));
2811
+ } else if (readEl) {
2812
+ pizarronReadAloud(readEl.getAttribute('data-pz-item-id'));
2813
+ } else if (copyEl) {
2814
+ pizarronCopy(copyEl.getAttribute('data-pz-item-id'));
2815
+ } else if (clearAllEl) {
2816
+ pizarronClearAll();
2817
+ }
2818
+ });
2819
+ /* Textarea input -> mark dirty + update editValue. */
2820
+ pzRoot.addEventListener('input', (e) => {
2821
+ const ta = e.target && e.target.closest && e.target.closest('[data-pz-edit-input]');
2822
+ if (!ta) return;
2823
+ const id = ta.getAttribute('data-pz-item-id');
2824
+ const it = state.pizarron.items.find((x) => x.id === id);
2825
+ if (!it) return;
2826
+ it.editValue = ta.value;
2827
+ const wasDirty = it.dirty;
2828
+ it.dirty = (it.editValue !== it.content);
2829
+ /* Update tab dirty indicator + edit-msg without rerendering
2830
+ the textarea (would lose caret + focus). */
2831
+ if (wasDirty !== it.dirty) {
2832
+ const tab = pzRoot.querySelector('[data-pz-tab][data-pz-item-id="' + id + '"]');
2833
+ if (tab) tab.classList.toggle('dirty', it.dirty);
2834
+ const msgEl = pzRoot.querySelector('.pz-edit-msg');
2835
+ if (msgEl) msgEl.innerHTML = it.dirty ? '<span style="color:#e88a3c;">●&nbsp;Sin guardar</span>' : '';
2836
+ }
2837
+ });
2838
+ /* Ctrl+S inside textarea -> save active tab. */
2839
+ pzRoot.addEventListener('keydown', (e) => {
2840
+ if ((e.ctrlKey || e.metaKey) && e.key === 's') {
2841
+ const ta = e.target && e.target.closest && e.target.closest('[data-pz-edit-input]');
2842
+ if (ta) {
2843
+ e.preventDefault();
2844
+ pizarronSave(ta.getAttribute('data-pz-item-id'));
2845
+ }
2846
+ }
2847
+ });
2848
+ }
2355
2849
 
2356
2850
  /* Voice controls. */
2357
2851
  $$('[data-mic-btn]').forEach((b) => b.addEventListener('click', () => micToggle(b)));
@@ -1 +1 @@
1
- {"version":3,"file":"panel.js","sourceRoot":"","sources":["../../src/chat/panel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EACL,eAAe,EAAE,QAAQ,GAG1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAepD,MAAM,UAAU,eAAe,CAAC,GAAgB;IAC9C,+DAA+D;IAC/D,+DAA+D;IAC/D,6DAA6D;IAC7D,4DAA4D;IAC5D,oCAAoC;IACpC,MAAM,IAAI,GAAsB,GAAG,CAAC,IAAI,IAAI,eAAe,EAAE,CAAC;IAE9D,4DAA4D;IAC5D,2DAA2D;IAC3D,+DAA+D;IAC/D,2DAA2D;IAC3D,uBAAuB;IACvB,MAAM,EAAE,GAAG;QACT,gBAAgB,EAAE,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;QAC3D,UAAU,EAAQ,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;QACrD,SAAS,EAAS,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;QACpD,YAAY,EAAM,QAAQ,CAAC,IAAI,EAAE,4BAA4B,CAAC;QAC9D,SAAS,EAAS,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;QACpD,UAAU,EAAQ,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;QACrD,cAAc,EAAI,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC;QACzD,WAAW,EAAO,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;QACtD,cAAc,EAAI,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC;QACzD,UAAU,EAAQ,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC;QAC1D,UAAU,EAAQ,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;QACrD,gBAAgB,EAAE,QAAQ,CAAC,IAAI,EAAE,0BAA0B,CAAC;QAC5D,eAAe,EAAG,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;QAC3D,eAAe,EAAG,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;QAC3D,cAAc,EAAI,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC;KAC3D,CAAC;IACF,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC;QACnC,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,IAAI,EAAS,GAAG,CAAC,IAAI;QACrB,OAAO,EAAM,OAAO;QACpB,IAAI;QACJ,IAAI,EAAS,EAAE;KAChB,CAAC,CAAC;IAEH,wDAAwD;IACxD,yDAAyD;IACzD,sCAAsC;IACtC,MAAM,GAAG,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IAE1C,OAAO;cACK,IAAI,UAAU,GAAG;;;;mCAII,UAAU,CAAC,OAAO,CAAC;mCACnB,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC;8BAChC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC;;EAEvD,eAAe,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA8WH,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,gBAAgB,CAAC;WAC7E,UAAU,CAAC,EAAE,CAAC,gBAAgB,CAAC,KAAK,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC;;;;;wBAKhD,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC;;;;6DAIY,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC;kFACvE,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC,YAAY,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;iFACnH,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC,YAAY,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC;;;;;;0EAMvE,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC,YAAY,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC;2EAC3D,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC,YAAY,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC;sCACjG,UAAU,CAAC,EAAE,CAAC,gBAAgB,CAAC,iBAAiB,UAAU,CAAC,EAAE,CAAC,gBAAgB,CAAC;yCAC5E,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC;;;;;;;6DAOL,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;6CAC/D,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC;;;2FAGV,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;oFACnD,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAmCrG,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC;;;;;;;;;;;;;;;8BAerB,UAAU,CAAC,EAAE,CAAC,cAAc,CAAC;yBAClC,UAAU,CAAC,EAAE,CAAC,cAAc,CAAC;;;;;8BAKxB,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC;yBAC/B,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iEAyDc,UAAU,CAAC,EAAE,CAAC,cAAc,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gFAoCd,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC,YAAY,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC;iFAC3D,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC,YAAY,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC;4CACjG,UAAU,CAAC,EAAE,CAAC,gBAAgB,CAAC,iBAAiB,UAAU,CAAC,EAAE,CAAC,gBAAgB,CAAC;+CAC5E,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC;;;;;;;;;;qCAUnC,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC,CAAC;iBACzE,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;;;;;;;;;;;;;;;yBAe5C,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;wBAC/C,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;;;;;iBAKpD,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAq2DtB,CAAC;AACT,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC;SACL,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"panel.js","sourceRoot":"","sources":["../../src/chat/panel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EACL,eAAe,EAAE,QAAQ,GAG1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAepD,MAAM,UAAU,eAAe,CAAC,GAAgB;IAC9C,+DAA+D;IAC/D,+DAA+D;IAC/D,6DAA6D;IAC7D,4DAA4D;IAC5D,oCAAoC;IACpC,MAAM,IAAI,GAAsB,GAAG,CAAC,IAAI,IAAI,eAAe,EAAE,CAAC;IAE9D,4DAA4D;IAC5D,2DAA2D;IAC3D,+DAA+D;IAC/D,2DAA2D;IAC3D,uBAAuB;IACvB,MAAM,EAAE,GAAG;QACT,gBAAgB,EAAE,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;QAC3D,UAAU,EAAQ,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;QACrD,SAAS,EAAS,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;QACpD,YAAY,EAAM,QAAQ,CAAC,IAAI,EAAE,4BAA4B,CAAC;QAC9D,SAAS,EAAS,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;QACpD,UAAU,EAAQ,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;QACrD,cAAc,EAAI,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC;QACzD,WAAW,EAAO,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;QACtD,cAAc,EAAI,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC;QACzD,UAAU,EAAQ,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC;QAC1D,UAAU,EAAQ,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;QACrD,gBAAgB,EAAE,QAAQ,CAAC,IAAI,EAAE,0BAA0B,CAAC;QAC5D,eAAe,EAAG,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;QAC3D,eAAe,EAAG,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;QAC3D,cAAc,EAAI,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC;KAC3D,CAAC;IACF,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC;QACnC,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,IAAI,EAAS,GAAG,CAAC,IAAI;QACrB,OAAO,EAAM,OAAO;QACpB,IAAI;QACJ,IAAI,EAAS,EAAE;KAChB,CAAC,CAAC;IAEH,wDAAwD;IACxD,yDAAyD;IACzD,sCAAsC;IACtC,MAAM,GAAG,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IAE1C,OAAO;cACK,IAAI,UAAU,GAAG;;;;mCAII,UAAU,CAAC,OAAO,CAAC;mCACnB,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC;8BAChC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC;;EAEvD,eAAe,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA+eH,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,gBAAgB,CAAC;WAC7E,UAAU,CAAC,EAAE,CAAC,gBAAgB,CAAC,KAAK,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC;;;;;wBAKhD,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC;;;;6DAIY,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC;kFACvE,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC,YAAY,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;iFACnH,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC,YAAY,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC;;;;;;0EAMvE,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC,YAAY,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC;2EAC3D,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC,YAAY,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC;sCACjG,UAAU,CAAC,EAAE,CAAC,gBAAgB,CAAC,iBAAiB,UAAU,CAAC,EAAE,CAAC,gBAAgB,CAAC;yCAC5E,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC;;;;;;;6DAOL,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;6CAC/D,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC;;;2FAGV,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;oFACnD,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAmCrG,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC;;;;;;;;;;;;;;;8BAerB,UAAU,CAAC,EAAE,CAAC,cAAc,CAAC;yBAClC,UAAU,CAAC,EAAE,CAAC,cAAc,CAAC;;;;;8BAKxB,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC;yBAC/B,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iEAyDc,UAAU,CAAC,EAAE,CAAC,cAAc,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gFAoCd,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC,YAAY,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC;iFAC3D,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC,YAAY,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC;4CACjG,UAAU,CAAC,EAAE,CAAC,gBAAgB,CAAC,iBAAiB,UAAU,CAAC,EAAE,CAAC,gBAAgB,CAAC;+CAC5E,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAiD/C,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;wBAC/C,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;;;;;iBAKpD,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA2rEtB,CAAC;AACT,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC;SACL,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC"}