Skip to content
Draft
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
5 changes: 5 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
"@open-wa/mcp",
"@open-wa/node-red",
"@open-wa/plugin-sdk",
"@open-wa/runtime-browser",
"@open-wa/runtime-bun",
"@open-wa/runtime-core",
"@open-wa/runtime-edge",
"@open-wa/runtime-node",
"@open-wa/schema",
"@open-wa/screencaster",
"@open-wa/session-sync",
Expand Down
8 changes: 8 additions & 0 deletions .changeset/effect-v4-runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@open-wa/core": minor
---

Adopt Effect v4 as the v5 runtime kernel, including scoped browser resources,
capability-enforced chat sandboxes, supervised plugin services, durable webhook
delivery, runtime-specific adapters, parallel startup work, and measured
replacement gates for queues and other concurrency primitives.
47 changes: 47 additions & 0 deletions .github/workflows/effect-contracts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Effect runtime contracts

on:
pull_request:
paths:
- 'packages/runtime-*/**'
- 'packages/client/**'
- 'packages/core/**'
- 'integrations/**'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- 'tools/check-effect-pins.mjs'
- 'tools/check-portable-imports.mjs'
- 'tools/check-bun-runtime.ts'
- 'tools/bench-effect-startup.mjs'
- '.github/workflows/effect-contracts.yml'
push:
branches: [master]
paths:
- 'packages/runtime-*/**'
- 'packages/client/**'
- 'packages/core/**'
- 'integrations/**'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'

jobs:
contracts:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 11.9.0
- uses: actions/setup-node@v4
with:
node-version: 22.21.1
cache: pnpm
- run: pnpm install --frozen-lockfile
env:
PUPPETEER_SKIP_DOWNLOAD: 'true'
- run: pnpm check:effect-contracts
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- run: bun tools/check-bun-runtime.ts
11 changes: 2 additions & 9 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
node_modules
dist
# Runtime browser session data / Chrome userData — NEVER commit these. The
# runtime's default userDataDir is _IGNORE_<sessionId> (see **_IGNORE_** below);
# these also catch session dirs a user points userDataDir at.
session/
sessions/
newsession/
# ...but wa-automate's source `session` directory is real code, not data:
!packages/wa-automate/src/session/
!packages/wa-automate/src/session/**
/session/
/newsession/
**buttons.js
**req.ts
**qr_code_session.png
Expand Down
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
trust-lockfile=true
2 changes: 1 addition & 1 deletion .oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
"jsx-a11y/lang": "off",
"jsx-a11y/html-has-lang": "off",
"jsx-a11y/prefer-tag-over-role": "off",
"typescript-eslint/no-extraneous-class": "off",
"jest/no-disabled-tests": "off"
},
"ignorePatterns": [
Expand All @@ -53,6 +52,7 @@
"**/.docusaurus/**",
"**/build/**",
"**/*.gen.ts",
"packages/core/src/transport/assets/**",
"packages/orchestrator/tests/**"
],
"overrides": [
Expand Down
49 changes: 24 additions & 25 deletions apps/dashboard-neo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,46 +18,45 @@
"url": "https://github.com/open-wa/wa-automate-nodejs.git"
},
"license": "Apache-2.0",
"dependencies": {},
"devDependencies": {
"@base-ui/react": "^1.3.0",
"@fontsource-variable/geist": "^5.2.8",
"@hugeicons/core-free-icons": "^4.1.1",
"@hugeicons/react": "^1.1.6",
"@base-ui/react": "^1.6.0",
"@fontsource-variable/geist": "^5.3.0",
"@hugeicons/core-free-icons": "^4.2.3",
"@hugeicons/react": "^1.1.9",
"@open-wa/screencaster": "workspace:*",
"@open-wa/socket-client": "workspace:*",
"@scalar/api-reference-react": "^0.9.18",
"@scalar/api-reference-react": "^0.9.59",
"@tailwindcss/vite": "catalog:",
"@tanstack/react-devtools": "^0.10.0",
"@tanstack/devtools-vite": "^0.8.1",
"@tanstack/eslint-config": "^0.4.0",
"@tanstack/react-devtools": "^0.10.8",
"@tanstack/react-router": "catalog:",
"@tanstack/react-router-devtools": "catalog:",
"@tanstack/react-router-ssr-query": "catalog:",
"@tanstack/router-plugin": "^1.167.10",
"@tanstack/router-plugin": "^1.168.23",
"@testing-library/dom": "^10.4.1",
"@testing-library/react": "^16.3.2",
"@types/node": "^26.1.1",
"@types/react": "^19.2.17",
"@types/react-dom": "catalog:",
"@vitejs/plugin-react": "catalog:",
"class-variance-authority": "^0.7.1",
"clsx": "catalog:",
"jsdom": "^29.1.1",
"lucide-react": "catalog:",
"next-themes": "^0.4.6",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"shadcn": "^4.1.2",
"prettier": "^3.9.6",
"prettier-plugin-tailwindcss": "^0.8.1",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"shadcn": "^4.14.0",
"sonner": "^2.0.7",
"tailwind-merge": "catalog:",
"tailwindcss": "^4.2.1",
"tailwindcss": "^4.3.3",
"tailwindcss-animate": "^1.0.7",
"@tanstack/devtools-vite": "^0.6.0",
"@tanstack/eslint-config": "^0.4.0",
"@testing-library/dom": "^10.4.1",
"@testing-library/react": "^16.3.2",
"@types/node": "^22.19.15",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "catalog:",
"jsdom": "^27.4.0",
"prettier": "^3.8.1",
"prettier-plugin-tailwindcss": "^0.7.2",
"typescript": "^5.9.3",
"typescript": "^7.0.2",
"vite": "catalog:",
"vitest": "catalog:",
"web-vitals": "^5.1.0"
"web-vitals": "^6.0.0"
}
}
1 change: 0 additions & 1 deletion apps/dashboard-neo/src/components/app-sidebar.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// @vitest-environment jsdom
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';
import React from 'react';

