@bryti/agent 0.0.1 → 0.1.0

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 (228) hide show
  1. package/Dockerfile +27 -0
  2. package/README.md +77 -50
  3. package/config.example.yml +265 -0
  4. package/dist/active-hours.d.ts +23 -0
  5. package/dist/active-hours.d.ts.map +1 -0
  6. package/dist/active-hours.js +68 -0
  7. package/dist/active-hours.js.map +1 -0
  8. package/dist/agent.d.ts +84 -0
  9. package/dist/agent.d.ts.map +1 -0
  10. package/dist/agent.js +383 -0
  11. package/dist/agent.js.map +1 -0
  12. package/dist/channels/markdown/ir.d.ts +79 -0
  13. package/dist/channels/markdown/ir.d.ts.map +1 -0
  14. package/dist/channels/markdown/ir.js +824 -0
  15. package/dist/channels/markdown/ir.js.map +1 -0
  16. package/dist/channels/markdown/render.d.ts +35 -0
  17. package/dist/channels/markdown/render.d.ts.map +1 -0
  18. package/dist/channels/markdown/render.js +178 -0
  19. package/dist/channels/markdown/render.js.map +1 -0
  20. package/dist/channels/telegram-network-errors.d.ts +27 -0
  21. package/dist/channels/telegram-network-errors.d.ts.map +1 -0
  22. package/dist/channels/telegram-network-errors.js +156 -0
  23. package/dist/channels/telegram-network-errors.js.map +1 -0
  24. package/dist/channels/telegram.d.ts +76 -0
  25. package/dist/channels/telegram.d.ts.map +1 -0
  26. package/dist/channels/telegram.js +814 -0
  27. package/dist/channels/telegram.js.map +1 -0
  28. package/dist/channels/types.d.ts +59 -0
  29. package/dist/channels/types.d.ts.map +1 -0
  30. package/dist/channels/types.js +9 -0
  31. package/dist/channels/types.js.map +1 -0
  32. package/dist/channels/whatsapp.d.ts +45 -0
  33. package/dist/channels/whatsapp.d.ts.map +1 -0
  34. package/dist/channels/whatsapp.js +310 -0
  35. package/dist/channels/whatsapp.js.map +1 -0
  36. package/dist/cli.d.ts +13 -0
  37. package/dist/cli.d.ts.map +1 -0
  38. package/dist/cli.js +635 -0
  39. package/dist/cli.js.map +1 -0
  40. package/dist/commands.d.ts +35 -0
  41. package/dist/commands.d.ts.map +1 -0
  42. package/dist/commands.js +113 -0
  43. package/dist/commands.js.map +1 -0
  44. package/dist/compaction/history.d.ts +17 -0
  45. package/dist/compaction/history.d.ts.map +1 -0
  46. package/dist/compaction/history.js +35 -0
  47. package/dist/compaction/history.js.map +1 -0
  48. package/dist/compaction/index.d.ts +3 -0
  49. package/dist/compaction/index.d.ts.map +1 -0
  50. package/dist/compaction/index.js +3 -0
  51. package/dist/compaction/index.js.map +1 -0
  52. package/dist/compaction/proactive.d.ts +25 -0
  53. package/dist/compaction/proactive.d.ts.map +1 -0
  54. package/dist/compaction/proactive.js +87 -0
  55. package/dist/compaction/proactive.js.map +1 -0
  56. package/dist/compaction/transcript-repair.d.ts +55 -0
  57. package/dist/compaction/transcript-repair.d.ts.map +1 -0
  58. package/dist/compaction/transcript-repair.js +215 -0
  59. package/dist/compaction/transcript-repair.js.map +1 -0
  60. package/dist/config.d.ts +128 -0
  61. package/dist/config.d.ts.map +1 -0
  62. package/dist/config.js +317 -0
  63. package/dist/config.js.map +1 -0
  64. package/dist/crash-recovery.d.ts +23 -0
  65. package/dist/crash-recovery.d.ts.map +1 -0
  66. package/dist/crash-recovery.js +96 -0
  67. package/dist/crash-recovery.js.map +1 -0
  68. package/dist/defaults/extensions/EXTENSIONS.md +158 -0
  69. package/dist/defaults/extensions/documents-hedgedoc.ts +153 -0
  70. package/dist/history.d.ts +31 -0
  71. package/dist/history.d.ts.map +1 -0
  72. package/dist/history.js +49 -0
  73. package/dist/history.js.map +1 -0
  74. package/dist/index.d.ts +19 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +673 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/logger.d.ts +39 -0
  79. package/dist/logger.d.ts.map +1 -0
  80. package/dist/logger.js +143 -0
  81. package/dist/logger.js.map +1 -0
  82. package/dist/memory/conversation-search.d.ts +15 -0
  83. package/dist/memory/conversation-search.d.ts.map +1 -0
  84. package/dist/memory/conversation-search.js +60 -0
  85. package/dist/memory/conversation-search.js.map +1 -0
  86. package/dist/memory/core-memory.d.ts +28 -0
  87. package/dist/memory/core-memory.d.ts.map +1 -0
  88. package/dist/memory/core-memory.js +102 -0
  89. package/dist/memory/core-memory.js.map +1 -0
  90. package/dist/memory/embeddings.d.ts +44 -0
  91. package/dist/memory/embeddings.d.ts.map +1 -0
  92. package/dist/memory/embeddings.js +139 -0
  93. package/dist/memory/embeddings.js.map +1 -0
  94. package/dist/memory/search.d.ts +49 -0
  95. package/dist/memory/search.d.ts.map +1 -0
  96. package/dist/memory/search.js +97 -0
  97. package/dist/memory/search.js.map +1 -0
  98. package/dist/memory/store.d.ts +32 -0
  99. package/dist/memory/store.d.ts.map +1 -0
  100. package/dist/memory/store.js +205 -0
  101. package/dist/memory/store.js.map +1 -0
  102. package/dist/message-queue.d.ts +73 -0
  103. package/dist/message-queue.d.ts.map +1 -0
  104. package/dist/message-queue.js +188 -0
  105. package/dist/message-queue.js.map +1 -0
  106. package/dist/model-infra.d.ts +64 -0
  107. package/dist/model-infra.d.ts.map +1 -0
  108. package/dist/model-infra.js +202 -0
  109. package/dist/model-infra.js.map +1 -0
  110. package/dist/projection/format.d.ts +10 -0
  111. package/dist/projection/format.d.ts.map +1 -0
  112. package/dist/projection/format.js +30 -0
  113. package/dist/projection/format.js.map +1 -0
  114. package/dist/projection/index.d.ts +11 -0
  115. package/dist/projection/index.d.ts.map +1 -0
  116. package/dist/projection/index.js +9 -0
  117. package/dist/projection/index.js.map +1 -0
  118. package/dist/projection/reflection.d.ts +94 -0
  119. package/dist/projection/reflection.d.ts.map +1 -0
  120. package/dist/projection/reflection.js +334 -0
  121. package/dist/projection/reflection.js.map +1 -0
  122. package/dist/projection/store.d.ts +144 -0
  123. package/dist/projection/store.d.ts.map +1 -0
  124. package/dist/projection/store.js +519 -0
  125. package/dist/projection/store.js.map +1 -0
  126. package/dist/projection/tools.d.ts +11 -0
  127. package/dist/projection/tools.d.ts.map +1 -0
  128. package/dist/projection/tools.js +237 -0
  129. package/dist/projection/tools.js.map +1 -0
  130. package/dist/scheduler.d.ts +36 -0
  131. package/dist/scheduler.d.ts.map +1 -0
  132. package/dist/scheduler.js +286 -0
  133. package/dist/scheduler.js.map +1 -0
  134. package/dist/system-prompt.d.ts +41 -0
  135. package/dist/system-prompt.d.ts.map +1 -0
  136. package/dist/system-prompt.js +162 -0
  137. package/dist/system-prompt.js.map +1 -0
  138. package/dist/time.d.ts +52 -0
  139. package/dist/time.d.ts.map +1 -0
  140. package/dist/time.js +138 -0
  141. package/dist/time.js.map +1 -0
  142. package/dist/tools/archival-memory-tool.d.ts +8 -0
  143. package/dist/tools/archival-memory-tool.d.ts.map +1 -0
  144. package/dist/tools/archival-memory-tool.js +68 -0
  145. package/dist/tools/archival-memory-tool.js.map +1 -0
  146. package/dist/tools/conversation-search-tool.d.ts +6 -0
  147. package/dist/tools/conversation-search-tool.d.ts.map +1 -0
  148. package/dist/tools/conversation-search-tool.js +28 -0
  149. package/dist/tools/conversation-search-tool.js.map +1 -0
  150. package/dist/tools/core-memory-tool.d.ts +7 -0
  151. package/dist/tools/core-memory-tool.d.ts.map +1 -0
  152. package/dist/tools/core-memory-tool.js +59 -0
  153. package/dist/tools/core-memory-tool.js.map +1 -0
  154. package/dist/tools/fetch-url.d.ts +15 -0
  155. package/dist/tools/fetch-url.d.ts.map +1 -0
  156. package/dist/tools/fetch-url.js +76 -0
  157. package/dist/tools/fetch-url.js.map +1 -0
  158. package/dist/tools/files.d.ts +10 -0
  159. package/dist/tools/files.d.ts.map +1 -0
  160. package/dist/tools/files.js +127 -0
  161. package/dist/tools/files.js.map +1 -0
  162. package/dist/tools/index.d.ts +17 -0
  163. package/dist/tools/index.d.ts.map +1 -0
  164. package/dist/tools/index.js +118 -0
  165. package/dist/tools/index.js.map +1 -0
  166. package/dist/tools/result.d.ts +21 -0
  167. package/dist/tools/result.d.ts.map +1 -0
  168. package/dist/tools/result.js +36 -0
  169. package/dist/tools/result.js.map +1 -0
  170. package/dist/tools/skill-install.d.ts +17 -0
  171. package/dist/tools/skill-install.d.ts.map +1 -0
  172. package/dist/tools/skill-install.js +148 -0
  173. package/dist/tools/skill-install.js.map +1 -0
  174. package/dist/tools/web-search.d.ts +42 -0
  175. package/dist/tools/web-search.d.ts.map +1 -0
  176. package/dist/tools/web-search.js +237 -0
  177. package/dist/tools/web-search.js.map +1 -0
  178. package/dist/trust/guardrail.d.ts +60 -0
  179. package/dist/trust/guardrail.d.ts.map +1 -0
  180. package/dist/trust/guardrail.js +171 -0
  181. package/dist/trust/guardrail.js.map +1 -0
  182. package/dist/trust/index.d.ts +12 -0
  183. package/dist/trust/index.d.ts.map +1 -0
  184. package/dist/trust/index.js +12 -0
  185. package/dist/trust/index.js.map +1 -0
  186. package/dist/trust/store.d.ts +118 -0
  187. package/dist/trust/store.d.ts.map +1 -0
  188. package/dist/trust/store.js +209 -0
  189. package/dist/trust/store.js.map +1 -0
  190. package/dist/trust/wrapper.d.ts +36 -0
  191. package/dist/trust/wrapper.d.ts.map +1 -0
  192. package/dist/trust/wrapper.js +142 -0
  193. package/dist/trust/wrapper.js.map +1 -0
  194. package/dist/usage.d.ts +53 -0
  195. package/dist/usage.d.ts.map +1 -0
  196. package/dist/usage.js +124 -0
  197. package/dist/usage.js.map +1 -0
  198. package/dist/util/math.d.ts +9 -0
  199. package/dist/util/math.d.ts.map +1 -0
  200. package/dist/util/math.js +22 -0
  201. package/dist/util/math.js.map +1 -0
  202. package/dist/util/ssrf.d.ts +21 -0
  203. package/dist/util/ssrf.d.ts.map +1 -0
  204. package/dist/util/ssrf.js +77 -0
  205. package/dist/util/ssrf.js.map +1 -0
  206. package/dist/workers/index.d.ts +8 -0
  207. package/dist/workers/index.d.ts.map +1 -0
  208. package/dist/workers/index.js +7 -0
  209. package/dist/workers/index.js.map +1 -0
  210. package/dist/workers/registry.d.ts +53 -0
  211. package/dist/workers/registry.d.ts.map +1 -0
  212. package/dist/workers/registry.js +38 -0
  213. package/dist/workers/registry.js.map +1 -0
  214. package/dist/workers/scoped-tools.d.ts +21 -0
  215. package/dist/workers/scoped-tools.d.ts.map +1 -0
  216. package/dist/workers/scoped-tools.js +111 -0
  217. package/dist/workers/scoped-tools.js.map +1 -0
  218. package/dist/workers/spawn.d.ts +62 -0
  219. package/dist/workers/spawn.d.ts.map +1 -0
  220. package/dist/workers/spawn.js +314 -0
  221. package/dist/workers/spawn.js.map +1 -0
  222. package/dist/workers/tools.d.ts +26 -0
  223. package/dist/workers/tools.d.ts.map +1 -0
  224. package/dist/workers/tools.js +380 -0
  225. package/dist/workers/tools.js.map +1 -0
  226. package/docker-compose.yml +72 -0
  227. package/package.json +16 -1
  228. package/run.sh +27 -0
