@hexis-ai/engram-sdk 0.5.0 → 0.7.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.
package/dist/client.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { ScoredSession, SearchOptions, Session, SessionStep } from "@hexis-ai/engram-core";
2
2
  import { type RefCandidate } from "./extract";
3
- import type { AliasInfo, AliasUpsert, EventBatch, IdentityInfo, IdentityUpsert, PersonCreate, PersonInfo, PersonMap, PersonUpdate, SessionEvent, SessionInit } from "./types";
3
+ import type { AliasInfo, AliasUpsert, EventBatch, IdentityInfo, IdentityUpsert, MessageContentBlock, PersonCreate, PersonInfo, PersonMap, PersonUpdate, SessionEvent, SessionInit, SessionUpdate } from "./types";
4
4
  /**
5
5
  * Envelope returned by session endpoints. The persons map is deduped
6
6
  * across whatever sessions the response carries so display info isn't
@@ -111,6 +111,12 @@ export declare class Engram {
111
111
  getSessionEvents(id: string): Promise<{
112
112
  events: SessionEvent[];
113
113
  }>;
114
+ /**
115
+ * Patch session-level metadata (title / channel / status / summary /
116
+ * model / trigger_*). `undefined` fields are left alone; explicit
117
+ * `null` clears. Returns the materialized session post-update.
118
+ */
119
+ updateSession(id: string, patch: SessionUpdate): Promise<SessionEnvelope>;
114
120
  /** List recent sessions plus the deduped persons map across them. */
