@webmcp-auto-ui/agent 2.5.28 → 2.5.29
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.
- package/package.json +1 -1
- package/src/autoui-server.ts +8 -23
- package/src/loop.ts +8 -5
- package/src/providers/hawk-models.ts +11 -10
- package/src/providers/wasm.ts +7 -5
- package/src/recipes/_generated.ts +22 -76
- package/src/recipes/hackathon-assemblee-nationale.md +4 -10
- package/src/recipes/notebook-playbook.md +18 -66
- package/src/tool-layers.ts +26 -4
- package/src/trace-observer.ts +4 -15
package/package.json
CHANGED
package/src/autoui-server.ts
CHANGED
|
@@ -5,22 +5,13 @@
|
|
|
5
5
|
import { createWebMcpServer, parseFrontmatter } from '@webmcp-auto-ui/core';
|
|
6
6
|
import { RAW_RECIPES } from './recipes/_generated.js';
|
|
7
7
|
|
|
8
|
-
// Notebook widget
|
|
8
|
+
// Notebook widget recipe (vanilla renderer) — moved to @webmcp-auto-ui/ui
|
|
9
9
|
// @ts-ignore — Vite raw imports, not resolved by tsc
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
import
|
|
13
|
-
// @ts-ignore
|
|
14
|
-
import documentRecipe from '@webmcp-auto-ui/ui/widgets/notebook/recipes/document.md?raw';
|
|
15
|
-
// @ts-ignore
|
|
16
|
-
import editorialRecipe from '@webmcp-auto-ui/ui/widgets/notebook/recipes/editorial.md?raw';
|
|
17
|
-
|
|
18
|
-
// Notebook widget renderers (vanilla JS) — import via subpath to avoid pulling
|
|
10
|
+
import notebookRecipe from '@webmcp-auto-ui/ui/widgets/notebook/recipes/notebook.md?raw';
|
|
11
|
+
|
|
12
|
+
// Notebook widget renderer (vanilla JS) — import via subpath to avoid pulling
|
|
19
13
|
// the .svelte exports of the ui package root through tsc.
|
|
20
|
-
import { render as
|
|
21
|
-
import { render as renderWorkspace } from '@webmcp-auto-ui/ui/widgets/notebook/workspace.js';
|
|
22
|
-
import { render as renderDocument } from '@webmcp-auto-ui/ui/widgets/notebook/document.js';
|
|
23
|
-
import { render as renderEditorial } from '@webmcp-auto-ui/ui/widgets/notebook/editorial.js';
|
|
14
|
+
import { render as renderNotebook } from '@webmcp-auto-ui/ui/widgets/notebook/notebook.js';
|
|
24
15
|
import { render as renderRecipeBrowser } from '@webmcp-auto-ui/ui/widgets/notebook/recipe-browser.js';
|
|
25
16
|
|
|
26
17
|
// Inline recipe for recipe-browser (real vanilla widget)
|
|
@@ -987,10 +978,7 @@ Call widget_display({name: "js-sandbox", params: {code: "document.getElementById
|
|
|
987
978
|
|
|
988
979
|
/** Derived from RECIPES + notebook widget recipes — always in sync with registered widgets */
|
|
989
980
|
const _NOTEBOOK_RECIPE_SOURCES: string[] = [
|
|
990
|
-
|
|
991
|
-
workspaceRecipe as string,
|
|
992
|
-
documentRecipe as string,
|
|
993
|
-
editorialRecipe as string,
|
|
981
|
+
notebookRecipe as string,
|
|
994
982
|
recipeBrowserRecipe,
|
|
995
983
|
];
|
|
996
984
|
export const NATIVE_WIDGET_NAMES = [...RECIPES, ..._NOTEBOOK_RECIPE_SOURCES].map(r => {
|
|
@@ -1011,12 +999,9 @@ for (const recipe of RECIPES) {
|
|
|
1011
999
|
autoui.registerWidget(recipe, undefined);
|
|
1012
1000
|
}
|
|
1013
1001
|
|
|
1014
|
-
// Notebook
|
|
1002
|
+
// Notebook widget — vanilla renderer (resolved via WidgetRenderer vanilla path)
|
|
1015
1003
|
const NOTEBOOK_WIDGETS: Array<[string, (container: HTMLElement, data: any) => any]> = [
|
|
1016
|
-
[
|
|
1017
|
-
[workspaceRecipe as string, renderWorkspace],
|
|
1018
|
-
[documentRecipe as string, renderDocument],
|
|
1019
|
-
[editorialRecipe as string, renderEditorial],
|
|
1004
|
+
[notebookRecipe as string, renderNotebook],
|
|
1020
1005
|
[recipeBrowserRecipe, renderRecipeBrowser],
|
|
1021
1006
|
];
|
|
1022
1007
|
for (const [recipe, renderer] of NOTEBOOK_WIDGETS) {
|
package/src/loop.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
LLMProvider, ProviderTool, McpToolDef, AgentCallbacks,
|
|
10
10
|
} from './types.js';
|
|
11
11
|
import type { ToolLayer, SchemaTransformOptions } from './tool-layers.js';
|
|
12
|
-
import { buildToolsFromLayers, buildDiscoveryToolsWithAliases, activateServerTools, toProviderTools, sanitizeServerName
|
|
12
|
+
import { buildToolsFromLayers, buildDiscoveryToolsWithAliases, activateServerTools, toProviderTools, sanitizeServerName } from './tool-layers.js';
|
|
13
13
|
import { buildSystemPromptWithAliases, buildSystemPrompt } from './prompts/index.js';
|
|
14
14
|
import type { DiscoveryCache } from './discovery-cache.js';
|
|
15
15
|
import { unflattenParams, validateJsonSchema } from '@webmcp-auto-ui/core';
|
|
@@ -168,9 +168,9 @@ export async function runAgentLoop(
|
|
|
168
168
|
// Use local alias maps (parallel-safe — no global singleton)
|
|
169
169
|
const activatedServers = new Set<string>();
|
|
170
170
|
const localAliasMap = new Map<string, string>();
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
const localPathMaps = new Map<string, Record<string, string[]>>(
|
|
171
|
+
// Local pathMaps for flattened schemas — populated as servers are lazily activated
|
|
172
|
+
// (see activateServerTools call below). Parallel-safe: scoped to this loop run.
|
|
173
|
+
const localPathMaps = new Map<string, Record<string, string[]>>();
|
|
174
174
|
const trace = new PipelineTrace();
|
|
175
175
|
|
|
176
176
|
const disc = buildDiscoveryToolsWithAliases(options.layers ?? [], schemaOptions, trace);
|
|
@@ -398,7 +398,10 @@ export async function runAgentLoop(
|
|
|
398
398
|
activatedServers.add(serverKey);
|
|
399
399
|
const layer = (options.layers ?? []).find(l => sanitizeServerName(l.serverName) === serverName && l.protocol === protocol);
|
|
400
400
|
if (layer) {
|
|
401
|
-
|
|
401
|
+
const act = activateServerTools(activeTools, layer, schemaOptions, trace);
|
|
402
|
+
activeTools = act.tools;
|
|
403
|
+
// Merge new pathMaps so unflattenParams works for lazily-activated tools.
|
|
404
|
+
for (const [k, v] of act.pathMaps) localPathMaps.set(k, v);
|
|
402
405
|
}
|
|
403
406
|
}
|
|
404
407
|
}
|
|
@@ -5,16 +5,17 @@ export interface HawkModelEntry {
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
export const HAWK_MODELS: HawkModelEntry[] = [
|
|
8
|
-
{ id: 'qwen35-2b',
|
|
9
|
-
{ id: 'bielik-1.5b-v3',
|
|
10
|
-
{ id: 'gemma4-e2b',
|
|
11
|
-
{ id: '
|
|
12
|
-
{ id: '
|
|
13
|
-
{ id: '
|
|
14
|
-
{ id: '
|
|
15
|
-
{ id: '
|
|
16
|
-
{ id: '
|
|
17
|
-
{ id: '
|
|
8
|
+
{ id: 'qwen35-2b', label: 'Qwen 3.5 2B — 49 tok/s', tokps: 49 },
|
|
9
|
+
{ id: 'bielik-1.5b-v3', label: 'Bielik 1.5B — 47 tok/s', tokps: 47 },
|
|
10
|
+
{ id: 'gemma4-e2b', label: 'Gemma 4 E2B — 43 tok/s', tokps: 43 },
|
|
11
|
+
{ id: 'deepseek-coder-16b', label: 'DeepSeek Coder 16B — 41 tok/s', tokps: 41 },
|
|
12
|
+
{ id: 'ministral3-3b', label: 'Ministral 3B — 35 tok/s', tokps: 35 },
|
|
13
|
+
{ id: 'qwen3-4b', label: 'Qwen 3 4B — 28 tok/s', tokps: 28 },
|
|
14
|
+
{ id: 'gemma4-e4b', label: 'Gemma 4 E4B — 26 tok/s', tokps: 26 },
|
|
15
|
+
{ id: 'qwen35-4b', label: 'Qwen 3.5 4B — 23 tok/s', tokps: 23 },
|
|
16
|
+
{ id: 'qwen36-35b-a3b', label: 'Qwen 3.6 35B MoE — 22 tok/s', tokps: 22 },
|
|
17
|
+
{ id: 'gemma4-26b-a4b', label: 'Gemma 4 26B MoE — 20 tok/s', tokps: 20 },
|
|
18
|
+
{ id: 'ministral-8b', label: 'Ministral 8B — 16 tok/s', tokps: 16 },
|
|
18
19
|
];
|
|
19
20
|
|
|
20
21
|
export function listHawkModels(): HawkModelEntry[] {
|
package/src/providers/wasm.ts
CHANGED
|
@@ -313,11 +313,13 @@ export class WasmProvider implements LLMProvider {
|
|
|
313
313
|
}
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
// Strip hallucinated framework tokens the model should never emit on its own
|
|
317
|
-
//
|
|
318
|
-
//
|
|
319
|
-
//
|
|
320
|
-
// - <|
|
|
316
|
+
// Strip hallucinated framework tokens the model should never emit on its own.
|
|
317
|
+
// Thinking mode is disabled for Gemma (since commit 164a24d) but the model
|
|
318
|
+
// may still leak these tokens as pretraining artefacts — keep the defensive
|
|
319
|
+
// strip regardless of activation.
|
|
320
|
+
// - <|tool_response>...<tool_response|> (framework-injected, never generated)
|
|
321
|
+
// - <|channel>thought...<channel|> (ghost thought channels)
|
|
322
|
+
// - <|think|> (stray pretraining artefacts)
|
|
321
323
|
fullText = fullText
|
|
322
324
|
.replace(/<\|tool_response>[\s\S]*?<tool_response\|>/g, '')
|
|
323
325
|
.replace(/<\|channel>thought[\s\S]*?<channel\|>/g, '')
|
|
@@ -932,7 +932,7 @@ component("gallery", {
|
|
|
932
932
|
'hackathon-assemblee-nationale': `---
|
|
933
933
|
id: hackathon-assemblee-nationale-mcp-webmcp
|
|
934
934
|
name: Hackathon Assemblée Nationale · MCP & WebMCP starter
|
|
935
|
-
components_used: [notebook
|
|
935
|
+
components_used: [notebook]
|
|
936
936
|
when: the user mentions the Assemblée Nationale hackathon, wants to experiment with parliamentary data (Tricoteuses, Legifrance), or asks for a starter notebook to explore deputies, votes, amendments, or legislative texts in a hackathon context. Keywords include "hackathon Assemblée Nationale", "MCP WebMCP hackathon", "tricoteuses playbook", "parlement playground", "hackathon parlementaire".
|
|
937
937
|
servers: [autoui, tricoteuses]
|
|
938
938
|
layout:
|
|
@@ -951,14 +951,9 @@ This recipe is a **specialization** of the generic \`notebook-playbook\` recipe
|
|
|
951
951
|
|
|
952
952
|
## How to use
|
|
953
953
|
|
|
954
|
-
### Step 1 —
|
|
954
|
+
### Step 1 — Use the \`notebook\` widget
|
|
955
955
|
|
|
956
|
-
|
|
957
|
-
- Participants expect to collaborate and leave traces for each other (avatars, comments)
|
|
958
|
-
- The document layout reads naturally as "hackathon brief + starter code" rather than "dev tool"
|
|
959
|
-
- Margin comments can be seeded to hint at directions to explore
|
|
960
|
-
|
|
961
|
-
If the participant asks for a minimal dev-focused playground instead, fall back to \`notebook-compact\`.
|
|
956
|
+
The single \`notebook\` widget fits the hackathon brief: prose, SQL and JS share one drag-and-droppable flow, suited both to a "brief + starter code" read and to free exploration.
|
|
962
957
|
|
|
963
958
|
### Step 2 — Seed the cells
|
|
964
959
|
|
|
@@ -974,7 +969,7 @@ The notebook should contain 5–7 cells covering:
|
|
|
974
969
|
Example template (to be refined with actual hackathon organizers' briefs):
|
|
975
970
|
|
|
976
971
|
\`\`\`
|
|
977
|
-
widget_display({name: "notebook
|
|
972
|
+
widget_display({name: "notebook", params: {
|
|
978
973
|
title: "Hackathon Assemblée Nationale · starter",
|
|
979
974
|
cells: [
|
|
980
975
|
{
|
|
@@ -1039,7 +1034,6 @@ These recipes produce more specialized layouts than a generic notebook, and are
|
|
|
1039
1034
|
- **Forgetting the hackathon framing**: without the "bienvenue" and "à vous" markdown cells, participants land on a bare notebook and lose the playbook feeling.
|
|
1040
1035
|
- **SQL without LIMIT**: Tricoteuses queries without \`LIMIT\` can return thousands of rows and slow down the first impression.
|
|
1041
1036
|
- **Inventing data**: do not seed with fake French parliamentary content (fake deputies, fake votes). If the actual data is not known at seed time, use generic queries (\`SELECT * FROM scrutins LIMIT 5\`) and let the user discover from there.
|
|
1042
|
-
- **Picking the wrong layout**: if the user is solo and wants to code fast, \`notebook-compact\` is better than \`notebook-document\`. Default to document for hackathon context because of the collaborative framing, not as a hard rule.
|
|
1043
1037
|
`,
|
|
1044
1038
|
'hummingbird-data': `---
|
|
1045
1039
|
id: hummingbird-data
|
|
@@ -1133,8 +1127,8 @@ Do NOT render any widget.
|
|
|
1133
1127
|
'notebook-playbook': `---
|
|
1134
1128
|
id: create-interactive-notebook-playbook
|
|
1135
1129
|
name: Create an interactive notebook playbook
|
|
1136
|
-
components_used: [notebook
|
|
1137
|
-
when: the user wants to experiment with data, prototype a small analysis, share a reusable scenario, or prepare a hackathon-ready playground. Keywords include "playground", "playbook", "experiment", "try", "prototype", "hackathon", "share a notebook", "template", "starter", "publish".
|
|
1130
|
+
components_used: [notebook]
|
|
1131
|
+
when: the user wants to experiment with data, prototype a small analysis, share a reusable scenario, or prepare a hackathon-ready playground. Keywords include "playground", "playbook", "experiment", "try", "prototype", "hackathon", "share a notebook", "template", "starter", "publish", "memo", "report".
|
|
1138
1132
|
servers: [autoui]
|
|
1139
1133
|
layout:
|
|
1140
1134
|
type: single
|
|
@@ -1154,32 +1148,23 @@ This recipe applies across domains (parliamentary data, biodiversity, news, busi
|
|
|
1154
1148
|
|
|
1155
1149
|
## How to use
|
|
1156
1150
|
|
|
1157
|
-
### Step 1 —
|
|
1158
|
-
|
|
1159
|
-
Choose one of the four \`notebook-*\` widgets based on the user's implicit intent:
|
|
1151
|
+
### Step 1 — Use the \`notebook\` widget
|
|
1160
1152
|
|
|
1161
|
-
|
|
1162
|
-
|---|---|
|
|
1163
|
-
| \`notebook-compact\` | Quick data exploration, reactive dataflow with named outputs, minimal chrome. **Default for most "playground" and "hackathon" requests.** |
|
|
1164
|
-
| \`notebook-workspace\` | The user expects a multi-cell analyst workspace with sources, cell navigation, \`run all\`, and a \`publish\` step. Use when they mention "dashboard", "app", "workspace", "publish". |
|
|
1165
|
-
| \`notebook-document\` | The user plans to share and discuss with a team. Use when "collaborate", "review", "comment", "reply" appear. |
|
|
1166
|
-
| \`notebook-editorial\` | The user wants a polished, article-like final deliverable mixing prose and code. Use for "memo", "report", "writeup", "blog-style". |
|
|
1167
|
-
|
|
1168
|
-
When in doubt, pick \`notebook-compact\`.
|
|
1153
|
+
There is a single notebook widget. Prose paragraphs (\`md\`), SQL queries (\`sql\`) and JS code (\`js\`) share one ordered flow, all drag-and-droppable together. Publication-ready serif prose, suitable for playgrounds, memos, collaborative reviews and analyst workspaces alike.
|
|
1169
1154
|
|
|
1170
1155
|
### Step 2 — Pre-fill the cells with context-aware seeds
|
|
1171
1156
|
|
|
1172
1157
|
Never create an empty notebook. Always seed with 3–5 cells that give the user an immediate starting point:
|
|
1173
1158
|
|
|
1174
1159
|
1. **First cell: markdown** — title + one-sentence context of what the notebook is for
|
|
1175
|
-
2. **Second cell:
|
|
1176
|
-
3. **Third cell: code** — a transformation or a visualization that uses the output of step 2. Use \`varname\` on the SQL cell (\`varname: "rows"\`) and reference it in the JS cell
|
|
1160
|
+
2. **Second cell: sql or md** — if an MCP data source is connected, a starter query that returns something visible (e.g. \`SELECT * FROM {table} LIMIT 10\`). Otherwise a markdown cell describing the next step
|
|
1161
|
+
3. **Third cell: code** — a transformation or a visualization that uses the output of step 2. Use \`varname\` on the SQL cell (\`varname: "rows"\`) and reference it in the JS cell to activate the reactive dataflow
|
|
1177
1162
|
4. **Last cell: markdown** — a short "to you to play" note inviting the user to add cells or edit
|
|
1178
1163
|
|
|
1179
1164
|
Example seed for a generic data playground:
|
|
1180
1165
|
|
|
1181
1166
|
\`\`\`
|
|
1182
|
-
widget_display({name: "notebook
|
|
1167
|
+
widget_display({name: "notebook", params: {
|
|
1183
1168
|
title: "Exploration playground",
|
|
1184
1169
|
cells: [
|
|
1185
1170
|
{type: "md", content: "### Exploration playground\\n\\nStart by running the first SQL cell, then iterate."},
|
|
@@ -1203,7 +1188,7 @@ SQL cells are dispatched automatically to the server's \`*_query_sql\` tool (fir
|
|
|
1203
1188
|
|
|
1204
1189
|
### Step 4 — Exporting & publishing
|
|
1205
1190
|
|
|
1206
|
-
|
|
1191
|
+
The toolbar \`share\` button offers **four export formats**:
|
|
1207
1192
|
|
|
1208
1193
|
| Format | What it does |
|
|
1209
1194
|
|---|---|
|
|
@@ -1212,27 +1197,23 @@ All four notebook layouts share the same \`share\` button in the toolbar, offeri
|
|
|
1212
1197
|
| **PNG** | Snapshots the rendered notebook to an image. |
|
|
1213
1198
|
| **JSON** | Exports the full widget state — re-importable for programmatic reuse. |
|
|
1214
1199
|
|
|
1215
|
-
**Layout-specific share affordances:**
|
|
1216
|
-
- \`notebook-workspace\` has a dedicated \`publish\` button (primary, accent-coloured) that flips \`mode: 'view'\`, tags the notebook \`published\` (from \`draft\`), and copies the Hyperskill link in one gesture. Use this when the user wants a clean hand-off.
|
|
1217
|
-
- \`notebook-document\` shows a single \`share\` link (live invite/collaboration is not available in this build; presence avatars only render when the \`presence\` param is explicitly provided).
|
|
1218
|
-
|
|
1219
1200
|
### Step 5 — Working with connected data servers
|
|
1220
1201
|
|
|
1221
|
-
When one or more MCP data servers are connected,
|
|
1202
|
+
When one or more MCP data servers are connected, the notebook exposes a **collapsible left pane** (bookmark-bar styling, collapsed by default) that lists:
|
|
1222
1203
|
- **Recipes** published by each server (\`{server}_list_recipes()\`)
|
|
1223
1204
|
- **Tools / tables** exposed by each server (\`{server}_list_tools()\`)
|
|
1224
1205
|
|
|
1225
|
-
Clicking any recipe opens a viewer modal. Each fenced code block inside the recipe has a \`↳ inject\` button that drops the snippet into the notebook as a new cell
|
|
1206
|
+
Clicking any recipe opens a viewer modal. Each fenced code block inside the recipe has a \`↳ inject\` button that drops the snippet into the notebook as a new cell.
|
|
1226
1207
|
|
|
1227
|
-
Two toolbar buttons flank the left pane
|
|
1208
|
+
Two toolbar buttons flank the left pane:
|
|
1228
1209
|
- **\`+ md\`** — 3-tab modal (New / File / URL) to create a markdown cell from scratch, from a local \`.md\` file, or from a URL
|
|
1229
1210
|
- **\`+ recipe\`** — 3-tab modal (Browser / File / URL) to import a recipe from a connected server, a local \`.recipe.md\` file, or a URL
|
|
1230
1211
|
|
|
1231
|
-
Pass the server metadata via the \`servers:\` param
|
|
1212
|
+
Pass the server metadata via the \`servers:\` param:
|
|
1232
1213
|
|
|
1233
1214
|
\`\`\`ts
|
|
1234
1215
|
widget_display({
|
|
1235
|
-
name: 'notebook
|
|
1216
|
+
name: 'notebook',
|
|
1236
1217
|
params: {
|
|
1237
1218
|
title: '...',
|
|
1238
1219
|
cells: [...],
|
|
@@ -1241,26 +1222,21 @@ widget_display({
|
|
|
1241
1222
|
})
|
|
1242
1223
|
\`\`\`
|
|
1243
1224
|
|
|
1244
|
-
**Filter rule**: only MCP *data* servers (\`kind: 'data'\`) belong in \`servers:\`. Do NOT include WebMCP UI servers such as \`autoui
|
|
1225
|
+
**Filter rule**: only MCP *data* servers (\`kind: 'data'\`) belong in \`servers:\`. Do NOT include WebMCP UI servers such as \`autoui\`.
|
|
1245
1226
|
|
|
1246
1227
|
### Step 6 — Hand-off guidance
|
|
1247
1228
|
|
|
1248
1229
|
After creating the notebook, mention to the user that they can:
|
|
1249
1230
|
- **Share in four formats** via the toolbar \`share\` button (Hyperskill / Markdown / PNG / JSON)
|
|
1250
1231
|
- **Switch to \`view\` mode** (read-only) when presenting
|
|
1251
|
-
- Use **\`run all\`** (workspace) or **\`publish\`** (workspace) for one-shot execution and publication
|
|
1252
|
-
- **Reply** to margin comments in a document layout (\`+ reply\` under each comment)
|
|
1253
1232
|
- Access the \`⟲ history\` panel to see the edit trace and restore deleted cells
|
|
1254
1233
|
- **Import recipes** from connected MCP servers via the left pane or the \`+ recipe\` modal
|
|
1255
1234
|
|
|
1256
|
-
For hackathon contexts, prefer seeding a \`notebook-document\` layout so participants can leave margin comments and replies on cells (presence stays opt-in — pass a \`presence\` array only if you have real editors to show).
|
|
1257
|
-
|
|
1258
1235
|
## Examples
|
|
1259
1236
|
|
|
1260
1237
|
### Generic CSV / table playground
|
|
1261
1238
|
\`\`\`
|
|
1262
|
-
|
|
1263
|
-
widget_display({name: "notebook-compact", params: {
|
|
1239
|
+
widget_display({name: "notebook", params: {
|
|
1264
1240
|
title: "CSV playground",
|
|
1265
1241
|
cells: [
|
|
1266
1242
|
{type: "md", content: "### CSV playground\\n\\nRun the SQL cell to see the first rows, then iterate."},
|
|
@@ -1270,37 +1246,9 @@ widget_display({name: "notebook-compact", params: {
|
|
|
1270
1246
|
}})
|
|
1271
1247
|
\`\`\`
|
|
1272
1248
|
|
|
1273
|
-
### Publishable analyst workspace
|
|
1274
|
-
\`\`\`
|
|
1275
|
-
// user: "Set up an analysis I can publish to the team as an app"
|
|
1276
|
-
widget_display({name: "notebook-workspace", params: {
|
|
1277
|
-
title: "Sales review",
|
|
1278
|
-
cells: [
|
|
1279
|
-
{type: "md", name: "intro", content: "What this analysis covers."},
|
|
1280
|
-
{type: "sql", name: "fetch_sales", content: "select * from sales limit 100"},
|
|
1281
|
-
{type: "js", name: "plot", content: "// chart the rows"}
|
|
1282
|
-
]
|
|
1283
|
-
}})
|
|
1284
|
-
// Then tell the user: click \`run all\` to execute, then \`publish\` to flip to view mode and copy the Hyperskill link.
|
|
1285
|
-
\`\`\`
|
|
1286
|
-
|
|
1287
|
-
### Collaborative analysis with comments
|
|
1288
|
-
\`\`\`
|
|
1289
|
-
// user: "Set up a notebook my team can edit and comment on"
|
|
1290
|
-
widget_display({name: "notebook-document", params: {
|
|
1291
|
-
title: "Team analysis",
|
|
1292
|
-
cells: [
|
|
1293
|
-
{type: "md", content: "Kick-off: describe the question here."},
|
|
1294
|
-
{type: "sql", content: "select * from source limit 10", comment: {who: "reviewer", when: "2m", body: "Should we filter to last quarter only?"}},
|
|
1295
|
-
{type: "md", content: "Your findings: add thoughts, <mark>highlights</mark>, and reply to the comment on the query above."}
|
|
1296
|
-
]
|
|
1297
|
-
}})
|
|
1298
|
-
\`\`\`
|
|
1299
|
-
|
|
1300
1249
|
### Final memo
|
|
1301
1250
|
\`\`\`
|
|
1302
|
-
|
|
1303
|
-
widget_display({name: "notebook-editorial", params: {
|
|
1251
|
+
widget_display({name: "notebook", params: {
|
|
1304
1252
|
title: "Findings memo",
|
|
1305
1253
|
kicker: "memo",
|
|
1306
1254
|
cells: [
|
|
@@ -1317,12 +1265,10 @@ widget_display({name: "notebook-editorial", params: {
|
|
|
1317
1265
|
## Common mistakes
|
|
1318
1266
|
|
|
1319
1267
|
- **Empty notebook**: never call \`widget_display\` without at least 3 seed cells. The user expects something they can immediately run.
|
|
1320
|
-
- **Wrong layout for the intent**: do not use \`notebook-editorial\` for quick exploration — it signals "finished article" and intimidates. Use \`notebook-compact\` unless the user explicitly asks for a publication feel.
|
|
1321
1268
|
- **Heavy initial queries**: always \`LIMIT 10\` or \`LIMIT 20\` in seed SQL cells. Users will expand later if needed.
|
|
1322
|
-
- **Missing \`varname\` on SQL cells
|
|
1269
|
+
- **Missing \`varname\` on SQL cells**: the named output drives the reactive dataflow (downstream JS cells go stale when their upstream re-runs). Without it, the notebook loses half its story.
|
|
1323
1270
|
- **Inventing UUIDs**: leave \`id\` unset — the widget generates a sensible default. Only pass \`id\` when restoring an existing notebook.
|
|
1324
|
-
- **
|
|
1325
|
-
- **Including \`autoui\` in \`servers:\`**: only MCP *data* servers (\`kind: 'data'\`) belong there. UI servers like \`autoui\` would pollute the left pane.
|
|
1271
|
+
- **Including \`autoui\` in \`servers:\`**: only MCP *data* servers (\`kind: 'data'\`) belong there.
|
|
1326
1272
|
`,
|
|
1327
1273
|
'parlementaire-profile': `---
|
|
1328
1274
|
id: display-parliamentary-profile-with-hemicycle-and-votes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
id: hackathon-assemblee-nationale-mcp-webmcp
|
|
3
3
|
name: Hackathon Assemblée Nationale · MCP & WebMCP starter
|
|
4
|
-
components_used: [notebook
|
|
4
|
+
components_used: [notebook]
|
|
5
5
|
when: the user mentions the Assemblée Nationale hackathon, wants to experiment with parliamentary data (Tricoteuses, Legifrance), or asks for a starter notebook to explore deputies, votes, amendments, or legislative texts in a hackathon context. Keywords include "hackathon Assemblée Nationale", "MCP WebMCP hackathon", "tricoteuses playbook", "parlement playground", "hackathon parlementaire".
|
|
6
6
|
servers: [autoui, tricoteuses]
|
|
7
7
|
layout:
|
|
@@ -20,14 +20,9 @@ This recipe is a **specialization** of the generic `notebook-playbook` recipe
|
|
|
20
20
|
|
|
21
21
|
## How to use
|
|
22
22
|
|
|
23
|
-
### Step 1 —
|
|
23
|
+
### Step 1 — Use the `notebook` widget
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
- Participants expect to collaborate and leave traces for each other (avatars, comments)
|
|
27
|
-
- The document layout reads naturally as "hackathon brief + starter code" rather than "dev tool"
|
|
28
|
-
- Margin comments can be seeded to hint at directions to explore
|
|
29
|
-
|
|
30
|
-
If the participant asks for a minimal dev-focused playground instead, fall back to `notebook-compact`.
|
|
25
|
+
The single `notebook` widget fits the hackathon brief: prose, SQL and JS share one drag-and-droppable flow, suited both to a "brief + starter code" read and to free exploration.
|
|
31
26
|
|
|
32
27
|
### Step 2 — Seed the cells
|
|
33
28
|
|
|
@@ -43,7 +38,7 @@ The notebook should contain 5–7 cells covering:
|
|
|
43
38
|
Example template (to be refined with actual hackathon organizers' briefs):
|
|
44
39
|
|
|
45
40
|
```
|
|
46
|
-
widget_display({name: "notebook
|
|
41
|
+
widget_display({name: "notebook", params: {
|
|
47
42
|
title: "Hackathon Assemblée Nationale · starter",
|
|
48
43
|
cells: [
|
|
49
44
|
{
|
|
@@ -108,4 +103,3 @@ These recipes produce more specialized layouts than a generic notebook, and are
|
|
|
108
103
|
- **Forgetting the hackathon framing**: without the "bienvenue" and "à vous" markdown cells, participants land on a bare notebook and lose the playbook feeling.
|
|
109
104
|
- **SQL without LIMIT**: Tricoteuses queries without `LIMIT` can return thousands of rows and slow down the first impression.
|
|
110
105
|
- **Inventing data**: do not seed with fake French parliamentary content (fake deputies, fake votes). If the actual data is not known at seed time, use generic queries (`SELECT * FROM scrutins LIMIT 5`) and let the user discover from there.
|
|
111
|
-
- **Picking the wrong layout**: if the user is solo and wants to code fast, `notebook-compact` is better than `notebook-document`. Default to document for hackathon context because of the collaborative framing, not as a hard rule.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
id: create-interactive-notebook-playbook
|
|
3
3
|
name: Create an interactive notebook playbook
|
|
4
|
-
components_used: [notebook
|
|
5
|
-
when: the user wants to experiment with data, prototype a small analysis, share a reusable scenario, or prepare a hackathon-ready playground. Keywords include "playground", "playbook", "experiment", "try", "prototype", "hackathon", "share a notebook", "template", "starter", "publish".
|
|
4
|
+
components_used: [notebook]
|
|
5
|
+
when: the user wants to experiment with data, prototype a small analysis, share a reusable scenario, or prepare a hackathon-ready playground. Keywords include "playground", "playbook", "experiment", "try", "prototype", "hackathon", "share a notebook", "template", "starter", "publish", "memo", "report".
|
|
6
6
|
servers: [autoui]
|
|
7
7
|
layout:
|
|
8
8
|
type: single
|
|
@@ -22,32 +22,23 @@ This recipe applies across domains (parliamentary data, biodiversity, news, busi
|
|
|
22
22
|
|
|
23
23
|
## How to use
|
|
24
24
|
|
|
25
|
-
### Step 1 —
|
|
25
|
+
### Step 1 — Use the `notebook` widget
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
| Layout | Use when |
|
|
30
|
-
|---|---|
|
|
31
|
-
| `notebook-compact` | Quick data exploration, reactive dataflow with named outputs, minimal chrome. **Default for most "playground" and "hackathon" requests.** |
|
|
32
|
-
| `notebook-workspace` | The user expects a multi-cell analyst workspace with sources, cell navigation, `run all`, and a `publish` step. Use when they mention "dashboard", "app", "workspace", "publish". |
|
|
33
|
-
| `notebook-document` | The user plans to share and discuss with a team. Use when "collaborate", "review", "comment", "reply" appear. |
|
|
34
|
-
| `notebook-editorial` | The user wants a polished, article-like final deliverable mixing prose and code. Use for "memo", "report", "writeup", "blog-style". |
|
|
35
|
-
|
|
36
|
-
When in doubt, pick `notebook-compact`.
|
|
27
|
+
There is a single notebook widget. Prose paragraphs (`md`), SQL queries (`sql`) and JS code (`js`) share one ordered flow, all drag-and-droppable together. Publication-ready serif prose, suitable for playgrounds, memos, collaborative reviews and analyst workspaces alike.
|
|
37
28
|
|
|
38
29
|
### Step 2 — Pre-fill the cells with context-aware seeds
|
|
39
30
|
|
|
40
31
|
Never create an empty notebook. Always seed with 3–5 cells that give the user an immediate starting point:
|
|
41
32
|
|
|
42
33
|
1. **First cell: markdown** — title + one-sentence context of what the notebook is for
|
|
43
|
-
2. **Second cell:
|
|
44
|
-
3. **Third cell: code** — a transformation or a visualization that uses the output of step 2. Use `varname` on the SQL cell (`varname: "rows"`) and reference it in the JS cell
|
|
34
|
+
2. **Second cell: sql or md** — if an MCP data source is connected, a starter query that returns something visible (e.g. `SELECT * FROM {table} LIMIT 10`). Otherwise a markdown cell describing the next step
|
|
35
|
+
3. **Third cell: code** — a transformation or a visualization that uses the output of step 2. Use `varname` on the SQL cell (`varname: "rows"`) and reference it in the JS cell to activate the reactive dataflow
|
|
45
36
|
4. **Last cell: markdown** — a short "to you to play" note inviting the user to add cells or edit
|
|
46
37
|
|
|
47
38
|
Example seed for a generic data playground:
|
|
48
39
|
|
|
49
40
|
```
|
|
50
|
-
widget_display({name: "notebook
|
|
41
|
+
widget_display({name: "notebook", params: {
|
|
51
42
|
title: "Exploration playground",
|
|
52
43
|
cells: [
|
|
53
44
|
{type: "md", content: "### Exploration playground\n\nStart by running the first SQL cell, then iterate."},
|
|
@@ -71,7 +62,7 @@ SQL cells are dispatched automatically to the server's `*_query_sql` tool (first
|
|
|
71
62
|
|
|
72
63
|
### Step 4 — Exporting & publishing
|
|
73
64
|
|
|
74
|
-
|
|
65
|
+
The toolbar `share` button offers **four export formats**:
|
|
75
66
|
|
|
76
67
|
| Format | What it does |
|
|
77
68
|
|---|---|
|
|
@@ -80,27 +71,23 @@ All four notebook layouts share the same `share` button in the toolbar, offering
|
|
|
80
71
|
| **PNG** | Snapshots the rendered notebook to an image. |
|
|
81
72
|
| **JSON** | Exports the full widget state — re-importable for programmatic reuse. |
|
|
82
73
|
|
|
83
|
-
**Layout-specific share affordances:**
|
|
84
|
-
- `notebook-workspace` has a dedicated `publish` button (primary, accent-coloured) that flips `mode: 'view'`, tags the notebook `published` (from `draft`), and copies the Hyperskill link in one gesture. Use this when the user wants a clean hand-off.
|
|
85
|
-
- `notebook-document` shows a single `share` link (live invite/collaboration is not available in this build; presence avatars only render when the `presence` param is explicitly provided).
|
|
86
|
-
|
|
87
74
|
### Step 5 — Working with connected data servers
|
|
88
75
|
|
|
89
|
-
When one or more MCP data servers are connected,
|
|
76
|
+
When one or more MCP data servers are connected, the notebook exposes a **collapsible left pane** (bookmark-bar styling, collapsed by default) that lists:
|
|
90
77
|
- **Recipes** published by each server (`{server}_list_recipes()`)
|
|
91
78
|
- **Tools / tables** exposed by each server (`{server}_list_tools()`)
|
|
92
79
|
|
|
93
|
-
Clicking any recipe opens a viewer modal. Each fenced code block inside the recipe has a `↳ inject` button that drops the snippet into the notebook as a new cell
|
|
80
|
+
Clicking any recipe opens a viewer modal. Each fenced code block inside the recipe has a `↳ inject` button that drops the snippet into the notebook as a new cell.
|
|
94
81
|
|
|
95
|
-
Two toolbar buttons flank the left pane
|
|
82
|
+
Two toolbar buttons flank the left pane:
|
|
96
83
|
- **`+ md`** — 3-tab modal (New / File / URL) to create a markdown cell from scratch, from a local `.md` file, or from a URL
|
|
97
84
|
- **`+ recipe`** — 3-tab modal (Browser / File / URL) to import a recipe from a connected server, a local `.recipe.md` file, or a URL
|
|
98
85
|
|
|
99
|
-
Pass the server metadata via the `servers:` param
|
|
86
|
+
Pass the server metadata via the `servers:` param:
|
|
100
87
|
|
|
101
88
|
```ts
|
|
102
89
|
widget_display({
|
|
103
|
-
name: 'notebook
|
|
90
|
+
name: 'notebook',
|
|
104
91
|
params: {
|
|
105
92
|
title: '...',
|
|
106
93
|
cells: [...],
|
|
@@ -109,26 +96,21 @@ widget_display({
|
|
|
109
96
|
})
|
|
110
97
|
```
|
|
111
98
|
|
|
112
|
-
**Filter rule**: only MCP *data* servers (`kind: 'data'`) belong in `servers:`. Do NOT include WebMCP UI servers such as `autoui
|
|
99
|
+
**Filter rule**: only MCP *data* servers (`kind: 'data'`) belong in `servers:`. Do NOT include WebMCP UI servers such as `autoui`.
|
|
113
100
|
|
|
114
101
|
### Step 6 — Hand-off guidance
|
|
115
102
|
|
|
116
103
|
After creating the notebook, mention to the user that they can:
|
|
117
104
|
- **Share in four formats** via the toolbar `share` button (Hyperskill / Markdown / PNG / JSON)
|
|
118
105
|
- **Switch to `view` mode** (read-only) when presenting
|
|
119
|
-
- Use **`run all`** (workspace) or **`publish`** (workspace) for one-shot execution and publication
|
|
120
|
-
- **Reply** to margin comments in a document layout (`+ reply` under each comment)
|
|
121
106
|
- Access the `⟲ history` panel to see the edit trace and restore deleted cells
|
|
122
107
|
- **Import recipes** from connected MCP servers via the left pane or the `+ recipe` modal
|
|
123
108
|
|
|
124
|
-
For hackathon contexts, prefer seeding a `notebook-document` layout so participants can leave margin comments and replies on cells (presence stays opt-in — pass a `presence` array only if you have real editors to show).
|
|
125
|
-
|
|
126
109
|
## Examples
|
|
127
110
|
|
|
128
111
|
### Generic CSV / table playground
|
|
129
112
|
```
|
|
130
|
-
|
|
131
|
-
widget_display({name: "notebook-compact", params: {
|
|
113
|
+
widget_display({name: "notebook", params: {
|
|
132
114
|
title: "CSV playground",
|
|
133
115
|
cells: [
|
|
134
116
|
{type: "md", content: "### CSV playground\n\nRun the SQL cell to see the first rows, then iterate."},
|
|
@@ -138,37 +120,9 @@ widget_display({name: "notebook-compact", params: {
|
|
|
138
120
|
}})
|
|
139
121
|
```
|
|
140
122
|
|
|
141
|
-
### Publishable analyst workspace
|
|
142
|
-
```
|
|
143
|
-
// user: "Set up an analysis I can publish to the team as an app"
|
|
144
|
-
widget_display({name: "notebook-workspace", params: {
|
|
145
|
-
title: "Sales review",
|
|
146
|
-
cells: [
|
|
147
|
-
{type: "md", name: "intro", content: "What this analysis covers."},
|
|
148
|
-
{type: "sql", name: "fetch_sales", content: "select * from sales limit 100"},
|
|
149
|
-
{type: "js", name: "plot", content: "// chart the rows"}
|
|
150
|
-
]
|
|
151
|
-
}})
|
|
152
|
-
// Then tell the user: click `run all` to execute, then `publish` to flip to view mode and copy the Hyperskill link.
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
### Collaborative analysis with comments
|
|
156
|
-
```
|
|
157
|
-
// user: "Set up a notebook my team can edit and comment on"
|
|
158
|
-
widget_display({name: "notebook-document", params: {
|
|
159
|
-
title: "Team analysis",
|
|
160
|
-
cells: [
|
|
161
|
-
{type: "md", content: "Kick-off: describe the question here."},
|
|
162
|
-
{type: "sql", content: "select * from source limit 10", comment: {who: "reviewer", when: "2m", body: "Should we filter to last quarter only?"}},
|
|
163
|
-
{type: "md", content: "Your findings: add thoughts, <mark>highlights</mark>, and reply to the comment on the query above."}
|
|
164
|
-
]
|
|
165
|
-
}})
|
|
166
|
-
```
|
|
167
|
-
|
|
168
123
|
### Final memo
|
|
169
124
|
```
|
|
170
|
-
|
|
171
|
-
widget_display({name: "notebook-editorial", params: {
|
|
125
|
+
widget_display({name: "notebook", params: {
|
|
172
126
|
title: "Findings memo",
|
|
173
127
|
kicker: "memo",
|
|
174
128
|
cells: [
|
|
@@ -185,9 +139,7 @@ widget_display({name: "notebook-editorial", params: {
|
|
|
185
139
|
## Common mistakes
|
|
186
140
|
|
|
187
141
|
- **Empty notebook**: never call `widget_display` without at least 3 seed cells. The user expects something they can immediately run.
|
|
188
|
-
- **Wrong layout for the intent**: do not use `notebook-editorial` for quick exploration — it signals "finished article" and intimidates. Use `notebook-compact` unless the user explicitly asks for a publication feel.
|
|
189
142
|
- **Heavy initial queries**: always `LIMIT 10` or `LIMIT 20` in seed SQL cells. Users will expand later if needed.
|
|
190
|
-
- **Missing `varname` on SQL cells
|
|
143
|
+
- **Missing `varname` on SQL cells**: the named output drives the reactive dataflow (downstream JS cells go stale when their upstream re-runs). Without it, the notebook loses half its story.
|
|
191
144
|
- **Inventing UUIDs**: leave `id` unset — the widget generates a sensible default. Only pass `id` when restoring an existing notebook.
|
|
192
|
-
- **
|
|
193
|
-
- **Including `autoui` in `servers:`**: only MCP *data* servers (`kind: 'data'`) belong there. UI servers like `autoui` would pollute the left pane.
|
|
145
|
+
- **Including `autoui` in `servers:`**: only MCP *data* servers (`kind: 'data'`) belong there.
|
package/src/tool-layers.ts
CHANGED
|
@@ -456,19 +456,31 @@ export function buildDiscoveryTools(layers: ToolLayer[]): ProviderTool[] {
|
|
|
456
456
|
return tools;
|
|
457
457
|
}
|
|
458
458
|
|
|
459
|
+
/** Result of activateServerTools — extended tool set + per-call path maps for newly activated tools */
|
|
460
|
+
export interface ActivateServerToolsResult {
|
|
461
|
+
tools: ProviderTool[];
|
|
462
|
+
/** Path maps for flattened schemas of newly added tools (empty if flatten is off). */
|
|
463
|
+
pathMaps: Map<string, Record<string, string[]>>;
|
|
464
|
+
}
|
|
465
|
+
|
|
459
466
|
/**
|
|
460
467
|
* Add all tools from a specific server layer to the active tool set.
|
|
461
468
|
* Called when a server is "touched" for the first time.
|
|
469
|
+
*
|
|
470
|
+
* Returns `{ tools, pathMaps }` — `pathMaps` is non-empty when `schemaOptions.flatten`
|
|
471
|
+
* is on, and must be merged into the loop-local pathMaps so `unflattenParams` works
|
|
472
|
+
* for lazily-activated tools. Backward-compat: if you only need `tools`, read `.tools`.
|
|
462
473
|
*/
|
|
463
474
|
export function activateServerTools(
|
|
464
475
|
currentTools: ProviderTool[],
|
|
465
476
|
layer: ToolLayer,
|
|
466
477
|
schemaOptions?: SchemaTransformOptions,
|
|
467
478
|
trace?: PipelineTrace,
|
|
468
|
-
):
|
|
479
|
+
): ActivateServerToolsResult {
|
|
469
480
|
const prefix = `${sanitizeServerName(layer.serverName)}_${protocolToken(layer.protocol)}_`;
|
|
470
481
|
const existing = new Set(currentTools.map(t => t.name));
|
|
471
482
|
const newTools = [...currentTools];
|
|
483
|
+
const pathMaps = new Map<string, Record<string, string[]>>();
|
|
472
484
|
|
|
473
485
|
const layerTools = layer.protocol === 'mcp'
|
|
474
486
|
? toProviderTools(layer.tools, schemaOptions, trace)
|
|
@@ -476,12 +488,22 @@ export function activateServerTools(
|
|
|
476
488
|
|
|
477
489
|
for (const tool of layerTools) {
|
|
478
490
|
const prefixed = `${prefix}${tool.name}`;
|
|
479
|
-
if (
|
|
480
|
-
|
|
491
|
+
if (existing.has(prefixed)) continue;
|
|
492
|
+
|
|
493
|
+
let finalTool = { ...tool, name: prefixed };
|
|
494
|
+
|
|
495
|
+
if (schemaOptions?.flatten) {
|
|
496
|
+
const { schema: flatSchema, pathMap } = flattenSchema(finalTool.input_schema as import('@webmcp-auto-ui/core').JsonSchema);
|
|
497
|
+
if (Object.keys(pathMap).length > 0) {
|
|
498
|
+
finalTool.input_schema = flatSchema as Record<string, unknown>;
|
|
499
|
+
pathMaps.set(prefixed, pathMap);
|
|
500
|
+
}
|
|
481
501
|
}
|
|
502
|
+
|
|
503
|
+
newTools.push(finalTool);
|
|
482
504
|
}
|
|
483
505
|
|
|
484
|
-
return newTools;
|
|
506
|
+
return { tools: newTools, pathMaps };
|
|
485
507
|
}
|
|
486
508
|
|
|
487
509
|
/**
|
package/src/trace-observer.ts
CHANGED
|
@@ -374,9 +374,7 @@ export function createTraceObserver(ctx: TraceObserverContext): TraceObserver {
|
|
|
374
374
|
|
|
375
375
|
function flush(): void {
|
|
376
376
|
if (ids === null) return;
|
|
377
|
-
ctx.updateWidget(ids.dagId, buildCytoscapeData());
|
|
378
377
|
ctx.updateWidget(ids.treeId, buildTreeData());
|
|
379
|
-
ctx.updateWidget(ids.sankeyId, buildSankeyData());
|
|
380
378
|
}
|
|
381
379
|
|
|
382
380
|
const callbacks: Partial<AgentCallbacks> = {
|
|
@@ -602,11 +600,11 @@ export function createTraceObserver(ctx: TraceObserverContext): TraceObserver {
|
|
|
602
600
|
callbacks,
|
|
603
601
|
mount(): { dagId: string; treeId: string; sankeyId: string } | null {
|
|
604
602
|
if (ids !== null) return ids;
|
|
605
|
-
const dag = ctx.addWidget('animated-flow', buildCytoscapeData(), 'cytoscape');
|
|
606
603
|
const tree = ctx.addWidget('tree', buildTreeData(), 'd3');
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
604
|
+
if (!tree) return null;
|
|
605
|
+
// dagId/sankeyId kept as empty strings for shape compatibility — the
|
|
606
|
+
// cytoscape + sankey sub-widgets were removed in favor of the tree only.
|
|
607
|
+
ids = { dagId: '', treeId: tree.id, sankeyId: '' };
|
|
610
608
|
// Synchronous immediate flush — guarantees widgets reflect full buffer
|
|
611
609
|
// when trace is toggled mid-run (retroactive within current session).
|
|
612
610
|
flush();
|
|
@@ -633,19 +631,10 @@ export function createTraceObserver(ctx: TraceObserverContext): TraceObserver {
|
|
|
633
631
|
flushTimer = null;
|
|
634
632
|
}
|
|
635
633
|
if (ids !== null) {
|
|
636
|
-
ctx.updateWidget(ids.dagId, {
|
|
637
|
-
elements: [],
|
|
638
|
-
style: CYTOSCAPE_STYLE,
|
|
639
|
-
layout: { name: 'cose', animate: true },
|
|
640
|
-
});
|
|
641
634
|
ctx.updateWidget(ids.treeId, {
|
|
642
635
|
root: { name: 'conv', children: [] },
|
|
643
636
|
orientation: 'horizontal',
|
|
644
637
|
});
|
|
645
|
-
ctx.updateWidget(ids.sankeyId, {
|
|
646
|
-
nodes: [],
|
|
647
|
-
links: [],
|
|
648
|
-
});
|
|
649
638
|
}
|
|
650
639
|
},
|
|
651
640
|
detach(): void {
|