@ouro.bot/cli 0.1.0-alpha.210 → 0.1.0-alpha.212

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,18 @@
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.212",
6
+ "changes": [
7
+ "refactor: consolidate BlueBubbles sense into senses/bluebubbles/ directory — move 9 flat files (bluebubbles.ts, bluebubbles-client.ts, bluebubbles-model.ts, bluebubbles-media.ts, bluebubbles-inbound-log.ts, bluebubbles-mutation-log.ts, bluebubbles-runtime-state.ts, bluebubbles-session-cleanup.ts, bluebubbles-entry.ts) into senses/bluebubbles/ with shorter names (index.ts, client.ts, model.ts, etc.). All imports updated across 20+ files including test files, sense-manager, daemon, and package.json."
8
+ ]
9
+ },
10
+ {
11
+ "version": "0.1.0-alpha.211",
12
+ "changes": [
13
+ "refactor: extract duplicated patterns into shared utilities — mind/embedding-provider.ts (shared OpenAI embedding client from diary + associative-recall), arc/json-store.ts (shared JSON file CRUD from obligations + cares + intentions), repertoire/api-client.ts (shared HTTP request helper from graph + ado + github clients). M12 (channel callback factory) skipped: CLI and Teams streaming implementations are too different for clean abstraction."
14
+ ]
15
+ },
4
16
  {
5
17
  "version": "0.1.0-alpha.210",
6
18
  "changes": [
package/dist/arc/cares.js CHANGED
@@ -38,24 +38,15 @@ exports.readCares = readCares;
38
38
  exports.readActiveCares = readActiveCares;
39
39
  exports.updateCare = updateCare;
40
40
  exports.resolveCare = resolveCare;
41
- const fs = __importStar(require("fs"));
42
41
  const path = __importStar(require("path"));
43
42
  const runtime_1 = require("../nerves/runtime");
44
- const sync_1 = require("../heart/sync");
43
+ const json_store_1 = require("./json-store");
45
44
  function caresDir(agentRoot) {
46
45
  return path.join(agentRoot, "arc", "cares");
47
46
  }
48
- function careFilePath(agentRoot, id) {
49
- return path.join(caresDir(agentRoot), `${id}.json`);
50
- }
51
- function generateId() {
52
- const timestamp = Date.now();
53
- const random = Math.random().toString(36).slice(2, 10);
54
- return `care-${timestamp}-${random}`;
55
- }
56
47
  function createCare(agentRoot, input) {
57
48
  const now = new Date().toISOString();
58
- const id = generateId();
49
+ const id = (0, json_store_1.generateTimestampId)("care");
59
50
  const care = {
60
51
  id,
61
52
  label: input.label,
@@ -73,11 +64,7 @@ function createCare(agentRoot, input) {
73
64
  createdAt: now,
74
65
  updatedAt: now,
75
66
  };
76
- const dir = caresDir(agentRoot);
77
- fs.mkdirSync(dir, { recursive: true });
78
- const filePath = careFilePath(agentRoot, id);
79
- fs.writeFileSync(filePath, JSON.stringify(care, null, 2), "utf-8");
80
- (0, sync_1.trackSyncWrite)(filePath);
67
+ (0, json_store_1.writeJsonFile)(caresDir(agentRoot), id, care);
81
68
  (0, runtime_1.emitNervesEvent)({
82
69
  component: "heart",
83
70
  event: "heart.care_created",
@@ -88,31 +75,11 @@ function createCare(agentRoot, input) {
88
75
  }
89
76
  function readCares(agentRoot) {
90
77
  const dir = caresDir(agentRoot);
91
- if (!fs.existsSync(dir)) {
92
- (0, runtime_1.emitNervesEvent)({
93
- component: "heart",
94
- event: "heart.cares_read",
95
- message: "read cares: directory missing, returning empty",
96
- meta: { count: 0 },
97
- });
98
- return [];
99
- }
100
- const files = fs.readdirSync(dir).filter((f) => f.endsWith(".json"));
101
- const cares = [];
102
- for (const file of files) {
103
- try {
104
- const content = fs.readFileSync(path.join(dir, file), "utf-8");
105
- const care = JSON.parse(content);
106
- cares.push(care);
107
- }
108
- catch {
109
- // Skip malformed JSON files gracefully
110
- }
111
- }
78
+ const cares = (0, json_store_1.readJsonDir)(dir);
112
79
  (0, runtime_1.emitNervesEvent)({
113
80
  component: "heart",
114
81
  event: "heart.cares_read",
115
- message: `read ${cares.length} cares`,
82
+ message: cares.length === 0 ? "read cares: directory missing, returning empty" : `read ${cares.length} cares`,
116
83
  meta: { count: cares.length },
117
84
  });
118
85
  return cares;
@@ -129,16 +96,10 @@ function readActiveCares(agentRoot) {
129
96
  return active;
130
97
  }
131
98
  function readCareFile(agentRoot, id) {
132
- const filePath = careFilePath(agentRoot, id);
133
- if (!fs.existsSync(filePath)) {
134
- throw new Error(`Care not found: ${id}`);
135
- }
136
- return JSON.parse(fs.readFileSync(filePath, "utf-8"));
99
+ return (0, json_store_1.readJsonFileOrThrow)(caresDir(agentRoot), id, "Care");
137
100
  }
138
101
  function writeCareFile(agentRoot, care) {
139
- const filePath = careFilePath(agentRoot, care.id);
140
- fs.writeFileSync(filePath, JSON.stringify(care, null, 2), "utf-8");
141
- (0, sync_1.trackSyncWrite)(filePath);
102
+ (0, json_store_1.writeJsonFile)(caresDir(agentRoot), care.id, care);
142
103
  }
143
104
  function updateCare(agentRoot, id, updates) {
144
105
  const care = readCareFile(agentRoot, id);
@@ -37,21 +37,12 @@ exports.captureIntention = captureIntention;
37
37
  exports.readOpenIntentions = readOpenIntentions;
38
38
  exports.resolveIntention = resolveIntention;
39
39
  exports.dismissIntention = dismissIntention;
40
- const fs = __importStar(require("fs"));
41
40
  const path = __importStar(require("path"));
42
41
  const runtime_1 = require("../nerves/runtime");
43
- const sync_1 = require("../heart/sync");
42
+ const json_store_1 = require("./json-store");
44
43
  function intentionsDir(agentRoot) {
45
44
  return path.join(agentRoot, "arc", "intentions");
46
45
  }
47
- function intentionFilePath(agentRoot, id) {
48
- return path.join(intentionsDir(agentRoot), `${id}.json`);
49
- }
50
- function generateId() {
51
- const timestamp = Date.now();
52
- const random = Math.random().toString(36).slice(2, 10);
53
- return `int-${timestamp}-${random}`;
54
- }
55
46
  const SALIENCE_ORDER = {
56
47
  high: 3,
57
48
  medium: 2,
@@ -64,7 +55,7 @@ function salienceRank(salience) {
64
55
  }
65
56
  function captureIntention(agentRoot, input) {
66
57
  const now = new Date().toISOString();
67
- const id = generateId();
58
+ const id = (0, json_store_1.generateTimestampId)("int");
68
59
  const intention = {
69
60
  id,
70
61
  content: input.content,
@@ -78,11 +69,7 @@ function captureIntention(agentRoot, input) {
78
69
  ...(input.relatedCareId ? { relatedCareId: input.relatedCareId } : {}),
79
70
  ...(input.nudgeAfter ? { nudgeAfter: input.nudgeAfter } : {}),
80
71
  };
81
- const dir = intentionsDir(agentRoot);
82
- fs.mkdirSync(dir, { recursive: true });
83
- const filePath = intentionFilePath(agentRoot, id);
84
- fs.writeFileSync(filePath, JSON.stringify(intention, null, 2), "utf-8");
85
- (0, sync_1.trackSyncWrite)(filePath);
72
+ (0, json_store_1.writeJsonFile)(intentionsDir(agentRoot), id, intention);
86
73
  (0, runtime_1.emitNervesEvent)({
87
74
  component: "heart",
88
75
  event: "heart.intention_captured",
@@ -93,30 +80,9 @@ function captureIntention(agentRoot, input) {
93
80
  }
94
81
  function readOpenIntentions(agentRoot, options) {
95
82
  const dir = intentionsDir(agentRoot);
96
- if (!fs.existsSync(dir)) {
97
- (0, runtime_1.emitNervesEvent)({
98
- component: "heart",
99
- event: "heart.intentions_read",
100
- message: "read intentions: directory missing, returning empty",
101
- meta: { count: 0 },
102
- });
103
- return [];
104
- }
83
+ const all = (0, json_store_1.readJsonDir)(dir);
105
84
  const limit = options?.limit ?? 20;
106
- const files = fs.readdirSync(dir).filter((f) => f.endsWith(".json"));
107
- const intentions = [];
108
- for (const file of files) {
109
- try {
110
- const content = fs.readFileSync(path.join(dir, file), "utf-8");
111
- const intention = JSON.parse(content);
112
- if (intention.status === "open") {
113
- intentions.push(intention);
114
- }
115
- }
116
- catch {
117
- // Skip malformed JSON files
118
- }
119
- }
85
+ const intentions = all.filter((i) => i.status === "open");
120
86
  // Sort by salience descending, then createdAt descending
121
87
  intentions.sort((a, b) => {
122
88
  const salienceDiff = salienceRank(b.salience) - salienceRank(a.salience);
@@ -134,16 +100,10 @@ function readOpenIntentions(agentRoot, options) {
134
100
  return result;
135
101
  }
136
102
  function readIntentionFile(agentRoot, id) {
137
- const filePath = intentionFilePath(agentRoot, id);
138
- if (!fs.existsSync(filePath)) {
139
- throw new Error(`Intention not found: ${id}`);
140
- }
141
- return JSON.parse(fs.readFileSync(filePath, "utf-8"));
103
+ return (0, json_store_1.readJsonFileOrThrow)(intentionsDir(agentRoot), id, "Intention");
142
104
  }
143
105
  function writeIntentionFile(agentRoot, intention) {
144
- const filePath = intentionFilePath(agentRoot, intention.id);
145
- fs.writeFileSync(filePath, JSON.stringify(intention, null, 2), "utf-8");
146
- (0, sync_1.trackSyncWrite)(filePath);
106
+ (0, json_store_1.writeJsonFile)(intentionsDir(agentRoot), intention.id, intention);
147
107
  }
148
108
  function resolveIntention(agentRoot, id) {
149
109
  const intention = readIntentionFile(agentRoot, id);
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ /**
3
+ * Shared JSON file store helpers for arc/ modules.
4
+ *
5
+ * obligations.ts, cares.ts, and intentions.ts all use the same pattern:
6
+ * individual JSON files in a directory, with read-all / read-one / write-one
7
+ * operations. This module extracts those patterns.
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.generateTimestampId = generateTimestampId;
44
+ exports.readJsonDir = readJsonDir;
45
+ exports.readJsonFile = readJsonFile;
46
+ exports.readJsonFileOrThrow = readJsonFileOrThrow;
47
+ exports.writeJsonFile = writeJsonFile;
48
+ const fs = __importStar(require("fs"));
49
+ const path = __importStar(require("path"));
50
+ const sync_1 = require("../heart/sync");
51
+ /**
52
+ * Generate a timestamped random ID.
53
+ * @param prefix Optional prefix (e.g. "care", "int"). Omit for plain timestamp IDs.
54
+ */
55
+ function generateTimestampId(prefix) {
56
+ const timestamp = Date.now();
57
+ const random = Math.random().toString(36).slice(2, 10);
58
+ return prefix ? `${prefix}-${timestamp}-${random}` : `${timestamp}-${random}`;
59
+ }
60
+ /**
61
+ * Read all JSON files from a directory, parse each, and return an array.
62
+ * Silently skips malformed files. Returns empty array if directory is missing.
63
+ */
64
+ function readJsonDir(dir) {
65
+ if (!fs.existsSync(dir))
66
+ return [];
67
+ let entries;
68
+ try {
69
+ entries = fs.readdirSync(dir);
70
+ }
71
+ catch {
72
+ /* v8 ignore next -- defensive: readdirSync race after existsSync @preserve */
73
+ return [];
74
+ }
75
+ const jsonFiles = entries.filter((entry) => entry.endsWith(".json")).sort();
76
+ const records = [];
77
+ for (const file of jsonFiles) {
78
+ try {
79
+ const raw = fs.readFileSync(path.join(dir, file), "utf-8");
80
+ records.push(JSON.parse(raw));
81
+ }
82
+ catch {
83
+ // Skip malformed JSON files
84
+ }
85
+ }
86
+ return records;
87
+ }
88
+ /**
89
+ * Read a single JSON file by ID from a directory.
90
+ * Returns null if the file doesn't exist or is unparseable.
91
+ */
92
+ function readJsonFile(dir, id) {
93
+ try {
94
+ const raw = fs.readFileSync(path.join(dir, `${id}.json`), "utf-8");
95
+ return JSON.parse(raw);
96
+ }
97
+ catch {
98
+ return null;
99
+ }
100
+ }
101
+ /**
102
+ * Read a single JSON file by ID, throwing if not found.
103
+ */
104
+ function readJsonFileOrThrow(dir, id, label) {
105
+ const filePath = path.join(dir, `${id}.json`);
106
+ if (!fs.existsSync(filePath)) {
107
+ throw new Error(`${label} not found: ${id}`);
108
+ }
109
+ return JSON.parse(fs.readFileSync(filePath, "utf-8"));
110
+ }
111
+ /**
112
+ * Write a record to a JSON file, creating the directory if needed.
113
+ * Automatically calls trackSyncWrite.
114
+ */
115
+ function writeJsonFile(dir, id, record) {
116
+ fs.mkdirSync(dir, { recursive: true });
117
+ const filePath = path.join(dir, `${id}.json`);
118
+ fs.writeFileSync(filePath, JSON.stringify(record, null, 2), "utf-8");
119
+ (0, sync_1.trackSyncWrite)(filePath);
120
+ }
@@ -48,22 +48,13 @@ exports.createReturnObligation = createReturnObligation;
48
48
  exports.readReturnObligation = readReturnObligation;
49
49
  exports.advanceReturnObligation = advanceReturnObligation;
50
50
  exports.listActiveReturnObligations = listActiveReturnObligations;
51
- const fs = __importStar(require("fs"));
52
51
  const path = __importStar(require("path"));
53
52
  const identity_1 = require("../heart/identity");
54
53
  const runtime_1 = require("../nerves/runtime");
55
- const sync_1 = require("../heart/sync");
54
+ const json_store_1 = require("./json-store");
56
55
  function obligationsDir(agentRoot) {
57
56
  return path.join(agentRoot, "arc", "obligations");
58
57
  }
59
- function obligationFilePath(agentRoot, id) {
60
- return path.join(obligationsDir(agentRoot), `${id}.json`);
61
- }
62
- function generateId() {
63
- const timestamp = Date.now();
64
- const random = Math.random().toString(36).slice(2, 10);
65
- return `${timestamp}-${random}`;
66
- }
67
58
  function isOpenObligationStatus(status) {
68
59
  return status !== "fulfilled";
69
60
  }
@@ -72,7 +63,7 @@ function isOpenObligation(obligation) {
72
63
  }
73
64
  function createObligation(agentRoot, input) {
74
65
  const now = new Date().toISOString();
75
- const id = generateId();
66
+ const id = (0, json_store_1.generateTimestampId)();
76
67
  const obligation = {
77
68
  id,
78
69
  origin: input.origin,
@@ -82,11 +73,7 @@ function createObligation(agentRoot, input) {
82
73
  createdAt: now,
83
74
  updatedAt: now,
84
75
  };
85
- const dir = obligationsDir(agentRoot);
86
- fs.mkdirSync(dir, { recursive: true });
87
- const filePath = obligationFilePath(agentRoot, id);
88
- fs.writeFileSync(filePath, JSON.stringify(obligation, null, 2), "utf-8");
89
- (0, sync_1.trackSyncWrite)(filePath);
76
+ (0, json_store_1.writeJsonFile)(obligationsDir(agentRoot), id, obligation);
90
77
  (0, runtime_1.emitNervesEvent)({
91
78
  component: "engine",
92
79
  event: "engine.obligation_created",
@@ -101,46 +88,17 @@ function createObligation(agentRoot, input) {
101
88
  return obligation;
102
89
  }
103
90
  function readObligations(agentRoot) {
104
- const dir = obligationsDir(agentRoot);
105
- if (!fs.existsSync(dir))
106
- return [];
107
- let entries;
108
- try {
109
- entries = fs.readdirSync(dir);
110
- }
111
- catch {
112
- /* v8 ignore next -- defensive: readdirSync race after existsSync @preserve */
113
- return [];
114
- }
115
- const jsonFiles = entries.filter((entry) => entry.endsWith(".json")).sort();
116
- const obligations = [];
117
- for (const file of jsonFiles) {
118
- try {
119
- const raw = fs.readFileSync(path.join(dir, file), "utf-8");
120
- const parsed = JSON.parse(raw);
121
- if (typeof parsed.id === "string" && typeof parsed.content === "string") {
122
- obligations.push(parsed);
123
- }
124
- }
125
- catch {
126
- // skip malformed files
127
- }
128
- }
129
- return obligations;
91
+ const all = (0, json_store_1.readJsonDir)(obligationsDir(agentRoot));
92
+ return all.filter((parsed) => typeof parsed.id === "string" && typeof parsed.content === "string");
130
93
  }
131
94
  function readPendingObligations(agentRoot) {
132
95
  return readObligations(agentRoot).filter(isOpenObligation);
133
96
  }
134
97
  function advanceObligation(agentRoot, obligationId, update) {
135
- const filePath = obligationFilePath(agentRoot, obligationId);
136
- let obligation;
137
- try {
138
- const raw = fs.readFileSync(filePath, "utf-8");
139
- obligation = JSON.parse(raw);
140
- }
141
- catch {
98
+ const dir = obligationsDir(agentRoot);
99
+ const obligation = (0, json_store_1.readJsonFile)(dir, obligationId);
100
+ if (!obligation)
142
101
  return;
143
- }
144
102
  const previousStatus = obligation.status;
145
103
  if (update.status) {
146
104
  obligation.status = update.status;
@@ -161,8 +119,7 @@ function advanceObligation(agentRoot, obligationId, update) {
161
119
  obligation.latestNote = update.latestNote;
162
120
  }
163
121
  obligation.updatedAt = new Date().toISOString();
164
- fs.writeFileSync(filePath, JSON.stringify(obligation, null, 2), "utf-8");
165
- (0, sync_1.trackSyncWrite)(filePath);
122
+ (0, json_store_1.writeJsonFile)(dir, obligationId, obligation);
166
123
  (0, runtime_1.emitNervesEvent)({
167
124
  component: "engine",
168
125
  event: "engine.obligation_advanced",
@@ -181,15 +138,9 @@ function advanceObligation(agentRoot, obligationId, update) {
181
138
  }
182
139
  function fulfillObligation(agentRoot, obligationId) {
183
140
  advanceObligation(agentRoot, obligationId, { status: "fulfilled" });
184
- const filePath = obligationFilePath(agentRoot, obligationId);
185
- let obligation;
186
- try {
187
- const raw = fs.readFileSync(filePath, "utf-8");
188
- obligation = JSON.parse(raw);
189
- }
190
- catch {
141
+ const obligation = (0, json_store_1.readJsonFile)(obligationsDir(agentRoot), obligationId);
142
+ if (!obligation)
191
143
  return;
192
- }
193
144
  (0, runtime_1.emitNervesEvent)({
194
145
  component: "engine",
195
146
  event: "engine.obligation_fulfilled",
@@ -208,16 +159,15 @@ function findPendingObligationForOrigin(agentRoot, origin) {
208
159
  && ob.origin.key === origin.key);
209
160
  }
210
161
  function enrichObligation(agentRoot, id, meaning) {
211
- const filePath = obligationFilePath(agentRoot, id);
212
- if (!fs.existsSync(filePath)) {
162
+ const dir = obligationsDir(agentRoot);
163
+ const existing = (0, json_store_1.readJsonFile)(dir, id);
164
+ if (!existing) {
213
165
  throw new Error(`Obligation not found: ${id}`);
214
166
  }
215
- const raw = fs.readFileSync(filePath, "utf-8");
216
- const obligation = JSON.parse(raw);
167
+ const obligation = existing;
217
168
  obligation.meaning = meaning;
218
169
  obligation.updatedAt = new Date().toISOString();
219
- fs.writeFileSync(filePath, JSON.stringify(obligation, null, 2), "utf-8");
220
- (0, sync_1.trackSyncWrite)(filePath);
170
+ (0, json_store_1.writeJsonFile)(dir, id, obligation);
221
171
  (0, runtime_1.emitNervesEvent)({
222
172
  component: "engine",
223
173
  event: "engine.obligation_enriched",
@@ -238,10 +188,8 @@ function getReturnObligationsDir(agentName) {
238
188
  }
239
189
  function createReturnObligation(agentName, obligation) {
240
190
  const dir = getReturnObligationsDir(agentName);
241
- fs.mkdirSync(dir, { recursive: true });
191
+ (0, json_store_1.writeJsonFile)(dir, obligation.id, obligation);
242
192
  const filePath = path.join(dir, `${obligation.id}.json`);
243
- fs.writeFileSync(filePath, JSON.stringify(obligation, null, 2), "utf8");
244
- (0, sync_1.trackSyncWrite)(filePath);
245
193
  (0, runtime_1.emitNervesEvent)({
246
194
  event: "mind.obligation_created",
247
195
  component: "mind",
@@ -255,14 +203,7 @@ function createReturnObligation(agentName, obligation) {
255
203
  return filePath;
256
204
  }
257
205
  function readReturnObligation(agentName, obligationId) {
258
- const dir = getReturnObligationsDir(agentName);
259
- try {
260
- const raw = fs.readFileSync(path.join(dir, `${obligationId}.json`), "utf-8");
261
- return JSON.parse(raw);
262
- }
263
- catch {
264
- return null;
265
- }
206
+ return (0, json_store_1.readJsonFile)(getReturnObligationsDir(agentName), obligationId);
266
207
  }
267
208
  function advanceReturnObligation(agentName, obligationId, update) {
268
209
  const existing = readReturnObligation(agentName, obligationId);
@@ -275,10 +216,7 @@ function advanceReturnObligation(agentName, obligationId, update) {
275
216
  ...(update.returnedAt !== undefined ? { returnedAt: update.returnedAt } : {}),
276
217
  ...(update.returnTarget !== undefined ? { returnTarget: update.returnTarget } : {}),
277
218
  };
278
- const dir = getReturnObligationsDir(agentName);
279
- const advancedFilePath = path.join(dir, `${obligationId}.json`);
280
- fs.writeFileSync(advancedFilePath, JSON.stringify(updated, null, 2), "utf8");
281
- (0, sync_1.trackSyncWrite)(advancedFilePath);
219
+ (0, json_store_1.writeJsonFile)(getReturnObligationsDir(agentName), obligationId, updated);
282
220
  (0, runtime_1.emitNervesEvent)({
283
221
  event: "mind.obligation_advanced",
284
222
  component: "mind",
@@ -292,30 +230,8 @@ function advanceReturnObligation(agentName, obligationId, update) {
292
230
  return updated;
293
231
  }
294
232
  function listActiveReturnObligations(agentName) {
295
- const dir = getReturnObligationsDir(agentName);
296
- if (!fs.existsSync(dir))
297
- return [];
298
- let entries;
299
- try {
300
- entries = fs.readdirSync(dir);
301
- }
302
- catch {
303
- return [];
304
- }
305
- const obligations = [];
306
- for (const file of entries) {
307
- if (!file.endsWith(".json"))
308
- continue;
309
- try {
310
- const raw = fs.readFileSync(path.join(dir, file), "utf-8");
311
- const parsed = JSON.parse(raw);
312
- if (parsed.status === "queued" || parsed.status === "running") {
313
- obligations.push(parsed);
314
- }
315
- }
316
- catch {
317
- // skip unparseable
318
- }
319
- }
320
- return obligations.sort((a, b) => a.createdAt - b.createdAt);
233
+ const all = (0, json_store_1.readJsonDir)(getReturnObligationsDir(agentName));
234
+ return all
235
+ .filter((parsed) => parsed.status === "queued" || parsed.status === "running")
236
+ .sort((a, b) => a.createdAt - b.createdAt);
321
237
  }
@@ -90,7 +90,7 @@ function killOrphanProcesses() {
90
90
  // Only match daemon-owned entry points, NOT mcp-serve or other external processes
91
91
  if (line.includes("mcp-serve") || line.includes("mcp serve"))
92
92
  continue;
93
- if (!line.includes("agent-entry.js") && !line.includes("daemon-entry.js") && !line.includes("bluebubbles-entry.js") && !line.includes("teams-entry.js"))
93
+ if (!line.includes("agent-entry.js") && !line.includes("daemon-entry.js") && !line.includes("bluebubbles/entry.js") && !line.includes("teams-entry.js"))
94
94
  continue;
95
95
  const pid = parseInt(line.trim(), 10);
96
96
  if (!isNaN(pid) && pid !== process.pid)
@@ -248,7 +248,7 @@ class DaemonSenseManager {
248
248
  .map((sense) => ({
249
249
  name: `${agent}:${sense}`,
250
250
  agentArg: agent,
251
- entry: sense === "teams" ? "senses/teams-entry.js" : "senses/bluebubbles-entry.js",
251
+ entry: sense === "teams" ? "senses/teams-entry.js" : "senses/bluebubbles/entry.js",
252
252
  channel: sense,
253
253
  autoStart: true,
254
254
  }));
@@ -39,47 +39,17 @@ exports.searchJournalIndex = searchJournalIndex;
39
39
  exports.injectAssociativeRecall = injectAssociativeRecall;
40
40
  const fs = __importStar(require("fs"));
41
41
  const path = __importStar(require("path"));
42
- const config_1 = require("../heart/config");
43
42
  const runtime_1 = require("../nerves/runtime");
44
43
  const diary_1 = require("./diary");
45
- const DEFAULT_EMBEDDING_MODEL = "text-embedding-3-small";
44
+ const embedding_provider_1 = require("./embedding-provider");
46
45
  const DEFAULT_MIN_SCORE = 0.5;
47
46
  const DEFAULT_TOP_K = 3;
48
- class OpenAIEmbeddingProvider {
49
- apiKey;
50
- model;
51
- constructor(apiKey, model = DEFAULT_EMBEDDING_MODEL) {
52
- this.apiKey = apiKey;
53
- this.model = model;
54
- }
55
- async embed(texts) {
56
- const response = await fetch("https://api.openai.com/v1/embeddings", {
57
- method: "POST",
58
- headers: {
59
- Authorization: `Bearer ${this.apiKey}`,
60
- "Content-Type": "application/json",
61
- },
62
- body: JSON.stringify({
63
- model: this.model,
64
- input: texts,
65
- }),
66
- });
67
- if (!response.ok) {
68
- throw new Error(`embedding request failed: ${response.status} ${response.statusText}`);
69
- }
70
- const payload = (await response.json());
71
- if (!payload.data || payload.data.length !== texts.length) {
72
- throw new Error("embedding response missing expected vectors");
73
- }
74
- return payload.data.map((entry) => entry.embedding);
75
- }
76
- }
77
47
  function createDefaultProvider() {
78
- const apiKey = (0, config_1.getOpenAIEmbeddingsApiKey)();
79
- if (!apiKey) {
48
+ const provider = (0, embedding_provider_1.createDefaultEmbeddingProvider)();
49
+ if (!provider) {
80
50
  throw new Error("openaiEmbeddingsApiKey not configured");
81
51
  }
82
- return new OpenAIEmbeddingProvider(apiKey);
52
+ return provider;
83
53
  }
84
54
  function readFacts(diaryRoot) {
85
55
  const factsPath = path.join(diaryRoot, "facts.jsonl");