novyx 2.2.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/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # Novyx SDK for JavaScript / TypeScript
2
+
3
+ Persistent memory, rollback, and audit trail for AI agents.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install novyx
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { Novyx } from "novyx";
15
+
16
+ const nx = new Novyx({ apiKey: "nram_your_key_here" });
17
+
18
+ // Store a memory
19
+ await nx.remember("User prefers dark mode", { tags: ["ui", "prefs"], importance: 8 });
20
+
21
+ // Search semantically
22
+ const results = await nx.recall("user preferences");
23
+ for (const mem of results.memories) {
24
+ console.log(`${mem.observation} (score: ${mem.score})`);
25
+ }
26
+
27
+ // Get a specific memory
28
+ const mem = await nx.memory("urn:uuid:...");
29
+
30
+ // Delete a memory
31
+ await nx.forget("urn:uuid:...");
32
+ ```
33
+
34
+ ## Sessions
35
+
36
+ Automatically tag and filter memories by session:
37
+
38
+ ```typescript
39
+ const session = nx.session("chat-abc123");
40
+
41
+ await session.remember("User asked about billing");
42
+ const results = await session.recall("billing");
43
+ // Only returns memories from this session
44
+ ```
45
+
46
+ ## Links / Graph
47
+
48
+ Create relationships between memories:
49
+
50
+ ```typescript
51
+ await nx.link("mem-1", "mem-2", { relation: "caused_by", weight: 0.9 });
52
+
53
+ const linked = await nx.links("mem-1");
54
+ console.log(linked.edges);
55
+
56
+ await nx.unlink("mem-1", "mem-2", "caused_by");
57
+ ```
58
+
59
+ ## API Reference
60
+
61
+ | Method | Description |
62
+ |---|---|
63
+ | `remember(observation, opts?)` | Store a memory |
64
+ | `recall(query, opts?)` | Semantic search |
65
+ | `memories(opts?)` | List memories (raw) |
66
+ | `memory(id)` | Get memory by ID |
67
+ | `forget(id)` | Delete a memory |
68
+ | `delete(id)` | Alias for forget |
69
+ | `list(opts?)` | List memories (ListResult) |
70
+ | `stats()` | Memory statistics |
71
+ | `shareContext(tag, email, permission?)` | Share a context space |
72
+ | `acceptSharedContext(token)` | Join a shared space |
73
+ | `sharedContexts()` | List shared spaces |
74
+ | `revokeSharedContext(token)` | Revoke a share |
75
+ | `graph(opts?)` | Get memory graph |
76
+ | `rollback(target, dryRun?, preserveEvidence?)` | Rollback memories |
77
+ | `rollbackPreview(target)` | Preview rollback |
78
+ | `rollbackHistory(limit?)` | List past rollbacks |
79
+ | `audit(opts?)` | Get audit trail |
80
+ | `auditExport(format?)` | Export audit log |
81
+ | `auditVerify()` | Verify audit integrity |
82
+ | `traceCreate(agentId, sessionId?, metadata?)` | Create trace |
83
+ | `traceStep(traceId, stepType, name, content?, attrs?)` | Add trace step |
84
+ | `traceComplete(traceId)` | Complete trace |
85
+ | `traceVerify(traceId)` | Verify trace |
86
+ | `usage()` | Current usage stats |
87
+ | `plans()` | Available plans |
88
+ | `health()` | API health check |
89
+ | `session(sessionId)` | Create session scope |
90
+ | `link(sourceId, targetId, opts?)` | Link two memories |
91
+ | `unlink(sourceId, targetId, relation?)` | Remove a link |
92
+ | `links(memoryId, relation?)` | Get memory links |
93
+
94
+ ## Error Handling
95
+
96
+ ```typescript
97
+ import { Novyx, NovyxAuthError, NovyxForbiddenError, NovyxRateLimitError } from "novyx";
98
+
99
+ try {
100
+ await nx.rollback("2 hours ago");
101
+ } catch (err) {
102
+ if (err instanceof NovyxForbiddenError) {
103
+ console.log(`Upgrade required: ${err.requiredPlan}`);
104
+ console.log(`Upgrade at: ${err.upgradeUrl}`);
105
+ } else if (err instanceof NovyxRateLimitError) {
106
+ console.log(`Limit: ${err.limitType}, retry in ${err.retryAfter}s`);
107
+ }
108
+ }
109
+ ```
110
+
111
+ ## License
112
+
113
+ MIT
@@ -0,0 +1,202 @@
1
+ interface Memory {
2
+ uuid: string;
3
+ observation: string;
4
+ context?: string;
5
+ agent_id?: string;
6
+ tags: string[];
7
+ importance: number;
8
+ confidence: number;
9
+ created_at: string;
10
+ score?: number;
11
+ similarity?: number;
12
+ vector_clock?: Record<string, number>;
13
+ conflict_metadata?: Record<string, any>;
14
+ expires_at?: string;
15
+ }
16
+ interface SearchResult {
17
+ query: string;
18
+ total_results: number;
19
+ memories: Memory[];
20
+ }
21
+ interface ListResult {
22
+ total_count: number;
23
+ memories: Memory[];
24
+ filters: Record<string, any>;
25
+ }
26
+ interface NovyxConfig {
27
+ apiKey: string;
28
+ apiUrl?: string;
29
+ timeout?: number;
30
+ agentId?: string;
31
+ }
32
+ interface Edge {
33
+ edge_id: string;
34
+ source_id: string;
35
+ target_id: string;
36
+ relation: string;
37
+ weight: number;
38
+ metadata: Record<string, any>;
39
+ created_at: string;
40
+ }
41
+ interface LinksResult {
42
+ memory_id: string;
43
+ edges: Edge[];
44
+ total: number;
45
+ }
46
+
47
+ declare class NovyxSession {
48
+ private client;
49
+ private sessionTag;
50
+ constructor(client: Novyx, sessionId: string);
51
+ remember(observation: string, opts?: {
52
+ tags?: string[];
53
+ context?: string;
54
+ importance?: number;
55
+ agent_id?: string;
56
+ space_id?: string;
57
+ metadata?: Record<string, any>;
58
+ ttl_seconds?: number;
59
+ }): Promise<Record<string, any>>;
60
+ recall(query: string, opts?: {
61
+ limit?: number;
62
+ tags?: string[];
63
+ min_score?: number;
64
+ scope?: string;
65
+ agents?: string[];
66
+ include_shared?: boolean;
67
+ space_id?: string;
68
+ }): Promise<SearchResult>;
69
+ memories(opts?: {
70
+ limit?: number;
71
+ offset?: number;
72
+ tags?: string[];
73
+ min_importance?: number;
74
+ include_shared?: boolean;
75
+ agent_id?: string;
76
+ space_id?: string;
77
+ }): Promise<Memory[]>;
78
+ list(opts?: {
79
+ limit?: number;
80
+ offset?: number;
81
+ tags?: string[];
82
+ min_importance?: number;
83
+ include_shared?: boolean;
84
+ agent_id?: string;
85
+ space_id?: string;
86
+ }): Promise<ListResult>;
87
+ }
88
+
89
+ declare class Novyx {
90
+ private apiKey;
91
+ private apiUrl;
92
+ private timeout;
93
+ private agentId?;
94
+ constructor(config: NovyxConfig);
95
+ private _validateKey;
96
+ private _request;
97
+ remember(observation: string, opts?: {
98
+ tags?: string[];
99
+ context?: string;
100
+ importance?: number;
101
+ agent_id?: string;
102
+ space_id?: string;
103
+ metadata?: Record<string, any>;
104
+ ttl_seconds?: number;
105
+ }): Promise<Record<string, any>>;
106
+ recall(query: string, opts?: {
107
+ limit?: number;
108
+ tags?: string[];
109
+ min_score?: number;
110
+ scope?: string;
111
+ agents?: string[];
112
+ include_shared?: boolean;
113
+ space_id?: string;
114
+ }): Promise<SearchResult>;
115
+ memories(opts?: {
116
+ limit?: number;
117
+ offset?: number;
118
+ tags?: string[];
119
+ min_importance?: number;
120
+ include_shared?: boolean;
121
+ agent_id?: string;
122
+ space_id?: string;
123
+ }): Promise<Memory[]>;
124
+ memory(memoryId: string): Promise<Memory>;
125
+ forget(memoryId: string): Promise<boolean>;
126
+ delete(memoryId: string): Promise<boolean>;
127
+ list(opts?: {
128
+ limit?: number;
129
+ offset?: number;
130
+ tags?: string[];
131
+ min_importance?: number;
132
+ include_shared?: boolean;
133
+ agent_id?: string;
134
+ space_id?: string;
135
+ }): Promise<ListResult>;
136
+ stats(): Promise<Record<string, any>>;
137
+ shareContext(tag: string, toEmail: string, permission?: string): Promise<Record<string, any>>;
138
+ acceptSharedContext(token: string): Promise<Record<string, any>>;
139
+ sharedContexts(): Promise<Record<string, any>>;
140
+ revokeSharedContext(token: string): Promise<Record<string, any>>;
141
+ graph(opts?: {
142
+ include_shared?: boolean;
143
+ agents?: string[];
144
+ }): Promise<Record<string, any>>;
145
+ rollback(target: string, dryRun?: boolean, preserveEvidence?: boolean): Promise<Record<string, any>>;
146
+ rollbackPreview(target: string): Promise<Record<string, any>>;
147
+ rollbackHistory(limit?: number): Promise<Record<string, any>[]>;
148
+ audit(opts?: {
149
+ limit?: number;
150
+ since?: string;
151
+ until?: string;
152
+ operation?: string;
153
+ artifact_id?: string;
154
+ }): Promise<Record<string, any>[]>;
155
+ auditExport(format?: string): Promise<Response>;
156
+ auditVerify(): Promise<Record<string, any>>;
157
+ traceCreate(agentId: string, sessionId?: string, metadata?: Record<string, any>): Promise<Record<string, any>>;
158
+ traceStep(traceId: string, stepType: string, name: string, content?: string, attributes?: Record<string, any>): Promise<Record<string, any>>;
159
+ traceComplete(traceId: string): Promise<Record<string, any>>;
160
+ traceVerify(traceId: string): Promise<Record<string, any>>;
161
+ usage(): Promise<Record<string, any>>;
162
+ plans(): Promise<Record<string, any>[]>;
163
+ health(): Promise<Record<string, any>>;
164
+ session(sessionId: string): NovyxSession;
165
+ link(sourceId: string, targetId: string, opts?: {
166
+ relation?: string;
167
+ weight?: number;
168
+ metadata?: Record<string, any>;
169
+ }): Promise<Record<string, any>>;
170
+ unlink(sourceId: string, targetId: string, relation?: string): Promise<Record<string, any>>;
171
+ links(memoryId: string, relation?: string): Promise<LinksResult>;
172
+ }
173
+
174
+ declare class NovyxError extends Error {
175
+ constructor(message: string);
176
+ }
177
+ declare class NovyxAuthError extends NovyxError {
178
+ constructor(message?: string);
179
+ }
180
+ declare class NovyxForbiddenError extends NovyxError {
181
+ data: Record<string, any>;
182
+ feature?: string;
183
+ requiredPlan?: string;
184
+ upgradeUrl?: string;
185
+ constructor(message?: string, data?: Record<string, any>);
186
+ }
187
+ declare class NovyxRateLimitError extends NovyxError {
188
+ data: Record<string, any>;
189
+ limitType?: string;
190
+ current?: number;
191
+ limit?: number;
192
+ retryAfter?: number;
193
+ constructor(message?: string, data?: Record<string, any>);
194
+ }
195
+ declare class NovyxNotFoundError extends NovyxError {
196
+ constructor(message?: string);
197
+ }
198
+ declare class NovyxSecurityError extends NovyxError {
199
+ constructor(message?: string);
200
+ }
201
+
202
+ export { type Edge, type LinksResult, type ListResult, type Memory, Novyx, NovyxAuthError, type NovyxConfig, NovyxError, NovyxForbiddenError, NovyxNotFoundError, NovyxRateLimitError, NovyxSecurityError, NovyxSession, type SearchResult };
@@ -0,0 +1,202 @@
1
+ interface Memory {
2
+ uuid: string;
3
+ observation: string;
4
+ context?: string;
5
+ agent_id?: string;
6
+ tags: string[];
7
+ importance: number;
8
+ confidence: number;
9
+ created_at: string;
10
+ score?: number;
11
+ similarity?: number;
12
+ vector_clock?: Record<string, number>;
13
+ conflict_metadata?: Record<string, any>;
14
+ expires_at?: string;
15
+ }
16
+ interface SearchResult {
17
+ query: string;
18
+ total_results: number;
19
+ memories: Memory[];
20
+ }
21
+ interface ListResult {
22
+ total_count: number;
23
+ memories: Memory[];
24
+ filters: Record<string, any>;
25
+ }
26
+ interface NovyxConfig {
27
+ apiKey: string;
28
+ apiUrl?: string;
29
+ timeout?: number;
30
+ agentId?: string;
31
+ }
32
+ interface Edge {
33
+ edge_id: string;
34
+ source_id: string;
35
+ target_id: string;
36
+ relation: string;
37
+ weight: number;
38
+ metadata: Record<string, any>;
39
+ created_at: string;
40
+ }
41
+ interface LinksResult {
42
+ memory_id: string;
43
+ edges: Edge[];
44
+ total: number;
45
+ }
46
+
47
+ declare class NovyxSession {
48
+ private client;
49
+ private sessionTag;
50
+ constructor(client: Novyx, sessionId: string);
51
+ remember(observation: string, opts?: {
52
+ tags?: string[];
53
+ context?: string;
54
+ importance?: number;
55
+ agent_id?: string;
56
+ space_id?: string;
57
+ metadata?: Record<string, any>;
58
+ ttl_seconds?: number;
59
+ }): Promise<Record<string, any>>;
60
+ recall(query: string, opts?: {
61
+ limit?: number;
62
+ tags?: string[];
63
+ min_score?: number;
64
+ scope?: string;
65
+ agents?: string[];
66
+ include_shared?: boolean;
67
+ space_id?: string;
68
+ }): Promise<SearchResult>;
69
+ memories(opts?: {
70
+ limit?: number;
71
+ offset?: number;
72
+ tags?: string[];
73
+ min_importance?: number;
74
+ include_shared?: boolean;
75
+ agent_id?: string;
76
+ space_id?: string;
77
+ }): Promise<Memory[]>;
78
+ list(opts?: {
79
+ limit?: number;
80
+ offset?: number;
81
+ tags?: string[];
82
+ min_importance?: number;
83
+ include_shared?: boolean;
84
+ agent_id?: string;
85
+ space_id?: string;
86
+ }): Promise<ListResult>;
87
+ }
88
+
89
+ declare class Novyx {
90
+ private apiKey;
91
+ private apiUrl;
92
+ private timeout;
93
+ private agentId?;
94
+ constructor(config: NovyxConfig);
95
+ private _validateKey;
96
+ private _request;
97
+ remember(observation: string, opts?: {
98
+ tags?: string[];
99
+ context?: string;
100
+ importance?: number;
101
+ agent_id?: string;
102
+ space_id?: string;
103
+ metadata?: Record<string, any>;
104
+ ttl_seconds?: number;
105
+ }): Promise<Record<string, any>>;
106
+ recall(query: string, opts?: {
107
+ limit?: number;
108
+ tags?: string[];
109
+ min_score?: number;
110
+ scope?: string;
111
+ agents?: string[];
112
+ include_shared?: boolean;
113
+ space_id?: string;
114
+ }): Promise<SearchResult>;
115
+ memories(opts?: {
116
+ limit?: number;
117
+ offset?: number;
118
+ tags?: string[];
119
+ min_importance?: number;
120
+ include_shared?: boolean;
121
+ agent_id?: string;
122
+ space_id?: string;
123
+ }): Promise<Memory[]>;
124
+ memory(memoryId: string): Promise<Memory>;
125
+ forget(memoryId: string): Promise<boolean>;
126
+ delete(memoryId: string): Promise<boolean>;
127
+ list(opts?: {
128
+ limit?: number;
129
+ offset?: number;
130
+ tags?: string[];
131
+ min_importance?: number;
132
+ include_shared?: boolean;
133
+ agent_id?: string;
134
+ space_id?: string;
135
+ }): Promise<ListResult>;
136
+ stats(): Promise<Record<string, any>>;
137
+ shareContext(tag: string, toEmail: string, permission?: string): Promise<Record<string, any>>;
138
+ acceptSharedContext(token: string): Promise<Record<string, any>>;
139
+ sharedContexts(): Promise<Record<string, any>>;
140
+ revokeSharedContext(token: string): Promise<Record<string, any>>;
141
+ graph(opts?: {
142
+ include_shared?: boolean;
143
+ agents?: string[];
144
+ }): Promise<Record<string, any>>;
145
+ rollback(target: string, dryRun?: boolean, preserveEvidence?: boolean): Promise<Record<string, any>>;
146
+ rollbackPreview(target: string): Promise<Record<string, any>>;
147
+ rollbackHistory(limit?: number): Promise<Record<string, any>[]>;
148
+ audit(opts?: {
149
+ limit?: number;
150
+ since?: string;
151
+ until?: string;
152
+ operation?: string;
153
+ artifact_id?: string;
154
+ }): Promise<Record<string, any>[]>;
155
+ auditExport(format?: string): Promise<Response>;
156
+ auditVerify(): Promise<Record<string, any>>;
157
+ traceCreate(agentId: string, sessionId?: string, metadata?: Record<string, any>): Promise<Record<string, any>>;
158
+ traceStep(traceId: string, stepType: string, name: string, content?: string, attributes?: Record<string, any>): Promise<Record<string, any>>;
159
+ traceComplete(traceId: string): Promise<Record<string, any>>;
160
+ traceVerify(traceId: string): Promise<Record<string, any>>;
161
+ usage(): Promise<Record<string, any>>;
162
+ plans(): Promise<Record<string, any>[]>;
163
+ health(): Promise<Record<string, any>>;
164
+ session(sessionId: string): NovyxSession;
165
+ link(sourceId: string, targetId: string, opts?: {
166
+ relation?: string;
167
+ weight?: number;
168
+ metadata?: Record<string, any>;
169
+ }): Promise<Record<string, any>>;
170
+ unlink(sourceId: string, targetId: string, relation?: string): Promise<Record<string, any>>;
171
+ links(memoryId: string, relation?: string): Promise<LinksResult>;
172
+ }
173
+
174
+ declare class NovyxError extends Error {
175
+ constructor(message: string);
176
+ }
177
+ declare class NovyxAuthError extends NovyxError {
178
+ constructor(message?: string);
179
+ }
180
+ declare class NovyxForbiddenError extends NovyxError {
181
+ data: Record<string, any>;
182
+ feature?: string;
183
+ requiredPlan?: string;
184
+ upgradeUrl?: string;
185
+ constructor(message?: string, data?: Record<string, any>);
186
+ }
187
+ declare class NovyxRateLimitError extends NovyxError {
188
+ data: Record<string, any>;
189
+ limitType?: string;
190
+ current?: number;
191
+ limit?: number;
192
+ retryAfter?: number;
193
+ constructor(message?: string, data?: Record<string, any>);
194
+ }
195
+ declare class NovyxNotFoundError extends NovyxError {
196
+ constructor(message?: string);
197
+ }
198
+ declare class NovyxSecurityError extends NovyxError {
199
+ constructor(message?: string);
200
+ }
201
+
202
+ export { type Edge, type LinksResult, type ListResult, type Memory, Novyx, NovyxAuthError, type NovyxConfig, NovyxError, NovyxForbiddenError, NovyxNotFoundError, NovyxRateLimitError, NovyxSecurityError, NovyxSession, type SearchResult };
package/dist/index.js ADDED
@@ -0,0 +1,445 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Novyx: () => Novyx,
24
+ NovyxAuthError: () => NovyxAuthError,
25
+ NovyxError: () => NovyxError,
26
+ NovyxForbiddenError: () => NovyxForbiddenError,
27
+ NovyxNotFoundError: () => NovyxNotFoundError,
28
+ NovyxRateLimitError: () => NovyxRateLimitError,
29
+ NovyxSecurityError: () => NovyxSecurityError,
30
+ NovyxSession: () => NovyxSession
31
+ });
32
+ module.exports = __toCommonJS(index_exports);
33
+
34
+ // src/errors.ts
35
+ var NovyxError = class extends Error {
36
+ constructor(message) {
37
+ super(message);
38
+ this.name = "NovyxError";
39
+ }
40
+ };
41
+ var NovyxAuthError = class extends NovyxError {
42
+ constructor(message = "Invalid API key or unauthorized") {
43
+ super(message);
44
+ this.name = "NovyxAuthError";
45
+ }
46
+ };
47
+ var NovyxForbiddenError = class extends NovyxError {
48
+ constructor(message = "Forbidden", data = {}) {
49
+ super(message);
50
+ this.name = "NovyxForbiddenError";
51
+ this.data = data;
52
+ this.feature = data.feature;
53
+ this.requiredPlan = data.required_plan ?? "pro";
54
+ this.upgradeUrl = data.upgrade_url ?? "https://novyxlabs.com/pricing";
55
+ }
56
+ };
57
+ var NovyxRateLimitError = class extends NovyxError {
58
+ constructor(message = "Rate limit exceeded", data = {}) {
59
+ super(message);
60
+ this.name = "NovyxRateLimitError";
61
+ this.data = data;
62
+ this.limitType = data.limit;
63
+ this.current = data.current;
64
+ this.limit = data.max_allowed ?? data.max ?? data.limit;
65
+ this.retryAfter = data.retry_after;
66
+ }
67
+ };
68
+ var NovyxNotFoundError = class extends NovyxError {
69
+ constructor(message = "Not found") {
70
+ super(message);
71
+ this.name = "NovyxNotFoundError";
72
+ }
73
+ };
74
+ var NovyxSecurityError = class extends NovyxError {
75
+ constructor(message = "Security policy violation") {
76
+ super(message);
77
+ this.name = "NovyxSecurityError";
78
+ }
79
+ };
80
+
81
+ // src/session.ts
82
+ var NovyxSession = class {
83
+ constructor(client, sessionId) {
84
+ this.client = client;
85
+ this.sessionTag = `session:${sessionId}`;
86
+ }
87
+ async remember(observation, opts) {
88
+ const tags = [...opts?.tags ?? [], this.sessionTag];
89
+ return this.client.remember(observation, { ...opts, tags });
90
+ }
91
+ async recall(query, opts) {
92
+ const tags = [...opts?.tags ?? [], this.sessionTag];
93
+ return this.client.recall(query, { ...opts, tags });
94
+ }
95
+ async memories(opts) {
96
+ const tags = [...opts?.tags ?? [], this.sessionTag];
97
+ return this.client.memories({ ...opts, tags });
98
+ }
99
+ async list(opts) {
100
+ const tags = [...opts?.tags ?? [], this.sessionTag];
101
+ return this.client.list({ ...opts, tags });
102
+ }
103
+ };
104
+
105
+ // src/client.ts
106
+ var Novyx = class {
107
+ constructor(config) {
108
+ this.apiKey = config.apiKey;
109
+ this.apiUrl = (config.apiUrl ?? "https://novyx-ram-api.fly.dev").replace(/\/+$/, "");
110
+ this.timeout = config.timeout ?? 30;
111
+ this.agentId = config.agentId;
112
+ this._validateKey();
113
+ }
114
+ _validateKey() {
115
+ if (!this.apiKey || !this.apiKey.startsWith("nram_")) {
116
+ throw new NovyxAuthError("Invalid API key format. Expected: nram_<tenant>_<signature>");
117
+ }
118
+ }
119
+ async _request(method, endpoint, opts) {
120
+ const url = new URL(`${this.apiUrl}${endpoint}`);
121
+ if (opts?.params) {
122
+ for (const [key, value] of Object.entries(opts.params)) {
123
+ if (value !== void 0 && value !== null) {
124
+ url.searchParams.set(key, String(value));
125
+ }
126
+ }
127
+ }
128
+ const controller = new AbortController();
129
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout * 1e3);
130
+ try {
131
+ const fetchOpts = {
132
+ method,
133
+ headers: {
134
+ Authorization: `Bearer ${this.apiKey}`,
135
+ "Content-Type": "application/json"
136
+ },
137
+ signal: controller.signal
138
+ };
139
+ if (opts?.body && (method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE")) {
140
+ fetchOpts.body = JSON.stringify(opts.body);
141
+ }
142
+ const response = await fetch(url.toString(), fetchOpts);
143
+ if (response.status === 401) {
144
+ throw new NovyxAuthError("Invalid API key or unauthorized");
145
+ }
146
+ if (response.status === 403) {
147
+ let data = {};
148
+ try {
149
+ data = await response.json();
150
+ } catch {
151
+ }
152
+ throw new NovyxForbiddenError(data.error ?? "Forbidden", data);
153
+ }
154
+ if (response.status === 404) {
155
+ let data = {};
156
+ try {
157
+ data = await response.json();
158
+ } catch {
159
+ }
160
+ throw new NovyxNotFoundError(data.error ?? "Not found");
161
+ }
162
+ if (response.status === 429) {
163
+ let data = {};
164
+ try {
165
+ data = await response.json();
166
+ } catch {
167
+ }
168
+ throw new NovyxRateLimitError(data.error ?? "Rate limit exceeded", data);
169
+ }
170
+ if (opts?.rawResponse) {
171
+ return response;
172
+ }
173
+ if (response.status === 204 || response.headers.get("content-length") === "0") {
174
+ return {};
175
+ }
176
+ const text = await response.text();
177
+ if (!text) {
178
+ return {};
179
+ }
180
+ let json;
181
+ try {
182
+ json = JSON.parse(text);
183
+ } catch {
184
+ if (response.status >= 400) {
185
+ throw new NovyxError(`HTTP ${response.status}: ${text.slice(0, 200)}`);
186
+ }
187
+ throw new NovyxError(`Invalid JSON response: ${text.slice(0, 200)}`);
188
+ }
189
+ if (response.status >= 400) {
190
+ throw new NovyxError(`HTTP ${response.status}: ${json.error ?? JSON.stringify(json).slice(0, 200)}`);
191
+ }
192
+ return json;
193
+ } catch (err) {
194
+ if (err instanceof NovyxError) throw err;
195
+ if (err.name === "AbortError") {
196
+ throw new NovyxError(`Request timed out after ${this.timeout}s`);
197
+ }
198
+ throw new NovyxError(`Request failed: ${err.message}`);
199
+ } finally {
200
+ clearTimeout(timeoutId);
201
+ }
202
+ }
203
+ // ========================================================================
204
+ // Memory Methods
205
+ // ========================================================================
206
+ async remember(observation, opts) {
207
+ const resolvedAgentId = opts?.agent_id ?? this.agentId;
208
+ const body = {
209
+ observation,
210
+ tags: opts?.tags ?? [],
211
+ importance: opts?.importance ?? 5
212
+ };
213
+ if (resolvedAgentId) body.agent_id = resolvedAgentId;
214
+ if (opts?.space_id) body.space_id = opts.space_id;
215
+ if (opts?.ttl_seconds !== void 0) body.ttl_seconds = opts.ttl_seconds;
216
+ if (opts?.context) {
217
+ body.context = opts.context;
218
+ } else if (opts?.metadata) {
219
+ body.context = JSON.stringify(opts.metadata);
220
+ }
221
+ return this._request("POST", "/v1/memories", { body });
222
+ }
223
+ async recall(query, opts) {
224
+ const params = {
225
+ q: query,
226
+ limit: opts?.limit ?? 5,
227
+ min_score: opts?.min_score ?? 0
228
+ };
229
+ if (opts?.tags) params.tags = opts.tags.join(",");
230
+ if (opts?.agents) params.agents = opts.agents.join(",");
231
+ if (opts?.space_id) params.space_id = opts.space_id;
232
+ const result = await this._request("GET", "/v1/memories/search", { params });
233
+ const raw = Array.isArray(result) ? result : result.memories ?? [];
234
+ return {
235
+ query,
236
+ total_results: raw.length,
237
+ memories: raw
238
+ };
239
+ }
240
+ async memories(opts) {
241
+ const params = {
242
+ limit: opts?.limit ?? 100,
243
+ offset: opts?.offset ?? 0
244
+ };
245
+ if (opts?.tags) params.tags = opts.tags.join(",");
246
+ if (opts?.min_importance !== void 0) params.min_importance = opts.min_importance;
247
+ if (opts?.include_shared) params.include_shared = "true";
248
+ if (opts?.agent_id) params.agent_id = opts.agent_id;
249
+ if (opts?.space_id) params.space_id = opts.space_id;
250
+ const result = await this._request("GET", "/v1/memories", { params });
251
+ return typeof result === "object" && !Array.isArray(result) ? result.memories ?? [] : result;
252
+ }
253
+ async memory(memoryId) {
254
+ return this._request("GET", `/v1/memories/${memoryId}`);
255
+ }
256
+ async forget(memoryId) {
257
+ const result = await this._request("DELETE", `/v1/memories/${memoryId}`);
258
+ return result?.success ?? true;
259
+ }
260
+ async delete(memoryId) {
261
+ return this.forget(memoryId);
262
+ }
263
+ async list(opts) {
264
+ const params = {
265
+ limit: opts?.limit ?? 100,
266
+ offset: opts?.offset ?? 0
267
+ };
268
+ if (opts?.tags) params.tags = opts.tags.join(",");
269
+ if (opts?.min_importance !== void 0) params.min_importance = opts.min_importance;
270
+ if (opts?.include_shared) params.include_shared = "true";
271
+ if (opts?.agent_id) params.agent_id = opts.agent_id;
272
+ if (opts?.space_id) params.space_id = opts.space_id;
273
+ const result = await this._request("GET", "/v1/memories", { params });
274
+ const rawMemories = typeof result === "object" && !Array.isArray(result) ? result.memories ?? [] : result;
275
+ return {
276
+ total_count: typeof result === "object" && !Array.isArray(result) ? result.total_count ?? rawMemories.length : rawMemories.length,
277
+ memories: rawMemories,
278
+ filters: typeof result === "object" && !Array.isArray(result) ? result.filters ?? {} : {}
279
+ };
280
+ }
281
+ async stats() {
282
+ return this._request("GET", "/v1/memories/stats");
283
+ }
284
+ // ========================================================================
285
+ // Context Space & Sharing
286
+ // ========================================================================
287
+ async shareContext(tag, toEmail, permission = "read") {
288
+ return this._request("POST", "/v1/spaces/share", {
289
+ body: { tag, email: toEmail, permission }
290
+ });
291
+ }
292
+ async acceptSharedContext(token) {
293
+ return this._request("POST", "/v1/spaces/join", {
294
+ body: { token }
295
+ });
296
+ }
297
+ async sharedContexts() {
298
+ return this._request("GET", "/v1/spaces/shared");
299
+ }
300
+ async revokeSharedContext(token) {
301
+ return this._request("DELETE", `/v1/spaces/share/${token}`);
302
+ }
303
+ async graph(opts) {
304
+ const params = {};
305
+ if (opts?.include_shared) params.include_shared = "true";
306
+ if (opts?.agents) params.agents = opts.agents.join(",");
307
+ return this._request("GET", "/v1/memories/graph", { params });
308
+ }
309
+ // ========================================================================
310
+ // Rollback
311
+ // ========================================================================
312
+ async rollback(target, dryRun = false, preserveEvidence = true) {
313
+ return this._request("POST", "/v1/rollback", {
314
+ body: { target, dry_run: dryRun, preserve_evidence: preserveEvidence }
315
+ });
316
+ }
317
+ async rollbackPreview(target) {
318
+ return this._request("GET", "/v1/rollback/preview", {
319
+ params: { target }
320
+ });
321
+ }
322
+ async rollbackHistory(limit = 50) {
323
+ const result = await this._request("GET", "/v1/rollback/history", {
324
+ params: { limit }
325
+ });
326
+ return Array.isArray(result) ? result : [];
327
+ }
328
+ // ========================================================================
329
+ // Audit
330
+ // ========================================================================
331
+ async audit(opts) {
332
+ const params = { limit: opts?.limit ?? 50 };
333
+ if (opts?.since) params.start_time = opts.since;
334
+ if (opts?.until) params.end_time = opts.until;
335
+ if (opts?.operation) params.operation = opts.operation;
336
+ if (opts?.artifact_id) params.artifact_id = opts.artifact_id;
337
+ const result = await this._request("GET", "/v1/audit", { params });
338
+ return typeof result === "object" && !Array.isArray(result) ? result.entries ?? [] : result;
339
+ }
340
+ async auditExport(format = "csv") {
341
+ return this._request("GET", "/v1/audit/export", {
342
+ params: { format },
343
+ rawResponse: true
344
+ });
345
+ }
346
+ async auditVerify() {
347
+ return this._request("GET", "/v1/audit/verify");
348
+ }
349
+ // ========================================================================
350
+ // Traces
351
+ // ========================================================================
352
+ async traceCreate(agentId, sessionId, metadata) {
353
+ return this._request("POST", "/v1/traces", {
354
+ body: {
355
+ agent_id: agentId,
356
+ session_id: sessionId,
357
+ metadata: metadata ?? {}
358
+ }
359
+ });
360
+ }
361
+ async traceStep(traceId, stepType, name, content, attributes) {
362
+ return this._request("POST", `/v1/traces/${traceId}/steps`, {
363
+ body: {
364
+ step_type: stepType,
365
+ name,
366
+ content,
367
+ attributes: attributes ?? {}
368
+ }
369
+ });
370
+ }
371
+ async traceComplete(traceId) {
372
+ return this._request("POST", `/v1/traces/${traceId}/complete`);
373
+ }
374
+ async traceVerify(traceId) {
375
+ return this._request("GET", `/v1/traces/${traceId}/verify`);
376
+ }
377
+ // ========================================================================
378
+ // Usage & Plans
379
+ // ========================================================================
380
+ async usage() {
381
+ return this._request("GET", "/v1/usage");
382
+ }
383
+ async plans() {
384
+ return this._request("GET", "/v1/plans");
385
+ }
386
+ async health() {
387
+ try {
388
+ const controller = new AbortController();
389
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout * 1e3);
390
+ try {
391
+ const response = await fetch(`${this.apiUrl}/health`, {
392
+ signal: controller.signal
393
+ });
394
+ return await response.json();
395
+ } finally {
396
+ clearTimeout(timeoutId);
397
+ }
398
+ } catch (err) {
399
+ return { status: "error", error: err.message };
400
+ }
401
+ }
402
+ // ========================================================================
403
+ // Sessions
404
+ // ========================================================================
405
+ session(sessionId) {
406
+ return new NovyxSession(this, sessionId);
407
+ }
408
+ // ========================================================================
409
+ // Links / Edges
410
+ // ========================================================================
411
+ async link(sourceId, targetId, opts) {
412
+ const body = {
413
+ source_id: sourceId,
414
+ target_id: targetId
415
+ };
416
+ if (opts?.relation) body.relation = opts.relation;
417
+ if (opts?.weight !== void 0) body.weight = opts.weight;
418
+ if (opts?.metadata) body.metadata = opts.metadata;
419
+ return this._request("POST", "/v1/memories/link", { body });
420
+ }
421
+ async unlink(sourceId, targetId, relation) {
422
+ const body = {
423
+ source_id: sourceId,
424
+ target_id: targetId
425
+ };
426
+ if (relation) body.relation = relation;
427
+ return this._request("DELETE", "/v1/memories/link", { body });
428
+ }
429
+ async links(memoryId, relation) {
430
+ const params = {};
431
+ if (relation) params.relation = relation;
432
+ return this._request("GET", `/v1/memories/${memoryId}/links`, { params });
433
+ }
434
+ };
435
+ // Annotate the CommonJS export names for ESM import in node:
436
+ 0 && (module.exports = {
437
+ Novyx,
438
+ NovyxAuthError,
439
+ NovyxError,
440
+ NovyxForbiddenError,
441
+ NovyxNotFoundError,
442
+ NovyxRateLimitError,
443
+ NovyxSecurityError,
444
+ NovyxSession
445
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,411 @@
1
+ // src/errors.ts
2
+ var NovyxError = class extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = "NovyxError";
6
+ }
7
+ };
8
+ var NovyxAuthError = class extends NovyxError {
9
+ constructor(message = "Invalid API key or unauthorized") {
10
+ super(message);
11
+ this.name = "NovyxAuthError";
12
+ }
13
+ };
14
+ var NovyxForbiddenError = class extends NovyxError {
15
+ constructor(message = "Forbidden", data = {}) {
16
+ super(message);
17
+ this.name = "NovyxForbiddenError";
18
+ this.data = data;
19
+ this.feature = data.feature;
20
+ this.requiredPlan = data.required_plan ?? "pro";
21
+ this.upgradeUrl = data.upgrade_url ?? "https://novyxlabs.com/pricing";
22
+ }
23
+ };
24
+ var NovyxRateLimitError = class extends NovyxError {
25
+ constructor(message = "Rate limit exceeded", data = {}) {
26
+ super(message);
27
+ this.name = "NovyxRateLimitError";
28
+ this.data = data;
29
+ this.limitType = data.limit;
30
+ this.current = data.current;
31
+ this.limit = data.max_allowed ?? data.max ?? data.limit;
32
+ this.retryAfter = data.retry_after;
33
+ }
34
+ };
35
+ var NovyxNotFoundError = class extends NovyxError {
36
+ constructor(message = "Not found") {
37
+ super(message);
38
+ this.name = "NovyxNotFoundError";
39
+ }
40
+ };
41
+ var NovyxSecurityError = class extends NovyxError {
42
+ constructor(message = "Security policy violation") {
43
+ super(message);
44
+ this.name = "NovyxSecurityError";
45
+ }
46
+ };
47
+
48
+ // src/session.ts
49
+ var NovyxSession = class {
50
+ constructor(client, sessionId) {
51
+ this.client = client;
52
+ this.sessionTag = `session:${sessionId}`;
53
+ }
54
+ async remember(observation, opts) {
55
+ const tags = [...opts?.tags ?? [], this.sessionTag];
56
+ return this.client.remember(observation, { ...opts, tags });
57
+ }
58
+ async recall(query, opts) {
59
+ const tags = [...opts?.tags ?? [], this.sessionTag];
60
+ return this.client.recall(query, { ...opts, tags });
61
+ }
62
+ async memories(opts) {
63
+ const tags = [...opts?.tags ?? [], this.sessionTag];
64
+ return this.client.memories({ ...opts, tags });
65
+ }
66
+ async list(opts) {
67
+ const tags = [...opts?.tags ?? [], this.sessionTag];
68
+ return this.client.list({ ...opts, tags });
69
+ }
70
+ };
71
+
72
+ // src/client.ts
73
+ var Novyx = class {
74
+ constructor(config) {
75
+ this.apiKey = config.apiKey;
76
+ this.apiUrl = (config.apiUrl ?? "https://novyx-ram-api.fly.dev").replace(/\/+$/, "");
77
+ this.timeout = config.timeout ?? 30;
78
+ this.agentId = config.agentId;
79
+ this._validateKey();
80
+ }
81
+ _validateKey() {
82
+ if (!this.apiKey || !this.apiKey.startsWith("nram_")) {
83
+ throw new NovyxAuthError("Invalid API key format. Expected: nram_<tenant>_<signature>");
84
+ }
85
+ }
86
+ async _request(method, endpoint, opts) {
87
+ const url = new URL(`${this.apiUrl}${endpoint}`);
88
+ if (opts?.params) {
89
+ for (const [key, value] of Object.entries(opts.params)) {
90
+ if (value !== void 0 && value !== null) {
91
+ url.searchParams.set(key, String(value));
92
+ }
93
+ }
94
+ }
95
+ const controller = new AbortController();
96
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout * 1e3);
97
+ try {
98
+ const fetchOpts = {
99
+ method,
100
+ headers: {
101
+ Authorization: `Bearer ${this.apiKey}`,
102
+ "Content-Type": "application/json"
103
+ },
104
+ signal: controller.signal
105
+ };
106
+ if (opts?.body && (method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE")) {
107
+ fetchOpts.body = JSON.stringify(opts.body);
108
+ }
109
+ const response = await fetch(url.toString(), fetchOpts);
110
+ if (response.status === 401) {
111
+ throw new NovyxAuthError("Invalid API key or unauthorized");
112
+ }
113
+ if (response.status === 403) {
114
+ let data = {};
115
+ try {
116
+ data = await response.json();
117
+ } catch {
118
+ }
119
+ throw new NovyxForbiddenError(data.error ?? "Forbidden", data);
120
+ }
121
+ if (response.status === 404) {
122
+ let data = {};
123
+ try {
124
+ data = await response.json();
125
+ } catch {
126
+ }
127
+ throw new NovyxNotFoundError(data.error ?? "Not found");
128
+ }
129
+ if (response.status === 429) {
130
+ let data = {};
131
+ try {
132
+ data = await response.json();
133
+ } catch {
134
+ }
135
+ throw new NovyxRateLimitError(data.error ?? "Rate limit exceeded", data);
136
+ }
137
+ if (opts?.rawResponse) {
138
+ return response;
139
+ }
140
+ if (response.status === 204 || response.headers.get("content-length") === "0") {
141
+ return {};
142
+ }
143
+ const text = await response.text();
144
+ if (!text) {
145
+ return {};
146
+ }
147
+ let json;
148
+ try {
149
+ json = JSON.parse(text);
150
+ } catch {
151
+ if (response.status >= 400) {
152
+ throw new NovyxError(`HTTP ${response.status}: ${text.slice(0, 200)}`);
153
+ }
154
+ throw new NovyxError(`Invalid JSON response: ${text.slice(0, 200)}`);
155
+ }
156
+ if (response.status >= 400) {
157
+ throw new NovyxError(`HTTP ${response.status}: ${json.error ?? JSON.stringify(json).slice(0, 200)}`);
158
+ }
159
+ return json;
160
+ } catch (err) {
161
+ if (err instanceof NovyxError) throw err;
162
+ if (err.name === "AbortError") {
163
+ throw new NovyxError(`Request timed out after ${this.timeout}s`);
164
+ }
165
+ throw new NovyxError(`Request failed: ${err.message}`);
166
+ } finally {
167
+ clearTimeout(timeoutId);
168
+ }
169
+ }
170
+ // ========================================================================
171
+ // Memory Methods
172
+ // ========================================================================
173
+ async remember(observation, opts) {
174
+ const resolvedAgentId = opts?.agent_id ?? this.agentId;
175
+ const body = {
176
+ observation,
177
+ tags: opts?.tags ?? [],
178
+ importance: opts?.importance ?? 5
179
+ };
180
+ if (resolvedAgentId) body.agent_id = resolvedAgentId;
181
+ if (opts?.space_id) body.space_id = opts.space_id;
182
+ if (opts?.ttl_seconds !== void 0) body.ttl_seconds = opts.ttl_seconds;
183
+ if (opts?.context) {
184
+ body.context = opts.context;
185
+ } else if (opts?.metadata) {
186
+ body.context = JSON.stringify(opts.metadata);
187
+ }
188
+ return this._request("POST", "/v1/memories", { body });
189
+ }
190
+ async recall(query, opts) {
191
+ const params = {
192
+ q: query,
193
+ limit: opts?.limit ?? 5,
194
+ min_score: opts?.min_score ?? 0
195
+ };
196
+ if (opts?.tags) params.tags = opts.tags.join(",");
197
+ if (opts?.agents) params.agents = opts.agents.join(",");
198
+ if (opts?.space_id) params.space_id = opts.space_id;
199
+ const result = await this._request("GET", "/v1/memories/search", { params });
200
+ const raw = Array.isArray(result) ? result : result.memories ?? [];
201
+ return {
202
+ query,
203
+ total_results: raw.length,
204
+ memories: raw
205
+ };
206
+ }
207
+ async memories(opts) {
208
+ const params = {
209
+ limit: opts?.limit ?? 100,
210
+ offset: opts?.offset ?? 0
211
+ };
212
+ if (opts?.tags) params.tags = opts.tags.join(",");
213
+ if (opts?.min_importance !== void 0) params.min_importance = opts.min_importance;
214
+ if (opts?.include_shared) params.include_shared = "true";
215
+ if (opts?.agent_id) params.agent_id = opts.agent_id;
216
+ if (opts?.space_id) params.space_id = opts.space_id;
217
+ const result = await this._request("GET", "/v1/memories", { params });
218
+ return typeof result === "object" && !Array.isArray(result) ? result.memories ?? [] : result;
219
+ }
220
+ async memory(memoryId) {
221
+ return this._request("GET", `/v1/memories/${memoryId}`);
222
+ }
223
+ async forget(memoryId) {
224
+ const result = await this._request("DELETE", `/v1/memories/${memoryId}`);
225
+ return result?.success ?? true;
226
+ }
227
+ async delete(memoryId) {
228
+ return this.forget(memoryId);
229
+ }
230
+ async list(opts) {
231
+ const params = {
232
+ limit: opts?.limit ?? 100,
233
+ offset: opts?.offset ?? 0
234
+ };
235
+ if (opts?.tags) params.tags = opts.tags.join(",");
236
+ if (opts?.min_importance !== void 0) params.min_importance = opts.min_importance;
237
+ if (opts?.include_shared) params.include_shared = "true";
238
+ if (opts?.agent_id) params.agent_id = opts.agent_id;
239
+ if (opts?.space_id) params.space_id = opts.space_id;
240
+ const result = await this._request("GET", "/v1/memories", { params });
241
+ const rawMemories = typeof result === "object" && !Array.isArray(result) ? result.memories ?? [] : result;
242
+ return {
243
+ total_count: typeof result === "object" && !Array.isArray(result) ? result.total_count ?? rawMemories.length : rawMemories.length,
244
+ memories: rawMemories,
245
+ filters: typeof result === "object" && !Array.isArray(result) ? result.filters ?? {} : {}
246
+ };
247
+ }
248
+ async stats() {
249
+ return this._request("GET", "/v1/memories/stats");
250
+ }
251
+ // ========================================================================
252
+ // Context Space & Sharing
253
+ // ========================================================================
254
+ async shareContext(tag, toEmail, permission = "read") {
255
+ return this._request("POST", "/v1/spaces/share", {
256
+ body: { tag, email: toEmail, permission }
257
+ });
258
+ }
259
+ async acceptSharedContext(token) {
260
+ return this._request("POST", "/v1/spaces/join", {
261
+ body: { token }
262
+ });
263
+ }
264
+ async sharedContexts() {
265
+ return this._request("GET", "/v1/spaces/shared");
266
+ }
267
+ async revokeSharedContext(token) {
268
+ return this._request("DELETE", `/v1/spaces/share/${token}`);
269
+ }
270
+ async graph(opts) {
271
+ const params = {};
272
+ if (opts?.include_shared) params.include_shared = "true";
273
+ if (opts?.agents) params.agents = opts.agents.join(",");
274
+ return this._request("GET", "/v1/memories/graph", { params });
275
+ }
276
+ // ========================================================================
277
+ // Rollback
278
+ // ========================================================================
279
+ async rollback(target, dryRun = false, preserveEvidence = true) {
280
+ return this._request("POST", "/v1/rollback", {
281
+ body: { target, dry_run: dryRun, preserve_evidence: preserveEvidence }
282
+ });
283
+ }
284
+ async rollbackPreview(target) {
285
+ return this._request("GET", "/v1/rollback/preview", {
286
+ params: { target }
287
+ });
288
+ }
289
+ async rollbackHistory(limit = 50) {
290
+ const result = await this._request("GET", "/v1/rollback/history", {
291
+ params: { limit }
292
+ });
293
+ return Array.isArray(result) ? result : [];
294
+ }
295
+ // ========================================================================
296
+ // Audit
297
+ // ========================================================================
298
+ async audit(opts) {
299
+ const params = { limit: opts?.limit ?? 50 };
300
+ if (opts?.since) params.start_time = opts.since;
301
+ if (opts?.until) params.end_time = opts.until;
302
+ if (opts?.operation) params.operation = opts.operation;
303
+ if (opts?.artifact_id) params.artifact_id = opts.artifact_id;
304
+ const result = await this._request("GET", "/v1/audit", { params });
305
+ return typeof result === "object" && !Array.isArray(result) ? result.entries ?? [] : result;
306
+ }
307
+ async auditExport(format = "csv") {
308
+ return this._request("GET", "/v1/audit/export", {
309
+ params: { format },
310
+ rawResponse: true
311
+ });
312
+ }
313
+ async auditVerify() {
314
+ return this._request("GET", "/v1/audit/verify");
315
+ }
316
+ // ========================================================================
317
+ // Traces
318
+ // ========================================================================
319
+ async traceCreate(agentId, sessionId, metadata) {
320
+ return this._request("POST", "/v1/traces", {
321
+ body: {
322
+ agent_id: agentId,
323
+ session_id: sessionId,
324
+ metadata: metadata ?? {}
325
+ }
326
+ });
327
+ }
328
+ async traceStep(traceId, stepType, name, content, attributes) {
329
+ return this._request("POST", `/v1/traces/${traceId}/steps`, {
330
+ body: {
331
+ step_type: stepType,
332
+ name,
333
+ content,
334
+ attributes: attributes ?? {}
335
+ }
336
+ });
337
+ }
338
+ async traceComplete(traceId) {
339
+ return this._request("POST", `/v1/traces/${traceId}/complete`);
340
+ }
341
+ async traceVerify(traceId) {
342
+ return this._request("GET", `/v1/traces/${traceId}/verify`);
343
+ }
344
+ // ========================================================================
345
+ // Usage & Plans
346
+ // ========================================================================
347
+ async usage() {
348
+ return this._request("GET", "/v1/usage");
349
+ }
350
+ async plans() {
351
+ return this._request("GET", "/v1/plans");
352
+ }
353
+ async health() {
354
+ try {
355
+ const controller = new AbortController();
356
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout * 1e3);
357
+ try {
358
+ const response = await fetch(`${this.apiUrl}/health`, {
359
+ signal: controller.signal
360
+ });
361
+ return await response.json();
362
+ } finally {
363
+ clearTimeout(timeoutId);
364
+ }
365
+ } catch (err) {
366
+ return { status: "error", error: err.message };
367
+ }
368
+ }
369
+ // ========================================================================
370
+ // Sessions
371
+ // ========================================================================
372
+ session(sessionId) {
373
+ return new NovyxSession(this, sessionId);
374
+ }
375
+ // ========================================================================
376
+ // Links / Edges
377
+ // ========================================================================
378
+ async link(sourceId, targetId, opts) {
379
+ const body = {
380
+ source_id: sourceId,
381
+ target_id: targetId
382
+ };
383
+ if (opts?.relation) body.relation = opts.relation;
384
+ if (opts?.weight !== void 0) body.weight = opts.weight;
385
+ if (opts?.metadata) body.metadata = opts.metadata;
386
+ return this._request("POST", "/v1/memories/link", { body });
387
+ }
388
+ async unlink(sourceId, targetId, relation) {
389
+ const body = {
390
+ source_id: sourceId,
391
+ target_id: targetId
392
+ };
393
+ if (relation) body.relation = relation;
394
+ return this._request("DELETE", "/v1/memories/link", { body });
395
+ }
396
+ async links(memoryId, relation) {
397
+ const params = {};
398
+ if (relation) params.relation = relation;
399
+ return this._request("GET", `/v1/memories/${memoryId}/links`, { params });
400
+ }
401
+ };
402
+ export {
403
+ Novyx,
404
+ NovyxAuthError,
405
+ NovyxError,
406
+ NovyxForbiddenError,
407
+ NovyxNotFoundError,
408
+ NovyxRateLimitError,
409
+ NovyxSecurityError,
410
+ NovyxSession
411
+ };
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "novyx",
3
+ "version": "2.2.0",
4
+ "description": "Novyx SDK - Persistent memory, rollback, and audit trail for AI agents",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
20
+ "test": "vitest run",
21
+ "lint": "tsc --noEmit"
22
+ },
23
+ "engines": {
24
+ "node": ">=18"
25
+ },
26
+ "devDependencies": {
27
+ "tsup": "^8.0.0",
28
+ "typescript": "^5.3.0",
29
+ "vitest": "^1.0.0"
30
+ },
31
+ "license": "MIT",
32
+ "author": "Novyx Labs"
33
+ }