@aiassist-secure/core 1.0.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.
@@ -0,0 +1,223 @@
1
+ /**
2
+ * AiAssist SDK Types
3
+ */
4
+ interface Message {
5
+ role: 'system' | 'user' | 'assistant';
6
+ content: string;
7
+ name?: string;
8
+ }
9
+ interface ChatCompletionChoice {
10
+ index: number;
11
+ message: Message;
12
+ finish_reason: 'stop' | 'length' | 'content_filter' | null;
13
+ }
14
+ interface Usage {
15
+ prompt_tokens: number;
16
+ completion_tokens: number;
17
+ total_tokens: number;
18
+ }
19
+ interface ChatCompletion {
20
+ id: string;
21
+ object: 'chat.completion';
22
+ created: number;
23
+ model: string;
24
+ choices: ChatCompletionChoice[];
25
+ usage?: Usage;
26
+ }
27
+ interface ChatCompletionChunkDelta {
28
+ role?: 'assistant';
29
+ content?: string;
30
+ }
31
+ interface ChatCompletionChunkChoice {
32
+ index: number;
33
+ delta: ChatCompletionChunkDelta;
34
+ finish_reason: 'stop' | 'length' | 'content_filter' | null;
35
+ }
36
+ interface ChatCompletionChunk {
37
+ id: string;
38
+ object: 'chat.completion.chunk';
39
+ created: number;
40
+ model: string;
41
+ choices: ChatCompletionChunkChoice[];
42
+ }
43
+ interface ChatCompletionCreateParams {
44
+ messages: Message[];
45
+ model?: string;
46
+ temperature?: number;
47
+ max_tokens?: number;
48
+ top_p?: number;
49
+ stream?: boolean;
50
+ provider?: string;
51
+ }
52
+ type WorkspaceMode = 'ai' | 'shadow' | 'takeover';
53
+ type WorkspaceStatus = 'active' | 'archived' | 'deleted';
54
+ type MessageRole = 'user' | 'ai' | 'human' | 'system';
55
+ interface Workspace {
56
+ id: string;
57
+ mode: WorkspaceMode;
58
+ status: WorkspaceStatus;
59
+ metadata?: Record<string, unknown>;
60
+ created_at?: string;
61
+ updated_at?: string;
62
+ }
63
+ interface WorkspaceMessage {
64
+ id: string;
65
+ role: MessageRole;
66
+ content: string;
67
+ created_at?: string;
68
+ workspace_id?: string;
69
+ }
70
+ interface WorkspaceCreateParams {
71
+ initial_message?: string;
72
+ client_id?: string;
73
+ system_prompt?: string;
74
+ context?: Record<string, unknown>;
75
+ metadata?: Record<string, unknown>;
76
+ }
77
+ interface WorkspaceCreateResponse {
78
+ workspace: Workspace;
79
+ messages: WorkspaceMessage[];
80
+ }
81
+ interface SendMessageResponse {
82
+ user_message: WorkspaceMessage;
83
+ responses: WorkspaceMessage[];
84
+ mode: WorkspaceMode;
85
+ pending_approval?: boolean;
86
+ }
87
+ interface WorkspaceByClientResponse {
88
+ workspace: Workspace | null;
89
+ messages: WorkspaceMessage[];
90
+ exists: boolean;
91
+ }
92
+ interface Model {
93
+ id: string;
94
+ object: 'model';
95
+ owned_by: string;
96
+ created?: number;
97
+ }
98
+ interface ModelList {
99
+ object: 'list';
100
+ data: Model[];
101
+ }
102
+ interface LeadInfo {
103
+ leadId: string;
104
+ email: string;
105
+ }
106
+ interface AiAssistClientOptions {
107
+ apiKey: string;
108
+ baseURL?: string;
109
+ timeout?: number;
110
+ maxRetries?: number;
111
+ defaultHeaders?: Record<string, string>;
112
+ }
113
+ declare class AiAssistError extends Error {
114
+ status?: number;
115
+ code?: string;
116
+ constructor(message: string, status?: number, code?: string);
117
+ }
118
+ declare class AuthenticationError extends AiAssistError {
119
+ constructor(message?: string);
120
+ }
121
+ declare class RateLimitError extends AiAssistError {
122
+ retryAfter?: number;
123
+ constructor(message?: string, retryAfter?: number);
124
+ }
125
+ declare class APIError extends AiAssistError {
126
+ constructor(message: string, status?: number, code?: string);
127
+ }
128
+
129
+ /**
130
+ * AiAssist API Client
131
+ *
132
+ * Framework-agnostic TypeScript client for the AiAssist API.
133
+ * Works in Node.js and browsers.
134
+ *
135
+ * Full feature parity with React and Vanilla SDKs including:
136
+ * - Shadow mode support (pending_approval)
137
+ * - Human-in-the-loop mode detection
138
+ * - Typing preview
139
+ * - Conversation management
140
+ */
141
+
142
+ declare class AiAssistClient {
143
+ private apiKey;
144
+ private baseURL;
145
+ private timeout;
146
+ private maxRetries;
147
+ private defaultHeaders;
148
+ chat: ChatAPI;
149
+ models: ModelsAPI;
150
+ workspaces: WorkspacesAPI;
151
+ constructor(options: AiAssistClientOptions);
152
+ private getHeaders;
153
+ request<T>(method: string, path: string, options?: {
154
+ body?: unknown;
155
+ headers?: Record<string, string>;
156
+ }): Promise<T>;
157
+ requestSilent(method: string, path: string, options?: {
158
+ body?: unknown;
159
+ }): Promise<void>;
160
+ stream(method: string, path: string, body: unknown): AsyncGenerator<ChatCompletionChunk, void, unknown>;
161
+ private sleep;
162
+ }
163
+ declare class ChatAPI {
164
+ completions: ChatCompletionsAPI;
165
+ constructor(client: AiAssistClient);
166
+ }
167
+ declare class ChatCompletionsAPI {
168
+ private client;
169
+ constructor(client: AiAssistClient);
170
+ create(params: ChatCompletionCreateParams & {
171
+ stream?: false;
172
+ }): Promise<ChatCompletion>;
173
+ create(params: ChatCompletionCreateParams & {
174
+ stream: true;
175
+ }): Promise<AsyncGenerator<ChatCompletionChunk, void, unknown>>;
176
+ create(params: ChatCompletionCreateParams): Promise<ChatCompletion | AsyncGenerator<ChatCompletionChunk, void, unknown>>;
177
+ }
178
+ declare class ModelsAPI {
179
+ private client;
180
+ constructor(client: AiAssistClient);
181
+ list(): Promise<Model[]>;
182
+ }
183
+ declare class WorkspacesAPI {
184
+ private client;
185
+ constructor(client: AiAssistClient);
186
+ /**
187
+ * Create a new workspace with optional system prompt and context.
188
+ *
189
+ * @param params - Workspace creation options
190
+ * @returns Workspace and initial messages
191
+ */
192
+ create(params?: WorkspaceCreateParams): Promise<WorkspaceCreateResponse>;
193
+ /**
194
+ * Get workspace by ID.
195
+ */
196
+ get(workspaceId: string): Promise<Workspace>;
197
+ /**
198
+ * Get workspace by client ID.
199
+ * Returns null if not found.
200
+ */
201
+ getByClientId(clientId: string): Promise<WorkspaceByClientResponse>;
202
+ /**
203
+ * Send a message to a workspace.
204
+ * Returns user message, AI/human responses, mode, and shadow mode approval status.
205
+ */
206
+ sendMessage(workspaceId: string, content: string): Promise<SendMessageResponse>;
207
+ /**
208
+ * Get all messages in a workspace.
209
+ */
210
+ getMessages(workspaceId: string): Promise<WorkspaceMessage[]>;
211
+ /**
212
+ * Send typing preview to workspace (for real-time typing indicators).
213
+ * Fails silently - non-critical operation.
214
+ */
215
+ sendTypingPreview(workspaceId: string, text: string): Promise<void>;
216
+ /**
217
+ * End a conversation/workspace.
218
+ * Fails silently - non-critical operation.
219
+ */
220
+ endConversation(workspaceId: string): Promise<void>;
221
+ }
222
+
223
+ export { APIError, AiAssistClient, type AiAssistClientOptions, AiAssistError, AuthenticationError, type ChatCompletion, type ChatCompletionChoice, type ChatCompletionChunk, type ChatCompletionChunkChoice, type ChatCompletionChunkDelta, type ChatCompletionCreateParams, type LeadInfo, type Message, type MessageRole, type Model, type ModelList, RateLimitError, type SendMessageResponse, type Usage, type Workspace, type WorkspaceByClientResponse, type WorkspaceCreateParams, type WorkspaceCreateResponse, type WorkspaceMessage, type WorkspaceMode, type WorkspaceStatus };
package/dist/index.js ADDED
@@ -0,0 +1,345 @@
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
+ APIError: () => APIError,
24
+ AiAssistClient: () => AiAssistClient,
25
+ AiAssistError: () => AiAssistError,
26
+ AuthenticationError: () => AuthenticationError,
27
+ RateLimitError: () => RateLimitError
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/types.ts
32
+ var AiAssistError = class extends Error {
33
+ constructor(message, status, code) {
34
+ super(message);
35
+ this.name = "AiAssistError";
36
+ this.status = status;
37
+ this.code = code;
38
+ }
39
+ };
40
+ var AuthenticationError = class extends AiAssistError {
41
+ constructor(message = "Invalid API key") {
42
+ super(message, 401, "invalid_api_key");
43
+ this.name = "AuthenticationError";
44
+ }
45
+ };
46
+ var RateLimitError = class extends AiAssistError {
47
+ constructor(message = "Rate limit exceeded", retryAfter) {
48
+ super(message, 429, "rate_limit_exceeded");
49
+ this.name = "RateLimitError";
50
+ this.retryAfter = retryAfter;
51
+ }
52
+ };
53
+ var APIError = class extends AiAssistError {
54
+ constructor(message, status, code) {
55
+ super(message, status, code);
56
+ this.name = "APIError";
57
+ }
58
+ };
59
+
60
+ // src/client.ts
61
+ var DEFAULT_BASE_URL = "https://api.aiassist.net";
62
+ var DEFAULT_TIMEOUT = 3e4;
63
+ var DEFAULT_MAX_RETRIES = 3;
64
+ var VERSION = "1.0.0";
65
+ function normalizeRole(role) {
66
+ if (role === "assistant" || role === "ai") return "ai";
67
+ if (role === "human") return "human";
68
+ if (role === "system") return "system";
69
+ return "user";
70
+ }
71
+ var AiAssistClient = class {
72
+ constructor(options) {
73
+ this.apiKey = options.apiKey;
74
+ this.baseURL = options.baseURL ?? DEFAULT_BASE_URL;
75
+ this.timeout = options.timeout ?? DEFAULT_TIMEOUT;
76
+ this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
77
+ this.defaultHeaders = options.defaultHeaders ?? {};
78
+ this.chat = new ChatAPI(this);
79
+ this.models = new ModelsAPI(this);
80
+ this.workspaces = new WorkspacesAPI(this);
81
+ }
82
+ getHeaders() {
83
+ return {
84
+ "Content-Type": "application/json",
85
+ "X-API-Key": this.apiKey,
86
+ "Authorization": `Bearer ${this.apiKey}`,
87
+ "User-Agent": `aiassist-js/${VERSION}`,
88
+ ...this.defaultHeaders
89
+ };
90
+ }
91
+ async request(method, path, options) {
92
+ const url = `${this.baseURL}${path}`;
93
+ const headers = { ...this.getHeaders(), ...options?.headers };
94
+ let lastError = null;
95
+ for (let attempt = 0; attempt < this.maxRetries; attempt++) {
96
+ try {
97
+ const controller = new AbortController();
98
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
99
+ const response = await fetch(url, {
100
+ method,
101
+ headers,
102
+ body: options?.body ? JSON.stringify(options.body) : void 0,
103
+ signal: controller.signal
104
+ });
105
+ clearTimeout(timeoutId);
106
+ if (response.status === 401) {
107
+ throw new AuthenticationError();
108
+ }
109
+ if (response.status === 429) {
110
+ const retryAfter = parseInt(response.headers.get("Retry-After") ?? "5", 10);
111
+ if (attempt < this.maxRetries - 1) {
112
+ await this.sleep(retryAfter * 1e3);
113
+ continue;
114
+ }
115
+ throw new RateLimitError("Rate limit exceeded", retryAfter);
116
+ }
117
+ if (!response.ok) {
118
+ const errorData = await response.json().catch(() => ({}));
119
+ throw new APIError(
120
+ errorData.detail ?? `HTTP ${response.status}`,
121
+ response.status,
122
+ errorData.code
123
+ );
124
+ }
125
+ return await response.json();
126
+ } catch (error) {
127
+ lastError = error;
128
+ if (error instanceof AiAssistError) {
129
+ throw error;
130
+ }
131
+ if (attempt < this.maxRetries - 1) {
132
+ await this.sleep(Math.pow(2, attempt) * 1e3);
133
+ continue;
134
+ }
135
+ }
136
+ }
137
+ throw new APIError(`Request failed: ${lastError?.message}`);
138
+ }
139
+ async requestSilent(method, path, options) {
140
+ try {
141
+ await this.request(method, path, options);
142
+ } catch {
143
+ }
144
+ }
145
+ async *stream(method, path, body) {
146
+ const url = `${this.baseURL}${path}`;
147
+ const headers = this.getHeaders();
148
+ const response = await fetch(url, {
149
+ method,
150
+ headers,
151
+ body: JSON.stringify(body)
152
+ });
153
+ if (!response.ok) {
154
+ if (response.status === 401) throw new AuthenticationError();
155
+ if (response.status === 429) throw new RateLimitError();
156
+ const errorData = await response.json().catch(() => ({}));
157
+ throw new APIError(errorData.detail ?? `HTTP ${response.status}`, response.status);
158
+ }
159
+ const reader = response.body?.getReader();
160
+ if (!reader) throw new APIError("Response body is not readable");
161
+ const decoder = new TextDecoder();
162
+ let buffer = "";
163
+ while (true) {
164
+ const { done, value } = await reader.read();
165
+ if (done) break;
166
+ buffer += decoder.decode(value, { stream: true });
167
+ const lines = buffer.split("\n");
168
+ buffer = lines.pop() ?? "";
169
+ for (const line of lines) {
170
+ if (line.startsWith("data: ")) {
171
+ const data = line.slice(6);
172
+ if (data === "[DONE]") return;
173
+ try {
174
+ yield JSON.parse(data);
175
+ } catch {
176
+ }
177
+ }
178
+ }
179
+ }
180
+ }
181
+ sleep(ms) {
182
+ return new Promise((resolve) => setTimeout(resolve, ms));
183
+ }
184
+ };
185
+ var ChatAPI = class {
186
+ constructor(client) {
187
+ this.completions = new ChatCompletionsAPI(client);
188
+ }
189
+ };
190
+ var ChatCompletionsAPI = class {
191
+ constructor(client) {
192
+ this.client = client;
193
+ }
194
+ async create(params) {
195
+ if (params.stream) {
196
+ return this.client.stream("POST", "/v1/chat/completions", params);
197
+ }
198
+ return this.client.request("POST", "/v1/chat/completions", {
199
+ body: params
200
+ });
201
+ }
202
+ };
203
+ var ModelsAPI = class {
204
+ constructor(client) {
205
+ this.client = client;
206
+ }
207
+ async list() {
208
+ const response = await this.client.request("GET", "/v1/models");
209
+ return response.data;
210
+ }
211
+ };
212
+ var WorkspacesAPI = class {
213
+ constructor(client) {
214
+ this.client = client;
215
+ }
216
+ /**
217
+ * Create a new workspace with optional system prompt and context.
218
+ *
219
+ * @param params - Workspace creation options
220
+ * @returns Workspace and initial messages
221
+ */
222
+ async create(params) {
223
+ const body = {};
224
+ if (params?.initial_message) body.initial_message = params.initial_message;
225
+ if (params?.client_id) body.client_id = params.client_id;
226
+ if (params?.system_prompt) body.system_prompt = params.system_prompt;
227
+ if (params?.context) body.context = params.context;
228
+ if (params?.metadata) body.metadata = params.metadata;
229
+ const data = await this.client.request("POST", "/api/workspaces", { body });
230
+ return {
231
+ workspace: {
232
+ id: data.workspace.id,
233
+ mode: data.workspace.mode,
234
+ status: data.workspace.status || "active"
235
+ },
236
+ messages: (data.messages || []).map((m) => ({
237
+ id: m.id,
238
+ role: normalizeRole(m.role),
239
+ content: m.content,
240
+ created_at: m.created_at
241
+ }))
242
+ };
243
+ }
244
+ /**
245
+ * Get workspace by ID.
246
+ */
247
+ async get(workspaceId) {
248
+ const data = await this.client.request("GET", `/api/workspaces/${workspaceId}`);
249
+ const ws = data.workspace || data;
250
+ return {
251
+ id: ws.id,
252
+ mode: ws.mode || "ai",
253
+ status: ws.status || "active"
254
+ };
255
+ }
256
+ /**
257
+ * Get workspace by client ID.
258
+ * Returns null if not found.
259
+ */
260
+ async getByClientId(clientId) {
261
+ try {
262
+ const data = await this.client.request("GET", `/api/workspaces/by-client/${clientId}`);
263
+ return {
264
+ workspace: data.workspace ? {
265
+ id: data.workspace.id,
266
+ mode: data.workspace.mode,
267
+ status: "active"
268
+ } : null,
269
+ messages: (data.messages || []).map((m) => ({
270
+ id: m.id,
271
+ role: normalizeRole(m.role),
272
+ content: m.content,
273
+ created_at: m.created_at
274
+ })),
275
+ exists: data.exists
276
+ };
277
+ } catch (error) {
278
+ if (error instanceof APIError && error.status === 404) {
279
+ return { workspace: null, messages: [], exists: false };
280
+ }
281
+ throw error;
282
+ }
283
+ }
284
+ /**
285
+ * Send a message to a workspace.
286
+ * Returns user message, AI/human responses, mode, and shadow mode approval status.
287
+ */
288
+ async sendMessage(workspaceId, content) {
289
+ const data = await this.client.request("POST", `/api/workspaces/${workspaceId}/messages`, {
290
+ body: { content }
291
+ });
292
+ return {
293
+ user_message: {
294
+ id: data.user_message.id,
295
+ role: "user",
296
+ content: data.user_message.content,
297
+ created_at: data.user_message.created_at
298
+ },
299
+ responses: data.responses.map((r) => ({
300
+ id: r.id,
301
+ role: normalizeRole(r.role),
302
+ content: r.content,
303
+ created_at: r.created_at
304
+ })),
305
+ mode: data.mode,
306
+ pending_approval: data.pending_approval
307
+ };
308
+ }
309
+ /**
310
+ * Get all messages in a workspace.
311
+ */
312
+ async getMessages(workspaceId) {
313
+ const data = await this.client.request("GET", `/api/workspaces/${workspaceId}/messages`);
314
+ return (data.messages || []).map((m) => ({
315
+ id: m.id,
316
+ role: normalizeRole(m.role),
317
+ content: m.content,
318
+ created_at: m.created_at
319
+ }));
320
+ }
321
+ /**
322
+ * Send typing preview to workspace (for real-time typing indicators).
323
+ * Fails silently - non-critical operation.
324
+ */
325
+ async sendTypingPreview(workspaceId, text) {
326
+ await this.client.requestSilent("POST", `/api/workspaces/${workspaceId}/typing`, {
327
+ body: { text }
328
+ });
329
+ }
330
+ /**
331
+ * End a conversation/workspace.
332
+ * Fails silently - non-critical operation.
333
+ */
334
+ async endConversation(workspaceId) {
335
+ await this.client.requestSilent("POST", `/api/workspaces/${workspaceId}/end`, {});
336
+ }
337
+ };
338
+ // Annotate the CommonJS export names for ESM import in node:
339
+ 0 && (module.exports = {
340
+ APIError,
341
+ AiAssistClient,
342
+ AiAssistError,
343
+ AuthenticationError,
344
+ RateLimitError
345
+ });