MCPcopy Create free account
hub / github.com/microsoft/data-formulator / buildOtherThreads

Function buildOtherThreads

src/app/useFormulateData.ts:163–219  ·  view source on GitHub ↗

* Build peripheral thread summaries — leaf tables in the workspace that * are NOT part of the focused chain. Mirrors the data agent's Tier 3 * context (`SimpleChartRecBox.exploreFromChat`): all leaves except the * focused one, with per-step `display → chart_type (encodings)` lines

(currentTable: DictTable)

Source from the content-addressed store, hash-verified

161 * using resolved field names.
162 */
163 function buildOtherThreads(currentTable: DictTable): any[] {
164 // Collect all table IDs in the focused thread
165 const focusedIds = new Set<string>();
166 if (currentTable.derive && !currentTable.anchored) {
167 const triggers = getTriggers(currentTable, tables);
168 for (const t of triggers) {
169 focusedIds.add(t.resultTableId);
170 }
171 }
172 focusedIds.add(currentTable.id);
173
174 // Find every leaf table (no children, or all children anchored) that
175 // is derived from somewhere and NOT part of the focused chain.
176 const otherThreads: any[] = [];
177 for (const table of tables) {
178 if (focusedIds.has(table.id)) continue;
179 if (!table.derive) continue;
180 const children = tables.filter(c => c.derive?.trigger?.tableId === table.id);
181 const isLeaf = children.length === 0 || children.every(c => c.anchored);
182 if (!isLeaf) continue;
183
184 const triggers = getTriggers(table, tables);
185 if (triggers.length === 0) continue;
186
187 const STEP_FINDING_CHAR_LIMIT = 200;
188 const steps = triggers.map(trigger => {
189 const instr = trigger.interaction?.find(e => e.role === 'instruction');
190 const label = instr?.displayContent || instr?.content || trigger.resultTableId;
191 // Use the actual rendered chart, not the trigger's "Auto" stub.
192 const chart = resolveChartForTable(trigger.resultTableId);
193 const chartType = chart?.chartType && chart.chartType !== 'Auto' ? chart.chartType : '';
194 const encStr = Object.entries(chartEncodingsByName(chart))
195 .map(([k, v]) => `${k}: ${v}`)
196 .join(', ');
197 // Per-step agent commentary: the `summary` entry the visualize
198 // action emits after running this step.
199 let finding = trigger.interaction?.find(
200 e => e.role === 'summary',
201 )?.content?.trim() || '';
202 if (finding.length > STEP_FINDING_CHAR_LIMIT) {
203 finding = finding.slice(0, STEP_FINDING_CHAR_LIMIT - 1).trimEnd() + '…';
204 }
205 const head = `${label}${chartType ? ` → ${chartType}` : ''}${encStr ? ` (${encStr})` : ''}`;
206 return finding ? `${head} — finding: ${finding}` : head;
207 });
208
209 const sourceTableId = triggers[0].tableId;
210 const sourceTable = tables.find(t => t.id === sourceTableId);
211 otherThreads.push({
212 source_table: sourceTable?.virtual?.tableId || sourceTableId,
213 leaf_table: table.virtual?.tableId || table.id,
214 step_count: triggers.length,
215 steps,
216 });
217 }
218 return otherThreads;
219 }
220

Callers 1

streamIdeasFunction · 0.85

Calls 4

getTriggersFunction · 0.90
resolveChartForTableFunction · 0.85
chartEncodingsByNameFunction · 0.85
filterMethod · 0.80

Tested by

no test coverage detected