@chrysb/alphaclaw 0.8.1-beta.4 → 0.8.1-beta.6

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.
@@ -4,7 +4,11 @@ import {
4
4
  kAgentSessionsCacheKey,
5
5
  kAgentLastSessionKey,
6
6
  } from "../lib/storage-keys.js";
7
- import { getSessionRowKey, isDestinationSessionKey } from "../lib/session-keys.js";
7
+ import {
8
+ getSessionRowKey,
9
+ isDestinationSessionKey,
10
+ sortSessionsByPriority,
11
+ } from "../lib/session-keys.js";
8
12
 
9
13
  const readCachedSessions = () => {
10
14
  try {
@@ -115,7 +119,7 @@ export const useAgentSessions = ({ enabled = false, filter } = {}) => {
115
119
  }, [enabled]);
116
120
 
117
121
  const sessions = useMemo(
118
- () => (filter ? allSessions.filter(filter) : allSessions),
122
+ () => sortSessionsByPriority(filter ? allSessions.filter(filter) : allSessions),
119
123
  [allSessions, filter],
120
124
  );
121
125
 
@@ -24,6 +24,26 @@ export const kDestinationSessionFilter = (sessionRow) =>
24
24
  String(sessionRow?.replyTo || "").trim()
25
25
  ) || isDestinationSessionKey(getSessionRowKey(sessionRow));
26
26
 
