agent-stage 0.2.0
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/add-page.d.ts +2 -0
- package/dist/commands/add-page.js +132 -0
- package/dist/commands/components.d.ts +2 -0
- package/dist/commands/components.js +136 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +247 -0
- package/dist/commands/exec.d.ts +2 -0
- package/dist/commands/exec.js +59 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +208 -0
- package/dist/commands/inspect.d.ts +2 -0
- package/dist/commands/inspect.js +62 -0
- package/dist/commands/ls.d.ts +2 -0
- package/dist/commands/ls.js +84 -0
- package/dist/commands/reset.d.ts +2 -0
- package/dist/commands/reset.js +92 -0
- package/dist/commands/restart.d.ts +2 -0
- package/dist/commands/restart.js +90 -0
- package/dist/commands/rm-page.d.ts +2 -0
- package/dist/commands/rm-page.js +32 -0
- package/dist/commands/start.d.ts +2 -0
- package/dist/commands/start.js +82 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.js +52 -0
- package/dist/commands/stop.d.ts +2 -0
- package/dist/commands/stop.js +58 -0
- package/dist/commands/watch.d.ts +2 -0
- package/dist/commands/watch.js +54 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +48 -0
- package/dist/utils/paths.d.ts +45 -0
- package/dist/utils/paths.js +138 -0
- package/package.json +32 -0
- package/template/components.json +17 -0
- package/template/index.html +13 -0
- package/template/package.json +40 -0
- package/template/postcss.config.js +6 -0
- package/template/src/components/ui/button.tsx +55 -0
- package/template/src/components/ui/card.tsx +78 -0
- package/template/src/components/ui/input.tsx +24 -0
- package/template/src/index.css +59 -0
- package/template/src/lib/utils.ts +6 -0
- package/template/src/main.tsx +23 -0
- package/template/src/routes/__root.tsx +11 -0
- package/template/src/routes/index.tsx +46 -0
- package/template/src/vite-env.d.ts +1 -0
- package/template/tailwind.config.js +53 -0
- package/template/tsconfig.json +25 -0
- package/template/tsconfig.node.json +11 -0
- package/template/vite.config.ts +22 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import consola from 'consola';
|
|
3
|
+
import c from 'picocolors';
|
|
4
|
+
import { getWorkspaceDir, readRuntimeConfig, isInitialized } from '../utils/paths.js';
|
|
5
|
+
function isRunning(pid) {
|
|
6
|
+
try {
|
|
7
|
+
process.kill(pid, 0);
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export const statusCommand = new Command('status')
|
|
15
|
+
.description('Show the Agentstage Runtime status')
|
|
16
|
+
.action(async () => {
|
|
17
|
+
// 1. 检查是否已初始化
|
|
18
|
+
if (!isInitialized()) {
|
|
19
|
+
consola.error('Project not initialized. Please run `agentstage init` first.');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const workspaceDir = await getWorkspaceDir();
|
|
23
|
+
console.log();
|
|
24
|
+
console.log(c.bold('Agentstage Runtime'));
|
|
25
|
+
console.log(c.gray('─'.repeat(40)));
|
|
26
|
+
console.log(`Workspace: ${c.cyan(workspaceDir)}`);
|
|
27
|
+
// 2. 读取运行时配置
|
|
28
|
+
const config = await readRuntimeConfig();
|
|
29
|
+
if (!config) {
|
|
30
|
+
console.log(`Status: ${c.red('●')} Stopped`);
|
|
31
|
+
console.log();
|
|
32
|
+
console.log(c.gray('Run `agentstage start` to start the runtime.'));
|
|
33
|
+
console.log();
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
// 3. 检查进程是否存活
|
|
37
|
+
const running = isRunning(config.pid);
|
|
38
|
+
if (running) {
|
|
39
|
+
console.log(`Status: ${c.green('●')} Running`);
|
|
40
|
+
console.log(`PID: ${config.pid}`);
|
|
41
|
+
console.log(`Port: ${config.port}`);
|
|
42
|
+
console.log(`Started: ${new Date(config.startedAt).toLocaleString()}`);
|
|
43
|
+
console.log(`Web: ${c.cyan(`http://localhost:${config.port}`)}`);
|
|
44
|
+
console.log(`Bridge: ${c.cyan(`ws://localhost:${config.port}/_bridge`)}`);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.log(`Status: ${c.yellow('●')} Dead (PID file exists but process not found)`);
|
|
48
|
+
console.log();
|
|
49
|
+
console.log(c.gray('Run `agentstage start` to restart the runtime.'));
|
|
50
|
+
}
|
|
51
|
+
console.log();
|
|
52
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import consola from 'consola';
|
|
3
|
+
import { unlink } from 'fs/promises';
|
|
4
|
+
import { existsSync } from 'fs';
|
|
5
|
+
import { getPidFile, readRuntimeConfig, removeRuntimeConfig, isInitialized } from '../utils/paths.js';
|
|
6
|
+
async function killProcess(pid) {
|
|
7
|
+
try {
|
|
8
|
+
process.kill(pid, 'SIGTERM');
|
|
9
|
+
let attempts = 0;
|
|
10
|
+
while (attempts < 10) {
|
|
11
|
+
await new Promise(r => setTimeout(r, 500));
|
|
12
|
+
try {
|
|
13
|
+
process.kill(pid, 0);
|
|
14
|
+
attempts++;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (attempts >= 10) {
|
|
21
|
+
process.kill(pid, 'SIGKILL');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (error.code !== 'ESRCH')
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export const stopCommand = new Command('stop')
|
|
30
|
+
.description('Stop the Agentstage Runtime')
|
|
31
|
+
.action(async () => {
|
|
32
|
+
// 1. 检查是否已初始化
|
|
33
|
+
if (!isInitialized()) {
|
|
34
|
+
consola.error('Project not initialized. Please run `agentstage init` first.');
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
// 2. 读取运行时配置
|
|
38
|
+
const config = await readRuntimeConfig();
|
|
39
|
+
if (!config) {
|
|
40
|
+
consola.info('Runtime is not running');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// 3. 停止进程
|
|
44
|
+
try {
|
|
45
|
+
await killProcess(config.pid);
|
|
46
|
+
await removeRuntimeConfig();
|
|
47
|
+
// 兼容旧版本:删除 pid 文件
|
|
48
|
+
const pidFile = await getPidFile();
|
|
49
|
+
if (existsSync(pidFile)) {
|
|
50
|
+
await unlink(pidFile).catch(() => { });
|
|
51
|
+
}
|
|
52
|
+
consola.success('Runtime stopped');
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
consola.error('Failed to stop runtime:', error.message);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import consola from 'consola';
|
|
3
|
+
import c from 'picocolors';
|
|
4
|
+
import { BridgeClient } from 'agent-stage-bridge/sdk';
|
|
5
|
+
import { readRuntimeConfig, isInitialized } from '../utils/paths.js';
|
|
6
|
+
export const watchCommand = new Command('watch')
|
|
7
|
+
.description('Watch a page for real-time changes')
|
|
8
|
+
.argument('<page>', 'Page ID')
|
|
9
|
+
.action(async (pageId) => {
|
|
10
|
+
try {
|
|
11
|
+
// 1. 检查是否已初始化
|
|
12
|
+
if (!isInitialized()) {
|
|
13
|
+
consola.error('Project not initialized. Please run `agentstage init` first.');
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
// 2. 检查是否已启动
|
|
17
|
+
const config = await readRuntimeConfig();
|
|
18
|
+
if (!config) {
|
|
19
|
+
consola.error('Runtime is not running. Please run `agentstage start` first.');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const client = new BridgeClient(`ws://localhost:${config.port}/_bridge`);
|
|
23
|
+
client.onEvent((event) => {
|
|
24
|
+
const timestamp = new Date().toISOString();
|
|
25
|
+
console.log(c.gray(`[${timestamp}]`), event);
|
|
26
|
+
});
|
|
27
|
+
await client.connect();
|
|
28
|
+
// 查找并订阅所有该 page 的 stores
|
|
29
|
+
const stores = await client.listStores();
|
|
30
|
+
const pageStores = stores.filter(s => s.pageId === pageId);
|
|
31
|
+
if (pageStores.length === 0) {
|
|
32
|
+
consola.error(`Page "${pageId}" not found`);
|
|
33
|
+
client.disconnect();
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
for (const store of pageStores) {
|
|
37
|
+
client.subscribe(store.id);
|
|
38
|
+
}
|
|
39
|
+
consola.success(`Watching ${c.cyan(pageId)}. Press Ctrl+C to exit.`);
|
|
40
|
+
console.log();
|
|
41
|
+
// 保持运行
|
|
42
|
+
process.on('SIGINT', () => {
|
|
43
|
+
console.log();
|
|
44
|
+
consola.info('Stopped watching');
|
|
45
|
+
client.disconnect();
|
|
46
|
+
process.exit(0);
|
|
47
|
+
});
|
|
48
|
+
await new Promise(() => { });
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
consola.error('Failed to watch page:', error.message);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
});
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import consola from 'consola';
|
|
4
|
+
import { initCommand } from './commands/init.js';
|
|
5
|
+
import { startCommand } from './commands/start.js';
|
|
6
|
+
import { stopCommand } from './commands/stop.js';
|
|
7
|
+
import { restartCommand } from './commands/restart.js';
|
|
8
|
+
import { statusCommand } from './commands/status.js';
|
|
9
|
+
import { lsCommand } from './commands/ls.js';
|
|
10
|
+
import { inspectCommand } from './commands/inspect.js';
|
|
11
|
+
import { watchCommand } from './commands/watch.js';
|
|
12
|
+
import { execCommand } from './commands/exec.js';
|
|
13
|
+
import { addPageCommand } from './commands/add-page.js';
|
|
14
|
+
import { rmPageCommand } from './commands/rm-page.js';
|
|
15
|
+
import { componentsCommand } from './commands/components.js';
|
|
16
|
+
import { doctorCommand } from './commands/doctor.js';
|
|
17
|
+
import { resetCommand } from './commands/reset.js';
|
|
18
|
+
const program = new Command();
|
|
19
|
+
program
|
|
20
|
+
.name('agentstage')
|
|
21
|
+
.description('Agent UI Stage CLI - Create interactive UI for AI agents')
|
|
22
|
+
.version('0.2.0');
|
|
23
|
+
// 注册命令
|
|
24
|
+
program.addCommand(initCommand);
|
|
25
|
+
program.addCommand(startCommand);
|
|
26
|
+
program.addCommand(stopCommand);
|
|
27
|
+
program.addCommand(restartCommand);
|
|
28
|
+
program.addCommand(statusCommand);
|
|
29
|
+
program.addCommand(lsCommand);
|
|
30
|
+
program.addCommand(inspectCommand);
|
|
31
|
+
program.addCommand(watchCommand);
|
|
32
|
+
program.addCommand(execCommand);
|
|
33
|
+
program.addCommand(addPageCommand);
|
|
34
|
+
program.addCommand(rmPageCommand);
|
|
35
|
+
program.addCommand(componentsCommand);
|
|
36
|
+
program.addCommand(doctorCommand);
|
|
37
|
+
program.addCommand(resetCommand);
|
|
38
|
+
// 错误处理
|
|
39
|
+
program.exitOverride();
|
|
40
|
+
try {
|
|
41
|
+
await program.parseAsync(process.argv);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (error.code !== 'commander.help' && error.code !== 'commander.version') {
|
|
45
|
+
consola.error(error.message || 'Unknown error');
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export declare const CLI_CONFIG_DIR: string;
|
|
2
|
+
export declare const WORKSPACE_FILE: string;
|
|
3
|
+
export declare const DEFAULT_WORKSPACE: string;
|
|
4
|
+
/**
|
|
5
|
+
* 获取当前工作目录
|
|
6
|
+
*/
|
|
7
|
+
export declare function getWorkspaceDir(): Promise<string>;
|
|
8
|
+
/**
|
|
9
|
+
* 设置工作目录
|
|
10
|
+
*/
|
|
11
|
+
export declare function setWorkspaceDir(dir: string): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* 获取 PID 文件路径
|
|
14
|
+
*/
|
|
15
|
+
export declare function getPidFile(): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* 获取 pages 目录
|
|
18
|
+
*/
|
|
19
|
+
export declare function getPagesDir(): Promise<string>;
|
|
20
|
+
export declare function getRuntimeConfigFile(): Promise<string>;
|
|
21
|
+
export interface RuntimeConfig {
|
|
22
|
+
pid: number;
|
|
23
|
+
port: number;
|
|
24
|
+
startedAt: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 读取运行时配置
|
|
28
|
+
*/
|
|
29
|
+
export declare function readRuntimeConfig(): Promise<RuntimeConfig | null>;
|
|
30
|
+
/**
|
|
31
|
+
* 保存运行时配置
|
|
32
|
+
*/
|
|
33
|
+
export declare function saveRuntimeConfig(config: RuntimeConfig): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* 删除运行时配置
|
|
36
|
+
*/
|
|
37
|
+
export declare function removeRuntimeConfig(): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* 检查是否已初始化
|
|
40
|
+
*/
|
|
41
|
+
export declare function isInitialized(): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* 检查服务是否正在运行
|
|
44
|
+
*/
|
|
45
|
+
export declare function isRunning(): Promise<boolean>;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { join, resolve } from 'pathe';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { mkdir, readFile, writeFile } from 'fs/promises';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
// CLI 配置目录
|
|
6
|
+
export const CLI_CONFIG_DIR = join(homedir(), '.config', 'agentstage');
|
|
7
|
+
export const WORKSPACE_FILE = join(CLI_CONFIG_DIR, 'workspace');
|
|
8
|
+
// 默认工作目录
|
|
9
|
+
export const DEFAULT_WORKSPACE = join(homedir(), '.agentstage');
|
|
10
|
+
/**
|
|
11
|
+
* 获取当前工作目录
|
|
12
|
+
*/
|
|
13
|
+
export async function getWorkspaceDir() {
|
|
14
|
+
// 1. 从配置文件读取
|
|
15
|
+
try {
|
|
16
|
+
const workspace = await readFile(WORKSPACE_FILE, 'utf8');
|
|
17
|
+
if (workspace && existsSync(workspace.trim())) {
|
|
18
|
+
return workspace.trim();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// 配置文件不存在
|
|
23
|
+
}
|
|
24
|
+
// 2. 检查当前目录是否有 .agentstage
|
|
25
|
+
const currentDir = join(process.cwd(), '.agentstage');
|
|
26
|
+
if (existsSync(currentDir)) {
|
|
27
|
+
return currentDir;
|
|
28
|
+
}
|
|
29
|
+
// 3. 检查默认目录是否存在
|
|
30
|
+
if (existsSync(DEFAULT_WORKSPACE)) {
|
|
31
|
+
return DEFAULT_WORKSPACE;
|
|
32
|
+
}
|
|
33
|
+
// 4. 没有初始化
|
|
34
|
+
throw new Error('No workspace found. Run `agentstage init` first, or cd to a directory with .agentstage/');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 设置工作目录
|
|
38
|
+
*/
|
|
39
|
+
export async function setWorkspaceDir(dir) {
|
|
40
|
+
await mkdir(CLI_CONFIG_DIR, { recursive: true });
|
|
41
|
+
await writeFile(WORKSPACE_FILE, resolve(dir));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 获取 PID 文件路径
|
|
45
|
+
*/
|
|
46
|
+
export async function getPidFile() {
|
|
47
|
+
const workspace = await getWorkspaceDir();
|
|
48
|
+
return join(workspace, '.agentstage', 'pid');
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 获取 pages 目录
|
|
52
|
+
*/
|
|
53
|
+
export async function getPagesDir() {
|
|
54
|
+
const workspace = await getWorkspaceDir();
|
|
55
|
+
// Vite template structure
|
|
56
|
+
if (existsSync(join(workspace, 'src', 'pages'))) {
|
|
57
|
+
return join(workspace, 'src', 'pages');
|
|
58
|
+
}
|
|
59
|
+
// Legacy TanStack Start structure (for backwards compatibility)
|
|
60
|
+
if (existsSync(join(workspace, 'src', 'routes', 'pages'))) {
|
|
61
|
+
return join(workspace, 'src', 'routes', 'pages');
|
|
62
|
+
}
|
|
63
|
+
if (existsSync(join(workspace, 'app', 'routes', 'pages'))) {
|
|
64
|
+
return join(workspace, 'app', 'routes', 'pages');
|
|
65
|
+
}
|
|
66
|
+
throw new Error('Pages directory not found at src/pages');
|
|
67
|
+
}
|
|
68
|
+
// 运行时配置文件路径
|
|
69
|
+
export async function getRuntimeConfigFile() {
|
|
70
|
+
const workspace = await getWorkspaceDir();
|
|
71
|
+
return join(workspace, '.agentstage', 'runtime.json');
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 读取运行时配置
|
|
75
|
+
*/
|
|
76
|
+
export async function readRuntimeConfig() {
|
|
77
|
+
const configFile = await getRuntimeConfigFile();
|
|
78
|
+
if (!existsSync(configFile)) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const content = await readFile(configFile, 'utf8');
|
|
83
|
+
return JSON.parse(content);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* 保存运行时配置
|
|
91
|
+
*/
|
|
92
|
+
export async function saveRuntimeConfig(config) {
|
|
93
|
+
const configFile = await getRuntimeConfigFile();
|
|
94
|
+
await mkdir(join(configFile, '..'), { recursive: true });
|
|
95
|
+
await writeFile(configFile, JSON.stringify(config, null, 2));
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 删除运行时配置
|
|
99
|
+
*/
|
|
100
|
+
export async function removeRuntimeConfig() {
|
|
101
|
+
const configFile = await getRuntimeConfigFile();
|
|
102
|
+
if (existsSync(configFile)) {
|
|
103
|
+
await writeFile(configFile, ''); // 清空而不是删除,便于检查
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* 检查是否已初始化
|
|
108
|
+
*/
|
|
109
|
+
export function isInitialized() {
|
|
110
|
+
// 检查配置文件是否存在
|
|
111
|
+
if (!existsSync(WORKSPACE_FILE)) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
const workspace = readFileSync(WORKSPACE_FILE, 'utf8');
|
|
116
|
+
// 检查工作目录是否有 package.json(项目标志)
|
|
117
|
+
return existsSync(join(workspace.trim(), 'package.json'));
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* 检查服务是否正在运行
|
|
125
|
+
*/
|
|
126
|
+
export async function isRunning() {
|
|
127
|
+
const config = await readRuntimeConfig();
|
|
128
|
+
if (!config)
|
|
129
|
+
return false;
|
|
130
|
+
try {
|
|
131
|
+
process.kill(config.pid, 0);
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
import { readFileSync } from 'fs';
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-stage",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"files": ["dist", "template"],
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"agent-stage": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "tsx src/index.ts",
|
|
11
|
+
"build": "rimraf dist && tsc -p tsconfig.build.json",
|
|
12
|
+
"typecheck": "pnpm -C ../bridge build && tsc -p tsconfig.json --noEmit"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"agent-stage-bridge": "^0.1.0",
|
|
16
|
+
"@clack/prompts": "^0.8.2",
|
|
17
|
+
"commander": "^12.1.0",
|
|
18
|
+
"consola": "^3.2.3",
|
|
19
|
+
"execa": "^9.3.1",
|
|
20
|
+
"pathe": "^1.1.2",
|
|
21
|
+
"picocolors": "^1.1.1"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^22.13.5",
|
|
25
|
+
"rimraf": "^6.0.1",
|
|
26
|
+
"tsx": "^4.21.0",
|
|
27
|
+
"typescript": "^5.8.2"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "default",
|
|
4
|
+
"rsc": false,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "tailwind.config.js",
|
|
8
|
+
"css": "src/index.css",
|
|
9
|
+
"baseColor": "neutral",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
13
|
+
"aliases": {
|
|
14
|
+
"components": "@/components",
|
|
15
|
+
"utils": "@/lib/utils"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Agentstage App</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="root"></div>
|
|
11
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agentstage-app",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "tsc && vite build",
|
|
9
|
+
"preview": "vite preview",
|
|
10
|
+
"type-check": "tsc --noEmit"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"react": "^18.2.0",
|
|
14
|
+
"react-dom": "^18.2.0",
|
|
15
|
+
"@tanstack/react-router": "^1.114.3",
|
|
16
|
+
"@tanstack/router-core": "^1.114.3",
|
|
17
|
+
"@tanstack/router-devtools": "^1.114.3",
|
|
18
|
+
"agent-stage-bridge": "workspace:*",
|
|
19
|
+
"class-variance-authority": "^0.7.0",
|
|
20
|
+
"clsx": "^2.1.0",
|
|
21
|
+
"tailwind-merge": "^2.2.0",
|
|
22
|
+
"tailwindcss-animate": "^1.0.7",
|
|
23
|
+
"lucide-react": "^0.300.0",
|
|
24
|
+
"zod": "^3.23.0",
|
|
25
|
+
"zustand": "^4.5.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/react": "^18.2.43",
|
|
29
|
+
"@types/react-dom": "^18.2.17",
|
|
30
|
+
"@radix-ui/react-slot": "^1.0.2",
|
|
31
|
+
"@tanstack/router-generator": "^1.114.3",
|
|
32
|
+
"@tanstack/router-plugin": "^1.114.3",
|
|
33
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
34
|
+
"autoprefixer": "^10.4.17",
|
|
35
|
+
"postcss": "^8.4.33",
|
|
36
|
+
"tailwindcss": "^3.4.1",
|
|
37
|
+
"typescript": "^5.2.2",
|
|
38
|
+
"vite": "^5.0.8"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
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 }
|
|
@@ -0,0 +1,78 @@
|
|
|
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 }
|
|
@@ -0,0 +1,24 @@
|
|
|
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 }
|