@nfreeness/clawdbot 0.124.21701 → 0.124.21703

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.
Files changed (53) hide show
  1. package/dist/agents/context.js +1 -1
  2. package/dist/agents/model-catalog.js +1 -1
  3. package/dist/agents/pi-discovery.js +16 -0
  4. package/dist/agents/pi-embedded-runner/compact.js +11 -6
  5. package/dist/agents/pi-embedded-runner/model.js +1 -1
  6. package/dist/agents/pi-embedded-runner/run/attempt.js +12 -7
  7. package/dist/agents/pi-embedded-runner/system-prompt.js +1 -1
  8. package/dist/agents/pi-tool-definition-adapter.js +2 -4
  9. package/dist/agents/tools/image-tool.js +1 -1
  10. package/dist/build-info.json +3 -3
  11. package/dist/cli/update-cli.js +30 -12
  12. package/dist/commands/auth-choice.apply.oauth.js +1 -1
  13. package/dist/commands/models/list.registry.js +1 -1
  14. package/dist/commands/onboard-auth.credentials.js +5 -1
  15. package/dist/daemon/service.js +22 -1
  16. package/dist/gateway/test-helpers.mocks.js +2 -2
  17. package/dist/infra/update-global.js +38 -7
  18. package/dist/infra/update-runner.js +20 -2
  19. package/dist/media-understanding/providers/image.js +1 -1
  20. package/extensions/bluebubbles/package.json +1 -1
  21. package/extensions/copilot-proxy/package.json +1 -1
  22. package/extensions/diagnostics-otel/package.json +1 -1
  23. package/extensions/discord/package.json +1 -1
  24. package/extensions/google-antigravity-auth/package.json +1 -1
  25. package/extensions/google-gemini-cli-auth/package.json +1 -1
  26. package/extensions/googlechat/package.json +1 -1
  27. package/extensions/imessage/package.json +1 -1
  28. package/extensions/line/package.json +1 -1
  29. package/extensions/llm-task/package.json +1 -1
  30. package/extensions/lobster/package.json +1 -1
  31. package/extensions/matrix/CHANGELOG.md +5 -0
  32. package/extensions/matrix/package.json +1 -1
  33. package/extensions/mattermost/package.json +1 -1
  34. package/extensions/memory-core/package.json +1 -1
  35. package/extensions/memory-lancedb/package.json +1 -1
  36. package/extensions/msteams/CHANGELOG.md +5 -0
  37. package/extensions/msteams/package.json +1 -1
  38. package/extensions/nextcloud-talk/package.json +1 -1
  39. package/extensions/nostr/CHANGELOG.md +5 -0
  40. package/extensions/nostr/package.json +1 -1
  41. package/extensions/open-prose/package.json +1 -1
  42. package/extensions/signal/package.json +1 -1
  43. package/extensions/slack/package.json +1 -1
  44. package/extensions/telegram/package.json +1 -1
  45. package/extensions/tlon/package.json +1 -1
  46. package/extensions/voice-call/CHANGELOG.md +5 -0
  47. package/extensions/voice-call/package.json +1 -1
  48. package/extensions/whatsapp/package.json +1 -1
  49. package/extensions/zalo/CHANGELOG.md +5 -0
  50. package/extensions/zalo/package.json +1 -1
  51. package/extensions/zalouser/CHANGELOG.md +5 -0
  52. package/extensions/zalouser/package.json +1 -1
  53. package/package.json +7 -7
@@ -6,7 +6,7 @@ import { ensureClawdbotModelsJson } from "./models-config.js";
6
6
  const MODEL_CACHE = new Map();
