clawport-ui 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/.env.example +35 -0
- package/BRANDING.md +131 -0
- package/CLAUDE.md +252 -0
- package/README.md +262 -0
- package/SETUP.md +337 -0
- package/app/agents/[id]/page.tsx +727 -0
- package/app/api/agents/route.ts +12 -0
- package/app/api/chat/[id]/route.ts +139 -0
- package/app/api/cron-runs/route.ts +13 -0
- package/app/api/crons/route.ts +12 -0
- package/app/api/kanban/chat/[id]/route.ts +119 -0
- package/app/api/kanban/chat-history/[ticketId]/route.ts +36 -0
- package/app/api/memory/route.ts +12 -0
- package/app/api/transcribe/route.ts +37 -0
- package/app/api/tts/route.ts +42 -0
- package/app/chat/[id]/page.tsx +10 -0
- package/app/chat/page.tsx +200 -0
- package/app/crons/page.tsx +870 -0
- package/app/docs/page.tsx +399 -0
- package/app/favicon.ico +0 -0
- package/app/globals.css +692 -0
- package/app/kanban/page.tsx +327 -0
- package/app/layout.tsx +45 -0
- package/app/memory/page.tsx +685 -0
- package/app/page.tsx +817 -0
- package/app/providers.tsx +37 -0
- package/app/settings/page.tsx +901 -0
- package/app/settings-provider.tsx +209 -0
- package/components/AgentAvatar.tsx +54 -0
- package/components/AgentNode.tsx +122 -0
- package/components/Breadcrumbs.tsx +126 -0
- package/components/DynamicFavicon.tsx +62 -0
- package/components/ErrorState.tsx +97 -0
- package/components/FeedView.tsx +494 -0
- package/components/GlobalSearch.tsx +571 -0
- package/components/GridView.tsx +532 -0
- package/components/ManorMap.tsx +157 -0
- package/components/MobileSidebar.tsx +251 -0
- package/components/NavLinks.tsx +271 -0
- package/components/OnboardingWizard.tsx +1067 -0
- package/components/Sidebar.tsx +115 -0
- package/components/ThemeToggle.tsx +108 -0
- package/components/chat/AgentList.tsx +537 -0
- package/components/chat/ConversationView.tsx +1047 -0
- package/components/chat/FileAttachment.tsx +140 -0
- package/components/chat/MediaPreview.tsx +111 -0
- package/components/chat/VoiceMessage.tsx +139 -0
- package/components/crons/PipelineGraph.tsx +327 -0
- package/components/crons/WeeklySchedule.tsx +630 -0
- package/components/docs/AgentsSection.tsx +209 -0
- package/components/docs/ApiReferenceSection.tsx +256 -0
- package/components/docs/ArchitectureSection.tsx +221 -0
- package/components/docs/ComponentsSection.tsx +253 -0
- package/components/docs/CronSystemSection.tsx +235 -0
- package/components/docs/DocSection.tsx +346 -0
- package/components/docs/GettingStartedSection.tsx +169 -0
- package/components/docs/ThemingSection.tsx +257 -0
- package/components/docs/TroubleshootingSection.tsx +200 -0
- package/components/kanban/AgentPicker.tsx +321 -0
- package/components/kanban/CreateTicketModal.tsx +333 -0
- package/components/kanban/KanbanBoard.tsx +70 -0
- package/components/kanban/KanbanColumn.tsx +166 -0
- package/components/kanban/TicketCard.tsx +245 -0
- package/components/kanban/TicketDetailPanel.tsx +850 -0
- package/components/ui/badge.tsx +48 -0
- package/components/ui/button.tsx +64 -0
- package/components/ui/card.tsx +92 -0
- package/components/ui/dialog.tsx +158 -0
- package/components/ui/scroll-area.tsx +58 -0
- package/components/ui/separator.tsx +28 -0
- package/components/ui/skeleton.tsx +27 -0
- package/components/ui/tabs.tsx +91 -0
- package/components/ui/tooltip.tsx +57 -0
- package/components.json +23 -0
- package/docs/API.md +648 -0
- package/docs/COMPONENTS.md +1059 -0
- package/docs/THEMING.md +795 -0
- package/lib/agents-registry.ts +35 -0
- package/lib/agents.json +282 -0
- package/lib/agents.test.ts +367 -0
- package/lib/agents.ts +32 -0
- package/lib/anthropic.test.ts +422 -0
- package/lib/anthropic.ts +220 -0
- package/lib/api-error.ts +16 -0
- package/lib/audio-recorder.test.ts +72 -0
- package/lib/audio-recorder.ts +169 -0
- package/lib/conversations.test.ts +331 -0
- package/lib/conversations.ts +117 -0
- package/lib/cron-pipelines.test.ts +69 -0
- package/lib/cron-pipelines.ts +58 -0
- package/lib/cron-runs.test.ts +118 -0
- package/lib/cron-runs.ts +67 -0
- package/lib/cron-utils.test.ts +222 -0
- package/lib/cron-utils.ts +160 -0
- package/lib/crons.test.ts +502 -0
- package/lib/crons.ts +114 -0
- package/lib/env.test.ts +44 -0
- package/lib/env.ts +14 -0
- package/lib/kanban/automation.test.ts +245 -0
- package/lib/kanban/automation.ts +143 -0
- package/lib/kanban/chat-store.test.ts +149 -0
- package/lib/kanban/chat-store.ts +81 -0
- package/lib/kanban/store.test.ts +238 -0
- package/lib/kanban/store.ts +98 -0
- package/lib/kanban/types.ts +50 -0
- package/lib/kanban/useAgentWork.ts +78 -0
- package/lib/memory.ts +45 -0
- package/lib/multimodal.test.ts +219 -0
- package/lib/multimodal.ts +68 -0
- package/lib/pipeline.integration.test.ts +343 -0
- package/lib/sanitize.ts +194 -0
- package/lib/settings.test.ts +137 -0
- package/lib/settings.ts +94 -0
- package/lib/styles.ts +24 -0
- package/lib/themes.ts +9 -0
- package/lib/transcribe.test.ts +141 -0
- package/lib/transcribe.ts +111 -0
- package/lib/types.ts +66 -0
- package/lib/utils.ts +6 -0
- package/lib/validation.test.ts +132 -0
- package/lib/validation.ts +80 -0
- package/next.config.ts +7 -0
- package/package.json +56 -0
- package/postcss.config.mjs +7 -0
- package/public/file.svg +1 -0
- package/public/globe.svg +1 -0
- package/public/next.svg +1 -0
- package/public/vercel.svg +1 -0
- package/public/window.svg +1 -0
- package/scripts/setup.mjs +215 -0
- package/tsconfig.json +34 -0
- package/vitest.config.ts +17 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// ClawPort -- Auto-detect environment and write .env.local
|
|
4
|
+
// Usage: npm run setup
|
|
5
|
+
|
|
6
|
+
import { execSync } from 'node:child_process'
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync } from 'node:fs'
|
|
8
|
+
import { resolve, join } from 'node:path'
|
|
9
|
+
import { createInterface } from 'node:readline'
|
|
10
|
+
import { homedir } from 'node:os'
|
|
11
|
+
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Helpers
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
const green = (s) => `\x1b[32m${s}\x1b[0m`
|
|
17
|
+
const yellow = (s) => `\x1b[33m${s}\x1b[0m`
|
|
18
|
+
const red = (s) => `\x1b[31m${s}\x1b[0m`
|
|
19
|
+
const dim = (s) => `\x1b[2m${s}\x1b[0m`
|
|
20
|
+
const bold = (s) => `\x1b[1m${s}\x1b[0m`
|
|
21
|
+
|
|
22
|
+
function ask(question) {
|
|
23
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout })
|
|
24
|
+
return new Promise((resolve) => {
|
|
25
|
+
rl.question(question, (answer) => {
|
|
26
|
+
rl.close()
|
|
27
|
+
resolve(answer.trim())
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function exec(cmd) {
|
|
33
|
+
try {
|
|
34
|
+
return execSync(cmd, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim()
|
|
35
|
+
} catch {
|
|
36
|
+
return null
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Detectors
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
function detectWorkspacePath() {
|
|
45
|
+
const defaultPath = join(homedir(), '.openclaw', 'workspace')
|
|
46
|
+
if (existsSync(defaultPath)) return defaultPath
|
|
47
|
+
return null
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function detectOpenClawBin() {
|
|
51
|
+
return exec('which openclaw')
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function detectGatewayToken() {
|
|
55
|
+
const configPath = join(homedir(), '.openclaw', 'openclaw.json')
|
|
56
|
+
if (!existsSync(configPath)) return null
|
|
57
|
+
try {
|
|
58
|
+
const config = JSON.parse(readFileSync(configPath, 'utf-8'))
|
|
59
|
+
const token = config?.gateway?.auth?.token
|
|
60
|
+
return typeof token === 'string' ? token : null
|
|
61
|
+
} catch {
|
|
62
|
+
return null
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function checkGatewayRunning() {
|
|
67
|
+
const result = exec('curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:18789/ 2>/dev/null')
|
|
68
|
+
return result && result !== '000'
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// Main
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
async function main() {
|
|
76
|
+
console.log()
|
|
77
|
+
console.log(bold(' ClawPort Setup'))
|
|
78
|
+
console.log(dim(' Auto-detecting your OpenClaw configuration...\n'))
|
|
79
|
+
|
|
80
|
+
// Detect all values
|
|
81
|
+
const detected = {
|
|
82
|
+
WORKSPACE_PATH: detectWorkspacePath(),
|
|
83
|
+
OPENCLAW_BIN: detectOpenClawBin(),
|
|
84
|
+
OPENCLAW_GATEWAY_TOKEN: detectGatewayToken(),
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const gatewayUp = checkGatewayRunning()
|
|
88
|
+
|
|
89
|
+
// Report findings
|
|
90
|
+
const entries = [
|
|
91
|
+
['WORKSPACE_PATH', detected.WORKSPACE_PATH],
|
|
92
|
+
['OPENCLAW_BIN', detected.OPENCLAW_BIN],
|
|
93
|
+
['OPENCLAW_GATEWAY_TOKEN', detected.OPENCLAW_GATEWAY_TOKEN],
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
let allFound = true
|
|
97
|
+
for (const [name, value] of entries) {
|
|
98
|
+
if (value) {
|
|
99
|
+
const display = name === 'OPENCLAW_GATEWAY_TOKEN'
|
|
100
|
+
? value.slice(0, 8) + '...' + value.slice(-4)
|
|
101
|
+
: value
|
|
102
|
+
console.log(` ${green('+')} ${bold(name)}`)
|
|
103
|
+
console.log(` ${dim(display)}`)
|
|
104
|
+
} else {
|
|
105
|
+
allFound = false
|
|
106
|
+
console.log(` ${red('x')} ${bold(name)}`)
|
|
107
|
+
console.log(` ${red('Not found')}`)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Gateway status
|
|
112
|
+
console.log()
|
|
113
|
+
if (gatewayUp) {
|
|
114
|
+
console.log(` ${green('+')} Gateway running at ${dim('localhost:18789')}`)
|
|
115
|
+
} else {
|
|
116
|
+
console.log(` ${yellow('!')} Gateway not responding at localhost:18789`)
|
|
117
|
+
console.log(` ${dim('Start it with: openclaw gateway run')}`)
|
|
118
|
+
}
|
|
119
|
+
console.log()
|
|
120
|
+
|
|
121
|
+
// Handle missing values
|
|
122
|
+
const final = { ...detected }
|
|
123
|
+
|
|
124
|
+
if (!final.WORKSPACE_PATH) {
|
|
125
|
+
const answer = await ask(` ${yellow('?')} Enter your WORKSPACE_PATH: `)
|
|
126
|
+
if (answer && existsSync(answer)) {
|
|
127
|
+
final.WORKSPACE_PATH = answer
|
|
128
|
+
} else if (answer) {
|
|
129
|
+
console.log(` ${yellow('Warning: path does not exist yet')}`)
|
|
130
|
+
final.WORKSPACE_PATH = answer
|
|
131
|
+
} else {
|
|
132
|
+
console.log(`\n ${red('Aborted.')} WORKSPACE_PATH is required.`)
|
|
133
|
+
process.exit(1)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!final.OPENCLAW_BIN) {
|
|
138
|
+
const answer = await ask(` ${yellow('?')} Enter path to openclaw binary: `)
|
|
139
|
+
if (answer) {
|
|
140
|
+
final.OPENCLAW_BIN = answer
|
|
141
|
+
} else {
|
|
142
|
+
console.log(`\n ${red('Aborted.')} OPENCLAW_BIN is required.`)
|
|
143
|
+
process.exit(1)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (!final.OPENCLAW_GATEWAY_TOKEN) {
|
|
148
|
+
console.log(` ${dim('Find your token in ~/.openclaw/openclaw.json under gateway.auth.token')}`)
|
|
149
|
+
const answer = await ask(` ${yellow('?')} Enter your gateway token: `)
|
|
150
|
+
if (answer) {
|
|
151
|
+
final.OPENCLAW_GATEWAY_TOKEN = answer
|
|
152
|
+
} else {
|
|
153
|
+
console.log(`\n ${red('Aborted.')} OPENCLAW_GATEWAY_TOKEN is required.`)
|
|
154
|
+
process.exit(1)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Check if .env.local already exists
|
|
159
|
+
const envPath = resolve(process.cwd(), '.env.local')
|
|
160
|
+
if (existsSync(envPath)) {
|
|
161
|
+
const overwrite = await ask(` ${yellow('?')} .env.local already exists. Overwrite? (y/N) `)
|
|
162
|
+
if (overwrite.toLowerCase() !== 'y') {
|
|
163
|
+
console.log(`\n ${dim('Keeping existing .env.local')}`)
|
|
164
|
+
process.exit(0)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Confirm
|
|
169
|
+
console.log()
|
|
170
|
+
console.log(dim(' Will write .env.local with:'))
|
|
171
|
+
console.log(` WORKSPACE_PATH=${dim(final.WORKSPACE_PATH)}`)
|
|
172
|
+
console.log(` OPENCLAW_BIN=${dim(final.OPENCLAW_BIN)}`)
|
|
173
|
+
console.log(` OPENCLAW_GATEWAY_TOKEN=${dim(final.OPENCLAW_GATEWAY_TOKEN.slice(0, 8) + '...')}`)
|
|
174
|
+
console.log()
|
|
175
|
+
|
|
176
|
+
const confirm = await ask(` ${bold('Write .env.local?')} (Y/n) `)
|
|
177
|
+
if (confirm.toLowerCase() === 'n') {
|
|
178
|
+
console.log(`\n ${dim('Aborted.')}`)
|
|
179
|
+
process.exit(0)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Write
|
|
183
|
+
const content = [
|
|
184
|
+
'# ClawPort -- generated by npm run setup',
|
|
185
|
+
`# Created: ${new Date().toISOString()}`,
|
|
186
|
+
'',
|
|
187
|
+
'# Required',
|
|
188
|
+
`WORKSPACE_PATH=${final.WORKSPACE_PATH}`,
|
|
189
|
+
`OPENCLAW_BIN=${final.OPENCLAW_BIN}`,
|
|
190
|
+
`OPENCLAW_GATEWAY_TOKEN=${final.OPENCLAW_GATEWAY_TOKEN}`,
|
|
191
|
+
'',
|
|
192
|
+
'# Optional -- uncomment to enable voice features',
|
|
193
|
+
'# ELEVENLABS_API_KEY=',
|
|
194
|
+
'',
|
|
195
|
+
].join('\n')
|
|
196
|
+
|
|
197
|
+
writeFileSync(envPath, content, 'utf-8')
|
|
198
|
+
|
|
199
|
+
console.log()
|
|
200
|
+
console.log(` ${green('Done!')} .env.local written.`)
|
|
201
|
+
console.log()
|
|
202
|
+
console.log(` Next steps:`)
|
|
203
|
+
if (!gatewayUp) {
|
|
204
|
+
console.log(` 1. Start the gateway: ${dim('openclaw gateway run')}`)
|
|
205
|
+
console.log(` 2. Start ClawPort: ${dim('npm run dev')}`)
|
|
206
|
+
} else {
|
|
207
|
+
console.log(` ${dim('npm run dev')}`)
|
|
208
|
+
}
|
|
209
|
+
console.log()
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
main().catch((err) => {
|
|
213
|
+
console.error(`\n ${red('Error:')} ${err.message}`)
|
|
214
|
+
process.exit(1)
|
|
215
|
+
})
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2017",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "esnext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"jsx": "react-jsx",
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"plugins": [
|
|
17
|
+
{
|
|
18
|
+
"name": "next"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"paths": {
|
|
22
|
+
"@/*": ["./*"]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"include": [
|
|
26
|
+
"next-env.d.ts",
|
|
27
|
+
"**/*.ts",
|
|
28
|
+
"**/*.tsx",
|
|
29
|
+
".next/types/**/*.ts",
|
|
30
|
+
".next/dev/types/**/*.ts",
|
|
31
|
+
"**/*.mts"
|
|
32
|
+
],
|
|
33
|
+
"exclude": ["node_modules"]
|
|
34
|
+
}
|
package/vitest.config.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config'
|
|
2
|
+
import react from '@vitejs/plugin-react'
|
|
3
|
+
import path from 'path'
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [react()],
|
|
7
|
+
resolve: {
|
|
8
|
+
alias: {
|
|
9
|
+
'@': path.resolve(__dirname, './'),
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
test: {
|
|
13
|
+
environment: 'jsdom',
|
|
14
|
+
include: ['**/*.test.ts', '**/*.test.tsx'],
|
|
15
|
+
exclude: ['node_modules', '.next'],
|
|
16
|
+
},
|
|
17
|
+
})
|