agent-stage 0.2.0 → 0.2.1
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/cleanup.d.ts +2 -0
- package/dist/commands/{reset.js → cleanup.js} +3 -2
- package/dist/commands/dev/index.d.ts +2 -0
- package/dist/commands/dev/index.js +11 -0
- package/dist/commands/dev/init.d.ts +2 -0
- package/dist/commands/dev/init.js +231 -0
- package/dist/commands/dev/start.d.ts +2 -0
- package/dist/commands/dev/start.js +145 -0
- package/dist/commands/dev/status.d.ts +2 -0
- package/dist/commands/dev/status.js +55 -0
- package/dist/commands/dev/stop.d.ts +2 -0
- package/dist/commands/dev/stop.js +45 -0
- package/dist/commands/doctor.js +2 -2
- package/dist/commands/exec.js +46 -30
- package/dist/commands/guide.d.ts +2 -0
- package/dist/commands/guide.js +268 -0
- package/dist/commands/init.js +9 -9
- package/dist/commands/inspect.js +1 -1
- package/dist/commands/ls.js +65 -17
- package/dist/commands/page/add.d.ts +2 -0
- package/dist/commands/page/add.js +262 -0
- package/dist/commands/page/index.d.ts +2 -0
- package/dist/commands/page/index.js +11 -0
- package/dist/commands/page/ls.d.ts +2 -0
- package/dist/commands/page/ls.js +45 -0
- package/dist/commands/page/manifest.d.ts +2 -0
- package/dist/commands/page/manifest.js +82 -0
- package/dist/commands/page/rm.d.ts +2 -0
- package/dist/commands/page/rm.js +89 -0
- package/dist/commands/run/exec.d.ts +2 -0
- package/dist/commands/run/exec.js +89 -0
- package/dist/commands/run/get-state.d.ts +2 -0
- package/dist/commands/run/get-state.js +71 -0
- package/dist/commands/run/index.d.ts +2 -0
- package/dist/commands/run/index.js +13 -0
- package/dist/commands/run/inspect.d.ts +2 -0
- package/dist/commands/run/inspect.js +80 -0
- package/dist/commands/run/set-state.d.ts +2 -0
- package/dist/commands/run/set-state.js +93 -0
- package/dist/commands/run/watch.d.ts +2 -0
- package/dist/commands/run/watch.js +72 -0
- package/dist/commands/verify.d.ts +2 -0
- package/dist/commands/verify.js +230 -0
- package/dist/commands/watch.js +1 -1
- package/dist/index.js +11 -30
- package/dist/utils/agent-helper.d.ts +30 -0
- package/dist/utils/agent-helper.js +181 -0
- package/dist/utils/cloudflared.d.ts +21 -0
- package/dist/utils/cloudflared.js +90 -0
- package/dist/utils/paths.d.ts +2 -1
- package/dist/utils/paths.js +7 -10
- package/dist/utils/tunnel.d.ts +21 -0
- package/dist/utils/tunnel.js +116 -0
- package/package.json +3 -2
- package/template/package.json +7 -6
- package/template/src/components/PageRenderer.tsx +108 -0
- package/template/src/components/bridge-state-provider.tsx +87 -0
- package/template/src/lib/bridge.ts +53 -0
- package/template/src/pages/counter/store.json +8 -0
- package/template/src/pages/counter/ui.json +108 -0
- package/template/src/pages/test-page/store.json +8 -0
- package/template/src/routeTree.gen.ts +77 -0
- package/template/src/routes/__root.tsx +1 -1
- package/template/src/routes/counter.tsx +19 -0
- package/dist/commands/add-page.d.ts +0 -2
- package/dist/commands/add-page.js +0 -132
- package/dist/commands/reset.d.ts +0 -2
|
@@ -0,0 +1,87 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
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
|
+
})
|
|
@@ -0,0 +1,108 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
|
|
3
|
+
// @ts-nocheck
|
|
4
|
+
|
|
5
|
+
// noinspection JSUnusedGlobalSymbols
|
|
6
|
+
|
|
7
|
+
// This file was automatically generated by TanStack Router.
|
|
8
|
+
// You should NOT make any changes in this file as it will be overwritten.
|
|
9
|
+
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
|
10
|
+
|
|
11
|
+
import { Route as rootRouteImport } from './routes/__root'
|
|
12
|
+
import { Route as CounterRouteImport } from './routes/counter'
|
|
13
|
+
import { Route as IndexRouteImport } from './routes/index'
|
|
14
|
+
|
|
15
|
+
const CounterRoute = CounterRouteImport.update({
|
|
16
|
+
id: '/counter',
|
|
17
|
+
path: '/counter',
|
|
18
|
+
getParentRoute: () => rootRouteImport,
|
|
19
|
+
} as any)
|
|
20
|
+
const IndexRoute = IndexRouteImport.update({
|
|
21
|
+
id: '/',
|
|
22
|
+
path: '/',
|
|
23
|
+
getParentRoute: () => rootRouteImport,
|
|
24
|
+
} as any)
|
|
25
|
+
|
|
26
|
+
export interface FileRoutesByFullPath {
|
|
27
|
+
'/': typeof IndexRoute
|
|
28
|
+
'/counter': typeof CounterRoute
|
|
29
|
+
}
|
|
30
|
+
export interface FileRoutesByTo {
|
|
31
|
+
'/': typeof IndexRoute
|
|
32
|
+
'/counter': typeof CounterRoute
|
|
33
|
+
}
|
|
34
|
+
export interface FileRoutesById {
|
|
35
|
+
__root__: typeof rootRouteImport
|
|
36
|
+
'/': typeof IndexRoute
|
|
37
|
+
'/counter': typeof CounterRoute
|
|
38
|
+
}
|
|
39
|
+
export interface FileRouteTypes {
|
|
40
|
+
fileRoutesByFullPath: FileRoutesByFullPath
|
|
41
|
+
fullPaths: '/' | '/counter'
|
|
42
|
+
fileRoutesByTo: FileRoutesByTo
|
|
43
|
+
to: '/' | '/counter'
|
|
44
|
+
id: '__root__' | '/' | '/counter'
|
|
45
|
+
fileRoutesById: FileRoutesById
|
|
46
|
+
}
|
|
47
|
+
export interface RootRouteChildren {
|
|
48
|
+
IndexRoute: typeof IndexRoute
|
|
49
|
+
CounterRoute: typeof CounterRoute
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
declare module '@tanstack/react-router' {
|
|
53
|
+
interface FileRoutesByPath {
|
|
54
|
+
'/counter': {
|
|
55
|
+
id: '/counter'
|
|
56
|
+
path: '/counter'
|
|
57
|
+
fullPath: '/counter'
|
|
58
|
+
preLoaderRoute: typeof CounterRouteImport
|
|
59
|
+
parentRoute: typeof rootRouteImport
|
|
60
|
+
}
|
|
61
|
+
'/': {
|
|
62
|
+
id: '/'
|
|
63
|
+
path: '/'
|
|
64
|
+
fullPath: '/'
|
|
65
|
+
preLoaderRoute: typeof IndexRouteImport
|
|
66
|
+
parentRoute: typeof rootRouteImport
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const rootRouteChildren: RootRouteChildren = {
|
|
72
|
+
IndexRoute: IndexRoute,
|
|
73
|
+
CounterRoute: CounterRoute,
|
|
74
|
+
}
|
|
75
|
+
export const routeTree = rootRouteImport
|
|
76
|
+
._addFileChildren(rootRouteChildren)
|
|
77
|
+
._addFileTypes<FileRouteTypes>()
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
2
|
+
import { useMemo } from 'react'
|
|
3
|
+
import { PageRenderer } from '../components/PageRenderer'
|
|
4
|
+
import { createPageBridge } from '../lib/bridge'
|
|
5
|
+
|
|
6
|
+
export const Route = createFileRoute('/counter')({
|
|
7
|
+
component: CounterPage,
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
function CounterPage() {
|
|
11
|
+
// Create bridge instance for this page
|
|
12
|
+
const bridge = useMemo(() => {
|
|
13
|
+
return createPageBridge({
|
|
14
|
+
pageId: 'counter',
|
|
15
|
+
})
|
|
16
|
+
}, [])
|
|
17
|
+
|
|
18
|
+
return <PageRenderer pageId="counter" bridge={bridge} />
|
|
19
|
+
}
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import consola from 'consola';
|
|
3
|
-
import c from 'picocolors';
|
|
4
|
-
import { writeFile, mkdir } from 'fs/promises';
|
|
5
|
-
import { existsSync } from 'fs';
|
|
6
|
-
import { join } from 'pathe';
|
|
7
|
-
import { getWorkspaceDir, isInitialized, readRuntimeConfig } from '../utils/paths.js';
|
|
8
|
-
export const addPageCommand = new Command('add-page')
|
|
9
|
-
.description('Add a new page with Bridge store')
|
|
10
|
-
.argument('<name>', 'Page name (e.g., counter, about)')
|
|
11
|
-
.action(async (name) => {
|
|
12
|
-
// 检查是否已初始化
|
|
13
|
-
if (!isInitialized()) {
|
|
14
|
-
consola.error('Project not initialized. Please run `agentstage init` first.');
|
|
15
|
-
process.exit(1);
|
|
16
|
-
}
|
|
17
|
-
if (!/^[a-z0-9-]+$/.test(name)) {
|
|
18
|
-
consola.error('Page name must be lowercase letters, numbers, and hyphens');
|
|
19
|
-
process.exit(1);
|
|
20
|
-
}
|
|
21
|
-
try {
|
|
22
|
-
const workspaceDir = await getWorkspaceDir();
|
|
23
|
-
const config = await readRuntimeConfig();
|
|
24
|
-
const routesDir = join(workspaceDir, 'src', 'routes');
|
|
25
|
-
const pageFile = join(routesDir, `${name}.tsx`);
|
|
26
|
-
// 确保 routes 目录存在
|
|
27
|
-
await mkdir(routesDir, { recursive: true });
|
|
28
|
-
if (existsSync(pageFile)) {
|
|
29
|
-
consola.error(`Page "${name}" already exists at src/routes/${name}.tsx`);
|
|
30
|
-
process.exit(1);
|
|
31
|
-
}
|
|
32
|
-
const pageContent = `import { z } from 'zod';
|
|
33
|
-
import { createFileRoute } from '@tanstack/react-router';
|
|
34
|
-
import { createBridgeStore } from 'agent-stage-bridge/browser';
|
|
35
|
-
import { useEffect } from 'react';
|
|
36
|
-
import { Button } from '../components/ui/button';
|
|
37
|
-
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../components/ui/card';
|
|
38
|
-
|
|
39
|
-
// Define the page state schema
|
|
40
|
-
const StateSchema = z.object({
|
|
41
|
-
count: z.number().default(0),
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
type State = z.infer<typeof StateSchema>;
|
|
45
|
-
|
|
46
|
-
// Create the bridge store for this page
|
|
47
|
-
const bridgeStore = createBridgeStore<State, { increment: { payload?: number }; decrement: {} }>({
|
|
48
|
-
pageId: '${name}',
|
|
49
|
-
storeKey: 'main',
|
|
50
|
-
description: {
|
|
51
|
-
schema: StateSchema,
|
|
52
|
-
actions: {
|
|
53
|
-
increment: {
|
|
54
|
-
description: 'Increment the counter by a specified amount (default: 1)',
|
|
55
|
-
payload: z.number().optional(),
|
|
56
|
-
},
|
|
57
|
-
decrement: {
|
|
58
|
-
description: 'Decrement the counter by 1',
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
createState: (set) => ({
|
|
63
|
-
count: 0,
|
|
64
|
-
dispatch: (action) => {
|
|
65
|
-
switch (action.type) {
|
|
66
|
-
case 'increment':
|
|
67
|
-
set((state) => ({ count: state.count + (action.payload ?? 1) }));
|
|
68
|
-
break;
|
|
69
|
-
case 'decrement':
|
|
70
|
-
set((state) => ({ count: state.count - 1 }));
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
}),
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
export const Route = createFileRoute('/${name}')({
|
|
78
|
-
component: ${toPascalCase(name)}Page,
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
function ${toPascalCase(name)}Page() {
|
|
82
|
-
// Connect to the bridge when the component mounts
|
|
83
|
-
useEffect(() => {
|
|
84
|
-
bridgeStore.connect().catch(console.error);
|
|
85
|
-
}, []);
|
|
86
|
-
|
|
87
|
-
return (
|
|
88
|
-
<div className="min-h-screen bg-background p-8">
|
|
89
|
-
<div className="mx-auto max-w-2xl">
|
|
90
|
-
<Card>
|
|
91
|
-
<CardHeader>
|
|
92
|
-
<CardTitle>${toTitleCase(name)}</CardTitle>
|
|
93
|
-
<CardDescription>
|
|
94
|
-
This page is connected to the Agentstage Bridge.
|
|
95
|
-
</CardDescription>
|
|
96
|
-
</CardHeader>
|
|
97
|
-
<CardContent className="space-y-4">
|
|
98
|
-
<p className="text-sm text-muted-foreground">
|
|
99
|
-
Edit this page at src/routes/${name}.tsx
|
|
100
|
-
</p>
|
|
101
|
-
<div className="flex gap-2">
|
|
102
|
-
<Button variant="outline">Action 1</Button>
|
|
103
|
-
<Button>Action 2</Button>
|
|
104
|
-
</div>
|
|
105
|
-
</CardContent>
|
|
106
|
-
</Card>
|
|
107
|
-
</div>
|
|
108
|
-
</div>
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
`;
|
|
112
|
-
await writeFile(pageFile, pageContent);
|
|
113
|
-
consola.success(`Page "${name}" created`);
|
|
114
|
-
console.log(` File: ${c.cyan(`src/routes/${name}.tsx`)}`);
|
|
115
|
-
const port = config?.port || 3000;
|
|
116
|
-
console.log(` URL: ${c.cyan(`http://localhost:${port}/${name}`)}`);
|
|
117
|
-
console.log(` Route: ${c.gray(`/${name}`)} (file-based, auto-registered by TanStack Router)`);
|
|
118
|
-
console.log();
|
|
119
|
-
console.log(` The route is automatically registered by TanStack Router.`);
|
|
120
|
-
console.log(` No manual route configuration needed!`);
|
|
121
|
-
}
|
|
122
|
-
catch (error) {
|
|
123
|
-
consola.error('Failed to create page:', error.message);
|
|
124
|
-
process.exit(1);
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
function toPascalCase(str) {
|
|
128
|
-
return str.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('');
|
|
129
|
-
}
|
|
130
|
-
function toTitleCase(str) {
|
|
131
|
-
return str.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
|
|
132
|
-
}
|
package/dist/commands/reset.d.ts
DELETED