agent-stage 0.2.15 → 0.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/commands/guide.js +5 -5
  2. package/dist/commands/init.d.ts +2 -0
  3. package/dist/commands/init.js +164 -0
  4. package/dist/commands/page/add.js +5 -40
  5. package/dist/commands/run/exec.js +1 -1
  6. package/dist/commands/run/inspect.js +1 -1
  7. package/dist/commands/run/watch.js +1 -1
  8. package/dist/commands/serve.d.ts +2 -0
  9. package/dist/commands/serve.js +238 -0
  10. package/dist/commands/status.d.ts +2 -0
  11. package/dist/commands/{dev/status.js → status.js} +17 -19
  12. package/dist/commands/stop.d.ts +2 -0
  13. package/dist/commands/stop.js +40 -0
  14. package/dist/index.js +8 -2
  15. package/dist/utils/agent-helper.js +5 -5
  16. package/dist/utils/paths.js +5 -5
  17. package/dist/utils/tunnel.d.ts +1 -1
  18. package/dist/utils/tunnel.js +1 -1
  19. package/package.json +8 -5
  20. package/dist/commands/dev/index.d.ts +0 -2
  21. package/dist/commands/dev/index.js +0 -11
  22. package/dist/commands/dev/init.d.ts +0 -2
  23. package/dist/commands/dev/init.js +0 -215
  24. package/dist/commands/dev/start.d.ts +0 -2
  25. package/dist/commands/dev/start.js +0 -145
  26. package/dist/commands/dev/status.d.ts +0 -2
  27. package/dist/commands/dev/stop.d.ts +0 -2
  28. package/dist/commands/dev/stop.js +0 -45
  29. package/template/components.json +0 -17
  30. package/template/index.html +0 -13
  31. package/template/package.json +0 -41
  32. package/template/postcss.config.js +0 -6
  33. package/template/src/components/PageRenderer.tsx +0 -108
  34. package/template/src/components/bridge-state-provider.tsx +0 -87
  35. package/template/src/components/ui/button.tsx +0 -55
  36. package/template/src/components/ui/card.tsx +0 -78
  37. package/template/src/components/ui/input.tsx +0 -24
  38. package/template/src/index.css +0 -59
  39. package/template/src/lib/bridge.ts +0 -53
  40. package/template/src/lib/utils.ts +0 -6
  41. package/template/src/main.tsx +0 -23
  42. package/template/src/pages/counter/store.json +0 -8
  43. package/template/src/pages/counter/ui.json +0 -108
  44. package/template/src/pages/test-page/store.json +0 -8
  45. package/template/src/routeTree.gen.ts +0 -77
  46. package/template/src/routes/__root.tsx +0 -11
  47. package/template/src/routes/counter.tsx +0 -19
  48. package/template/src/routes/index.tsx +0 -46
  49. package/template/src/vite-env.d.ts +0 -1
  50. package/template/tailwind.config.js +0 -53
  51. package/template/tsconfig.json +0 -25
  52. package/template/tsconfig.node.json +0 -11
  53. package/template/vite.config.ts +0 -22
