@hexis-ai/engram-server 0.10.0 → 0.11.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.
@@ -29,7 +29,11 @@ export declare class InMemoryAdapter implements StorageAdapter {
29
29
  listSessions(opts: {
30
30
  limit: number;
31
31
  channel?: string;
32
+ channel_prefix?: string;
32
33
  status?: "active" | "idle" | "completed";
34
+ has_trigger?: boolean;
35
+ no_summary?: boolean;
36
+ updated_before?: string;
33
37
  }): Promise<Session[]>;
34
38
  sessionsForPerson(personId: string, opts: {
35
39
  limit: number;
@@ -147,8 +147,17 @@ export class InMemoryAdapter {
147
147
  for (const stored of this.sessions.values()) {
148
148
  if (opts.channel && stored.row.channel !== opts.channel)
149
149
  continue;
150
+ if (opts.channel_prefix &&
151
+ !(stored.row.channel ?? "").startsWith(opts.channel_prefix))
152
+ continue;
150
153
  if (opts.status && stored.row.status !== opts.status)
151
154
  continue;
155
+ if (opts.has_trigger && stored.row.trigger_conversation_id == null)
156
+ continue;
157
+ if (opts.no_summary && stored.row.summary != null)
158
+ continue;
159
+ if (opts.updated_before && stored.row.updatedAt >= opts.updated_before)
160
+ continue;
152
161
  all.push({
153
162
  s: foldEvents(stored.row, [...stored.events.values()], now),
154
163
  updatedAt: stored.row.updatedAt,
@@ -42,7 +42,11 @@ export declare class PostgresAdapter implements StorageAdapter {
42
42
  listSessions(opts: {
43
43
  limit: number;
44
44
  channel?: string;
45
+ channel_prefix?: string;
45
46
  status?: "active" | "idle" | "completed";
47
+ has_trigger?: boolean;
48
+ no_summary?: boolean;
49
+ updated_before?: string;
46
50
  }): Promise<Session[]>;
47
51
  sessionsForPerson(personId: string, opts: {
48
52
  limit: number;
@@ -173,12 +173,20 @@ export class PostgresAdapter {
173
173
  }
174
174
  async listSessions(opts) {
175
175
  const channelFilter = opts.channel ?? null;
176
+ const channelPrefix = opts.channel_prefix ?? null;
176
177
  const statusFilter = opts.status ?? null;
178
+ const hasTrigger = opts.has_trigger === true;
179
+ const noSummary = opts.no_summary === true;
180
+ const updatedBefore = opts.updated_before ?? null;
177
181
  const rows = await this.sql `
178
182
  SELECT id FROM engram_sessions
179
183
  WHERE workspace_id = ${this.workspaceId}
180
184
  AND (${channelFilter}::text IS NULL OR channel = ${channelFilter}::text)
185
+ AND (${channelPrefix}::text IS NULL OR channel LIKE ${channelPrefix ? channelPrefix + "%" : null}::text)
181
186
  AND (${statusFilter}::text IS NULL OR status = ${statusFilter}::text)
187
+ AND (${hasTrigger}::boolean = FALSE OR trigger_conversation_id IS NOT NULL)
188
+ AND (${noSummary}::boolean = FALSE OR summary IS NULL)
189
+ AND (${updatedBefore}::timestamptz IS NULL OR updated_at < ${updatedBefore}::timestamptz)
182
190
  ORDER BY updated_at DESC
183
191
  LIMIT ${opts.limit}
184
192
  `;
@@ -63,14 +63,22 @@ export function sessionsRoutes(cfg) {
63
63
  app.get("/sessions", async (c) => {
64
64
  const limit = clampLimit(c, cfg.defaultListLimit, cfg.maxListLimit);
65
65
  const channel = c.req.query("channel") || undefined;
66
+ const channel_prefix = c.req.query("channel_prefix") || undefined;
66
67
  const rawStatus = c.req.query("status");
67
68
  const status = rawStatus === "active" || rawStatus === "idle" || rawStatus === "completed"
68
69
  ? rawStatus
69
70
  : undefined;
71
+ const has_trigger = c.req.query("has_trigger") === "true" || undefined;
72
+ const no_summary = c.req.query("no_summary") === "true" || undefined;
73
+ const updated_before = c.req.query("updated_before") || undefined;
70
74
  const sessions = await c.var.ctx.storage.listSessions({
71
75
  limit,
72
76
  channel,
77
+ channel_prefix,
73
78
  status,
79
+ has_trigger,
80
+ no_summary,
81
+ updated_before,
74
82
  });
75
83
  const persons = await resolvePersonMap(c.var.ctx.storage, sessions);
76
84
  return c.json({ sessions, persons });
package/dist/storage.d.ts CHANGED
@@ -33,11 +33,27 @@ export interface StorageAdapter {
33
33
  * events, which returns `[]`).
34
34
  */
35
35
  getSessionEvents(sessionId: string): Promise<SessionEvent[] | null>;
36
- /** List recent sessions, ordered by `updated_at` desc. */
36
+ /**
37
+ * List recent sessions, ordered by `updated_at` desc.
38
+ *
39
+ * Filter combinations are AND'd. Pass `channel_prefix` instead of
40
+ * `channel` to match channels by prefix (e.g. `slack_dm:C123/`) —
41
+ * this is the only way to express "any thread under DM Cxxx".
42
+ * `has_trigger=true` restricts to sessions whose
43
+ * `trigger_conversation_id` is set; `no_summary=true` restricts to
44
+ * sessions whose `summary` is null. `updated_before` restricts to
45
+ * sessions whose `updated_at` is strictly less than the ISO timestamp
46
+ * — combine with `status='idle' + no_summary=true` to find idle,
47
+ * unsummarized conversations older than N minutes.
48
+ */
37
49
  listSessions(opts: {
38
50
  limit: number;
39
51
  channel?: string;
52
+ channel_prefix?: string;
40
53
  status?: "active" | "idle" | "completed";
54
+ has_trigger?: boolean;
55
+ no_summary?: boolean;
56
+ updated_before?: string;
41
57
  }): Promise<Session[]>;
42
58
  /**
43
59
  * Create a person with a freshly allocated id. The host (e.g. monet)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexis-ai/engram-server",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Engram server: ingest agent session events, persist via a pluggable adapter, expose search.",
5
5
  "keywords": [
6
6
  "engram",
@@ -49,8 +49,8 @@
49
49
  "dev": "bun --hot src/dev.ts"
50
50
  },
51
51
  "dependencies": {
52
- "@hexis-ai/engram-core": "^0.1.5",
53
- "@hexis-ai/engram-sdk": "^0.9.0",
52
+ "@hexis-ai/engram-core": "^0.2.0",
53
+ "@hexis-ai/engram-sdk": "^0.10.0",
54
54
  "hono": "^4.6.0",
55
55
  "zod": "^4.0.0"
56
56
  },