Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ sdk/python/** linguist-generated
packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/** linguist-generated
# Built plugin web bundles (vite output, shipped in the wheel)
plugins/*/src/*/web/dist/** linguist-generated
# Rolled-up Studio plugin surface types (pnpm --filter @nemo/common types:plugin)
web/packages/common/plugin-types/** linguist-generated
# Generated Studio stylesheet
web/packages/studio/src/generated/** linguist-generated
# Generated license files
third_party/osv-licenses*.json linguist-generated
third_party/requirements*.txt linguist-generated
Expand Down
33 changes: 33 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1672,6 +1672,38 @@ jobs:
- name: Typecheck web packages against regenerated SDK
run: pnpm run --recursive --parallel --if-present typecheck

web-plugin-types:
name: Web plugin surface types check
needs: [changes]
if: >
!cancelled() && (
github.event_name == 'workflow_dispatch' ||
needs.changes.outputs.web-studio == 'true'
)
runs-on: ubuntu-latest
defaults:
run:
working-directory: web
shell: bash
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: .nvmrc
- name: Install pnpm via corepack
run: npm i -g corepack@0.31.0 && corepack enable pnpm
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Regenerate the plugin surface types
run: pnpm --filter @nemo/common types:plugin
# Out-of-tree plugins vendor this file, so a stale copy types them against
# a surface that no longer exists — and still compiles, which is the whole
# problem. Fail the change that moved the surface, not the plugin later.
- name: Check the committed artifact is up to date
run: git diff --exit-code -- packages/common/plugin-types

web-studio-deps:
name: Web studio deps check
needs: [changes]
Expand Down Expand Up @@ -2042,6 +2074,7 @@ jobs:
- web-format
- web-lint
- web-sdk-gen
- web-plugin-types
- web-studio-deps
- web-studio-e2e
- opa-policy-test
Expand Down
19 changes: 19 additions & 0 deletions plugins/example-plugin/web/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,25 @@ import { AssistantChat, StudioDataView, useStudioDataViewState } from '@nemo/com
- **Types come from source**, via `paths` in `tsconfig.json`; `@nemo/common` is
unpublished, so there is nothing to install. `src/env.d.ts` declares the `*.css`
side-effect imports those sources carry.
- **Out-of-tree plugins vendor a generated `.d.ts` instead.** A plugin living in
its own repository can't use `paths` into these sources — resolving them needs
this workspace's `node_modules`, including the unpublished `@nemo/sdk`. The
whole surface is rolled up into `packages/common/plugin-types/plugin.d.ts`,
which is committed here; a plugin repo copies that file in and points its
`paths` at it. Whatever the rolled-up file still imports, the consumer has to
resolve — check the `import` lines at the top of it rather than assuming this
list is current. Published packages (`class-variance-authority`,
`@assistant-ui/react` once the chat surface lands) are plain type-only
devDependencies. Only `@nemo/sdk/generated/platform/schema` needs a local stub,
because it is unpublished; it contributes `PlatformJobLog` and
`PlatformJobStatus`, reached solely through `LogViewer` and the job-status
constants, so a dozen structural lines cover it.
- **Regenerate with `pnpm --filter @nemo/common types:plugin` when you change
`plugin.ts`.** The `web-plugin-types` CI job regenerates and fails on a diff,
so the artifact can't drift from the surface it describes. It can still drift
from a plugin's *copy* — nothing in this repo knows about those — and a stale
copy compiles happily against a surface that no longer exists, so refresh it
deliberately when the surface moves.
- **CSS is already loaded.** The vendor build stubs stylesheet imports because
Studio bundles the same files through its own graph. A plugin adds no CSS.
- **`useStudioDataViewState` syncs to URL search params** on Studio's shared
Expand Down
3 changes: 3 additions & 0 deletions web/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ packages/**/playwright-report/

# Ignore generated style
packages/studio/src/generated/*

# Rolled-up plugin surface types; formatting it breaks the CI drift check
packages/common/plugin-types/
1 change: 1 addition & 0 deletions web/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ const ignores = [
`${pathPrefix}packages/studio/test-results`,
`${pathPrefix}packages/studio/.test-reports`,
`${pathPrefix}packages/sdk/generated/**`,
`${pathPrefix}packages/common/plugin-types/**`,
`${pathPrefix}packages/storybook/public/mockServiceWorker.js`,
`${pathPrefix}demo-notebook/**`,
];
Expand Down
3 changes: 3 additions & 0 deletions web/packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"test:ci": "vitest run --coverage",
"test:watch": "vitest watch",
"test:once": "vitest --run",
"types:plugin": "tsx scripts/build-plugin-types.ts",
"typecheck": "tsc --noEmit"
},
"peerDependencies": {
Expand Down Expand Up @@ -57,6 +58,8 @@
"p-limit": "catalog:",
"react-dropzone": "catalog:",
"react-hook-form": "catalog:",
"rolldown": "^1.2.2",
"rolldown-plugin-dts": "^0.28.2",
"tsx": "catalog:",
"typescript": "catalog:",
"vite": "catalog:",
Expand Down
Loading
Loading