@castlekit/castle 0.4.0 → 0.4.2
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/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +2 -2
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/server/app/_global-error.html +2 -2
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/avatars/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/agents/[id]/avatar/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/agents/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/agents/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/chat/attachments/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/chat/channels/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/chat/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/chat/search/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/chat/storage/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/config/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/events/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/logs/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/ping/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/session/context/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/session/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/openclaw/sessions/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/settings/avatar/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/settings/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/chat.html +1 -1
- package/.next/standalone/.next/server/app/chat.rsc +1 -1
- package/.next/standalone/.next/server/app/chat.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/chat.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/chat.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/chat.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/chat.segments/chat/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/chat.segments/chat.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings.html +1 -1
- package/.next/standalone/.next/server/app/settings.rsc +1 -1
- package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/ui-kit.html +1 -1
- package/.next/standalone/.next/server/app/ui-kit.rsc +1 -1
- package/.next/standalone/.next/server/app/ui-kit.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/ui-kit.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/ui-kit.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/ui-kit.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/ui-kit.segments/ui-kit/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/ui-kit.segments/ui-kit.segment.rsc +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_7a67de23._.js +1 -1
- package/.next/standalone/.next/server/middleware-manifest.json +5 -5
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +2 -2
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/{static/chunks/2b48886a383c2e37.js → standalone/.next/static/chunks/8c691cfaccdbb9ee.js} +1 -1
- package/.next/standalone/CHANGELOG.md +28 -0
- package/.next/standalone/bin/castle.js +2 -2
- package/.next/standalone/install.ps1 +437 -0
- package/.next/standalone/install.sh +4 -0
- package/.next/standalone/package.json +2 -1
- package/.next/standalone/src/app/page.tsx +3 -3
- package/.next/standalone/src/cli/onboarding.ts +178 -102
- package/.next/{standalone/.next/static/chunks/2b48886a383c2e37.js → static/chunks/8c691cfaccdbb9ee.js} +1 -1
- package/bin/castle.js +2 -2
- package/install.ps1 +437 -0
- package/install.sh +4 -0
- package/package.json +2 -1
- package/src/app/page.tsx +3 -3
- package/src/cli/onboarding.ts +178 -102
- /package/.next/standalone/.next/static/{R01Vc6rRTS_XwAg0Y8ERm → -R3HvmmPKzJ9Jfjg7hRqd}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{R01Vc6rRTS_XwAg0Y8ERm → -R3HvmmPKzJ9Jfjg7hRqd}/_clientMiddlewareManifest.json +0 -0
- /package/.next/standalone/.next/static/{R01Vc6rRTS_XwAg0Y8ERm → -R3HvmmPKzJ9Jfjg7hRqd}/_ssgManifest.js +0 -0
- /package/.next/static/{R01Vc6rRTS_XwAg0Y8ERm → -R3HvmmPKzJ9Jfjg7hRqd}/_buildManifest.js +0 -0
- /package/.next/static/{R01Vc6rRTS_XwAg0Y8ERm → -R3HvmmPKzJ9Jfjg7hRqd}/_clientMiddlewareManifest.json +0 -0
- /package/.next/static/{R01Vc6rRTS_XwAg0Y8ERm → -R3HvmmPKzJ9Jfjg7hRqd}/_ssgManifest.js +0 -0
package/install.ps1
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
# Castle Installer for Windows
|
|
2
|
+
# Usage: iwr -useb https://castlekit.com/install.ps1 | iex
|
|
3
|
+
# & ([scriptblock]::Create((iwr -useb https://castlekit.com/install.ps1))) -Version 0.4.0 -NoOnboard -DryRun
|
|
4
|
+
|
|
5
|
+
param(
|
|
6
|
+
[string]$Version = "latest",
|
|
7
|
+
[switch]$NoOnboard,
|
|
8
|
+
[switch]$DryRun,
|
|
9
|
+
[switch]$Verbose,
|
|
10
|
+
[switch]$Help
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
$ErrorActionPreference = "Stop"
|
|
14
|
+
|
|
15
|
+
# --- Taglines -----------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
$Taglines = @(
|
|
18
|
+
"Your kingdom awaits, sire."
|
|
19
|
+
"The throne room is ready."
|
|
20
|
+
"A fortress for your AI agents."
|
|
21
|
+
"All hail the command center."
|
|
22
|
+
"Knights of the round terminal."
|
|
23
|
+
"Raise the drawbridge, lower the latency."
|
|
24
|
+
"By royal decree, your agents are assembled."
|
|
25
|
+
"The court is now in session."
|
|
26
|
+
"From castle walls to API calls."
|
|
27
|
+
"Forged in code, ruled by you."
|
|
28
|
+
"Every king needs a castle."
|
|
29
|
+
"Where agents serve and dragons compile."
|
|
30
|
+
"The siege of busywork ends here."
|
|
31
|
+
"Hear ye, hear ye -- your agents await."
|
|
32
|
+
"A castle built on open source bedrock."
|
|
33
|
+
"One does not simply walk in without a CLI."
|
|
34
|
+
"The moat is deep but the docs are deeper."
|
|
35
|
+
"Fear not the dark mode, for it is default."
|
|
36
|
+
"In the land of AI, the castlekeeper wears a hoodie."
|
|
37
|
+
"Excalibur was a sword. This is better."
|
|
38
|
+
"npm install --save-the-kingdom."
|
|
39
|
+
"The Round Table, but make it a dashboard."
|
|
40
|
+
"Dragons? Handled. Bugs? Working on it."
|
|
41
|
+
"A quest to automate the mundane."
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
$Tagline = $Taglines | Get-Random
|
|
45
|
+
|
|
46
|
+
# --- Banner -------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
function Print-Banner {
|
|
49
|
+
$banner = @(
|
|
50
|
+
' |>>>'
|
|
51
|
+
' |'
|
|
52
|
+
' |>>> _ _|_ _ |>>>'
|
|
53
|
+
' | |;| |;| |;| |'
|
|
54
|
+
' _ _|_ _ \. . / _ _|_ _'
|
|
55
|
+
' |;|_|;|_|;| \:. , / |;|_|;|_|;|'
|
|
56
|
+
' \.. / ||; . | \. . /'
|
|
57
|
+
' \. , / ||: . | \: . /'
|
|
58
|
+
' ||: |_ _ ||_ . _ | _ _||: |'
|
|
59
|
+
' ||: .|||_|;|_|;|_|;|_|;|_|;||:. |'
|
|
60
|
+
' ||: ||. . . . ||: .|'
|
|
61
|
+
' ||: . || . . . . , ||: | \,/'
|
|
62
|
+
' ||: ||: , _______ . ||: , | /`\\'
|
|
63
|
+
' ||: || . /+++++++\ . ||: |'
|
|
64
|
+
' ||: ||. |+++++++| . ||: . |'
|
|
65
|
+
' __ ||: . ||: , |+++++++|. . _||_ |'
|
|
66
|
+
" ____--``~ '--~~__|. |+++++__|----~ ~``---, ___"
|
|
67
|
+
"-~--~ ~---__|,--~' ~~----_____-~' ``~----~~"
|
|
68
|
+
)
|
|
69
|
+
# Blue-to-purple gradient using ANSI escape codes
|
|
70
|
+
$gradient = @(27, 27, 33, 33, 63, 63, 99, 99, 135, 135, 141, 141, 177, 177, 177, 176, 176, 176)
|
|
71
|
+
Write-Host ""
|
|
72
|
+
for ($i = 0; $i -lt $banner.Length; $i++) {
|
|
73
|
+
$color = $gradient[$i]
|
|
74
|
+
Write-Host "`e[38;5;${color}m$($banner[$i])`e[0m"
|
|
75
|
+
}
|
|
76
|
+
Write-Host ""
|
|
77
|
+
Write-Host " " -NoNewline
|
|
78
|
+
Write-Host "Castle" -ForegroundColor Blue -NoNewline
|
|
79
|
+
Write-Host " - The multi-agent workspace" -ForegroundColor DarkGray
|
|
80
|
+
Write-Host " $Tagline" -ForegroundColor DarkGray
|
|
81
|
+
Write-Host ""
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# --- Help ---------------------------------------------------------------------
|
|
85
|
+
|
|
86
|
+
function Print-Usage {
|
|
87
|
+
Write-Host "Castle installer (Windows)"
|
|
88
|
+
Write-Host ""
|
|
89
|
+
Write-Host "Usage:"
|
|
90
|
+
Write-Host " iwr -useb https://castlekit.com/install.ps1 | iex"
|
|
91
|
+
Write-Host " & ([scriptblock]::Create((iwr -useb https://castlekit.com/install.ps1))) [options]"
|
|
92
|
+
Write-Host ""
|
|
93
|
+
Write-Host "Options:"
|
|
94
|
+
Write-Host " -Version <version> npm version to install (default: latest)"
|
|
95
|
+
Write-Host " -NoOnboard Skip setup wizard after install"
|
|
96
|
+
Write-Host " -DryRun Print what would happen (no changes)"
|
|
97
|
+
Write-Host " -Verbose Print debug output"
|
|
98
|
+
Write-Host " -Help Show this help"
|
|
99
|
+
Write-Host ""
|
|
100
|
+
Write-Host "Environment variables:"
|
|
101
|
+
Write-Host " CASTLE_VERSION=latest|<semver>"
|
|
102
|
+
Write-Host " CASTLE_NO_ONBOARD=1"
|
|
103
|
+
Write-Host " CASTLE_DRY_RUN=1"
|
|
104
|
+
Write-Host ""
|
|
105
|
+
Write-Host "Examples:"
|
|
106
|
+
Write-Host " iwr -useb https://castlekit.com/install.ps1 | iex"
|
|
107
|
+
Write-Host ' & ([scriptblock]::Create((iwr -useb https://castlekit.com/install.ps1))) -NoOnboard'
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# --- Environment variable overrides -------------------------------------------
|
|
111
|
+
|
|
112
|
+
if (-not $PSBoundParameters.ContainsKey("Version")) {
|
|
113
|
+
if (-not [string]::IsNullOrWhiteSpace($env:CASTLE_VERSION)) {
|
|
114
|
+
$Version = $env:CASTLE_VERSION
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (-not $PSBoundParameters.ContainsKey("NoOnboard")) {
|
|
118
|
+
if ($env:CASTLE_NO_ONBOARD -eq "1") {
|
|
119
|
+
$NoOnboard = $true
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (-not $PSBoundParameters.ContainsKey("DryRun")) {
|
|
123
|
+
if ($env:CASTLE_DRY_RUN -eq "1") {
|
|
124
|
+
$DryRun = $true
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# --- Helpers ------------------------------------------------------------------
|
|
129
|
+
|
|
130
|
+
function Refresh-Path {
|
|
131
|
+
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
# --- Node.js ------------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
function Check-Node {
|
|
137
|
+
try {
|
|
138
|
+
$nodeVersion = (node -v 2>$null)
|
|
139
|
+
if ($nodeVersion) {
|
|
140
|
+
$major = [int]($nodeVersion -replace 'v(\d+)\..*', '$1')
|
|
141
|
+
if ($major -ge 22) {
|
|
142
|
+
Write-Host "[OK] Node.js $nodeVersion found" -ForegroundColor Green
|
|
143
|
+
return $true
|
|
144
|
+
} else {
|
|
145
|
+
Write-Host "[!] Node.js $nodeVersion found, but v22+ required" -ForegroundColor Yellow
|
|
146
|
+
return $false
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
} catch {
|
|
150
|
+
Write-Host "[!] Node.js not found" -ForegroundColor Yellow
|
|
151
|
+
return $false
|
|
152
|
+
}
|
|
153
|
+
return $false
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function Install-Node {
|
|
157
|
+
Write-Host "[*] Installing Node.js 22..." -ForegroundColor Yellow
|
|
158
|
+
|
|
159
|
+
# Try winget first (Windows 11 / Windows 10 with App Installer)
|
|
160
|
+
if (Get-Command winget -ErrorAction SilentlyContinue) {
|
|
161
|
+
Write-Host " Using winget..." -ForegroundColor Gray
|
|
162
|
+
winget install OpenJS.NodeJS.LTS --source winget --accept-package-agreements --accept-source-agreements
|
|
163
|
+
Refresh-Path
|
|
164
|
+
Write-Host "[OK] Node.js installed via winget" -ForegroundColor Green
|
|
165
|
+
return
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
# Try Chocolatey
|
|
169
|
+
if (Get-Command choco -ErrorAction SilentlyContinue) {
|
|
170
|
+
Write-Host " Using Chocolatey..." -ForegroundColor Gray
|
|
171
|
+
choco install nodejs-lts -y
|
|
172
|
+
Refresh-Path
|
|
173
|
+
Write-Host "[OK] Node.js installed via Chocolatey" -ForegroundColor Green
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
# Try Scoop
|
|
178
|
+
if (Get-Command scoop -ErrorAction SilentlyContinue) {
|
|
179
|
+
Write-Host " Using Scoop..." -ForegroundColor Gray
|
|
180
|
+
scoop install nodejs-lts
|
|
181
|
+
Write-Host "[OK] Node.js installed via Scoop" -ForegroundColor Green
|
|
182
|
+
return
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
# No package manager available
|
|
186
|
+
Write-Host ""
|
|
187
|
+
Write-Host "Error: Could not find a package manager (winget, choco, or scoop)" -ForegroundColor Red
|
|
188
|
+
Write-Host ""
|
|
189
|
+
Write-Host "Please install Node.js 22+ manually:" -ForegroundColor Yellow
|
|
190
|
+
Write-Host " https://nodejs.org/en/download/" -ForegroundColor Cyan
|
|
191
|
+
Write-Host ""
|
|
192
|
+
Write-Host "Or install winget (App Installer) from the Microsoft Store." -ForegroundColor Gray
|
|
193
|
+
exit 1
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
# --- Git ----------------------------------------------------------------------
|
|
197
|
+
|
|
198
|
+
function Check-Git {
|
|
199
|
+
if (Get-Command git -ErrorAction SilentlyContinue) {
|
|
200
|
+
Write-Host "[OK] Git found" -ForegroundColor Green
|
|
201
|
+
return $true
|
|
202
|
+
}
|
|
203
|
+
Write-Host "[!] Git not found (optional -- needed for some npm packages)" -ForegroundColor Yellow
|
|
204
|
+
return $false
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
# --- npm PATH -----------------------------------------------------------------
|
|
208
|
+
|
|
209
|
+
function Ensure-NpmGlobalOnPath {
|
|
210
|
+
$npmPrefix = $null
|
|
211
|
+
try {
|
|
212
|
+
$npmPrefix = (npm config get prefix 2>$null).Trim()
|
|
213
|
+
} catch {
|
|
214
|
+
return
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if ([string]::IsNullOrWhiteSpace($npmPrefix)) { return }
|
|
218
|
+
|
|
219
|
+
# On Windows, npm global bin is directly in the prefix (not prefix/bin)
|
|
220
|
+
$npmBin = $npmPrefix
|
|
221
|
+
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
|
|
222
|
+
if (-not ($userPath -split ";" | Where-Object { $_ -ieq $npmBin })) {
|
|
223
|
+
[Environment]::SetEnvironmentVariable("Path", "$userPath;$npmBin", "User")
|
|
224
|
+
Refresh-Path
|
|
225
|
+
Write-Host "[!] Added $npmBin to user PATH" -ForegroundColor Yellow
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function Resolve-CastleBin {
|
|
230
|
+
# Check if castle is on PATH
|
|
231
|
+
if (Get-Command castle -ErrorAction SilentlyContinue) {
|
|
232
|
+
return (Get-Command castle).Source
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
Refresh-Path
|
|
236
|
+
|
|
237
|
+
if (Get-Command castle -ErrorAction SilentlyContinue) {
|
|
238
|
+
return (Get-Command castle).Source
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
# Check common npm global locations
|
|
242
|
+
$npmPrefix = $null
|
|
243
|
+
try { $npmPrefix = (npm config get prefix 2>$null).Trim() } catch {}
|
|
244
|
+
if ($npmPrefix -and (Test-Path (Join-Path $npmPrefix "castle.cmd"))) {
|
|
245
|
+
return (Join-Path $npmPrefix "castle.cmd")
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
# Check AppData roaming npm
|
|
249
|
+
$roamingNpm = Join-Path $env:APPDATA "npm"
|
|
250
|
+
if (Test-Path (Join-Path $roamingNpm "castle.cmd")) {
|
|
251
|
+
return (Join-Path $roamingNpm "castle.cmd")
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return $null
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
# --- Existing installation ----------------------------------------------------
|
|
258
|
+
|
|
259
|
+
function Check-ExistingCastle {
|
|
260
|
+
try {
|
|
261
|
+
$null = Get-Command castle -ErrorAction Stop
|
|
262
|
+
Write-Host "[*] Existing Castle installation detected" -ForegroundColor Yellow
|
|
263
|
+
return $true
|
|
264
|
+
} catch {
|
|
265
|
+
return $false
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
# --- Install Castle -----------------------------------------------------------
|
|
270
|
+
|
|
271
|
+
function Install-Castle {
|
|
272
|
+
$installSpec = "@castlekit/castle@$Version"
|
|
273
|
+
|
|
274
|
+
# Check if already installed with matching version
|
|
275
|
+
$resolvedVersion = $null
|
|
276
|
+
try {
|
|
277
|
+
$resolvedVersion = (npm view $installSpec version 2>$null).Trim()
|
|
278
|
+
} catch {}
|
|
279
|
+
|
|
280
|
+
$installedVersion = $null
|
|
281
|
+
try {
|
|
282
|
+
$npmList = npm list -g @castlekit/castle --depth=0 2>$null
|
|
283
|
+
if ($npmList -match '@castlekit/castle@(\S+)') {
|
|
284
|
+
$installedVersion = $Matches[1]
|
|
285
|
+
}
|
|
286
|
+
} catch {}
|
|
287
|
+
|
|
288
|
+
if ($resolvedVersion -and ($installedVersion -eq $resolvedVersion)) {
|
|
289
|
+
Write-Host "[OK] Castle $resolvedVersion already installed" -ForegroundColor Green
|
|
290
|
+
return
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if ($resolvedVersion) {
|
|
294
|
+
Write-Host "[*] Installing Castle $resolvedVersion..." -ForegroundColor Yellow
|
|
295
|
+
} else {
|
|
296
|
+
Write-Host "[*] Installing Castle ($Version)..." -ForegroundColor Yellow
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
# Suppress npm noise
|
|
300
|
+
$prevLogLevel = $env:NPM_CONFIG_LOGLEVEL
|
|
301
|
+
$prevUpdateNotifier = $env:NPM_CONFIG_UPDATE_NOTIFIER
|
|
302
|
+
$prevFund = $env:NPM_CONFIG_FUND
|
|
303
|
+
$prevAudit = $env:NPM_CONFIG_AUDIT
|
|
304
|
+
$env:NPM_CONFIG_LOGLEVEL = "error"
|
|
305
|
+
$env:NPM_CONFIG_UPDATE_NOTIFIER = "false"
|
|
306
|
+
$env:NPM_CONFIG_FUND = "false"
|
|
307
|
+
$env:NPM_CONFIG_AUDIT = "false"
|
|
308
|
+
try {
|
|
309
|
+
$npmOutput = npm install -g $installSpec 2>&1
|
|
310
|
+
if ($LASTEXITCODE -ne 0) {
|
|
311
|
+
Write-Host "[!] npm install failed" -ForegroundColor Red
|
|
312
|
+
$npmOutput | ForEach-Object { Write-Host $_ }
|
|
313
|
+
Write-Host ""
|
|
314
|
+
Write-Host "Try: npm install -g --force $installSpec" -ForegroundColor Cyan
|
|
315
|
+
exit 1
|
|
316
|
+
}
|
|
317
|
+
} finally {
|
|
318
|
+
$env:NPM_CONFIG_LOGLEVEL = $prevLogLevel
|
|
319
|
+
$env:NPM_CONFIG_UPDATE_NOTIFIER = $prevUpdateNotifier
|
|
320
|
+
$env:NPM_CONFIG_FUND = $prevFund
|
|
321
|
+
$env:NPM_CONFIG_AUDIT = $prevAudit
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
Write-Host "[OK] Castle installed" -ForegroundColor Green
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
# --- Main ---------------------------------------------------------------------
|
|
328
|
+
|
|
329
|
+
function Main {
|
|
330
|
+
if ($Help) {
|
|
331
|
+
Print-Usage
|
|
332
|
+
return
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if ($DryRun) {
|
|
336
|
+
Write-Host "[OK] Dry run" -ForegroundColor Green
|
|
337
|
+
Write-Host "[OK] Version: $Version" -ForegroundColor Green
|
|
338
|
+
if ($NoOnboard) {
|
|
339
|
+
Write-Host "[OK] Onboard: skipped" -ForegroundColor Green
|
|
340
|
+
}
|
|
341
|
+
Write-Host "Dry run complete (no changes made)." -ForegroundColor DarkGray
|
|
342
|
+
return
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
# Check PowerShell version
|
|
346
|
+
if ($PSVersionTable.PSVersion.Major -lt 5) {
|
|
347
|
+
Write-Host "Error: PowerShell 5+ required" -ForegroundColor Red
|
|
348
|
+
exit 1
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
Write-Host "[OK] Windows detected" -ForegroundColor Green
|
|
352
|
+
|
|
353
|
+
# Check for existing installation
|
|
354
|
+
$isUpgrade = Check-ExistingCastle
|
|
355
|
+
|
|
356
|
+
# Step 1: Node.js
|
|
357
|
+
if (-not (Check-Node)) {
|
|
358
|
+
Install-Node
|
|
359
|
+
|
|
360
|
+
# Verify after install
|
|
361
|
+
if (-not (Check-Node)) {
|
|
362
|
+
Write-Host ""
|
|
363
|
+
Write-Host "Error: Node.js installation may require a terminal restart" -ForegroundColor Red
|
|
364
|
+
Write-Host "Please close this terminal, open a new one, and run this installer again." -ForegroundColor Yellow
|
|
365
|
+
exit 1
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
# Step 2: Git check (non-blocking)
|
|
370
|
+
Check-Git | Out-Null
|
|
371
|
+
|
|
372
|
+
# Step 3: Ensure npm global bin is on PATH
|
|
373
|
+
Ensure-NpmGlobalOnPath
|
|
374
|
+
|
|
375
|
+
# Step 4: Install Castle
|
|
376
|
+
Install-Castle
|
|
377
|
+
|
|
378
|
+
# Resolve castle binary
|
|
379
|
+
Refresh-Path
|
|
380
|
+
$castleBin = Resolve-CastleBin
|
|
381
|
+
|
|
382
|
+
Write-Host ""
|
|
383
|
+
if ($isUpgrade) {
|
|
384
|
+
$updateMessages = @(
|
|
385
|
+
"The castle walls have been reinforced, my liege."
|
|
386
|
+
"New fortifications in place. The kingdom grows stronger."
|
|
387
|
+
"The royal engineers have been busy. Upgrade complete."
|
|
388
|
+
"Fresh stonework, same castle. Miss me?"
|
|
389
|
+
"The drawbridge has been upgraded. Smoother entry guaranteed."
|
|
390
|
+
)
|
|
391
|
+
Write-Host "Castle upgraded successfully!" -ForegroundColor Green
|
|
392
|
+
Write-Host ($updateMessages | Get-Random) -ForegroundColor DarkGray
|
|
393
|
+
} else {
|
|
394
|
+
$completionMessages = @(
|
|
395
|
+
"The castle has been erected. Long may it stand!"
|
|
396
|
+
"Your fortress is ready, sire. What are your orders?"
|
|
397
|
+
"The court is assembled. Your agents await."
|
|
398
|
+
"A fine castle indeed. Time to rule."
|
|
399
|
+
"Stone by stone, the kingdom begins."
|
|
400
|
+
)
|
|
401
|
+
Write-Host "Castle installed successfully!" -ForegroundColor Green
|
|
402
|
+
Write-Host ($completionMessages | Get-Random) -ForegroundColor DarkGray
|
|
403
|
+
}
|
|
404
|
+
Write-Host ""
|
|
405
|
+
|
|
406
|
+
if (-not $castleBin) {
|
|
407
|
+
Write-Host "[!] Castle is not on PATH yet." -ForegroundColor Yellow
|
|
408
|
+
Write-Host "Restart PowerShell, then run: castle setup" -ForegroundColor Cyan
|
|
409
|
+
$npmPrefix = $null
|
|
410
|
+
try { $npmPrefix = (npm config get prefix 2>$null).Trim() } catch {}
|
|
411
|
+
if ($npmPrefix) {
|
|
412
|
+
Write-Host "Expected path: $npmPrefix" -ForegroundColor DarkGray
|
|
413
|
+
}
|
|
414
|
+
return
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
# Step 5: Run setup
|
|
418
|
+
if ($NoOnboard) {
|
|
419
|
+
Write-Host "Skipping setup (requested). Run " -NoNewline
|
|
420
|
+
Write-Host "castle setup" -ForegroundColor Cyan -NoNewline
|
|
421
|
+
Write-Host " later."
|
|
422
|
+
} elseif (Test-Path (Join-Path $env:USERPROFILE ".castle\castle.json")) {
|
|
423
|
+
Write-Host "[OK] Castle is already configured" -ForegroundColor Green
|
|
424
|
+
Write-Host "Run " -NoNewline -ForegroundColor DarkGray
|
|
425
|
+
Write-Host "castle setup" -ForegroundColor Cyan -NoNewline
|
|
426
|
+
Write-Host " to reconfigure." -ForegroundColor DarkGray
|
|
427
|
+
} else {
|
|
428
|
+
Write-Host "Starting setup..." -ForegroundColor Cyan
|
|
429
|
+
Write-Host ""
|
|
430
|
+
& $castleBin setup
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
# --- Entry --------------------------------------------------------------------
|
|
435
|
+
|
|
436
|
+
Print-Banner
|
|
437
|
+
Main
|
package/install.sh
CHANGED
|
@@ -765,7 +765,11 @@ fi
|
|
|
765
765
|
|
|
766
766
|
if [[ "$OS" == "unknown" ]]; then
|
|
767
767
|
echo -e "${ERROR}Error: Unsupported operating system${NC}"
|
|
768
|
+
echo ""
|
|
768
769
|
echo "This installer supports macOS and Linux (including WSL)."
|
|
770
|
+
echo ""
|
|
771
|
+
echo -e "For ${INFO}Windows${NC} (PowerShell):"
|
|
772
|
+
echo -e " ${ACCENT}iwr -useb https://castlekit.com/install.ps1 | iex${NC}"
|
|
769
773
|
exit 1
|
|
770
774
|
fi
|
|
771
775
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@castlekit/castle",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "The multi-agent workspace",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"public/",
|
|
15
15
|
"index.js",
|
|
16
16
|
"install.sh",
|
|
17
|
+
"install.ps1",
|
|
17
18
|
"next.config.ts",
|
|
18
19
|
"postcss.config.mjs",
|
|
19
20
|
"tsconfig.json",
|
package/src/app/page.tsx
CHANGED
|
@@ -206,7 +206,7 @@ function ConnectionCard({
|
|
|
206
206
|
}) {
|
|
207
207
|
const getSubtitle = () => {
|
|
208
208
|
if (isLoading) return "Connecting to Gateway...";
|
|
209
|
-
if (!isConfigured) return "
|
|
209
|
+
if (!isConfigured) return "OpenClaw not installed — visit openclaw.ai";
|
|
210
210
|
if (isConnected) {
|
|
211
211
|
const parts = ["Connected"];
|
|
212
212
|
if (serverVersion) parts[0] = `Connected to OpenClaw ${serverVersion}`;
|
|
@@ -247,8 +247,8 @@ function ConnectionCard({
|
|
|
247
247
|
{isLoading ? (
|
|
248
248
|
<Badge variant="outline">Connecting...</Badge>
|
|
249
249
|
) : (
|
|
250
|
-
<Badge variant={isConnected ? "success" : "error"}>
|
|
251
|
-
{isConnected ? "Connected" : "Disconnected"}
|
|
250
|
+
<Badge variant={isConnected ? "success" : isConfigured ? "error" : "outline"}>
|
|
251
|
+
{isConnected ? "Connected" : isConfigured ? "Disconnected" : "Not Installed"}
|
|
252
252
|
</Badge>
|
|
253
253
|
)}
|
|
254
254
|
</div>
|