@butlerbot/sdk 0.0.6 → 0.0.7-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.d.ts +7 -0
- package/dist/config.js +5 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +6 -0
- package/dist/modules/conversation.d.ts +0 -1
- package/dist/modules/conversation.js +3 -18
- package/dist/modules/usage.d.ts +9 -0
- package/dist/modules/usage.js +31 -0
- package/dist/types/conversation/v3/conversation_v3.d.ts +3 -28
- package/dist/types/usage/policy.d.ts +45 -0
- package/dist/types/usage/policy.js +2 -0
- package/dist/util/url_formatter.d.ts +4 -0
- package/dist/util/url_formatter.js +18 -0
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
package/dist/config.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Conversation, ConversationOptions } from "./modules/conversation";
|
|
2
|
+
import { UsagePolicyDataOptions } from "./modules/usage";
|
|
2
3
|
type OptionalApiKey<T> = Omit<T, "apiKey"> & {
|
|
3
4
|
/** Optional API key, defaults to API key specified in client */
|
|
4
5
|
apiKey?: string;
|
|
@@ -20,6 +21,8 @@ export declare class ButlerBotClient {
|
|
|
20
21
|
healthCheck(healthCheckPath?: string): Promise<boolean>;
|
|
21
22
|
/** Spawns a new Conversation, inherits api key and server URL */
|
|
22
23
|
createConversation(config?: OptionalApiKey<ConversationOptions>): Conversation;
|
|
24
|
+
/** Get current usage policy data */
|
|
25
|
+
getUsagePolicyData(config: OptionalApiKey<UsagePolicyDataOptions>): Promise<import("./types/usage/policy").UsagePolicyData>;
|
|
23
26
|
}
|
|
24
|
-
export { Conversation, ConversationOptions };
|
|
25
27
|
export * from "./types/type_registry";
|
|
28
|
+
export { Conversation, ConversationOptions };
|
package/dist/index.js
CHANGED
|
@@ -27,6 +27,7 @@ exports.Conversation = exports.ButlerBotClient = void 0;
|
|
|
27
27
|
const config_1 = require("./config");
|
|
28
28
|
const conversation_1 = require("./modules/conversation");
|
|
29
29
|
Object.defineProperty(exports, "Conversation", { enumerable: true, get: function () { return conversation_1.Conversation; } });
|
|
30
|
+
const usage_1 = require("./modules/usage");
|
|
30
31
|
class ButlerBotClient {
|
|
31
32
|
constructor(config) {
|
|
32
33
|
this.apiKey = config.apiKey;
|
|
@@ -52,6 +53,11 @@ class ButlerBotClient {
|
|
|
52
53
|
createConversation(config = {}) {
|
|
53
54
|
return new conversation_1.Conversation(Object.assign({ debug: this.debug, apiKey: this.apiKey, serverUrl: this.serverUrl }, config));
|
|
54
55
|
}
|
|
56
|
+
/** Get current usage policy data */
|
|
57
|
+
getUsagePolicyData(config) {
|
|
58
|
+
return (0, usage_1.getUsagePolicyData)(Object.assign({ serverURL: this.serverUrl, apiKey: this.apiKey, debug: this.debug }, config));
|
|
59
|
+
}
|
|
55
60
|
}
|
|
56
61
|
exports.ButlerBotClient = ButlerBotClient;
|
|
62
|
+
// Expose types from subsequent modules
|
|
57
63
|
__exportStar(require("./types/type_registry"), exports);
|
|
@@ -84,7 +84,6 @@ export declare class Conversation {
|
|
|
84
84
|
getPlatform(): string | undefined;
|
|
85
85
|
/** Gets the current personality configuration */
|
|
86
86
|
getPersonality(): string | undefined;
|
|
87
|
-
formatURL(url: string, params?: Object): string;
|
|
88
87
|
/** Fetches the conversation state from the server, including message history and metadata */
|
|
89
88
|
fetchState(): Promise<ConversationStateResponse>;
|
|
90
89
|
/** Sends a message into the conversation */
|
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.Conversation = void 0;
|
|
13
13
|
const eventsource_1 = require("eventsource");
|
|
14
14
|
const config_1 = require("../config");
|
|
15
|
+
const url_formatter_1 = require("../util/url_formatter");
|
|
15
16
|
const DEFAULT_CONVO_API_V = "v3";
|
|
16
17
|
class Conversation {
|
|
17
18
|
constructor(config) {
|
|
@@ -108,29 +109,13 @@ class Conversation {
|
|
|
108
109
|
var _a;
|
|
109
110
|
return (_a = this.options) === null || _a === void 0 ? void 0 : _a.personality;
|
|
110
111
|
}
|
|
111
|
-
// HELPERS
|
|
112
|
-
formatURL(url, params = {}) {
|
|
113
|
-
const fParams = Object.assign({ api_key: this.apiKey }, params);
|
|
114
|
-
const paramQuery = new URLSearchParams(fParams).toString();
|
|
115
|
-
const fUrl = `${url}?${paramQuery}`;
|
|
116
|
-
if (this.debug) {
|
|
117
|
-
const debugUrl = new URL(fUrl);
|
|
118
|
-
const apiKey = debugUrl.searchParams.get('api_key');
|
|
119
|
-
if (apiKey) {
|
|
120
|
-
const obscuredKey = apiKey.length > 6 ? `${apiKey.slice(0, 3)}...${apiKey.slice(-3)}` : '***';
|
|
121
|
-
debugUrl.searchParams.set('api_key', obscuredKey);
|
|
122
|
-
}
|
|
123
|
-
console.log(`[Formatting URL ${debugUrl.toString()}]`);
|
|
124
|
-
}
|
|
125
|
-
return fUrl;
|
|
126
|
-
}
|
|
127
112
|
// GETTERS
|
|
128
113
|
/** Fetches the conversation state from the server, including message history and metadata */
|
|
129
114
|
fetchState() {
|
|
130
115
|
return __awaiter(this, void 0, void 0, function* () {
|
|
131
116
|
if (!this.convoId)
|
|
132
117
|
throw new Error("Conversation ID is not set");
|
|
133
|
-
const url =
|
|
118
|
+
const url = (0, url_formatter_1.formatURL)(`${this.endpoints.history}/${this.convoId}`, undefined, { apiKey: this.apiKey, debug: this.debug });
|
|
134
119
|
const response = yield fetch(url);
|
|
135
120
|
if (!response.ok) {
|
|
136
121
|
const errorText = yield response.text();
|
|
@@ -148,7 +133,7 @@ class Conversation {
|
|
|
148
133
|
);
|
|
149
134
|
if (this.convoId)
|
|
150
135
|
payload.chatId = this.convoId;
|
|
151
|
-
const url =
|
|
136
|
+
const url = (0, url_formatter_1.formatURL)(this.endpoints.conversation, payload, { apiKey: this.apiKey, debug: this.debug });
|
|
152
137
|
const sse = new eventsource_1.EventSource(url);
|
|
153
138
|
sse.addEventListener("message", (event) => {
|
|
154
139
|
const data = JSON.parse(event.data);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { UsagePolicyData } from "../types/usage/policy";
|
|
2
|
+
export type UsagePolicyDataOptions = {
|
|
3
|
+
serverURL?: string;
|
|
4
|
+
path?: string;
|
|
5
|
+
apiKey: string;
|
|
6
|
+
debug?: boolean;
|
|
7
|
+
};
|
|
8
|
+
/** Fetches the current usage policy data from the server */
|
|
9
|
+
export declare function getUsagePolicyData(options: UsagePolicyDataOptions): Promise<UsagePolicyData>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getUsagePolicyData = getUsagePolicyData;
|
|
13
|
+
const config_1 = require("../config");
|
|
14
|
+
const url_formatter_1 = require("../util/url_formatter");
|
|
15
|
+
/** Fetches the current usage policy data from the server */
|
|
16
|
+
function getUsagePolicyData(options) {
|
|
17
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
const useEndpoint = (options.serverURL || config_1.CONFIG.server) + (options.path || config_1.CONFIG.paths.usage.policy.v3.base);
|
|
19
|
+
const url = (0, url_formatter_1.formatURL)(useEndpoint, {}, { apiKey: options.apiKey, debug: options.debug });
|
|
20
|
+
const response = yield fetch(url);
|
|
21
|
+
const data = yield response.json();
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
const errorText = yield response.text();
|
|
24
|
+
throw new Error(`Failed to fetch usage policy data: ${response.status} ${response.statusText} - ${errorText}`);
|
|
25
|
+
}
|
|
26
|
+
if (!data.success) {
|
|
27
|
+
throw new Error(`API error while fetching usage policy data: ${data.error || 'Unknown error'}`);
|
|
28
|
+
}
|
|
29
|
+
return data;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
@@ -131,40 +131,15 @@ export type ResponseMetadata = {
|
|
|
131
131
|
};
|
|
132
132
|
/** Token usage breakdown */
|
|
133
133
|
tokens: TokenUsage;
|
|
134
|
-
/** The cost
|
|
134
|
+
/** The cost of the current turn */
|
|
135
135
|
cost: {
|
|
136
|
-
/** The cost of the current turn */
|
|
137
136
|
turnCost?: ModelMessageCost;
|
|
138
|
-
/** The current user's usage cost */
|
|
139
|
-
dailyUsageCost: number;
|
|
140
|
-
/** The user's cost limit for the conversation (e.g., daily limit) */
|
|
141
|
-
dailyUsageCostLimit: number;
|
|
142
|
-
};
|
|
143
|
-
/** Usage budget info */
|
|
144
|
-
limit: {
|
|
145
|
-
/** Current usage cost as a percentage of daily limit (0–1) */
|
|
146
|
-
percentage: number;
|
|
147
|
-
/** Human-readable percentage (e.g. "42.3%") */
|
|
148
|
-
percentageDisplay: string;
|
|
149
|
-
/** Name of the active usage stage */
|
|
150
|
-
stageName: string;
|
|
151
|
-
};
|
|
152
|
-
/** Model switching info (tiered auto-downgrade) */
|
|
153
|
-
modelSwitching: {
|
|
154
|
-
/** Whether the model was switched from the user's request */
|
|
155
|
-
switched: boolean;
|
|
156
|
-
/** Originally requested model */
|
|
157
|
-
requestedModel: string;
|
|
158
|
-
/** Model that was actually used */
|
|
159
|
-
activeModel: string;
|
|
160
|
-
/** Usage stage that triggered the switch */
|
|
161
|
-
stage?: string;
|
|
162
137
|
};
|
|
163
138
|
/** Response timing */
|
|
164
139
|
timing: {
|
|
165
|
-
/** Milliseconds from
|
|
140
|
+
/** Milliseconds from turn start to first streamed event */
|
|
166
141
|
firstEventMs: number;
|
|
167
|
-
/** Total
|
|
142
|
+
/** Total turn time in milliseconds */
|
|
168
143
|
totalMs: number;
|
|
169
144
|
};
|
|
170
145
|
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { AI_MODEL } from "../model";
|
|
2
|
+
export type PolicyRule = {
|
|
3
|
+
/** When the current usage exceeds this threshold */
|
|
4
|
+
whenUsageAbove: {
|
|
5
|
+
type: "percentage";
|
|
6
|
+
value: number;
|
|
7
|
+
};
|
|
8
|
+
/** When the current chosen model is equal to this model */
|
|
9
|
+
whenModelEquals?: {
|
|
10
|
+
value: AI_MODEL;
|
|
11
|
+
};
|
|
12
|
+
/** The model to overwrite the convos as, 'null' means no overwrite - use user's choice */
|
|
13
|
+
model: AI_MODEL | null;
|
|
14
|
+
/** When this rule is activated, this message will be sent to the user */
|
|
15
|
+
switchMessage?: string;
|
|
16
|
+
/** The message appended on the end of every message sent giving additional info */
|
|
17
|
+
appendMessage?: string;
|
|
18
|
+
};
|
|
19
|
+
export type UsagePolicy = {
|
|
20
|
+
rules: PolicyRule[];
|
|
21
|
+
maxConvoLength?: number;
|
|
22
|
+
};
|
|
23
|
+
export type UsagePolicyData = {
|
|
24
|
+
limit: {
|
|
25
|
+
/** Current usage cost as a percentage of daily limit (0–1) */
|
|
26
|
+
percentage: number;
|
|
27
|
+
};
|
|
28
|
+
/** Model switching info (tiered auto-downgrade) */
|
|
29
|
+
modelSwitching: {
|
|
30
|
+
/** Whether the model was switched from the user's request */
|
|
31
|
+
switched: boolean;
|
|
32
|
+
/** Originally requested model */
|
|
33
|
+
requestedModel?: string;
|
|
34
|
+
/** Model that was actually used */
|
|
35
|
+
activeModel?: string;
|
|
36
|
+
};
|
|
37
|
+
/** Usage policy information */
|
|
38
|
+
usagePolicy: UsagePolicy;
|
|
39
|
+
daily: {
|
|
40
|
+
/** The current user's usage cost */
|
|
41
|
+
dailyUsageCost: number;
|
|
42
|
+
/** The user's cost limit for the conversation (e.g., daily limit) */
|
|
43
|
+
dailyUsageCostLimit: number;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatURL = formatURL;
|
|
4
|
+
function formatURL(url, params = {}, config) {
|
|
5
|
+
const fParams = Object.assign({ api_key: config.apiKey }, params);
|
|
6
|
+
const paramQuery = new URLSearchParams(fParams).toString();
|
|
7
|
+
const fUrl = `${url}?${paramQuery}`;
|
|
8
|
+
if (config.debug) {
|
|
9
|
+
const debugUrl = new URL(fUrl);
|
|
10
|
+
const apiKey = debugUrl.searchParams.get('api_key');
|
|
11
|
+
if (apiKey) {
|
|
12
|
+
const obscuredKey = apiKey.length > 6 ? `${apiKey.slice(0, 3)}...${apiKey.slice(-3)}` : '***';
|
|
13
|
+
debugUrl.searchParams.set('api_key', obscuredKey);
|
|
14
|
+
}
|
|
15
|
+
console.log(`[Formatting URL ${debugUrl.toString()}]`);
|
|
16
|
+
}
|
|
17
|
+
return fUrl;
|
|
18
|
+
}
|