openpalm 0.9.8 → 0.9.10

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.
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Standalone setup wizard server — no Docker required.
4
+ *
5
+ * Starts the setup wizard HTTP server for manual testing or Playwright
6
+ * automation without running the full `openpalm install` flow.
7
+ *
8
+ * Usage:
9
+ * bun run packages/cli/src/setup-wizard/standalone.ts
10
+ * WIZARD_PORT=9100 bun run packages/cli/src/setup-wizard/standalone.ts
11
+ *
12
+ * Environment:
13
+ * WIZARD_PORT — Port to listen on (default: ephemeral/random)
14
+ * OPENPALM_CONFIG_HOME — Config dir override (default: temp dir)
15
+ * OPENPALM_DATA_HOME — Data dir override (default: temp dir)
16
+ * OPENPALM_STATE_HOME — State dir override (default: temp dir)
17
+ */
18
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
19
+ import { tmpdir } from "node:os";
20
+ import { join } from "node:path";
21
+ import type { CoreAssetProvider } from "@openpalm/lib";
22
+ import { createSetupServer } from "./server.ts";
23
+
24
+ // ── Configuration ──────────────────────────────────────────────────────
25
+
26
+ const port = Number(process.env.WIZARD_PORT) || 0;
27
+ const useDevDirs = !!(
28
+ process.env.OPENPALM_CONFIG_HOME &&
29
+ process.env.OPENPALM_DATA_HOME &&
30
+ process.env.OPENPALM_STATE_HOME
31
+ );
32
+
33
+ // ── Directory Setup ────────────────────────────────────────────────────
34
+
35
+ let tempBase: string | null = null;
36
+ let configDir: string;
37
+ let dataDir: string;
38
+ let stateDir: string;
39
+
40
+ if (useDevDirs) {
41
+ // Use caller-provided directories (e.g. .dev/ paths)
42
+ configDir = process.env.OPENPALM_CONFIG_HOME!;
43
+ dataDir = process.env.OPENPALM_DATA_HOME!;
44
+ stateDir = process.env.OPENPALM_STATE_HOME!;
45
+ } else {
46
+ // Create isolated temp directories
47
+ tempBase = mkdtempSync(join(tmpdir(), "openpalm-wizard-dev-"));
48
+ configDir = join(tempBase, "config");
49
+ dataDir = join(tempBase, "data");
50
+ stateDir = join(tempBase, "state");
51
+ }
52
+
53
+ // Ensure required directories exist
54
+ for (const dir of [
55
+ configDir,
56
+ join(configDir, "channels"),
57
+ join(configDir, "connections"),
58
+ join(configDir, "assistant"),
59
+ join(configDir, "automations"),
60
+ join(configDir, "stash"),
61
+ dataDir,
62
+ join(dataDir, "admin"),
63
+ join(dataDir, "memory"),
64
+ join(dataDir, "assistant"),
65
+ join(dataDir, "guardian"),
66
+ join(dataDir, "caddy"),
67
+ join(dataDir, "caddy", "data"),
68
+ join(dataDir, "caddy", "config"),
69
+ join(dataDir, "automations"),
70
+ join(dataDir, "opencode"),
71
+ stateDir,
72
+ join(stateDir, "artifacts"),
73
+ join(stateDir, "audit"),
74
+ join(stateDir, "artifacts", "channels"),
75
+ join(stateDir, "automations"),
76
+ join(stateDir, "opencode"),
77
+ ]) {
78
+ mkdirSync(dir, { recursive: true });
79
+ }
80
+
81
+ // Seed minimal env files so the wizard's status endpoint works
82
+ const stackEnvPath = join(stateDir, "artifacts", "stack.env");
83
+ writeFileSync(stackEnvPath, "OPENPALM_SETUP_COMPLETE=false\n");
84
+
85
+ const secretsPath = join(configDir, "secrets.env");
86
+ writeFileSync(
87
+ secretsPath,
88
+ [
89
+ "# OpenPalm Secrets (standalone wizard — dev/test)",
90
+ "export OPENPALM_ADMIN_TOKEN=",
91
+ "export ADMIN_TOKEN=",
92
+ "export OPENAI_API_KEY=",
93
+ "export OPENAI_BASE_URL=",
94
+ "export ANTHROPIC_API_KEY=",
95
+ "export GROQ_API_KEY=",
96
+ "export MISTRAL_API_KEY=",
97
+ "export GOOGLE_API_KEY=",
98
+ "export MEMORY_USER_ID=default_user",
99
+ "export MEMORY_AUTH_TOKEN=dev-wizard-token",
100
+ "export OWNER_NAME=",
101
+ "export OWNER_EMAIL=",
102
+ "",
103
+ ].join("\n"),
104
+ );
105
+
106
+ // Point lib's XDG resolvers at our directories
107
+ process.env.OPENPALM_CONFIG_HOME = configDir;
108
+ process.env.OPENPALM_DATA_HOME = dataDir;
109
+ process.env.OPENPALM_STATE_HOME = stateDir;
110
+
111
+ // ── Stub Asset Provider ────────────────────────────────────────────────
112
+ // Provides minimal valid asset content so performSetup() can write config
113
+ // files without needing real downloaded assets.
114
+
115
+ function createStubAssetProvider(): CoreAssetProvider {
116
+ return {
117
+ coreCompose: () => "services:\n caddy:\n image: caddy:latest\n",
118
+ caddyfile: () =>
119
+ ":80 {\n @denied not remote_ip 127.0.0.0/8 ::1\n respond @denied 403\n}\n",
120
+ ollamaCompose: () => "services:\n ollama:\n image: ollama/ollama\n",
121
+ adminCompose: () => "services:\n admin:\n image: openpalm/admin\n",
122
+ agentsMd: () => "# Agents\n",
123
+ opencodeConfig: () => '{"$schema":"https://opencode.ai/config.json"}\n',
124
+ adminOpencodeConfig: () =>
125
+ '{"$schema":"https://opencode.ai/config.json","plugin":["@openpalm/admin-tools"]}\n',
126
+ secretsSchema: () => "ADMIN_TOKEN=string\n",
127
+ stackSchema: () => "OPENPALM_IMAGE_TAG=string\n",
128
+ cleanupLogs: () => "name: cleanup-logs\nschedule: daily\n",
129
+ cleanupData: () => "name: cleanup-data\nschedule: weekly\n",
130
+ validateConfig: () => "name: validate-config\nschedule: hourly\n",
131
+ };
132
+ }
133
+
134
+ // ── Start Server ───────────────────────────────────────────────────────
135
+
136
+ const wizard = createSetupServer(port, {
137
+ assetProvider: createStubAssetProvider(),
138
+ configDir,
139
+ });
140
+
141
+ const url = `http://localhost:${wizard.server.port}/setup`;
142
+
143
+ console.log("");
144
+ console.log(" Setup wizard running (standalone mode — no Docker)");
145
+ console.log("");
146
+ console.log(` URL: ${url}`);
147
+ console.log(` Config dir: ${configDir}`);
148
+ console.log(` Data dir: ${dataDir}`);
149
+ console.log(` State dir: ${stateDir}`);
150
+ console.log("");
151
+ console.log(" Press Ctrl+C to stop.");
152
+ console.log("");
153
+
154
+ // ── Graceful Shutdown ──────────────────────────────────────────────────
155
+
156
+ function shutdown() {
157
+ console.log("\nStopping wizard server...");
158
+ wizard.stop();
159
+ if (tempBase) {
160
+ rmSync(tempBase, { recursive: true, force: true });
161
+ }
162
+ process.exit(0);
163
+ }
164
+
165
+ process.on("SIGINT", shutdown);
166
+ process.on("SIGTERM", shutdown);