// Mock dependencies
vi.mock('@/lib/hooks/use-health', () => ({
Expand Down
27 changes: 0 additions & 27 deletions apps/dashboard-neo/src/components/app-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,33 +47,6 @@ import {
Bot,
} from "lucide-react"

const navItems = [
{
group: "Overview",
items: [
{ title: "Session", href: "/", icon: <Zap size={18} /> },
{ title: "Health", href: "/health", icon: <HeartPulse size={18} /> },
{ title: "Events", href: "/events", icon: <Activity size={18} /> },
],
},
{
group: "Developer",
items: [
{ title: "API Docs", href: "/api-docs", icon: <BookOpen size={18} /> },
{ title: "Playground", href: "/playground", icon: <FlaskConical size={18} /> },
{ title: "Debug", href: "/debug", icon: <Bug size={18} /> },
],
},
{
group: "Communication",
items: [
{ title: "Chat", href: "/chat", icon: <MessageSquare size={18} /> },
{ title: "Contacts", href: "/contacts", icon: <Contact size={18} /> },
{ title: "Portal", href: "/portal", icon: <Tv size={18} /> },
],
},
]

/**
* Fetches the plugin manifest from the API server.
* Returns empty array if the API is unreachable.
Expand Down
24 changes: 18 additions & 6 deletions apps/dashboard-neo/src/lib/hooks/use-health.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ import {
} from "./use-health"

describe("runtime readiness helpers", () => {
const healthWithSession = (session: Record<string, unknown>): HealthData => ({
status: "ok",
version: "test",
connected: false,
session,
qr: null,
launchTimeline: [],
patches: [],
license: null,
reconnections: [],
startedAt: null,
lastEventAt: null,
})

it("allows runtime calls when health marks the session ready", () => {
expect(
isRuntimeReadySession({ ready: true, state: "AUTHENTICATING" })
Expand All @@ -31,13 +45,11 @@ describe("runtime readiness helpers", () => {
})

it("derives runtime call permission from health data", () => {
expect(canInvokeRuntime({ session: { ready: true } } as HealthData)).toBe(
true
)
expect(canInvokeRuntime(healthWithSession({ ready: true }))).toBe(true)
expect(
canInvokeRuntime({
session: { ready: false, state: "AUTHENTICATING" },
} as HealthData)
canInvokeRuntime(
healthWithSession({ ready: false, state: "AUTHENTICATING" })
)
).toBe(false)
expect(canInvokeRuntime(null)).toBe(false)
})
Expand Down
1 change: 0 additions & 1 deletion apps/dashboard-neo/src/routes/-mcp.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// @vitest-environment jsdom
import { describe, it, expect, vi, beforeEach } from 'vitest';
import React from 'react';

// Mock dependencies
vi.mock('@/lib/hooks/use-health', () => ({
Expand Down
2 changes: 1 addition & 1 deletion apps/dashboard-neo/src/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ function PreLaunchView({
autoScroll
showTimestamps
showControls
onClear={() => setLogLines([])}
onClear={isDemo ? () => setDemoLogLines([]) : undefined}
/>
</div>

Expand Down
10 changes: 3 additions & 7 deletions apps/dashboard-neo/src/routes/mcp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ import {
KeyRound,
Copy,
} from "lucide-react"
import { useState } from "react"
import { useState, type ReactNode } from "react"
import { getApiUrl } from "@/lib/api-client"

export const Route = createFileRoute("/mcp")({ component: McpPage })

export function McpPage() {
const { mcpAvailable, mcpEnabled, mcpPath, loading } = useHealth()
const { mcpAvailable, mcpEnabled, mcpPath } = useHealth()
const [copied, setCopied] = useState<string | null>(null)

const baseUrl = getApiUrl()
Expand Down Expand Up @@ -143,7 +143,6 @@ export function McpPage() {
icon={<Bot size={16} className="text-primary" />}
snippet={claudeConfig}
copied={copied}
setCopied={setCopied}
copyId="claude"
copyToClipboard={copyToClipboard}
instructions={[
Expand All @@ -160,7 +159,6 @@ export function McpPage() {
icon={<Code2 size={16} className="text-primary" />}
snippet={cursorConfig}
copied={copied}
setCopied={setCopied}
copyId="cursor"
copyToClipboard={copyToClipboard}
instructions={[
Expand Down Expand Up @@ -280,7 +278,6 @@ function ConfigSnippet({
icon,
snippet,
copied,
setCopied,
copyId,
copyToClipboard,
instructions,
Expand All @@ -289,10 +286,9 @@ function ConfigSnippet({
icon: React.ReactNode
snippet: string
copied: string | null
setCopied: (v: string | null) => void
copyId: string
copyToClipboard: (text: string, id: string) => void
instructions: React.ReactNode[]
instructions: ReactNode[]
}) {
return (
<div className="rounded-xl border bg-card">
Expand Down
16 changes: 8 additions & 8 deletions apps/dashboard-neo/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { defineConfig } from "vite"
import { fileURLToPath, URL } from "node:url"
import { defineConfig } from "vitest/config"
import { createRequire } from "node:module"
import { devtools } from "@tanstack/devtools-vite"
import { TanStackRouterVite } from "@tanstack/router-plugin/vite"
import viteReact from "@vitejs/plugin-react"
import tailwindcss from "@tailwindcss/vite"

const appReactPath = (path: string) => fileURLToPath(new URL(`./node_modules/${path}`, import.meta.url))
const resolvePackageExport = createRequire(import.meta.url).resolve

const config = defineConfig({
base: '/dashboard/',
resolve: {
tsconfigPaths: true,
dedupe: ["react", "react-dom", "react/jsx-runtime", "react/jsx-dev-runtime"],
alias: [
{ find: "react/jsx-runtime", replacement: appReactPath("react/jsx-runtime.js") },
{ find: "react/jsx-dev-runtime", replacement: appReactPath("react/jsx-dev-runtime.js") },
{ find: "react-dom/client", replacement: appReactPath("react-dom/client.js") },
{ find: /^react$/, replacement: appReactPath("react/index.js") },
{ find: /^react-dom$/, replacement: appReactPath("react-dom/index.js") },
{ find: "react/jsx-runtime", replacement: resolvePackageExport("react/jsx-runtime") },
{ find: "react/jsx-dev-runtime", replacement: resolvePackageExport("react/jsx-dev-runtime") },
{ find: "react-dom/client", replacement: resolvePackageExport("react-dom/client") },
{ find: /^react$/, replacement: resolvePackageExport("react") },
{ find: /^react-dom$/, replacement: resolvePackageExport("react-dom") },
],
},
plugins: [
Expand Down
2 changes: 1 addition & 1 deletion apps/docker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"homepage": "https://github.com/open-wa/wa-automate-docker#readme",
"dependencies": {
"@open-wa/wa-automate": "latest",
"npm": "^7.12.1"
"npm": "^12.0.1"
},
"private": true
}
Loading
Loading