@chrysb/alphaclaw 0.1.11 → 0.1.13

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.
@@ -11,7 +11,11 @@ const {
11
11
  } = require("./constants");
12
12
 
13
13
  const createAlphaclawVersionService = () => {
14
- let kUpdateStatusCache = { latestVersion: null, hasUpdate: false, fetchedAt: 0 };
14
+ let kUpdateStatusCache = {
15
+ latestVersion: null,
16
+ hasUpdate: false,
17
+ fetchedAt: 0,
18
+ };
15
19
  let kUpdateInProgress = false;
16
20
 
17
21
  const readAlphaclawVersion = () => {
@@ -30,22 +34,36 @@ const createAlphaclawVersionService = () => {
30
34
  const doGet = (url, redirects = 0) => {
31
35
  if (redirects > 3) return reject(new Error("Too many redirects"));
32
36
  const get = url.startsWith("https") ? https.get : http.get;
33
- get(url, { headers: { Accept: "application/vnd.npm.install-v1+json" } }, (res) => {
34
- if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
35
- res.resume();
36
- return doGet(res.headers.location, redirects + 1);
37
- }
38
- let data = "";
39
- res.on("data", (chunk) => { data += chunk; });
40
- res.on("end", () => {
41
- try {
42
- const parsed = JSON.parse(data);
43
- resolve(parsed["dist-tags"]?.latest || null);
44
- } catch (e) {
45
- reject(new Error(`Failed to parse registry response (status ${res.statusCode})`));
37
+ get(
38
+ url,
39
+ { headers: { Accept: "application/vnd.npm.install-v1+json" } },
40
+ (res) => {
41
+ if (
42
+ res.statusCode >= 300 &&
43
+ res.statusCode < 400 &&
44
+ res.headers.location
45
+ ) {
46
+ res.resume();
47
+ return doGet(res.headers.location, redirects + 1);
46
48
  }
47
- });
48
- }).on("error", reject);
49
+ let data = "";
50
+ res.on("data", (chunk) => {
51
+ data += chunk;
52
+ });
53
+ res.on("end", () => {
54
+ try {
55
+ const parsed = JSON.parse(data);
56
+ resolve(parsed["dist-tags"]?.latest || null);
57
+ } catch (e) {
58
+ reject(
59
+ new Error(
60
+ `Failed to parse registry response (status ${res.statusCode})`,
61
+ ),
62
+ );
63
+ }
64
+ });
65
+ },
66
+ ).on("error", reject);
49
67
  };
50
68
  doGet(kAlphaclawRegistryUrl);
51
69
  });
@@ -64,7 +82,11 @@ const createAlphaclawVersionService = () => {
64
82
  }
65
83
  const currentVersion = readAlphaclawVersion();
66
84
  const latestVersion = await fetchLatestVersionFromRegistry();
67
- const hasUpdate = !!(currentVersion && latestVersion && latestVersion !== currentVersion);
85
+ const hasUpdate = !!(
86
+ currentVersion &&
87
+ latestVersion &&
88
+ latestVersion !== currentVersion
89
+ );
68
90
  kUpdateStatusCache = { latestVersion, hasUpdate, fetchedAt: Date.now() };
69
91
  console.log(
70
92
  `[alphaclaw] alphaclaw update status: hasUpdate=${hasUpdate} current=${currentVersion} latest=${latestVersion || "unknown"}`,
@@ -78,7 +100,10 @@ const createAlphaclawVersionService = () => {
78
100
  let dir = kNpmPackageRoot;
79
101
  while (dir !== path.dirname(dir)) {
80
102
  const parent = path.dirname(dir);
81
- if (path.basename(parent) === "node_modules" || parent.includes("node_modules")) {
103
+ if (
104
+ path.basename(parent) === "node_modules" ||
105
+ parent.includes("node_modules")
106
+ ) {
82
107
  dir = parent;
83
108
  continue;
84
109
  }
@@ -100,9 +125,11 @@ const createAlphaclawVersionService = () => {
100
125
  const installLatestAlphaclaw = () =>
101
126
  new Promise((resolve, reject) => {
102
127
  const installDir = findInstallDir();
103
- console.log(`[alphaclaw] Running: npm install @chrysb/alphaclaw@latest (cwd: ${installDir})`);
128
+ console.log(
129
+ `[alphaclaw] Running: npm install @chrysb/alphaclaw@latest (cwd: ${installDir})`,
130
+ );
104
131
  exec(
105
- "npm install @chrysb/alphaclaw@latest --omit=dev --no-save --package-lock=false",
132
+ "npm install @chrysb/alphaclaw@latest --omit=dev --no-save --package-lock=false --prefer-online",
106
133
  {
107
134
  cwd: installDir,
108
135
  env: {
@@ -116,11 +143,19 @@ const createAlphaclawVersionService = () => {
116
143
  (err, stdout, stderr) => {
117
144
  if (err) {
118
145
  const message = String(stderr || err.message || "").trim();
119
- console.log(`[alphaclaw] alphaclaw install error: ${message.slice(0, 200)}`);
120
- return reject(new Error(message || "Failed to install @chrysb/alphaclaw@latest"));
146
+ console.log(
147
+ `[alphaclaw] alphaclaw install error: ${message.slice(0, 200)}`,
148
+ );
149
+ return reject(
150
+ new Error(
151
+ message || "Failed to install @chrysb/alphaclaw@latest",
152
+ ),
153
+ );
121
154
  }
122
155
  if (stdout?.trim()) {
123
- console.log(`[alphaclaw] alphaclaw install stdout: ${stdout.trim().slice(0, 300)}`);
156
+ console.log(
157
+ `[alphaclaw] alphaclaw install stdout: ${stdout.trim().slice(0, 300)}`,
158
+ );
124
159
  }
125
160
  console.log("[alphaclaw] alphaclaw install completed");
126
161
  resolve({ stdout: stdout?.trim(), stderr: stderr?.trim() });
@@ -157,7 +192,9 @@ const createAlphaclawVersionService = () => {
157
192
  const getVersionStatus = async (refresh) => {
158
193
  const currentVersion = readAlphaclawVersion();
159
194
  try {
160
- const { latestVersion, hasUpdate } = await readAlphaclawUpdateStatus({ refresh });
195
+ const { latestVersion, hasUpdate } = await readAlphaclawUpdateStatus({
196
+ refresh,
197
+ });
161
198
  return { ok: true, currentVersion, latestVersion, hasUpdate };
162
199
  } catch (err) {
163
200
  return {
@@ -185,12 +222,19 @@ const createAlphaclawVersionService = () => {
185
222
  // Write marker to persistent volume so the update survives container recreation
186
223
  const markerPath = path.join(kRootDir, ".alphaclaw-update-pending");
187
224
  try {
188
- fs.writeFileSync(markerPath, JSON.stringify({ from: previousVersion, ts: Date.now() }));
225
+ fs.writeFileSync(
226
+ markerPath,
227
+ JSON.stringify({ from: previousVersion, ts: Date.now() }),
228
+ );
189
229
  console.log(`[alphaclaw] Update marker written to ${markerPath}`);
190
230
  } catch (e) {
191
231
  console.log(`[alphaclaw] Could not write update marker: ${e.message}`);
192
232
  }
193
- kUpdateStatusCache = { latestVersion: null, hasUpdate: false, fetchedAt: 0 };
233
+ kUpdateStatusCache = {
234
+ latestVersion: null,
235
+ hasUpdate: false,
236
+ fetchedAt: 0,
237
+ };
194
238
  return {
195
239
  status: 200,
196
240
  body: {
@@ -7,8 +7,8 @@ const parsePositiveIntEnv = (value, fallbackValue) => {
7
7
  };
8
8
 
9
9
  // Portable root directory: --root-dir flag sets ALPHACLAW_ROOT_DIR before require
10
- const kRootDir = process.env.ALPHACLAW_ROOT_DIR
11
- || path.join(os.homedir(), ".alphaclaw");
10
+ const kRootDir =
11
+ process.env.ALPHACLAW_ROOT_DIR || path.join(os.homedir(), ".alphaclaw");
12
12
  const kPackageRoot = path.resolve(__dirname, "..");
13
13
  const kNpmPackageRoot = path.resolve(kPackageRoot, "..");
14
14
  const kSetupDir = path.join(kPackageRoot, "setup");
@@ -21,7 +21,13 @@ const OPENCLAW_DIR = path.join(kRootDir, ".openclaw");
21
21
  const GATEWAY_TOKEN = process.env.OPENCLAW_GATEWAY_TOKEN || "";
22
22
  const ENV_FILE_PATH = path.join(kRootDir, ".env");
23
23
  const WORKSPACE_DIR = path.join(OPENCLAW_DIR, "workspace");
24
- const AUTH_PROFILES_PATH = path.join(OPENCLAW_DIR, "agents", "main", "agent", "auth-profiles.json");
24
+ const AUTH_PROFILES_PATH = path.join(
25
+ OPENCLAW_DIR,
26
+ "agents",
27
+ "main",
28
+ "agent",
29
+ "auth-profiles.json",
30
+ );
25
31
  const CODEX_PROFILE_ID = "openai-codex:codex-cli";
26
32
  const CODEX_OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
27
33
  const CODEX_OAUTH_AUTHORIZE_URL = "https://auth.openai.com/oauth/authorize";
@@ -195,13 +201,15 @@ const SCOPE_MAP = {
195
201
  const REVERSE_SCOPE_MAP = Object.fromEntries(
196
202
  Object.entries(SCOPE_MAP).map(([k, v]) => [v, k]),
197
203
  );
198
- const BASE_SCOPES = ["openid", "https://www.googleapis.com/auth/userinfo.email"];
204
+ const BASE_SCOPES = [
205
+ "openid",
206
+ "https://www.googleapis.com/auth/userinfo.email",
207
+ ];
199
208
 
200
209
  const GOG_CONFIG_DIR = path.join(OPENCLAW_DIR, "gogcli");
201
210
  const GOG_CREDENTIALS_PATH = path.join(GOG_CONFIG_DIR, "credentials.json");
202
211
  const GOG_STATE_PATH = path.join(GOG_CONFIG_DIR, "state.json");
203
- const GOG_KEYRING_PASSWORD =
204
- process.env.GOG_KEYRING_PASSWORD || "alphaclaw";
212
+ const GOG_KEYRING_PASSWORD = process.env.GOG_KEYRING_PASSWORD || "alphaclaw";
205
213
 
206
214
  const API_TEST_COMMANDS = {
207
215
  gmail: "gmail labels list",
@@ -1,12 +1,18 @@
1
1
  const { exec, execSync } = require("child_process");
2
+ const fs = require("fs");
3
+ const path = require("path");
2
4
  const {
3
5
  kVersionCacheTtlMs,
4
6
  kLatestVersionCacheTtlMs,
5
- kAppDir,
7
+ kNpmPackageRoot,
6
8
  } = require("./constants");
7
9
  const { normalizeOpenclawVersion } = require("./helpers");
8
10
 
9
- const createOpenclawVersionService = ({ gatewayEnv, restartGateway, isOnboarded }) => {
11
+ const createOpenclawVersionService = ({
12
+ gatewayEnv,
13
+ restartGateway,
14
+ isOnboarded,
15
+ }) => {
10
16
  let kOpenclawVersionCache = { value: null, fetchedAt: 0 };
11
17
  let kOpenclawUpdateStatusCache = {
12
18
  latestVersion: null,
@@ -58,7 +64,8 @@ const createOpenclawVersionService = ({ gatewayEnv, restartGateway, isOnboarded
58
64
  }).trim();
59
65
  const parsed = JSON.parse(raw);
60
66
  const latestVersion = normalizeOpenclawVersion(
61
- parsed?.availability?.latestVersion || parsed?.update?.registry?.latestVersion,
67
+ parsed?.availability?.latestVersion ||
68
+ parsed?.update?.registry?.latestVersion,
62
69
  );
63
70
  const hasUpdate = !!parsed?.availability?.available;
64
71
  kOpenclawUpdateStatusCache = {
@@ -80,11 +87,42 @@ const createOpenclawVersionService = ({ gatewayEnv, restartGateway, isOnboarded
80
87
 
81
88
  const installLatestOpenclaw = () =>
82
89
  new Promise((resolve, reject) => {
83
- console.log("[alphaclaw] Running: npm install --omit=dev --no-save --package-lock=false openclaw@latest");
90
+ const installDir = (() => {
91
+ // Resolve the consumer app root (for example /app in Docker), not this package directory.
92
+ let dir = kNpmPackageRoot;
93
+ while (dir !== path.dirname(dir)) {
94
+ const parent = path.dirname(dir);
95
+ if (
96
+ path.basename(parent) === "node_modules" ||
97
+ parent.includes(`${path.sep}node_modules${path.sep}`)
98
+ ) {
99
+ dir = parent;
100
+ continue;
101
+ }
102
+ const pkgPath = path.join(parent, "package.json");
103
+ if (fs.existsSync(pkgPath)) {
104
+ try {
105
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
106
+ if (
107
+ pkg.dependencies?.["@chrysb/alphaclaw"] ||
108
+ pkg.devDependencies?.["@chrysb/alphaclaw"] ||
109
+ pkg.optionalDependencies?.["@chrysb/alphaclaw"]
110
+ ) {
111
+ return parent;
112
+ }
113
+ } catch {}
114
+ }
115
+ dir = parent;
116
+ }
117
+ return kNpmPackageRoot;
118
+ })();
119
+ console.log(
120
+ `[alphaclaw] Running: npm install --omit=dev --no-save --package-lock=false --prefer-online openclaw@latest (cwd: ${installDir})`,
121
+ );
84
122
  exec(
85
- "npm install --omit=dev --no-save --package-lock=false openclaw@latest",
123
+ "npm install --omit=dev --no-save --package-lock=false --prefer-online openclaw@latest",
86
124
  {
87
- cwd: kAppDir,
125
+ cwd: installDir,
88
126
  env: {
89
127
  ...process.env,
90
128
  npm_config_update_notifier: "false",
@@ -96,14 +134,22 @@ const createOpenclawVersionService = ({ gatewayEnv, restartGateway, isOnboarded
96
134
  (err, stdout, stderr) => {
97
135
  if (err) {
98
136
  const message = String(stderr || err.message || "").trim();
99
- console.log(`[alphaclaw] openclaw install error: ${message.slice(0, 200)}`);
100
- return reject(new Error(message || "Failed to install openclaw@latest"));
137
+ console.log(
138
+ `[alphaclaw] openclaw install error: ${message.slice(0, 200)}`,
139
+ );
140
+ return reject(
141
+ new Error(message || "Failed to install openclaw@latest"),
142
+ );
101
143
  }
102
144
  if (stdout && stdout.trim()) {
103
- console.log(`[alphaclaw] openclaw install stdout: ${stdout.trim().slice(0, 300)}`);
145
+ console.log(
146
+ `[alphaclaw] openclaw install stdout: ${stdout.trim().slice(0, 300)}`,
147
+ );
104
148
  }
105
149
  if (stderr && stderr.trim()) {
106
- console.log(`[alphaclaw] openclaw install stderr: ${stderr.trim().slice(0, 300)}`);
150
+ console.log(
151
+ `[alphaclaw] openclaw install stderr: ${stderr.trim().slice(0, 300)}`,
152
+ );
107
153
  }
108
154
  console.log("[alphaclaw] openclaw install completed");
109
155
  resolve({ stdout: stdout.trim(), stderr: stderr.trim() });
@@ -114,7 +160,9 @@ const createOpenclawVersionService = ({ gatewayEnv, restartGateway, isOnboarded
114
160
  const getVersionStatus = async (refresh) => {
115
161
  const currentVersion = readOpenclawVersion();
116
162
  try {
117
- const { latestVersion, hasUpdate } = readOpenclawUpdateStatus({ refresh });
163
+ const { latestVersion, hasUpdate } = readOpenclawUpdateStatus({
164
+ refresh,
165
+ });
118
166
  return { ok: true, currentVersion, latestVersion, hasUpdate };
119
167
  } catch (err) {
120
168
  return {
@@ -141,7 +189,9 @@ const createOpenclawVersionService = ({ gatewayEnv, restartGateway, isOnboarded
141
189
  await installLatestOpenclaw();
142
190
  kOpenclawVersionCache = { value: null, fetchedAt: 0 };
143
191
  const currentVersion = readOpenclawVersion();
144
- const { latestVersion, hasUpdate } = readOpenclawUpdateStatus({ refresh: true });
192
+ const { latestVersion, hasUpdate } = readOpenclawUpdateStatus({
193
+ refresh: true,
194
+ });
145
195
  let restarted = false;
146
196
  if (isOnboarded()) {
147
197
  restartGateway();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrysb/alphaclaw",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },