@thinkhive/sdk 3.1.1 → 4.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,169 @@
1
+ /**
2
+ * ThinkHive SDK - Agents Management
3
+ *
4
+ * CRUD operations for managing AI agents:
5
+ * - List, get, create, update, delete agents
6
+ * - Agent configuration management
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { agents } from 'thinkhive-js';
11
+ *
12
+ * // List all agents
13
+ * const allAgents = await agents.list();
14
+ *
15
+ * // Create a new agent
16
+ * const agent = await agents.create({
17
+ * name: 'Support Agent',
18
+ * description: 'Handles customer support',
19
+ * agentType: 'customer_support',
20
+ * primarySuccessMetric: 'Deflection Rate',
21
+ * });
22
+ *
23
+ * // Update an agent
24
+ * await agents.update(agent.id, { name: 'Updated Agent' });
25
+ *
26
+ * // Get agent configuration
27
+ * const config = await agents.getConfig(agent.id);
28
+ *
29
+ * // Delete an agent (with dry-run preview)
30
+ * const impact = await agents.delete(agent.id, { dryRun: true });
31
+ * console.log(`Will delete ${impact.cascadeImpact.traces} traces`);
32
+ *
33
+ * // Actually delete
34
+ * await agents.delete(agent.id);
35
+ * ```
36
+ */
37
+ export interface Agent {
38
+ id: string;
39
+ companyId: string;
40
+ departmentId?: string | null;
41
+ createdBy?: string | null;
42
+ name: string;
43
+ description: string;
44
+ industry: string;
45
+ successMetrics: string[];
46
+ agentType?: string | null;
47
+ agentOwner?: string | null;
48
+ builtInHouse?: boolean | null;
49
+ primarySuccessMetric?: string | null;
50
+ secondaryMetrics?: string[] | null;
51
+ connectedSystem?: string | null;
52
+ telemetryMethod?: string | null;
53
+ autoEvaluate?: boolean | null;
54
+ evaluationSampleRate?: string | null;
55
+ defaultCriteriaIds?: string[] | null;
56
+ defaultGuardrailIds?: string[] | null;
57
+ createdAt?: string | null;
58
+ }
59
+ export interface CreateAgentOptions {
60
+ name: string;
61
+ description?: string;
62
+ industry?: string;
63
+ agentType?: string;
64
+ agentOwner?: string;
65
+ builtInHouse?: boolean;
66
+ departmentId?: string;
67
+ successMetrics?: string[];
68
+ primarySuccessMetric?: string;
69
+ secondaryMetrics?: string[];
70
+ connectedSystem?: string;
71
+ autoEvaluate?: boolean;
72
+ evaluationSampleRate?: number;
73
+ }
74
+ export interface UpdateAgentOptions {
75
+ name?: string;
76
+ description?: string;
77
+ agentType?: string;
78
+ agentOwner?: string;
79
+ builtInHouse?: boolean;
80
+ departmentId?: string | null;
81
+ industry?: string;
82
+ primarySuccessMetric?: string;
83
+ secondaryMetrics?: string[];
84
+ connectedSystem?: string;
85
+ autoEvaluate?: boolean;
86
+ evaluationSampleRate?: number;
87
+ isActive?: boolean;
88
+ }
89
+ export interface AgentConfig {
90
+ id: string;
91
+ agentId: string;
92
+ version: number;
93
+ name: string;
94
+ description?: string | null;
95
+ provider: string;
96
+ model: string;
97
+ temperature?: string | null;
98
+ maxTokens?: number | null;
99
+ systemPrompt?: string | null;
100
+ promptTemplate?: string | null;
101
+ ragEnabled?: boolean | null;
102
+ ragConfig?: unknown;
103
+ toolsEnabled?: boolean | null;
104
+ tools?: unknown;
105
+ isBaseline?: boolean | null;
106
+ isActive?: boolean | null;
107
+ createdAt?: string | null;
108
+ updatedAt?: string | null;
109
+ }
110
+ export interface UpdateAgentConfigOptions {
111
+ name?: string;
112
+ provider?: string;
113
+ model?: string;
114
+ temperature?: number;
115
+ maxTokens?: number;
116
+ systemPrompt?: string;
117
+ promptTemplate?: string;
118
+ ragEnabled?: boolean;
119
+ ragConfig?: Record<string, unknown>;
120
+ toolsEnabled?: boolean;
121
+ tools?: unknown[];
122
+ }
123
+ export interface DeleteAgentOptions {
124
+ /** If true, returns cascade impact without actually deleting */
125
+ dryRun?: boolean;
126
+ }
127
+ export interface CascadeImpact {
128
+ dryRun: boolean;
129
+ agentId: string;
130
+ agentName: string;
131
+ cascadeImpact: {
132
+ traces: number;
133
+ apiKeys: number;
134
+ runningEvaluations?: number;
135
+ };
136
+ }
137
+ export declare const agents: {
138
+ /**
139
+ * List agents for the authenticated company
140
+ */
141
+ list(options?: {
142
+ companyId?: string;
143
+ departmentId?: string;
144
+ }): Promise<Agent[]>;
145
+ /**
146
+ * Get a single agent by ID
147
+ */
148
+ get(id: string): Promise<Agent>;
149
+ /**
150
+ * Create a new agent
151
+ */
152
+ create(options: CreateAgentOptions): Promise<Agent>;
153
+ /**
154
+ * Update an existing agent
155
+ */
156
+ update(id: string, options: UpdateAgentOptions): Promise<Agent>;
157
+ /**
158
+ * Delete an agent. Use dryRun option to preview cascade impact.
159
+ */
160
+ delete(id: string, options?: DeleteAgentOptions): Promise<void | CascadeImpact>;
161
+ /**
162
+ * Get agent configuration (baseline)
163
+ */
164
+ getConfig(agentId: string): Promise<AgentConfig | null>;
165
+ /**
166
+ * Create or update agent configuration
167
+ */
168
+ updateConfig(agentId: string, config: UpdateAgentConfigOptions): Promise<AgentConfig>;
169
+ };
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ /**
3
+ * ThinkHive SDK - Agents Management
4
+ *
5
+ * CRUD operations for managing AI agents:
6
+ * - List, get, create, update, delete agents
7
+ * - Agent configuration management
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { agents } from 'thinkhive-js';
12
+ *
13
+ * // List all agents
14
+ * const allAgents = await agents.list();
15
+ *
16
+ * // Create a new agent
17
+ * const agent = await agents.create({
18
+ * name: 'Support Agent',
19
+ * description: 'Handles customer support',
20
+ * agentType: 'customer_support',
21
+ * primarySuccessMetric: 'Deflection Rate',
22
+ * });
23
+ *
24
+ * // Update an agent
25
+ * await agents.update(agent.id, { name: 'Updated Agent' });
26
+ *
27
+ * // Get agent configuration
28
+ * const config = await agents.getConfig(agent.id);
29
+ *
30
+ * // Delete an agent (with dry-run preview)
31
+ * const impact = await agents.delete(agent.id, { dryRun: true });
32
+ * console.log(`Will delete ${impact.cascadeImpact.traces} traces`);
33
+ *
34
+ * // Actually delete
35
+ * await agents.delete(agent.id);
36
+ * ```
37
+ */
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.agents = void 0;
40
+ const client_1 = require("../core/client");
41
+ // ============================================================================
42
+ // API Client
43
+ // ============================================================================
44
+ exports.agents = {
45
+ /**
46
+ * List agents for the authenticated company
47
+ */
48
+ async list(options) {
49
+ const params = new URLSearchParams();
50
+ if (options?.companyId)
51
+ params.set('companyId', options.companyId);
52
+ if (options?.departmentId)
53
+ params.set('departmentId', options.departmentId);
54
+ const qs = params.toString();
55
+ const response = await (0, client_1.apiRequest)(`/agents${qs ? `?${qs}` : ''}`, { apiVersion: 'none' });
56
+ return response.data ?? response;
57
+ },
58
+ /**
59
+ * Get a single agent by ID
60
+ */
61
+ async get(id) {
62
+ if (!id)
63
+ throw new client_1.ThinkHiveValidationError('Agent ID is required', 'id');
64
+ const response = await (0, client_1.apiRequest)(`/agents/${id}`, { apiVersion: 'none' });
65
+ return response.data ?? response;
66
+ },
67
+ /**
68
+ * Create a new agent
69
+ */
70
+ async create(options) {
71
+ if (!options.name) {
72
+ throw new client_1.ThinkHiveValidationError('Agent name is required', 'name');
73
+ }
74
+ const body = {
75
+ name: options.name,
76
+ description: options.description || '',
77
+ industry: options.industry || 'other',
78
+ successMetrics: options.successMetrics ?? [options.primarySuccessMetric || 'Task Success Rate'],
79
+ };
80
+ if (options.agentType)
81
+ body.agentType = options.agentType;
82
+ if (options.agentOwner)
83
+ body.agentOwner = options.agentOwner;
84
+ if (options.builtInHouse !== undefined)
85
+ body.builtInHouse = options.builtInHouse;
86
+ if (options.departmentId)
87
+ body.departmentId = options.departmentId;
88
+ if (options.primarySuccessMetric)
89
+ body.primarySuccessMetric = options.primarySuccessMetric;
90
+ if (options.secondaryMetrics)
91
+ body.secondaryMetrics = options.secondaryMetrics;
92
+ if (options.connectedSystem)
93
+ body.connectedSystem = options.connectedSystem;
94
+ if (options.autoEvaluate !== undefined)
95
+ body.autoEvaluate = options.autoEvaluate;
96
+ if (options.evaluationSampleRate !== undefined) {
97
+ body.evaluationSampleRate = options.evaluationSampleRate.toFixed(4);
98
+ }
99
+ const response = await (0, client_1.apiRequest)('/agents', {
100
+ method: 'POST',
101
+ body,
102
+ apiVersion: 'none',
103
+ });
104
+ return response.data ?? response;
105
+ },
106
+ /**
107
+ * Update an existing agent
108
+ */
109
+ async update(id, options) {
110
+ if (!id)
111
+ throw new client_1.ThinkHiveValidationError('Agent ID is required', 'id');
112
+ const body = {};
113
+ if (options.name !== undefined)
114
+ body.name = options.name;
115
+ if (options.description !== undefined)
116
+ body.description = options.description;
117
+ if (options.agentType !== undefined)
118
+ body.agentType = options.agentType;
119
+ if (options.agentOwner !== undefined)
120
+ body.agentOwner = options.agentOwner;
121
+ if (options.builtInHouse !== undefined)
122
+ body.builtInHouse = options.builtInHouse;
123
+ if (options.departmentId !== undefined)
124
+ body.departmentId = options.departmentId;
125
+ if (options.industry !== undefined)
126
+ body.industry = options.industry;
127
+ if (options.primarySuccessMetric !== undefined)
128
+ body.primarySuccessMetric = options.primarySuccessMetric;
129
+ if (options.secondaryMetrics !== undefined)
130
+ body.secondaryMetrics = options.secondaryMetrics;
131
+ if (options.connectedSystem !== undefined)
132
+ body.connectedSystem = options.connectedSystem;
133
+ if (options.autoEvaluate !== undefined)
134
+ body.autoEvaluate = options.autoEvaluate;
135
+ if (options.isActive !== undefined)
136
+ body.isActive = options.isActive;
137
+ if (options.evaluationSampleRate !== undefined) {
138
+ body.evaluationSampleRate = options.evaluationSampleRate.toFixed(4);
139
+ }
140
+ const response = await (0, client_1.apiRequest)(`/agents/${id}`, {
141
+ method: 'PATCH',
142
+ body,
143
+ apiVersion: 'none',
144
+ });
145
+ return response.data ?? response;
146
+ },
147
+ /**
148
+ * Delete an agent. Use dryRun option to preview cascade impact.
149
+ */
150
+ async delete(id, options) {
151
+ if (!id)
152
+ throw new client_1.ThinkHiveValidationError('Agent ID is required', 'id');
153
+ const qs = options?.dryRun ? '?dryRun=true' : '';
154
+ const response = await (0, client_1.apiRequest)(`/agents/${id}${qs}`, {
155
+ method: 'DELETE',
156
+ apiVersion: 'none',
157
+ });
158
+ if (options?.dryRun) {
159
+ return response.data ?? response;
160
+ }
161
+ },
162
+ /**
163
+ * Get agent configuration (baseline)
164
+ */
165
+ async getConfig(agentId) {
166
+ if (!agentId)
167
+ throw new client_1.ThinkHiveValidationError('Agent ID is required', 'agentId');
168
+ const response = await (0, client_1.apiRequest)(`/agents/${agentId}/config`, { apiVersion: 'none' });
169
+ return response?.data ?? response ?? null;
170
+ },
171
+ /**
172
+ * Create or update agent configuration
173
+ */
174
+ async updateConfig(agentId, config) {
175
+ if (!agentId)
176
+ throw new client_1.ThinkHiveValidationError('Agent ID is required', 'agentId');
177
+ const response = await (0, client_1.apiRequest)(`/agents/${agentId}/config`, {
178
+ method: 'PUT',
179
+ body: config,
180
+ apiVersion: 'none',
181
+ });
182
+ return response.data ?? response;
183
+ },
184
+ };
185
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdlbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwaS9hZ2VudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1DRzs7O0FBRUgsMkNBQXNFO0FBaUh0RSwrRUFBK0U7QUFDL0UsYUFBYTtBQUNiLCtFQUErRTtBQUVsRSxRQUFBLE1BQU0sR0FBRztJQUNwQjs7T0FFRztJQUNILEtBQUssQ0FBQyxJQUFJLENBQUMsT0FHVjtRQUNDLE1BQU0sTUFBTSxHQUFHLElBQUksZUFBZSxFQUFFLENBQUM7UUFDckMsSUFBSSxPQUFPLEVBQUUsU0FBUztZQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNuRSxJQUFJLE9BQU8sRUFBRSxZQUFZO1lBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBRTVFLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUM3QixNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUEsbUJBQVUsRUFBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUMxRixPQUFRLFFBQWdCLENBQUMsSUFBSSxJQUFJLFFBQVEsQ0FBQztJQUM1QyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQVU7UUFDbEIsSUFBSSxDQUFDLEVBQUU7WUFBRSxNQUFNLElBQUksaUNBQXdCLENBQUMsc0JBQXNCLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDMUUsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFBLG1CQUFVLEVBQUMsV0FBVyxFQUFFLEVBQUUs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QyxPQUFPO1lBQUUsTUFBTSxJQUFJLGlDQUF3QixDQUFDLHNCQUFzQixFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBRXBGLE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBQSxtQkFBVSxFQUFDLFdBQVcsT0FBTyxTQUFTLEVBQUU7WUFDN0QsTUFBTSxFQUFFLEtBQUs7WUFDYixJQUFJLEVBQUUsTUFBTTtZQUNaLFVBQVUsRUFBRSxNQUFNO1NBQ25CLENBQUMsQ0FBQztRQUNILE9BQVEsUUFBZ0IsQ0FBQyxJQUFJLElBQUksUUFBUSxDQUFDO0lBQzVDLENBQUM7Q0FDRixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGlua0hpdmUgU0RLIC0gQWdlbnRzIE1hbmFnZW1lbnRcbiAqXG4gKiBDUlVEIG9wZXJhdGlvbnMgZm9yIG1hbmFnaW5nIEFJIGFnZW50czpcbiAqIC0gTGlzdCwgZ2V0LCBjcmVhdGUsIHVwZGF0ZSwgZGVsZXRlIGFnZW50c1xuICogLSBBZ2VudCBjb25maWd1cmF0aW9uIG1hbmFnZW1lbnRcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgYWdlbnRzIH0gZnJvbSAndGhpbmtoaXZlLWpzJztcbiAqXG4gKiAvLyBMaXN0IGFsbCBhZ2VudHNcbiAqIGNvbnN0IGFsbEFnZW50cyA9IGF3YWl0IGFnZW50cy5saXN0KCk7XG4gKlxuICogLy8gQ3JlYXRlIGEgbmV3IGFnZW50XG4gKiBjb25zdCBhZ2VudCA9IGF3YWl0IGFnZW50cy5jcmVhdGUoe1xuICogICBuYW1lOiAnU3VwcG9ydCBBZ2VudCcsXG4gKiAgIGRlc2NyaXB0aW9uOiAnSGFuZGxlcyBjdXN0b21lciBzdXBwb3J0JyxcbiAqICAgYWdlbnRUeXBlOiAnY3VzdG9tZXJfc3VwcG9ydCcsXG4gKiAgIHByaW1hcnlTdWNjZXNzTWV0cmljOiAnRGVmbGVjdGlvbiBSYXRlJyxcbiAqIH0pO1xuICpcbiAqIC8vIFVwZGF0ZSBhbiBhZ2VudFxuICogYXdhaXQgYWdlbnRzLnVwZGF0ZShhZ2VudC5pZCwgeyBuYW1lOiAnVXBkYXRlZCBBZ2VudCcgfSk7XG4gKlxuICogLy8gR2V0IGFnZW50IGNvbmZpZ3VyYXRpb25cbiAqIGNvbnN0IGNvbmZpZyA9IGF3YWl0IGFnZW50cy5nZXRDb25maWcoYWdlbnQuaWQpO1xuICpcbiAqIC8vIERlbGV0ZSBhbiBhZ2VudCAod2l0aCBkcnktcnVuIHByZXZpZXcpXG4gKiBjb25zdCBpbXBhY3QgPSBhd2FpdCBhZ2VudHMuZGVsZXRlKGFnZW50LmlkLCB7IGRyeVJ1bjogdHJ1ZSB9KTtcbiAqIGNvbnNvbGUubG9nKGBXaWxsIGRlbGV0ZSAke2ltcGFjdC5jYXNjYWRlSW1wYWN0LnRyYWNlc30gdHJhY2VzYCk7XG4gKlxuICogLy8gQWN0dWFsbHkgZGVsZXRlXG4gKiBhd2FpdCBhZ2VudHMuZGVsZXRlKGFnZW50LmlkKTtcbiAqIGBgYFxuICovXG5cbmltcG9ydCB7IGFwaVJlcXVlc3QsIFRoaW5rSGl2ZVZhbGlkYXRpb25FcnJvciB9IGZyb20gJy4uL2NvcmUvY2xpZW50JztcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVHlwZXNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBBZ2VudCB7XG4gIGlkOiBzdHJpbmc7XG4gIGNvbXBhbnlJZDogc3RyaW5nO1xuICBkZXBhcnRtZW50SWQ/OiBzdHJpbmcgfCBudWxsO1xuICBjcmVhdGVkQnk/OiBzdHJpbmcgfCBudWxsO1xuICBuYW1lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIGluZHVzdHJ5OiBzdHJpbmc7XG4gIHN1Y2Nlc3NNZXRyaWNzOiBzdHJpbmdbXTtcbiAgYWdlbnRUeXBlPzogc3RyaW5nIHwgbnVsbDtcbiAgYWdlbnRPd25lcj86IHN0cmluZyB8IG51bGw7XG4gIGJ1aWx0SW5Ib3VzZT86IGJvb2xlYW4gfCBudWxsO1xuICBwcmltYXJ5U3VjY2Vzc01ldHJpYz86IHN0cmluZyB8IG51bGw7XG4gIHNlY29uZGFyeU1ldHJpY3M/OiBzdHJpbmdbXSB8IG51bGw7XG4gIGNvbm5lY3RlZFN5c3RlbT86IHN0cmluZyB8IG51bGw7XG4gIHRlbGVtZXRyeU1ldGhvZD86IHN0cmluZyB8IG51bGw7XG4gIGF1dG9FdmFsdWF0ZT86IGJvb2xlYW4gfCBudWxsO1xuICBldmFsdWF0aW9uU2FtcGxlUmF0ZT86IHN0cmluZyB8IG51bGw7XG4gIGRlZmF1bHRDcml0ZXJpYUlkcz86IHN0cmluZ1tdIHwgbnVsbDtcbiAgZGVmYXVsdEd1YXJkcmFpbElkcz86IHN0cmluZ1tdIHwgbnVsbDtcbiAgY3JlYXRlZEF0Pzogc3RyaW5nIHwgbnVsbDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVBZ2VudE9wdGlvbnMge1xuICBuYW1lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuICBpbmR1c3RyeT86IHN0cmluZztcbiAgYWdlbnRUeXBlPzogc3RyaW5nO1xuICBhZ2VudE93bmVyPzogc3RyaW5nO1xuICBidWlsdEluSG91c2U/OiBib29sZWFuO1xuICBkZXBhcnRtZW50SWQ/OiBzdHJpbmc7XG4gIHN1Y2Nlc3NNZXRyaWNzPzogc3RyaW5nW107XG4gIHByaW1hcnlTdWNjZXNzTWV0cmljPzogc3RyaW5nO1xuICBzZWNvbmRhcnlNZXRyaWNzPzogc3RyaW5nW107XG4gIGNvbm5lY3RlZFN5c3RlbT86IHN0cmluZztcbiAgYXV0b0V2YWx1YXRlPzogYm9vbGVhbjtcbiAgZXZhbHVhdGlvblNhbXBsZVJhdGU/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVXBkYXRlQWdlbnRPcHRpb25zIHtcbiAgbmFtZT86IHN0cmluZztcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIGFnZW50VHlwZT86IHN0cmluZztcbiAgYWdlbnRPd25lcj86IHN0cmluZztcbiAgYnVpbHRJbkhvdXNlPzogYm9vbGVhbjtcbiAgZGVwYXJ0bWVudElkPzogc3RyaW5nIHwgbnVsbDtcbiAgaW5kdXN0cnk/OiBzdHJpbmc7XG4gIHByaW1hcnlTdWNjZXNzTWV0cmljPzogc3RyaW5nO1xuICBzZWNvbmRhcnlNZXRyaWNzPzogc3RyaW5nW107XG4gIGNvbm5lY3RlZFN5c3RlbT86IHN0cmluZztcbiAgYXV0b0V2YWx1YXRlPzogYm9vbGVhbjtcbiAgZXZhbHVhdGlvblNhbXBsZVJhdGU/OiBudW1iZXI7XG4gIGlzQWN0aXZlPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBZ2VudENvbmZpZyB7XG4gIGlkOiBzdHJpbmc7XG4gIGFnZW50SWQ6IHN0cmluZztcbiAgdmVyc2lvbjogbnVtYmVyO1xuICBuYW1lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uPzogc3RyaW5nIHwgbnVsbDtcbiAgcHJvdmlkZXI6IHN0cmluZztcbiAgbW9kZWw6IHN0cmluZztcbiAgdGVtcGVyYXR1cmU/OiBzdHJpbmcgfCBudWxsO1xuICBtYXhUb2tlbnM/OiBudW1iZXIgfCBudWxsO1xuICBzeXN0ZW1Qcm9tcHQ/OiBzdHJpbmcgfCBudWxsO1xuICBwcm9tcHRUZW1wbGF0ZT86IHN0cmluZyB8IG51bGw7XG4gIHJhZ0VuYWJsZWQ/OiBib29sZWFuIHwgbnVsbDtcbiAgcmFnQ29uZmlnPzogdW5rbm93bjtcbiAgdG9vbHNFbmFibGVkPzogYm9vbGVhbiB8IG51bGw7XG4gIHRvb2xzPzogdW5rbm93bjtcbiAgaXNCYXNlbGluZT86IGJvb2xlYW4gfCBudWxsO1xuICBpc0FjdGl2ZT86IGJvb2xlYW4gfCBudWxsO1xuICBjcmVhdGVkQXQ/OiBzdHJpbmcgfCBudWxsO1xuICB1cGRhdGVkQXQ/OiBzdHJpbmcgfCBudWxsO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFVwZGF0ZUFnZW50Q29uZmlnT3B0aW9ucyB7XG4gIG5hbWU/OiBzdHJpbmc7XG4gIHByb3ZpZGVyPzogc3RyaW5nO1xuICBtb2RlbD86IHN0cmluZztcbiAgdGVtcGVyYXR1cmU/OiBudW1iZXI7XG4gIG1heFRva2Vucz86IG51bWJlcjtcbiAgc3lzdGVtUHJvbXB0Pzogc3RyaW5nO1xuICBwcm9tcHRUZW1wbGF0ZT86IHN0cmluZztcbiAgcmFnRW5hYmxlZD86IGJvb2xlYW47XG4gIHJhZ0NvbmZpZz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICB0b29sc0VuYWJsZWQ/OiBib29sZWFuO1xuICB0b29scz86IHVua25vd25bXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEZWxldGVBZ2VudE9wdGlvbnMge1xuICAvKiogSWYgdHJ1ZSwgcmV0dXJucyBjYXNjYWRlIGltcGFjdCB3aXRob3V0IGFjdHVhbGx5IGRlbGV0aW5nICovXG4gIGRyeVJ1bj86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2FzY2FkZUltcGFjdCB7XG4gIGRyeVJ1bjogYm9vbGVhbjtcbiAgYWdlbnRJZDogc3RyaW5nO1xuICBhZ2VudE5hbWU6IHN0cmluZztcbiAgY2FzY2FkZUltcGFjdDoge1xuICAgIHRyYWNlczogbnVtYmVyO1xuICAgIGFwaUtleXM6IG51bWJlcjtcbiAgICBydW5uaW5nRXZhbHVhdGlvbnM/OiBudW1iZXI7XG4gIH07XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEFQSSBDbGllbnRcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGNvbnN0IGFnZW50cyA9IHtcbiAgLyoqXG4gICAqIExpc3QgYWdlbnRzIGZvciB0aGUgYXV0aGVudGljYXRlZCBjb21wYW55XG4gICAqL1xuICBhc3luYyBsaXN0KG9wdGlvbnM/OiB7XG4gICAgY29tcGFueUlkPzogc3RyaW5nO1xuICAgIGRlcGFydG1lbnRJZD86IHN0cmluZztcbiAgfSk6IFByb21pc2U8QWdlbnRbXT4ge1xuICAgIGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoKTtcbiAgICBpZiAob3B0aW9ucz8uY29tcGFueUlkKSBwYXJhbXMuc2V0KCdjb21wYW55SWQnLCBvcHRpb25zLmNvbXBhbnlJZCk7XG4gICAgaWYgKG9wdGlvbnM/LmRlcGFydG1lbnRJZCkgcGFyYW1zLnNldCgnZGVwYXJ0bWVudElkJywgb3B0aW9ucy5kZXBhcnRtZW50SWQpO1xuXG4gICAgY29uc3QgcXMgPSBwYXJhbXMudG9TdHJpbmcoKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGFwaVJlcXVlc3QoYC9hZ2VudHMke3FzID8gYD8ke3FzfWAgOiAnJ31gLCB7IGFwaVZlcnNpb246ICdub25lJyB9KTtcbiAgICByZXR1cm4gKHJlc3BvbnNlIGFzIGFueSkuZGF0YSA/PyByZXNwb25zZTtcbiAgfSxcblxuICAvKipcbiAgICogR2V0IGEgc2luZ2xlIGFnZW50IGJ5IElEXG4gICAqL1xuICBhc3luYyBnZXQoaWQ6IHN0cmluZyk6IFByb21pc2U8QWdlbnQ+IHtcbiAgICBpZiAoIWlkKSB0aHJvdyBuZXcgVGhpbmtIaXZlVmFsaWRhdGlvbkVycm9yKCdBZ2VudCBJRCBpcyByZXF1aXJlZCcsICdpZCcpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXBpUmVxdWVzdChgL2FnZW50cy8ke2lkfWAsIHsgYXBpVmVyc2lvbjogJ25vbmUnIH0pO1xuICAgIHJldHVybiAocmVzcG9uc2UgYXMgYW55KS5kYXRhID8/IHJlc3BvbnNlO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgYWdlbnRcbiAgICovXG4gIGFzeW5jIGNyZWF0ZShvcHRpb25zOiBDcmVhdGVBZ2VudE9wdGlvbnMpOiBQcm9taXNlPEFnZW50PiB7XG4gICAgaWYgKCFvcHRpb25zLm5hbWUpIHtcbiAgICAgIHRocm93IG5ldyBUaGlua0hpdmVWYWxpZGF0aW9uRXJyb3IoJ0FnZW50IG5hbWUgaXMgcmVxdWlyZWQnLCAnbmFtZScpO1xuICAgIH1cblxuICAgIGNvbnN0IGJvZHk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge1xuICAgICAgbmFtZTogb3B0aW9ucy5uYW1lLFxuICAgICAgZGVzY3JpcHRpb246IG9wdGlvbnMuZGVzY3JpcHRpb24gfHwgJycsXG4gICAgICBpbmR1c3RyeTogb3B0aW9ucy5pbmR1c3RyeSB8fCAnb3RoZXInLFxuICAgICAgc3VjY2Vzc01ldHJpY3M6IG9wdGlvbnMuc3VjY2Vzc01ldHJpY3MgPz8gW29wdGlvbnMucHJpbWFyeVN1Y2Nlc3NNZXRyaWMgfHwgJ1Rhc2sgU3VjY2VzcyBSYXRlJ10sXG4gICAgfTtcblxuICAgIGlmIChvcHRpb25zLmFnZW50VHlwZSkgYm9keS5hZ2VudFR5cGUgPSBvcHRpb25zLmFnZW50VHlwZTtcbiAgICBpZiAob3B0aW9ucy5hZ2VudE93bmVyKSBib2R5LmFnZW50T3duZXIgPSBvcHRpb25zLmFnZW50T3duZXI7XG4gICAgaWYgKG9wdGlvbnMuYnVpbHRJbkhvdXNlICE9PSB1bmRlZmluZWQpIGJvZHkuYnVpbHRJbkhvdXNlID0gb3B0aW9ucy5idWlsdEluSG91c2U7XG4gICAgaWYgKG9wdGlvbnMuZGVwYXJ0bWVudElkKSBib2R5LmRlcGFydG1lbnRJZCA9IG9wdGlvbnMuZGVwYXJ0bWVudElkO1xuICAgIGlmIChvcHRpb25zLnByaW1hcnlTdWNjZXNzTWV0cmljKSBib2R5LnByaW1hcnlTdWNjZXNzTWV0cmljID0gb3B0aW9ucy5wcmltYXJ5U3VjY2Vzc01ldHJpYztcbiAgICBpZiAob3B0aW9ucy5zZWNvbmRhcnlNZXRyaWNzKSBib2R5LnNlY29uZGFyeU1ldHJpY3MgPSBvcHRpb25zLnNlY29uZGFyeU1ldHJpY3M7XG4gICAgaWYgKG9wdGlvbnMuY29ubmVjdGVkU3lzdGVtKSBib2R5LmNvbm5lY3RlZFN5c3RlbSA9IG9wdGlvbnMuY29ubmVjdGVkU3lzdGVtO1xuICAgIGlmIChvcHRpb25zLmF1dG9FdmFsdWF0ZSAhPT0gdW5kZWZpbmVkKSBib2R5LmF1dG9FdmFsdWF0ZSA9IG9wdGlvbnMuYXV0b0V2YWx1YXRlO1xuICAgIGlmIChvcHRpb25zLmV2YWx1YXRpb25TYW1wbGVSYXRlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGJvZHkuZXZhbHVhdGlvblNhbXBsZVJhdGUgPSBvcHRpb25zLmV2YWx1YXRpb25TYW1wbGVSYXRlLnRvRml4ZWQoNCk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBhcGlSZXF1ZXN0KCcvYWdlbnRzJywge1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBib2R5LFxuICAgICAgYXBpVmVyc2lvbjogJ25vbmUnLFxuICAgIH0pO1xuICAgIHJldHVybiAocmVzcG9uc2UgYXMgYW55KS5kYXRhID8/IHJlc3BvbnNlO1xuICB9LFxuXG4gIC8qKlxuICAgKiBVcGRhdGUgYW4gZXhpc3RpbmcgYWdlbnRcbiAgICovXG4gIGFzeW5jIHVwZGF0ZShpZDogc3RyaW5nLCBvcHRpb25zOiBVcGRhdGVBZ2VudE9wdGlvbnMpOiBQcm9taXNlPEFnZW50PiB7XG4gICAgaWYgKCFpZCkgdGhyb3cgbmV3IFRoaW5rSGl2ZVZhbGlkYXRpb25FcnJvcignQWdlbnQgSUQgaXMgcmVxdWlyZWQnLCAnaWQnKTtcblxuICAgIGNvbnN0IGJvZHk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XG4gICAgaWYgKG9wdGlvbnMubmFtZSAhPT0gdW5kZWZpbmVkKSBib2R5Lm5hbWUgPSBvcHRpb25zLm5hbWU7XG4gICAgaWYgKG9wdGlvbnMuZGVzY3JpcHRpb24gIT09IHVuZGVmaW5lZCkgYm9keS5kZXNjcmlwdGlvbiA9IG9wdGlvbnMuZGVzY3JpcHRpb247XG4gICAgaWYgKG9wdGlvbnMuYWdlbnRUeXBlICE9PSB1bmRlZmluZWQpIGJvZHkuYWdlbnRUeXBlID0gb3B0aW9ucy5hZ2VudFR5cGU7XG4gICAgaWYgKG9wdGlvbnMuYWdlbnRPd25lciAhPT0gdW5kZWZpbmVkKSBib2R5LmFnZW50T3duZXIgPSBvcHRpb25zLmFnZW50T3duZXI7XG4gICAgaWYgKG9wdGlvbnMuYnVpbHRJbkhvdXNlICE9PSB1bmRlZmluZWQpIGJvZHkuYnVpbHRJbkhvdXNlID0gb3B0aW9ucy5idWlsdEluSG91c2U7XG4gICAgaWYgKG9wdGlvbnMuZGVwYXJ0bWVudElkICE9PSB1bmRlZmluZWQpIGJvZHkuZGVwYXJ0bWVudElkID0gb3B0aW9ucy5kZXBhcnRtZW50SWQ7XG4gICAgaWYgKG9wdGlvbnMuaW5kdXN0cnkgIT09IHVuZGVmaW5lZCkgYm9keS5pbmR1c3RyeSA9IG9wdGlvbnMuaW5kdXN0cnk7XG4gICAgaWYgKG9wdGlvbnMucHJpbWFyeVN1Y2Nlc3NNZXRyaWMgIT09IHVuZGVmaW5lZCkgYm9keS5wcmltYXJ5U3VjY2Vzc01ldHJpYyA9IG9wdGlvbnMucHJpbWFyeVN1Y2Nlc3NNZXRyaWM7XG4gICAgaWYgKG9wdGlvbnMuc2Vjb25kYXJ5TWV0cmljcyAhPT0gdW5kZWZpbmVkKSBib2R5LnNlY29uZGFyeU1ldHJpY3MgPSBvcHRpb25zLnNlY29uZGFyeU1ldHJpY3M7XG4gICAgaWYgKG9wdGlvbnMuY29ubmVjdGVkU3lzdGVtICE9PSB1bmRlZmluZWQpIGJvZHkuY29ubmVjdGVkU3lzdGVtID0gb3B0aW9ucy5jb25uZWN0ZWRTeXN0ZW07XG4gICAgaWYgKG9wdGlvbnMuYXV0b0V2YWx1YXRlICE9PSB1bmRlZmluZWQpIGJvZHkuYXV0b0V2YWx1YXRlID0gb3B0aW9ucy5hdXRvRXZhbHVhdGU7XG4gICAgaWYgKG9wdGlvbnMuaXNBY3RpdmUgIT09IHVuZGVmaW5lZCkgYm9keS5pc0FjdGl2ZSA9IG9wdGlvbnMuaXNBY3RpdmU7XG4gICAgaWYgKG9wdGlvbnMuZXZhbHVhdGlvblNhbXBsZVJhdGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgYm9keS5ldmFsdWF0aW9uU2FtcGxlUmF0ZSA9IG9wdGlvbnMuZXZhbHVhdGlvblNhbXBsZVJhdGUudG9GaXhlZCg0KTtcbiAgICB9XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGFwaVJlcXVlc3QoYC9hZ2VudHMvJHtpZH1gLCB7XG4gICAgICBtZXRob2Q6ICdQQVRDSCcsXG4gICAgICBib2R5LFxuICAgICAgYXBpVmVyc2lvbjogJ25vbmUnLFxuICAgIH0pO1xuICAgIHJldHVybiAocmVzcG9uc2UgYXMgYW55KS5kYXRhID8/IHJlc3BvbnNlO1xuICB9LFxuXG4gIC8qKlxuICAgKiBEZWxldGUgYW4gYWdlbnQuIFVzZSBkcnlSdW4gb3B0aW9uIHRvIHByZXZpZXcgY2FzY2FkZSBpbXBhY3QuXG4gICAqL1xuICBhc3luYyBkZWxldGUoaWQ6IHN0cmluZywgb3B0aW9ucz86IERlbGV0ZUFnZW50T3B0aW9ucyk6IFByb21pc2U8dm9pZCB8IENhc2NhZGVJbXBhY3Q+IHtcbiAgICBpZiAoIWlkKSB0aHJvdyBuZXcgVGhpbmtIaXZlVmFsaWRhdGlvbkVycm9yKCdBZ2VudCBJRCBpcyByZXF1aXJlZCcsICdpZCcpO1xuXG4gICAgY29uc3QgcXMgPSBvcHRpb25zPy5kcnlSdW4gPyAnP2RyeVJ1bj10cnVlJyA6ICcnO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXBpUmVxdWVzdChgL2FnZW50cy8ke2lkfSR7cXN9YCwge1xuICAgICAgbWV0aG9kOiAnREVMRVRFJyxcbiAgICAgIGFwaVZlcnNpb246ICdub25lJyxcbiAgICB9KTtcblxuICAgIGlmIChvcHRpb25zPy5kcnlSdW4pIHtcbiAgICAgIHJldHVybiAocmVzcG9uc2UgYXMgYW55KS5kYXRhID8/IHJlc3BvbnNlO1xuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogR2V0IGFnZW50IGNvbmZpZ3VyYXRpb24gKGJhc2VsaW5lKVxuICAgKi9cbiAgYXN5bmMgZ2V0Q29uZmlnKGFnZW50SWQ6IHN0cmluZyk6IFByb21pc2U8QWdlbnRDb25maWcgfCBudWxsPiB7XG4gICAgaWYgKCFhZ2VudElkKSB0aHJvdyBuZXcgVGhpbmtIaXZlVmFsaWRhdGlvbkVycm9yKCdBZ2VudCBJRCBpcyByZXF1aXJlZCcsICdhZ2VudElkJyk7XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGFwaVJlcXVlc3QoYC9hZ2VudHMvJHthZ2VudElkfS9jb25maWdgLCB7IGFwaVZlcnNpb246ICdub25lJyB9KTtcbiAgICByZXR1cm4gKHJlc3BvbnNlIGFzIGFueSk/LmRhdGEgPz8gcmVzcG9uc2UgPz8gbnVsbDtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYXRlIG9yIHVwZGF0ZSBhZ2VudCBjb25maWd1cmF0aW9uXG4gICAqL1xuICBhc3luYyB1cGRhdGVDb25maWcoYWdlbnRJZDogc3RyaW5nLCBjb25maWc6IFVwZGF0ZUFnZW50Q29uZmlnT3B0aW9ucyk6IFByb21pc2U8QWdlbnRDb25maWc+IHtcbiAgICBpZiAoIWFnZW50SWQpIHRocm93IG5ldyBUaGlua0hpdmVWYWxpZGF0aW9uRXJyb3IoJ0FnZW50IElEIGlzIHJlcXVpcmVkJywgJ2FnZW50SWQnKTtcblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXBpUmVxdWVzdChgL2FnZW50cy8ke2FnZW50SWR9L2NvbmZpZ2AsIHtcbiAgICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgICBib2R5OiBjb25maWcsXG4gICAgICBhcGlWZXJzaW9uOiAnbm9uZScsXG4gICAgfSk7XG4gICAgcmV0dXJuIChyZXNwb25zZSBhcyBhbnkpLmRhdGEgPz8gcmVzcG9uc2U7XG4gIH0sXG59O1xuIl19
@@ -0,0 +1,252 @@
1
+ /**
2
+ * ThinkHive SDK - API Keys Management
3
+ *
4
+ * Create and manage scoped API keys with:
5
+ * - Permission control (read/write/delete)
6
+ * - Agent-level scoping (allowedAgentIds)
7
+ * - Environment separation (production/staging/development)
8
+ * - IP whitelisting (allowedIps)
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { apiKeys } from 'thinkhive-js';
13
+ *
14
+ * // Create a read-only key for monitoring
15
+ * const readOnlyKey = await apiKeys.create({
16
+ * name: 'Monitoring Key',
17
+ * scopeType: 'readonly'
18
+ * });
19
+ *
20
+ * // Create a key scoped to specific agents
21
+ * const agentKey = await apiKeys.create({
22
+ * name: 'Agent A Key',
23
+ * allowedAgentIds: ['agent-a-id', 'agent-b-id'],
24
+ * permissions: { read: true, write: true, delete: false }
25
+ * });
26
+ *
27
+ * // Create a staging environment key
28
+ * const stagingKey = await apiKeys.create({
29
+ * name: 'Staging Key',
30
+ * environment: 'staging',
31
+ * allowedIps: ['10.0.0.1', '10.0.0.2']
32
+ * });
33
+ * ```
34
+ */
35
+ /**
36
+ * API key permission configuration
37
+ */
38
+ export interface ApiKeyPermissions {
39
+ /** Allow read operations (GET requests, listing, etc.) */
40
+ read: boolean;
41
+ /** Allow write operations (POST, PUT requests) */
42
+ write: boolean;
43
+ /** Allow delete operations (DELETE requests) */
44
+ delete: boolean;
45
+ }
46
+ /**
47
+ * API key scope type
48
+ * - `company`: Full access to all company data
49
+ * - `agent`: Limited to specific agents (requires allowedAgentIds)
50
+ * - `readonly`: Read-only access regardless of other settings
51
+ */
52
+ export type ScopeType = 'company' | 'agent' | 'readonly';
53
+ /**
54
+ * API key environment
55
+ * - `production`: For production systems
56
+ * - `staging`: For staging/pre-production
57
+ * - `development`: For local development
58
+ */
59
+ export type Environment = 'production' | 'staging' | 'development';
60
+ /**
61
+ * Options for creating an API key
62
+ */
63
+ export interface CreateApiKeyOptions {
64
+ /** Display name for the key */
65
+ name: string;
66
+ /** Permission configuration (defaults to read+write) */
67
+ permissions?: Partial<ApiKeyPermissions>;
68
+ /**
69
+ * Restrict key to specific agent IDs
70
+ * When set, key can only access traces for these agents
71
+ */
72
+ allowedAgentIds?: string[];
73
+ /**
74
+ * Scope type for the key
75
+ * @default 'company' or 'agent' if allowedAgentIds is set
76
+ */
77
+ scopeType?: ScopeType;
78
+ /**
79
+ * Environment for the key
80
+ * @default 'production'
81
+ */
82
+ environment?: Environment;
83
+ /**
84
+ * Restrict key to specific IP addresses
85
+ * When set, only requests from these IPs can use this key
86
+ */
87
+ allowedIps?: string[];
88
+ /** Expiration date for the key */
89
+ expiresAt?: Date;
90
+ }
91
+ /**
92
+ * API key metadata (returned from server)
93
+ */
94
+ export interface ApiKey {
95
+ /** Unique key ID */
96
+ id: string;
97
+ /** Display name */
98
+ name: string;
99
+ /** Key prefix (first 8 chars for identification) */
100
+ keyPrefix: string;
101
+ /** Permission configuration */
102
+ permissions: ApiKeyPermissions | string[];
103
+ /** Scope type */
104
+ scopeType: ScopeType;
105
+ /** Environment */
106
+ environment: Environment;
107
+ /** Allowed agent IDs (null = all agents) */
108
+ allowedAgentIds: string[] | null;
109
+ /** Allowed IP addresses (null = all IPs) */
110
+ allowedIps: string[] | null;
111
+ /** Whether key is active */
112
+ isActive: boolean;
113
+ /** Last usage timestamp */
114
+ lastUsedAt: string | null;
115
+ /** Total usage count */
116
+ usageCount: number;
117
+ /** Expiration date */
118
+ expiresAt: string | null;
119
+ /** Creation timestamp */
120
+ createdAt: string;
121
+ }
122
+ /**
123
+ * Result of creating an API key (includes secret)
124
+ */
125
+ export interface CreateApiKeyResult extends ApiKey {
126
+ /**
127
+ * The full API key value
128
+ * IMPORTANT: This is only returned once and cannot be retrieved later!
129
+ * Store it securely.
130
+ */
131
+ key: string;
132
+ }
133
+ /**
134
+ * Create a new API key with specified permissions and scoping
135
+ *
136
+ * @param options - API key configuration
137
+ * @returns Created key with secret (only returned once!)
138
+ *
139
+ * @example
140
+ * ```typescript
141
+ * // Create a production write key
142
+ * const result = await apiKeys.create({
143
+ * name: 'Production SDK Key',
144
+ * permissions: { read: true, write: true, delete: false }
145
+ * });
146
+ *
147
+ * // Save the key securely - it won't be shown again!
148
+ * console.log('Save this key:', result.key);
149
+ * ```
150
+ */
151
+ export declare function create(options: CreateApiKeyOptions): Promise<CreateApiKeyResult>;
152
+ /**
153
+ * List all API keys for the authenticated company
154
+ *
155
+ * @returns Array of API keys (without secrets)
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * const keys = await apiKeys.list();
160
+ * console.log(`Found ${keys.length} API keys`);
161
+ *
162
+ * // Filter by environment
163
+ * const prodKeys = keys.filter(k => k.environment === 'production');
164
+ * ```
165
+ */
166
+ export declare function list(): Promise<ApiKey[]>;
167
+ /**
168
+ * Revoke (deactivate) an API key
169
+ *
170
+ * @param keyId - ID of the key to revoke
171
+ *
172
+ * @example
173
+ * ```typescript
174
+ * // Revoke a compromised key
175
+ * await apiKeys.revoke('key-id-to-revoke');
176
+ * ```
177
+ */
178
+ export declare function revoke(keyId: string): Promise<void>;
179
+ /**
180
+ * Rotate an API key (revoke old, create new with same config)
181
+ *
182
+ * @param keyId - ID of the key to rotate
183
+ * @param options - Optional overrides for the new key
184
+ * @returns New key with secret
185
+ *
186
+ * @example
187
+ * ```typescript
188
+ * // Rotate a key periodically
189
+ * const existingKeys = await apiKeys.list();
190
+ * const oldKey = existingKeys.find(k => k.name === 'Production Key');
191
+ *
192
+ * if (oldKey) {
193
+ * const newKey = await apiKeys.rotate(oldKey.id);
194
+ * // Update your systems with newKey.key
195
+ * console.log('New key:', newKey.key);
196
+ * }
197
+ * ```
198
+ */
199
+ export declare function rotate(keyId: string, options?: Partial<CreateApiKeyOptions>): Promise<CreateApiKeyResult>;
200
+ /**
201
+ * Test an API key connection
202
+ *
203
+ * @param apiKey - The full API key value to test
204
+ * @param agentId - Optional agent ID to test with
205
+ * @returns Test result
206
+ *
207
+ * @example
208
+ * ```typescript
209
+ * const result = await apiKeys.test('thk_...', 'my-agent-id');
210
+ * if (result.success) {
211
+ * console.log('Key is valid!');
212
+ * }
213
+ * ```
214
+ */
215
+ export declare function test(apiKey: string, agentId?: string): Promise<{
216
+ success: boolean;
217
+ error?: string;
218
+ testTraceId?: string;
219
+ }>;
220
+ /**
221
+ * Check if an API key has a specific permission
222
+ */
223
+ export declare function hasPermission(key: ApiKey, permission: 'read' | 'write' | 'delete'): boolean;
224
+ /**
225
+ * Check if an API key is expired
226
+ */
227
+ export declare function isExpired(key: ApiKey): boolean;
228
+ /**
229
+ * Check if an API key is valid (active and not expired)
230
+ */
231
+ export declare function isValid(key: ApiKey): boolean;
232
+ /**
233
+ * Get time until key expires (in milliseconds)
234
+ * Returns null if key doesn't expire
235
+ */
236
+ export declare function getTimeUntilExpiry(key: ApiKey): number | null;
237
+ /**
238
+ * Check if a key can access a specific agent
239
+ */
240
+ export declare function canAccessAgent(key: ApiKey, agentId: string): boolean;
241
+ export declare const apiKeys: {
242
+ create: typeof create;
243
+ list: typeof list;
244
+ revoke: typeof revoke;
245
+ rotate: typeof rotate;
246
+ test: typeof test;
247
+ hasPermission: typeof hasPermission;
248
+ isExpired: typeof isExpired;
249
+ isValid: typeof isValid;
250
+ getTimeUntilExpiry: typeof getTimeUntilExpiry;
251
+ canAccessAgent: typeof canAccessAgent;
252
+ };