@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.
- package/lib/server/alphaclaw-version.js +70 -26
- package/lib/server/constants.js +14 -6
- package/lib/server/openclaw-version.js +62 -12
- package/package.json +1 -1
|
@@ -11,7 +11,11 @@ const {
|
|
|
11
11
|
} = require("./constants");
|
|
12
12
|
|
|
13
13
|
const createAlphaclawVersionService = () => {
|
|
14
|
-
let kUpdateStatusCache = {
|
|
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(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
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 = !!(
|
|
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 (
|
|
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(
|
|
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(
|
|
120
|
-
|
|
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(
|
|
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({
|
|
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(
|
|
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 = {
|
|
233
|
+
kUpdateStatusCache = {
|
|
234
|
+
latestVersion: null,
|
|
235
|
+
hasUpdate: false,
|
|
236
|
+
fetchedAt: 0,
|
|
237
|
+
};
|
|
194
238
|
return {
|
|
195
239
|
status: 200,
|
|
196
240
|
body: {
|
package/lib/server/constants.js
CHANGED
|
@@ -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 =
|
|
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(
|
|
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 = [
|
|
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
|
-
|
|
7
|
+
kNpmPackageRoot,
|
|
6
8
|
} = require("./constants");
|
|
7
9
|
const { normalizeOpenclawVersion } = require("./helpers");
|
|
8
10
|
|
|
9
|
-
const createOpenclawVersionService = ({
|
|
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 ||
|
|
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
|
-
|
|
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:
|
|
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(
|
|
100
|
-
|
|
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(
|
|
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(
|
|
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({
|
|
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({
|
|
192
|
+
const { latestVersion, hasUpdate } = readOpenclawUpdateStatus({
|
|
193
|
+
refresh: true,
|
|
194
|
+
});
|
|
145
195
|
let restarted = false;
|
|
146
196
|
if (isOnboarded()) {
|
|
147
197
|
restartGateway();
|