@@ -0,0 +1,519 @@
1
+ /**
2
+ * Projection store: SQLite-backed storage for forward-looking agent memory.
3
+ *
4
+ * Stores future events, plans, and commitments with a resolution
5
+ * (exact/day/week/month/someday) and lifecycle (pending -> done/cancelled/passed).
6
+ *
7
+ * Lives in the same per-user memory.db as archival memory, its own table.
8
+ *
9
+ * Key columns: summary, raw_when (what the user said), resolved_when (ISO
10
+ * datetime), resolution, recurrence (cron), trigger_on_fact (keyword trigger),
11
+ * status, and dependencies (separate table for DAG relationships).
12
+ */
13
+ import Database from "better-sqlite3";
14
+ import fs from "node:fs";
15
+ import path from "node:path";
16
+ import crypto from "node:crypto";
17
+ import { cosineSimilarity } from "../util/math.js";
18
+ function rowToProjection(row) {
19
+ let linked_ids = [];
20
+ if (row.linked_ids) {
21
+ try {
22
+ linked_ids = JSON.parse(row.linked_ids);
23
+ }
24
+ catch {
25
+ linked_ids = [];
26
+ }
27
+ }
28
+ return {
29
+ id: row.id,
30
+ summary: row.summary,
31
+ raw_when: row.raw_when,
32
+ resolved_when: row.resolved_when,
33
+ resolution: row.resolution,
34
+ recurrence: row.recurrence,
35
+ trigger_on_fact: row.trigger_on_fact,
36
+ context: row.context,
37
+ linked_ids,
38
+ status: row.status,
39
+ created_at: row.created_at,
40
+ resolved_at: row.resolved_at,
41
+ };
42
+ }
43
+ function rowToDependency(row) {
44
+ return {
45
+ id: row.id,
46
+ observer_id: row.observer_id,
47
+ subject_id: row.subject_id,
48
+ condition: row.condition,
49
+ condition_type: row.condition_type,
50
+ created_at: row.created_at,
51
+ };
52
+ }
53
+ // ---------------------------------------------------------------------------
54
+ // Factory
55
+ // ---------------------------------------------------------------------------
56
+ /**
57
+ * Open (or create) the per-user projection store. Shares memory.db with
58
+ * archival memory.
59
+ *
60
+ * Schema overview
61
+ * ---------------
62
+ * projections
63
+ * Primary record. Holds the summary, timing fields (raw_when, resolved_when,
64
+ * resolution), recurrence cron, trigger_on_fact keyword, and status.
65
+ *
66
+ * projection_links
67
+ * Many-to-many cross-reference between projections (e.g., "this task belongs
68
+ * to that project"). Links are stored as a JSON array on the projections row
69
+ * (linked_ids) and optionally in this table for reverse lookups.
70
+ *
71
+ * projection_dependencies
72
+ * DAG edges. An observer projection waits for its subject projection(s) to
73
+ * reach a condition before it becomes active. Conditions are either a status
74
+ * keyword ("done", "cancelled", "passed") or an LLM-evaluated expression.
75
+ *
76
+ * Lifecycle state machine
77
+ * -----------------------
78
+ * pending → done (agent or user explicitly resolves it)
79
+ * pending → cancelled (agent or user cancels it)
80
+ * pending → passed (autoExpire: the time window elapsed without action)
81
+ *
82
+ * Recurring projections return to pending after each firing (see rearm()).
83
+ * Trigger-based projections become active (resolution='exact') when a matching
84
+ * fact arrives via checkTriggers(), then fire on the next scheduler tick.
85
+ */
86
+ export function createProjectionStore(userId, dataDir) {
87
+ const userDir = path.join(dataDir, "users", userId);
88
+ fs.mkdirSync(userDir, { recursive: true });
89
+ const dbPath = path.join(userDir, "memory.db");
90
+ const db = new Database(dbPath);
91
+ db.pragma("journal_mode = WAL");
92
+ db.exec(`
93
+ CREATE TABLE IF NOT EXISTS projections (
94
+ id TEXT PRIMARY KEY,
95
+ summary TEXT NOT NULL,
96
+ raw_when TEXT,
97
+ resolved_when TEXT,
98
+ resolution TEXT NOT NULL DEFAULT 'day',
99
+ recurrence TEXT,
100
+ trigger_on_fact TEXT,
101
+ context TEXT,
102
+ linked_ids TEXT,
103
+ status TEXT NOT NULL DEFAULT 'pending',
104
+ created_at TEXT NOT NULL,
105
+ resolved_at TEXT
106
+ );
107
+ `);
108
+ db.exec(`
109
+ CREATE TABLE IF NOT EXISTS projection_dependencies (
110
+ id TEXT PRIMARY KEY,
111
+ observer_id TEXT NOT NULL,
112
+ subject_id TEXT NOT NULL,
113
+ condition TEXT NOT NULL,
114
+ condition_type TEXT NOT NULL DEFAULT 'status_change',
115
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
116
+ );
117
+ `);
118
+ // Migrate: add columns to existing databases that predate these features.
119
+ for (const ddl of [
120
+ `ALTER TABLE projections ADD COLUMN recurrence TEXT;`,
121
+ `ALTER TABLE projections ADD COLUMN trigger_on_fact TEXT;`,
122
+ ]) {
123
+ try {
124
+ db.exec(ddl);
125
+ }
126
+ catch {
127
+ // Column already exists — ignore
128
+ }
129
+ }
130
+ const stmtInsert = db.prepare(`
131
+ INSERT INTO projections
132
+ (id, summary, raw_when, resolved_when, resolution, recurrence, trigger_on_fact, context, linked_ids, status, created_at)
133
+ VALUES
134
+ (?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending', ?)
135
+ `);
136
+ const stmtInsertDependency = db.prepare(`
137
+ INSERT INTO projection_dependencies
138
+ (id, observer_id, subject_id, condition, condition_type, created_at)
139
+ VALUES
140
+ (?, ?, ?, ?, ?, ?)
141
+ `);
142
+ const stmtProjectionExists = db.prepare(`
143
+ SELECT id FROM projections WHERE id = ?
144
+ `);
145
+ const stmtDependencyEdges = db.prepare(`
146
+ SELECT subject_id, observer_id FROM projection_dependencies
147
+ `);
148
+ const stmtDependenciesForEvaluation = db.prepare(`
149
+ SELECT
150
+ d.id,
151
+ d.observer_id,
152
+ d.subject_id,
153
+ d.condition,
154
+ d.condition_type,
155
+ d.created_at,
156
+ s.status AS subject_status
157
+ FROM projection_dependencies d
158
+ JOIN projections o ON o.id = d.observer_id
159
+ JOIN projections s ON s.id = d.subject_id
160
+ WHERE o.status = 'pending'
161
+ `);
162
+ const stmtActivateObserver = db.prepare(`
163
+ UPDATE projections
164
+ SET resolved_when = datetime('now'), resolution = 'exact'
165
+ WHERE id = ? AND status = 'pending'
166
+ `);
167
+ const stmtDeleteDependenciesByObserver = db.prepare(`
168
+ DELETE FROM projection_dependencies WHERE observer_id = ?
169
+ `);
170
+ const stmtDependenciesList = db.prepare(`
171
+ SELECT * FROM projection_dependencies ORDER BY created_at ASC
172
+ `);
173
+ const stmtDependenciesListByObserver = db.prepare(`
174
+ SELECT * FROM projection_dependencies WHERE observer_id = ? ORDER BY created_at ASC
175
+ `);
176
+ const stmtUpcoming = db.prepare(`
177
+ SELECT * FROM projections
178
+ WHERE status = 'pending'
179
+ AND (
180
+ resolution = 'someday'
181
+ OR resolved_when IS NULL
182
+ OR resolved_when <= datetime('now', ? || ' days')
183
+ )
184
+ ORDER BY
185
+ CASE WHEN resolved_when IS NULL THEN 1 ELSE 0 END,
186
+ resolved_when ASC
187
+ `);
188
+ const stmtExactDue = db.prepare(`
189
+ SELECT * FROM projections
190
+ WHERE status = 'pending'
191
+ AND resolution = 'exact'
192
+ AND resolved_when IS NOT NULL
193
+ AND resolved_when <= datetime('now', ? || ' minutes')
194
+ AND resolved_when > datetime('now', '-10 minutes')
195
+ ORDER BY resolved_when ASC
196
+ `);
197
+ const stmtResolve = db.prepare(`
198
+ UPDATE projections
199
+ SET status = ?, resolved_at = datetime('now')
200
+ WHERE id = ? AND status = 'pending'
201
+ `);
202
+ const stmtRearm = db.prepare(`
203
+ UPDATE projections
204
+ SET status = 'pending', resolved_when = ?, resolved_at = NULL
205
+ WHERE id = ?
206
+ `);
207
+ // Fetch all pending projections that have a trigger_on_fact set.
208
+ const stmtPendingWithTriggers = db.prepare(`
209
+ SELECT * FROM projections
210
+ WHERE status = 'pending'
211
+ AND trigger_on_fact IS NOT NULL
212
+ AND trigger_on_fact != ''
213
+ `);
214
+ // Activate a trigger-matched projection: set resolved_when to now, resolution
215
+ // to 'exact', and clear trigger_on_fact so it won't re-match on future inserts.
216
+ const stmtActivateTrigger = db.prepare(`
217
+ UPDATE projections
218
+ SET resolved_when = datetime('now'), resolution = 'exact', trigger_on_fact = NULL
219
+ WHERE id = ? AND status = 'pending'
220
+ `);
221
+ const stmtExpire = db.prepare(`
222
+ UPDATE projections
223
+ SET status = 'passed', resolved_at = datetime('now')
224
+ WHERE status = 'pending'
225
+ AND resolution != 'someday'
226
+ AND resolved_when IS NOT NULL
227
+ AND (
228
+ -- Exact-time items expire after 1 hour (they either fired or were missed)
229
+ (resolution = 'exact' AND resolved_when < datetime('now', '-1 hours'))
230
+ OR
231
+ -- Day/week/month items expire after the configured threshold
232
+ (resolution != 'exact' AND resolved_when < datetime('now', ? || ' hours'))
233
+ )
234
+ `);
235
+ function inferConditionType(condition, explicit) {
236
+ if (explicit)
237
+ return explicit;
238
+ return ["done", "cancelled", "passed"].includes(condition) ? "status_change" : "llm";
239
+ }
240
+ function validateAndInsertDependency(observerId, subjectId, condition, conditionType) {
241
+ if (!condition.trim()) {
242
+ throw new Error("Dependency condition must not be empty");
243
+ }
244
+ const observerExists = stmtProjectionExists.get(observerId);
245
+ if (!observerExists) {
246
+ throw new Error(`Observer projection not found: ${observerId}`);
247
+ }
248
+ const subjectExists = stmtProjectionExists.get(subjectId);
249
+ if (!subjectExists) {
250
+ throw new Error(`Subject projection not found: ${subjectId}`);
251
+ }
252
+ if (observerId === subjectId) {
253
+ throw new Error("Projection cannot depend on itself");
254
+ }
255
+ const existingEdges = stmtDependencyEdges.all();
256
+ const edges = existingEdges.map((e) => ({ subject: e.subject_id, observer: e.observer_id }));
257
+ edges.push({ subject: subjectId, observer: observerId });
258
+ const adjacency = new Map();
259
+ for (const edge of edges) {
260
+ const list = adjacency.get(edge.subject) ?? [];
261
+ list.push(edge.observer);
262
+ adjacency.set(edge.subject, list);
263
+ }
264
+ // Cycle check: if observer can already reach subject, adding subject->observer closes a cycle.
265
+ const stack = [observerId];
266
+ const visited = new Set();
267
+ while (stack.length > 0) {
268
+ const current = stack.pop();
269
+ if (current === subjectId) {
270
+ throw new Error("Dependency cycle detected");
271
+ }
272
+ if (visited.has(current))
273
+ continue;
274
+ visited.add(current);
275
+ const next = adjacency.get(current) ?? [];
276
+ for (const n of next)
277
+ stack.push(n);
278
+ }
279
+ // Depth check across the full DAG after the new edge is considered.
280
+ const depthMemo = new Map();
281
+ const visiting = new Set();
282
+ const longestFrom = (node) => {
283
+ const cached = depthMemo.get(node);
284
+ if (cached !== undefined)
285
+ return cached;
286
+ if (visiting.has(node)) {
287
+ // Defensive guard; cycle should be caught above.
288
+ throw new Error("Dependency cycle detected");
289
+ }
290
+ visiting.add(node);
291
+ const children = adjacency.get(node) ?? [];
292
+ let best = 1;
293
+ for (const child of children) {
294
+ best = Math.max(best, 1 + longestFrom(child));
295
+ }
296
+ visiting.delete(node);
297
+ depthMemo.set(node, best);
298
+ return best;
299
+ };
300
+ const nodes = new Set([observerId, subjectId]);
301
+ for (const edge of edges) {
302
+ nodes.add(edge.subject);
303
+ nodes.add(edge.observer);
304
+ }
305
+ let maxDepth = 0;
306
+ for (const n of nodes) {
307
+ maxDepth = Math.max(maxDepth, longestFrom(n));
308
+ }
309
+ if (maxDepth > 5) {
310
+ throw new Error("Dependency chain too deep (max 5)");
311
+ }
312
+ const id = crypto.randomUUID();
313
+ const now = new Date().toISOString();
314
+ stmtInsertDependency.run(id, observerId, subjectId, condition.trim(), inferConditionType(condition.trim(), conditionType), now);
315
+ return id;
316
+ }
317
+ const addWithDependencies = db.transaction((params) => {
318
+ const id = crypto.randomUUID();
319
+ const now = new Date().toISOString();
320
+ // resolved_when is the normalised ISO datetime derived from raw_when (the
321
+ // caller is responsible for resolving natural-language expressions like
322
+ // "next Monday" before calling add()). For trigger_on_fact projections no
323
+ // resolved_when is needed upfront — checkTriggers() sets it at fire time.
324
+ stmtInsert.run(id, params.summary, params.raw_when ?? null, params.resolved_when ?? null, params.resolution ?? "day", params.recurrence ?? null, params.trigger_on_fact ?? null, params.context ?? null, params.linked_ids ? JSON.stringify(params.linked_ids) : null, now);
325
+ // Each entry in depends_on creates a DAG edge: this new projection (observer)
326
+ // will not activate until the referenced subject projection reaches its condition.
327
+ for (const dep of params.depends_on ?? []) {
328
+ validateAndInsertDependency(id, dep.subject_id, dep.condition, dep.condition_type);
329
+ }
330
+ return id;
331
+ });
332
+ return {
333
+ add({ summary, raw_when, resolved_when, resolution, recurrence, trigger_on_fact, context, linked_ids, depends_on }) {
334
+ return addWithDependencies({
335
+ summary,
336
+ raw_when,
337
+ resolved_when,
338
+ resolution,
339
+ recurrence,
340
+ trigger_on_fact,
341
+ context,
342
+ linked_ids,
343
+ depends_on,
344
+ });
345
+ },
346
+ getUpcoming(horizon_days) {
347
+ // SQL note: the ORDER BY uses a CASE expression to push rows with no
348
+ // resolved_when (someday / trigger-only items) to the end; time-bound
349
+ // projections are sorted ascending by resolved_when. Trigger-based
350
+ // projections also land here when they have no resolved_when yet; the
351
+ // caller can identify them by the non-null trigger_on_fact column.
352
+ const rows = stmtUpcoming.all(String(horizon_days));
353
+ return rows.map(rowToProjection);
354
+ },
355
+ getExactDue(window_minutes) {
356
+ // Filters to resolution='exact' only: day/week/month projections are surfaced
357
+ // through getUpcoming, not here. window_minutes must be larger than the
358
+ // scheduler tick (5 min) so that projections due between ticks are never
359
+ // skipped. The lower bound ('-10 minutes') prevents re-firing events that
360
+ // already fired but whose resolved_at hasn't been written yet.
361
+ const rows = stmtExactDue.all(String(window_minutes));
362
+ return rows.map(rowToProjection);
363
+ },
364
+ resolve(id, status) {
365
+ const result = stmtResolve.run(status, id);
366
+ return result.changes > 0;
367
+ },
368
+ rearm(id, nextResolvedWhen) {
369
+ // Only called for recurring projections after they fire. Resets status to
370
+ // 'pending' and advances resolved_when to the next occurrence so the
371
+ // scheduler will pick it up again. resolved_at is cleared so the projection
372
+ // looks fresh for the next cycle.
373
+ const result = stmtRearm.run(nextResolvedWhen, id);
374
+ return result.changes > 0;
375
+ },
376
+ async checkTriggers(factContent, embed, similarityThreshold = 0.55) {
377
+ const candidates = stmtPendingWithTriggers.all();
378
+ if (candidates.length === 0)
379
+ return [];
380
+ // Normalise the incoming fact to lowercase words for matching.
381
+ const factLower = factContent.toLowerCase();
382
+ const activated = [];
383
+ const embeddingFallback = [];
384
+ for (const row of candidates) {
385
+ const trigger = row.trigger_on_fact.toLowerCase().trim();
386
+ if (!trigger)
387
+ continue;
388
+ // Fast path (keyword matching): split trigger into tokens and require
389
+ // every token to appear in the fact text. This is O(n*m) but fast for
390
+ // short triggers. If all keywords are present the projection fires
391
+ // immediately, without involving the embedding model.
392
+ const keywords = trigger.split(/\W+/).filter(Boolean);
393
+ const allPresent = keywords.every((kw) => factLower.includes(kw));
394
+ if (allPresent) {
395
+ // Activate immediately: set resolved_when to now and resolution to
396
+ // 'exact' so the scheduler will fire this projection on the next tick.
397
+ // trigger_on_fact is cleared so it won't re-match future facts.
398
+ const result = stmtActivateTrigger.run(row.id);
399
+ if (result.changes > 0) {
400
+ const updated = { ...row, resolved_when: new Date().toISOString().slice(0, 16).replace("T", " "), resolution: "exact", trigger_on_fact: null };
401
+ activated.push(rowToProjection(updated));
402
+ }
403
+ }
404
+ else if (embed) {
405
+ // Skip embedding fallback for triggers that contain specific identifiers
406
+ // (worker IDs, UUIDs, etc.). These should only match on exact keywords,
407
+ // not semantic similarity. "worker w-abc123 complete" is semantically
408
+ // similar to "worker w-xyz789 complete" but they're about different workers.
409
+ const hasSpecificId = /w-[0-9a-f]{6,}|[0-9a-f]{8}-[0-9a-f]{4}-/.test(trigger);
410
+ if (!hasSpecificId) {
411
+ embeddingFallback.push(row);
412
+ }
413
+ }
414
+ }
415
+ // Slow path (semantic matching): embed both the fact and the trigger phrase,
416
+ // then compute cosine similarity. Projections that score above
417
+ // similarityThreshold are activated the same way as keyword matches.
418
+ // The projection is resolved immediately on trigger (rather than queued)
419
+ // because by the time checkTriggers() runs the activating fact already
420
+ // exists — there is no point delaying the notification.
421
+ if (embeddingFallback.length > 0 && embed) {
422
+ const factVec = await embed(factContent);
423
+ for (const row of embeddingFallback) {
424
+ const triggerVec = await embed(row.trigger_on_fact);
425
+ const sim = cosineSimilarity(factVec, triggerVec);
426
+ if (sim >= similarityThreshold) {
427
+ const result = stmtActivateTrigger.run(row.id);
428
+ if (result.changes > 0) {
429
+ const updated = { ...row, resolved_when: new Date().toISOString().slice(0, 16).replace("T", " "), resolution: "exact", trigger_on_fact: null };
430
+ activated.push(rowToProjection(updated));
431
+ }
432
+ }
433
+ }
434
+ }
435
+ return activated;
436
+ },
437
+ /**
438
+ * Marks pending projections as 'passed' when their resolved_when timestamp
439
+ * is more than threshold_hours hours in the past and they are still pending.
440
+ * Exact-resolution projections use a fixed 1-hour window (they either fired
441
+ * via the scheduler or were missed); all other resolutions use the caller-
442
+ * supplied threshold. Someday projections are never expired by time.
443
+ *
444
+ * Returns the number of rows updated.
445
+ */
446
+ autoExpire(threshold_hours = 24) {
447
+ const result = stmtExpire.run(String(-threshold_hours));
448
+ return result.changes;
449
+ },
450
+ linkDependency(observerId, subjectId, condition, conditionType) {
451
+ return validateAndInsertDependency(observerId, subjectId, condition, conditionType);
452
+ },
453
+ /**
454
+ * Evaluates the dependency DAG and activates any observer projections whose
455
+ * conditions are all satisfied.
456
+ *
457
+ * Evaluation is performed in a fixed-point loop (up to 10 iterations):
458
+ * activating an observer may satisfy a condition for another observer further
459
+ * up the chain, so the loop re-runs until no new activations occur.
460
+ *
461
+ * Condition types:
462
+ * 'status_change' — satisfied when subject.status equals the condition
463
+ * string (e.g., "done"). Evaluated entirely in SQL-land via a JOIN.
464
+ * 'llm' — not yet implemented; always returns false here. Future
465
+ * implementation would call completeSimple() to evaluate the condition
466
+ * expression against the current state of both projections and the
467
+ * agent's archival memory.
468
+ *
469
+ * Returns the total number of observer projections activated.
470
+ */
471
+ evaluateDependencies() {
472
+ let activatedTotal = 0;
473
+ // Iterate until stable so multiple newly-satisfied observers can activate in one pass.
474
+ for (let iteration = 0; iteration < 10; iteration++) {
475
+ const rows = stmtDependenciesForEvaluation.all();
476
+ const byObserver = new Map();
477
+ for (const row of rows) {
478
+ const group = byObserver.get(row.observer_id) ?? [];
479
+ group.push(row);
480
+ byObserver.set(row.observer_id, group);
481
+ }
482
+ let activatedThisIteration = 0;
483
+ for (const [observerId, deps] of byObserver) {
484
+ const allMet = deps.every((dep) => {
485
+ if (dep.condition_type === "status_change") {
486
+ return dep.subject_status === dep.condition;
487
+ }
488
+ // TODO: 'llm' condition type is not yet implemented. A future
489
+ // implementation would call completeSimple() with the condition
490
+ // string and the subject projection's current state to produce a
491
+ // boolean verdict, rather than relying on a fixed status keyword.
492
+ return false;
493
+ });
494
+ if (!allMet)
495
+ continue;
496
+ const result = stmtActivateObserver.run(observerId);
497
+ if (result.changes > 0) {
498
+ stmtDeleteDependenciesByObserver.run(observerId);
499
+ activatedThisIteration++;
500
+ }
501
+ }
502
+ activatedTotal += activatedThisIteration;
503
+ if (activatedThisIteration === 0)
504
+ break;
505
+ }
506
+ return activatedTotal;
507
+ },
508
+ getDependencies(observerId) {
509
+ const rows = observerId
510
+ ? stmtDependenciesListByObserver.all(observerId)
511
+ : stmtDependenciesList.all();
512
+ return rows.map(rowToDependency);
513
+ },
514
+ close() {
515
+ db.close();
516
+ },
517
+ };
518
+ }
519
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/projection/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Projection tools: create, list, resolve, and link projections.
3
+ */
4
+ import type { AgentTool } from "@mariozechner/pi-agent-core";
5
+ import type { ProjectionStore } from "./store.js";
6
+ /**
7
+ * Create projection tools. When timezone is set, naive datetimes from the
8
+ * agent are converted to UTC before storage.
9
+ */
10
+ export declare function createProjectionTools(store: ProjectionStore, timezone?: string): AgentTool<any>[];
11
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/projection/tools.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAmB,MAAM,6BAA6B,CAAC;AAG9E,OAAO,KAAK,EAAiD,eAAe,EAAE,MAAM,YAAY,CAAC;AA8HjG;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAiJjG"}