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.
- package/dist/commands/guide.js +5 -5
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +164 -0
- package/dist/commands/page/add.js +5 -40
- package/dist/commands/run/exec.js +1 -1
- package/dist/commands/run/inspect.js +1 -1
- package/dist/commands/run/watch.js +1 -1
- package/dist/commands/serve.d.ts +2 -0
- package/dist/commands/serve.js +238 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/{dev/status.js → status.js} +17 -19
- package/dist/commands/stop.d.ts +2 -0
- package/dist/commands/stop.js +40 -0
- package/dist/index.js +8 -2
- package/dist/utils/agent-helper.js +5 -5
- package/dist/utils/paths.js +5 -5
- package/dist/utils/tunnel.d.ts +1 -1
- package/dist/utils/tunnel.js +1 -1
- package/package.json +8 -5
- package/dist/commands/dev/index.d.ts +0 -2
- package/dist/commands/dev/index.js +0 -11
- package/dist/commands/dev/init.d.ts +0 -2
- package/dist/commands/dev/init.js +0 -215
- package/dist/commands/dev/start.d.ts +0 -2
- package/dist/commands/dev/start.js +0 -145
- package/dist/commands/dev/status.d.ts +0 -2
- package/dist/commands/dev/stop.d.ts +0 -2
- package/dist/commands/dev/stop.js +0 -45
- package/template/components.json +0 -17
- package/template/index.html +0 -13
- package/template/package.json +0 -41
- package/template/postcss.config.js +0 -6
- package/template/src/components/PageRenderer.tsx +0 -108
- package/template/src/components/bridge-state-provider.tsx +0 -87
- package/template/src/components/ui/button.tsx +0 -55
- package/template/src/components/ui/card.tsx +0 -78
- package/template/src/components/ui/input.tsx +0 -24
- package/template/src/index.css +0 -59
- package/template/src/lib/bridge.ts +0 -53
- package/template/src/lib/utils.ts +0 -6
- package/template/src/main.tsx +0 -23
- package/template/src/pages/counter/store.json +0 -8
- package/template/src/pages/counter/ui.json +0 -108
- package/template/src/pages/test-page/store.json +0 -8
- package/template/src/routeTree.gen.ts +0 -77
- package/template/src/routes/__root.tsx +0 -11
- package/template/src/routes/counter.tsx +0 -19
- package/template/src/routes/index.tsx +0 -46
- package/template/src/vite-env.d.ts +0 -1
- package/template/tailwind.config.js +0 -53
- package/template/tsconfig.json +0 -25
- package/template/tsconfig.node.json +0 -11
- 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 }
|
package/template/src/index.css
DELETED
|
@@ -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
|
-
})
|
package/template/src/main.tsx
DELETED
|
@@ -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,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
|
-
}
|