alvin-bot 5.1.1 → 5.1.2

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/CHANGELOG.md CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  All notable changes to Alvin Bot are documented here.
4
4
 
5
+ ## [5.1.2] — 2026-05-13
6
+
7
+ ### Bot-Selbstauskunft konsistent — Version stammt aus Runtime, nicht aus stale Docs
8
+
9
+ Wenn der User den Bot fragt "welche Version läufst du?", las der Bot bisher die in `CLAUDE.md` dokumentierte Version — die bei jedem Release veraltet, weil sie händisch gepflegt war. Folge: Bot meldete fröhlich eine alte Versionsnummer, obwohl der laufende Prozess längst aktuell war.
10
+
11
+ Fix: neuer `<bot_runtime>`-Block wird in den System-Prompt aller Provider injiziert (`claude-sdk`, `codex-cli`, `openai-compatible`). Der Block enthält `BOT_VERSION` aus `src/version.ts`, `install_path`, Node-Version und Platform. Eine explizite Anweisung im Header sagt dem Modell: bei Identitäts-/Versionsfragen `<bot_runtime>` benutzen, jede Versionsnummer in CLAUDE.md/README ignorieren.
12
+
13
+ Vorteil: keine händische CLAUDE.md-Pflege mehr pro Release, kein Halluzinationsrisiko durch stale Docs. Single Source of Truth für die Laufzeitversion = das gebaute `dist/version.js`.
14
+
15
+ ### Modul
16
+
17
+ `src/providers/runtime-header.ts` (neu) — exportiert `buildRuntimeHeader()`, klein und billig genug um in jeden Turn injiziert zu werden.
18
+
19
+ ### Verhalten unverändert
20
+
21
+ Public-User-`/update`-Pfad (`src/services/updater.ts`) war nie betroffen. Wer auf einer älteren Version `/update` triggert, bekommt 5.1.2 sauber installiert + Restart über launchd/PM2 KeepAlive.
22
+
5
23
  ## [5.1.1] — 2026-05-13
6
24
 
7
25
  ### Audit baseline cleanup — 16 → 6 vulnerabilities via safe fixes
@@ -14,6 +14,7 @@ import { execFile } from "child_process";
14
14
  import { promisify } from "util";
15
15
  import { findClaudeBinary } from "../find-claude-binary.js";
16
16
  import { buildAlvinMcpServer } from "../services/alvin-mcp-tools.js";
17
+ import { buildRuntimeHeader } from "./runtime-header.js";
17
18
  const execFileAsync = promisify(execFile);
