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
103 changes: 103 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,106 @@ jobs:

- name: Test Tier 3
run: ./tools/test.sh --ci --tier 3

too-many-cooks-mcp:
name: Too Many Cooks MCP Server
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Dart
uses: dart-lang/setup-dart@v1
with:
sdk: ${{ vars.DART_VERSION }}

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: examples/too_many_cooks/package-lock.json

- name: Get tools/build dependencies
working-directory: tools/build
run: dart pub get

- name: Get MCP server dependencies
working-directory: examples/too_many_cooks
run: |
dart pub get
npm ci

- name: Compile MCP server
run: |
set -e
dart compile js -o examples/too_many_cooks/build/bin/server.js examples/too_many_cooks/bin/server.dart
dart run tools/build/add_preamble.dart \
examples/too_many_cooks/build/bin/server.js \
examples/too_many_cooks/build/bin/server_node.js \
--shebang

- name: Verify server exists
run: |
set -e
test -f examples/too_many_cooks/build/bin/server_node.js || (echo "Server build failed!" && exit 1)
echo "MCP server built successfully"

vscode-extension:
name: VSCode Extension Tests
runs-on: ubuntu-latest
needs: too-many-cooks-mcp
steps:
- uses: actions/checkout@v4

- name: Setup Dart
uses: dart-lang/setup-dart@v1
with:
sdk: ${{ vars.DART_VERSION }}

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: examples/too_many_cooks_vscode_extension/package-lock.json

- name: Get tools/build dependencies
working-directory: tools/build
run: dart pub get

- name: Build Too Many Cooks MCP server
run: |
set -e
cd examples/too_many_cooks
dart pub get
npm ci
dart compile js -o build/bin/server.js bin/server.dart
cd ../..
dart run tools/build/add_preamble.dart \
examples/too_many_cooks/build/bin/server.js \
examples/too_many_cooks/build/bin/server_node.js \
--shebang

- name: Get dart_node_vsix dependencies
working-directory: packages/dart_node_vsix
run: dart pub get

- name: Get extension dependencies (Dart)
working-directory: examples/too_many_cooks_vscode_extension
run: dart pub get

- name: Get extension dependencies (npm)
working-directory: examples/too_many_cooks_vscode_extension
run: npm ci

- name: Compile extension and tests
working-directory: examples/too_many_cooks_vscode_extension
run: |
set -e
npm run pretest

- name: Run VSCode extension tests
uses: coactions/setup-xvfb@v1
with:
run: npm test
working-directory: examples/too_many_cooks_vscode_extension
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ website/.dart-doc-temp/
examples/frontend/coverage/

*.mjs
!.vscode-test.mjs

examples/too_many_cooks_vscode_extension/.vscode-test/user-data/

Expand All @@ -49,8 +50,28 @@ examples/reflux_demo/flutter_counter/test/failures/


mutation-reports

out/


.vscode-test/
.playwright-mcp/

# dart_node_vsix build artifacts
packages/dart_node_vsix/out/
packages/dart_node_vsix/build/

website/playwright-report/

website/test-results/

# IntelliJ IDEA
.idea/
*.iml

# Dart metadata
.metadata

# Flutter web scaffolding (not needed for VSCode extension)
examples/too_many_cooks_vscode_extension/web/
examples/too_many_cooks_vscode_extension/lib/main.dart
26 changes: 10 additions & 16 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# CLAUDE.md

Dart packages for building Node.js apps. Typed Dart layer over JS interop.
Dart packages for building Node.js apps. Strongly Typed Dart layer over JS interop.

## Rules

⛔️ NEVER KILL (pkill) THE VSCODE PROCESS!!!
- Do not use Git unless asked by user

## Multi-Agent Coordination (Too Many Cooks)
- Keep your key! It's critical. Do not lose it!
- Check messages regularly, lock files before editing, unlock after
- Don't edit locked files; signal intent via plans and messages
- Coordinator: keep delegating via messages. Worker: keep asking for tasks via messages
- Clean up expired locks routinely
- Do not use Git unless asked by user

## Code Rules

**Language & Types**
- All Dart, minimal JS. Use `dart:js_interop` (not deprecated `dart:js_util`/`package:js`)
- Never expose `JSObject`/`JSAny`/`dynamic` in public APIs—always typed
- AVOID `JSObject`/`JSAny`/`dynamic`!
- Prefer typedef records over classes for data (structural typing)
- ILLEGAL: `as`, `late`, `!`, `.then()`, global state

Expand All @@ -23,11 +23,12 @@ Dart packages for building Node.js apps. Typed Dart layer over JS interop.
- Return `Result<T,E>` (nadz) instead of throwing exceptions
- Functions < 20 lines, files < 500 LOC
- Switch expressions/ternaries over if/else (except in declarative contexts)
- Where Typescript code exists with no Dart wrapper, create the Dart wrapper APIs and add to the appropriate packages.

