@ouro.bot/cli 0.1.0-alpha.29 → 0.1.0-alpha.30

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.json CHANGED
@@ -1,6 +1,13 @@
1
1
  {
2
2
  "_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
3
3
  "versions": [
4
+ {
5
+ "version": "0.1.0-alpha.30",
6
+ "changes": [
7
+ "BlueBubbles reply threads now stay inside one shared chat trunk instead of creating separate persisted mini-sessions, so Slugger keeps parent-chat awareness and active work when you switch between threaded and top-level replies.",
8
+ "BlueBubbles now injects explicit current-turn thread scope metadata into inbound messages and automatically removes obsolete per-thread session artifacts that used to cause mid-task resets like 'hiya, what do ya need help with?'"
9
+ ]
10
+ },
4
11
  {
5
12
  "version": "0.1.0-alpha.29",
6
13
  "changes": [
@@ -39,6 +39,7 @@ function extractChatIdentifierFromGuid(chatGuid) {
39
39
  return parts.length >= 3 ? parts[2]?.trim() || undefined : undefined;
40
40
  }
41
41
  function buildChatRef(data, threadOriginatorGuid) {
42
+ void threadOriginatorGuid;
42
43
  const chats = Array.isArray(data.chats) ? data.chats : [];
43
44
  const chat = asRecord(chats[0]) ?? null;
44
45
  const chatGuid = readString(chat, "guid");
@@ -48,12 +49,9 @@ function buildChatRef(data, threadOriginatorGuid) {
48
49
  const displayName = readString(chat, "displayName")?.trim() || undefined;
49
50
  const style = readNumber(chat, "style");
50
51
  const isGroup = style === 43 || (chatGuid?.includes(";+;") ?? false) || Boolean(displayName);
51
- const baseKey = chatGuid?.trim()
52
+ const sessionKey = chatGuid?.trim()
52
53
  ? `chat:${chatGuid.trim()}`
53
54
  : `chat_identifier:${(chatIdentifier ?? "unknown").trim()}`;
54
- const sessionKey = threadOriginatorGuid?.trim()
55
- ? `${baseKey}:thread:${threadOriginatorGuid.trim()}`
56
- : baseKey;
57
55
  return {
58
56
  chatGuid: chatGuid?.trim() || undefined,
59
57
  chatIdentifier: chatIdentifier?.trim() || undefined,
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.cleanupObsoleteBlueBubblesThreadSessions = cleanupObsoleteBlueBubblesThreadSessions;
37
+ const fs = __importStar(require("node:fs"));
38
+ const path = __importStar(require("node:path"));
39
+ const runtime_1 = require("../nerves/runtime");
40
+ function cleanupObsoleteBlueBubblesThreadSessions(trunkSessionPath) {
41
+ const normalized = trunkSessionPath.trim();
42
+ if (!normalized.endsWith(".json"))
43
+ return [];
44
+ const trunkName = path.basename(normalized);
45
+ if (trunkName.includes("_thread_"))
46
+ return [];
47
+ if (!fs.existsSync(normalized))
48
+ return [];
49
+ const dir = path.dirname(normalized);
50
+ const prefix = trunkName.slice(0, -".json".length);
51
+ const removed = [];
52
+ for (const entry of fs.readdirSync(dir)) {
53
+ if (!entry.endsWith(".json"))
54
+ continue;
55
+ if (!entry.startsWith(`${prefix}_thread_`))
56
+ continue;
57
+ const target = path.join(dir, entry);
58
+ fs.rmSync(target, { force: true });
59
+ removed.push(target);
60
+ }
61
+ if (removed.length > 0) {
62
+ (0, runtime_1.emitNervesEvent)({
63
+ component: "senses",
64
+ event: "senses.bluebubbles_thread_lane_cleanup",
65
+ message: "removed obsolete bluebubbles thread-lane sessions",
66
+ meta: {
67
+ trunkSessionPath: normalized,
68
+ removedCount: removed.length,
69
+ },
70
+ });
71
+ }
72
+ return removed;
73
+ }
@@ -51,6 +51,7 @@ const runtime_1 = require("../nerves/runtime");
51
51
  const bluebubbles_model_1 = require("./bluebubbles-model");
52
52
  const bluebubbles_client_1 = require("./bluebubbles-client");
53
53
  const bluebubbles_mutation_log_1 = require("./bluebubbles-mutation-log");
54
+ const bluebubbles_session_cleanup_1 = require("./bluebubbles-session-cleanup");
54
55
  const debug_activity_1 = require("./debug-activity");
55
56
  const defaultDeps = {
56
57
  getAgentName: identity_1.getAgentName,
@@ -84,15 +85,27 @@ function resolveFriendParams(event) {
84
85
  };
85
86
  }
86
87
  function buildInboundText(event) {
88
+ const metadataPrefix = buildConversationScopePrefix(event);
87
89
  const baseText = event.repairNotice?.trim()
88
90
  ? `${event.textForAgent}\n[${event.repairNotice.trim()}]`
89
91
  : event.textForAgent;
90
- if (!event.chat.isGroup)
91
- return baseText;
92
+ if (!event.chat.isGroup) {
93
+ return metadataPrefix ? `${metadataPrefix}\n${baseText}` : baseText;
94
+ }
95
+ const scopedText = metadataPrefix ? `${metadataPrefix}\n${baseText}` : baseText;
92
96
  if (event.kind === "mutation") {
93
- return `${event.sender.displayName} ${baseText}`;
97
+ return `${event.sender.displayName} ${scopedText}`;
98
+ }
99
+ return `${event.sender.displayName}: ${scopedText}`;
100
+ }
101
+ function buildConversationScopePrefix(event) {
102
+ if (event.kind !== "message") {
103
+ return "";
94
104
  }
95
- return `${event.sender.displayName}: ${baseText}`;
105
+ if (event.threadOriginatorGuid?.trim()) {
106
+ return `[conversation scope: existing chat trunk | current turn: thread reply | thread id: ${event.threadOriginatorGuid.trim()}]`;
107
+ }
108
+ return "[conversation scope: existing chat trunk | current turn: top-level]";
96
109
  }
97
110
  function buildInboundContent(event) {
98
111
  const text = buildInboundText(event);
@@ -299,6 +312,21 @@ async function handleBlueBubblesEvent(payload, deps = {}) {
299
312
  };
300
313
  const friendId = context.friend.id;
301
314
  const sessPath = resolvedDeps.sessionPath(friendId, "bluebubbles", event.chat.sessionKey);
315
+ try {
316
+ (0, bluebubbles_session_cleanup_1.cleanupObsoleteBlueBubblesThreadSessions)(sessPath);
317
+ }
318
+ catch (error) {
319
+ (0, runtime_1.emitNervesEvent)({
320
+ level: "warn",
321
+ component: "senses",
322
+ event: "senses.bluebubbles_thread_lane_cleanup_error",
323
+ message: "failed to clean up obsolete bluebubbles thread-lane sessions",
324
+ meta: {
325
+ sessionPath: sessPath,
326
+ reason: error instanceof Error ? error.message : String(error),
327
+ },
328
+ });
329
+ }
302
330
  const existing = resolvedDeps.loadSession(sessPath);
303
331
  const messages = existing?.messages && existing.messages.length > 0
304
332
  ? existing.messages
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.29",
3
+ "version": "0.1.0-alpha.30",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",