@hexis-ai/engram-sdk 0.1.4 → 0.1.5
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/admin.d.ts +60 -0
- package/dist/admin.js +62 -0
- package/dist/client.d.ts +57 -10
- package/dist/client.js +45 -4
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -0
- package/dist/types.d.ts +37 -1
- package/package.json +2 -2
package/dist/admin.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin SDK: provisions workspaces and API keys against an engram-server
|
|
3
|
+
* `/admin/v1/*` mount. Use from privileged contexts only — the admin token
|
|
4
|
+
* is platform-root and must never reach end-user code paths.
|
|
5
|
+
*/
|
|
6
|
+
export interface AdminClientOptions {
|
|
7
|
+
baseUrl: string;
|
|
8
|
+
adminToken: string;
|
|
9
|
+
fetch?: typeof fetch;
|
|
10
|
+
}
|
|
11
|
+
export interface Workspace {
|
|
12
|
+
id: string;
|
|
13
|
+
name?: string;
|
|
14
|
+
metadata?: Record<string, unknown>;
|
|
15
|
+
createdAt: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ApiKey {
|
|
18
|
+
id: string;
|
|
19
|
+
workspaceId: string;
|
|
20
|
+
prefix: string;
|
|
21
|
+
name?: string;
|
|
22
|
+
createdAt: string;
|
|
23
|
+
lastUsedAt?: string;
|
|
24
|
+
revokedAt?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface IssuedKey extends ApiKey {
|
|
27
|
+
/** Plaintext key. Stored only by the caller; never retrievable again. */
|
|
28
|
+
raw: string;
|
|
29
|
+
}
|
|
30
|
+
export interface CreateWorkspaceInput {
|
|
31
|
+
id?: string;
|
|
32
|
+
name?: string;
|
|
33
|
+
metadata?: Record<string, unknown>;
|
|
34
|
+
/** Whether to also issue an initial API key. Default true. */
|
|
35
|
+
issueKey?: boolean;
|
|
36
|
+
/** Optional name applied to the initial API key. */
|
|
37
|
+
keyName?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface CreateWorkspaceResult {
|
|
40
|
+
workspace: Workspace;
|
|
41
|
+
/** Present when `issueKey !== false`. */
|
|
42
|
+
key?: IssuedKey;
|
|
43
|
+
}
|
|
44
|
+
export declare class EngramAdmin {
|
|
45
|
+
private readonly baseUrl;
|
|
46
|
+
private readonly adminToken;
|
|
47
|
+
private readonly fetchImpl;
|
|
48
|
+
constructor(opts: AdminClientOptions);
|
|
49
|
+
createWorkspace(input?: CreateWorkspaceInput): Promise<CreateWorkspaceResult>;
|
|
50
|
+
listWorkspaces(): Promise<Workspace[]>;
|
|
51
|
+
getWorkspace(id: string): Promise<Workspace>;
|
|
52
|
+
deleteWorkspace(id: string): Promise<void>;
|
|
53
|
+
issueKey(workspaceId: string, opts?: {
|
|
54
|
+
name?: string;
|
|
55
|
+
}): Promise<IssuedKey>;
|
|
56
|
+
listKeys(workspaceId: string): Promise<ApiKey[]>;
|
|
57
|
+
revokeKey(workspaceId: string, keyId: string): Promise<void>;
|
|
58
|
+
private request;
|
|
59
|
+
}
|
|
60
|
+
export declare function createAdminClient(opts: AdminClientOptions): EngramAdmin;
|
package/dist/admin.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin SDK: provisions workspaces and API keys against an engram-server
|
|
3
|
+
* `/admin/v1/*` mount. Use from privileged contexts only — the admin token
|
|
4
|
+
* is platform-root and must never reach end-user code paths.
|
|
5
|
+
*/
|
|
6
|
+
export class EngramAdmin {
|
|
7
|
+
baseUrl;
|
|
8
|
+
adminToken;
|
|
9
|
+
fetchImpl;
|
|
10
|
+
constructor(opts) {
|
|
11
|
+
if (!opts.baseUrl)
|
|
12
|
+
throw new Error("EngramAdmin: baseUrl is required");
|
|
13
|
+
if (!opts.adminToken)
|
|
14
|
+
throw new Error("EngramAdmin: adminToken is required");
|
|
15
|
+
this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
|
|
16
|
+
this.adminToken = opts.adminToken;
|
|
17
|
+
this.fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
18
|
+
}
|
|
19
|
+
async createWorkspace(input = {}) {
|
|
20
|
+
return this.request("POST", "/admin/v1/workspaces", input);
|
|
21
|
+
}
|
|
22
|
+
async listWorkspaces() {
|
|
23
|
+
const r = await this.request("GET", "/admin/v1/workspaces");
|
|
24
|
+
return r.workspaces;
|
|
25
|
+
}
|
|
26
|
+
async getWorkspace(id) {
|
|
27
|
+
return this.request("GET", `/admin/v1/workspaces/${encodeURIComponent(id)}`);
|
|
28
|
+
}
|
|
29
|
+
async deleteWorkspace(id) {
|
|
30
|
+
await this.request("DELETE", `/admin/v1/workspaces/${encodeURIComponent(id)}`);
|
|
31
|
+
}
|
|
32
|
+
async issueKey(workspaceId, opts = {}) {
|
|
33
|
+
return this.request("POST", `/admin/v1/workspaces/${encodeURIComponent(workspaceId)}/keys`, opts);
|
|
34
|
+
}
|
|
35
|
+
async listKeys(workspaceId) {
|
|
36
|
+
const r = await this.request("GET", `/admin/v1/workspaces/${encodeURIComponent(workspaceId)}/keys`);
|
|
37
|
+
return r.keys;
|
|
38
|
+
}
|
|
39
|
+
async revokeKey(workspaceId, keyId) {
|
|
40
|
+
await this.request("DELETE", `/admin/v1/workspaces/${encodeURIComponent(workspaceId)}/keys/${encodeURIComponent(keyId)}`);
|
|
41
|
+
}
|
|
42
|
+
async request(method, path, body) {
|
|
43
|
+
const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
44
|
+
method,
|
|
45
|
+
headers: {
|
|
46
|
+
"content-type": "application/json",
|
|
47
|
+
authorization: `Bearer ${this.adminToken}`,
|
|
48
|
+
},
|
|
49
|
+
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
50
|
+
});
|
|
51
|
+
if (!res.ok) {
|
|
52
|
+
const text = await res.text().catch(() => "");
|
|
53
|
+
throw new Error(`engram-admin ${method} ${path} ${res.status}: ${text}`);
|
|
54
|
+
}
|
|
55
|
+
if (res.status === 204)
|
|
56
|
+
return undefined;
|
|
57
|
+
return (await res.json());
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export function createAdminClient(opts) {
|
|
61
|
+
return new EngramAdmin(opts);
|
|
62
|
+
}
|
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import type { ScoredSession, SearchOptions, Session, SessionStep } from "@hexis-ai/engram-core";
|
|
2
2
|
import { type RefCandidate } from "./extract";
|
|
3
|
-
import type { EventBatch, SessionInit } from "./types";
|
|
3
|
+
import type { EventBatch, PersonCreate, PersonInfo, PersonMap, PersonUpdate, SessionInit } from "./types";
|
|
4
|
+
/**
|
|
5
|
+
* Envelope returned by session endpoints. The persons map is deduped
|
|
6
|
+
* across whatever sessions the response carries so display info isn't
|
|
7
|
+
* repeated per row.
|
|
8
|
+
*/
|
|
9
|
+
export interface SessionEnvelope {
|
|
10
|
+
session: Session;
|
|
11
|
+
persons: PersonMap;
|
|
12
|
+
}
|
|
13
|
+
export interface SessionListEnvelope {
|
|
14
|
+
sessions: Session[];
|
|
15
|
+
persons: PersonMap;
|
|
16
|
+
}
|
|
17
|
+
export interface SearchEnvelope {
|
|
18
|
+
results: ScoredSession[];
|
|
19
|
+
persons: PersonMap;
|
|
20
|
+
}
|
|
4
21
|
export interface EngramOptions {
|
|
5
22
|
apiKey: string;
|
|
6
23
|
baseUrl: string;
|
|
@@ -63,9 +80,8 @@ export interface SearchRequest {
|
|
|
63
80
|
};
|
|
64
81
|
options?: SearchOptions;
|
|
65
82
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
83
|
+
/** @deprecated Use `SearchEnvelope` (carries `persons` map too). */
|
|
84
|
+
export type SearchResponse = SearchEnvelope;
|
|
69
85
|
export declare class Engram {
|
|
70
86
|
private readonly apiKey;
|
|
71
87
|
private readonly baseUrl;
|
|
@@ -78,17 +94,46 @@ export declare class Engram {
|
|
|
78
94
|
readonly maxRetries: number;
|
|
79
95
|
readonly retryBackoffMs: number;
|
|
80
96
|
constructor(opts: EngramOptions);
|
|
97
|
+
/** Probe identity — returns the workspace the configured key resolves to. */
|
|
98
|
+
me(): Promise<{
|
|
99
|
+
workspaceId: string;
|
|
100
|
+
}>;
|
|
81
101
|
/** Begin a new session. Returns a handle for buffering events. */
|
|
82
102
|
startSession(init?: SessionInit): Promise<EngramSession>;
|
|
83
|
-
/** Fetch a single
|
|
84
|
-
getSession(id: string): Promise<
|
|
85
|
-
/** List recent sessions
|
|
103
|
+
/** Fetch a single session by id, plus the persons map for its participants/viewers. */
|
|
104
|
+
getSession(id: string): Promise<SessionEnvelope>;
|
|
105
|
+
/** List recent sessions plus the deduped persons map across them. */
|
|
86
106
|
listSessions(opts?: {
|
|
87
107
|
limit?: number;
|
|
88
108
|
channel?: string;
|
|
89
|
-
}): Promise<
|
|
109
|
+
}): Promise<SessionListEnvelope>;
|
|
90
110
|
/** Run a search. */
|
|
91
|
-
search(req: SearchRequest): Promise<
|
|
111
|
+
search(req: SearchRequest): Promise<SearchEnvelope>;
|
|
112
|
+
/** Person operations. The host (e.g. monet) resolves platform identities
|
|
113
|
+
* to person ids before storing sessions; this namespace lets it own the
|
|
114
|
+
* underlying person records (display name + canonical id). */
|
|
115
|
+
readonly persons: {
|
|
116
|
+
/** Allocate a new person id and return the row. */
|
|
117
|
+
create: (input: PersonCreate) => Promise<PersonInfo>;
|
|
118
|
+
/** Upsert at a host-supplied id (backfill / fallback). */
|
|
119
|
+
upsert: (id: string, input: PersonCreate) => Promise<PersonInfo>;
|
|
120
|
+
/** Patch profile fields. Returns 404 if id is unknown. */
|
|
121
|
+
update: (id: string, patch: PersonUpdate) => Promise<PersonInfo>;
|
|
122
|
+
get: (id: string) => Promise<PersonInfo>;
|
|
123
|
+
/** Free-text search (substring across id + display_name). */
|
|
124
|
+
list: (opts?: {
|
|
125
|
+
limit?: number;
|
|
126
|
+
q?: string;
|
|
127
|
+
}) => Promise<{
|
|
128
|
+
persons: PersonInfo[];
|
|
129
|
+
}>;
|
|
130
|
+
/** Sessions where this person appears in participants (default) or viewable_by. */
|
|
131
|
+
sessions: (id: string, opts?: {
|
|
132
|
+
limit?: number;
|
|
133
|
+
channel?: string;
|
|
134
|
+
scope?: "participant" | "viewable";
|
|
135
|
+
}) => Promise<SessionListEnvelope>;
|
|
136
|
+
};
|
|
92
137
|
/** Internal: ship an event batch to the server. */
|
|
93
138
|
sendBatch(sessionId: string, batch: EventBatch): Promise<void>;
|
|
94
139
|
/** Internal accessor used by EngramSession to honor SDK config. */
|
|
@@ -109,7 +154,9 @@ export declare class EngramSession {
|
|
|
109
154
|
private ended;
|
|
110
155
|
constructor(engram: Engram, id: string);
|
|
111
156
|
recordStep(input: RecordStepInput): SessionStep;
|
|
112
|
-
|
|
157
|
+
/** Append a participant to the running session. `personId` must already be
|
|
158
|
+
* resolved by the host (engram-server does not resolve platform identities). */
|
|
159
|
+
addParticipant(personId: string): void;
|
|
113
160
|
setTitle(title: string): void;
|
|
114
161
|
/** Mark the session ended and flush buffered events. */
|
|
115
162
|
end(): Promise<void>;
|
package/dist/client.js
CHANGED
|
@@ -27,16 +27,20 @@ export class Engram {
|
|
|
27
27
|
this.maxRetries = opts.maxRetries ?? 4;
|
|
28
28
|
this.retryBackoffMs = opts.retryBackoffMs ?? 500;
|
|
29
29
|
}
|
|
30
|
+
/** Probe identity — returns the workspace the configured key resolves to. */
|
|
31
|
+
async me() {
|
|
32
|
+
return this.request("GET", "/v1/me");
|
|
33
|
+
}
|
|
30
34
|
/** Begin a new session. Returns a handle for buffering events. */
|
|
31
35
|
async startSession(init = {}) {
|
|
32
36
|
const ack = await this.request("POST", "/v1/sessions", init);
|
|
33
37
|
return new EngramSession(this, ack.id);
|
|
34
38
|
}
|
|
35
|
-
/** Fetch a single
|
|
39
|
+
/** Fetch a single session by id, plus the persons map for its participants/viewers. */
|
|
36
40
|
async getSession(id) {
|
|
37
41
|
return this.request("GET", `/v1/sessions/${encodeURIComponent(id)}`);
|
|
38
42
|
}
|
|
39
|
-
/** List recent sessions
|
|
43
|
+
/** List recent sessions plus the deduped persons map across them. */
|
|
40
44
|
async listSessions(opts = {}) {
|
|
41
45
|
const qs = new URLSearchParams();
|
|
42
46
|
if (opts.limit !== undefined)
|
|
@@ -50,6 +54,41 @@ export class Engram {
|
|
|
50
54
|
async search(req) {
|
|
51
55
|
return this.request("POST", "/v1/search", req);
|
|
52
56
|
}
|
|
57
|
+
// ---- Persons ----
|
|
58
|
+
/** Person operations. The host (e.g. monet) resolves platform identities
|
|
59
|
+
* to person ids before storing sessions; this namespace lets it own the
|
|
60
|
+
* underlying person records (display name + canonical id). */
|
|
61
|
+
persons = {
|
|
62
|
+
/** Allocate a new person id and return the row. */
|
|
63
|
+
create: (input) => this.request("POST", "/v1/persons", input),
|
|
64
|
+
/** Upsert at a host-supplied id (backfill / fallback). */
|
|
65
|
+
upsert: (id, input) => this.request("PUT", `/v1/persons/${encodeURIComponent(id)}`, input),
|
|
66
|
+
/** Patch profile fields. Returns 404 if id is unknown. */
|
|
67
|
+
update: (id, patch) => this.request("PATCH", `/v1/persons/${encodeURIComponent(id)}`, patch),
|
|
68
|
+
get: (id) => this.request("GET", `/v1/persons/${encodeURIComponent(id)}`),
|
|
69
|
+
/** Free-text search (substring across id + display_name). */
|
|
70
|
+
list: (opts = {}) => {
|
|
71
|
+
const qs = new URLSearchParams();
|
|
72
|
+
if (opts.limit !== undefined)
|
|
73
|
+
qs.set("limit", String(opts.limit));
|
|
74
|
+
if (opts.q)
|
|
75
|
+
qs.set("q", opts.q);
|
|
76
|
+
const tail = qs.toString();
|
|
77
|
+
return this.request("GET", `/v1/persons${tail ? `?${tail}` : ""}`);
|
|
78
|
+
},
|
|
79
|
+
/** Sessions where this person appears in participants (default) or viewable_by. */
|
|
80
|
+
sessions: (id, opts = {}) => {
|
|
81
|
+
const qs = new URLSearchParams();
|
|
82
|
+
if (opts.limit !== undefined)
|
|
83
|
+
qs.set("limit", String(opts.limit));
|
|
84
|
+
if (opts.channel)
|
|
85
|
+
qs.set("channel", opts.channel);
|
|
86
|
+
if (opts.scope)
|
|
87
|
+
qs.set("scope", opts.scope);
|
|
88
|
+
const tail = qs.toString();
|
|
89
|
+
return this.request("GET", `/v1/persons/${encodeURIComponent(id)}/sessions${tail ? `?${tail}` : ""}`);
|
|
90
|
+
},
|
|
91
|
+
};
|
|
53
92
|
/** Internal: ship an event batch to the server. */
|
|
54
93
|
async sendBatch(sessionId, batch) {
|
|
55
94
|
if (batch.events.length === 0)
|
|
@@ -112,12 +151,14 @@ export class EngramSession {
|
|
|
112
151
|
this.enqueue(ev);
|
|
113
152
|
return { tool, resources };
|
|
114
153
|
}
|
|
115
|
-
|
|
154
|
+
/** Append a participant to the running session. `personId` must already be
|
|
155
|
+
* resolved by the host (engram-server does not resolve platform identities). */
|
|
156
|
+
addParticipant(personId) {
|
|
116
157
|
const ev = {
|
|
117
158
|
type: "participant",
|
|
118
159
|
seq: this.seq++,
|
|
119
160
|
at: new Date().toISOString(),
|
|
120
|
-
|
|
161
|
+
personId,
|
|
121
162
|
};
|
|
122
163
|
this.enqueue(ev);
|
|
123
164
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export { Engram, EngramSession, type EngramOptions, type RecordStepInput, type SearchRequest, type SearchResponse, } from "./client";
|
|
1
|
+
export { Engram, EngramSession, type EngramOptions, type RecordStepInput, type SearchRequest, type SearchResponse, type SearchEnvelope, type SessionEnvelope, type SessionListEnvelope, } from "./client";
|
|
2
2
|
export { extractReferences, encodeResourceId, type RefCandidate, type ReferenceService, type ReferenceAction, } from "./extract";
|
|
3
3
|
export { parseToolName, type ParsedToolName } from "./tool-name";
|
|
4
4
|
export { fetchIdToken, cloudRunIdTokenAuth } from "./id-token";
|
|
5
|
-
export
|
|
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, } from "./types";
|
package/dist/index.js
CHANGED
|
@@ -2,3 +2,4 @@ export { Engram, EngramSession, } from "./client";
|
|
|
2
2
|
export { extractReferences, encodeResourceId, } from "./extract";
|
|
3
3
|
export { parseToolName } from "./tool-name";
|
|
4
4
|
export { fetchIdToken, cloudRunIdTokenAuth } from "./id-token";
|
|
5
|
+
export { EngramAdmin, createAdminClient, } from "./admin";
|
package/dist/types.d.ts
CHANGED
|
@@ -13,7 +13,18 @@ export interface SessionInit {
|
|
|
13
13
|
* (e.g. `chat_ui`, `slack_dm`, `cron:dailyDigest`).
|
|
14
14
|
*/
|
|
15
15
|
channel?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Person ids that took part. The host (e.g. monet) is responsible for
|
|
18
|
+
* resolving platform identities (slack:U..., email:...) to person ids
|
|
19
|
+
* before calling startSession.
|
|
20
|
+
*/
|
|
16
21
|
participants?: string[];
|
|
22
|
+
/**
|
|
23
|
+
* Person ids that may view this session. Defaults to participants when
|
|
24
|
+
* omitted. engram-server unions this with participants to guarantee
|
|
25
|
+
* `participants ⊆ viewable_by`.
|
|
26
|
+
*/
|
|
27
|
+
viewable_by?: string[];
|
|
17
28
|
}
|
|
18
29
|
export interface SessionAck {
|
|
19
30
|
id: string;
|
|
@@ -29,7 +40,8 @@ export interface ParticipantEvent {
|
|
|
29
40
|
type: "participant";
|
|
30
41
|
seq: number;
|
|
31
42
|
at: string;
|
|
32
|
-
|
|
43
|
+
/** Person id (resolved by the host). */
|
|
44
|
+
personId: string;
|
|
33
45
|
}
|
|
34
46
|
export interface TitleEvent {
|
|
35
47
|
type: "title";
|
|
@@ -46,3 +58,27 @@ export type SessionEvent = StepEvent | ParticipantEvent | TitleEvent | EndEvent;
|
|
|
46
58
|
export interface EventBatch {
|
|
47
59
|
events: SessionEvent[];
|
|
48
60
|
}
|
|
61
|
+
/**
|
|
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 here — those belong to HR / source-of-truth
|
|
65
|
+
* systems the host integrates with.
|
|
66
|
+
*/
|
|
67
|
+
export interface PersonInfo {
|
|
68
|
+
id: string;
|
|
69
|
+
display_name: string | null;
|
|
70
|
+
created_at: string;
|
|
71
|
+
updated_at: string;
|
|
72
|
+
}
|
|
73
|
+
export interface PersonCreate {
|
|
74
|
+
display_name?: string;
|
|
75
|
+
}
|
|
76
|
+
export interface PersonUpdate {
|
|
77
|
+
display_name?: string | null;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Map of person_id → PersonInfo, deduped across whatever `Session`s the
|
|
81
|
+
* response contains. Returned at the envelope level so list responses
|
|
82
|
+
* don't repeat the same person info per row.
|
|
83
|
+
*/
|
|
84
|
+
export type PersonMap = Record<string, PersonInfo>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hexis-ai/engram-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Host SDK for engram. Records agent session steps and ships them to an engram server.",
|
|
5
5
|
"keywords": ["engram", "agents", "claude", "anthropic", "sdk", "observability"],
|
|
6
6
|
"homepage": "https://github.com/hexis-ltd/engram#readme",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"type-check": "tsc --noEmit"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@hexis-ai/engram-core": "^0.1.
|
|
43
|
+
"@hexis-ai/engram-core": "^0.1.5"
|
|
44
44
|
},
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public"
|