@prestyj/core 4.10.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/LICENSE +21 -0
- package/dist/chunk-2MH5WQIW.js +24 -0
- package/dist/chunk-2MH5WQIW.js.map +1 -0
- package/dist/chunk-LN5L2S5G.js +345 -0
- package/dist/chunk-LN5L2S5G.js.map +1 -0
- package/dist/index.cjs +2333 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +359 -0
- package/dist/index.d.ts +359 -0
- package/dist/index.js +1915 -0
- package/dist/index.js.map +1 -0
- package/dist/model-registry.cjs +378 -0
- package/dist/model-registry.cjs.map +1 -0
- package/dist/model-registry.d.cts +78 -0
- package/dist/model-registry.d.ts +78 -0
- package/dist/model-registry.js +25 -0
- package/dist/model-registry.js.map +1 -0
- package/dist/paths.cjs +58 -0
- package/dist/paths.cjs.map +1 -0
- package/dist/paths.d.cts +16 -0
- package/dist/paths.d.ts +16 -0
- package/dist/paths.js +7 -0
- package/dist/paths.js.map +1 -0
- package/package.json +55 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
export { ContextWindowOptions, DEFAULT_MAX_VIDEO_BYTES, MODELS, ModelInfo, getContextWindow, getDefaultModel, getMaxThinkingLevel, getModel, getModelsForProvider, getSummaryModel, getVideoByteLimit, usesOpenAICodexTransport } from './model-registry.js';
|
|
2
|
+
import { Provider, ThinkingLevel } from '@prestyj/ai';
|
|
3
|
+
export { AppPaths, getAppPaths } from './paths.js';
|
|
4
|
+
|
|
5
|
+
declare function getSupportedThinkingLevels(provider: Provider, model: string): readonly ThinkingLevel[];
|
|
6
|
+
declare function isThinkingLevelSupported(provider: Provider, model: string, level: ThinkingLevel): boolean;
|
|
7
|
+
declare function getNextThinkingLevel(provider: Provider, model: string, current: ThinkingLevel | undefined): ThinkingLevel | undefined;
|
|
8
|
+
|
|
9
|
+
type LogLevel = "INFO" | "ERROR" | "WARN" | "DEBUG";
|
|
10
|
+
/**
|
|
11
|
+
* Open the debug log in append mode, tagging this process with a session id and
|
|
12
|
+
* remembering `name` for the shutdown line. Idempotent — re-calling while open
|
|
13
|
+
* is a no-op. Returns true only when it *newly* opened the file (so callers can
|
|
14
|
+
* write a one-time startup line); returns false if already open or if the file
|
|
15
|
+
* could not be opened.
|
|
16
|
+
*/
|
|
17
|
+
declare function openLog(filePath: string, name: string): boolean;
|
|
18
|
+
/** Session identifier included on every log line as `sid=<id>`. */
|
|
19
|
+
declare function getSessionId(): string;
|
|
20
|
+
/** True if the logger has an open file descriptor. */
|
|
21
|
+
declare function isLoggerOpen(): boolean;
|
|
22
|
+
/** Write a timestamped log line. No-op if the logger is not open. */
|
|
23
|
+
declare function log(level: LogLevel, category: string, message: string, data?: Record<string, unknown>): void;
|
|
24
|
+
/**
|
|
25
|
+
* Register a cleanup callback (e.g. an EventBus unsubscriber) to run when the
|
|
26
|
+
* logger closes. Lets app-side bridges hook into the shared lifecycle without
|
|
27
|
+
* the core needing to know about app types.
|
|
28
|
+
*/
|
|
29
|
+
declare function registerLogCleanup(fn: () => void): void;
|
|
30
|
+
/**
|
|
31
|
+
* Write a shutdown line (unless suppressed), close the file descriptor, and run
|
|
32
|
+
* any registered cleanups.
|
|
33
|
+
*/
|
|
34
|
+
declare function closeLogger(opts?: {
|
|
35
|
+
shutdownLine?: boolean;
|
|
36
|
+
}): void;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Simple file-based lock with PID tracking and stale detection.
|
|
40
|
+
* Uses atomic file creation (wx flag) to prevent races.
|
|
41
|
+
*/
|
|
42
|
+
declare function withFileLock<T>(filePath: string, fn: () => Promise<T>): Promise<T>;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Resolve the current Claude Code release version for spoofing the claude-cli
|
|
46
|
+
* User-Agent on OAuth and inference requests. Cached in-memory for the process
|
|
47
|
+
* lifetime and on disk for 24h. Falls back to a hardcoded constant if the npm
|
|
48
|
+
* registry is unreachable and no cache exists.
|
|
49
|
+
*/
|
|
50
|
+
declare function getClaudeCodeVersion(): Promise<string>;
|
|
51
|
+
/** Build the User-Agent string Anthropic's OAuth + inference edges expect. */
|
|
52
|
+
declare function getClaudeCliUserAgent(): Promise<string>;
|
|
53
|
+
|
|
54
|
+
interface OAuthCredentials {
|
|
55
|
+
accessToken: string;
|
|
56
|
+
refreshToken: string;
|
|
57
|
+
expiresAt: number;
|
|
58
|
+
accountId?: string;
|
|
59
|
+
projectId?: string;
|
|
60
|
+
baseUrl?: string;
|
|
61
|
+
}
|
|
62
|
+
interface OAuthLoginCallbacks {
|
|
63
|
+
onOpenUrl: (url: string) => void;
|
|
64
|
+
onPromptCode: (message: string) => Promise<string>;
|
|
65
|
+
onStatus: (message: string) => void;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Storage key for Kimi Code OAuth credentials. Kept distinct from the
|
|
70
|
+
* `moonshot` API-key entry so a user can configure BOTH and we always
|
|
71
|
+
* prefer OAuth for the logical `moonshot` provider.
|
|
72
|
+
*/
|
|
73
|
+
declare const MOONSHOT_OAUTH_KEY = "moonshot-oauth";
|
|
74
|
+
declare class AuthStorage {
|
|
75
|
+
private data;
|
|
76
|
+
private filePath;
|
|
77
|
+
private loaded;
|
|
78
|
+
/** Per-provider lock to serialize concurrent refresh calls. */
|
|
79
|
+
private refreshLocks;
|
|
80
|
+
constructor(filePath?: string);
|
|
81
|
+
/** Path to the on-disk auth file. Useful for status output. */
|
|
82
|
+
get path(): string;
|
|
83
|
+
/** List provider keys with stored credentials. */
|
|
84
|
+
listProviders(): Promise<string[]>;
|
|
85
|
+
/** True if credentials exist for `provider`. */
|
|
86
|
+
hasCredentials(provider: string): Promise<boolean>;
|
|
87
|
+
/**
|
|
88
|
+
* True if the user has any usable auth for the logical provider. For
|
|
89
|
+
* `moonshot` this is satisfied by either the Kimi OAuth credential or the
|
|
90
|
+
* Moonshot API key.
|
|
91
|
+
*/
|
|
92
|
+
hasProviderAuth(provider: string): Promise<boolean>;
|
|
93
|
+
/**
|
|
94
|
+
* True if the active credential for `provider` is a static API key with no
|
|
95
|
+
* refresh mechanism. For `moonshot` this is only true when the Kimi OAuth
|
|
96
|
+
* credential is absent (a present OAuth credential is refreshable).
|
|
97
|
+
*/
|
|
98
|
+
isStaticApiKey(provider: string): Promise<boolean>;
|
|
99
|
+
load(): Promise<void>;
|
|
100
|
+
private ensureLoaded;
|
|
101
|
+
getCredentials(provider: string): Promise<OAuthCredentials | undefined>;
|
|
102
|
+
setCredentials(provider: string, creds: OAuthCredentials): Promise<void>;
|
|
103
|
+
clearCredentials(provider: string): Promise<void>;
|
|
104
|
+
clearAll(): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* Returns valid credentials, auto-refreshing if expired.
|
|
107
|
+
* If `forceRefresh` is true, refreshes even if the token hasn't expired
|
|
108
|
+
* (useful when the provider rejects a token with 401 before its stored expiry).
|
|
109
|
+
* Throws if not logged in.
|
|
110
|
+
*/
|
|
111
|
+
resolveCredentials(provider: string, opts?: {
|
|
112
|
+
forceRefresh?: boolean;
|
|
113
|
+
}): Promise<OAuthCredentials>;
|
|
114
|
+
/**
|
|
115
|
+
* Returns a valid access token, auto-refreshing if expired.
|
|
116
|
+
* Throws if not logged in.
|
|
117
|
+
*/
|
|
118
|
+
resolveToken(provider: string): Promise<string>;
|
|
119
|
+
private save;
|
|
120
|
+
}
|
|
121
|
+
declare class NotLoggedInError extends Error {
|
|
122
|
+
provider: string;
|
|
123
|
+
constructor(provider: string);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
declare function generatePKCE(): Promise<{
|
|
127
|
+
verifier: string;
|
|
128
|
+
challenge: string;
|
|
129
|
+
}>;
|
|
130
|
+
|
|
131
|
+
declare function loginAnthropic(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;
|
|
132
|
+
declare function refreshAnthropicToken(refreshToken: string): Promise<OAuthCredentials>;
|
|
133
|
+
|
|
134
|
+
declare function loginOpenAI(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;
|
|
135
|
+
declare function refreshOpenAIToken(refreshToken: string): Promise<OAuthCredentials>;
|
|
136
|
+
|
|
137
|
+
declare function loginGemini(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;
|
|
138
|
+
declare function refreshGeminiToken(refreshToken: string): Promise<OAuthCredentials>;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Kimi Code OAuth — Device Authorization Grant (RFC 8628).
|
|
142
|
+
*
|
|
143
|
+
* Mirrors MoonshotAI/kimi-code's managed-auth flow. Three form-encoded
|
|
144
|
+
* POST endpoints against the OAuth host (default `https://auth.kimi.com`):
|
|
145
|
+
*
|
|
146
|
+
* - `/api/oauth/device_authorization` (client_id) → device + user code
|
|
147
|
+
* - `/api/oauth/token` (grant_type=device_code) → poll until authorized
|
|
148
|
+
* - `/api/oauth/token` (grant_type=refresh_token) → refresh access token
|
|
149
|
+
*
|
|
150
|
+
* Unlike Anthropic/OpenAI/Gemini (browser-redirect PKCE), this is a
|
|
151
|
+
* device-code/poll flow: we show the user a URL + code, they authorize in a
|
|
152
|
+
* browser on any device, and we poll for the token.
|
|
153
|
+
*
|
|
154
|
+
* After login the issued token is used against the managed coding API
|
|
155
|
+
* (`https://api.kimi.com/coding/v1`, distinct from the `api.moonshot.ai`
|
|
156
|
+
* API-key endpoint) via `Authorization: Bearer <access_token>`. We persist
|
|
157
|
+
* that base URL on the credential so the runtime routes there automatically.
|
|
158
|
+
*/
|
|
159
|
+
|
|
160
|
+
/** Managed coding API base URL the issued OAuth token is used against. */
|
|
161
|
+
declare function kimiCodeBaseUrl(): string;
|
|
162
|
+
/**
|
|
163
|
+
* Headers the Kimi For Coding API requires on every model request. The
|
|
164
|
+
* managed endpoint gates access to recognized coding agents: requests must
|
|
165
|
+
* carry a `kimi_code_cli` platform identity and matching `User-Agent`, or the
|
|
166
|
+
* server rejects with "only available for Coding Agents". Attach these to the
|
|
167
|
+
* inference client's default headers whenever the Kimi OAuth token is used.
|
|
168
|
+
*/
|
|
169
|
+
declare function kimiCodingHeaders(): Record<string, string>;
|
|
170
|
+
/**
|
|
171
|
+
* True if `baseUrl` targets the Kimi For Coding managed endpoint (the URL
|
|
172
|
+
* persisted on Kimi OAuth credentials). Callers use this to decide whether to
|
|
173
|
+
* attach `kimiCodingHeaders()` — the Moonshot API-key path uses a different
|
|
174
|
+
* host and must NOT receive the coding-agent identity headers.
|
|
175
|
+
*/
|
|
176
|
+
declare function isKimiCodingEndpoint(baseUrl: string | undefined): boolean;
|
|
177
|
+
/**
|
|
178
|
+
* Drive the Kimi device-code flow end-to-end. Shows the verification URL +
|
|
179
|
+
* user code via callbacks, opens the browser, and polls until the user
|
|
180
|
+
* authorizes (or a 15-minute local timeout elapses).
|
|
181
|
+
*/
|
|
182
|
+
declare function loginKimi(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;
|
|
183
|
+
/** Exchange a refresh token for a fresh Kimi access token. */
|
|
184
|
+
declare function refreshKimiToken(refreshToken: string): Promise<OAuthCredentials>;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Minimal Telegram Bot API client using raw fetch().
|
|
188
|
+
* Supports long polling, markdown messages, inline keyboards, and message splitting.
|
|
189
|
+
*/
|
|
190
|
+
interface TelegramConfig {
|
|
191
|
+
botToken: string;
|
|
192
|
+
/** Only accept messages from this Telegram user ID. */
|
|
193
|
+
allowedUserId: number;
|
|
194
|
+
}
|
|
195
|
+
interface TelegramUpdate {
|
|
196
|
+
update_id: number;
|
|
197
|
+
message?: {
|
|
198
|
+
message_id: number;
|
|
199
|
+
from: {
|
|
200
|
+
id: number;
|
|
201
|
+
first_name: string;
|
|
202
|
+
};
|
|
203
|
+
chat: {
|
|
204
|
+
id: number;
|
|
205
|
+
type: string;
|
|
206
|
+
title?: string;
|
|
207
|
+
};
|
|
208
|
+
text?: string;
|
|
209
|
+
voice?: {
|
|
210
|
+
file_id: string;
|
|
211
|
+
duration: number;
|
|
212
|
+
mime_type?: string;
|
|
213
|
+
file_size?: number;
|
|
214
|
+
};
|
|
215
|
+
};
|
|
216
|
+
callback_query?: {
|
|
217
|
+
id: string;
|
|
218
|
+
from: {
|
|
219
|
+
id: number;
|
|
220
|
+
};
|
|
221
|
+
message: {
|
|
222
|
+
chat: {
|
|
223
|
+
id: number;
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
data: string;
|
|
227
|
+
};
|
|
228
|
+
my_chat_member?: {
|
|
229
|
+
chat: {
|
|
230
|
+
id: number;
|
|
231
|
+
type: string;
|
|
232
|
+
title?: string;
|
|
233
|
+
};
|
|
234
|
+
from: {
|
|
235
|
+
id: number;
|
|
236
|
+
};
|
|
237
|
+
new_chat_member: {
|
|
238
|
+
status: string;
|
|
239
|
+
};
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
interface InlineButton {
|
|
243
|
+
text: string;
|
|
244
|
+
callback_data: string;
|
|
245
|
+
}
|
|
246
|
+
/** Incoming message with chat context. */
|
|
247
|
+
interface TelegramMessage {
|
|
248
|
+
text: string;
|
|
249
|
+
chatId: number;
|
|
250
|
+
chatType: "private" | "group" | "supergroup" | "channel";
|
|
251
|
+
chatTitle?: string;
|
|
252
|
+
}
|
|
253
|
+
/** Incoming voice note with chat context. */
|
|
254
|
+
interface TelegramVoiceMessage {
|
|
255
|
+
fileId: string;
|
|
256
|
+
duration: number;
|
|
257
|
+
chatId: number;
|
|
258
|
+
chatType: "private" | "group" | "supergroup" | "channel";
|
|
259
|
+
chatTitle?: string;
|
|
260
|
+
}
|
|
261
|
+
declare class TelegramBot {
|
|
262
|
+
private token;
|
|
263
|
+
private allowedUserId;
|
|
264
|
+
private offset;
|
|
265
|
+
private running;
|
|
266
|
+
private onMessage;
|
|
267
|
+
private onVoiceMessage;
|
|
268
|
+
private onCallback;
|
|
269
|
+
private onBotAdded;
|
|
270
|
+
private onBotRemoved;
|
|
271
|
+
constructor(config: TelegramConfig);
|
|
272
|
+
/** Register handler for incoming text messages. */
|
|
273
|
+
onText(handler: (msg: TelegramMessage) => void): void;
|
|
274
|
+
/** Register handler for incoming voice notes. */
|
|
275
|
+
onVoice(handler: (msg: TelegramVoiceMessage) => void): void;
|
|
276
|
+
/** Register handler for inline keyboard button presses. */
|
|
277
|
+
onCallbackQuery(handler: (data: string, chatId: number) => void): void;
|
|
278
|
+
/** Register handler for when the bot is added to a group. */
|
|
279
|
+
onAddedToGroup(handler: (chatId: number, chatTitle?: string) => void): void;
|
|
280
|
+
/** Register handler for when the bot is removed from a group. */
|
|
281
|
+
onRemovedFromGroup(handler: (chatId: number) => void): void;
|
|
282
|
+
/** Start long polling. Blocks until stop() is called. */
|
|
283
|
+
start(): Promise<void>;
|
|
284
|
+
/** Stop long polling. */
|
|
285
|
+
stop(): void;
|
|
286
|
+
/** Send a text message to a specific chat. Converts markdown and splits long messages. */
|
|
287
|
+
send(chatId: number, text: string, buttons?: InlineButton[][]): Promise<void>;
|
|
288
|
+
/** Send a plain text message (no markdown parsing) to a specific chat. */
|
|
289
|
+
sendPlain(chatId: number, text: string): Promise<void>;
|
|
290
|
+
/** Send a typing indicator to a specific chat. */
|
|
291
|
+
sendTyping(chatId: number): Promise<void>;
|
|
292
|
+
/** Get a direct download URL for a Telegram file. */
|
|
293
|
+
getFileUrl(fileId: string): Promise<string>;
|
|
294
|
+
private getUpdates;
|
|
295
|
+
private handleUpdate;
|
|
296
|
+
private apiCall;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Voice note transcription using local Whisper model.
|
|
301
|
+
* Uses @huggingface/transformers (pure JS/WASM) — no native deps, no API keys.
|
|
302
|
+
* Model (~75MB) is downloaded on first use and cached locally.
|
|
303
|
+
*/
|
|
304
|
+
/** Optional callback for model download progress. */
|
|
305
|
+
type ProgressCallback = (info: {
|
|
306
|
+
status: string;
|
|
307
|
+
progress?: number;
|
|
308
|
+
file?: string;
|
|
309
|
+
}) => void;
|
|
310
|
+
/** Set a callback to receive model download progress updates. */
|
|
311
|
+
declare function setProgressCallback(cb: ProgressCallback | null): void;
|
|
312
|
+
/**
|
|
313
|
+
* Resample audio from one sample rate to another using linear interpolation.
|
|
314
|
+
*/
|
|
315
|
+
declare function resample(audio: Float32Array, fromRate: number, toRate: number): Float32Array;
|
|
316
|
+
/**
|
|
317
|
+
* Downmix multi-channel audio to mono by averaging all channels.
|
|
318
|
+
*/
|
|
319
|
+
declare function downmixToMono(channelData: Float32Array[]): Float32Array;
|
|
320
|
+
/**
|
|
321
|
+
* Decode OGG Opus audio buffer to 16kHz mono PCM Float32Array.
|
|
322
|
+
*/
|
|
323
|
+
declare function decodeOggOpus(buffer: Uint8Array): Promise<Float32Array>;
|
|
324
|
+
/** Whether the model has been loaded already. */
|
|
325
|
+
declare function isModelLoaded(): boolean;
|
|
326
|
+
/**
|
|
327
|
+
* Transcribe a voice message from its Telegram file URL.
|
|
328
|
+
* Downloads the OGG Opus file, decodes to PCM, and runs Whisper locally.
|
|
329
|
+
*/
|
|
330
|
+
declare function transcribeVoice(fileUrl: string): Promise<string>;
|
|
331
|
+
|
|
332
|
+
interface AutoUpdateConfig {
|
|
333
|
+
/** npm package to self-update, e.g. "@prestyj/cli". */
|
|
334
|
+
packageName: string;
|
|
335
|
+
/**
|
|
336
|
+
* Absolute path to this app's update-state.json, or a thunk resolving it.
|
|
337
|
+
* A thunk keeps path resolution lazy so callers can derive it from
|
|
338
|
+
* `os.homedir()` without freezing the value at module-load time (which
|
|
339
|
+
* breaks tests that mock the home directory after import).
|
|
340
|
+
*/
|
|
341
|
+
stateFilePath: string | (() => string);
|
|
342
|
+
/** Builds the in-session "update available" notification. */
|
|
343
|
+
periodicMessage?: (args: {
|
|
344
|
+
currentVersion: string;
|
|
345
|
+
latestVersion: string;
|
|
346
|
+
updateCommand: string;
|
|
347
|
+
}) => string;
|
|
348
|
+
}
|
|
349
|
+
interface AutoUpdater {
|
|
350
|
+
checkAndAutoUpdate(currentVersion: string): string | null;
|
|
351
|
+
getPendingUpdate(currentVersion: string): {
|
|
352
|
+
latestVersion: string;
|
|
353
|
+
} | null;
|
|
354
|
+
startPeriodicUpdateCheck(currentVersion: string, onUpdate: (message: string) => void): void;
|
|
355
|
+
stopPeriodicUpdateCheck(): void;
|
|
356
|
+
}
|
|
357
|
+
declare function createAutoUpdater(config: AutoUpdateConfig): AutoUpdater;
|
|
358
|
+
|
|
359
|
+
export { AuthStorage, type AutoUpdateConfig, type AutoUpdater, type InlineButton, type LogLevel, MOONSHOT_OAUTH_KEY, NotLoggedInError, type OAuthCredentials, type OAuthLoginCallbacks, type ProgressCallback, TelegramBot, type TelegramConfig, type TelegramMessage, type TelegramUpdate, type TelegramVoiceMessage, closeLogger, createAutoUpdater, decodeOggOpus, downmixToMono, generatePKCE, getClaudeCliUserAgent, getClaudeCodeVersion, getNextThinkingLevel, getSessionId, getSupportedThinkingLevels, isKimiCodingEndpoint, isLoggerOpen, isModelLoaded, isThinkingLevelSupported, kimiCodeBaseUrl, kimiCodingHeaders, log, loginAnthropic, loginGemini, loginKimi, loginOpenAI, openLog, refreshAnthropicToken, refreshGeminiToken, refreshKimiToken, refreshOpenAIToken, registerLogCleanup, resample, setProgressCallback, transcribeVoice, withFileLock };
|