**Testing**
- 100% coverage with high-level integration tests, not unit tests/mocks
- Tests in separate files, not groups. Dart only (JS only for interop testing)
- Never skip tests. Never remove assertions. Failing tests OK, silent failures ILLEGAL
- Never skip tests. Never remove assertions. Failing tests OK, silent failures = ⛔️ ILLEGAL. Aggressively unskip tests.
- NO PLACEHOLDERS—throw if incomplete

**Dependencies**
Expand Down Expand Up @@ -68,11 +69,4 @@ examples/
mobile/ # React Native example
too_many_cooks/ # Multi-agent coordination server
jsx_demo/ # JSX syntax demo
```

## Build & Test
```bash
dart run tools/build/build.dart # Build all
dart test # Run tests
dart analyze # Lint check
```
```
3 changes: 3 additions & 0 deletions cspell-dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -249,3 +249,6 @@ LTWH
blockquotes
Blockquotes
strikethrough
pkill
Preact
codeworkers
4 changes: 4 additions & 0 deletions examples/backend/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@

include: package:austerity/analysis_options.yaml

analyzer:
errors:
public_member_api_docs: ignore
13 changes: 12 additions & 1 deletion examples/bugs.md
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
- Most messages sit with the status of "Unread". I don't know if that's because the agents are not reading it, or the VSIX is not showing the correct status
- Most messages sit with the status of "Unread". I don't know if that's because the agents are not reading it, or the VSIX is not showing the correct status

- We need a button to clear all agents and history.

- Need to be able to multi select agents to delete many in one hit

- The agents are still losing their keys routinely. We need a solution to this

- The message button prompts the user to specify a username, but admin should automatically have the username HeadChef. Don't prompt for username

- Expired locks should be removed automatically. No need for anyone to remove them.

4 changes: 4 additions & 0 deletions examples/frontend/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@

include: package:austerity/analysis_options.yaml

analyzer:
errors:
public_member_api_docs: ignore
4 changes: 2 additions & 2 deletions examples/frontend/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ packages:
path: "../../packages/dart_node_core"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
dart_node_react:
dependency: "direct main"
description:
path: "../../packages/dart_node_react"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
file:
dependency: transitive
description:
Expand Down
4 changes: 2 additions & 2 deletions examples/jsx_demo/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ packages:
path: "../../packages/dart_node_core"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
dart_node_react:
dependency: "direct main"
description:
path: "../../packages/dart_node_react"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
file:
dependency: transitive
description:
Expand Down
4 changes: 2 additions & 2 deletions examples/markdown_editor/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ packages:
path: "../../packages/dart_node_core"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
dart_node_react:
dependency: "direct main"
description:
path: "../../packages/dart_node_react"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
file:
dependency: transitive
description:
Expand Down
6 changes: 3 additions & 3 deletions examples/mobile/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -95,21 +95,21 @@ packages:
path: "../../packages/dart_node_core"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
dart_node_react:
dependency: "direct main"
description:
path: "../../packages/dart_node_react"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
dart_node_react_native:
dependency: "direct main"
description:
path: "../../packages/dart_node_react_native"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
file:
dependency: transitive
description:
Expand Down
4 changes: 2 additions & 2 deletions examples/reflux_demo/counter_state/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ packages:
path: "../../../packages/dart_logging"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
file:
dependency: transitive
description:
Expand Down Expand Up @@ -230,7 +230,7 @@ packages:
path: "../../../packages/reflux"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
shelf:
dependency: transitive
description:
Expand Down
8 changes: 4 additions & 4 deletions examples/reflux_demo/web_counter/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -102,21 +102,21 @@ packages:
path: "../../../packages/dart_logging"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
dart_node_core:
dependency: transitive
description:
path: "../../../packages/dart_node_core"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
dart_node_react:
dependency: "direct main"
description:
path: "../../../packages/dart_node_react"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
file:
dependency: transitive
description:
Expand Down Expand Up @@ -251,7 +251,7 @@ packages:
path: "../../../packages/reflux"
relative: true
source: path
version: "0.9.0-beta"
version: "0.11.0-beta"
shelf:
dependency: transitive
description:
Expand Down
14 changes: 12 additions & 2 deletions examples/too_many_cooks/bin/server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
library;

import 'dart:async';
import 'dart:js_interop';

import 'package:dart_node_core/dart_node_core.dart';
import 'package:dart_node_mcp/dart_node_mcp.dart';
Expand All @@ -18,6 +19,11 @@ Future<void> main() async {
}
}

/// Keep the Node.js event loop alive using setInterval.
/// dart2js Completer.future doesn't keep the JS event loop running.
@JS('setInterval')
external void _setInterval(JSFunction callback, int delay);

Future<void> _startServer() async {
final serverResult = createTooManyCooksServer();

Expand All @@ -34,7 +40,11 @@ Future<void> _startServer() async {

await server.connect(transport);

// Keep the Dart event loop alive - stdio transport handles stdin listening
// in the JS layer, but dart2js needs pending async work to stay running.
// Keep the Node.js event loop alive - setInterval creates pending work
// that prevents the process from exiting. The stdio transport handles
// stdin listening in the JS layer.
_setInterval((() {}).toJS, 60000);

// Never resolve - server runs until killed
await Completer<void>().future;
}
Loading