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
35 changes: 9 additions & 26 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ jobs:
cache: true

- name: Check formatting
run: deno fmt --check
run: deno task fmt:check

- name: Run linter
run: deno lint
run: deno task lint

- name: Type check
run: deno check packages/*/mod.ts packages/*/src/*.ts
run: deno task check

test:
name: Tests
Expand All @@ -43,10 +43,7 @@ jobs:
cache: true

- name: Run tests
run: deno test --allow-env --allow-net --allow-read --coverage=cov/

- name: Generate coverage report
run: deno coverage --lcov cov/ > cov.lcov
run: deno task test:coverage

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
Expand All @@ -72,11 +69,6 @@ jobs:
cd packages/lib
timeout 10s deno run --allow-net --allow-env examples/echo-agent.ts --help || [ $? -eq 124 ]

- name: Test simple echo example
run: |
cd packages/lib
timeout 10s deno run --allow-net --allow-env examples/simple-echo.ts --help || [ $? -eq 124 ]

package-check:
name: Package Validation
runs-on: ubuntu-latest
Expand Down Expand Up @@ -145,7 +137,7 @@ jobs:
- name: Performance test
run: |
# Simple timing test
time deno test --allow-env --allow-net --allow-read packages/lib/src/execution-context.test.ts
time deno task test:unit

publish-check:
name: Publish Check
Expand All @@ -161,15 +153,8 @@ jobs:
deno-version: v2.x
cache: true

- name: Dry run publish schema package
run: |
cd packages/schema
deno publish --dry-run --allow-slow-types

- name: Dry run publish lib package
run: |
cd packages/lib
deno publish --dry-run --allow-slow-types
- name: Dry run publish all packages
run: deno task publish:dry-run

integration:
name: Integration
Expand All @@ -185,9 +170,7 @@ jobs:
cache: true

- name: Run integration tests
run: |
# Run only integration tests
deno test --allow-env --allow-net --allow-read packages/lib/test/
run: deno task test:integration

- name: Test cross-package imports
run: |
Expand Down Expand Up @@ -221,7 +204,7 @@ jobs:
cache: true

- name: Run core tests
run: deno test --allow-env --allow-net --allow-read packages/lib/src/
run: deno task test:unit

notify:
name: Notify
Expand Down
51 changes: 31 additions & 20 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ Runt is a TypeScript/Deno library for building runtime agents that connect to
Anode notebooks. It uses LiveStore for event-sourcing and real-time sync between
multiple users.

**Current Status**: Working system with 72 passing tests. Core functionality is
implemented. Main areas needing work are better error handling and more robust
connection management.
**Current Status**: Working system with 29 passing tests. Core functionality is
implemented and published to JSR. The system is a working prototype with Python
execution via Pyodide, real-time collaboration, and executable installation
support.

## Architecture

Expand All @@ -38,14 +39,14 @@ connection management.
- Direct Python code execution with IPython rich formatting
- HTML rendering, pandas tables, matplotlib SVG plots
- Real-time interrupt support via SharedArrayBuffer
- JSR publishing for all packages
- JSR publishing for all packages with executable installation
- Global executable installation as `pyrunt`

## What Needs Work

- Error handling is basic
- Test coverage is good but could expand edge cases
- LiveStore complex types require `--allow-slow-types` for publishing
- Pyodide package loading can be slow on first run
- Available Python packages are constrained by Pyodide ecosystem
- Publishing requires `--allow-slow-types` flag due to LiveStore's complex types

## Development Workflow

Expand All @@ -59,10 +60,12 @@ deno task dev # run example echo agent

When making changes:

1. Edit code
2. Run `deno task ci` to check everything
3. Commit changes
4. GitHub Actions runs the same checks
1. **Always create a branch first** - never commit directly to `main`
2. Edit code
3. Run `deno task ci` to check everything
4. Commit changes with focused, descriptive messages
5. Push branch and create PR
6. GitHub Actions runs the same checks

## Key Constraints

Expand Down Expand Up @@ -123,7 +126,7 @@ don't return data from the execution handler.

Run tests with: `deno test --allow-env --allow-net --allow-read`

Current test count: 72 passing, 0 failing
Current test count: 29 passing, 0 failing

## Dependencies

Expand All @@ -144,36 +147,44 @@ All dependencies are pinned in `deno.json` import maps.
- It's okay to say "this is a prototype" or "this part needs work"
- Code examples are better than long explanations
- Keep documentation concise and consolidate when possible
- Remove marketing fluff and focus on technical accuracy
- Don't claim things "need work" without specific evidence
- Position this as a working prototype, not a production system

## Development Guidelines

- **Always work on a branch** - never commit directly to `main`
- Follow existing code patterns
- Write tests for new functionality
- Update documentation when adding features
- Use TypeScript strictly - fix all type errors
- Follow Deno formatting conventions (`deno fmt`)
- Keep commits focused and descriptive
- Squash related commits before merging to keep history clean

## For AI Assistants

When working on this codebase:

- **Create a branch first** - never work directly on `main`
- Read the existing code to understand patterns
- Run tests after making changes
- Check that CI passes before submitting
- Don't make assumptions about complex LiveStore behavior
- Ask for clarification if event-sourcing concepts are unclear
- Focus on making the code work reliably rather than adding features
- Be honest about limitations and current state
- Avoid marketing language - this is a prototype for developers

The goal is to make this library useful for developers building runtime agents,
not to impress anyone with complexity.

## Recent Fixes Applied
## Recent Changes

- Fixed Pyodide code execution by using direct execution instead of IPython
transforms
- Eliminated duplicate execute_result outputs by proper displayhook handling
- Added proper JSR publishing configuration for all packages
- Consolidated documentation to reduce redundancy
- Upgraded Pyodide to version 0.27.7
- Moved dependency version constraints to deno.json imports
- Published all packages to JSR with proper dependency management
- Restructured pyodide package for executable installation (`pyrunt`)
- Cleaned up test suite from 47 to 29 focused test cases
- Removed marketing fluff from documentation
- Fixed JSR publishing with proper import constraints
- Added executable bin configuration for global installation
- Consolidated redundant documentation and tests
16 changes: 8 additions & 8 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@
},
"tasks": {
"dev": "deno run --allow-net --allow-env packages/lib/examples/echo-agent.ts",
"test": "deno test --allow-env --allow-net --allow-read --allow-sys",
"test": "deno test --allow-env --allow-net --allow-read --allow-write --allow-sys",
"test:watch": "deno test --allow-env --allow-net --allow-read --watch",
"test:coverage": "deno test --allow-env --allow-net --allow-read --allow-sys --coverage=cov/ && deno coverage --lcov cov/ > cov.lcov",
"test:unit": "deno test --allow-env --allow-net --allow-read --allow-sys packages/lib/src/",
"test:integration": "deno test --allow-env --allow-net --allow-read --allow-sys packages/lib/test/",
"test:examples": "deno test --allow-env --allow-net --allow-read --allow-sys packages/lib/examples/",
"test:pyodide": "deno test --allow-env --allow-net --allow-read --allow-sys packages/pyodide-runtime-agent/test/",
"test:pyodide:integration": "deno test --allow-env --allow-net --allow-read --allow-sys packages/pyodide-runtime-agent/test/in-memory-integration.test.ts",
"integration": "deno test --allow-env --allow-net --allow-read --allow-sys packages/pyodide-runtime-agent/test/simple-integration.test.ts packages/pyodide-runtime-agent/test/in-memory-integration.test.ts",
"test:coverage": "deno test --allow-env --allow-net --allow-read --allow-write --allow-sys --coverage=cov/ && deno coverage --lcov cov/ > cov.lcov",
"test:unit": "deno test --allow-env --allow-net --allow-read --allow-write --allow-sys packages/lib/src/",
"test:integration": "deno test --allow-env --allow-net --allow-read --allow-write --allow-sys packages/lib/test/",
"test:examples": "deno test --allow-env --allow-net --allow-read --allow-write --allow-sys packages/lib/examples/",
"test:pyodide": "deno test --allow-env --allow-net --allow-read --allow-write --allow-sys packages/pyodide-runtime-agent/test/",
"test:pyodide:integration": "deno test --allow-env --allow-net --allow-read --allow-write --allow-sys packages/pyodide-runtime-agent/test/in-memory-integration.test.ts",
"integration": "deno test --allow-env --allow-net --allow-read --allow-write --allow-sys packages/pyodide-runtime-agent/test/simple-integration.test.ts packages/pyodide-runtime-agent/test/in-memory-integration.test.ts",
"check": "deno check packages/*/mod.ts packages/*/src/*.ts",
"fmt": "deno fmt",
"fmt:check": "deno fmt --check",
Expand Down
46 changes: 42 additions & 4 deletions packages/pyodide-runtime-agent/src/pyodide-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,24 +65,43 @@ async function initializePyodide(

// Get cache configuration and packages to load
const { packageCacheDir } = getCacheConfig();
const packagesForInit = packagesToLoad || getEssentialPackages();
const basePackages = packagesToLoad || getEssentialPackages();

// Always ensure micropip and ipython are included for core functionality
const packagesForInit = Array.from(
new Set([
"micropip",
"ipython",
...basePackages,
]),
);

self.postMessage({
type: "log",
data: `Using cache directory: ${packageCacheDir}`,
});

// Load Pyodide with packages in parallel for faster initialization
// Load Pyodide with packages parameter (recommended by Pyodide docs)
pyodide = await loadPyodide({
packageCacheDir,
packages: packagesForInit, // Load packages in parallel with Pyodide initialization
stdout: (text: string) => {
// Log startup messages to our telemetry for debugging
self.postMessage({
type: "log",
data: `[Pyodide stdout on startup]: ${text}`,
});
self.postMessage({
type: "stream_output",
data: { type: "stdout", text },
});
},
stderr: (text: string) => {
// Log startup errors to our telemetry for debugging
self.postMessage({
type: "log",
data: `[Pyodide stderr on startup]: ${text}`,
});
self.postMessage({
type: "stream_output",
data: { type: "stderr", text },
Expand All @@ -97,7 +116,7 @@ async function initializePyodide(
self.postMessage({ type: "log", data: "Interrupt buffer configured" });
}

// Packages are already loaded in parallel during Pyodide initialization
// Packages are loaded in parallel during Pyodide initialization
self.postMessage({
type: "log",
data: `Packages loaded in parallel: ${packagesForInit.join(", ")}`,
Expand All @@ -106,9 +125,28 @@ async function initializePyodide(
// Load our Python bootstrap file
await setupIPythonEnvironment();

// Switch to clean stdout/stderr handlers after startup
pyodide.setStdout({
batched: (text: string) => {
self.postMessage({
type: "stream_output",
data: { type: "stdout", text },
});
},
});

pyodide.setStderr({
batched: (text: string) => {
self.postMessage({
type: "stream_output",
data: { type: "stderr", text },
});
},
});

self.postMessage({
type: "log",
data: "Enhanced Pyodide initialized successfully",
data: "Enhanced Pyodide worker initialized successfully",
});
}

Expand Down