27
+ const kSessionPriority = {
28
+ destination: 0,
29
+ other: 1,
30
+ };
31
+
32
+ export const getSessionPriority = (sessionRow = null) =>
33
+ isDestinationSessionKey(getSessionRowKey(sessionRow))
34
+ ? kSessionPriority.destination
35
+ : kSessionPriority.other;
36
+
37
+ export const sortSessionsByPriority = (sessions = []) =>
38
+ [...(Array.isArray(sessions) ? sessions : [])].sort((leftRow, rightRow) => {
39
+ const priorityDiff = getSessionPriority(leftRow) - getSessionPriority(rightRow);
40
+ if (priorityDiff !== 0) return priorityDiff;
41
+ const updatedAtDiff =
42
+ Number(rightRow?.updatedAt || 0) - Number(leftRow?.updatedAt || 0);
43
+ if (updatedAtDiff !== 0) return updatedAtDiff;
44
+ return getSessionRowKey(leftRow).localeCompare(getSessionRowKey(rightRow));
45
+ });
46
+
27
47
  export const getDestinationFromSession = (sessionRow = null) => {
28
48
  const channel = String(sessionRow?.replyChannel || "").trim();
29
49
  const to = String(sessionRow?.replyTo || "").trim();
@@ -3,6 +3,7 @@ const startServerLifecycle = ({
3
3
  PORT,
4
4
  isOnboarded,
5
5
  runOnboardedBootSequence,
6
+ ensureUsageTrackerPluginConfig,
6
7
  doSyncPromptFiles,
7
8
  reloadEnv,
8
9
  syncChannelConfig,
@@ -17,6 +18,7 @@ const startServerLifecycle = ({
17
18
  console.log(`[alphaclaw] Express listening on :${PORT}`);
18
19
  if (isOnboarded()) {
19
20
  runOnboardedBootSequence({
21
+ ensureUsageTrackerPluginConfig,
20
22
  doSyncPromptFiles,
21
23
  reloadEnv,
22
24
  syncChannelConfig,
@@ -1,13 +1,10 @@
1
- const path = require("path");
2
1
  const { buildSecretReplacements } = require("../helpers");
2
+ const {
3
+ ensurePluginsShell,
4
+ ensurePluginAllowed,
5
+ ensureUsageTrackerPluginEntry,
6
+ } = require("../usage-tracker-config");
3
7
 
4
- const kUsageTrackerPluginPath = path.resolve(
5
- __dirname,
6
- "..",
7
- "..",
8
- "plugin",
9
- "usage-tracker",
10
- );
11
8
  const kDefaultToolsProfile = "full";
12
9
  const kBootstrapExtraFiles = [
13
10
  "hooks/bootstrap/AGENTS.md",
@@ -136,19 +133,9 @@ const buildOnboardArgs = ({
136
133
  return onboardArgs;
137
134
  };
138
135
 
139
- const ensurePluginAllowed = (cfg, pluginKey) => {
140
- if (!cfg.plugins.allow.includes(pluginKey)) {
141
- cfg.plugins.allow.push(pluginKey);
142
- }
143
- };
144
-
145
136
  const ensureManagedConfigShell = (cfg) => {
146
137
  if (!cfg.channels) cfg.channels = {};
147
- if (!cfg.plugins) cfg.plugins = {};
148
- if (!Array.isArray(cfg.plugins.allow)) cfg.plugins.allow = [];
149
- if (!cfg.plugins.load) cfg.plugins.load = {};
150
- if (!Array.isArray(cfg.plugins.load.paths)) cfg.plugins.load.paths = [];
151
- if (!cfg.plugins.entries) cfg.plugins.entries = {};
138
+ ensurePluginsShell(cfg);
152
139
  if (!cfg.commands) cfg.commands = {};
153
140
  if (!cfg.tools) cfg.tools = {};
154
141
  if (!cfg.hooks) cfg.hooks = {};
@@ -184,7 +171,7 @@ const applyFreshOnboardingChannels = ({ cfg, varMap }) => {
184
171
  groupPolicy: "allowlist",
185
172
  };
186
173
  cfg.plugins.entries.telegram = { enabled: true };
187
- ensurePluginAllowed(cfg, "telegram");
174
+ ensurePluginAllowed({ cfg, pluginKey: "telegram" });
188
175
  console.log("[onboard] Telegram configured");
189
176
  }
190
177
  if (varMap.DISCORD_BOT_TOKEN) {
@@ -195,7 +182,7 @@ const applyFreshOnboardingChannels = ({ cfg, varMap }) => {
195
182
  groupPolicy: "allowlist",
196
183
  };
197
184
  cfg.plugins.entries.discord = { enabled: true };
198
- ensurePluginAllowed(cfg, "discord");
185
+ ensurePluginAllowed({ cfg, pluginKey: "discord" });
199
186
  console.log("[onboard] Discord configured");
200
187
  }
201
188
  if (varMap.SLACK_BOT_TOKEN && varMap.SLACK_APP_TOKEN) {
@@ -208,14 +195,10 @@ const applyFreshOnboardingChannels = ({ cfg, varMap }) => {
208
195
  groupPolicy: "open",
209
196
  };
210
197
  cfg.plugins.entries.slack = { enabled: true };
211
- ensurePluginAllowed(cfg, "slack");
198
+ ensurePluginAllowed({ cfg, pluginKey: "slack" });
212
199
  console.log("[onboard] Slack configured");
213
200
  }
214
- if (!cfg.plugins.load.paths.includes(kUsageTrackerPluginPath)) {
215
- cfg.plugins.load.paths.push(kUsageTrackerPluginPath);
216
- }
217
- ensurePluginAllowed(cfg, "usage-tracker");
218
- cfg.plugins.entries["usage-tracker"] = { enabled: true };
201
+ ensureUsageTrackerPluginEntry(cfg);
219
202
  };
220
203
 
221
204
  const writeSanitizedOpenclawConfig = ({ fs, openclawDir, varMap }) => {
@@ -248,14 +231,7 @@ const writeManagedImportOpenclawConfig = ({ fs, openclawDir, varMap }) => {
248
231
  const cfg = JSON.parse(fs.readFileSync(configPath, "utf8"));
249
232
  ensureManagedConfigShell(cfg);
250
233
 
251
- if (!cfg.plugins.load.paths.includes(kUsageTrackerPluginPath)) {
252
- cfg.plugins.load.paths.push(kUsageTrackerPluginPath);
253
- }
254
- ensurePluginAllowed(cfg, "usage-tracker");
255
- cfg.plugins.entries["usage-tracker"] = {
256
- ...(cfg.plugins.entries["usage-tracker"] || {}),
257
- enabled: true,
258
- };
234
+ ensureUsageTrackerPluginEntry(cfg);
259
235
 
260
236
  if (varMap.TELEGRAM_BOT_TOKEN) {
261
237
  cfg.channels.telegram = {
@@ -269,7 +245,7 @@ const writeManagedImportOpenclawConfig = ({ fs, openclawDir, varMap }) => {
269
245
  ...(cfg.plugins.entries.telegram || {}),
270
246
  enabled: true,
271
247
  };
272
- ensurePluginAllowed(cfg, "telegram");
248
+ ensurePluginAllowed({ cfg, pluginKey: "telegram" });
273
249
  }
274
250
 
275
251
  if (varMap.DISCORD_BOT_TOKEN) {
@@ -284,7 +260,7 @@ const writeManagedImportOpenclawConfig = ({ fs, openclawDir, varMap }) => {
284
260
  ...(cfg.plugins.entries.discord || {}),
285
261
  enabled: true,
286
262
  };
287
- ensurePluginAllowed(cfg, "discord");
263
+ ensurePluginAllowed({ cfg, pluginKey: "discord" });
288
264
  }
289
265
 
290
266
  if (varMap.SLACK_BOT_TOKEN && varMap.SLACK_APP_TOKEN) {
@@ -301,7 +277,7 @@ const writeManagedImportOpenclawConfig = ({ fs, openclawDir, varMap }) => {
301
277
  ...(cfg.plugins.entries.slack || {}),
302
278
  enabled: true,
303
279
  };
304
- ensurePluginAllowed(cfg, "slack");
280
+ ensurePluginAllowed({ cfg, pluginKey: "slack" });
305
281
  }
306
282
 
307
283
  fs.writeFileSync(configPath, JSON.stringify(cfg, null, 2));
@@ -1,4 +1,5 @@
1
1
  const runOnboardedBootSequence = ({
2
+ ensureUsageTrackerPluginConfig,
2
3
  doSyncPromptFiles,
3
4
  reloadEnv,
4
5
  syncChannelConfig,
@@ -9,6 +10,13 @@ const runOnboardedBootSequence = ({
9
10
  watchdog,
10
11
  gmailWatchService,
11
12
  }) => {
13
+ try {
14
+ ensureUsageTrackerPluginConfig();
15
+ } catch (error) {
16
+ console.error(
17
+ `[alphaclaw] Failed to ensure usage-tracker plugin config on boot: ${error.message}`,
18
+ );
19
+ }
12
20
  doSyncPromptFiles();
13
21
  reloadEnv();
14
22
  syncChannelConfig(readEnvFile());
@@ -0,0 +1,71 @@
1
+ const path = require("path");
2
+ const { readOpenclawConfig, writeOpenclawConfig } = require("./openclaw-config");
3
+
4
+ const kUsageTrackerPluginPath = path.resolve(
5
+ __dirname,
6
+ "..",
7
+ "plugin",
8
+ "usage-tracker",
9
+ );
10
+
11
+ const ensurePluginsShell = (cfg = {}) => {
12
+ if (!cfg.plugins || typeof cfg.plugins !== "object") cfg.plugins = {};
13
+ if (!Array.isArray(cfg.plugins.allow)) cfg.plugins.allow = [];
14
+ if (!cfg.plugins.load || typeof cfg.plugins.load !== "object") {
15
+ cfg.plugins.load = {};
16
+ }
17
+ if (!Array.isArray(cfg.plugins.load.paths)) cfg.plugins.load.paths = [];
18
+ if (!cfg.plugins.entries || typeof cfg.plugins.entries !== "object") {
19
+ cfg.plugins.entries = {};
20
+ }
21
+ };
22
+
23
+ const ensurePluginAllowed = ({ cfg = {}, pluginKey = "" }) => {
24
+ const normalizedPluginKey = String(pluginKey || "").trim();
25
+ if (!normalizedPluginKey) return;
26
+ ensurePluginsShell(cfg);
27
+ if (!cfg.plugins.allow.includes(normalizedPluginKey)) {
28
+ cfg.plugins.allow.push(normalizedPluginKey);
29
+ }
30
+ };
31
+
32
+ const ensureUsageTrackerPluginEntry = (cfg = {}) => {
33
+ const before = JSON.stringify(cfg);
34
+ ensurePluginAllowed({ cfg, pluginKey: "usage-tracker" });
35
+ if (!cfg.plugins.load.paths.includes(kUsageTrackerPluginPath)) {
36
+ cfg.plugins.load.paths.push(kUsageTrackerPluginPath);
37
+ }
38
+ cfg.plugins.entries["usage-tracker"] = {
39
+ ...(cfg.plugins.entries["usage-tracker"] &&
40
+ typeof cfg.plugins.entries["usage-tracker"] === "object"
41
+ ? cfg.plugins.entries["usage-tracker"]
42
+ : {}),
43
+ enabled: true,
44
+ };
45
+ return JSON.stringify(cfg) !== before;
46
+ };
47
+
48
+ const ensureUsageTrackerPluginConfig = ({ fsModule, openclawDir }) => {
49
+ const cfg = readOpenclawConfig({
50
+ fsModule,
51
+ openclawDir,
52
+ fallback: {},
53
+ });
54
+ const changed = ensureUsageTrackerPluginEntry(cfg);
55
+ if (!changed) return false;
56
+ writeOpenclawConfig({
57
+ fsModule,
58
+ openclawDir,
59
+ config: cfg,
60
+ spacing: 2,
61
+ });
62
+ return true;
63
+ };
64
+
65
+ module.exports = {
66
+ kUsageTrackerPluginPath,
67
+ ensurePluginsShell,
68
+ ensurePluginAllowed,
69
+ ensureUsageTrackerPluginEntry,
70
+ ensureUsageTrackerPluginConfig,
71
+ };
package/lib/server.js CHANGED
@@ -133,6 +133,9 @@ const {
133
133
  startServerLifecycle,
134
134
  registerServerShutdown,
135
135
  } = require("./server/init/server-lifecycle");
136
+ const {
137
+ ensureUsageTrackerPluginConfig,
138
+ } = require("./server/usage-tracker-config");
136
139
 
137
140
  const { PORT, kTrustProxyHops, SETUP_API_PREFIXES } = constants;
138
141
 
@@ -338,6 +341,11 @@ startServerLifecycle({
338
341
  PORT,
339
342
  isOnboarded,
340
343
  runOnboardedBootSequence,
344
+ ensureUsageTrackerPluginConfig: () =>
345
+ ensureUsageTrackerPluginConfig({
346
+ fsModule: fs,
347
+ openclawDir: constants.OPENCLAW_DIR,
348
+ }),
341
349
  doSyncPromptFiles,
342
350
  reloadEnv,
343
351
  syncChannelConfig,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrysb/alphaclaw",
3
- "version": "0.8.1-beta.4",
3
+ "version": "0.8.1-beta.6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },