@hexis-ai/engram-sdk 0.13.0 → 0.15.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/admin.d.ts +14 -4
- package/dist/admin.js +29 -27
- package/dist/client.d.ts +1 -5
- package/dist/client.js +14 -35
- package/dist/http.d.ts +24 -0
- package/dist/http.js +37 -0
- package/dist/types.d.ts +13 -0
- package/package.json +2 -2
package/dist/admin.d.ts
CHANGED
|
@@ -77,10 +77,7 @@ export interface OrgWorkspace {
|
|
|
77
77
|
orgId: string;
|
|
78
78
|
}
|
|
79
79
|
export declare class EngramAdmin {
|
|
80
|
-
private readonly
|
|
81
|
-
private readonly adminToken;
|
|
82
|
-
private readonly fetchImpl;
|
|
83
|
-
private readonly authHeaders?;
|
|
80
|
+
private readonly http;
|
|
84
81
|
constructor(opts: AdminClientOptions);
|
|
85
82
|
createWorkspace(input?: CreateWorkspaceInput): Promise<CreateWorkspaceResult>;
|
|
86
83
|
listWorkspaces(): Promise<Workspace[]>;
|
|
@@ -101,6 +98,19 @@ export declare class EngramAdmin {
|
|
|
101
98
|
/** Create a workspace under an org and (by default) issue an api key. */
|
|
102
99
|
createWorkspaceUnderOrg(orgId: string, input?: CreateWorkspaceInput): Promise<CreateWorkspaceResult>;
|
|
103
100
|
listOrgWorkspaces(orgId: string): Promise<OrgWorkspace[]>;
|
|
101
|
+
/**
|
|
102
|
+
* Issue a fresh API key for a workspace under an org. Org-scoped
|
|
103
|
+
* replacement for the legacy `issueKey(workspaceId, ...)` which
|
|
104
|
+
* targeted `/admin/v1/workspaces/:id/keys`. Use this for key
|
|
105
|
+
* rotation after the initial `createWorkspaceUnderOrg`.
|
|
106
|
+
*/
|
|
107
|
+
issueWorkspaceKey(orgId: string, workspaceId: string, opts?: {
|
|
108
|
+
name?: string;
|
|
109
|
+
}): Promise<IssuedKey>;
|
|
110
|
+
/** List the API keys of an org-owned workspace. */
|
|
111
|
+
listWorkspaceKeys(orgId: string, workspaceId: string): Promise<ApiKey[]>;
|
|
112
|
+
/** Revoke an API key on an org-owned workspace. */
|
|
113
|
+
revokeWorkspaceKey(orgId: string, workspaceId: string, keyId: string): Promise<void>;
|
|
104
114
|
private request;
|
|
105
115
|
}
|
|
106
116
|
export declare function createAdminClient(opts: AdminClientOptions): EngramAdmin;
|
package/dist/admin.js
CHANGED
|
@@ -3,20 +3,21 @@
|
|
|
3
3
|
* `/admin/v1/*` mount. Use from privileged contexts only — the admin token
|
|
4
4
|
* is platform-root and must never reach end-user code paths.
|
|
5
5
|
*/
|
|
6
|
+
import { createHttpClient } from "./http";
|
|
6
7
|
export class EngramAdmin {
|
|
7
|
-
|
|
8
|
-
adminToken;
|
|
9
|
-
fetchImpl;
|
|
10
|
-
authHeaders;
|
|
8
|
+
http;
|
|
11
9
|
constructor(opts) {
|
|
12
10
|
if (!opts.baseUrl)
|
|
13
11
|
throw new Error("EngramAdmin: baseUrl is required");
|
|
14
12
|
if (!opts.adminToken)
|
|
15
13
|
throw new Error("EngramAdmin: adminToken is required");
|
|
16
|
-
this.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
this.http = createHttpClient({
|
|
15
|
+
baseUrl: opts.baseUrl,
|
|
16
|
+
...(opts.fetch ? { fetch: opts.fetch } : {}),
|
|
17
|
+
...(opts.authHeaders ? { authHeaders: opts.authHeaders } : {}),
|
|
18
|
+
staticHeaders: { "x-admin-token": opts.adminToken },
|
|
19
|
+
errorPrefix: "engram-admin",
|
|
20
|
+
});
|
|
20
21
|
}
|
|
21
22
|
async createWorkspace(input = {}) {
|
|
22
23
|
return this.request("POST", "/admin/v1/workspaces", input);
|
|
@@ -76,25 +77,26 @@ export class EngramAdmin {
|
|
|
76
77
|
const r = await this.request("GET", `/admin/v1/orgs/${encodeURIComponent(orgId)}/workspaces`);
|
|
77
78
|
return r.workspaces;
|
|
78
79
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Issue a fresh API key for a workspace under an org. Org-scoped
|
|
82
|
+
* replacement for the legacy `issueKey(workspaceId, ...)` which
|
|
83
|
+
* targeted `/admin/v1/workspaces/:id/keys`. Use this for key
|
|
84
|
+
* rotation after the initial `createWorkspaceUnderOrg`.
|
|
85
|
+
*/
|
|
86
|
+
async issueWorkspaceKey(orgId, workspaceId, opts = {}) {
|
|
87
|
+
return this.request("POST", `/admin/v1/orgs/${encodeURIComponent(orgId)}/workspaces/${encodeURIComponent(workspaceId)}/keys`, opts);
|
|
88
|
+
}
|
|
89
|
+
/** List the API keys of an org-owned workspace. */
|
|
90
|
+
async listWorkspaceKeys(orgId, workspaceId) {
|
|
91
|
+
const r = await this.request("GET", `/admin/v1/orgs/${encodeURIComponent(orgId)}/workspaces/${encodeURIComponent(workspaceId)}/keys`);
|
|
92
|
+
return r.keys;
|
|
93
|
+
}
|
|
94
|
+
/** Revoke an API key on an org-owned workspace. */
|
|
95
|
+
async revokeWorkspaceKey(orgId, workspaceId, keyId) {
|
|
96
|
+
await this.request("DELETE", `/admin/v1/orgs/${encodeURIComponent(orgId)}/workspaces/${encodeURIComponent(workspaceId)}/keys/${encodeURIComponent(keyId)}`);
|
|
97
|
+
}
|
|
98
|
+
request(method, path, body) {
|
|
99
|
+
return this.http.request(method, path, body);
|
|
98
100
|
}
|
|
99
101
|
}
|
|
100
102
|
export function createAdminClient(opts) {
|
package/dist/client.d.ts
CHANGED
|
@@ -84,14 +84,10 @@ export interface SearchRequest {
|
|
|
84
84
|
/** @deprecated Use `SearchEnvelope` (carries `persons` map too). */
|
|
85
85
|
export type SearchResponse = SearchEnvelope;
|
|
86
86
|
export declare class Engram {
|
|
87
|
-
private readonly
|
|
88
|
-
private readonly baseUrl;
|
|
89
|
-
private readonly fetchImpl;
|
|
87
|
+
private readonly http;
|
|
90
88
|
private readonly flushIntervalMs;
|
|
91
89
|
private readonly batchSize;
|
|
92
90
|
private readonly onError;
|
|
93
|
-
private readonly apiKeyHeader;
|
|
94
|
-
private readonly authHeaders?;
|
|
95
91
|
readonly maxRetries: number;
|
|
96
92
|
readonly retryBackoffMs: number;
|
|
97
93
|
private telemetry;
|
package/dist/client.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { encodeResourceId, extractReferences } from "./extract";
|
|
2
2
|
import { parseToolName } from "./tool-name";
|
|
3
3
|
import { BufferedTelemetry, } from "./buffered";
|
|
4
|
+
import { createHttpClient } from "./http";
|
|
4
5
|
export class Engram {
|
|
5
|
-
|
|
6
|
-
baseUrl;
|
|
7
|
-
fetchImpl;
|
|
6
|
+
http;
|
|
8
7
|
flushIntervalMs;
|
|
9
8
|
batchSize;
|
|
10
9
|
onError;
|
|
11
|
-
apiKeyHeader;
|
|
12
|
-
authHeaders;
|
|
13
10
|
maxRetries;
|
|
14
11
|
retryBackoffMs;
|
|
15
12
|
telemetry = null;
|
|
@@ -18,16 +15,21 @@ export class Engram {
|
|
|
18
15
|
throw new Error("Engram: apiKey is required");
|
|
19
16
|
if (!opts.baseUrl)
|
|
20
17
|
throw new Error("Engram: baseUrl is required");
|
|
21
|
-
this.apiKey = opts.apiKey;
|
|
22
|
-
this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
|
|
23
|
-
this.fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
24
18
|
this.flushIntervalMs = opts.flushIntervalMs ?? 2000;
|
|
25
19
|
this.batchSize = opts.batchSize ?? 32;
|
|
26
20
|
this.onError = opts.onError ?? ((e) => console.error("[engram]", e));
|
|
27
|
-
this.apiKeyHeader = opts.apiKeyHeader ?? "authorization";
|
|
28
|
-
this.authHeaders = opts.authHeaders;
|
|
29
21
|
this.maxRetries = opts.maxRetries ?? 4;
|
|
30
22
|
this.retryBackoffMs = opts.retryBackoffMs ?? 500;
|
|
23
|
+
const apiKeyHeader = opts.apiKeyHeader ?? "authorization";
|
|
24
|
+
this.http = createHttpClient({
|
|
25
|
+
baseUrl: opts.baseUrl,
|
|
26
|
+
...(opts.fetch ? { fetch: opts.fetch } : {}),
|
|
27
|
+
...(opts.authHeaders ? { authHeaders: opts.authHeaders } : {}),
|
|
28
|
+
staticHeaders: apiKeyHeader === "authorization"
|
|
29
|
+
? { authorization: `Bearer ${opts.apiKey}` }
|
|
30
|
+
: { "x-api-key": opts.apiKey },
|
|
31
|
+
errorPrefix: "engram",
|
|
32
|
+
});
|
|
31
33
|
}
|
|
32
34
|
/**
|
|
33
35
|
* Langfuse-style fire-and-forget telemetry surface. Lazily initialised
|
|
@@ -254,31 +256,8 @@ export class Engram {
|
|
|
254
256
|
get config() {
|
|
255
257
|
return { flushIntervalMs: this.flushIntervalMs, batchSize: this.batchSize, onError: this.onError };
|
|
256
258
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
if (this.apiKeyHeader === "authorization") {
|
|
260
|
-
headers["authorization"] = `Bearer ${this.apiKey}`;
|
|
261
|
-
}
|
|
262
|
-
else {
|
|
263
|
-
headers["x-api-key"] = this.apiKey;
|
|
264
|
-
}
|
|
265
|
-
if (this.authHeaders)
|
|
266
|
-
Object.assign(headers, await this.authHeaders());
|
|
267
|
-
const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
268
|
-
method,
|
|
269
|
-
headers,
|
|
270
|
-
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
271
|
-
});
|
|
272
|
-
if (!res.ok) {
|
|
273
|
-
const text = await res.text().catch(() => "");
|
|
274
|
-
throw new Error(`engram ${method} ${path} ${res.status}: ${text}`);
|
|
275
|
-
}
|
|
276
|
-
if (res.status === 204)
|
|
277
|
-
return undefined;
|
|
278
|
-
const ct = res.headers.get("content-type") ?? "";
|
|
279
|
-
if (!ct.includes("application/json"))
|
|
280
|
-
return undefined;
|
|
281
|
-
return (await res.json());
|
|
259
|
+
request(method, path, body) {
|
|
260
|
+
return this.http.request(method, path, body);
|
|
282
261
|
}
|
|
283
262
|
}
|
|
284
263
|
export class EngramSession {
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal JSON HTTP client shared by `Engram` (workspace api-key) and
|
|
3
|
+
* `EngramAdmin` (platform admin token). Encapsulates baseUrl normalisation,
|
|
4
|
+
* header merging, request body serialisation, and the small JSON-or-empty
|
|
5
|
+
* response contract that both clients use.
|
|
6
|
+
*/
|
|
7
|
+
export interface HttpClientOptions {
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
fetch?: typeof fetch;
|
|
10
|
+
/** Static headers attached to every request before {@link authHeaders} overlay. */
|
|
11
|
+
staticHeaders?: Record<string, string>;
|
|
12
|
+
/**
|
|
13
|
+
* Async per-request hook returning headers to attach. Useful for short-lived
|
|
14
|
+
* credentials like Cloud Run ID tokens. Resolves before each request; values
|
|
15
|
+
* overwrite {@link staticHeaders} on conflict.
|
|
16
|
+
*/
|
|
17
|
+
authHeaders?: () => Promise<Record<string, string>> | Record<string, string>;
|
|
18
|
+
/** Error-message prefix — distinguishes overlapping SDKs in stack traces. */
|
|
19
|
+
errorPrefix: string;
|
|
20
|
+
}
|
|
21
|
+
export interface HttpClient {
|
|
22
|
+
request<T>(method: string, path: string, body?: unknown): Promise<T>;
|
|
23
|
+
}
|
|
24
|
+
export declare function createHttpClient(opts: HttpClientOptions): HttpClient;
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal JSON HTTP client shared by `Engram` (workspace api-key) and
|
|
3
|
+
* `EngramAdmin` (platform admin token). Encapsulates baseUrl normalisation,
|
|
4
|
+
* header merging, request body serialisation, and the small JSON-or-empty
|
|
5
|
+
* response contract that both clients use.
|
|
6
|
+
*/
|
|
7
|
+
export function createHttpClient(opts) {
|
|
8
|
+
const baseUrl = opts.baseUrl.replace(/\/+$/, "");
|
|
9
|
+
const fetchImpl = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
10
|
+
const staticHeaders = opts.staticHeaders ?? {};
|
|
11
|
+
const { authHeaders, errorPrefix } = opts;
|
|
12
|
+
return {
|
|
13
|
+
async request(method, path, body) {
|
|
14
|
+
const headers = {
|
|
15
|
+
"content-type": "application/json",
|
|
16
|
+
...staticHeaders,
|
|
17
|
+
};
|
|
18
|
+
if (authHeaders)
|
|
19
|
+
Object.assign(headers, await authHeaders());
|
|
20
|
+
const res = await fetchImpl(`${baseUrl}${path}`, {
|
|
21
|
+
method,
|
|
22
|
+
headers,
|
|
23
|
+
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
24
|
+
});
|
|
25
|
+
if (!res.ok) {
|
|
26
|
+
const text = await res.text().catch(() => "");
|
|
27
|
+
throw new Error(`${errorPrefix} ${method} ${path} ${res.status}: ${text}`);
|
|
28
|
+
}
|
|
29
|
+
if (res.status === 204)
|
|
30
|
+
return undefined;
|
|
31
|
+
const ct = res.headers.get("content-type") ?? "";
|
|
32
|
+
if (!ct.includes("application/json"))
|
|
33
|
+
return undefined;
|
|
34
|
+
return (await res.json());
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -39,6 +39,17 @@ export interface SessionInit {
|
|
|
39
39
|
trigger_conversation_id?: string | null;
|
|
40
40
|
/** Causal lineage — an external event (e.g. calendar event id). */
|
|
41
41
|
trigger_event_id?: string | null;
|
|
42
|
+
/**
|
|
43
|
+
* Host-defined "why was this side-conversation started" — set when
|
|
44
|
+
* a parent session opens a side-conv with a stated goal. Opaque to
|
|
45
|
+
* engram; the host's agent reads it back to drive resume behaviour.
|
|
46
|
+
*/
|
|
47
|
+
trigger_purpose?: string | null;
|
|
48
|
+
/**
|
|
49
|
+
* Host-defined "what condition should make us resume the parent" —
|
|
50
|
+
* paired with `trigger_purpose`. Opaque to engram.
|
|
51
|
+
*/
|
|
52
|
+
trigger_resume_hint?: string | null;
|
|
42
53
|
}
|
|
43
54
|
/** Patch for `updateSession`. */
|
|
44
55
|
export interface SessionUpdate {
|
|
@@ -49,6 +60,8 @@ export interface SessionUpdate {
|
|
|
49
60
|
model?: string | null;
|
|
50
61
|
trigger_conversation_id?: string | null;
|
|
51
62
|
trigger_event_id?: string | null;
|
|
63
|
+
trigger_purpose?: string | null;
|
|
64
|
+
trigger_resume_hint?: string | null;
|
|
52
65
|
}
|
|
53
66
|
export interface SessionAck {
|
|
54
67
|
id: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hexis-ai/engram-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"author": "hexis ltd.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"main": "dist/index.js",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@hexis-ai/engram-core": "^0.
|
|
12
|
+
"@hexis-ai/engram-core": "^0.3.0"
|
|
13
13
|
},
|
|
14
14
|
"exports": {
|
|
15
15
|
".": {
|