7
7
  const loadPromise = (async () => {
8
8
  try {
9
- const { discoverAuthStorage, discoverModels } = await import("@mariozechner/pi-coding-agent");
9
+ const { discoverAuthStorage, discoverModels } = await import("./pi-discovery.js");
10
10
  const cfg = loadConfig();
11
11
  await ensureClawdbotModelsJson(cfg);
12
12
  const agentDir = resolveClawdbotAgentDir();
@@ -3,7 +3,7 @@ import { resolveClawdbotAgentDir } from "./agent-paths.js";
3
3
  import { ensureClawdbotModelsJson } from "./models-config.js";
4
4
  let modelCatalogPromise = null;
5
5
  let hasLoggedModelCatalogError = false;
6
- const defaultImportPiSdk = () => import("@mariozechner/pi-coding-agent");
6
+ const defaultImportPiSdk = () => import("./pi-discovery.js");
7
7
  let importPiSdk = defaultImportPiSdk;
8
8
  export function resetModelCatalogCacheForTest() {
9
9
  modelCatalogPromise = null;
@@ -0,0 +1,16 @@
1
+ import path from "node:path";
2
+ import { AuthStorage, ModelRegistry } from "@mariozechner/pi-coding-agent";
3
+ /**
4
+ * Backward-compatible discovery helpers for pi-coding-agent >= 0.52.
5
+ * The old discover* helpers were removed upstream.
6
+ */
7
+ export function discoverAuthStorage(agentDir) {
8
+ const trimmedAgentDir = agentDir?.trim();
9
+ const authPath = trimmedAgentDir ? path.join(trimmedAgentDir, "auth.json") : undefined;
10
+ return new AuthStorage(authPath);
11
+ }
12
+ export function discoverModels(authStorage, agentDir) {
13
+ const trimmedAgentDir = agentDir?.trim();
14
+ const modelsPath = trimmedAgentDir ? path.join(trimmedAgentDir, "models.json") : undefined;
15
+ return new ModelRegistry(authStorage, modelsPath);
16
+ }
@@ -1,6 +1,6 @@
1
1
  import fs from "node:fs/promises";
2
2
  import os from "node:os";
3
- import { createAgentSession, estimateTokens, SessionManager, SettingsManager, } from "@mariozechner/pi-coding-agent";
3
+ import { createAgentSession, DefaultResourceLoader, estimateTokens, SessionManager, SettingsManager, } from "@mariozechner/pi-coding-agent";
4
4
  import { resolveHeartbeatPrompt } from "../../auto-reply/heartbeat.js";
5
5
  import { listChannelSupportedActions, resolveChannelMessageToolHints } from "../channel-tools.js";
6
6
  import { resolveChannelCapabilities } from "../../config/channel-capabilities.js";
@@ -272,7 +272,7 @@ export async function compactEmbeddedPiSessionDirect(params) {
272
272
  userTimeFormat,
273
273
  contextFiles,
274
274
  });
275
- const systemPrompt = createSystemPromptOverride(appendPrompt);
275
+ const systemPromptOverride = createSystemPromptOverride(appendPrompt);
276
276
  const sessionLock = await acquireSessionWriteLock({
277
277
  sessionFile: params.sessionFile,
278
278
  });
@@ -301,6 +301,14 @@ export async function compactEmbeddedPiSessionDirect(params) {
301
301
  modelId,
302
302
  model,
303
303
  });
304
+ const resourceLoader = new DefaultResourceLoader({
305
+ cwd: resolvedWorkspace,
306
+ agentDir,
307
+ settingsManager,
308
+ additionalExtensionPaths,
309
+ systemPromptOverride,
310
+ });
311
+ await resourceLoader.reload();
304
312
  const { builtInTools, customTools } = splitSdkTools({
305
313
  tools,
306
314
  sandboxEnabled: !!sandbox?.enabled,
@@ -313,14 +321,11 @@ export async function compactEmbeddedPiSessionDirect(params) {
313
321
  modelRegistry,
314
322
  model,
315
323
  thinkingLevel: mapThinkingLevel(params.thinkLevel),
316
- systemPrompt,
317
324
  tools: builtInTools,
318
325
  customTools,
326
+ resourceLoader,
319
327
  sessionManager,
320
328
  settingsManager,
321
- skills: [],
322
- contextFiles: [],
323
- additionalExtensionPaths,
324
329
  }));
325
330
  try {
326
331
  const prior = await sanitizeSessionHistory({
@@ -1,4 +1,4 @@
1
- import { discoverAuthStorage, discoverModels } from "@mariozechner/pi-coding-agent";
1
+ import { discoverAuthStorage, discoverModels } from "../pi-discovery.js";
2
2
  import { resolveClawdbotAgentDir } from "../agent-paths.js";
3
3
  import { DEFAULT_CONTEXT_TOKENS } from "../defaults.js";
4
4
  import { normalizeModelCompat } from "../model-compat.js";
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs/promises";
2
2
  import os from "node:os";
3
3
  import { streamSimple } from "@mariozechner/pi-ai";
4
- import { createAgentSession, SessionManager, SettingsManager } from "@mariozechner/pi-coding-agent";
4
+ import { createAgentSession, DefaultResourceLoader, SessionManager, SettingsManager, } from "@mariozechner/pi-coding-agent";
5
5
  import { resolveHeartbeatPrompt } from "../../../auto-reply/heartbeat.js";
6
6
  import { listChannelSupportedActions, resolveChannelMessageToolHints, } from "../../channel-tools.js";
7
7
  import { resolveChannelCapabilities } from "../../../config/channel-capabilities.js";
@@ -318,7 +318,7 @@ export async function runEmbeddedAttempt(params) {
318
318
  skillsPrompt,
319
319
  tools,
320
320
  });
321
- const systemPrompt = createSystemPromptOverride(appendPrompt);
321
+ const systemPromptOverride = createSystemPromptOverride(appendPrompt);
322
322
  const sessionLock = await acquireSessionWriteLock({
323
323
  sessionFile: params.sessionFile,
324
324
  });
@@ -360,6 +360,14 @@ export async function runEmbeddedAttempt(params) {
360
360
  modelId: params.modelId,
361
361
  model: params.model,
362
362
  });
363
+ const resourceLoader = new DefaultResourceLoader({
364
+ cwd: resolvedWorkspace,
365
+ agentDir,
366
+ settingsManager,
367
+ additionalExtensionPaths,
368
+ systemPromptOverride,
369
+ });
370
+ await resourceLoader.reload();
363
371
  const { builtInTools, customTools } = splitSdkTools({
364
372
  tools,
365
373
  sandboxEnabled: !!sandbox?.enabled,
@@ -379,14 +387,11 @@ export async function runEmbeddedAttempt(params) {
379
387
  modelRegistry: params.modelRegistry,
380
388
  model: params.model,
381
389
  thinkingLevel: mapThinkingLevel(params.thinkLevel),
382
- systemPrompt,
383
390
  tools: builtInTools,
384
391
  customTools: allCustomTools,
392
+ resourceLoader,
385
393
  sessionManager,
386
394
  settingsManager,
387
- skills: [],
388
- contextFiles: [],
389
- additionalExtensionPaths,
390
395
  }));
391
396
  if (!session) {
392
397
  throw new Error("Embedded agent session missing");
@@ -419,7 +424,7 @@ export async function runEmbeddedAttempt(params) {
419
424
  if (cacheTrace) {
420
425
  cacheTrace.recordStage("session:loaded", {
421
426
  messages: activeSession.messages,
422
- system: systemPrompt,
427
+ system: appendPrompt,
423
428
  note: "after session create",
424
429
  });
425
430
  activeSession.agent.streamFn = cacheTrace.wrapStreamFn(activeSession.agent.streamFn);
@@ -29,5 +29,5 @@ export function buildEmbeddedSystemPrompt(params) {
29
29
  }
30
30
  export function createSystemPromptOverride(systemPrompt) {
31
31
  const trimmed = systemPrompt.trim();
32
- return () => trimmed;
32
+ return () => (trimmed ? trimmed : undefined);
33
33
  }
@@ -18,9 +18,7 @@ export function toToolDefinitions(tools) {
18
18
  description: tool.description ?? "",
19
19
  // biome-ignore lint/suspicious/noExplicitAny: TypeBox schema from pi-agent-core uses a different module instance.
20
20
  parameters: tool.parameters,
21
- execute: async (toolCallId, params, onUpdate, _ctx, signal) => {
22
- // KNOWN: pi-coding-agent `ToolDefinition.execute` has a different signature/order
23
- // than pi-agent-core `AgentTool.execute`. This adapter keeps our existing tools intact.
21
+ execute: async (toolCallId, params, signal, onUpdate, _ctx) => {
24
22
  try {
25
23
  return await tool.execute(toolCallId, params, signal, onUpdate);
26
24
  }
@@ -57,7 +55,7 @@ export function toClientToolDefinitions(tools, onClientToolCall) {
57
55
  label: func.name,
58
56
  description: func.description ?? "",
59
57
  parameters: func.parameters,
60
- execute: async (toolCallId, params, _onUpdate, _ctx, _signal) => {
58
+ execute: async (toolCallId, params, _signal, _onUpdate, _ctx) => {
61
59
  // Notify handler that a client tool was called
62
60
  if (onClientToolCall) {
63
61
  onClientToolCall(func.name, params);
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { complete, } from "@mariozechner/pi-ai";
4
- import { discoverAuthStorage, discoverModels } from "@mariozechner/pi-coding-agent";
4
+ import { discoverAuthStorage, discoverModels } from "../pi-discovery.js";
5
5
  import { Type } from "@sinclair/typebox";
6
6
  import { resolveUserPath } from "../../utils.js";
7
7
  import { loadWebMedia } from "../../web/media.js";
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.124.21701",
3
- "commit": "173ba50fdd10855fff8e941cc969becdcac6e624",
4
- "builtAt": "2026-02-17T08:24:56.870Z"
2
+ "version": "0.124.21703",
3
+ "commit": "7f515d663c475d027b92e4a9a4f91d31d5b8276d",
4
+ "builtAt": "2026-02-17T12:50:00.229Z"
5
5
  }
@@ -69,7 +69,13 @@ function normalizeTag(value) {
69
69
  const trimmed = value.trim();
70
70
  if (!trimmed)
71
71
  return null;
72
- return trimmed.startsWith("clawdbot@") ? trimmed.slice("clawdbot@".length) : trimmed;
72
+ const lastAt = trimmed.lastIndexOf("@");
73
+ if (lastAt > 0) {
74
+ const suffix = trimmed.slice(lastAt + 1).trim();
75
+ if (suffix)
76
+ return suffix;
77
+ }
78
+ return trimmed;
73
79
  }
74
80
  function pickUpdateQuip() {
75
81
  return UPDATE_QUIPS[Math.floor(Math.random() * UPDATE_QUIPS.length)] ?? "Update complete.";
@@ -91,6 +97,22 @@ async function readPackageVersion(root) {
91
97
  return null;
92
98
  }
93
99
  }
100
+ async function readPackageName(root) {
101
+ try {
102
+ const raw = await fs.readFile(path.join(root, "package.json"), "utf-8");
103
+ const parsed = JSON.parse(raw);
104
+ const name = typeof parsed.name === "string" ? parsed.name.trim() : "";
105
+ return name || null;
106
+ }
107
+ catch {
108
+ return null;
109
+ }
110
+ }
111
+ function isClawdbotPackageName(name) {
112
+ if (!name)
113
+ return false;
114
+ return name === "clawdbot" || name.endsWith("/clawdbot");
115
+ }
94
116
  async function resolveTargetVersion(tag, timeoutMs) {
95
117
  const direct = normalizeVersionTag(tag);
96
118
  if (direct)
@@ -108,14 +130,7 @@ async function isGitCheckout(root) {
108
130
  }
109
131
  }
110
132
  async function isClawdbotPackage(root) {
111
- try {
112
- const raw = await fs.readFile(path.join(root, "package.json"), "utf-8");
113
- const parsed = JSON.parse(raw);
114
- return parsed?.name === "clawdbot";
115
- }
116
- catch {
117
- return false;
118
- }
133
+ return isClawdbotPackageName(await readPackageName(root));
119
134
  }
120
135
  async function pathExists(targetPath) {
121
136
  try {
@@ -438,6 +453,9 @@ export async function updateCommand(opts) {
438
453
  argv1: process.argv[1],
439
454
  cwd: process.cwd(),
440
455
  })) ?? process.cwd();
456
+ const rootPackageNameRaw = await readPackageName(root);
457
+ const rootPackageName = isClawdbotPackageName(rootPackageNameRaw) ? rootPackageNameRaw : null;
458
+ const installPackageName = rootPackageName ?? "clawdbot";
441
459
  const updateStatus = await checkUpdateStatus({
442
460
  root,
443
461
  timeoutMs: timeoutMs ?? 3500,
@@ -542,11 +560,11 @@ export async function updateCommand(opts) {
542
560
  const res = await runCommandWithTimeout(argv, options);
543
561
  return { stdout: res.stdout, stderr: res.stderr, code: res.code };
544
562
  };
545
- const pkgRoot = await resolveGlobalPackageRoot(manager, runCommand, timeoutMs ?? 20 * 60_000);
563
+ const pkgRoot = await resolveGlobalPackageRoot(manager, runCommand, timeoutMs ?? 20 * 60_000, installPackageName);
546
564
  const beforeVersion = pkgRoot ? await readPackageVersion(pkgRoot) : null;
547
565
  const updateStep = await runUpdateStep({
548
566
  name: "global update",
549
- argv: globalInstallArgs(manager, `clawdbot@${tag}`),
567
+ argv: globalInstallArgs(manager, `${installPackageName}@${tag}`),
550
568
  timeoutMs: timeoutMs ?? 20 * 60_000,
551
569
  progress,
552
570
  });
@@ -651,7 +669,7 @@ export async function updateCommand(opts) {
651
669
  }
652
670
  if (result.reason === "not-git-install") {
653
671
  defaultRuntime.log(theme.warn(`Skipped: this Clawdbot install isn't a git checkout, and the package manager couldn't be detected. Update via your package manager, then run \`${formatCliCommand("clawdbot doctor")}\` and \`${formatCliCommand("clawdbot gateway restart")}\`.`));
654
- defaultRuntime.log(theme.muted("Examples: `npm i -g clawdbot@latest` or `pnpm add -g clawdbot@latest`"));
672
+ defaultRuntime.log(theme.muted(`Examples: \`npm i -g ${installPackageName}@latest\` or \`pnpm add -g ${installPackageName}@latest\``));
655
673
  }
656
674
  defaultRuntime.exit(0);
657
675
  return;
@@ -53,7 +53,7 @@ export async function applyAuthChoiceOAuth(params) {
53
53
  onProgress: (msg) => spin.update(msg),
54
54
  });
55
55
  spin.stop("Chutes OAuth complete");
56
- const email = creds.email?.trim() || "default";
56
+ const email = typeof creds.email === "string" && creds.email.trim() ? creds.email.trim() : "default";
57
57
  const profileId = `chutes:${email}`;
58
58
  await writeOAuthCredentials("chutes", creds, params.agentDir);
59
59
  nextConfig = applyAuthProfileConfig(nextConfig, {
@@ -1,4 +1,4 @@
1
- import { discoverAuthStorage, discoverModels } from "@mariozechner/pi-coding-agent";
1
+ import { discoverAuthStorage, discoverModels } from "../../agents/pi-discovery.js";
2
2
  import { resolveClawdbotAgentDir } from "../../agents/agent-paths.js";
3
3
  import { listProfilesForProvider } from "../../agents/auth-profiles.js";
4
4
  import { getCustomProviderApiKey, resolveAwsSdkEnvVarName, resolveEnvApiKey, } from "../../agents/model-auth.js";
@@ -1,10 +1,14 @@
1
1
  import { resolveClawdbotAgentDir } from "../agents/agent-paths.js";
2
2
  import { upsertAuthProfile } from "../agents/auth-profiles.js";
3
3
  const resolveAuthAgentDir = (agentDir) => agentDir ?? resolveClawdbotAgentDir();
4
+ const resolveOAuthEmailLabel = (creds) => {
5
+ const email = creds.email;
6
+ return typeof email === "string" && email.trim() ? email.trim() : "default";
7
+ };
4
8
  export async function writeOAuthCredentials(provider, creds, agentDir) {
5
9
  // Write to resolved agent dir so gateway finds credentials on startup.
6
10
  upsertAuthProfile({
7
- profileId: `${provider}:${creds.email ?? "default"}`,
11
+ profileId: `${provider}:${resolveOAuthEmailLabel(creds)}`,
8
12
  credential: {
9
13
  type: "oauth",
10
14
  provider,
@@ -86,5 +86,26 @@ export function resolveGatewayService() {
86
86
  readRuntime: async (env) => await readScheduledTaskRuntime(env),
87
87
  };
88
88
  }
89
- throw new Error(`Gateway service install not supported on ${process.platform}`);
89
+ // Unsupported platforms (e.g. Android/Termux): return a no-op service
90
+ // so that `clawdbot status` can display other info without crashing.
91
+ return {
92
+ label: "unsupported",
93
+ loadedText: "not supported",
94
+ notLoadedText: "not supported",
95
+ install: async () => {
96
+ throw new Error(`Gateway service install not supported on ${process.platform}`);
97
+ },
98
+ uninstall: async () => {
99
+ throw new Error(`Gateway service uninstall not supported on ${process.platform}`);
100
+ },
101
+ stop: async () => {
102
+ throw new Error(`Gateway service stop not supported on ${process.platform}`);
103
+ },
104
+ restart: async () => {
105
+ throw new Error(`Gateway service restart not supported on ${process.platform}`);
106
+ },
107
+ isLoaded: async () => false,
108
+ readCommand: async () => null,
109
+ readRuntime: async () => ({}),
110
+ };
90
111
  }
@@ -197,8 +197,8 @@ export const testState = {
197
197
  export const testIsNixMode = hoisted.testIsNixMode;
198
198
  export const sessionStoreSaveDelayMs = hoisted.sessionStoreSaveDelayMs;
199
199
  export const embeddedRunMock = hoisted.embeddedRunMock;
200
- vi.mock("@mariozechner/pi-coding-agent", async () => {
201
- const actual = await vi.importActual("@mariozechner/pi-coding-agent");
200
+ vi.mock("../agents/pi-discovery.js", async () => {
201
+ const actual = await vi.importActual("../agents/pi-discovery.js");
202
202
  return {
203
203
  ...actual,
204
204
  discoverModels: (...args) => {
@@ -18,6 +18,34 @@ async function tryRealpath(targetPath) {
18
18
  return path.resolve(targetPath);
19
19
  }
20
20
  }
21
+ function packagePathFromName(packageName) {
22
+ const normalized = packageName
23
+ .trim()
24
+ .split("/")
25
+ .map((segment) => segment.trim())
26
+ .filter(Boolean);
27
+ if (normalized.length === 0)
28
+ return "clawdbot";
29
+ return path.join(...normalized);
30
+ }
31
+ function inferPackageNameFromRoot(pkgRoot) {
32
+ const base = path.basename(pkgRoot);
33
+ const parent = path.basename(path.dirname(pkgRoot));
34
+ if (parent.startsWith("@") && base)
35
+ return `${parent}/${base}`;
36
+ return base || "clawdbot";
37
+ }
38
+ async function readPackageName(pkgRoot) {
39
+ try {
40
+ const raw = await fs.readFile(path.join(pkgRoot, "package.json"), "utf-8");
41
+ const parsed = JSON.parse(raw);
42
+ const name = typeof parsed.name === "string" ? parsed.name.trim() : "";
43
+ return name || null;
44
+ }
45
+ catch {
46
+ return null;
47
+ }
48
+ }
21
49
  function resolveBunGlobalRoot() {
22
50
  const bunInstall = process.env.BUN_INSTALL?.trim() || path.join(os.homedir(), ".bun");
23
51
  return path.join(bunInstall, "install", "global", "node_modules");
@@ -32,14 +60,16 @@ export async function resolveGlobalRoot(manager, runCommand, timeoutMs) {
32
60
  const root = res.stdout.trim();
33
61
  return root || null;
34
62
  }
35
- export async function resolveGlobalPackageRoot(manager, runCommand, timeoutMs) {
63
+ export async function resolveGlobalPackageRoot(manager, runCommand, timeoutMs, packageName = "clawdbot") {
36
64
  const root = await resolveGlobalRoot(manager, runCommand, timeoutMs);
37
65
  if (!root)
38
66
  return null;
39
- return path.join(root, "clawdbot");
67
+ return path.join(root, packagePathFromName(packageName));
40
68
  }
41
69
  export async function detectGlobalInstallManagerForRoot(runCommand, pkgRoot, timeoutMs) {
42
70
  const pkgReal = await tryRealpath(pkgRoot);
71
+ const packageName = (await readPackageName(pkgRoot)) ?? inferPackageNameFromRoot(pkgRoot);
72
+ const packageRelativePath = packagePathFromName(packageName);
43
73
  const candidates = [
44
74
  { manager: "npm", argv: ["npm", "root", "-g"] },
45
75
  { manager: "pnpm", argv: ["pnpm", "root", "-g"] },
@@ -52,27 +82,28 @@ export async function detectGlobalInstallManagerForRoot(runCommand, pkgRoot, tim
52
82
  if (!globalRoot)
53
83
  continue;
54
84
  const globalReal = await tryRealpath(globalRoot);
55
- const expected = path.join(globalReal, "clawdbot");
85
+ const expected = path.join(globalReal, packageRelativePath);
56
86
  if (path.resolve(expected) === path.resolve(pkgReal))
57
87
  return manager;
58
88
  }
59
89
  const bunGlobalRoot = resolveBunGlobalRoot();
60
90
  const bunGlobalReal = await tryRealpath(bunGlobalRoot);
61
- const bunExpected = path.join(bunGlobalReal, "clawdbot");
91
+ const bunExpected = path.join(bunGlobalReal, packageRelativePath);
62
92
  if (path.resolve(bunExpected) === path.resolve(pkgReal))
63
93
  return "bun";
64
94
  return null;
65
95
  }
66
- export async function detectGlobalInstallManagerByPresence(runCommand, timeoutMs) {
96
+ export async function detectGlobalInstallManagerByPresence(runCommand, timeoutMs, packageName = "clawdbot") {
97
+ const packageRelativePath = packagePathFromName(packageName);
67
98
  for (const manager of ["npm", "pnpm"]) {
68
99
  const root = await resolveGlobalRoot(manager, runCommand, timeoutMs);
69
100
  if (!root)
70
101
  continue;
71
- if (await pathExists(path.join(root, "clawdbot")))
102
+ if (await pathExists(path.join(root, packageRelativePath)))
72
103
  return manager;
73
104
  }
74
105
  const bunRoot = resolveBunGlobalRoot();
75
- if (await pathExists(path.join(bunRoot, "clawdbot")))
106
+ if (await pathExists(path.join(bunRoot, packageRelativePath)))
76
107
  return "bun";
77
108
  return null;
78
109
  }
@@ -57,6 +57,17 @@ async function readPackageVersion(root) {
57
57
  return null;
58
58
  }
59
59
  }
60
+ async function readPackageName(root) {
61
+ try {
62
+ const raw = await fs.readFile(path.join(root, "package.json"), "utf-8");
63
+ const parsed = JSON.parse(raw);
64
+ const name = typeof parsed?.name === "string" ? parsed.name.trim() : "";
65
+ return name || null;
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ }
60
71
  async function readBranchName(runCommand, root, timeoutMs) {
61
72
  const res = await runCommand(["git", "-C", root, "rev-parse", "--abbrev-ref", "HEAD"], {
62
73
  timeoutMs,
@@ -203,7 +214,13 @@ function normalizeTag(tag) {
203
214
  const trimmed = tag?.trim();
204
215
  if (!trimmed)
205
216
  return "latest";
206
- return trimmed.startsWith("clawdbot@") ? trimmed.slice("clawdbot@".length) : trimmed;
217
+ const lastAt = trimmed.lastIndexOf("@");
218
+ if (lastAt > 0) {
219
+ const suffix = trimmed.slice(lastAt + 1).trim();
220
+ if (suffix)
221
+ return suffix;
222
+ }
223
+ return trimmed;
207
224
  }
208
225
  export async function runGatewayUpdate(opts = {}) {
209
226
  const startedAt = Date.now();
@@ -520,9 +537,10 @@ export async function runGatewayUpdate(opts = {}) {
520
537
  };
521
538
  }
522
539
  const beforeVersion = await readPackageVersion(pkgRoot);
540
+ const packageName = (await readPackageName(pkgRoot)) ?? "clawdbot";
523
541
  const globalManager = await detectGlobalInstallManagerForRoot(runCommand, pkgRoot, timeoutMs);
524
542
  if (globalManager) {
525
- const spec = `clawdbot@${normalizeTag(opts.tag)}`;
543
+ const spec = `${packageName}@${normalizeTag(opts.tag)}`;
526
544
  const updateStep = await runStep({
527
545
  runCommand,
528
546
  name: "global update",
@@ -1,5 +1,5 @@
1
1
  import { complete } from "@mariozechner/pi-ai";
2
- import { discoverAuthStorage, discoverModels } from "@mariozechner/pi-coding-agent";
2
+ import { discoverAuthStorage, discoverModels } from "../../agents/pi-discovery.js";
3
3
  import { getApiKeyForModel, requireApiKey } from "../../agents/model-auth.js";
4
4
  import { ensureClawdbotModelsJson } from "../../agents/models-config.js";
5
5
  import { minimaxUnderstandImage } from "../../agents/minimax-vlm.js";
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/bluebubbles",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot BlueBubbles channel plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/copilot-proxy",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Copilot Proxy provider plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/diagnostics-otel",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot diagnostics OpenTelemetry exporter",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/discord",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Discord channel plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/google-antigravity-auth",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Google Antigravity OAuth provider plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/google-gemini-cli-auth",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Gemini CLI OAuth provider plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/googlechat",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Google Chat channel plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/imessage",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot iMessage channel plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/line",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot LINE channel plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/llm-task",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot JSON-only LLM task plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/lobster",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Lobster workflow tool plugin (typed pipelines + resumable approvals)",
6
6
  "clawdbot": {
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.124.21703
4
+
5
+ ### Changes
6
+ - Version alignment with core Clawdbot release numbers.
7
+
3
8
  ## 2026.1.23
4
9
 
5
10
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/matrix",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Matrix channel plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/mattermost",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Mattermost channel plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/memory-core",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot core memory search plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/memory-lancedb",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot LanceDB-backed long-term memory plugin with auto-recall/capture",
6
6
  "dependencies": {
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.124.21703
4
+
5
+ ### Changes
6
+ - Version alignment with core Clawdbot release numbers.
7
+
3
8
  ## 2026.1.23
4
9
 
5
10
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/msteams",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Microsoft Teams channel plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/nextcloud-talk",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Nextcloud Talk channel plugin",
6
6
  "clawdbot": {
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.124.21703
4
+
5
+ ### Changes
6
+ - Version alignment with core Clawdbot release numbers.
7
+
3
8
  ## 2026.1.23
4
9
 
5
10
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/nostr",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Nostr channel plugin for NIP-04 encrypted DMs",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/open-prose",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "OpenProse VM skill pack plugin (slash command + telemetry).",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/signal",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Signal channel plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/slack",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Slack channel plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/telegram",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Telegram channel plugin",
6
6
  "clawdbot": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/tlon",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Tlon/Urbit channel plugin",
6
6
  "clawdbot": {
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.124.21703
4
+
5
+ ### Changes
6
+ - Version alignment with core Clawdbot release numbers.
7
+
3
8
  ## 2026.1.24
4
9
 
5
10
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/voice-call",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot voice-call plugin",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/whatsapp",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot WhatsApp channel plugin",
6
6
  "clawdbot": {
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.124.21703
4
+
5
+ ### Changes
6
+ - Version alignment with core Clawdbot release numbers.
7
+
3
8
  ## 2026.1.23
4
9
 
5
10
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/zalo",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Zalo channel plugin",
6
6
  "clawdbot": {
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.124.21703
4
+
5
+ ### Changes
6
+ - Version alignment with core Clawdbot release numbers.
7
+
3
8
  ## 2026.1.23
4
9
 
5
10
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/zalouser",
3
- "version": "2026.1.24",
3
+ "version": "0.124.21703",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Zalo Personal Account plugin via zca-cli",
6
6
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nfreeness/clawdbot",
3
- "version": "0.124.21701",
3
+ "version": "0.124.21703",
4
4
  "description": "WhatsApp gateway CLI (Baileys web) with Pi RPC agent",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -159,10 +159,10 @@
159
159
  "@homebridge/ciao": "^1.3.4",
160
160
  "@line/bot-sdk": "^10.6.0",
161
161
  "@lydell/node-pty": "1.2.0-beta.3",
162
- "@mariozechner/pi-agent-core": "0.49.3",
163
- "@mariozechner/pi-ai": "0.49.3",
164
- "@mariozechner/pi-coding-agent": "0.49.3",
165
- "@mariozechner/pi-tui": "0.49.3",
162
+ "@mariozechner/pi-agent-core": "0.52.12",
163
+ "@mariozechner/pi-ai": "0.52.12",
164
+ "@mariozechner/pi-coding-agent": "0.52.12",
165
+ "@mariozechner/pi-tui": "0.52.12",
166
166
  "@mozilla/readability": "^0.6.0",
167
167
  "@sinclair/typebox": "0.34.47",
168
168
  "@slack/bolt": "^4.6.0",
@@ -204,9 +204,9 @@
204
204
  "zod": "^4.3.6"
205
205
  },
206
206
  "optionalDependencies": {
207
- "sharp": "^0.34.5",
208
207
  "@napi-rs/canvas": "^0.1.88",
209
- "node-llama-cpp": "3.15.0"
208
+ "node-llama-cpp": "3.15.0",
209
+ "sharp": "^0.34.5"
210
210
  },
211
211
  "devDependencies": {
212
212
  "@grammyjs/types": "^3.23.0",