diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d53d47ac9..3a6699865 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,6 +12,7 @@ jobs: build_dev_docs: name: Build developer docs runs-on: ubuntu-latest + needs: build_instances_mockup steps: - name: Checkout repository uses: actions/checkout@v4 @@ -58,6 +59,12 @@ jobs: echo "πŸ”¨ Dev docs built and cached" fi + - name: Include instances mockup in developer docs + uses: actions/download-artifact@v4 + with: + name: instances-mockup + path: dev-docs/output/instances-mockup + - name: Upload developer docs uses: actions/upload-artifact@v4 with: @@ -168,6 +175,70 @@ jobs: name: frontend_docs path: packages/frontend/docs + build_instances_mockup: + name: Build instances mockup + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + # Need full history for `git log` for cache key + fetch-depth: 0 + + - name: Compute cache key + id: cache-key + run: | + hash=$(git log -1 --format="%H" -- packages/document-methods packages/catlog-wasm packages/document-types packages/ui-components tools/vite-plugin-monorepo-dedupe pnpm-lock.yaml pnpm-workspace.yaml) + echo "git-hash=${hash}" >> $GITHUB_OUTPUT + echo "Instances mockup hash: ${hash}" + + - name: Cache instances mockup build + id: cache-instances-mockup + uses: actions/cache@v4 + with: + path: packages/document-methods/demo/dist + key: instances-mockup-${{ steps.cache-key.outputs.git-hash }} + + - name: Setup pnpm + if: steps.cache-instances-mockup.outputs.cache-hit != 'true' + uses: pnpm/action-setup@v4 + + - name: Setup NodeJS + if: steps.cache-instances-mockup.outputs.cache-hit != 'true' + uses: actions/setup-node@v4 + with: + node-version: 24 + cache: "pnpm" + + - name: Install Rust toolchain from file + if: steps.cache-instances-mockup.outputs.cache-hit != 'true' + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + # Don't override flags in cargo config files. + rustflags: "" + + - name: Build instances mockup + if: steps.cache-instances-mockup.outputs.cache-hit != 'true' + run: | + pnpm install + pnpm --filter ./packages/document-methods run build:wasm + pnpm --filter ./packages/document-methods exec wasm-pack build ../catlog-wasm --target browser -d ./dist/pkg-browser --debug + pnpm --filter ./packages/document-methods run demo:build + + - name: Report cache status + run: | + if [ "${{ steps.cache-instances-mockup.outputs.cache-hit }}" = "true" ]; then + echo "βœ… Instances mockup restored from cache" + else + echo "πŸ”¨ Instances mockup built and cached" + fi + + - name: Upload instances mockup + uses: actions/upload-artifact@v4 + with: + name: instances-mockup + path: packages/document-methods/demo/dist + build_rust_docs: name: Build Rust docs runs-on: ubuntu-latest diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 89c28aef4..7408bddba 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -86,6 +86,7 @@ jobs: mv rust_docs site/dev/rust mv frontend_docs site/dev/frontend mv ui-components site/dev/ui-components + mv instances-mockup site/dev/instances-mockup mv math-docs site/math mv rfc site/rfc echo '/dev/rust /dev/rust/catlog' >> site/_redirects diff --git a/packages/document-methods/.agents/skills/catcolab-demo/SKILL.md b/packages/document-methods/.agents/skills/catcolab-demo/SKILL.md new file mode 100644 index 000000000..b959a7002 --- /dev/null +++ b/packages/document-methods/.agents/skills/catcolab-demo/SKILL.md @@ -0,0 +1,216 @@ +--- +name: catcolab-instances-demo-script +description: Drive the CatColab instances demo by running its script via the WebMCP `run_script` tool over Chrome DevTools. Use when you need to programmatically build or edit the demo's schema and instance (entities, mappings, attributes, and rows) in a running browser. +--- + +# CatColab instances demo: scripting via WebMCP + Chrome DevTools + +The instances demo (`pnpm demo` in `packages/document-methods`) exposes a single +WebMCP tool, `run_script`, on `document.modelContext`. It writes JavaScript into +the demo's script editor, opens the script pane, and **runs it**, returning the +script's return value (or thrown error). This skill covers driving that tool +through the Chrome DevTools MCP and what the script may contain. + +## Prerequisites + +- The demo dev server is running (default `http://localhost:5173/`). It is + usually already running; check first. +- A Chrome DevTools MCP connection to that page. + +The page installs the WebMCP polyfill at startup, so `document.modelContext` +exists app-wide and `run_script` is registered even when the script pane is +closed. + +## Using `run_script` over Chrome DevTools + +Chrome DevTools MCP has no direct WebMCP bridge, so call the tool through +`evaluate_script`, which runs in the page and can reach `document.modelContext`. + +1. Navigate to the demo (only if not already there): + + `navigate_page` -> `http://localhost:5173/` + +2. (Optional) List tools to confirm registration: + + ```js + () => + document.modelContext + .getTools() + .then((ts) => ts.map((t) => ({ name: t.name, inputSchema: t.inputSchema }))); + ``` + + Expect a `run_script` tool whose `inputSchema` (returned as a JSON string) + describes a single required `script` string property. + +3. Execute it. `executeTool` takes a tool descriptor from `getTools()` and a + **JSON string** of arguments, and returns a JSON string: + + ```js + async () => { + const mc = document.modelContext; + const tool = (await mc.getTools()).find((t) => t.name === "run_script"); + return mc.executeTool( + tool, + JSON.stringify({ + script: + `const p = schema.add(Entity, { label: "Person" });\n` + + `schema.add(Attr, { label: "name", from: p, to: attrTypes.String });\n`, + }), + ); + }; + ``` + + On success it returns + `{"content":[{"type":"text","text":"Script ran successfully."}]}` (with the + returned value appended, if the script returned one), and the script pane + opens with the source shown. If the script throws, the result is an error + with the message `Script threw: …`. + +4. Verify (optional). There are two `