@castlekit/castle 0.1.2 → 0.1.4

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/bin/castle.js CHANGED
@@ -41,6 +41,70 @@ program
41
41
  await open(url);
42
42
  });
43
43
 
44
+ program
45
+ .command("update")
46
+ .description("Check for updates and install the latest version")
47
+ .action(async () => {
48
+ const { execSync } = await import("child_process");
49
+
50
+ console.log(pc.bold("\n 🏰 Castle\n"));
51
+ console.log(pc.dim(" Checking for updates...\n"));
52
+
53
+ let latest;
54
+ try {
55
+ latest = execSync("npm view @castlekit/castle version", {
56
+ encoding: "utf-8",
57
+ timeout: 15000,
58
+ stdio: ["ignore", "pipe", "ignore"],
59
+ }).trim();
60
+ } catch {
61
+ console.log(pc.yellow(" Could not check for updates. Try again later.\n"));
62
+ return;
63
+ }
64
+
65
+ if (version === latest) {
66
+ console.log(` You're on the latest version (${pc.green(version)}).\n`);
67
+ return;
68
+ }
69
+
70
+ // Check for major version bump
71
+ const currentMajor = parseInt(version.split(".")[0], 10);
72
+ const latestMajor = parseInt(latest.split(".")[0], 10);
73
+
74
+ if (latestMajor > currentMajor) {
75
+ const readline = await import("readline");
76
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
77
+ const answer = await new Promise((resolve) => {
78
+ rl.question(
79
+ ` ${pc.yellow("⚠")} Castle ${pc.cyan(latest)} is available (you have ${pc.dim(version)}).\n` +
80
+ ` This is a major version update and may include breaking changes.\n\n` +
81
+ ` Continue? (y/N) `,
82
+ resolve
83
+ );
84
+ });
85
+ rl.close();
86
+
87
+ if (answer.toLowerCase() !== "y") {
88
+ console.log(pc.dim("\n Update cancelled.\n"));
89
+ return;
90
+ }
91
+ console.log();
92
+ }
93
+
94
+ console.log(` Updating Castle from ${pc.dim(version)} to ${pc.cyan(latest)}...\n`);
95
+
96
+ try {
97
+ execSync(`npm install -g @castlekit/castle@${latest}`, {
98
+ stdio: "inherit",
99
+ timeout: 120000,
100
+ });
101
+ console.log(pc.green(`\n ✔ Updated successfully!\n`));
102
+ } catch {
103
+ console.log(pc.red(`\n Update failed.`));
104
+ console.log(` Try manually: ${pc.cyan(`npm install -g @castlekit/castle@${latest}`)}\n`);
105
+ }
106
+ });
107
+
44
108
  program
45
109
  .command("status")
46
110
  .description("Show Castle and agent status")
@@ -83,10 +147,11 @@ if (process.argv.length <= 2) {
83
147
  } else {
84
148
  console.log(pc.bold("\n 🏰 Castle\n"));
85
149
  console.log(pc.dim(" The multi-agent workspace.\n"));
86
- console.log(` ${pc.cyan("castle open")} Open the web UI`);
87
- console.log(` ${pc.cyan("castle setup")} Re-run setup wizard`);
88
- console.log(` ${pc.cyan("castle status")} Show status`);
89
- console.log(` ${pc.cyan("castle --help")} All commands\n`);
150
+ console.log(` ${pc.cyan("castle open")} Open the web UI`);
151
+ console.log(` ${pc.cyan("castle setup")} Re-run setup wizard`);
152
+ console.log(` ${pc.cyan("castle status")} Show status`);
153
+ console.log(` ${pc.cyan("castle update")} Check for updates`);
154
+ console.log(` ${pc.cyan("castle --help")} All commands\n`);
90
155
  }
91
156
  })();
92
157
  } else {
package/install.sh CHANGED
@@ -553,6 +553,16 @@ install_castle() {
553
553
 
554
554
  local resolved_version=""
555
555
  resolved_version="$(npm view "${install_spec}" version 2>/dev/null || true)"
556
+
557
+ # Check if this version is already installed
558
+ local installed_version=""
559
+ installed_version="$(npm list -g @castlekit/castle --depth=0 2>/dev/null | grep '@castlekit/castle@' | sed 's/.*@castlekit\/castle@//' | tr -d '[:space:]' || true)"
560
+
561
+ if [[ -n "$resolved_version" && "$installed_version" == "$resolved_version" ]]; then
562
+ echo -e "${SUCCESS}✓${NC} Castle ${INFO}${resolved_version}${NC} already installed"
563
+ return 0
564
+ fi
565
+
556
566
  if [[ -n "$resolved_version" ]]; then
557
567
  echo -e "${WARN}→${NC} Installing Castle ${INFO}${resolved_version}${NC}..."
558
568
  else
@@ -585,9 +595,24 @@ main() {
585
595
 
586
596
  # Check for existing installation
587
597
  local is_upgrade=false
588
- if [[ -n "$(type -P castle 2>/dev/null || true)" ]]; then
589
- echo -e "${WARN}→${NC} Existing Castle installation detected"
598
+ local existing_bin=""
599
+ existing_bin="$(type -P castle 2>/dev/null || true)"
600
+ if [[ -n "$existing_bin" ]]; then
590
601
  is_upgrade=true
602
+
603
+ # Check if already fully set up with the latest version
604
+ local current_ver=""
605
+ current_ver="$(npm list -g @castlekit/castle --depth=0 2>/dev/null | grep '@castlekit/castle@' | sed 's/.*@castlekit\/castle@//' | tr -d '[:space:]' || true)"
606
+ local target_ver=""
607
+ target_ver="$(npm view "@castlekit/castle@${CASTLE_VERSION}" version 2>/dev/null || true)"
608
+
609
+ if [[ -n "$current_ver" && -n "$target_ver" && "$current_ver" == "$target_ver" && -f "$HOME/.castle/castle.json" ]]; then
610
+ echo -e "${SUCCESS}✓${NC} Castle ${INFO}${current_ver}${NC} already installed and configured"
611
+ echo -e "${MUTED}Nothing to do. Run ${INFO}castle setup${NC} to reconfigure.${NC}"
612
+ return 0
613
+ fi
614
+
615
+ echo -e "${WARN}→${NC} Existing Castle installation detected"
591
616
  fi
592
617
 
593
618
  # Step 1: Homebrew (macOS only)
@@ -642,6 +667,9 @@ main() {
642
667
  # Step 6: Run onboarding
643
668
  if [[ "$NO_ONBOARD" == "1" ]]; then
644
669
  echo -e "Skipping setup (requested). Run ${INFO}castle setup${NC} later."
670
+ elif [[ -f "$HOME/.castle/castle.json" ]]; then
671
+ echo -e "${SUCCESS}✓${NC} Castle is already configured"
672
+ echo -e "${MUTED}Run ${INFO}castle setup${NC} to reconfigure.${NC}"
645
673
  else
646
674
  if [[ -r /dev/tty && -w /dev/tty ]]; then
647
675
  echo -e "Starting setup..."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@castlekit/castle",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "The multi-agent workspace",
5
5
  "type": "module",
6
6
  "bin": {