antri_cli 1.57.35 → 1.57.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.
@@ -460,6 +460,8 @@ function renderActiveSessionMessages(messages) {
460
460
  <p>Minimalist environment for autonomous coding, architectural planning, and self-refinement. State, memory, profiles, and skills are synchronized across CLI and Desktop.</p>
461
461
  <div class="quick-action-pills">
462
462
  <button onclick="setPrompt('Plan the architecture for a real-time collaborative code editor')">Plan Editor Architecture</button>
463
+ <button onclick="setPrompt('/reproduce TypeError: Cannot read properties of undefined in calculateCartTotal')">🧬 BugTwin Reproduce</button>
464
+ <button onclick="setPrompt('/replay TypeError: Unhandled exception at src/server.ts:42:15')">⏱️ CrashZero Replay</button>
463
465
  <button onclick="setPrompt('/debate What are the trade-offs between WebSockets vs Server-Sent Events?')">Start Dialectic Debate</button>
464
466
  <button onclick="setPrompt('/goal Implement a zero-dependency LRU cache with TTL in TypeScript')">Run Goal Loop</button>
465
467
  </div>
@@ -561,6 +563,7 @@ async function deleteCurrentChatSession() {
561
563
  async function submitPrompt() {
562
564
  const input = document.getElementById('prompt-input');
563
565
  let prompt = input.value.trim();
566
+ let lastServerArtifacts = null;
564
567
 
565
568
  // Attach any uploaded files to prompt
566
569
  if (attachedFiles.length > 0) {
@@ -794,113 +797,7 @@ function appendMessage(role, text) {
794
797
  return row;
795
798
  }
796
799
 
797
- // Artifact Hub Management
798
- async function loadArtifactsTab() {
799
- try {
800
- const res = await fetch('/api/artifacts');
801
- const data = await res.json();
802
- const container = document.getElementById('artifacts-grouped-container');
803
- if (!container) return;
804
- container.innerHTML = '';
805
-
806
- if (!data.grouped || data.grouped.length === 0) {
807
- container.innerHTML = `
808
- <div style="text-align:center;padding:48px 16px;color:var(--text-muted);">
809
- <div style="font-size:36px;margin-bottom:12px;">🎨</div>
810
- <h3 style="color:var(--text-primary);margin-bottom:6px;">No Artifacts Generated Yet</h3>
811
- <p style="font-size:13px;">Generate interactive HTML plans, architecture graphs, or mind maps with <code>/view</code>, <code>/mindmap</code>, or <code>/imagine</code> in chat.</p>
812
- </div>
813
- `;
814
- return;
815
- }
816
-
817
- const totalCount = data.artifacts ? data.artifacts.length : 0;
818
- const toolbar = document.createElement('div');
819
- toolbar.className = 'artifacts-toolbar';
820
- toolbar.innerHTML = `
821
- <div style="font-size:13px;color:var(--text-muted);font-weight:600;">
822
- Showing <span style="color:var(--text-primary);font-weight:700;">${totalCount}</span> artifact${totalCount === 1 ? '' : 's'} across <span style="color:var(--text-primary);font-weight:700;">${data.grouped.length}</span> chat session${data.grouped.length === 1 ? '' : 's'}
823
- </div>
824
- <button class="artifacts-toggle-all-btn" id="artifactsToggleAllBtn" onclick="toggleAllArtifactGroups()">📁 Collapse All</button>
825
- `;
826
- container.appendChild(toolbar);
827
-
828
- data.grouped.forEach((grp, idx) => {
829
- const groupEl = document.createElement('div');
830
- groupEl.className = 'artifact-session-group';
831
- groupEl.id = `artifact-group-${idx}`;
832
-
833
- let cardsHtml = '';
834
- grp.artifacts.forEach((art) => {
835
- const isMindmap = art.type === 'mindmap';
836
- const isGraph = art.type === 'graph';
837
- const typeClass = isMindmap ? 'badge-mindmap' : isGraph ? 'badge-graph' : 'badge-html';
838
- const typeText = isMindmap ? 'Mind Map' : isGraph ? 'Code Graph' : 'Interactive HTML';
839
- const icon = isMindmap ? '🧠' : isGraph ? '📊' : '🌐';
840
- const dateStr = new Date(art.createdAt).toLocaleDateString();
841
-
842
- cardsHtml += `
843
- <div class="artifact-item-card">
844
- <div>
845
- <div style="display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:8px;">
846
- <span class="artifact-card-badge ${typeClass}">${icon} ${typeText}</span>
847
- <span style="font-size:11px;color:var(--text-muted);">${dateStr}</span>
848
- </div>
849
- <div style="font-weight:700;font-size:14px;color:var(--text-primary);margin-bottom:4px;">${escapeHtml(art.title)}</div>
850
- <div style="font-size:12px;color:var(--text-muted);">ID: ${art.id}</div>
851
- </div>
852
- <div style="display:flex;justify-content:space-between;align-items:center;margin-top:8px;">
853
- <button class="chat-artifact-btn" onclick="openArtifactViewer('${encodeURIComponent(art.id)}', '${escapeHtml(art.title)}', '${art.type}')">👁️ View Artifact</button>
854
- <button style="background:none;border:none;color:var(--text-muted);cursor:pointer;font-size:14px;" title="Delete Artifact" onclick="deleteArtifactDesktop('${art.id}')">🗑️</button>
855
- </div>
856
- </div>
857
- `;
858
- });
859
-
860
- groupEl.innerHTML = `
861
- <div class="artifact-session-header" onclick="toggleArtifactGroup('${groupEl.id}')">
862
- <div class="artifact-session-title">
863
- <span class="artifact-collapse-chevron">▼</span>
864
- <span>📁</span>
865
- <span>${escapeHtml(grp.sessionTitle || 'Chat Session')}</span>
866
- </div>
867
- <span style="font-size:12px;color:var(--text-muted);">${grp.artifacts.length} ${grp.artifacts.length === 1 ? 'artifact' : 'artifacts'}</span>
868
- </div>
869
- <div class="artifacts-grid">
870
- ${cardsHtml}
871
- </div>
872
- `;
873
- container.appendChild(groupEl);
874
- });
875
- } catch (err) {
876
- console.error('Failed to load artifacts tab:', err);
877
- }
878
- }
879
-
880
- function toggleArtifactGroup(groupId) {
881
- const el = document.getElementById(groupId);
882
- if (el) {
883
- el.classList.toggle('collapsed');
884
- }
885
- }
886
800
 
887
- function toggleAllArtifactGroups() {
888
- const groups = document.querySelectorAll('.artifact-session-group');
889
- const btn = document.getElementById('artifactsToggleAllBtn');
890
- const anyOpen = Array.from(groups).some((g) => !g.classList.contains('collapsed'));
891
-
892
- groups.forEach((g) => {
893
- if (anyOpen) {
894
- g.classList.add('collapsed');
895
- } else {
896
- g.classList.remove('collapsed');
897
- }
898
- });
899
-
900
- if (btn) {
901
- btn.textContent = anyOpen ? '📂 Expand All' : '📁 Collapse All';
902
- }
903
- }
904
801
 
905
802
  function openArtifactViewer(id, title = 'Artifact View', type = 'html') {
906
803
  const modal = document.getElementById('artifact-viewer-modal');
@@ -962,18 +859,114 @@ function setPrompt(text) {
962
859
  input.focus();
963
860
  }
964
861
 
965
- // Dialectic Debate Runner
862
+ // Markdown & Structured Content Renderer for Desktop Views
863
+ function renderFormattedMarkdown(text) {
864
+ if (!text) return '';
865
+ let html = escapeHtml(text);
866
+
867
+ // Code blocks: ```lang ... ```
868
+ html = html.replace(/```([a-zA-Z0-9_-]*)\n([\s\S]*?)```/g, (match, lang, code) => {
869
+ return `<div class="formatted-code-block"><div class="code-block-header">${lang || 'code'}</div><pre><code>${code.trim()}</code></pre></div>`;
870
+ });
871
+
872
+ // Inline code: `...`
873
+ html = html.replace(/`([^`]+)`/g, '<code class="inline-code">$1</code>');
874
+
875
+ // Headers
876
+ html = html.replace(/^#### (.*?)$/gm, '<h5 class="formatted-h5">$1</h5>');
877
+ html = html.replace(/^### (.*?)$/gm, '<h4 class="formatted-h4">$1</h4>');
878
+ html = html.replace(/^## (.*?)$/gm, '<h3 class="formatted-h3">$1</h3>');
879
+ html = html.replace(/^# (.*?)$/gm, '<h2 class="formatted-h2">$1</h2>');
880
+
881
+ // Bold & Italic
882
+ html = html.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
883
+ html = html.replace(/\*([^*]+)\*/g, '<em>$1</em>');
884
+
885
+ // Blockquotes
886
+ html = html.replace(/^> (.*?)$/gm, '<blockquote class="formatted-quote">$1</blockquote>');
887
+
888
+ // Bullet points
889
+ html = html.replace(/^[•\-\*] (.*?)$/gm, '<div class="bullet-item">• $1</div>');
890
+
891
+ // Numbered lists
892
+ html = html.replace(/^(\d+)\. (.*?)$/gm, '<div class="number-item"><span class="num-badge">$1.</span> $2</div>');
893
+
894
+ return html;
895
+ }
896
+
897
+ // Robust SSE Stream Reader with Chunk Buffer Persistence
898
+ async function readSSEStream(response, onEvent) {
899
+ const reader = response.body.getReader();
900
+ const decoder = new TextDecoder();
901
+ let buffer = '';
902
+
903
+ while (true) {
904
+ const { done, value } = await reader.read();
905
+ if (done) break;
906
+
907
+ buffer += decoder.decode(value, { stream: true });
908
+ const lines = buffer.split('\n');
909
+ buffer = lines.pop() || '';
910
+
911
+ let currentEvent = 'message';
912
+ for (const line of lines) {
913
+ const trimmed = line.trim();
914
+ if (!trimmed) {
915
+ currentEvent = 'message';
916
+ continue;
917
+ }
918
+ if (line.startsWith('event: ')) {
919
+ currentEvent = line.slice(7).trim();
920
+ } else if (line.startsWith('data: ')) {
921
+ const rawData = line.slice(6);
922
+ let parsed = rawData;
923
+ try {
924
+ parsed = JSON.parse(rawData);
925
+ } catch (_) {}
926
+ onEvent(currentEvent, parsed);
927
+ }
928
+ }
929
+ }
930
+
931
+ if (buffer.trim().startsWith('data: ')) {
932
+ const rawData = buffer.trim().slice(6);
933
+ let parsed = rawData;
934
+ try {
935
+ parsed = JSON.parse(rawData);
936
+ } catch (_) {}
937
+ onEvent('complete', parsed);
938
+ }
939
+ }
940
+
941
+ // Dialectic Debate Runner with Live Multi-Persona Streaming
966
942
  async function startDebate() {
967
943
  const input = document.getElementById('debate-query-input');
968
944
  const query = input.value.trim();
969
945
  if (!query) return;
970
946
 
971
- const depth = document.getElementById('debate-depth-select').value;
947
+ const depth = document.getElementById('debate-depth-select')?.value || 'deep';
948
+ const launchBtn = document.querySelector('#tab-dialectic .action-btn');
949
+ if (launchBtn) {
950
+ launchBtn.disabled = true;
951
+ launchBtn.textContent = 'Debating...';
952
+ }
953
+
954
+ const thesisEl = document.getElementById('dialectic-thesis');
955
+ const antithesisEl = document.getElementById('dialectic-antithesis');
956
+ const verificationEl = document.getElementById('dialectic-verification');
957
+ const synthesisEl = document.getElementById('dialectic-synthesis');
972
958
 
973
- document.getElementById('dialectic-thesis').textContent = 'Generating initial thesis & hypothesis...';
974
- document.getElementById('dialectic-antithesis').textContent = 'Awaiting thesis to challenge assumptions...';
975
- document.getElementById('dialectic-verification').textContent = 'Researcher standby for fact-checking...';
976
- document.getElementById('dialectic-synthesis').textContent = 'Synthesizer awaiting debate completion...';
959
+ thesisEl.innerHTML = '<div class="streaming-pulse">💡 The Proposer formulating thesis & core hypothesis...</div>';
960
+ antithesisEl.innerHTML = '<div class="placeholder-text">⏳ Awaiting thesis to challenge assumptions...</div>';
961
+ verificationEl.innerHTML = '<div class="placeholder-text">🔬 Researcher standby for empirical fact-checking...</div>';
962
+ synthesisEl.innerHTML = '<div class="placeholder-text">⚖️ Synthesizer awaiting debate completion...</div>';
963
+
964
+ let currentPersonaTokens = {
965
+ proposer: '',
966
+ adversary: '',
967
+ researcher: '',
968
+ judge: '',
969
+ };
977
970
 
978
971
  try {
979
972
  const res = await fetch('/api/debate', {
@@ -982,42 +975,87 @@ async function startDebate() {
982
975
  body: JSON.stringify({ query, depth }),
983
976
  });
984
977
 
985
- const reader = res.body.getReader();
986
- const decoder = new TextDecoder();
987
-
988
- while (true) {
989
- const { done, value } = await reader.read();
990
- if (done) break;
991
-
992
- const chunk = decoder.decode(value);
993
- const lines = chunk.split('\n');
994
-
995
- for (const line of lines) {
996
- if (line.startsWith('data: ')) {
997
- try {
998
- const data = JSON.parse(line.slice(6));
999
- if (data.thesis) document.getElementById('dialectic-thesis').textContent = data.thesis;
1000
- if (data.antithesis) document.getElementById('dialectic-antithesis').textContent = data.antithesis;
1001
- if (data.verification) document.getElementById('dialectic-verification').textContent = data.verification;
1002
- if (data.synthesis) document.getElementById('dialectic-synthesis').textContent = data.synthesis;
1003
- } catch (e) {}
978
+ await readSSEStream(res, (event, data) => {
979
+ if (event === 'status') {
980
+ if (data.stage === 'proposer') {
981
+ thesisEl.innerHTML = `<div class="streaming-pulse">💡 ${escapeHtml(data.message)}</div>`;
982
+ } else if (data.stage === 'adversary') {
983
+ antithesisEl.innerHTML = `<div class="streaming-pulse">⚔️ ${escapeHtml(data.message)}</div>`;
984
+ } else if (data.stage === 'researcher') {
985
+ verificationEl.innerHTML = `<div class="streaming-pulse">🔬 ${escapeHtml(data.message)}</div>`;
986
+ } else if (data.stage === 'judge') {
987
+ synthesisEl.innerHTML = `<div class="streaming-pulse">⚖️ ${escapeHtml(data.message)}</div>`;
988
+ }
989
+ } else if (event === 'token') {
990
+ const persona = data.persona || 'proposer';
991
+ currentPersonaTokens[persona] = (currentPersonaTokens[persona] || '') + (data.token || '');
992
+ if (persona === 'proposer') {
993
+ thesisEl.innerHTML = renderFormattedMarkdown(currentPersonaTokens.proposer);
994
+ } else if (persona === 'adversary') {
995
+ antithesisEl.innerHTML = renderFormattedMarkdown(currentPersonaTokens.adversary);
996
+ } else if (persona === 'researcher') {
997
+ verificationEl.innerHTML = renderFormattedMarkdown(currentPersonaTokens.researcher);
998
+ } else if (persona === 'judge') {
999
+ synthesisEl.innerHTML = renderFormattedMarkdown(currentPersonaTokens.judge);
1000
+ }
1001
+ } else if (event === 'stage') {
1002
+ if (data.persona === 'proposer') {
1003
+ thesisEl.innerHTML = renderFormattedMarkdown(data.content);
1004
+ } else if (data.persona === 'adversary') {
1005
+ antithesisEl.innerHTML = renderFormattedMarkdown(data.content);
1006
+ } else if (data.persona === 'researcher') {
1007
+ verificationEl.innerHTML = renderFormattedMarkdown(data.content);
1008
+ } else if (data.persona === 'judge') {
1009
+ synthesisEl.innerHTML = renderFormattedMarkdown(data.content);
1004
1010
  }
1011
+ } else if (event === 'complete') {
1012
+ if (typeof data === 'object') {
1013
+ if (data.thesis) thesisEl.innerHTML = renderFormattedMarkdown(data.thesis);
1014
+ if (data.antithesis) antithesisEl.innerHTML = renderFormattedMarkdown(data.antithesis);
1015
+ if (data.verification) {
1016
+ verificationEl.innerHTML = renderFormattedMarkdown(data.verification);
1017
+ } else if (depth === 'quick') {
1018
+ verificationEl.innerHTML = '<div class="placeholder-text">Empirical verification bypassed (Quick Depth).</div>';
1019
+ }
1020
+ if (data.synthesis) synthesisEl.innerHTML = renderFormattedMarkdown(data.synthesis);
1021
+ }
1022
+ showToast('Dialectic debate reached consensus!');
1023
+ loadArtifactsTab().catch(() => {});
1024
+ } else if (event === 'error') {
1025
+ synthesisEl.innerHTML = `<div style="color:#ef4444;">Debate Error: ${escapeHtml(data.message || data)}</div>`;
1005
1026
  }
1006
- }
1027
+ });
1007
1028
  } catch (err) {
1008
- document.getElementById('dialectic-synthesis').textContent = `Debate error: ${err.message}`;
1029
+ synthesisEl.innerHTML = `<div style="color:#ef4444;">Debate connection error: ${escapeHtml(err.message)}</div>`;
1030
+ } finally {
1031
+ if (launchBtn) {
1032
+ launchBtn.disabled = false;
1033
+ launchBtn.textContent = 'Launch Debate';
1034
+ }
1009
1035
  }
1010
1036
  }
1011
1037
 
1012
- // Goal Loop Runner
1038
+ // Goal Loop Runner with Live 3-Stage Streaming
1013
1039
  async function startGoalLoop() {
1014
1040
  const input = document.getElementById('goal-objective-input');
1015
1041
  const objective = input.value.trim();
1016
1042
  if (!objective) return;
1017
1043
 
1018
- document.getElementById('goal-stage-1-content').textContent = 'Stage 1 executing: Drafting initial plan and solution...';
1019
- document.getElementById('goal-stage-2-content').textContent = 'Stage 2 standby: Awaiting draft for adversarial critique...';
1020
- document.getElementById('goal-stage-3-content').textContent = 'Stage 3 standby: Awaiting synthesis for hardened output...';
1044
+ const launchBtn = document.querySelector('#tab-goal .action-btn');
1045
+ if (launchBtn) {
1046
+ launchBtn.disabled = true;
1047
+ launchBtn.textContent = 'Executing...';
1048
+ }
1049
+
1050
+ const stage1El = document.getElementById('goal-stage-1-content');
1051
+ const stage2El = document.getElementById('goal-stage-2-content');
1052
+ const stage3El = document.getElementById('goal-stage-3-content');
1053
+
1054
+ stage1El.innerHTML = '<div class="streaming-pulse">⚙️ Stage 1 executing: Drafting initial plan and solution...</div>';
1055
+ stage2El.innerHTML = '<div class="placeholder-text">⏳ Stage 2 standby: Awaiting draft for adversarial critique...</div>';
1056
+ stage3El.innerHTML = '<div class="placeholder-text">✨ Stage 3 standby: Awaiting synthesis for hardened output...</div>';
1057
+
1058
+ let currentIterTokens = { 1: '', 2: '', 3: '' };
1021
1059
 
1022
1060
  try {
1023
1061
  const res = await fetch('/api/goal', {
@@ -1026,29 +1064,54 @@ async function startGoalLoop() {
1026
1064
  body: JSON.stringify({ objective }),
1027
1065
  });
1028
1066
 
1029
- const reader = res.body.getReader();
1030
- const decoder = new TextDecoder();
1031
-
1032
- while (true) {
1033
- const { done, value } = await reader.read();
1034
- if (done) break;
1035
-
1036
- const chunk = decoder.decode(value);
1037
- const lines = chunk.split('\n');
1038
-
1039
- for (const line of lines) {
1040
- if (line.startsWith('data: ')) {
1041
- try {
1042
- const data = JSON.parse(line.slice(6));
1043
- if (data.draft) document.getElementById('goal-stage-1-content').textContent = data.draft;
1044
- if (data.critique) document.getElementById('goal-stage-2-content').textContent = data.critique;
1045
- if (data.finalOutput) document.getElementById('goal-stage-3-content').textContent = data.finalOutput;
1046
- } catch (e) {}
1067
+ await readSSEStream(res, (event, data) => {
1068
+ if (event === 'status') {
1069
+ if (data.iteration === 1) {
1070
+ stage1El.innerHTML = `<div class="streaming-pulse">⚙️ ${escapeHtml(data.message)}</div>`;
1071
+ } else if (data.iteration === 2) {
1072
+ stage2El.innerHTML = `<div class="streaming-pulse">🔍 ${escapeHtml(data.message)}</div>`;
1073
+ } else if (data.iteration === 3) {
1074
+ stage3El.innerHTML = `<div class="streaming-pulse">✨ ${escapeHtml(data.message)}</div>`;
1075
+ }
1076
+ } else if (event === 'token') {
1077
+ const iter = data.iteration || 1;
1078
+ currentIterTokens[iter] = (currentIterTokens[iter] || '') + (data.token || '');
1079
+ if (iter === 1) {
1080
+ stage1El.innerHTML = renderFormattedMarkdown(currentIterTokens[1]);
1081
+ } else if (iter === 2) {
1082
+ stage2El.innerHTML = renderFormattedMarkdown(currentIterTokens[2]);
1083
+ } else if (iter === 3) {
1084
+ stage3El.innerHTML = renderFormattedMarkdown(currentIterTokens[3]);
1047
1085
  }
1086
+ } else if (event === 'stage') {
1087
+ if (data.iteration === 1 || data.type === 'draft') {
1088
+ stage1El.innerHTML = renderFormattedMarkdown(data.content);
1089
+ } else if (data.iteration === 2 || data.type === 'review') {
1090
+ stage2El.innerHTML = renderFormattedMarkdown(data.content);
1091
+ } else if (data.iteration === 3 || data.type === 'refinement') {
1092
+ stage3El.innerHTML = renderFormattedMarkdown(data.content);
1093
+ }
1094
+ } else if (event === 'complete') {
1095
+ if (typeof data === 'object') {
1096
+ if (data.draft) stage1El.innerHTML = renderFormattedMarkdown(data.draft);
1097
+ if (data.critique) stage2El.innerHTML = renderFormattedMarkdown(data.critique);
1098
+ if (data.finalOutput) stage3El.innerHTML = renderFormattedMarkdown(data.finalOutput);
1099
+ } else if (typeof data === 'string') {
1100
+ stage3El.innerHTML = renderFormattedMarkdown(data);
1101
+ }
1102
+ showToast('Goal loop convergence reached!');
1103
+ loadArtifactsTab().catch(() => {});
1104
+ } else if (event === 'error') {
1105
+ stage3El.innerHTML = `<div style="color:#ef4444;">Goal Loop Error: ${escapeHtml(data.message || data)}</div>`;
1048
1106
  }
1049
- }
1107
+ });
1050
1108
  } catch (err) {
1051
- document.getElementById('goal-stage-3-content').textContent = `Goal execution error: ${err.message}`;
1109
+ stage3El.innerHTML = `<div style="color:#ef4444;">Goal execution error: ${escapeHtml(err.message)}</div>`;
1110
+ } finally {
1111
+ if (launchBtn) {
1112
+ launchBtn.disabled = false;
1113
+ launchBtn.textContent = 'Execute Goal Loop';
1114
+ }
1052
1115
  }
1053
1116
  }
1054
1117
 
@@ -15,7 +15,7 @@
15
15
  <header class="app-header">
16
16
  <div class="brand-zone">
17
17
  <span class="logo-mark">ANTRI</span>
18
- <span class="version-tag">v1.57.32</span>
18
+ <span class="version-tag">v1.57.36</span>
19
19
  </div>
20
20
 
21
21
  <!-- Mode Toggle -->
@@ -445,20 +445,7 @@
445
445
  </div>
446
446
  </section>
447
447
 
448
- <!-- TAB 7: Artifacts Hub -->
449
- <section id="tab-artifacts" class="tab-panel">
450
- <div class="panel-header">
451
- <div class="panel-title-group">
452
- <h2 class="panel-title">Generated Artifacts Hub</h2>
453
- <p class="panel-subtitle">Browse interactive HTML applications, stretching routines, and code architecture graphs grouped by chat session.</p>
454
- </div>
455
- <button class="action-btn" onclick="loadArtifactsTab()">⟳ Refresh Artifacts</button>
456
- </div>
457
448
 
458
- <div id="artifacts-grouped-container" class="artifacts-container">
459
- <!-- Populated dynamically via JS -->
460
- </div>
461
- </section>
462
449
 
463
450
  <!-- TAB 8: Suggestions & Ideation Studio -->
464
451
  <section id="tab-suggestions" class="tab-panel">
@@ -2159,6 +2159,118 @@ body.antri-app {
2159
2159
  flex-wrap: wrap;
2160
2160
  }
2161
2161
 
2162
+ /* Dialectic & Goal Output Formatting */
2163
+ .streaming-pulse {
2164
+ color: var(--primary);
2165
+ font-weight: 500;
2166
+ animation: pulse-glow 1.5s ease-in-out infinite alternate;
2167
+ }
2162
2168
 
2169
+ @keyframes pulse-glow {
2170
+ 0% { opacity: 0.6; }
2171
+ 100% { opacity: 1; }
2172
+ }
2163
2173
 
2174
+ .formatted-code-block {
2175
+ background: var(--bg-sidebar);
2176
+ border: 1px solid var(--border-main);
2177
+ border-radius: var(--radius-sm);
2178
+ margin: 0.75rem 0;
2179
+ overflow: hidden;
2180
+ }
2164
2181
 
2182
+ .code-block-header {
2183
+ background: rgba(0, 0, 0, 0.2);
2184
+ padding: 0.25rem 0.6rem;
2185
+ font-size: 0.72rem;
2186
+ font-family: var(--font-mono);
2187
+ color: var(--text-tertiary);
2188
+ border-bottom: 1px solid var(--border-main);
2189
+ text-transform: uppercase;
2190
+ font-weight: 600;
2191
+ }
2192
+
2193
+ .formatted-code-block pre {
2194
+ margin: 0;
2195
+ padding: 0.75rem;
2196
+ overflow-x: auto;
2197
+ }
2198
+
2199
+ .formatted-code-block code {
2200
+ font-family: var(--font-mono);
2201
+ font-size: 0.82rem;
2202
+ line-height: 1.5;
2203
+ color: var(--text-primary);
2204
+ white-space: pre;
2205
+ }
2206
+
2207
+ .inline-code {
2208
+ font-family: var(--font-mono);
2209
+ font-size: 0.82rem;
2210
+ background: var(--bg-sidebar);
2211
+ border: 1px solid var(--border-main);
2212
+ padding: 0.1rem 0.35rem;
2213
+ border-radius: 4px;
2214
+ color: var(--accent-primary, #6366f1);
2215
+ }
2216
+
2217
+ .formatted-h2 {
2218
+ font-size: 1.15rem;
2219
+ font-weight: 700;
2220
+ color: var(--text-primary);
2221
+ margin: 1rem 0 0.5rem 0;
2222
+ border-bottom: 1px solid var(--border-light);
2223
+ padding-bottom: 0.25rem;
2224
+ }
2225
+
2226
+ .formatted-h3 {
2227
+ font-size: 1.05rem;
2228
+ font-weight: 700;
2229
+ color: var(--text-primary);
2230
+ margin: 0.85rem 0 0.4rem 0;
2231
+ }
2232
+
2233
+ .formatted-h4 {
2234
+ font-size: 0.95rem;
2235
+ font-weight: 600;
2236
+ color: var(--text-primary);
2237
+ margin: 0.7rem 0 0.3rem 0;
2238
+ }
2239
+
2240
+ .formatted-h5 {
2241
+ font-size: 0.88rem;
2242
+ font-weight: 600;
2243
+ color: var(--text-secondary);
2244
+ margin: 0.5rem 0 0.25rem 0;
2245
+ }
2246
+
2247
+ .formatted-quote {
2248
+ border-left: 3px solid var(--primary);
2249
+ padding: 0.4rem 0.75rem;
2250
+ margin: 0.5rem 0;
2251
+ background: var(--bg-sidebar);
2252
+ border-radius: 0 var(--radius-xs) var(--radius-xs) 0;
2253
+ font-style: italic;
2254
+ color: var(--text-secondary);
2255
+ }
2256
+
2257
+ .bullet-item {
2258
+ margin: 0.25rem 0 0.25rem 0.5rem;
2259
+ color: var(--text-secondary);
2260
+ line-height: 1.6;
2261
+ }
2262
+
2263
+ .number-item {
2264
+ display: flex;
2265
+ align-items: flex-start;
2266
+ gap: 0.4rem;
2267
+ margin: 0.3rem 0;
2268
+ color: var(--text-secondary);
2269
+ line-height: 1.6;
2270
+ }
2271
+
2272
+ .num-badge {
2273
+ font-weight: 700;
2274
+ color: var(--primary);
2275
+ min-width: 1.2rem;
2276
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/desktop/server.ts"],"names":[],"mappings":"AAsCA,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,IAAI,CAA4C;IACxD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,kBAAkB,CAAiD;IAC3E,OAAO,CAAC,gBAAgB,CAAqD;;IAO7E,OAAO,CAAC,sBAAsB;IA2BjB,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAkGxB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAUpB,SAAS;WAuvBH,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAyBnD"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/desktop/server.ts"],"names":[],"mappings":"AAsCA,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,IAAI,CAA4C;IACxD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,kBAAkB,CAAiD;IAC3E,OAAO,CAAC,gBAAgB,CAAqD;;IAO7E,OAAO,CAAC,sBAAsB;IA2BjB,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAkGxB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAUpB,SAAS;WA+vBH,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAyBnD"}
@@ -513,7 +513,11 @@ export class DesktopServer {
513
513
  const engine = new DialecticEngine(configManager.get());
514
514
  try {
515
515
  sendEvent('start', { query, depth });
516
- const result = await engine.debate(query, depth);
516
+ const result = await engine.debate(query, depth, {
517
+ onStatus: (status) => sendEvent('status', status),
518
+ onStage: (stage) => sendEvent('stage', stage),
519
+ onToken: (persona, token) => sendEvent('token', { persona, token }),
520
+ });
517
521
  sendEvent('complete', result);
518
522
  res.end();
519
523
  }
@@ -537,7 +541,11 @@ export class DesktopServer {
537
541
  const engine = new GoalLoopEngine(configManager.get());
538
542
  try {
539
543
  sendEvent('start', { objective });
540
- const result = await engine.runGoal(objective);
544
+ const result = await engine.runGoal(objective, 3, {
545
+ onStatus: (status) => sendEvent('status', status),
546
+ onStage: (stage) => sendEvent('stage', stage),
547
+ onToken: (iteration, token) => sendEvent('token', { iteration, token }),
548
+ });
541
549
  sendEvent('complete', result);
542
550
  res.end();
543
551
  }