@bankr/cli 0.1.0-beta.6 → 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/README.md +27 -1
- package/dist/cli.js +222 -4
- package/dist/commands/balances.d.ts +5 -0
- package/dist/commands/balances.js +113 -0
- package/dist/commands/fees.d.ts +18 -0
- package/dist/commands/fees.js +793 -0
- package/dist/commands/launch.d.ts +13 -0
- package/dist/commands/launch.js +174 -0
- package/dist/commands/llm.d.ts +11 -0
- package/dist/commands/llm.js +319 -3
- package/dist/commands/login.d.ts +9 -0
- package/dist/commands/login.js +464 -147
- package/dist/commands/profile.d.ts +26 -0
- package/dist/commands/profile.js +183 -0
- package/dist/commands/prompt.js +5 -0
- package/dist/commands/sign.js +3 -0
- package/dist/commands/sounds.d.ts +12 -0
- package/dist/commands/sounds.js +262 -0
- package/dist/commands/submit.js +14 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/lib/api.d.ts +213 -0
- package/dist/lib/api.js +177 -3
- package/dist/lib/cesp/engine.d.ts +13 -0
- package/dist/lib/cesp/engine.js +132 -0
- package/dist/lib/cesp/player.d.ts +6 -0
- package/dist/lib/cesp/player.js +50 -0
- package/dist/lib/cesp/types.d.ts +38 -0
- package/dist/lib/cesp/types.js +2 -0
- package/dist/lib/config.d.ts +4 -0
- package/dist/lib/config.js +1 -0
- package/dist/lib/output.d.ts +1 -0
- package/dist/lib/output.js +3 -0
- package/package.json +4 -2
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/cancel.d.ts.map +0 -1
- package/dist/commands/cancel.js.map +0 -1
- package/dist/commands/capabilities.d.ts.map +0 -1
- package/dist/commands/capabilities.js.map +0 -1
- package/dist/commands/config.d.ts.map +0 -1
- package/dist/commands/config.js.map +0 -1
- package/dist/commands/llm.d.ts.map +0 -1
- package/dist/commands/llm.js.map +0 -1
- package/dist/commands/login.d.ts.map +0 -1
- package/dist/commands/login.js.map +0 -1
- package/dist/commands/logout.d.ts.map +0 -1
- package/dist/commands/logout.js.map +0 -1
- package/dist/commands/prompt.d.ts.map +0 -1
- package/dist/commands/prompt.js.map +0 -1
- package/dist/commands/sign.d.ts.map +0 -1
- package/dist/commands/sign.js.map +0 -1
- package/dist/commands/status.d.ts.map +0 -1
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/submit.d.ts.map +0 -1
- package/dist/commands/submit.js.map +0 -1
- package/dist/commands/whoami.d.ts.map +0 -1
- package/dist/commands/whoami.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/api.d.ts.map +0 -1
- package/dist/lib/api.js.map +0 -1
- package/dist/lib/config.d.ts.map +0 -1
- package/dist/lib/config.js.map +0 -1
- package/dist/lib/output.d.ts.map +0 -1
- package/dist/lib/output.js.map +0 -1
package/dist/lib/api.d.ts
CHANGED
|
@@ -48,6 +48,34 @@ export declare function getJobStatus(jobId: string): Promise<JobStatusResponse>;
|
|
|
48
48
|
export declare function cancelJob(jobId: string): Promise<JobStatusResponse>;
|
|
49
49
|
export declare function validateApiKey(): Promise<boolean>;
|
|
50
50
|
export declare function getUserInfo(): Promise<UserInfoResponse>;
|
|
51
|
+
export interface TokenBalanceInfo {
|
|
52
|
+
network: string;
|
|
53
|
+
token: {
|
|
54
|
+
balance: number;
|
|
55
|
+
balanceUSD: number;
|
|
56
|
+
baseToken: {
|
|
57
|
+
name: string;
|
|
58
|
+
address: string;
|
|
59
|
+
symbol: string;
|
|
60
|
+
price: number;
|
|
61
|
+
imgUrl: string;
|
|
62
|
+
decimals: number;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export interface ChainBalanceInfo {
|
|
67
|
+
nativeBalance: string;
|
|
68
|
+
nativeUsd: string;
|
|
69
|
+
tokenBalances: TokenBalanceInfo[];
|
|
70
|
+
total: string;
|
|
71
|
+
}
|
|
72
|
+
export interface BalancesResponse {
|
|
73
|
+
success: boolean;
|
|
74
|
+
evmAddress: string;
|
|
75
|
+
solAddress?: string;
|
|
76
|
+
balances: Record<string, ChainBalanceInfo>;
|
|
77
|
+
}
|
|
78
|
+
export declare function getBalances(chains?: string[]): Promise<BalancesResponse>;
|
|
51
79
|
export declare function pollJob(jobId: string, opts?: {
|
|
52
80
|
interval?: number;
|
|
53
81
|
maxAttempts?: number;
|
|
@@ -112,4 +140,189 @@ export interface SubmitResponse {
|
|
|
112
140
|
error?: string;
|
|
113
141
|
}
|
|
114
142
|
export declare function submit(request: SubmitRequest): Promise<SubmitResponse>;
|
|
143
|
+
export type FeeRecipientType = "wallet" | "x" | "farcaster" | "ens";
|
|
144
|
+
export interface DeployTokenRequest {
|
|
145
|
+
tokenName: string;
|
|
146
|
+
tokenSymbol?: string;
|
|
147
|
+
image?: string;
|
|
148
|
+
description?: string;
|
|
149
|
+
tweetUrl?: string;
|
|
150
|
+
websiteUrl?: string;
|
|
151
|
+
feeRecipient?: {
|
|
152
|
+
type: FeeRecipientType;
|
|
153
|
+
value: string;
|
|
154
|
+
};
|
|
155
|
+
simulateOnly?: boolean;
|
|
156
|
+
}
|
|
157
|
+
export interface DeployTokenResponse {
|
|
158
|
+
success: boolean;
|
|
159
|
+
tokenAddress: string;
|
|
160
|
+
poolId: string;
|
|
161
|
+
txHash?: string;
|
|
162
|
+
activityId: string;
|
|
163
|
+
chain: string;
|
|
164
|
+
simulated?: boolean;
|
|
165
|
+
feeDistribution: Record<string, {
|
|
166
|
+
address: string;
|
|
167
|
+
bps: number;
|
|
168
|
+
}>;
|
|
169
|
+
error?: string;
|
|
170
|
+
}
|
|
171
|
+
export declare function deployToken(request: DeployTokenRequest): Promise<DeployTokenResponse>;
|
|
172
|
+
export interface CreatorFeesTokenResult {
|
|
173
|
+
tokenAddress: string;
|
|
174
|
+
name: string;
|
|
175
|
+
symbol: string;
|
|
176
|
+
poolId: string;
|
|
177
|
+
initializer?: string;
|
|
178
|
+
share: string;
|
|
179
|
+
token0Label: string;
|
|
180
|
+
token1Label: string;
|
|
181
|
+
claimable: {
|
|
182
|
+
token0: string;
|
|
183
|
+
token1: string;
|
|
184
|
+
};
|
|
185
|
+
claimed: {
|
|
186
|
+
token0: string;
|
|
187
|
+
token1: string;
|
|
188
|
+
count: number;
|
|
189
|
+
};
|
|
190
|
+
source?: "doppler" | "clanker";
|
|
191
|
+
}
|
|
192
|
+
export interface CreatorFeesResponse {
|
|
193
|
+
address: string;
|
|
194
|
+
chain: "base";
|
|
195
|
+
days: number;
|
|
196
|
+
tokens: CreatorFeesTokenResult[];
|
|
197
|
+
dailyEarnings: Array<{
|
|
198
|
+
date: string;
|
|
199
|
+
weth: string;
|
|
200
|
+
}>;
|
|
201
|
+
totals: {
|
|
202
|
+
claimableWeth: string;
|
|
203
|
+
claimedWeth: string;
|
|
204
|
+
claimCount: number;
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
export interface BeneficiaryFeesResponse {
|
|
208
|
+
address: string;
|
|
209
|
+
chain: "base";
|
|
210
|
+
totalLaunches: number;
|
|
211
|
+
poolsWithShares: number;
|
|
212
|
+
tokens: CreatorFeesTokenResult[];
|
|
213
|
+
}
|
|
214
|
+
export interface DopplerClaimTxResponse {
|
|
215
|
+
to: string;
|
|
216
|
+
data: string;
|
|
217
|
+
chainId: number;
|
|
218
|
+
description: string;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Fetch creator fee data for a wallet address. Unauthenticated — calls
|
|
222
|
+
* the public endpoint directly.
|
|
223
|
+
*/
|
|
224
|
+
export declare function getCreatorFees(address: string, days?: number): Promise<CreatorFeesResponse>;
|
|
225
|
+
/**
|
|
226
|
+
* Fetch fee data for a wallet address as ANY beneficiary role (creator,
|
|
227
|
+
* protocol, platform, etc.). Processes ALL launches server-side in one
|
|
228
|
+
* request (mirrors the internal claim-doppler-fees script).
|
|
229
|
+
* Unauthenticated — calls the public endpoint.
|
|
230
|
+
*/
|
|
231
|
+
export declare function getBeneficiaryFees(address: string): Promise<BeneficiaryFeesResponse>;
|
|
232
|
+
export interface StreamProgress {
|
|
233
|
+
phase: string;
|
|
234
|
+
scanned: number;
|
|
235
|
+
total: number;
|
|
236
|
+
found?: number;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Fetch beneficiary fees with NDJSON streaming. The server sends progress
|
|
240
|
+
* lines during processing and a final result line. The onProgress callback
|
|
241
|
+
* is invoked for each progress update so the caller can update a spinner.
|
|
242
|
+
*/
|
|
243
|
+
export declare function getBeneficiaryFeesStreaming(address: string, onProgress: (progress: StreamProgress) => void): Promise<BeneficiaryFeesResponse>;
|
|
244
|
+
/**
|
|
245
|
+
* Fetch creator fee data for a specific token address. Unauthenticated —
|
|
246
|
+
* looks up the token's creator beneficiary and returns their fee data.
|
|
247
|
+
*/
|
|
248
|
+
export declare function getTokenCreatorFees(tokenAddress: string, days?: number): Promise<CreatorFeesResponse>;
|
|
249
|
+
/**
|
|
250
|
+
* Build a Doppler fee claim transaction. Requires authentication.
|
|
251
|
+
* The returned transaction data should be submitted via `submit()`.
|
|
252
|
+
*/
|
|
253
|
+
export declare function buildDopplerClaimTx(tokenAddress: string): Promise<DopplerClaimTxResponse>;
|
|
254
|
+
export interface BuildClaimTx {
|
|
255
|
+
tokenAddress: string;
|
|
256
|
+
tokenName: string;
|
|
257
|
+
tokenSymbol: string;
|
|
258
|
+
to: string;
|
|
259
|
+
data: string;
|
|
260
|
+
chainId: number;
|
|
261
|
+
gasEstimate: string;
|
|
262
|
+
maxFeePerGas: string;
|
|
263
|
+
maxPriorityFeePerGas: string;
|
|
264
|
+
description: string;
|
|
265
|
+
}
|
|
266
|
+
export interface BuildClaimResponse {
|
|
267
|
+
transactions: BuildClaimTx[];
|
|
268
|
+
errors?: Array<{
|
|
269
|
+
tokenAddress: string;
|
|
270
|
+
error: string;
|
|
271
|
+
}>;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Build unsigned claim transactions for the given beneficiary and tokens.
|
|
275
|
+
* Unauthenticated -- calls the public endpoint. The CLI signs and
|
|
276
|
+
* broadcasts locally.
|
|
277
|
+
*/
|
|
278
|
+
export interface AgentProfileResponse {
|
|
279
|
+
id: string;
|
|
280
|
+
slug: string;
|
|
281
|
+
projectName: string;
|
|
282
|
+
description?: string;
|
|
283
|
+
profileImageUrl?: string;
|
|
284
|
+
tokenAddress?: string;
|
|
285
|
+
tokenChainId?: string;
|
|
286
|
+
tokenSymbol?: string;
|
|
287
|
+
tokenName?: string;
|
|
288
|
+
marketCapUsd?: number;
|
|
289
|
+
weeklyRevenueWeth?: string;
|
|
290
|
+
twitterUsername?: string;
|
|
291
|
+
website?: string;
|
|
292
|
+
teamMembers: Array<{
|
|
293
|
+
name: string;
|
|
294
|
+
role?: string;
|
|
295
|
+
links: Array<{
|
|
296
|
+
type: string;
|
|
297
|
+
url: string;
|
|
298
|
+
}>;
|
|
299
|
+
}>;
|
|
300
|
+
products: Array<{
|
|
301
|
+
name: string;
|
|
302
|
+
description?: string;
|
|
303
|
+
url?: string;
|
|
304
|
+
}>;
|
|
305
|
+
revenueSources: Array<{
|
|
306
|
+
name: string;
|
|
307
|
+
description?: string;
|
|
308
|
+
}>;
|
|
309
|
+
projectUpdates: Array<{
|
|
310
|
+
title: string;
|
|
311
|
+
content: string;
|
|
312
|
+
createdAt: string;
|
|
313
|
+
}>;
|
|
314
|
+
approved: boolean;
|
|
315
|
+
createdAt: string;
|
|
316
|
+
}
|
|
317
|
+
export declare function getOwnProfile(): Promise<AgentProfileResponse>;
|
|
318
|
+
export declare function createProfile(data: Record<string, unknown>): Promise<AgentProfileResponse>;
|
|
319
|
+
export declare function updateProfile(data: Record<string, unknown>): Promise<AgentProfileResponse>;
|
|
320
|
+
export declare function deleteProfile(): Promise<{
|
|
321
|
+
success: boolean;
|
|
322
|
+
}>;
|
|
323
|
+
export declare function addProjectUpdate(data: {
|
|
324
|
+
title: string;
|
|
325
|
+
content: string;
|
|
326
|
+
}): Promise<AgentProfileResponse>;
|
|
327
|
+
export declare function buildPublicClaimTxs(beneficiaryAddress: string, tokenAddresses: string[]): Promise<BuildClaimResponse>;
|
|
115
328
|
//# sourceMappingURL=api.d.ts.map
|
package/dist/lib/api.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getApiUrl, requireApiKey } from "./config.js";
|
|
1
|
+
import { CLI_USER_AGENT, getApiUrl, readConfig, requireApiKey, } from "./config.js";
|
|
2
2
|
const TERMINAL_STATUSES = [
|
|
3
3
|
"completed",
|
|
4
4
|
"failed",
|
|
@@ -8,10 +8,16 @@ function isTerminalStatus(status) {
|
|
|
8
8
|
return TERMINAL_STATUSES.includes(status);
|
|
9
9
|
}
|
|
10
10
|
function authHeaders() {
|
|
11
|
-
|
|
11
|
+
const headers = {
|
|
12
12
|
"X-API-Key": requireApiKey(),
|
|
13
13
|
"Content-Type": "application/json",
|
|
14
|
+
"User-Agent": CLI_USER_AGENT,
|
|
14
15
|
};
|
|
16
|
+
const config = readConfig();
|
|
17
|
+
if (config.partnerKey) {
|
|
18
|
+
headers["X-Partner-Key"] = config.partnerKey;
|
|
19
|
+
}
|
|
20
|
+
return headers;
|
|
15
21
|
}
|
|
16
22
|
async function handleResponse(res) {
|
|
17
23
|
if (!res.ok) {
|
|
@@ -47,7 +53,7 @@ export async function cancelJob(jobId) {
|
|
|
47
53
|
export async function validateApiKey() {
|
|
48
54
|
try {
|
|
49
55
|
const res = await fetch(`${getApiUrl()}/_health`, {
|
|
50
|
-
headers: { "X-API-Key": requireApiKey() },
|
|
56
|
+
headers: { "X-API-Key": requireApiKey(), "User-Agent": CLI_USER_AGENT },
|
|
51
57
|
});
|
|
52
58
|
return res.ok;
|
|
53
59
|
}
|
|
@@ -61,6 +67,13 @@ export async function getUserInfo() {
|
|
|
61
67
|
});
|
|
62
68
|
return handleResponse(res);
|
|
63
69
|
}
|
|
70
|
+
export async function getBalances(chains) {
|
|
71
|
+
const params = chains?.length ? `?chains=${chains.join(",")}` : "";
|
|
72
|
+
const res = await fetch(`${getApiUrl()}/agent/balances${params}`, {
|
|
73
|
+
headers: authHeaders(),
|
|
74
|
+
});
|
|
75
|
+
return handleResponse(res);
|
|
76
|
+
}
|
|
64
77
|
export async function pollJob(jobId, opts = {}) {
|
|
65
78
|
const { interval = 2000, maxAttempts = 150, onStatus } = opts;
|
|
66
79
|
let attempts = 0;
|
|
@@ -91,4 +104,165 @@ export async function submit(request) {
|
|
|
91
104
|
});
|
|
92
105
|
return handleResponse(res);
|
|
93
106
|
}
|
|
107
|
+
export async function deployToken(request) {
|
|
108
|
+
const res = await fetch(`${getApiUrl()}/token-launches/deploy`, {
|
|
109
|
+
method: "POST",
|
|
110
|
+
headers: authHeaders(),
|
|
111
|
+
body: JSON.stringify(request),
|
|
112
|
+
});
|
|
113
|
+
return handleResponse(res);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Fetch creator fee data for a wallet address. Unauthenticated — calls
|
|
117
|
+
* the public endpoint directly.
|
|
118
|
+
*/
|
|
119
|
+
export async function getCreatorFees(address, days) {
|
|
120
|
+
const params = days ? `?days=${days}` : "";
|
|
121
|
+
const res = await fetch(`${getApiUrl()}/public/doppler/creator-fees/${address}${params}`, {
|
|
122
|
+
headers: {
|
|
123
|
+
"User-Agent": CLI_USER_AGENT,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
return handleResponse(res);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Fetch fee data for a wallet address as ANY beneficiary role (creator,
|
|
130
|
+
* protocol, platform, etc.). Processes ALL launches server-side in one
|
|
131
|
+
* request (mirrors the internal claim-doppler-fees script).
|
|
132
|
+
* Unauthenticated — calls the public endpoint.
|
|
133
|
+
*/
|
|
134
|
+
export async function getBeneficiaryFees(address) {
|
|
135
|
+
const res = await fetch(`${getApiUrl()}/public/doppler/beneficiary-fees/${address}`, {
|
|
136
|
+
headers: {
|
|
137
|
+
"User-Agent": CLI_USER_AGENT,
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
return handleResponse(res);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Fetch beneficiary fees with NDJSON streaming. The server sends progress
|
|
144
|
+
* lines during processing and a final result line. The onProgress callback
|
|
145
|
+
* is invoked for each progress update so the caller can update a spinner.
|
|
146
|
+
*/
|
|
147
|
+
export async function getBeneficiaryFeesStreaming(address, onProgress) {
|
|
148
|
+
const res = await fetch(`${getApiUrl()}/public/doppler/beneficiary-fees/${address}`, {
|
|
149
|
+
headers: {
|
|
150
|
+
"User-Agent": CLI_USER_AGENT,
|
|
151
|
+
Accept: "application/x-ndjson",
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
if (!res.ok) {
|
|
155
|
+
const body = (await res
|
|
156
|
+
.json()
|
|
157
|
+
.catch(() => ({ message: res.statusText })));
|
|
158
|
+
const msg = body.message || body.error || res.statusText;
|
|
159
|
+
throw new Error(`API error (${res.status}): ${msg}`);
|
|
160
|
+
}
|
|
161
|
+
if (!res.body) {
|
|
162
|
+
throw new Error("No response body");
|
|
163
|
+
}
|
|
164
|
+
const reader = res.body.getReader();
|
|
165
|
+
const decoder = new TextDecoder();
|
|
166
|
+
let buffer = "";
|
|
167
|
+
let result = null;
|
|
168
|
+
while (true) {
|
|
169
|
+
const { done, value } = await reader.read();
|
|
170
|
+
if (done)
|
|
171
|
+
break;
|
|
172
|
+
buffer += decoder.decode(value, { stream: true });
|
|
173
|
+
const lines = buffer.split("\n");
|
|
174
|
+
buffer = lines.pop() ?? "";
|
|
175
|
+
for (const line of lines) {
|
|
176
|
+
if (!line.trim())
|
|
177
|
+
continue;
|
|
178
|
+
const msg = JSON.parse(line);
|
|
179
|
+
if (msg.type === "progress") {
|
|
180
|
+
onProgress(msg);
|
|
181
|
+
}
|
|
182
|
+
else if (msg.type === "result") {
|
|
183
|
+
result = msg.data;
|
|
184
|
+
}
|
|
185
|
+
else if (msg.type === "error") {
|
|
186
|
+
throw new Error(msg.message || "Server error during streaming");
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (!result) {
|
|
191
|
+
throw new Error("No result received from server");
|
|
192
|
+
}
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Fetch creator fee data for a specific token address. Unauthenticated —
|
|
197
|
+
* looks up the token's creator beneficiary and returns their fee data.
|
|
198
|
+
*/
|
|
199
|
+
export async function getTokenCreatorFees(tokenAddress, days) {
|
|
200
|
+
const params = days ? `?days=${days}` : "";
|
|
201
|
+
const res = await fetch(`${getApiUrl()}/public/doppler/token-fees/${tokenAddress}${params}`, {
|
|
202
|
+
headers: {
|
|
203
|
+
"User-Agent": CLI_USER_AGENT,
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
return handleResponse(res);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Build a Doppler fee claim transaction. Requires authentication.
|
|
210
|
+
* The returned transaction data should be submitted via `submit()`.
|
|
211
|
+
*/
|
|
212
|
+
export async function buildDopplerClaimTx(tokenAddress) {
|
|
213
|
+
const res = await fetch(`${getApiUrl()}/agent/doppler/claim`, {
|
|
214
|
+
method: "POST",
|
|
215
|
+
headers: authHeaders(),
|
|
216
|
+
body: JSON.stringify({ tokenAddress }),
|
|
217
|
+
});
|
|
218
|
+
return handleResponse(res);
|
|
219
|
+
}
|
|
220
|
+
export async function getOwnProfile() {
|
|
221
|
+
const res = await fetch(`${getApiUrl()}/agent/profile`, {
|
|
222
|
+
headers: authHeaders(),
|
|
223
|
+
});
|
|
224
|
+
return handleResponse(res);
|
|
225
|
+
}
|
|
226
|
+
export async function createProfile(data) {
|
|
227
|
+
const res = await fetch(`${getApiUrl()}/agent/profile`, {
|
|
228
|
+
method: "POST",
|
|
229
|
+
headers: authHeaders(),
|
|
230
|
+
body: JSON.stringify(data),
|
|
231
|
+
});
|
|
232
|
+
return handleResponse(res);
|
|
233
|
+
}
|
|
234
|
+
export async function updateProfile(data) {
|
|
235
|
+
const res = await fetch(`${getApiUrl()}/agent/profile`, {
|
|
236
|
+
method: "PUT",
|
|
237
|
+
headers: authHeaders(),
|
|
238
|
+
body: JSON.stringify(data),
|
|
239
|
+
});
|
|
240
|
+
return handleResponse(res);
|
|
241
|
+
}
|
|
242
|
+
export async function deleteProfile() {
|
|
243
|
+
const res = await fetch(`${getApiUrl()}/agent/profile`, {
|
|
244
|
+
method: "DELETE",
|
|
245
|
+
headers: authHeaders(),
|
|
246
|
+
});
|
|
247
|
+
return handleResponse(res);
|
|
248
|
+
}
|
|
249
|
+
export async function addProjectUpdate(data) {
|
|
250
|
+
const res = await fetch(`${getApiUrl()}/agent/profile/update`, {
|
|
251
|
+
method: "POST",
|
|
252
|
+
headers: authHeaders(),
|
|
253
|
+
body: JSON.stringify(data),
|
|
254
|
+
});
|
|
255
|
+
return handleResponse(res);
|
|
256
|
+
}
|
|
257
|
+
export async function buildPublicClaimTxs(beneficiaryAddress, tokenAddresses) {
|
|
258
|
+
const res = await fetch(`${getApiUrl()}/public/doppler/build-claim`, {
|
|
259
|
+
method: "POST",
|
|
260
|
+
headers: {
|
|
261
|
+
"Content-Type": "application/json",
|
|
262
|
+
"User-Agent": CLI_USER_AGENT,
|
|
263
|
+
},
|
|
264
|
+
body: JSON.stringify({ beneficiaryAddress, tokenAddresses }),
|
|
265
|
+
});
|
|
266
|
+
return handleResponse(res);
|
|
267
|
+
}
|
|
94
268
|
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { InstalledPack, SoundConfig } from "./types.js";
|
|
2
|
+
/** Default sound config values (off by default). */
|
|
3
|
+
export declare const DEFAULT_SOUND_CONFIG: SoundConfig;
|
|
4
|
+
/**
|
|
5
|
+
* Fire a CESP sound event. Call from any command at the relevant lifecycle
|
|
6
|
+
* moment. Fire-and-forget: never throws, never blocks.
|
|
7
|
+
*/
|
|
8
|
+
export declare function emitCESP(category: string): void;
|
|
9
|
+
/** List all installed packs by scanning the packs directory. */
|
|
10
|
+
export declare function listInstalledPacks(): InstalledPack[];
|
|
11
|
+
/** Get the directory where packs are stored. */
|
|
12
|
+
export declare function getPacksDir(): string;
|
|
13
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { readConfig } from "../config.js";
|
|
5
|
+
import { playSound } from "./player.js";
|
|
6
|
+
const DEBOUNCE_MS = 500;
|
|
7
|
+
const PACKS_DIR = join(homedir(), ".bankr", "sounds");
|
|
8
|
+
/** In-memory state for the lifetime of the CLI process. */
|
|
9
|
+
const state = {
|
|
10
|
+
lastPlayed: new Map(),
|
|
11
|
+
lastTimestamp: new Map(),
|
|
12
|
+
};
|
|
13
|
+
/** Default sound config values (off by default). */
|
|
14
|
+
export const DEFAULT_SOUND_CONFIG = {
|
|
15
|
+
enabled: false,
|
|
16
|
+
volume: 0.7,
|
|
17
|
+
muted: false,
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Fire a CESP sound event. Call from any command at the relevant lifecycle
|
|
21
|
+
* moment. Fire-and-forget: never throws, never blocks.
|
|
22
|
+
*/
|
|
23
|
+
export function emitCESP(category) {
|
|
24
|
+
try {
|
|
25
|
+
const config = readConfig();
|
|
26
|
+
const sound = config.sound ?? DEFAULT_SOUND_CONFIG;
|
|
27
|
+
if (!sound.enabled || sound.muted || !sound.activePack)
|
|
28
|
+
return;
|
|
29
|
+
if (sound.disabledCategories?.includes(category))
|
|
30
|
+
return;
|
|
31
|
+
const pack = loadPack(sound.activePack);
|
|
32
|
+
if (!pack)
|
|
33
|
+
return;
|
|
34
|
+
// Debounce: skip if same category fired within threshold
|
|
35
|
+
const now = Date.now();
|
|
36
|
+
const lastTime = state.lastTimestamp.get(category) ?? 0;
|
|
37
|
+
if (now - lastTime < DEBOUNCE_MS)
|
|
38
|
+
return;
|
|
39
|
+
// Resolve category (direct match, then alias fallback)
|
|
40
|
+
const resolved = resolveCategory(pack.manifest, category);
|
|
41
|
+
if (!resolved)
|
|
42
|
+
return;
|
|
43
|
+
const cat = pack.manifest.categories[resolved];
|
|
44
|
+
if (!cat?.sounds?.length)
|
|
45
|
+
return;
|
|
46
|
+
const files = cat.sounds.map((s) => s.file);
|
|
47
|
+
const picked = pickSound(category, files);
|
|
48
|
+
if (!picked)
|
|
49
|
+
return;
|
|
50
|
+
// Update runtime state
|
|
51
|
+
state.lastPlayed.set(category, picked);
|
|
52
|
+
state.lastTimestamp.set(category, now);
|
|
53
|
+
// Resolve file path relative to manifest directory
|
|
54
|
+
const filePath = resolveFilePath(pack.path, picked);
|
|
55
|
+
if (existsSync(filePath)) {
|
|
56
|
+
playSound(filePath, sound.volume);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Sound must never crash the CLI
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** Resolve a CESP category, falling back through aliases. */
|
|
64
|
+
function resolveCategory(manifest, category) {
|
|
65
|
+
if (manifest.categories[category])
|
|
66
|
+
return category;
|
|
67
|
+
const alias = manifest.category_aliases?.[category];
|
|
68
|
+
if (alias && manifest.categories[alias])
|
|
69
|
+
return alias;
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
/** Pick a random sound, excluding the last-played file for the category. */
|
|
73
|
+
function pickSound(category, files) {
|
|
74
|
+
if (files.length === 0)
|
|
75
|
+
return undefined;
|
|
76
|
+
if (files.length === 1)
|
|
77
|
+
return files[0];
|
|
78
|
+
const last = state.lastPlayed.get(category);
|
|
79
|
+
const eligible = files.filter((f) => f !== last);
|
|
80
|
+
const candidates = eligible.length > 0 ? eligible : files;
|
|
81
|
+
return candidates[Math.floor(Math.random() * candidates.length)];
|
|
82
|
+
}
|
|
83
|
+
/** Resolve a manifest file path. Paths without slashes get sounds/ prefix. */
|
|
84
|
+
function resolveFilePath(packDir, filePath) {
|
|
85
|
+
// If the path has no directory component, prefix with sounds/
|
|
86
|
+
if (!filePath.includes("/")) {
|
|
87
|
+
return join(packDir, "sounds", filePath);
|
|
88
|
+
}
|
|
89
|
+
return join(packDir, filePath);
|
|
90
|
+
}
|
|
91
|
+
// -- Pack discovery --
|
|
92
|
+
const packCache = new Map();
|
|
93
|
+
function loadPack(name) {
|
|
94
|
+
if (packCache.has(name))
|
|
95
|
+
return packCache.get(name);
|
|
96
|
+
const packDir = join(PACKS_DIR, name);
|
|
97
|
+
const manifestPath = join(packDir, "openpeon.json");
|
|
98
|
+
if (!existsSync(manifestPath)) {
|
|
99
|
+
packCache.set(name, null);
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
const raw = readFileSync(manifestPath, "utf-8");
|
|
104
|
+
const manifest = JSON.parse(raw);
|
|
105
|
+
const pack = { name, path: packDir, manifest };
|
|
106
|
+
packCache.set(name, pack);
|
|
107
|
+
return pack;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
packCache.set(name, null);
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/** List all installed packs by scanning the packs directory. */
|
|
115
|
+
export function listInstalledPacks() {
|
|
116
|
+
if (!existsSync(PACKS_DIR))
|
|
117
|
+
return [];
|
|
118
|
+
const packs = [];
|
|
119
|
+
for (const entry of readdirSync(PACKS_DIR, { withFileTypes: true })) {
|
|
120
|
+
if (!entry.isDirectory())
|
|
121
|
+
continue;
|
|
122
|
+
const pack = loadPack(entry.name);
|
|
123
|
+
if (pack)
|
|
124
|
+
packs.push(pack);
|
|
125
|
+
}
|
|
126
|
+
return packs;
|
|
127
|
+
}
|
|
128
|
+
/** Get the directory where packs are stored. */
|
|
129
|
+
export function getPacksDir() {
|
|
130
|
+
return PACKS_DIR;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Play a sound file asynchronously. Never throws, never blocks the CLI.
|
|
3
|
+
* Spawns a detached child process so the sound continues even if Node exits.
|
|
4
|
+
*/
|
|
5
|
+
export declare function playSound(filePath: string, volume: number): void;
|
|
6
|
+
//# sourceMappingURL=player.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { platform } from "node:os";
|
|
3
|
+
/**
|
|
4
|
+
* Play a sound file asynchronously. Never throws, never blocks the CLI.
|
|
5
|
+
* Spawns a detached child process so the sound continues even if Node exits.
|
|
6
|
+
*/
|
|
7
|
+
export function playSound(filePath, volume) {
|
|
8
|
+
const os = platform();
|
|
9
|
+
try {
|
|
10
|
+
if (os === "darwin") {
|
|
11
|
+
// afplay volume: 0 = silent, 1 = normal, higher = amplified
|
|
12
|
+
const vol = Math.max(0, Math.min(volume, 2)).toString();
|
|
13
|
+
execFile("afplay", ["-v", vol, filePath], { timeout: 15000 }, noop);
|
|
14
|
+
}
|
|
15
|
+
else if (os === "linux") {
|
|
16
|
+
playLinux(filePath, volume);
|
|
17
|
+
}
|
|
18
|
+
else if (os === "win32") {
|
|
19
|
+
const script = [
|
|
20
|
+
"$p = New-Object System.Media.SoundPlayer",
|
|
21
|
+
`$p.SoundLocation = '${filePath.replace(/'/g, "''")}'`,
|
|
22
|
+
"$p.PlaySync()",
|
|
23
|
+
].join("; ");
|
|
24
|
+
execFile("powershell", ["-NoProfile", "-NonInteractive", "-Command", script], { timeout: 15000 }, noop);
|
|
25
|
+
}
|
|
26
|
+
// Unsupported platforms: silent no-op
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Audio failure must never crash the CLI
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function playLinux(filePath, volume) {
|
|
33
|
+
// PipeWire volume scale: cubic, 1.0 = 100%
|
|
34
|
+
const pwVol = Math.max(0, Math.min(volume, 1)).toFixed(2);
|
|
35
|
+
execFile("pw-play", ["--volume", pwVol, filePath], (err) => {
|
|
36
|
+
if (!err)
|
|
37
|
+
return;
|
|
38
|
+
// PulseAudio volume: 0-65536 where 65536 = 100%
|
|
39
|
+
const paVol = Math.round(volume * 65536).toString();
|
|
40
|
+
execFile("paplay", ["--volume", paVol, filePath], (err2) => {
|
|
41
|
+
if (!err2)
|
|
42
|
+
return;
|
|
43
|
+
// ALSA fallback (no volume control)
|
|
44
|
+
execFile("aplay", ["-q", filePath], noop);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
49
|
+
function noop() { }
|
|
50
|
+
//# sourceMappingURL=player.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** A single sound entry in a CESP manifest category. */
|
|
2
|
+
export interface CESPSound {
|
|
3
|
+
file: string;
|
|
4
|
+
label?: string;
|
|
5
|
+
}
|
|
6
|
+
/** A category entry containing one or more sound variants. */
|
|
7
|
+
export interface CESPCategory {
|
|
8
|
+
sounds: CESPSound[];
|
|
9
|
+
}
|
|
10
|
+
/** openpeon.json manifest (CESP v1.0). */
|
|
11
|
+
export interface CESPManifest {
|
|
12
|
+
cesp_version: string;
|
|
13
|
+
name: string;
|
|
14
|
+
display_name?: string;
|
|
15
|
+
version: string;
|
|
16
|
+
categories: Record<string, CESPCategory>;
|
|
17
|
+
category_aliases?: Record<string, string>;
|
|
18
|
+
}
|
|
19
|
+
/** Metadata for an installed sound pack. */
|
|
20
|
+
export interface InstalledPack {
|
|
21
|
+
name: string;
|
|
22
|
+
path: string;
|
|
23
|
+
manifest: CESPManifest;
|
|
24
|
+
}
|
|
25
|
+
/** Persisted sound configuration (stored in BankrConfig.sound). */
|
|
26
|
+
export interface SoundConfig {
|
|
27
|
+
enabled: boolean;
|
|
28
|
+
volume: number;
|
|
29
|
+
muted: boolean;
|
|
30
|
+
activePack?: string;
|
|
31
|
+
disabledCategories?: string[];
|
|
32
|
+
}
|
|
33
|
+
/** In-memory runtime state (not persisted). */
|
|
34
|
+
export interface CESPState {
|
|
35
|
+
lastPlayed: Map<string, string>;
|
|
36
|
+
lastTimestamp: Map<string, number>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=types.d.ts.map
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
import type { SoundConfig } from "./cesp/types.js";
|
|
1
2
|
export interface BankrConfig {
|
|
2
3
|
apiKey?: string;
|
|
3
4
|
apiUrl?: string;
|
|
4
5
|
llmKey?: string;
|
|
5
6
|
llmUrl?: string;
|
|
6
7
|
lastThreadId?: string;
|
|
8
|
+
partnerKey?: string;
|
|
9
|
+
sound?: SoundConfig;
|
|
7
10
|
}
|
|
8
11
|
export declare function setConfigPath(path: string): void;
|
|
9
12
|
export declare function getConfigPath(): string;
|
|
10
13
|
export declare const DEFAULT_API_URL = "https://api.bankr.bot";
|
|
11
14
|
export declare const DEFAULT_LLM_URL = "https://llm.bankr.bot";
|
|
15
|
+
export declare const CLI_USER_AGENT = "bankr-cli/0.1";
|
|
12
16
|
export declare function readConfig(): BankrConfig;
|
|
13
17
|
export declare function writeConfig(config: BankrConfig): void;
|
|
14
18
|
export declare function clearConfig(): void;
|