arcane-sdk 0.1.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/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2023-2025 ArcaneTracing
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # arcane-sdk
2
+
3
+ Official TypeScript/JavaScript SDK for the Arcane public API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install arcane-sdk
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { Arcane } from 'arcane-sdk';
15
+
16
+ const arcane = new Arcane({
17
+ baseUrl: 'https://your-instance.example.com',
18
+ apiKey: process.env.ARCAN_API_KEY!,
19
+ });
20
+
21
+ // List prompts
22
+ const prompts = await arcane.prompts.list();
23
+
24
+ // Get a dataset (paginated rows, default page 1)
25
+ const dataset = await arcane.datasets.get('dataset-uuid', { page: 1, limit: 20 });
26
+
27
+ // Iterate over all rows without loading everything
28
+ for await (const row of arcane.datasets.listRowsPaginated('dataset-uuid')) {
29
+ console.log(row.values);
30
+ }
31
+
32
+ // Add a row
33
+ const newRow = await arcane.datasets.addRow('dataset-uuid', {
34
+ values: ['input1', 'input2', 'expected'],
35
+ });
36
+
37
+ // Search traces
38
+ const searchResult = await arcane.traces.search('datasource-uuid', {
39
+ limit: 100,
40
+ q: 'status_code=200',
41
+ });
42
+
43
+ // Iterate over experiment results (paginated, memory-efficient)
44
+ for await (const result of arcane.experiments.listResultsPaginated('experiment-uuid')) {
45
+ console.log(result.datasetRow, result.experimentResult);
46
+ }
47
+ ```
48
+
49
+ ## Authentication
50
+
51
+ Use a **project-scoped API key**. Create one in the Arcane UI under Project → API Keys.
52
+
53
+ The SDK uses HTTP Basic Auth with username `api-key` and the API key as the password.
54
+
55
+ ## Resources
56
+
57
+ | Resource | Methods |
58
+ | ------------ | ----------------------------------------------------------------------- |
59
+ | `prompts` | `list()`, `get(id)`, `listVersions(id)`, `getLatestVersion(id)` |
60
+ | `datasources`| `list()` |
61
+ | `traces` | `search(datasourceId, params)`, `get(datasourceId, traceId)`, `getAttributeNames()`, `getAttributeValues()` |
62
+ | `datasets` | `list()`, `get(id, params?)`, `listRowsPaginated(id)`, `addRow(id, { values })` |
63
+ | `entities` | `list()`, `get(id)` |
64
+ | `evaluations`| `list()`, `get(id)`, `getExperimentScores()`, `create()`, `createResult()` |
65
+ | `experiments`| `list()`, `get(id)`, `listResults()`, `listResultsPaginated()`, `create()`, `createResult()` |
66
+
67
+ ## Retries
68
+
69
+ The SDK automatically retries on:
70
+
71
+ - HTTP 5xx errors
72
+ - Network errors (`ECONNRESET`, `ETIMEDOUT`)
73
+
74
+ Configure with `maxRetries` (default: 3):
75
+
76
+ ```typescript
77
+ const arcane = new Arcane({
78
+ baseUrl: 'https://api.example.com',
79
+ apiKey: '...',
80
+ maxRetries: 5,
81
+ });
82
+ ```
83
+
84
+ ## Error Handling
85
+
86
+ ```typescript
87
+ import { Arcane, ArcanApiError, ArcanNotFoundError } from 'arcane-sdk';
88
+
89
+ try {
90
+ await arcane.datasets.get('invalid-id');
91
+ } catch (err) {
92
+ if (err instanceof ArcanNotFoundError) {
93
+ console.log('Dataset not found');
94
+ } else if (err instanceof ArcanApiError) {
95
+ console.log(err.statusCode, err.message, err.requestId);
96
+ }
97
+ }
98
+ ```
99
+
100
+ ## License
101
+
102
+ MIT
@@ -0,0 +1,415 @@
1
+ import { AxiosInstance, AxiosError } from 'axios';
2
+
3
+ interface ArcaneClientConfig {
4
+ baseUrl: string;
5
+ apiKey: string;
6
+ maxRetries?: number;
7
+ timeout?: number;
8
+ }
9
+ declare class ArcaneClient {
10
+ private readonly http;
11
+ constructor(config: ArcaneClientConfig);
12
+ getHttp(): AxiosInstance;
13
+ get<T>(path: string, params?: Record<string, unknown>): Promise<T>;
14
+ post<T>(path: string, body?: unknown): Promise<T>;
15
+ handleError(err: unknown): never;
16
+ }
17
+
18
+ interface PaginationMeta {
19
+ page: number;
20
+ limit: number;
21
+ total: number;
22
+ totalPages: number;
23
+ hasNextPage: boolean;
24
+ hasPreviousPage: boolean;
25
+ }
26
+ interface Prompt {
27
+ id: string;
28
+ name: string;
29
+ description: string | null;
30
+ metadata: Record<string, unknown> | null;
31
+ promotedVersionId: string | null;
32
+ createdAt: string;
33
+ updatedAt: string;
34
+ }
35
+ interface PromptVersion {
36
+ id: string;
37
+ promptId: string;
38
+ promptName: string;
39
+ versionName: string | null;
40
+ description: string | null;
41
+ modelConfigurationId: string;
42
+ template: unknown;
43
+ templateType: string;
44
+ templateFormat: string;
45
+ invocationParameters: unknown;
46
+ tools: unknown | null;
47
+ responseFormat: unknown | null;
48
+ createdAt: string;
49
+ updatedAt: string;
50
+ }
51
+ interface Entity {
52
+ id: string;
53
+ name: string;
54
+ description?: string;
55
+ type: string;
56
+ matchingAttributeName: string;
57
+ matchingPatternType: string;
58
+ matchingPattern?: string | null;
59
+ matchingValue?: string | null;
60
+ entityType: string;
61
+ entityHighlights?: Array<{
62
+ title: string;
63
+ key: string;
64
+ valueType: string;
65
+ }>;
66
+ messageMatching?: Record<string, unknown> | null;
67
+ iconId?: string | null;
68
+ createdAt: string;
69
+ updatedAt: string;
70
+ }
71
+ interface DatasourceListItem {
72
+ id: string;
73
+ name: string;
74
+ description: string;
75
+ type: string;
76
+ source: string;
77
+ isSearchByQueryEnabled: boolean;
78
+ isSearchByAttributesEnabled: boolean;
79
+ isGetAttributeNamesEnabled: boolean;
80
+ isGetAttributeValuesEnabled: boolean;
81
+ }
82
+ interface TraceSearchResponse {
83
+ traces: Array<{
84
+ traceID: string;
85
+ rootServiceName?: string;
86
+ rootTraceName?: string;
87
+ startTimeUnixNano?: string;
88
+ durationMs?: number;
89
+ spanSet?: {
90
+ spans?: unknown[];
91
+ matched?: number;
92
+ };
93
+ }>;
94
+ }
95
+ interface TraceResponse {
96
+ batches: unknown[];
97
+ }
98
+ interface DatasetListItem {
99
+ id: string;
100
+ name: string;
101
+ description?: string;
102
+ createdAt: string;
103
+ updatedAt: string;
104
+ }
105
+ interface DatasetRow {
106
+ id: string;
107
+ values: string[];
108
+ }
109
+ interface Dataset {
110
+ id: string;
111
+ name: string;
112
+ description?: string;
113
+ header: string[];
114
+ rows: DatasetRow[];
115
+ createdAt: string;
116
+ updatedAt: string;
117
+ }
118
+ interface PaginatedDataset {
119
+ id: string;
120
+ name: string;
121
+ description?: string;
122
+ header: string[];
123
+ data: DatasetRow[];
124
+ pagination: PaginationMeta;
125
+ }
126
+ interface Evaluation {
127
+ id: string;
128
+ projectId: string;
129
+ evaluationType: string;
130
+ evaluationScope: string;
131
+ name: string;
132
+ description?: string | null;
133
+ datasetId?: string | null;
134
+ metadata?: Record<string, unknown> | null;
135
+ scoreMappings?: Record<string, Record<string, unknown>> | null;
136
+ ragasModelConfigurationId?: string | null;
137
+ scores: Array<{
138
+ id: string;
139
+ description: string;
140
+ scoringType: string;
141
+ }>;
142
+ experiments: Array<{
143
+ id: string;
144
+ promptVersionId: string;
145
+ datasetId: string;
146
+ }>;
147
+ createdAt: string;
148
+ updatedAt: string;
149
+ }
150
+ interface EvaluationResult {
151
+ id: string;
152
+ datasetRowId?: string | null;
153
+ datasetRow?: DatasetRow | null;
154
+ experimentResultId?: string | null;
155
+ scoreResults: Array<{
156
+ id: string;
157
+ scoreId: string;
158
+ value: number | null;
159
+ reasoning?: string | null;
160
+ status: string;
161
+ datasetRowId?: string | null;
162
+ }>;
163
+ createdAt: string;
164
+ }
165
+ interface ExperimentScores {
166
+ experimentId: string;
167
+ evaluationId: string;
168
+ scoreResults: Array<{
169
+ id: string;
170
+ scoreId: string;
171
+ value: number | null;
172
+ reasoning?: string | null;
173
+ status: string;
174
+ datasetRowId?: string | null;
175
+ }>;
176
+ totalCount: number;
177
+ }
178
+ interface Experiment {
179
+ id: string;
180
+ projectId: string;
181
+ name: string;
182
+ description?: string | null;
183
+ promptVersionId: string;
184
+ datasetId: string;
185
+ promptInputMappings: Record<string, string>;
186
+ createdAt: string;
187
+ updatedAt: string;
188
+ results?: ExperimentResult[];
189
+ }
190
+ interface ExperimentResult {
191
+ id: string;
192
+ datasetRowId: string;
193
+ result: string | null;
194
+ status: string;
195
+ createdAt: string;
196
+ }
197
+ interface CombinedExperimentResult {
198
+ datasetRow: DatasetRow;
199
+ experimentResult: string | null;
200
+ experimentResultId: string;
201
+ createdAt: string;
202
+ }
203
+ interface PaginatedExperimentResults {
204
+ data: CombinedExperimentResult[];
205
+ pagination: PaginationMeta;
206
+ }
207
+ interface SearchTracesParams {
208
+ minDuration?: number;
209
+ maxDuration?: number;
210
+ start?: string;
211
+ end?: string;
212
+ limit?: number;
213
+ q?: string;
214
+ serviceName?: string;
215
+ operationName?: string;
216
+ attributes?: string;
217
+ filterByAttributeExists?: string[];
218
+ }
219
+ interface PaginationParams {
220
+ page?: number;
221
+ limit?: number;
222
+ search?: string;
223
+ sortBy?: string;
224
+ sortOrder?: 'asc' | 'desc';
225
+ }
226
+ interface CreateEvaluationParams {
227
+ evaluationType: 'AUTOMATIC' | 'MANUAL';
228
+ evaluationScope: 'DATASET' | 'EXPERIMENT';
229
+ name: string;
230
+ description?: string;
231
+ scoreIds: string[];
232
+ datasetId?: string;
233
+ experimentIds?: string[];
234
+ metadata?: Record<string, unknown>;
235
+ scoreMappings?: Record<string, Record<string, unknown>>;
236
+ ragasModelConfigurationId?: string;
237
+ }
238
+ interface CreateEvaluationResultParams {
239
+ datasetRowId?: string;
240
+ experimentResultId?: string;
241
+ scoreResults: Array<{
242
+ scoreId: string;
243
+ value: number;
244
+ reasoning?: string;
245
+ }>;
246
+ }
247
+ interface CreateExperimentParams {
248
+ name: string;
249
+ description?: string | null;
250
+ promptVersionId: string;
251
+ datasetId: string;
252
+ promptInputMappings?: Record<string, string>;
253
+ }
254
+ interface CreateExperimentResultParams {
255
+ datasetRowId: string;
256
+ result: string;
257
+ }
258
+ interface AddDatasetRowParams {
259
+ values: string[];
260
+ }
261
+ interface PendingScoreResult {
262
+ id: string;
263
+ scoreId: string;
264
+ value: number | null;
265
+ reasoning?: string | null;
266
+ status: string;
267
+ datasetRowId?: string | null;
268
+ experimentResultId?: string | null;
269
+ }
270
+ interface PaginatedPendingScoreResults {
271
+ data: PendingScoreResult[];
272
+ pagination: PaginationMeta;
273
+ }
274
+ interface ListPendingScoreResultsOptions {
275
+ experimentId?: string;
276
+ page?: number;
277
+ limit?: number;
278
+ }
279
+ interface ImportScoreResultRow {
280
+ datasetRowId?: string;
281
+ experimentResultId?: string;
282
+ value: number;
283
+ reasoning?: string;
284
+ }
285
+ interface ImportScoreResultsResponse {
286
+ importedCount: number;
287
+ }
288
+
289
+ declare class PromptsResource {
290
+ private readonly client;
291
+ constructor(client: ArcaneClient);
292
+ list(): Promise<Prompt[]>;
293
+ get(promptIdentifier: string): Promise<Prompt>;
294
+ listVersions(promptIdentifier: string): Promise<PromptVersion[]>;
295
+ getLatestVersion(promptIdentifier: string): Promise<PromptVersion>;
296
+ }
297
+
298
+ declare class DatasourcesResource {
299
+ private readonly client;
300
+ constructor(client: ArcaneClient);
301
+ list(): Promise<DatasourceListItem[]>;
302
+ }
303
+
304
+ declare class TracesResource {
305
+ private readonly client;
306
+ constructor(client: ArcaneClient);
307
+ search(datasourceId: string, params?: SearchTracesParams): Promise<TraceSearchResponse>;
308
+ get(datasourceId: string, traceId: string): Promise<TraceResponse>;
309
+ getAttributeNames(datasourceId: string): Promise<string[]>;
310
+ getAttributeValues(datasourceId: string, attributeName: string): Promise<string[]>;
311
+ }
312
+
313
+ declare class DatasetsResource {
314
+ private readonly client;
315
+ constructor(client: ArcaneClient);
316
+ list(): Promise<DatasetListItem[]>;
317
+ get(datasetId: string, params?: PaginationParams): Promise<PaginatedDataset>;
318
+ listRowsPaginated(datasetId: string, options?: {
319
+ pageSize?: number;
320
+ }): AsyncGenerator<DatasetRow, void, unknown>;
321
+ addRow(datasetId: string, params: AddDatasetRowParams): Promise<DatasetRow>;
322
+ }
323
+
324
+ declare class EntitiesResource {
325
+ private readonly client;
326
+ constructor(client: ArcaneClient);
327
+ list(): Promise<Entity[]>;
328
+ get(entityId: string): Promise<Entity>;
329
+ }
330
+
331
+ declare class EvaluationsResource {
332
+ private readonly client;
333
+ constructor(client: ArcaneClient);
334
+ list(): Promise<Evaluation[]>;
335
+ get(evaluationId: string): Promise<Evaluation>;
336
+ getExperimentScores(evaluationId: string, experimentId: string): Promise<ExperimentScores>;
337
+ create(params: CreateEvaluationParams): Promise<Evaluation>;
338
+ createResult(evaluationId: string, params: CreateEvaluationResultParams): Promise<EvaluationResult>;
339
+ listPendingScoreResults(evaluationId: string, scoreId: string, options?: ListPendingScoreResultsOptions): Promise<{
340
+ data: PendingScoreResult[];
341
+ pagination: {
342
+ page: number;
343
+ limit: number;
344
+ total: number;
345
+ totalPages: number;
346
+ hasNextPage: boolean;
347
+ hasPreviousPage: boolean;
348
+ };
349
+ }>;
350
+ listPendingScoreResultsIterator(evaluationId: string, scoreId: string, options?: Omit<ListPendingScoreResultsOptions, 'page'>): AsyncGenerator<PendingScoreResult>;
351
+ importScoreResults(evaluationId: string, scoreId: string, results: ImportScoreResultRow[]): Promise<ImportScoreResultsResponse>;
352
+ }
353
+
354
+ declare class ExperimentsResource {
355
+ private readonly client;
356
+ constructor(client: ArcaneClient);
357
+ list(): Promise<Experiment[]>;
358
+ get(experimentId: string): Promise<Experiment>;
359
+ listResults(experimentId: string, params?: PaginationParams): Promise<PaginatedExperimentResults>;
360
+ listResultsPaginated(experimentId: string, options?: {
361
+ pageSize?: number;
362
+ }): AsyncGenerator<CombinedExperimentResult, void, unknown>;
363
+ create(params: CreateExperimentParams): Promise<Experiment>;
364
+ createResult(experimentId: string, params: CreateExperimentResultParams): Promise<ExperimentResult>;
365
+ }
366
+
367
+ declare class ArcanApiError extends Error {
368
+ readonly statusCode?: number | undefined;
369
+ readonly requestId?: string | undefined;
370
+ readonly cause?: unknown | undefined;
371
+ constructor(message: string, statusCode?: number | undefined, requestId?: string | undefined, cause?: unknown | undefined);
372
+ static fromAxiosError(err: AxiosError<{
373
+ message?: string;
374
+ }>): ArcanApiError;
375
+ }
376
+ declare class ArcanNotFoundError extends ArcanApiError {
377
+ constructor(message: string, requestId?: string);
378
+ }
379
+ declare class ArcanUnauthorizedError extends ArcanApiError {
380
+ constructor(message: string, requestId?: string);
381
+ }
382
+
383
+ /**
384
+ * High-level client for the Arcane public API.
385
+ * Use project-scoped API keys for authentication.
386
+ *
387
+ * @example
388
+ * ```ts
389
+ * import { Arcan } from 'arcane-sdk';
390
+ *
391
+ * const arcan = new Arcan({
392
+ * baseUrl: 'https://api.example.com',
393
+ * apiKey: process.env.ARCAN_API_KEY!,
394
+ * });
395
+ *
396
+ * const prompts = await arcan.prompts.list();
397
+ * const datasets = await arcan.datasets.list();
398
+ *
399
+ * for await (const result of arcan.experiments.listResultsPaginated('exp-id')) {
400
+ * console.log(result);
401
+ * }
402
+ * ```
403
+ */
404
+ declare class Arcan extends ArcaneClient {
405
+ readonly prompts: PromptsResource;
406
+ readonly datasources: DatasourcesResource;
407
+ readonly traces: TracesResource;
408
+ readonly datasets: DatasetsResource;
409
+ readonly entities: EntitiesResource;
410
+ readonly evaluations: EvaluationsResource;
411
+ readonly experiments: ExperimentsResource;
412
+ constructor(config: ArcaneClientConfig);
413
+ }
414
+
415
+ export { type AddDatasetRowParams, Arcan, ArcanApiError, ArcanNotFoundError, ArcanUnauthorizedError, ArcaneClient, type ArcaneClientConfig, type CombinedExperimentResult, type CreateEvaluationParams, type CreateEvaluationResultParams, type CreateExperimentParams, type CreateExperimentResultParams, type Dataset, type DatasetListItem, type DatasetRow, type DatasourceListItem, type Entity, type Evaluation, type EvaluationResult, type Experiment, type ExperimentResult, type ExperimentScores, type ImportScoreResultRow, type ImportScoreResultsResponse, type ListPendingScoreResultsOptions, type PaginatedDataset, type PaginatedExperimentResults, type PaginatedPendingScoreResults, type PaginationMeta, type PaginationParams, type PendingScoreResult, type Prompt, type PromptVersion, type SearchTracesParams, type TraceResponse, type TraceSearchResponse };