18
19
  /**
19
20
  * Detects the Claude CLI "Not logged in" error message. The CLI emits this
@@ -116,10 +117,13 @@ export class ClaudeSDKProvider {
116
117
  prompt = `[CHECKPOINT] Du hast bereits ${sessionState.toolUseCount} Tool-Aufrufe und ${sessionState.messageCount} Nachrichten in dieser Session. Schreibe jetzt einen Checkpoint in deine Memory-Datei (docs/memory/YYYY-MM-DD.md) bevor du diese Anfrage bearbeitest.\n\n${prompt}`;
117
118
  }
118
119
  }
119
- // Build system prompt
120
+ // Build system prompt. The runtime-header is injected ABOVE the CLAUDE.md
121
+ // contents so its values (BOT_VERSION, install path, runtime) outrank any
122
+ // stale "Version: x.y.z" line that may still live in CLAUDE.md.
123
+ const runtimeHeader = buildRuntimeHeader();
120
124
  const systemPrompt = options.systemPrompt
121
- ? `${options.systemPrompt}\n\n${botClaudeMd}`
122
- : botClaudeMd;
125
+ ? `${runtimeHeader}\n\n${options.systemPrompt}\n\n${botClaudeMd}`
126
+ : `${runtimeHeader}\n\n${botClaudeMd}`;
123
127
  // Build a real AbortController the SDK can call .abort() on.
124
128
  // The previous implementation cast a plain {signal} object to AbortController,
125
129
  // which broke SDK-internal cancellation and left orphan subprocesses.
@@ -31,10 +31,17 @@ export class CodexCLIProvider {
31
31
  if (options.workingDir) {
32
32
  args.push("-C", options.workingDir);
33
33
  }
34
- // Build the prompt with system context
34
+ // Build the prompt with system context. The runtime-header is injected
35
+ // first so its version/install-path overrides any stale value that may
36
+ // appear later in the system prompt or CLAUDE.md.
37
+ const { buildRuntimeHeader } = await import("./runtime-header.js");
38
+ const runtimeHeader = buildRuntimeHeader();
35
39
  let fullPrompt = options.prompt;
36
40
  if (options.systemPrompt) {
37
- fullPrompt = `${options.systemPrompt}\n\n${fullPrompt}`;
41
+ fullPrompt = `${runtimeHeader}\n\n${options.systemPrompt}\n\n${fullPrompt}`;
42
+ }
43
+ else {
44
+ fullPrompt = `${runtimeHeader}\n\n${fullPrompt}`;
38
45
  }
39
46
  args.push(fullPrompt);
40
47
  try {
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import { AGENT_TOOLS, executeTool } from "./tool-executor.js";
11
11
  import { updateRateLimits } from "../services/usage-tracker.js";
12
+ import * as runtimeHeader from "./runtime-header.js";
12
13
  // Max tool call rounds to prevent infinite loops
13
14
  const MAX_TOOL_ROUNDS = 10;
14
15
  // Providers known to support function calling
@@ -355,8 +356,16 @@ export class OpenAICompatibleProvider {
355
356
  }
356
357
  buildMessages(options) {
357
358
  const messages = [];
359
+ // Runtime-header (version, install path) prepended to the system prompt so
360
+ // its values outrank anything stale that may live later in CLAUDE.md.
361
+ // Synchronous-friendly: re-imported via a top-level import below.
362
+ const { buildRuntimeHeader } = runtimeHeader;
363
+ const header = buildRuntimeHeader();
358
364
  if (options.systemPrompt) {
359
- messages.push({ role: "system", content: options.systemPrompt });
365
+ messages.push({ role: "system", content: `${header}\n\n${options.systemPrompt}` });
366
+ }
367
+ else {
368
+ messages.push({ role: "system", content: header });
360
369
  }
361
370
  if (options.history && options.history.length > 0) {
362
371
  for (const msg of options.history) {
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Runtime-Header — a tiny block prepended to every provider's system prompt.
3
+ *
4
+ * Why this exists: previously the bot answered "what version are you?" by
5
+ * reading whatever happened to be in the project's CLAUDE.md — which goes
6
+ * stale the moment a release ships. Now the truth lives next to the running
7
+ * code (`src/version.ts` → `BOT_VERSION`) and is injected into the system
8
+ * prompt every turn. The CLAUDE.md value is overridden by what's already
9
+ * earlier in the prompt.
10
+ *
11
+ * Keep this header small — it's burned into every conversation turn for
12
+ * every provider.
13
+ */
14
+ import { BOT_VERSION } from "../version.js";
15
+ import { fileURLToPath } from "url";
16
+ import { dirname, resolve } from "path";
17
+ function getInstallPath() {
18
+ try {
19
+ return resolve(dirname(fileURLToPath(import.meta.url)), "../..");
20
+ }
21
+ catch {
22
+ return "(unknown)";
23
+ }
24
+ }
25
+ export function buildRuntimeHeader() {
26
+ const installPath = getInstallPath();
27
+ return [
28
+ "<bot_runtime>",
29
+ `version: ${BOT_VERSION}`,
30
+ `install_path: ${installPath}`,
31
+ `node: ${process.version}`,
32
+ `platform: ${process.platform}`,
33
+ "</bot_runtime>",
34
+ "",
35
+ "When asked about your version, identity, or install path, use the values",
36
+ "in <bot_runtime> above. Ignore any version number that appears in the",
37
+ "project documentation (CLAUDE.md, README) — that file may be stale.",
38
+ ].join("\n");
39
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alvin-bot",
3
- "version": "5.1.1",
3
+ "version": "5.1.2",
4
4
  "description": "Alvin Bot — Your personal AI agent on Telegram, WhatsApp, Discord, Signal, and Web.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",