vibepulse 0.1.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/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # VibePulse
2
+
3
+ Real-time dashboard for monitoring and managing OpenCode sessions.
4
+
5
+ ![VibePulse README cover](./public/readme-cover.png)
6
+
7
+ ## Features
8
+
9
+ ### Session Management
10
+ - **Real-time sync** — Automatically syncs OpenCode sessions via SSE + polling
11
+ - **4-column board** — Idle, Busy, Review, Done
12
+ - **Drag & drop** — Reorder cards within columns
13
+ - **IDE integration** — Click to open workspace in VSCode / Antigravity
14
+ - **Audio notifications** — Sound alerts when sessions complete or need attention
15
+ - **Process hints** — Detects OpenCode processes without exposed API ports
16
+ - **Offline snapshot** — Displays last known state when OpenCode is unreachable
17
+ - **Auto-generated cards** — No manual card creation needed
18
+
19
+ ### Configuration Management (New)
20
+ - **Profile System** — Create and manage multiple configuration profiles for different workflows
21
+ - Built-in profiles (e.g., "Balanced") with optimized agent/category configurations
22
+ - Custom profiles with user-defined settings
23
+ - One-click profile switching
24
+ - **Reset to Profile** — After applying a profile, if you modify configs elsewhere, click "Reset" to restore the profile's original values (with confirmation dialog)
25
+ - **Agent Configuration** — Configure models, temperature, and other parameters for each agent (sisyphus, oracle, librarian, etc.)
26
+ - **Category Configuration** — Set up model preferences for different task categories (visual-engineering, ultrabrain, deep, quick, etc.)
27
+ - **Model Selector** — Smart model selection with grouped providers and search; shows error state with retry button if model fetch fails
28
+
29
+ ## Tech Stack
30
+
31
+ - Next.js (App Router)
32
+ - TypeScript
33
+ - Tailwind CSS
34
+ - @dnd-kit (drag and drop)
35
+ - TanStack Query (state management)
36
+ - @opencode-ai/sdk
37
+
38
+ ## Getting Started
39
+
40
+ ### Quick Start (npx)
41
+
42
+ ```bash
43
+ # Run directly without installing
44
+ npx vibepulse
45
+
46
+ # Or specify a custom port
47
+ PORT=8080 npx vibepulse
48
+ ```
49
+
50
+ Open [http://localhost:3456](http://localhost:3456)
51
+
52
+ ### Development
53
+
54
+ ```bash
55
+ # Install dependencies
56
+ npm install
57
+
58
+ # Make sure OpenCode is running locally, then:
59
+ npm run dev
60
+
61
+ # Or specify a custom port
62
+ PORT=8080 npm run dev
63
+ ```
64
+
65
+ Open [http://localhost:3456](http://localhost:3456) (default port: 3456)
66
+
67
+ ## Architecture
68
+
69
+ ```
70
+ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
71
+ │ Browser │────▶│ Next.js │────▶│ OpenCode │
72
+ │ │◀────│ API │◀────│ SDK │
73
+ └─────────────┘ └─────────────┘ └─────────────┘
74
+ │ │
75
+ └───────────────────┘
76
+ SSE Events (real-time)
77
+ ```
78
+
79
+ 📖 **Session Status Detection**: See [docs/session-status-detection.md](./docs/session-status-detection.md) for detailed explanation of how session statuses are detected, including the sticky state mechanism and detection limitations.
80
+
81
+ ## How It Works
82
+
83
+ ### Session Management
84
+ 1. Discovers OpenCode instances via port scanning and process detection
85
+ 2. Fetches sessions from OpenCode SDK with 5-second polling
86
+ 3. SSE connection provides real-time updates for immediate feedback
87
+ 4. Multi-layer status detection (see [docs/session-status-detection.md](./docs/session-status-detection.md)):
88
+ - Analyzes message part states (running/completed/waiting)
89
+ - Applies sticky state buffering to prevent flickering
90
+ - Cascades child session status to parent sessions
91
+ 5. Cards are auto-generated and organized into kanban columns
92
+
93
+ ### Configuration Management
94
+ 1. **Profiles** are stored in `~/.config/opencode/profiles/`
95
+ 2. **Applying a Profile** overwrites your current agent and category configurations
96
+ 3. **Reset Functionality** — When a profile shows "Reset" button:
97
+ - The profile was previously applied but configs have been modified
98
+ - Click "Reset" and confirm to restore the profile's original values
99
+ 4. **Model Fetching** — Models are fetched from `opencode models` CLI command; if it fails, an error state is shown with a retry button (no fallback models)
100
+
101
+ ## Troubleshooting
102
+
103
+ ### Configuration Management
104
+
105
+ #### Models not loading / "Failed to fetch models" error
106
+ - Ensure `opencode` CLI is installed and available in your PATH
107
+ - Check that `~/.opencode/bin` is in your PATH
108
+ - Click the **Retry** button in the model selector to attempt fetching again
109
+ - Run `opencode models` in your terminal to verify CLI is working
110
+
111
+ #### Profile Reset not working
112
+ - Make sure the profile was previously applied (shows "Reset" button instead of "Apply")
113
+ - The reset requires confirmation — check that you clicked "Reset" in the confirmation dialog
114
+ - If configs still don't reset, try re-applying the profile from the profile list
115
+
116
+ #### Board shows "No sessions found"
117
+ - Ensure OpenCode is running locally
118
+ - Check that the SDK can connect (port conflicts)
119
+ - Look for the ℹ️ icon in the header for process hints
120
+
121
+ ### Session status flickers or seems inaccurate
122
+ - This is a known limitation due to sparse OpenCode status signals
123
+ - See [docs/session-status-detection.md](./docs/session-status-detection.md) for detailed explanation
124
+ - The board uses 25-second sticky buffering to reduce flickering
125
+
126
+ ### IDE doesn't open
127
+ - Make sure VSCode / Antigravity is installed
128
+ - Check that the corresponding protocol handler is registered (e.g. `vscode://`)
129
+
130
+ ### Prevent VSCode from replacing an existing window
131
+
132
+ Open VSCode Settings (JSON) and add:
133
+
134
+ ```json
135
+ "window.openFoldersInNewWindow": "on"
136
+ ```
137
+
138
+ ## Known Limitations
139
+
140
+ - Single user only (no collaboration)
141
+ - Card positions stored in LocalStorage only
142
+ - Cannot focus specific IDE window (opens workspace)
143
+ - No manual card creation/editing
144
+ - Session status detection has inherent limitations (see [docs/session-status-detection.md](./docs/session-status-detection.md))
145
+
146
+ ## License
147
+
148
+ MIT
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawn } = require('child_process');
4
+ const path = require('path');
5
+ const fs = require('fs');
6
+
7
+ const port = process.env.PORT || '3456';
8
+
9
+ console.log(`🚀 Starting VibePulse on port ${port}...`);
10
+ console.log(`📊 Open http://localhost:${port} to view the dashboard`);
11
+ console.log('');
12
+
13
+ // Try to find next binary
14
+ let nextBin;
15
+ const possiblePaths = [
16
+ // Local development
17
+ path.join(__dirname, '..', 'node_modules', '.bin', 'next'),
18
+ // Global install
19
+ path.join(__dirname, '..', '..', '.bin', 'next'),
20
+ ];
21
+
22
+ for (const p of possiblePaths) {
23
+ if (fs.existsSync(p)) {
24
+ nextBin = p;
25
+ break;
26
+ }
27
+ }
28
+
29
+ if (!nextBin) {
30
+ // Try using npx
31
+ nextBin = 'npx';
32
+ }
33
+
34
+ const args = nextBin === 'npx'
35
+ ? ['next', 'dev', '-p', port]
36
+ : ['dev', '-p', port];
37
+
38
+ const proc = spawn(nextBin, args, {
39
+ cwd: path.join(__dirname, '..'),
40
+ stdio: 'inherit',
41
+ env: {
42
+ ...process.env,
43
+ PORT: port
44
+ }
45
+ });
46
+
47
+ proc.on('error', (err) => {
48
+ console.error('Failed to start VibePulse:', err.message);
49
+ console.error('\nMake sure you have Next.js installed:');
50
+ console.error(' npm install next');
51
+ process.exit(1);
52
+ });
53
+
54
+ proc.on('exit', (code) => {
55
+ process.exit(code);
56
+ });
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Agent configuration - defines how an agent behaves
3
+ * All fields are optional as configuration may be partial
4
+ */
5
+ interface AgentConfig {
6
+ /** Model identifier (e.g., 'claude-3-5-sonnet-20241022') */
7
+ model?: string;
8
+ /** Sampling temperature (0-2) */
9
+ temperature?: number;
10
+ /** Top-p sampling parameter (0-1) */
11
+ top_p?: number;
12
+ /** Maximum tokens per response */
13
+ max_tokens?: number;
14
+ /** System prompt override for this agent */
15
+ system?: string;
16
+ /** Additional model-specific parameters */
17
+ [key: string]: unknown;
18
+ }
19
+ /**
20
+ * Category configuration - defines model settings for task categories
21
+ * Categories are used by task() to select appropriate models
22
+ * All fields are optional as configuration may be partial
23
+ */
24
+ interface CategoryConfig {
25
+ /** Model identifier (e.g., 'google/gemini-3.1-pro') */
26
+ model?: string;
27
+ /** Model variant (e.g., 'max', 'high', 'medium', 'low', 'xhigh') */
28
+ variant?: string;
29
+ /** Sampling temperature (0-2) */
30
+ temperature?: number;
31
+ /** Top-p sampling parameter (0-1) */
32
+ top_p?: number;
33
+ /** Additional system prompt to append */
34
+ prompt_append?: string;
35
+ /** Human-readable description */
36
+ description?: string;
37
+ }
38
+ /**
39
+ * OhMyOpencode configuration
40
+ * Root configuration object for oh-my-opencode
41
+ * All fields are optional as configuration may be partial
42
+ */
43
+ interface OhMyOpencodeConfig {
44
+ /** Global agent configurations keyed by agent name */
45
+ agents?: Record<string, AgentConfig>;
46
+ /** Category configurations for task type model selection */
47
+ categories?: Record<string, CategoryConfig>;
48
+ /** Default agent configuration to use as base */
49
+ defaultAgent?: AgentConfig;
50
+ /** Project-specific settings */
51
+ project?: {
52
+ /** Project name */
53
+ name?: string;
54
+ /** Working directory */
55
+ cwd?: string;
56
+ };
57
+ /** Runtime configuration */
58
+ runtime?: {
59
+ /** Enable/disable features */
60
+ features?: {
61
+ /** Enable auto-approval for safe operations */
62
+ autoApprove?: boolean;
63
+ /** Enable verbose logging */
64
+ verbose?: boolean;
65
+ /** Enable debug mode */
66
+ debug?: boolean;
67
+ };
68
+ /** Maximum retry attempts */
69
+ maxRetries?: number;
70
+ /** Request timeout in milliseconds */
71
+ timeout?: number;
72
+ };
73
+ /** Tool-specific configurations */
74
+ tools?: Record<string, unknown>;
75
+ /** Custom environment variables */
76
+ env?: Record<string, string>;
77
+ /** Additional custom configuration */
78
+ [key: string]: unknown;
79
+ }
80
+ /**
81
+ * Profile configuration - defines agent and category settings for a profile
82
+ * Profiles allow switching between different agent/category configurations
83
+ */
84
+ interface ProfileConfig {
85
+ /** Agent configurations keyed by agent name */
86
+ agents: Record<string, AgentConfig>;
87
+ /** Category configurations for task type model selection */
88
+ categories?: Record<string, CategoryConfig>;
89
+ }
90
+ /**
91
+ * Profile - represents a named configuration profile
92
+ * Profiles can be built-in or user-created
93
+ */
94
+ interface Profile {
95
+ /** Unique identifier */
96
+ id: string;
97
+ /** Human-readable name */
98
+ name: string;
99
+ /** Emoji icon for display */
100
+ emoji: string;
101
+ /** Optional description */
102
+ description?: string;
103
+ /** Creation timestamp */
104
+ createdAt: string;
105
+ /** Last update timestamp */
106
+ updatedAt: string;
107
+ /** Whether this is a default system profile */
108
+ isDefault?: boolean;
109
+ /** Whether this is a built-in profile that cannot be deleted */
110
+ isBuiltIn?: boolean;
111
+ }
112
+ /**
113
+ * Profile index - tracks all profiles and active selection
114
+ * This is the top-level structure for profile management
115
+ */
116
+ interface ProfileIndex {
117
+ /** Schema version for migrations */
118
+ version: number;
119
+ /** All available profiles */
120
+ profiles: Profile[];
121
+ /** Currently active profile ID */
122
+ activeProfileId: string | null;
123
+ /** Last modification timestamp */
124
+ lastModified: string;
125
+ }
126
+
127
+ declare const CONFIG_DIR: string;
128
+ declare const CONFIG_PATH: string;
129
+ type OpenCodeConfig = {
130
+ agents?: Record<string, unknown>;
131
+ [key: string]: unknown;
132
+ };
133
+ declare function detectConfig(configPath?: string): boolean;
134
+ declare function readConfig(configPath?: string): Promise<OpenCodeConfig>;
135
+ declare function writeConfig(config: OpenCodeConfig, configPath?: string): Promise<void>;
136
+
137
+ export { type AgentConfig, CONFIG_DIR, CONFIG_PATH, type CategoryConfig, type OhMyOpencodeConfig, type OpenCodeConfig, type Profile, type ProfileConfig, type ProfileIndex, detectConfig, readConfig, writeConfig };
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Agent configuration - defines how an agent behaves
3
+ * All fields are optional as configuration may be partial
4
+ */
5
+ interface AgentConfig {
6
+ /** Model identifier (e.g., 'claude-3-5-sonnet-20241022') */
7
+ model?: string;
8
+ /** Sampling temperature (0-2) */
9
+ temperature?: number;
10
+ /** Top-p sampling parameter (0-1) */
11
+ top_p?: number;
12
+ /** Maximum tokens per response */
13
+ max_tokens?: number;
14
+ /** System prompt override for this agent */
15
+ system?: string;
16
+ /** Additional model-specific parameters */
17
+ [key: string]: unknown;
18
+ }
19
+ /**
20
+ * Category configuration - defines model settings for task categories
21
+ * Categories are used by task() to select appropriate models
22
+ * All fields are optional as configuration may be partial
23
+ */
24
+ interface CategoryConfig {
25
+ /** Model identifier (e.g., 'google/gemini-3.1-pro') */
26
+ model?: string;
27
+ /** Model variant (e.g., 'max', 'high', 'medium', 'low', 'xhigh') */
28
+ variant?: string;
29
+ /** Sampling temperature (0-2) */
30
+ temperature?: number;
31
+ /** Top-p sampling parameter (0-1) */
32
+ top_p?: number;
33
+ /** Additional system prompt to append */
34
+ prompt_append?: string;
35
+ /** Human-readable description */
36
+ description?: string;
37
+ }
38
+ /**
39
+ * OhMyOpencode configuration
40
+ * Root configuration object for oh-my-opencode
41
+ * All fields are optional as configuration may be partial
42
+ */
43
+ interface OhMyOpencodeConfig {
44
+ /** Global agent configurations keyed by agent name */
45
+ agents?: Record<string, AgentConfig>;
46
+ /** Category configurations for task type model selection */
47
+ categories?: Record<string, CategoryConfig>;
48
+ /** Default agent configuration to use as base */
49
+ defaultAgent?: AgentConfig;
50
+ /** Project-specific settings */
51
+ project?: {
52
+ /** Project name */
53
+ name?: string;
54
+ /** Working directory */
55
+ cwd?: string;
56
+ };
57
+ /** Runtime configuration */
58
+ runtime?: {
59
+ /** Enable/disable features */
60
+ features?: {
61
+ /** Enable auto-approval for safe operations */
62
+ autoApprove?: boolean;
63
+ /** Enable verbose logging */
64
+ verbose?: boolean;
65
+ /** Enable debug mode */
66
+ debug?: boolean;
67
+ };
68
+ /** Maximum retry attempts */
69
+ maxRetries?: number;
70
+ /** Request timeout in milliseconds */
71
+ timeout?: number;
72
+ };
73
+ /** Tool-specific configurations */
74
+ tools?: Record<string, unknown>;
75
+ /** Custom environment variables */
76
+ env?: Record<string, string>;
77
+ /** Additional custom configuration */
78
+ [key: string]: unknown;
79
+ }
80
+ /**
81
+ * Profile configuration - defines agent and category settings for a profile
82
+ * Profiles allow switching between different agent/category configurations
83
+ */
84
+ interface ProfileConfig {
85
+ /** Agent configurations keyed by agent name */
86
+ agents: Record<string, AgentConfig>;
87
+ /** Category configurations for task type model selection */
88
+ categories?: Record<string, CategoryConfig>;
89
+ }
90
+ /**
91
+ * Profile - represents a named configuration profile
92
+ * Profiles can be built-in or user-created
93
+ */
94
+ interface Profile {
95
+ /** Unique identifier */
96
+ id: string;
97
+ /** Human-readable name */
98
+ name: string;
99
+ /** Emoji icon for display */
100
+ emoji: string;
101
+ /** Optional description */
102
+ description?: string;
103
+ /** Creation timestamp */
104
+ createdAt: string;
105
+ /** Last update timestamp */
106
+ updatedAt: string;
107
+ /** Whether this is a default system profile */
108
+ isDefault?: boolean;
109
+ /** Whether this is a built-in profile that cannot be deleted */
110
+ isBuiltIn?: boolean;
111
+ }
112
+ /**
113
+ * Profile index - tracks all profiles and active selection
114
+ * This is the top-level structure for profile management
115
+ */
116
+ interface ProfileIndex {
117
+ /** Schema version for migrations */
118
+ version: number;
119
+ /** All available profiles */
120
+ profiles: Profile[];
121
+ /** Currently active profile ID */
122
+ activeProfileId: string | null;
123
+ /** Last modification timestamp */
124
+ lastModified: string;
125
+ }
126
+
127
+ declare const CONFIG_DIR: string;
128
+ declare const CONFIG_PATH: string;
129
+ type OpenCodeConfig = {
130
+ agents?: Record<string, unknown>;
131
+ [key: string]: unknown;
132
+ };
133
+ declare function detectConfig(configPath?: string): boolean;
134
+ declare function readConfig(configPath?: string): Promise<OpenCodeConfig>;
135
+ declare function writeConfig(config: OpenCodeConfig, configPath?: string): Promise<void>;
136
+
137
+ export { type AgentConfig, CONFIG_DIR, CONFIG_PATH, type CategoryConfig, type OhMyOpencodeConfig, type OpenCodeConfig, type Profile, type ProfileConfig, type ProfileIndex, detectConfig, readConfig, writeConfig };
package/dist/index.js ADDED
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ CONFIG_DIR: () => CONFIG_DIR,
24
+ CONFIG_PATH: () => CONFIG_PATH,
25
+ detectConfig: () => detectConfig,
26
+ readConfig: () => readConfig,
27
+ writeConfig: () => writeConfig
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/lib/opencodeConfig.ts
32
+ var import_promises = require("fs/promises");
33
+ var import_fs = require("fs");
34
+ var import_path = require("path");
35
+ var import_os = require("os");
36
+ var import_comment_json = require("comment-json");
37
+ var CONFIG_DIR = (0, import_path.join)((0, import_os.homedir)(), ".config", "opencode");
38
+ var CONFIG_PATH = (0, import_path.join)(CONFIG_DIR, "oh-my-opencode.json");
39
+ function detectConfig(configPath = CONFIG_PATH) {
40
+ try {
41
+ return (0, import_fs.existsSync)(configPath);
42
+ } catch {
43
+ return false;
44
+ }
45
+ }
46
+ async function readConfig(configPath = CONFIG_PATH) {
47
+ try {
48
+ const content = await (0, import_promises.readFile)(configPath, "utf-8");
49
+ const config = (0, import_comment_json.parse)(content, null, false);
50
+ return config;
51
+ } catch (error) {
52
+ return {};
53
+ }
54
+ }
55
+ async function writeConfig(config, configPath = CONFIG_PATH) {
56
+ try {
57
+ const configDir = (0, import_path.join)(configPath, "..");
58
+ if (!(0, import_fs.existsSync)(configDir)) {
59
+ (0, import_fs.mkdirSync)(configDir, { recursive: true });
60
+ }
61
+ const content = (0, import_comment_json.stringify)(config, null, 2);
62
+ await (0, import_promises.writeFile)(configPath, content, "utf-8");
63
+ } catch (error) {
64
+ throw new Error(`Failed to write config: ${error}`);
65
+ }
66
+ }
67
+ // Annotate the CommonJS export names for ESM import in node:
68
+ 0 && (module.exports = {
69
+ CONFIG_DIR,
70
+ CONFIG_PATH,
71
+ detectConfig,
72
+ readConfig,
73
+ writeConfig
74
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,43 @@
1
+ // src/lib/opencodeConfig.ts
2
+ import { readFile, writeFile } from "fs/promises";
3
+ import { existsSync, mkdirSync } from "fs";
4
+ import { join } from "path";
5
+ import { homedir } from "os";
6
+ import { parse, stringify } from "comment-json";
7
+ var CONFIG_DIR = join(homedir(), ".config", "opencode");
8
+ var CONFIG_PATH = join(CONFIG_DIR, "oh-my-opencode.json");
9
+ function detectConfig(configPath = CONFIG_PATH) {
10
+ try {
11
+ return existsSync(configPath);
12
+ } catch {
13
+ return false;
14
+ }
15
+ }
16
+ async function readConfig(configPath = CONFIG_PATH) {
17
+ try {
18
+ const content = await readFile(configPath, "utf-8");
19
+ const config = parse(content, null, false);
20
+ return config;
21
+ } catch (error) {
22
+ return {};
23
+ }
24
+ }
25
+ async function writeConfig(config, configPath = CONFIG_PATH) {
26
+ try {
27
+ const configDir = join(configPath, "..");
28
+ if (!existsSync(configDir)) {
29
+ mkdirSync(configDir, { recursive: true });
30
+ }
31
+ const content = stringify(config, null, 2);
32
+ await writeFile(configPath, content, "utf-8");
33
+ } catch (error) {
34
+ throw new Error(`Failed to write config: ${error}`);
35
+ }
36
+ }
37
+ export {
38
+ CONFIG_DIR,
39
+ CONFIG_PATH,
40
+ detectConfig,
41
+ readConfig,
42
+ writeConfig
43
+ };
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "vibepulse",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "description": "Real-time dashboard for monitoring and managing OpenCode sessions",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/ChatTreeNet/VibePulse"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "files": [
13
+ "dist",
14
+ "bin",
15
+ "README.md",
16
+ "LICENSE"
17
+ ],
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js",
22
+ "require": "./dist/index.cjs"
23
+ }
24
+ },
25
+ "peerDependencies": {
26
+ "next": ">=14.0.0",
27
+ "react": ">=18.0.0",
28
+ "react-dom": ">=18.0.0"
29
+ },
30
+ "peerDependenciesMeta": {
31
+ "next": {
32
+ "optional": true
33
+ }
34
+ },
35
+ "scripts": {
36
+ "dev": "next dev -p 3456",
37
+ "build": "next build",
38
+ "start": "next start -p 3456",
39
+ "lint": "eslint",
40
+ "test": "vitest",
41
+ "test:run": "vitest run",
42
+ "build:lib": "tsup src/index.ts --format cjs,esm --dts --clean --outDir dist --external react,react-dom,next --tsconfig tsconfig.lib.json"
43
+ },
44
+ "bin": {
45
+ "vibepulse": "./bin/vibepulse.js"
46
+ },
47
+ "dependencies": {
48
+ "@dnd-kit/core": "^6.3.1",
49
+ "@dnd-kit/sortable": "^10.0.0",
50
+ "@dnd-kit/utilities": "^3.2.2",
51
+ "@opencode-ai/sdk": "^1.2.15",
52
+ "@radix-ui/react-dialog": "^1.1.15",
53
+ "@radix-ui/react-select": "^2.2.6",
54
+ "@radix-ui/react-tabs": "^1.1.13",
55
+ "@tanstack/react-query": "^5.90.21",
56
+ "clsx": "^2.1.1",
57
+ "comment-json": "^4.6.2",
58
+ "lucide-react": "^0.575.0",
59
+ "react-hook-form": "^7.71.2",
60
+ "tailwind-merge": "^3.5.0"
61
+ },
62
+ "devDependencies": {
63
+ "@tailwindcss/postcss": "^4",
64
+ "@testing-library/dom": "^10.4.1",
65
+ "@testing-library/jest-dom": "^6.6.3",
66
+ "@testing-library/react": "^16.3.0",
67
+ "@testing-library/user-event": "^14.6.1",
68
+ "@types/node": "^20",
69
+ "@types/react": "^19",
70
+ "@types/react-dom": "^19",
71
+ "@vitejs/plugin-react": "^4.5.2",
72
+ "esbuild-plugin-alias": "^0.2.1",
73
+ "eslint": "^9",
74
+ "eslint-config-next": "16.1.6",
75
+ "jsdom": "^26.1.0",
76
+ "tailwindcss": "^4",
77
+ "tsup": "^8.5.1",
78
+ "typescript": "^5",
79
+ "vitest": "^3.2.4"
80
+ }
81
+ }