115
121
  listSessions(opts?: {
116
122
  limit?: number;
@@ -190,6 +196,28 @@ export declare class EngramSession {
190
196
  * resolved by the host (engram-server does not resolve platform identities). */
191
197
  addParticipant(personId: string): void;
192
198
  setTitle(title: string): void;
199
+ /**
200
+ * Append a turn to the session. `content` is an Anthropic-shaped
201
+ * block array — the same shape monet stores in
202
+ * `conversation_messages.trace`, with `text` + `tool_use` +
203
+ * `tool_result` blocks. Re-emitting with the same `message_id` is
204
+ * intentional: the host may want to refresh content (e.g. after
205
+ * summarisation rewrites the user-visible text).
206
+ */
207
+ recordMessage(input: {
208
+ role: string;
209
+ content: MessageContentBlock[];
210
+ message_id?: string;
211
+ model?: string;
212
+ tokens?: {
213
+ input: number;
214
+ output: number;
215
+ };
216
+ /** When omitted, the SDK stamps `at` to the wall-clock moment of
217
+ * enqueue — appropriate for live agent emission. Pass an explicit
218
+ * ISO string to mirror an existing host record's timestamp. */
219
+ at?: string;
220
+ }): void;
193
221
  /** Mark the session ended and flush buffered events. */
194
222
  end(): Promise<void>;
195
223
  /**
package/dist/client.js CHANGED
@@ -49,6 +49,14 @@ export class Engram {
49
49
  async getSessionEvents(id) {
50
50
  return this.request("GET", `/v1/sessions/${encodeURIComponent(id)}/events`);
51
51
  }
52
+ /**
53
+ * Patch session-level metadata (title / channel / status / summary /
54
+ * model / trigger_*). `undefined` fields are left alone; explicit
55
+ * `null` clears. Returns the materialized session post-update.
56
+ */
57
+ async updateSession(id, patch) {
58
+ return this.request("PATCH", `/v1/sessions/${encodeURIComponent(id)}`, patch);
59
+ }
52
60
  /** List recent sessions plus the deduped persons map across them. */
53
61
  async listSessions(opts = {}) {
54
62
  const qs = new URLSearchParams();
@@ -199,6 +207,27 @@ export class EngramSession {
199
207
  };
200
208
  this.enqueue(ev);
201
209
  }
210
+ /**
211
+ * Append a turn to the session. `content` is an Anthropic-shaped
212
+ * block array — the same shape monet stores in
213
+ * `conversation_messages.trace`, with `text` + `tool_use` +
214
+ * `tool_result` blocks. Re-emitting with the same `message_id` is
215
+ * intentional: the host may want to refresh content (e.g. after
216
+ * summarisation rewrites the user-visible text).
217
+ */
218
+ recordMessage(input) {
219
+ const ev = {
220
+ type: "message",
221
+ seq: this.seq++,
222
+ at: input.at ?? new Date().toISOString(),
223
+ role: input.role,
224
+ content: input.content,
225
+ ...(input.message_id !== undefined ? { message_id: input.message_id } : {}),
226
+ ...(input.model !== undefined ? { model: input.model } : {}),
227
+ ...(input.tokens !== undefined ? { tokens: input.tokens } : {}),
228
+ };
229
+ this.enqueue(ev);
230
+ }
202
231
  /** Mark the session ended and flush buffered events. */
203
232
  async end() {
204
233
  if (this.ended)
package/dist/index.d.ts CHANGED
@@ -3,4 +3,4 @@ export { extractReferences, encodeResourceId, type RefCandidate, type ReferenceS
3
3
  export { parseToolName, type ParsedToolName } from "./tool-name";
4
4
  export { fetchIdToken, cloudRunIdTokenAuth } from "./id-token";
5
5
  export { EngramAdmin, createAdminClient, type AdminClientOptions, type CreateWorkspaceInput, type CreateWorkspaceResult, type Workspace as AdminWorkspace, type ApiKey as AdminApiKey, type IssuedKey as AdminIssuedKey, } from "./admin";
6
- export type { SessionInit, SessionAck, SessionEvent, StepEvent, ParticipantEvent, TitleEvent, EndEvent, EventBatch, PersonInfo, PersonCreate, PersonUpdate, PersonMap, AliasInfo, AliasUpsert, IdentityInfo, IdentityUpsert, } from "./types";
6
+ export type { SessionInit, SessionUpdate, SessionAck, SessionEvent, StepEvent, ParticipantEvent, TitleEvent, EndEvent, MessageContentBlock, MessageEvent, EventBatch, PersonInfo, PersonCreate, PersonUpdate, PersonMap, AliasInfo, AliasUpsert, IdentityInfo, IdentityUpsert, } from "./types";
package/dist/types.d.ts CHANGED
@@ -25,6 +25,30 @@ export interface SessionInit {
25
25
  * `participants ⊆ viewable_by`.
26
26
  */
27
27
  viewable_by?: string[];
28
+ /**
29
+ * Lifecycle state. `active` (default) → in progress; `idle` →
30
+ * inactive but resumable; `completed` → terminal. Pass at create time
31
+ * or update later with `updateSession`.
32
+ */
33
+ status?: "active" | "idle" | "completed";
34
+ /** LLM-generated summary of the session's outcome. */
35
+ summary?: string | null;
36
+ /** Model the host used for this session (e.g. `claude-opus-4-7`). */
37
+ model?: string | null;
38
+ /** Causal lineage — the conversation that triggered this one. */
39
+ trigger_conversation_id?: string | null;
40
+ /** Causal lineage — an external event (e.g. calendar event id). */
41
+ trigger_event_id?: string | null;
42
+ }
43
+ /** Patch for `updateSession`. */
44
+ export interface SessionUpdate {
45
+ title?: string | null;
46
+ channel?: string | null;
47
+ status?: "active" | "idle" | "completed";
48
+ summary?: string | null;
49
+ model?: string | null;
50
+ trigger_conversation_id?: string | null;
51
+ trigger_event_id?: string | null;
28
52
  }
29
53
  export interface SessionAck {
30
54
  id: string;
@@ -54,27 +78,103 @@ export interface EndEvent {
54
78
  seq: number;
55
79
  at: string;
56
80
  }
57
- export type SessionEvent = StepEvent | ParticipantEvent | TitleEvent | EndEvent;
81
+ /**
82
+ * One block within a message's content. Modelled after Anthropic's
83
+ * Messages API content blocks so SDK callers can pass agent runtime
84
+ * output through with zero translation. The discriminated union covers
85
+ * the standard block types; unknown `type` values pass through
86
+ * untouched so future Anthropic / vendor blocks don't require an SDK
87
+ * upgrade to ingest.
88
+ */
89
+ export type MessageContentBlock = {
90
+ type: "text";
91
+ text: string;
92
+ } | {
93
+ type: "tool_use";
94
+ id: string;
95
+ name: string;
96
+ input: unknown;
97
+ } | {
98
+ type: "tool_result";
99
+ tool_use_id: string;
100
+ content: unknown;
101
+ is_error?: boolean;
102
+ } | {
103
+ type: "thinking";
104
+ thinking: string;
105
+ } | {
106
+ type: string;
107
+ [k: string]: unknown;
108
+ };
109
+ /**
110
+ * One turn in a session — the canonical record of what someone or the
111
+ * agent actually said/did. Carries the full Anthropic-shaped content
112
+ * (text + tool_use + tool_result + thinking + …) so engram is lossless
113
+ * relative to monet's PG transcript.
114
+ *
115
+ * `role` is intentionally `string` rather than `user|assistant` because
116
+ * monet-style channel-originated turns use richer role labels (`system`,
117
+ * `resume`, identity refs like `slack:U…`). Tighten to a union on the
118
+ * read side if a consumer needs it; the wire stays permissive.
119
+ */
120
+ export interface MessageEvent {
121
+ type: "message";
122
+ seq: number;
123
+ at: string;
124
+ /** Stable host-side id (monet's `conversation_messages` row id). The
125
+ * same logical message can be re-emitted idempotently if the host
126
+ * needs to update content (e.g. summarisation rewrite). */
127
+ message_id?: string;
128
+ role: string;
129
+ content: MessageContentBlock[];
130
+ /** Model + usage metadata captured at write time. Optional because
131
+ * inbound channel messages (slack, calendar) don't have these. */
132
+ model?: string;
133
+ tokens?: {
134
+ input: number;
135
+ output: number;
136
+ };
137
+ }
138
+ export type SessionEvent = StepEvent | ParticipantEvent | TitleEvent | EndEvent | MessageEvent;
58
139
  export interface EventBatch {
59
140
  events: SessionEvent[];
60
141
  }
61
142
  /**
62
- * Minimal representation engram-server returns for any person. Hosts cache
63
- * `display_name` for UI rendering; richer profile attributes (role, team,
64
- * etc.) are intentionally NOT herethose belong to HR / source-of-truth
65
- * systems the host integrates with.
143
+ * The canonical record for one person in a workspace. Now that engram
144
+ * is the host's primary memory store, this carries the organizational
145
+ * facts (role / team / source) too not just the minimal display
146
+ * surface earlier versions exposed. Older fields stay, new fields are
147
+ * additive and optional so existing clients aren't disturbed.
66
148
  */
67
149
  export interface PersonInfo {
68
150
  id: string;
69
151
  display_name: string | null;
152
+ /** Free-form job title, e.g. "engineer", "designer". */
153
+ role?: string | null;
154
+ /** Free-form team name, e.g. "engineering", "design". */
155
+ team?: string | null;
156
+ /**
157
+ * How this row was authored. Mirrors monet's enum:
158
+ * - `user_provided` — entered by a human via the UI.
159
+ * - `auto` — synthesised by identity-resolver from an external
160
+ * identity (slack profile, gcal attendee, …).
161
+ * Server-side defaults to `auto` when omitted.
162
+ */
163
+ source?: string;
70
164
  created_at: string;
71
165
  updated_at: string;
72
166
  }
73
167
  export interface PersonCreate {
74
168
  display_name?: string;
169
+ role?: string | null;
170
+ team?: string | null;
171
+ source?: string;
75
172
  }
76
173
  export interface PersonUpdate {
77
174
  display_name?: string | null;
175
+ role?: string | null;
176
+ team?: string | null;
177
+ source?: string;
78
178
  }
79
179
  /**
80
180
  * One alias (alternate name) for a person, mirrored from monet's
@@ -121,8 +221,16 @@ export interface IdentityInfo {
121
221
  source: string | null;
122
222
  is_primary: boolean | null;
123
223
  picture: string | null;
124
- /** `YYYY-MM-DD`. */
224
+ /** ISO 8601 timestamp (post-migration 0004) or `YYYY-MM-DD` from
225
+ * pre-migration rows. Treat as a parseable date string either way. */
125
226
  linked_at: string;
227
+ /**
228
+ * ISO 8601 timestamp of when the link was revoked. Null while the
229
+ * identity is active; non-null means callers should not treat it as
230
+ * an authoritative source for this person → external mapping.
231
+ * Available only after migration 0004.
232
+ */
233
+ unlinked_at?: string | null;
126
234
  created_at: string;
127
235
  updated_at: string;
128
236
  }
@@ -134,8 +242,14 @@ export interface IdentityUpsert {
134
242
  source?: string | null;
135
243
  is_primary?: boolean | null;
136
244
  picture?: string | null;
137
- /** `YYYY-MM-DD`. */
245
+ /** ISO 8601 timestamp or `YYYY-MM-DD`. */
138
246
  linked_at: string;
247
+ /**
248
+ * Setting non-null marks the identity as revoked. Most upsert calls
249
+ * leave this undefined (no change); pass `null` to explicitly clear
250
+ * a previous revoke.
251
+ */
252
+ unlinked_at?: string | null;
139
253
  }
140
254
  /**
141
255
  * Map of person_id → PersonInfo, deduped across whatever `Session`s the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexis-ai/engram-sdk",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Host SDK for engram. Records agent session steps and ships them to an engram server.",
5
5
  "keywords": [
6
6
  "engram",