@hienlh/ppm 0.9.45 → 0.9.47

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
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.47] - 2026-04-06
4
+
5
+ ### Fixed
6
+ - **AI writes to Claude memory files**: Added core directive preventing AI from managing its own memory/identity files. Memory is handled by PPMBot externally.
7
+ - **Garbage identity saved**: Removed `hasCheckedIdentity` fallback that saved random messages as identity. Identity only collected through `/start` onboarding flow.
8
+ - **Identity onboarding context**: AI now gets a hint that the message is an identity intro, so it acknowledges warmly instead of treating it as a task.
9
+
10
+ ## [0.9.46] - 2026-04-06
11
+
12
+ ### Added
13
+ - **/version command**: Shows current PPM version in Telegram.
14
+
3
15
  ## [0.9.45] - 2026-04-06
4
16
 
5
17
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hienlh/ppm",
3
- "version": "0.9.45",
3
+ "version": "0.9.47",
4
4
  "description": "Personal Project Manager — mobile-first web IDE with AI assistance",
5
5
  "author": "hienlh",
6
6
  "license": "MIT",
@@ -41,9 +41,6 @@ class PPMBotService {
41
41
  /** Chat IDs that just received identity onboarding prompt */
42
42
  private identityPending = new Set<string>();
43
43
 
44
- /** Chat IDs where we've already checked for identity (once per session) */
45
- private hasCheckedIdentity = new Set<string>();
46
-
47
44
  /** Message count per session for periodic memory save */
48
45
  private messageCount = new Map<string, number>();
49
46
 
@@ -95,7 +92,6 @@ class PPMBotService {
95
92
  this.processing.clear();
96
93
  this.messageQueue.clear();
97
94
  this.identityPending.clear();
98
- this.hasCheckedIdentity.clear();
99
95
  this.messageCount.clear();
100
96
 
101
97
  console.log("[ppmbot] Stopped");
@@ -182,6 +178,7 @@ class PPMBotService {
182
178
  case "forget": await this.cmdForget(chatId, cmd.args); break;
183
179
  case "remember": await this.cmdRemember(chatId, cmd.args); break;
184
180
  case "restart": await this.cmdRestart(chatId); break;
181
+ case "version": await this.cmdVersion(chatId); break;
185
182
  case "help": await this.cmdHelp(chatId); break;
186
183
  default: await tg.sendMessage(Number(chatId), `Unknown command: /${cmd.command}`);
187
184
  }
@@ -421,6 +418,17 @@ class PPMBotService {
421
418
  } catch {}
422
419
  }
423
420
 
421
+ private async cmdVersion(chatId: string): Promise<void> {
422
+ let version = "unknown";
423
+ try {
424
+ const { join } = await import("node:path");
425
+ const pkgPath = join(import.meta.dir, "../../../package.json");
426
+ const pkg = await Bun.file(pkgPath).json();
427
+ version = pkg.version ?? "unknown";
428
+ } catch {}
429
+ await this.telegram!.sendMessage(Number(chatId), `<b>PPM</b> v${version}`);
430
+ }
431
+
424
432
  private async cmdHelp(chatId: string): Promise<void> {
425
433
  const text = `<b>PPMBot Commands</b>
426
434
 
@@ -435,6 +443,7 @@ class PPMBotService {
435
443
  /forget &lt;topic&gt; — Remove matching memories
436
444
  /remember &lt;fact&gt; — Save a fact
437
445
  /restart — Restart PPM server
446
+ /version — Show PPM version
438
447
  /help — This message`;
439
448
  await this.telegram!.sendMessage(Number(chatId), text);
440
449
  }
@@ -491,8 +500,9 @@ class PPMBotService {
491
500
  text,
492
501
  );
493
502
 
494
- // Build system prompt with memory
495
- let systemPrompt = config?.system_prompt ?? "";
503
+ // Build system prompt with memory + core directives
504
+ const coreDirective = "IMPORTANT: Do NOT write files, save to MEMORY.md, or manage your own memory/identity files. Your memory is managed externally by PPMBot. Just respond naturally.";
505
+ let systemPrompt = coreDirective + "\n\n" + (config?.system_prompt ?? "");
496
506
  const memorySection = this.memory.buildRecallPrompt(memories);
497
507
  if (memorySection) {
498
508
  systemPrompt += memorySection;
@@ -503,23 +513,19 @@ class PPMBotService {
503
513
  permissionMode: (config?.permission_mode ?? "bypassPermissions") as PermissionMode,
504
514
  };
505
515
 
506
- let fullMessage = text;
507
- if (systemPrompt) {
508
- fullMessage = `<system-context>\n${systemPrompt}\n</system-context>\n\n${text}`;
509
- }
510
-
511
516
  // Save identity BEFORE streaming — must persist even if streaming times out
517
+ let messageForAI = text;
512
518
  if (this.identityPending.has(chatId)) {
513
519
  this.identityPending.delete(chatId);
514
520
  this.memory.saveOne("_global", `User identity: ${text}`, "preference", session.sessionId);
515
521
  console.log("[ppmbot] Saved identity memory from onboarding");
516
- } else if (!this.hasCheckedIdentity.has(chatId)) {
517
- this.hasCheckedIdentity.add(chatId);
518
- const globalMems = this.memory.getSummary("_global", 50);
519
- if (!globalMems.some((m) => m.category === "preference" && /identity/i.test(m.content))) {
520
- this.memory.saveOne("_global", `User identity: ${text}`, "preference", session.sessionId);
521
- console.log("[ppmbot] Saved identity memory (first message, no identity found)");
522
- }
522
+ // Tell AI this is an identity intro so it acknowledges warmly
523
+ messageForAI = `[User just introduced themselves in response to onboarding prompt. Acknowledge warmly and briefly.]\n\n${text}`;
524
+ }
525
+
526
+ let fullMessage = messageForAI;
527
+ if (systemPrompt) {
528
+ fullMessage = `<system-context>\n${systemPrompt}\n</system-context>\n\n${messageForAI}`;
523
529
  }
524
530
 
525
531
  const events = chatService.sendMessage(
@@ -13,7 +13,7 @@ const BOT_TOKEN_RE = /^\d+:[A-Za-z0-9_-]{30,50}$/;
13
13
  /** Known PPMBot slash commands */
14
14
  const COMMANDS = new Set([
15
15
  "start", "project", "new", "sessions", "resume",
16
- "status", "stop", "memory", "forget", "remember", "restart", "help",
16
+ "status", "stop", "memory", "forget", "remember", "restart", "version", "help",
17
17
  ]);
18
18
 
19
19
  export type UpdateHandler = (update: TelegramUpdate) => Promise<void>;
@@ -53,6 +53,7 @@ export class PPMBotTelegram {
53
53
  { command: "forget", description: "Remove matching memories" },
54
54
  { command: "remember", description: "Save a fact" },
55
55
  { command: "restart", description: "Restart PPM server" },
56
+ { command: "version", description: "Show PPM version" },
56
57
  { command: "help", description: "Show all commands" },
57
58
  ],
58
59
  });