@@ -1,108 +0,0 @@
1
- import { useEffect, useState } from 'react'
2
- import type { Spec } from '@agentstage/render'
3
- import { Renderer, defineRegistry, defineCatalog, schema } from '@agentstage/render'
4
- import { shadcnComponents, shadcnComponentDefinitions } from '@agentstage/render/shadcn'
5
- import type { Bridge } from '../lib/bridge'
6
- import { BridgeStateProvider } from './bridge-state-provider'
7
-
8
- interface PageRendererProps {
9
- pageId: string
10
- bridge: Bridge
11
- }
12
-
13
- // Create catalog with all shadcn components
14
- const catalog = defineCatalog(schema, {
15
- components: {
16
- Card: shadcnComponentDefinitions.Card,
17
- Button: shadcnComponentDefinitions.Button,
18
- Input: shadcnComponentDefinitions.Input,
19
- Stack: shadcnComponentDefinitions.Stack,
20
- Text: shadcnComponentDefinitions.Text,
21
- Heading: shadcnComponentDefinitions.Heading,
22
- Badge: shadcnComponentDefinitions.Badge,
23
- Separator: shadcnComponentDefinitions.Separator,
24
- Dialog: shadcnComponentDefinitions.Dialog,
25
- Tabs: shadcnComponentDefinitions.Tabs,
26
- Table: shadcnComponentDefinitions.Table,
27
- },
28
- actions: {},
29
- })
30
-
31
- // Create registry
32
- const { registry } = defineRegistry(catalog, {
33
- components: {
34
- Card: shadcnComponents.Card,
35
- Button: shadcnComponents.Button,
36
- Input: shadcnComponents.Input,
37
- Stack: shadcnComponents.Stack,
38
- Text: shadcnComponents.Text,
39
- Heading: shadcnComponents.Heading,
40
- Badge: shadcnComponents.Badge,
41
- Separator: shadcnComponents.Separator,
42
- Dialog: shadcnComponents.Dialog,
43
- Tabs: shadcnComponents.Tabs,
44
- Table: shadcnComponents.Table,
45
- },
46
- })
47
-
48
- export function PageRenderer({ pageId, bridge }: PageRendererProps) {
49
- const [uiSpec, setUiSpec] = useState<Spec | null>(null)
50
- const [loading, setLoading] = useState(true)
51
- const [error, setError] = useState<string | null>(null)
52
-
53
- useEffect(() => {
54
- // Load ui.json
55
- fetch(`/src/pages/${pageId}/ui.json`)
56
- .then((res) => {
57
- if (!res.ok) throw new Error(`Failed to load ui.json: ${res.status}`)
58
- return res.json()
59
- })
60
- .then((spec) => {
61
- setUiSpec(spec)
62
- setLoading(false)
63
- })
64
- .catch((err) => {
65
- setError(err.message)
66
- setLoading(false)
67
- })
68
- }, [pageId])
69
-
70
- // Connect to bridge
71
- useEffect(() => {
72
- bridge.connect().then((result: { storeId: string }) => {
73
- console.log('Connected to bridge:', result.storeId)
74
- })
75
- }, [bridge])
76
-
77
- if (loading) {
78
- return (
79
- <div className="flex items-center justify-center min-h-screen">
80
- <div className="animate-pulse text-muted-foreground">Loading UI...</div>
81
- </div>
82
- )
83
- }
84
-
85
- if (error) {
86
- return (
87
- <div className="flex items-center justify-center min-h-screen">
88
- <div className="text-destructive">Error: {error}</div>
89
- </div>
90
- )
91
- }
92
-
93
- if (!uiSpec) {
94
- return (
95
- <div className="flex items-center justify-center min-h-screen">
96
- <div className="text-muted-foreground">No UI spec found</div>
97
- </div>
98
- )
99
- }
100
-
101
- return (
102
- <BridgeStateProvider bridge={bridge}>
103
- <div className="min-h-screen bg-background p-8">
104
- <Renderer spec={uiSpec} registry={registry} />
105
- </div>
106
- </BridgeStateProvider>
107
- )
108
- }
@@ -1,87 +0,0 @@
1
- import { createContext, useContext, useState, useEffect, type ReactNode } from 'react'
2
- import type { Bridge } from '../lib/bridge'
3
-
4
- interface BridgeStateContextValue {
5
- state: Record<string, unknown>
6
- get: (path: string) => unknown
7
- set: (path: string, value: unknown) => void
8
- update: (updates: Record<string, unknown>) => void
9
- }
10
-
11
- const BridgeStateContext = createContext<BridgeStateContextValue | null>(null)
12
-
13
- interface BridgeStateProviderProps {
14
- bridge: Bridge
15
- children: ReactNode
16
- }
17
-
18
- export function BridgeStateProvider({ bridge, children }: BridgeStateProviderProps) {
19
- const [state, setLocalState] = useState(() => bridge.store.getState())
20
-
21
- useEffect(() => {
22
- return bridge.store.subscribe((newState) => {
23
- setLocalState(newState)
24
- })
25
- }, [bridge])
26
-
27
- const value: BridgeStateContextValue = {
28
- state,
29
- get: (path: string) => {
30
- const parts = path.split('/').filter(Boolean)
31
- let current: unknown = state
32
- for (const part of parts) {
33
- if (current === null || current === undefined) return undefined
34
- current = (current as Record<string, unknown>)[part]
35
- }
36
- return current
37
- },
38
- set: (path: string, value: unknown) => {
39
- const parts = path.split('/').filter(Boolean)
40
- bridge.store.setState((prev) => {
41
- const next = { ...prev }
42
- let current: Record<string, unknown> = next
43
- for (let i = 0; i < parts.length - 1; i++) {
44
- const part = parts[i]
45
- if (!(part in current) || typeof current[part] !== 'object') {
46
- current[part] = {}
47
- }
48
- current = current[part] as Record<string, unknown>
49
- }
50
- current[parts[parts.length - 1]] = value
51
- return next
52
- })
53
- },
54
- update: (updates: Record<string, unknown>) => {
55
- bridge.store.setState((prev) => {
56
- const next = { ...prev }
57
- for (const [path, value] of Object.entries(updates)) {
58
- const parts = path.split('/').filter(Boolean)
59
- let current: Record<string, unknown> = next
60
- for (let i = 0; i < parts.length - 1; i++) {
61
- const part = parts[i]
62
- if (!(part in current) || typeof current[part] !== 'object') {
63
- current[part] = {}
64
- }
65
- current = current[part] as Record<string, unknown>
66
- }
67
- current[parts[parts.length - 1]] = value
68
- }
69
- return next
70
- })
71
- },
72
- }
73
-
74
- return (
75
- <BridgeStateContext.Provider value={value}>
76
- {children}
77
- </BridgeStateContext.Provider>
78
- )
79
- }
80
-
81
- export function useBridgeStateContext(): BridgeStateContextValue {
82
- const context = useContext(BridgeStateContext)
83
- if (!context) {
84
- throw new Error('useBridgeStateContext must be used within BridgeStateProvider')
85
- }
86
- return context
87
- }
@@ -1,55 +0,0 @@
1
- import * as React from "react"
2
- import { Slot } from "@radix-ui/react-slot"
3
- import { cva, type VariantProps } from "class-variance-authority"
4
- import { cn } from "@/lib/utils"
5
-
6
- const buttonVariants = cva(
7
- "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
8
- {
9
- variants: {
10
- variant: {
11
- default: "bg-primary text-primary-foreground hover:bg-primary/90",
12
- destructive:
13
- "bg-destructive text-destructive-foreground hover:bg-destructive/90",
14
- outline:
15
- "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
16
- secondary:
17
- "bg-secondary text-secondary-foreground hover:bg-secondary/80",
18
- ghost: "hover:bg-accent hover:text-accent-foreground",
19
- link: "text-primary underline-offset-4 hover:underline",
20
- },
21
- size: {
22
- default: "h-10 px-4 py-2",
23
- sm: "h-9 rounded-md px-3",
24
- lg: "h-11 rounded-md px-8",
25
- icon: "h-10 w-10",
26
- },
27
- },
28
- defaultVariants: {
29
- variant: "default",
30
- size: "default",
31
- },
32
- }
33
- )
34
-
35
- export interface ButtonProps
36
- extends React.ButtonHTMLAttributes<HTMLButtonElement>,
37
- VariantProps<typeof buttonVariants> {
38
- asChild?: boolean
39
- }
40
-
41
- const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
42
- ({ className, variant, size, asChild = false, ...props }, ref) => {
43
- const Comp = asChild ? Slot : "button"
44
- return (
45
- <Comp
46
- className={cn(buttonVariants({ variant, size, className }))}
47
- ref={ref}
48
- {...props}
49
- />
50
- )
51
- }
52
- )
53
- Button.displayName = "Button"
54
-
55
- export { Button, buttonVariants }
@@ -1,78 +0,0 @@
1
- import * as React from "react"
2
- import { cn } from "@/lib/utils"
3
-
4
- const Card = React.forwardRef<
5
- HTMLDivElement,
6
- React.HTMLAttributes<HTMLDivElement>
7
- >(({ className, ...props }, ref) => (
8
- <div
9
- ref={ref}
10
- className={cn(
11
- "rounded-lg border bg-card text-card-foreground shadow-sm",
12
- className
13
- )}
14
- {...props}
15
- />
16
- ))
17
- Card.displayName = "Card"
18
-
19
- const CardHeader = React.forwardRef<
20
- HTMLDivElement,
21
- React.HTMLAttributes<HTMLDivElement>
22
- >(({ className, ...props }, ref) => (
23
- <div
24
- ref={ref}
25
- className={cn("flex flex-col space-y-1.5 p-6", className)}
26
- {...props}
27
- />
28
- ))
29
- CardHeader.displayName = "CardHeader"
30
-
31
- const CardTitle = React.forwardRef<
32
- HTMLParagraphElement,
33
- React.HTMLAttributes<HTMLHeadingElement>
34
- >(({ className, ...props }, ref) => (
35
- <h3
36
- ref={ref}
37
- className={cn(
38
- "text-2xl font-semibold leading-none tracking-tight",
39
- className
40
- )}
41
- {...props}
42
- />
43
- ))
44
- CardTitle.displayName = "CardTitle"
45
-
46
- const CardDescription = React.forwardRef<
47
- HTMLParagraphElement,
48
- React.HTMLAttributes<HTMLParagraphElement>
49
- >(({ className, ...props }, ref) => (
50
- <p
51
- ref={ref}
52
- className={cn("text-sm text-muted-foreground", className)}
53
- {...props}
54
- />
55
- ))
56
- CardDescription.displayName = "CardDescription"
57
-
58
- const CardContent = React.forwardRef<
59
- HTMLDivElement,
60
- React.HTMLAttributes<HTMLDivElement>
61
- >(({ className, ...props }, ref) => (
62
- <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
63
- ))
64
- CardContent.displayName = "CardContent"
65
-
66
- const CardFooter = React.forwardRef<
67
- HTMLDivElement,
68
- React.HTMLAttributes<HTMLDivElement>
69
- >(({ className, ...props }, ref) => (
70
- <div
71
- ref={ref}
72
- className={cn("flex items-center p-6 pt-0", className)}
73
- {...props}
74
- />
75
- ))
76
- CardFooter.displayName = "CardFooter"
77
-
78
- export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
@@ -1,24 +0,0 @@
1
- import * as React from "react"
2
- import { cn } from "@/lib/utils"
3
-
4
- export interface InputProps
5
- extends React.InputHTMLAttributes<HTMLInputElement> {}
6
-
7
- const Input = React.forwardRef<HTMLInputElement, InputProps>(
8
- ({ className, type, ...props }, ref) => {
9
- return (
10
- <input
11
- type={type}
12
- className={cn(
13
- "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
14
- className
15
- )}
16
- ref={ref}
17
- {...props}
18
- />
19
- )
20
- }
21
- )
22
- Input.displayName = "Input"
23
-
24
- export { Input }
@@ -1,59 +0,0 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
-
5
- @layer base {
6
- :root {
7
- --background: 0 0% 100%;
8
- --foreground: 0 0% 3.9%;
9
- --card: 0 0% 100%;
10
- --card-foreground: 0 0% 3.9%;
11
- --popover: 0 0% 100%;
12
- --popover-foreground: 0 0% 3.9%;
13
- --primary: 0 0% 9%;
14
- --primary-foreground: 0 0% 98%;
15
- --secondary: 0 0% 96.1%;
16
- --secondary-foreground: 0 0% 9%;
17
- --muted: 0 0% 96.1%;
18
- --muted-foreground: 0 0% 45.1%;
19
- --accent: 0 0% 96.1%;
20
- --accent-foreground: 0 0% 9%;
21
- --destructive: 0 84.2% 60.2%;
22
- --destructive-foreground: 0 0% 98%;
23
- --border: 0 0% 89.8%;
24
- --input: 0 0% 89.8%;
25
- --ring: 0 0% 3.9%;
26
- --radius: 0.5rem;
27
- }
28
-
29
- .dark {
30
- --background: 0 0% 3.9%;
31
- --foreground: 0 0% 98%;
32
- --card: 0 0% 3.9%;
33
- --card-foreground: 0 0% 98%;
34
- --popover: 0 0% 3.9%;
35
- --popover-foreground: 0 0% 98%;
36
- --primary: 0 0% 98%;
37
- --primary-foreground: 0 0% 9%;
38
- --secondary: 0 0% 14.9%;
39
- --secondary-foreground: 0 0% 98%;
40
- --muted: 0 0% 14.9%;
41
- --muted-foreground: 0 0% 63.9%;
42
- --accent: 0 0% 14.9%;
43
- --accent-foreground: 0 0% 98%;
44
- --destructive: 0 62.8% 30.6%;
45
- --destructive-foreground: 0 0% 98%;
46
- --border: 0 0% 14.9%;
47
- --input: 0 0% 14.9%;
48
- --ring: 0 0% 83.1%;
49
- }
50
- }
51
-
52
- @layer base {
53
- * {
54
- @apply border-border;
55
- }
56
- body {
57
- @apply bg-background text-foreground;
58
- }
59
- }
@@ -1,53 +0,0 @@
1
- import { createBridgeStore } from 'agent-stage-bridge/browser'
2
- import { z } from 'zod'
3
- import type { ZodSchema } from 'zod'
4
-
5
- export interface Bridge {
6
- store: {
7
- getState: () => Record<string, unknown>
8
- subscribe: (callback: (state: Record<string, unknown>) => void) => () => void
9
- setState: (updater: (prev: Record<string, unknown>) => Record<string, unknown>) => void
10
- }
11
- connect: () => Promise<{ storeId: string }>
12
- isHydrated: boolean
13
- pageId: string
14
- }
15
-
16
- interface CreatePageBridgeOptions {
17
- pageId: string
18
- schema?: ZodSchema
19
- actions?: Record<string, { description: string; payload?: ZodSchema }>
20
- events?: Record<string, { description: string }>
21
- }
22
-
23
- // Default schema that accepts any object
24
- const defaultSchema = z.record(z.unknown())
25
-
26
- export function createPageBridge(options: CreatePageBridgeOptions): Bridge {
27
- const { pageId, schema = defaultSchema, actions = {}, events = {} } = options
28
-
29
- const bridge = createBridgeStore({
30
- pageId,
31
- storeKey: 'main',
32
- description: {
33
- schema,
34
- actions,
35
- events,
36
- },
37
- createState: () => ({
38
- // Initial state will be loaded from store.json by gateway
39
- }),
40
- })
41
-
42
- // Mount to window for debugging
43
- if (typeof window !== 'undefined') {
44
- ;(window as unknown as Record<string, unknown>)[`bridge_${pageId}`] = bridge
45
- }
46
-
47
- return bridge as unknown as Bridge
48
- }
49
-
50
- // Legacy export for compatibility
51
- export const bridge = createPageBridge({
52
- pageId: 'counter',
53
- })
@@ -1,6 +0,0 @@
1
- import { clsx, type ClassValue } from "clsx"
2
- import { twMerge } from "tailwind-merge"
3
-
4
- export function cn(...inputs: ClassValue[]) {
5
- return twMerge(clsx(inputs))
6
- }
@@ -1,23 +0,0 @@
1
- import React from 'react'
2
- import ReactDOM from 'react-dom/client'
3
- import { RouterProvider, createRouter } from '@tanstack/react-router'
4
- import './index.css'
5
-
6
- // Import the generated route tree
7
- import { routeTree } from './routeTree.gen'
8
-
9
- // Create a new router instance
10
- const router = createRouter({ routeTree })
11
-
12
- // Register the router instance for type safety
13
- declare module '@tanstack/react-router' {
14
- interface Register {
15
- router: typeof router
16
- }
17
- }
18
-
19
- ReactDOM.createRoot(document.getElementById('root')!).render(
20
- <React.StrictMode>
21
- <RouterProvider router={router} />
22
- </React.StrictMode>,
23
- )
@@ -1,8 +0,0 @@
1
- {
2
- "state": {
3
- "count": 5
4
- },
5
- "version": 1,
6
- "updatedAt": "2026-02-19T08:00:00.000Z",
7
- "pageId": "counter"
8
- }
@@ -1,108 +0,0 @@
1
- {
2
- "root": "container",
3
- "elements": {
4
- "container": {
5
- "type": "Stack",
6
- "props": {
7
- "direction": "vertical",
8
- "gap": "md",
9
- "align": "center"
10
- },
11
- "children": ["header", "card"]
12
- },
13
- "header": {
14
- "type": "Stack",
15
- "props": {
16
- "direction": "vertical",
17
- "gap": "sm",
18
- "align": "center"
19
- },
20
- "children": ["title", "description"]
21
- },
22
- "title": {
23
- "type": "Heading",
24
- "props": {
25
- "text": "File-based Store Demo",
26
- "level": "h1"
27
- }
28
- },
29
- "description": {
30
- "type": "Text",
31
- "props": {
32
- "text": "This page demonstrates the JSON-render architecture. State is persisted to store.json and synced via bridge.",
33
- "variant": "muted"
34
- }
35
- },
36
- "card": {
37
- "type": "Card",
38
- "props": {
39
- "title": "Counter",
40
- "description": "Try modifying store.json or use CLI to update state"
41
- },
42
- "children": ["counter-content"]
43
- },
44
- "counter-content": {
45
- "type": "Stack",
46
- "props": {
47
- "direction": "vertical",
48
- "gap": "md",
49
- "align": "center"
50
- },
51
- "children": ["count-display", "buttons", "hint"]
52
- },
53
- "count-display": {
54
- "type": "Text",
55
- "props": {
56
- "text": { "$state": "/count" },
57
- "variant": "lead"
58
- }
59
- },
60
- "buttons": {
61
- "type": "Stack",
62
- "props": {
63
- "direction": "horizontal",
64
- "gap": "sm"
65
- },
66
- "children": ["btn-decrement", "btn-increment"]
67
- },
68
- "btn-decrement": {
69
- "type": "Button",
70
- "props": {
71
- "label": "-",
72
- "variant": "secondary"
73
- },
74
- "on": {
75
- "press": {
76
- "action": "setState",
77
- "params": {
78
- "statePath": "/count",
79
- "value": -1
80
- }
81
- }
82
- }
83
- },
84
- "btn-increment": {
85
- "type": "Button",
86
- "props": {
87
- "label": "+",
88
- "variant": "primary"
89
- },
90
- "on": {
91
- "press": {
92
- "action": "setState",
93
- "params": {
94
- "statePath": "/count",
95
- "value": 1
96
- }
97
- }
98
- }
99
- },
100
- "hint": {
101
- "type": "Text",
102
- "props": {
103
- "text": "State is saved to pages/counter/store.json. Try refreshing or editing the file!",
104
- "variant": "caption"
105
- }
106
- }
107
- }
108
- }
@@ -1,8 +0,0 @@
1
- {
2
- "state": {
3
- "count": 42
4
- },
5
- "version": 1,
6
- "updatedAt": "2026-02-17T11:51:56.723Z",
7
- "pageId": "test-page"
8
- }