dsh-workbuddy-connect 0.3.2 → 0.5.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.en.md +40 -10
- package/README.md +42 -12
- package/lib/bin.js +71 -23
- package/lib/client.js +1033 -45
- package/lib/index.d.ts +619 -13
- package/lib/index.js +1196 -126
- package/lib/variants-GgLTJgZs.js +2321 -0
- package/package.json +11 -5
- package/lib/host-heartbeat-BSsKUoB8.js +0 -1198
package/lib/index.d.ts
CHANGED
|
@@ -1,8 +1,136 @@
|
|
|
1
1
|
import z from "@deepseek-ai/schemastery";
|
|
2
|
+
import "@earendil-works/pi-ai";
|
|
2
3
|
import { PiAiAdapter } from "@deepseek-ai/dsh-llm-pi-ai";
|
|
3
4
|
import { Context } from "@deepseek-ai/cordis";
|
|
4
5
|
import { SettingsNamespace } from "@deepseek-ai/dsh-settings";
|
|
5
6
|
import { AttachmentStore } from "@deepseek-ai/dsh-attachment";
|
|
7
|
+
//#region src/app-version.d.ts
|
|
8
|
+
/** Basename of the saved version under `$DSH_HOME`. */
|
|
9
|
+
declare const WORKBUDDY_APP_VERSION_FILENAME = ".workbuddy-ai-version.json";
|
|
10
|
+
/** Where the version came from, for `doctor` output. */
|
|
11
|
+
type WorkBuddyAppVersionSource = 'installed' | 'saved' | 'fallback';
|
|
12
|
+
/** Resolved version plus provenance. */
|
|
13
|
+
interface AppVersionInfo {
|
|
14
|
+
version: string;
|
|
15
|
+
source: WorkBuddyAppVersionSource;
|
|
16
|
+
/** Basename of the App bundle the version was read from, when installed. */
|
|
17
|
+
bundle?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Whether a string is safe to interpolate into an HTTP header.
|
|
21
|
+
*
|
|
22
|
+
* Strict on purpose: the value reaches a header, so anything that could split
|
|
23
|
+
* the request (CR, LF, spaces beyond the separator) or inject a second UA
|
|
24
|
+
* token must never pass. The App's own version is always `N.N.N` or `N.N.N.N`.
|
|
25
|
+
*/
|
|
26
|
+
declare function validAppVersion(value: unknown): value is string;
|
|
27
|
+
/**
|
|
28
|
+
* Read `CFBundleShortVersionString` out of an `Info.plist`.
|
|
29
|
+
*
|
|
30
|
+
* Parsed as XML rather than grepped, because the plist contains several
|
|
31
|
+
* `<string>` values and a regex would be one unrelated key away from
|
|
32
|
+
* returning the wrong one. A binary plist has no `<dict>` in its bytes and is
|
|
33
|
+
* reported as unreadable (the saved value then applies) rather than guessed at.
|
|
34
|
+
*/
|
|
35
|
+
declare function readBundleVersion(plistPath: string): Promise<string | undefined>;
|
|
36
|
+
/**
|
|
37
|
+
* The installed international App's version, or `undefined` when it is not
|
|
38
|
+
* installed (or not readable).
|
|
39
|
+
*
|
|
40
|
+
* Windows and Linux have no verified bundle-metadata location yet, so this
|
|
41
|
+
* returns `undefined` there and the saved/fallback value is used instead of
|
|
42
|
+
* guessing a path — the same discipline the credential discovery follows.
|
|
43
|
+
*/
|
|
44
|
+
declare function installedAppVersion(): Promise<{
|
|
45
|
+
version: string;
|
|
46
|
+
bundle: string;
|
|
47
|
+
} | undefined>;
|
|
48
|
+
/** Constructor dependencies; all injectable so tests never touch the real FS. */
|
|
49
|
+
interface ResolveAppVersionOptions {
|
|
50
|
+
/** Installed-version reader; defaults to {@link installedAppVersion}. */
|
|
51
|
+
installed?: () => Promise<{
|
|
52
|
+
version: string;
|
|
53
|
+
bundle: string;
|
|
54
|
+
} | undefined>;
|
|
55
|
+
/** Saved-version path; defaults to {@link appVersionPath}. */
|
|
56
|
+
path?: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Resolve the UA version: installed App first, then the last saved value, then
|
|
60
|
+
* the compiled-in fallback.
|
|
61
|
+
*
|
|
62
|
+
* A value read from the App is written back immediately, so an uninstalled App
|
|
63
|
+
* or an unreadable plist later still has the last real version to fall back
|
|
64
|
+
* on. The write is best-effort: failing to cache a version must never fail the
|
|
65
|
+
* catalog request that asked for it.
|
|
66
|
+
*/
|
|
67
|
+
declare function resolveAppVersion(options?: ResolveAppVersionOptions): Promise<AppVersionInfo>;
|
|
68
|
+
/**
|
|
69
|
+
* Build the App-shaped User-Agent for catalog requests.
|
|
70
|
+
*
|
|
71
|
+
* `WorkBuddyAI/<version>` with no space is the form measured to reach the App
|
|
72
|
+
* document; the space form is rejected with 400/12403. Throws on an invalid
|
|
73
|
+
* version rather than sending a malformed header.
|
|
74
|
+
*/
|
|
75
|
+
declare function appUserAgent(version: string): string;
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region src/probe.d.ts
|
|
78
|
+
/**
|
|
79
|
+
* The canonical values a probe tests, in a fixed order.
|
|
80
|
+
*
|
|
81
|
+
* `minimal` is absent: it appears in no upstream vocabulary. `off` is absent
|
|
82
|
+
* by policy — disabling thinking is a separate capability the upstream must
|
|
83
|
+
* declare through `canDisableThinking`, never something probing may infer.
|
|
84
|
+
*/
|
|
85
|
+
declare const PROBE_EFFORT_CANDIDATES: readonly WorkBuddyEffort[];
|
|
86
|
+
/** Sentinel generator; injectable so tests get deterministic values. */
|
|
87
|
+
type SentinelFactory = () => string;
|
|
88
|
+
/** Default sentinel: unmistakably non-canonical, different on every call. */
|
|
89
|
+
declare function randomSentinel(): string;
|
|
90
|
+
/**
|
|
91
|
+
* One response as the probe sees it, split into the only distinctions the
|
|
92
|
+
* attribution rule needs.
|
|
93
|
+
*/
|
|
94
|
+
interface ProbeAttempt {
|
|
95
|
+
/** HTTP status, or 0 for a transport failure. */
|
|
96
|
+
status: number;
|
|
97
|
+
/** True when a parseable SSE event arrived. */
|
|
98
|
+
streamed: boolean;
|
|
99
|
+
/** `extError.code` from a JSON error body, when present. */
|
|
100
|
+
errorCode?: string;
|
|
101
|
+
/** Free-form detail for logs; never shown as a capability claim. */
|
|
102
|
+
detail?: string;
|
|
103
|
+
}
|
|
104
|
+
/** How one attempt is performed; the caller owns credentials and HTTP. */
|
|
105
|
+
type ProbeSender = (effort: string | undefined, signal: AbortSignal) => Promise<ProbeAttempt>;
|
|
106
|
+
/** The outcome of probing one model. */
|
|
107
|
+
type ProbeOutcome = {
|
|
108
|
+
validation: 'validating';
|
|
109
|
+
efforts: readonly WorkBuddyEffort[];
|
|
110
|
+
requests: number;
|
|
111
|
+
} | {
|
|
112
|
+
validation: 'non-validating';
|
|
113
|
+
efforts: readonly [];
|
|
114
|
+
requests: number;
|
|
115
|
+
} | {
|
|
116
|
+
validation: 'unknown';
|
|
117
|
+
efforts: readonly [];
|
|
118
|
+
requests: number;
|
|
119
|
+
reason: string;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Probe one model.
|
|
123
|
+
*
|
|
124
|
+
* `options.candidates` exists so tests can shorten the sweep; production always
|
|
125
|
+
* uses {@link PROBE_EFFORT_CANDIDATES}.
|
|
126
|
+
*/
|
|
127
|
+
declare function probeModel(options: {
|
|
128
|
+
send: ProbeSender;
|
|
129
|
+
sentinel?: SentinelFactory;
|
|
130
|
+
candidates?: readonly WorkBuddyEffort[];
|
|
131
|
+
timeoutMs?: number;
|
|
132
|
+
}): Promise<ProbeOutcome>;
|
|
133
|
+
//#endregion
|
|
6
134
|
//#region src/upstream.d.ts
|
|
7
135
|
/** WorkBuddy region selected by the credential's login domain. */
|
|
8
136
|
type WorkBuddyRegion = 'cn' | 'global';
|
|
@@ -13,6 +141,9 @@ interface WorkBuddyUpstreamModel {
|
|
|
13
141
|
id: string;
|
|
14
142
|
name: string;
|
|
15
143
|
contextWindow: number;
|
|
144
|
+
maxInputTokens?: number;
|
|
145
|
+
supportedContextWindows?: readonly number[];
|
|
146
|
+
promotions?: readonly WorkBuddyPromotion[];
|
|
16
147
|
maxTokens: number;
|
|
17
148
|
/**
|
|
18
149
|
* Upstream-declared image input capability. Missing or false upstream data
|
|
@@ -63,6 +194,17 @@ interface WorkBuddyModelBilling {
|
|
|
63
194
|
badges?: readonly string[];
|
|
64
195
|
/** Whether the model is currently free (`x0.00` credits). */
|
|
65
196
|
free: boolean;
|
|
197
|
+
/**
|
|
198
|
+
* The rate cannot be stated for this model right now.
|
|
199
|
+
*
|
|
200
|
+
* Set when a row that arrived with promotions attached has no promotion in
|
|
201
|
+
* force: the upstream bakes the discounted value into `credits`, so the
|
|
202
|
+
* cached rate describes a discount that has ended. The original price is not
|
|
203
|
+
* recoverable from the row, so the plugin reports "unknown, refresh needed"
|
|
204
|
+
* rather than repeating a figure it can no longer stand behind — in
|
|
205
|
+
* particular it never keeps claiming the model is free.
|
|
206
|
+
*/
|
|
207
|
+
rateUnknown?: boolean;
|
|
66
208
|
}
|
|
67
209
|
/** One billing package and its remaining credit. */
|
|
68
210
|
interface WorkBuddyCreditAccount {
|
|
@@ -124,20 +266,177 @@ declare function regionOf(domain: string): WorkBuddyRegion;
|
|
|
124
266
|
* compatible spelling the upstream accepts.
|
|
125
267
|
*/
|
|
126
268
|
declare function prepareChatBody(source: string): string;
|
|
269
|
+
/** Provenance of one successful catalog fetch, surfaced by the status card. */
|
|
270
|
+
interface WorkBuddyCatalogFetch {
|
|
271
|
+
fetchedAtMs: number;
|
|
272
|
+
/** Which document answered, e.g. `workbuddy-ai:app`. */
|
|
273
|
+
source: string;
|
|
274
|
+
/** UA version used, when the request needed one. */
|
|
275
|
+
appVersion?: AppVersionInfo;
|
|
276
|
+
}
|
|
277
|
+
/** Constructor dependencies. */
|
|
278
|
+
interface WorkBuddyUpstreamClientOptions {
|
|
279
|
+
/** App-version resolver for international catalog requests; injectable for tests. */
|
|
280
|
+
resolveAppVersion?: () => Promise<AppVersionInfo>;
|
|
281
|
+
}
|
|
127
282
|
/**
|
|
128
283
|
* Upstream HTTP client. One instance serves the whole plugin; requests take
|
|
129
284
|
* the credential explicitly so token refreshes apply on the next call.
|
|
285
|
+
*
|
|
286
|
+
* One instance is *per variant*: the international provider needs its own
|
|
287
|
+
* catalog source, UA version, and probe differences, and keeping them on the
|
|
288
|
+
* instance avoids passing a variant through every call signature.
|
|
130
289
|
*/
|
|
131
290
|
declare class WorkBuddyUpstreamClient {
|
|
291
|
+
/**
|
|
292
|
+
* Resolves the App-shaped UA version for international catalog requests.
|
|
293
|
+
* Injectable so tests never read the real filesystem.
|
|
294
|
+
*/
|
|
295
|
+
private readonly resolveAppVersion;
|
|
296
|
+
/** Provenance of the most recent successful catalog fetch, for the card. */
|
|
297
|
+
lastCatalog: WorkBuddyCatalogFetch | undefined;
|
|
298
|
+
constructor(options?: WorkBuddyUpstreamClientOptions);
|
|
132
299
|
/** POST the chat endpoint; a successful answer is the raw SSE response. */
|
|
133
300
|
chatStream(credential: WorkBuddyCredential, bodyJson: string, signal?: AbortSignal): Promise<WorkBuddyChatResult>;
|
|
134
301
|
/** POST the token-refresh endpoint; the caller merges the outcome. */
|
|
135
302
|
refreshToken(credential: WorkBuddyCredential): Promise<WorkBuddyRefreshOutcome>;
|
|
136
|
-
/**
|
|
137
|
-
|
|
303
|
+
/**
|
|
304
|
+
* GET the personal model catalog.
|
|
305
|
+
*
|
|
306
|
+
* Two upstream documents feed this, one per variant:
|
|
307
|
+
*
|
|
308
|
+
* - CN (`workbuddy`): `/console/enterprises/personal/models`, the document
|
|
309
|
+
* the official CLI itself consumes. Unchanged behaviour.
|
|
310
|
+
* - International (`workbuddy-ai`): `/v3/config`, the product document the
|
|
311
|
+
* App's main process fetches. The gateway splits it by User-Agent, so this
|
|
312
|
+
* request carries the App-shaped UA while every other request keeps the
|
|
313
|
+
* CLI UA it has always sent.
|
|
314
|
+
*
|
|
315
|
+
* Both are unwrapped and classified the same way — `readEnvelope` plus
|
|
316
|
+
* `envelopeError` — so an expired session or exhausted credit is reported as
|
|
317
|
+
* such rather than as a generic catalog failure.
|
|
318
|
+
*/
|
|
319
|
+
fetchModels(credential: WorkBuddyCredential, signal?: AbortSignal): Promise<readonly WorkBuddyUpstreamModel[]>;
|
|
138
320
|
/** POST the billing endpoint for the aggregated remaining credit. */
|
|
139
321
|
fetchCredits(credential: WorkBuddyCredential): Promise<WorkBuddyCredits>;
|
|
322
|
+
/**
|
|
323
|
+
* One probe request: a real streaming chat call carrying the effort under
|
|
324
|
+
* test.
|
|
325
|
+
*
|
|
326
|
+
* Shares `chatHeaders` with the normal chat path on purpose — the plan
|
|
327
|
+
* forbids probing through anything but the plugin's own credential handling,
|
|
328
|
+
* so a result describes what a real message would experience.
|
|
329
|
+
*
|
|
330
|
+
* The caller aborts as soon as a parseable event arrives; the body is never
|
|
331
|
+
* assembled into an answer. `reasoning_effort` is omitted entirely (rather
|
|
332
|
+
* than sent empty) when `effort` is undefined, so the baseline case is a
|
|
333
|
+
* genuinely bare request.
|
|
334
|
+
*
|
|
335
|
+
* Two international differences, both measured on 2026-09-11:
|
|
336
|
+
*
|
|
337
|
+
* - The gateway requires a leading `system` message (400/11128 otherwise), so
|
|
338
|
+
* one is prepended for the global region only.
|
|
339
|
+
* - `max_tokens: 1` is below some models' floor (the GPT-5.6 family rejects it
|
|
340
|
+
* with 400/11133 `integer_below_min_value`), so the international probe asks
|
|
341
|
+
* for a slightly larger minimum. This is a floor the plugin must clear, not
|
|
342
|
+
* evidence about any model's effort support: a model still refusing that
|
|
343
|
+
* minimum is reported as an incompatible request, never as "effort
|
|
344
|
+
* unsupported", and the ceiling is never raised further to force an answer.
|
|
345
|
+
*/
|
|
346
|
+
probeEffort(credential: WorkBuddyCredential, model: string, effort: string | undefined, signal: AbortSignal): Promise<ProbeAttempt>;
|
|
347
|
+
}
|
|
348
|
+
/** Parse either response shape after its envelope has been checked. */
|
|
349
|
+
declare function parseModelCatalog(data: Record<string, unknown>, international?: boolean): readonly WorkBuddyUpstreamModel[];
|
|
350
|
+
/**
|
|
351
|
+
* One verified promotion entry.
|
|
352
|
+
*
|
|
353
|
+
* Only the shape actually observed in the international App document is
|
|
354
|
+
* modelled — an enabled, time-boxed, `displayMode: "replace"` discount. An
|
|
355
|
+
* entry that does not match is dropped rather than guessed at: rendering a
|
|
356
|
+
* discount the plugin does not understand could understate what the user pays.
|
|
357
|
+
*/
|
|
358
|
+
interface WorkBuddyPromotion {
|
|
359
|
+
/** Window start, epoch ms, parsed from the document's offset timestamp. */
|
|
360
|
+
start: number;
|
|
361
|
+
/** Window end, epoch ms. */
|
|
362
|
+
end: number;
|
|
363
|
+
/** Badge text as the upstream wrote it, e.g. `Free now`. */
|
|
364
|
+
label: string;
|
|
365
|
+
/** Multiplier applied to the model's rate; `0` replaces it outright. */
|
|
366
|
+
factor: number;
|
|
367
|
+
/** Higher wins when several promotions cover one model. */
|
|
368
|
+
priority: number;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Re-evaluate a model's promotion against the current time.
|
|
372
|
+
*
|
|
373
|
+
* Promotions are time-boxed, and the catalog they arrive in is cached for the
|
|
374
|
+
* life of the process. Frozen at parse time, a cached "Free now" would keep
|
|
375
|
+
* claiming a discount after `validUntil` had passed, and would keep showing the
|
|
376
|
+
* pre-discount rate as the discounted one. Re-deriving on every read means the
|
|
377
|
+
* badge disappears on its own and the rate reverts, with no refresh needed.
|
|
378
|
+
*
|
|
379
|
+
* Non-destructive: the model's own `credits` and `badges` are the base, and the
|
|
380
|
+
* promotion is layered onto a copy. A model with no live promotion is returned
|
|
381
|
+
* as-is, so the common case allocates nothing.
|
|
382
|
+
*/
|
|
383
|
+
declare function modelWithCurrentPromotion(model: WorkBuddyUpstreamModel, now?: number): WorkBuddyUpstreamModel;
|
|
384
|
+
/**
|
|
385
|
+
* Apply the international endpoint's extra chat requirement: the first message
|
|
386
|
+
* must be a system prompt.
|
|
387
|
+
*
|
|
388
|
+
* The international gateway rejects a body whose first message is not `system`
|
|
389
|
+
* with HTTP 400 code 11128 ("first message is not system prompt"). Note that
|
|
390
|
+
* the *same* code means something else on the CN endpoint — there it reports a
|
|
391
|
+
* rejected `developer` role — so the two are never branched on by code alone.
|
|
392
|
+
*
|
|
393
|
+
* The added prompt is deliberately empty of user content and prepended, never
|
|
394
|
+
* merged: existing messages keep their order and wording. A body that is not a
|
|
395
|
+
* JSON object is returned unchanged, exactly as {@link prepareChatBody} does,
|
|
396
|
+
* so this is safe to run over an already-prepared-or-not body.
|
|
397
|
+
*/
|
|
398
|
+
declare function prepareInternationalChatBody(source: string): string;
|
|
399
|
+
//#endregion
|
|
400
|
+
//#region src/variants.d.ts
|
|
401
|
+
/** One WorkBuddy product variant. */
|
|
402
|
+
interface WorkBuddyVariant {
|
|
403
|
+
/** Provider id registered with DSH, e.g. `workbuddy-ai`. */
|
|
404
|
+
id: string;
|
|
405
|
+
/** Model-group heading and card title stem, e.g. `WorkBuddy AI`. */
|
|
406
|
+
displayName: string;
|
|
407
|
+
/** Desktop app name as users know it, for diagnostics and error copy. */
|
|
408
|
+
appName: string;
|
|
409
|
+
/** Which upstream region this variant's credentials must belong to. */
|
|
410
|
+
region: WorkBuddyRegion;
|
|
411
|
+
/** Env var overriding the desktop auth-file location. */
|
|
412
|
+
env: string;
|
|
413
|
+
/** Basename of the desktop app's own auth file in the shared auth directory. */
|
|
414
|
+
desktopFilename: string;
|
|
415
|
+
/** Basename of the plugin-owned credential copy under `$DSH_HOME`. */
|
|
416
|
+
ownFilename: string;
|
|
417
|
+
/** Basename of the plugin-owned probe-record file under `$DSH_HOME`. */
|
|
418
|
+
probeFilename: string;
|
|
419
|
+
/**
|
|
420
|
+
* Basename of the plugin-owned saved-catalog file under `$DSH_HOME`.
|
|
421
|
+
*
|
|
422
|
+
* One per variant, like the probe records: the two endpoints disagree about
|
|
423
|
+
* rates, windows, and even which models exist for a shared id, so a catalog
|
|
424
|
+
* saved from one must never be served as the other's.
|
|
425
|
+
*/
|
|
426
|
+
catalogFilename: string;
|
|
427
|
+
/** Same-origin status route consumed by this variant's card. */
|
|
428
|
+
statusPath: string;
|
|
429
|
+
/** Same-origin probe-control route consumed by this variant's card. */
|
|
430
|
+
probePath: string;
|
|
140
431
|
}
|
|
432
|
+
/** CN WorkBuddy first: the existing provider keeps its id, paths, and copy. */
|
|
433
|
+
declare const WORKBUDDY_VARIANTS: readonly WorkBuddyVariant[];
|
|
434
|
+
/** The CN variant; the plugin's long-standing default and compatibility anchor. */
|
|
435
|
+
declare const CN_VARIANT: WorkBuddyVariant;
|
|
436
|
+
/** The international variant. */
|
|
437
|
+
declare const AI_VARIANT: WorkBuddyVariant;
|
|
438
|
+
/** Look up a variant by provider id. */
|
|
439
|
+
declare function variantFor(id: string): WorkBuddyVariant | undefined;
|
|
141
440
|
//#endregion
|
|
142
441
|
//#region src/auth.d.ts
|
|
143
442
|
/** Normalized WorkBuddy credential, timestamps in epoch milliseconds. */
|
|
@@ -161,9 +460,16 @@ interface WorkBuddyAuthStatus {
|
|
|
161
460
|
nickname?: string;
|
|
162
461
|
domain?: string;
|
|
163
462
|
source?: 'desktop' | 'dsh';
|
|
463
|
+
/**
|
|
464
|
+
* Why no credential is usable, when the reason is diagnosable rather than
|
|
465
|
+
* "nobody is signed in" — a region mismatch being the case that matters.
|
|
466
|
+
* Present only on `signed-out`, and never a substitute for fixing the file.
|
|
467
|
+
*/
|
|
468
|
+
reason?: string;
|
|
164
469
|
}
|
|
165
470
|
/** Constructor options; only {@link refresh} is required. */
|
|
166
471
|
interface WorkBuddyStoreOptions {
|
|
472
|
+
variant?: WorkBuddyVariant;
|
|
167
473
|
/** Explicit desktop auth-file path, overriding env and platform defaults. */
|
|
168
474
|
desktopPath?: string;
|
|
169
475
|
/** Explicit plugin-owned copy path, defaulting under `$DSH_HOME`. */
|
|
@@ -187,8 +493,16 @@ declare function workbuddyOwnAuthPath(): string;
|
|
|
187
493
|
* native Linux location.
|
|
188
494
|
*/
|
|
189
495
|
declare function defaultDesktopAuthCandidates(): string[];
|
|
496
|
+
/**
|
|
497
|
+
* The platform-default candidates for one variant, in probe order.
|
|
498
|
+
*
|
|
499
|
+
* Both apps write into the *same* shared `CodeBuddyExtension` auth directory
|
|
500
|
+
* and differ only in the file's basename, so the per-platform ordering above
|
|
501
|
+
* is reused verbatim and just the filename is swapped.
|
|
502
|
+
*/
|
|
503
|
+
declare function desktopAuthCandidatesFor(variant: WorkBuddyVariant): string[];
|
|
190
504
|
/** First platform-default candidate; see {@link defaultDesktopAuthCandidates}. */
|
|
191
|
-
declare function defaultDesktopAuthPath(): string | undefined;
|
|
505
|
+
declare function defaultDesktopAuthPath(variant?: WorkBuddyVariant): string | undefined;
|
|
192
506
|
/**
|
|
193
507
|
* Parse a WorkBuddy auth document in either on-disk shape: the plugin OAuth
|
|
194
508
|
* nested form `{"auth":{...},"account":{...}}` and the flat panel form.
|
|
@@ -205,6 +519,7 @@ declare function parseWorkBuddyAuth(text: string): WorkBuddyCredential | undefin
|
|
|
205
519
|
* not take down a working session.
|
|
206
520
|
*/
|
|
207
521
|
declare class WorkBuddyCredentialStore {
|
|
522
|
+
private readonly variant;
|
|
208
523
|
private readonly refresh;
|
|
209
524
|
private readonly refreshMarginMs;
|
|
210
525
|
private readonly ownPath;
|
|
@@ -262,19 +577,165 @@ type WorkBuddyModelInfo = WorkBuddyUpstreamModel;
|
|
|
262
577
|
* registers with a usable catalog even while the first fetch is in flight or
|
|
263
578
|
* offline.
|
|
264
579
|
*
|
|
265
|
-
* The list tracks the `cli` agent's model roster exactly: the
|
|
580
|
+
* The list tracks the `cli` agent's model roster exactly: the 16 models the
|
|
266
581
|
* desktop CLI offers. Reasoning metadata is taken verbatim from the live
|
|
267
582
|
* endpoint — each model's supported effort set and whether thinking can be
|
|
268
583
|
* disabled — and the `free` flag follows the upstream `x0.00` credits marker.
|
|
269
584
|
*/
|
|
270
585
|
declare const FALLBACK_WORKBUDDY_MODELS: readonly WorkBuddyModelInfo[];
|
|
271
|
-
/**
|
|
586
|
+
/**
|
|
587
|
+
* Static CLI models for the international endpoint, captured 2026-09-11 from
|
|
588
|
+
* the App-form `/v3/config` document (the 20 ids of its `cli` agent, in order).
|
|
589
|
+
*
|
|
590
|
+
* Same purpose and same discipline as {@link FALLBACK_WORKBUDDY_MODELS}: it
|
|
591
|
+
* covers the window before the first successful fetch and an offline start,
|
|
592
|
+
* and it is deliberately *not* a promise about the upstream's current state.
|
|
593
|
+
* Reasoning metadata is verbatim from that snapshot. No promo badge is baked
|
|
594
|
+
* in: promotions are time-boxed (`modelPromotions` carries `validFrom`/
|
|
595
|
+
* `validUntil`), so hard-coding a "Free now" label would keep claiming a
|
|
596
|
+
* discount the upstream may have already ended.
|
|
597
|
+
*/
|
|
598
|
+
declare const FALLBACK_WORKBUDDY_AI_MODELS: readonly WorkBuddyModelInfo[];
|
|
599
|
+
/**
|
|
600
|
+
* Mutable catalog shared by the shim's `/v1/models` and the adapter.
|
|
601
|
+
*
|
|
602
|
+
* Visibility is separate from content. A variant whose app has no credentials
|
|
603
|
+
* must expose *no* models rather than a fallback roster: the DSH model picker
|
|
604
|
+
* drops an empty group, so an empty catalog is exactly how a provider hides
|
|
605
|
+
* without touching registration. Serving the fallback to a signed-out user
|
|
606
|
+
* instead offers models that can only fail (`store.resolve()` throws on the
|
|
607
|
+
* first message), which is worse than showing nothing.
|
|
608
|
+
*
|
|
609
|
+
* The flag defaults to visible so a directly-constructed catalog behaves as it
|
|
610
|
+
* always has; the plugin runtime applies the credential gate.
|
|
611
|
+
*/
|
|
272
612
|
declare class WorkBuddyCatalog {
|
|
273
613
|
private models;
|
|
274
|
-
|
|
614
|
+
private visible;
|
|
615
|
+
constructor(initial?: readonly WorkBuddyModelInfo[]);
|
|
616
|
+
/** Current entries; empty while the variant has no usable credential. */
|
|
275
617
|
current(): readonly WorkBuddyModelInfo[];
|
|
276
618
|
/** Replace the list; callers invalidate their adapter snapshot after this. */
|
|
277
619
|
set(models: readonly WorkBuddyModelInfo[]): void;
|
|
620
|
+
/** Whether this variant's models are exposed at all. */
|
|
621
|
+
isVisible(): boolean;
|
|
622
|
+
/**
|
|
623
|
+
* Show or hide the whole catalog. Returns whether the value changed, so the
|
|
624
|
+
* caller can skip an invalidation that would re-render an identical list.
|
|
625
|
+
*/
|
|
626
|
+
setVisible(visible: boolean): boolean;
|
|
627
|
+
/** Models to fall back to when the upstream fetch fails; ignores visibility. */
|
|
628
|
+
fallback(): readonly WorkBuddyModelInfo[];
|
|
629
|
+
}
|
|
630
|
+
//#endregion
|
|
631
|
+
//#region src/probe-store.d.ts
|
|
632
|
+
/** Basename of the probe record inside the Harness home. */
|
|
633
|
+
declare const WORKBUDDY_PROBE_FILENAME = ".workbuddy-probe.json";
|
|
634
|
+
/**
|
|
635
|
+
* Whether the model's effort parameter is actually validated.
|
|
636
|
+
*
|
|
637
|
+
* - `validating`: the upstream rejected an unknown sentinel value, so a
|
|
638
|
+
* per-level answer is meaningful.
|
|
639
|
+
* - `non-validating`: the upstream accepted the sentinel, so it ignores or
|
|
640
|
+
* loosely coerces the parameter and no per-level answer can be trusted.
|
|
641
|
+
* - `unknown`: baseline or sentinel failed for an unrelated reason (auth,
|
|
642
|
+
* rate limit, transport, ambiguous error body). Not a negative claim.
|
|
643
|
+
*/
|
|
644
|
+
type WorkBuddyProbeValidation = 'validating' | 'non-validating' | 'unknown';
|
|
645
|
+
/** One model's recorded observation. */
|
|
646
|
+
interface WorkBuddyProbeRecord {
|
|
647
|
+
/** Fingerprint of the catalog row this observation was made against. */
|
|
648
|
+
fingerprint: string;
|
|
649
|
+
validation: WorkBuddyProbeValidation;
|
|
650
|
+
/** Efforts verified as accepted; only ever non-empty for `validating`. */
|
|
651
|
+
efforts: readonly WorkBuddyEffort[];
|
|
652
|
+
/** When the probe ran, epoch milliseconds. */
|
|
653
|
+
probedAtMs: number;
|
|
654
|
+
/** Plugin version that produced the record. */
|
|
655
|
+
pluginVersion: string;
|
|
656
|
+
/**
|
|
657
|
+
* The account this observation was made under, as `uid:enterpriseId`.
|
|
658
|
+
*
|
|
659
|
+
* An effort set is a fact about one account's entitlement as much as about
|
|
660
|
+
* the model: the same model id can accept different levels under a different
|
|
661
|
+
* subscription. Without this a record outlived the account that produced it,
|
|
662
|
+
* so signing out and in as someone else inherited the previous account's
|
|
663
|
+
* detected levels. Records written before this field existed carry no
|
|
664
|
+
* identity and are therefore never reused.
|
|
665
|
+
*/
|
|
666
|
+
account?: string;
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Plugin-owned probe record path inside the Harness home.
|
|
670
|
+
*
|
|
671
|
+
* One file per variant. Same-named models exist on both endpoints (the
|
|
672
|
+
* international catalog repeats `glm-5.3`, `glm-5.2`, `hy3`, `kimi-k2.6`), and
|
|
673
|
+
* {@link fingerprintModel} covers only `id`/`reasoning`/`supportsImages` —
|
|
674
|
+
* never the provider — so a single shared file would let one variant's
|
|
675
|
+
* observation answer for the other. The paths differ; the format does not.
|
|
676
|
+
*/
|
|
677
|
+
declare function workbuddyProbePath(filename?: string): string;
|
|
678
|
+
/**
|
|
679
|
+
* Fingerprint the catalog fields a probe depends on.
|
|
680
|
+
*
|
|
681
|
+
* Deliberately excludes display-only fields (`name`, `billing`, `contextWindow`)
|
|
682
|
+
* so a rename or a promo badge does not throw away a valid observation, and
|
|
683
|
+
* deliberately includes the whole reasoning object so any change to the
|
|
684
|
+
* declared shape re-probes.
|
|
685
|
+
*/
|
|
686
|
+
declare function fingerprintModel(info: WorkBuddyModelInfo): string;
|
|
687
|
+
/** Options for {@link WorkBuddyProbeStore}. */
|
|
688
|
+
interface WorkBuddyProbeStoreOptions {
|
|
689
|
+
/** Explicit state-file path, overriding the `$DSH_HOME` default. */
|
|
690
|
+
path?: string;
|
|
691
|
+
/** Observation lifetime; defaults to 14 days. */
|
|
692
|
+
ttlMs?: number;
|
|
693
|
+
/** Plugin version stamped into new records. */
|
|
694
|
+
pluginVersion: string;
|
|
695
|
+
/** Clock injection for tests. */
|
|
696
|
+
now?: () => number;
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* The plugin's probe records: read once, written atomically, never trusted
|
|
700
|
+
* across a fingerprint change or past the TTL.
|
|
701
|
+
*/
|
|
702
|
+
declare class WorkBuddyProbeStore {
|
|
703
|
+
private readonly path;
|
|
704
|
+
private readonly ttlMs;
|
|
705
|
+
private readonly pluginVersion;
|
|
706
|
+
private readonly now;
|
|
707
|
+
private records;
|
|
708
|
+
constructor(options: WorkBuddyProbeStoreOptions | string);
|
|
709
|
+
/** Resolved state-file path, for the CLI and tests. */
|
|
710
|
+
filePath(): string;
|
|
711
|
+
private load;
|
|
712
|
+
/**
|
|
713
|
+
* The usable record for a model, or `undefined` when there is none, it is
|
|
714
|
+
* expired, it was taken against a different catalog row, or it belongs to a
|
|
715
|
+
* different account.
|
|
716
|
+
*
|
|
717
|
+
* @param account - the account in effect, as `uid:enterpriseId`. Records are
|
|
718
|
+
* only returned for the account that produced them.
|
|
719
|
+
*/
|
|
720
|
+
get(modelId: string, fingerprint: string, account: string): WorkBuddyProbeRecord | undefined;
|
|
721
|
+
/**
|
|
722
|
+
* Store one observation. Only a decisive answer (`validating` /
|
|
723
|
+
* `non-validating`) replaces an existing decisive record: a transient
|
|
724
|
+
* `unknown` must not erase knowledge the user already paid for.
|
|
725
|
+
*/
|
|
726
|
+
set(modelId: string, record: WorkBuddyProbeRecord): void;
|
|
727
|
+
/** Drop every record; used by the card's explicit "clear" action. */
|
|
728
|
+
clear(): void;
|
|
729
|
+
/** Every record currently held, for status display. */
|
|
730
|
+
all(): Readonly<Record<string, WorkBuddyProbeRecord>>;
|
|
731
|
+
/** Build a record stamped with this store's clock, version, and account. */
|
|
732
|
+
record(fingerprint: string, validation: WorkBuddyProbeValidation, efforts: readonly WorkBuddyEffort[], account: string): WorkBuddyProbeRecord;
|
|
733
|
+
/**
|
|
734
|
+
* Write through a temporary file and rename, so a crash mid-write cannot
|
|
735
|
+
* leave a half-parsed document that reads as "no records" and silently drops
|
|
736
|
+
* every observation.
|
|
737
|
+
*/
|
|
738
|
+
private persist;
|
|
278
739
|
}
|
|
279
740
|
//#endregion
|
|
280
741
|
//#region src/shim.d.ts
|
|
@@ -319,11 +780,18 @@ declare const WORKBUDDY_PROVIDER = "workbuddy";
|
|
|
319
780
|
declare const WORKBUDDY_STREAM_IDLE_TIMEOUT_MS = 300000;
|
|
320
781
|
/** Constructor dependencies. */
|
|
321
782
|
interface WorkBuddyAdapterOptions {
|
|
783
|
+
providerId?: string;
|
|
784
|
+
displayName?: string;
|
|
322
785
|
shim: WorkBuddyShim;
|
|
323
786
|
store: WorkBuddyCredentialStore;
|
|
324
787
|
catalog: WorkBuddyCatalog;
|
|
325
788
|
/** Resolve the durable attachment service at request time, when present. */
|
|
326
789
|
resolveAttachments?: () => AttachmentStore | undefined;
|
|
790
|
+
/**
|
|
791
|
+
* Look up a local probe observation for a model. Consulted only for rows the
|
|
792
|
+
* upstream left undeclared; absent means declared-set-only behavior.
|
|
793
|
+
*/
|
|
794
|
+
observe?: (modelId: string) => WorkBuddyProbeRecord | undefined;
|
|
327
795
|
}
|
|
328
796
|
/** What {@link createWorkBuddyAdapter} hands back. */
|
|
329
797
|
interface WorkBuddyAdapter {
|
|
@@ -345,6 +813,120 @@ interface WorkBuddyAdapter {
|
|
|
345
813
|
*/
|
|
346
814
|
declare function createWorkBuddyAdapter(options: WorkBuddyAdapterOptions): WorkBuddyAdapter;
|
|
347
815
|
//#endregion
|
|
816
|
+
//#region src/catalog-store.d.ts
|
|
817
|
+
/** Basename of the CN variant's saved catalog inside the Harness home. */
|
|
818
|
+
declare const WORKBUDDY_CATALOG_FILENAME = ".workbuddy-catalog.json";
|
|
819
|
+
/** One saved catalog: the account it belonged to, and the models it listed. */
|
|
820
|
+
interface SavedCatalog {
|
|
821
|
+
/** `uid:enterpriseId` the catalog was fetched for. */
|
|
822
|
+
account: string;
|
|
823
|
+
/** Which document answered, so a CN roster is never served as an AI one. */
|
|
824
|
+
source: string;
|
|
825
|
+
/** When the fetch succeeded, epoch milliseconds. */
|
|
826
|
+
fetchedAtMs: number;
|
|
827
|
+
models: readonly WorkBuddyUpstreamModel[];
|
|
828
|
+
/** App version used as the UA, when the variant needed one. */
|
|
829
|
+
appVersion?: string;
|
|
830
|
+
}
|
|
831
|
+
/** Plugin-owned saved-catalog path inside the Harness home. */
|
|
832
|
+
declare function workbuddyCatalogPath(filename?: string): string;
|
|
833
|
+
/** Options for {@link WorkBuddyCatalogStore}. */
|
|
834
|
+
interface WorkBuddyCatalogStoreOptions {
|
|
835
|
+
/** Explicit state-file path, overriding the `$DSH_HOME` default. */
|
|
836
|
+
path?: string;
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* The last successful catalog per account, read once and written atomically.
|
|
840
|
+
*
|
|
841
|
+
* Malformed content reads as "nothing saved" rather than throwing: this file
|
|
842
|
+
* is an optimization for the offline and first-seconds cases, and a corrupt one
|
|
843
|
+
* must never be able to stop the plugin from serving models.
|
|
844
|
+
*/
|
|
845
|
+
declare class WorkBuddyCatalogStore {
|
|
846
|
+
private readonly path;
|
|
847
|
+
private entries;
|
|
848
|
+
constructor(options?: WorkBuddyCatalogStoreOptions | string);
|
|
849
|
+
/** Resolved state-file path, for the CLI and tests. */
|
|
850
|
+
filePath(): string;
|
|
851
|
+
private load;
|
|
852
|
+
/** The saved catalog for one account, or `undefined` when there is none. */
|
|
853
|
+
get(account: string): SavedCatalog | undefined;
|
|
854
|
+
/**
|
|
855
|
+
* Remember a catalog for an account, replacing whatever was saved before.
|
|
856
|
+
*
|
|
857
|
+
* A failed write is swallowed: the plugin has already served these models,
|
|
858
|
+
* and losing the *memory* of them is not worth surfacing.
|
|
859
|
+
*/
|
|
860
|
+
set(account: string, catalog: Omit<SavedCatalog, 'account'>): void;
|
|
861
|
+
/** Forget one account's catalog — used when that account signs out. */
|
|
862
|
+
delete(account: string): void;
|
|
863
|
+
private persist;
|
|
864
|
+
}
|
|
865
|
+
//#endregion
|
|
866
|
+
//#region src/probe-service.d.ts
|
|
867
|
+
/** What the caller learns about a completed probe. */
|
|
868
|
+
type WorkBuddyProbeStatus = {
|
|
869
|
+
state: 'ok';
|
|
870
|
+
validation: WorkBuddyProbeRecord['validation'];
|
|
871
|
+
efforts: readonly string[];
|
|
872
|
+
requests: number;
|
|
873
|
+
} | {
|
|
874
|
+
state: 'unavailable';
|
|
875
|
+
reason: string;
|
|
876
|
+
};
|
|
877
|
+
/** Options for {@link WorkBuddyProbeService}. */
|
|
878
|
+
interface WorkBuddyProbeServiceOptions {
|
|
879
|
+
store: WorkBuddyProbeStore;
|
|
880
|
+
catalog: WorkBuddyCatalog;
|
|
881
|
+
credentials: WorkBuddyCredentialStore;
|
|
882
|
+
client: WorkBuddyUpstreamClient;
|
|
883
|
+
/** Whether probing is permitted at all; consulted before every sweep. */
|
|
884
|
+
consent: () => boolean;
|
|
885
|
+
/**
|
|
886
|
+
* The account currently in effect, as `uid:enterpriseId`, or `undefined`
|
|
887
|
+
* while signed out.
|
|
888
|
+
*
|
|
889
|
+
* Records are read and written against this identity, and it is re-checked
|
|
890
|
+
* after the sweep finishes: an observation produced under account A must not
|
|
891
|
+
* be stored once account B is in effect, however long the probe took. The
|
|
892
|
+
* caller's `clear()` on an account switch is not sufficient on its own,
|
|
893
|
+
* because an in-flight probe completes *after* that clear.
|
|
894
|
+
*/
|
|
895
|
+
account: () => string | undefined;
|
|
896
|
+
sentinel?: SentinelFactory;
|
|
897
|
+
/** Injectable for tests; defaults to the live upstream sender. */
|
|
898
|
+
send?: (modelId: string) => ProbeSender;
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* Serial probe runner. One instance is shared by the manual API and any
|
|
902
|
+
* future automatic trigger, so the two can never overlap.
|
|
903
|
+
*/
|
|
904
|
+
declare class WorkBuddyProbeService {
|
|
905
|
+
private readonly options;
|
|
906
|
+
private queue;
|
|
907
|
+
private readonly pending;
|
|
908
|
+
private running;
|
|
909
|
+
constructor(options: WorkBuddyProbeServiceOptions);
|
|
910
|
+
/** Whether a sweep is in flight right now. */
|
|
911
|
+
isRunning(): boolean;
|
|
912
|
+
/**
|
|
913
|
+
* The record the adapter may use for this model, or `undefined`.
|
|
914
|
+
*
|
|
915
|
+
* Applies the plan's precedence (§5): a declared set always wins, so a model
|
|
916
|
+
* that declares `supportedEfforts` is never answered from an observation.
|
|
917
|
+
*/
|
|
918
|
+
recordFor(modelId: string): WorkBuddyProbeRecord | undefined;
|
|
919
|
+
/**
|
|
920
|
+
* Probe one model, serially.
|
|
921
|
+
*
|
|
922
|
+
* The authenticated manual route supplies one-request consent after UI
|
|
923
|
+
* confirmation. Other callers must pass the configured consent gate.
|
|
924
|
+
* Manual consent never changes the automatic-probing configuration.
|
|
925
|
+
* Explicit requests bypass historical results, but share an ongoing run.
|
|
926
|
+
*/
|
|
927
|
+
probe(modelId: string, manualConsent?: boolean): Promise<WorkBuddyProbeStatus>;
|
|
928
|
+
}
|
|
929
|
+
//#endregion
|
|
348
930
|
//#region src/host-heartbeat.d.ts
|
|
349
931
|
/**
|
|
350
932
|
* Host-side heartbeat: a small JSON file written under `$DSH_HOME` once the
|
|
@@ -416,7 +998,7 @@ declare const name = "llm-workbuddy";
|
|
|
416
998
|
/** The model registry required before the provider can register. */
|
|
417
999
|
declare const inject: string[];
|
|
418
1000
|
/**
|
|
419
|
-
* Settings namespace owning the
|
|
1001
|
+
* Settings namespace owning the CN card's section.
|
|
420
1002
|
*
|
|
421
1003
|
* DSH 0.1.2 dropped the `settingsNamespace()` branding function: a namespace is
|
|
422
1004
|
* now a nominal string, validated by the type system where it is used rather
|
|
@@ -428,18 +1010,42 @@ declare const inject: string[];
|
|
|
428
1010
|
* their namespaces as plain string literals).
|
|
429
1011
|
*/
|
|
430
1012
|
declare const WORKBUDDY_SETTINGS_NS: SettingsNamespace;
|
|
1013
|
+
/**
|
|
1014
|
+
* Settings namespace owning the international card's section.
|
|
1015
|
+
*
|
|
1016
|
+
* One namespace per card, not one shared: the settings Plugins tab dispatches a
|
|
1017
|
+
* card by rendering `settings.plugin.item` with `entryKey = ns` for each
|
|
1018
|
+
* namespace the Host serves, and skips an entry whose key names no served
|
|
1019
|
+
* namespace. With a single installed section, the international card registers
|
|
1020
|
+
* into the slot but is never rendered — the card list is built from the Host's
|
|
1021
|
+
* sections, not from the slot's entries. Each card therefore needs its own
|
|
1022
|
+
* installed section whose namespace equals the card's slot key.
|
|
1023
|
+
*/
|
|
1024
|
+
declare const WORKBUDDY_AI_SETTINGS_NS: SettingsNamespace;
|
|
431
1025
|
/** Plugin configuration. */
|
|
432
1026
|
interface Config {
|
|
433
|
-
/** Explicit WorkBuddy desktop auth-file path, overriding env and platform defaults. */
|
|
1027
|
+
/** Explicit WorkBuddy (CN) desktop auth-file path, overriding env and platform defaults. */
|
|
434
1028
|
authFile?: string;
|
|
1029
|
+
/** Explicit WorkBuddy AI (international) desktop auth-file path, overriding env and platform defaults. */
|
|
1030
|
+
authFileAI?: string;
|
|
1031
|
+
/**
|
|
1032
|
+
* Whether the user has authorized sending probe requests about reasoning
|
|
1033
|
+
* efforts. Off by default: a probe spends real credit, so nothing is sent
|
|
1034
|
+
* until the user explicitly agrees.
|
|
1035
|
+
*/
|
|
1036
|
+
probeConsent?: boolean;
|
|
435
1037
|
}
|
|
436
1038
|
declare const Config: z<Config>;
|
|
437
1039
|
/**
|
|
438
|
-
* Start
|
|
439
|
-
*
|
|
440
|
-
*
|
|
441
|
-
*
|
|
1040
|
+
* Start both variants: their loopback endpoints, the `workbuddy` and
|
|
1041
|
+
* `workbuddy-ai` providers, their configuration cards, and their
|
|
1042
|
+
* credential-driven catalog lifecycles.
|
|
1043
|
+
*
|
|
1044
|
+
* Each variant registers unconditionally; what varies is whether its catalog is
|
|
1045
|
+
* *visible*. An empty catalog is how DSH hides a model group (the host filters
|
|
1046
|
+
* out groups with no models), which keeps a sign-in that happens after startup
|
|
1047
|
+
* working without re-registering the provider.
|
|
442
1048
|
*/
|
|
443
1049
|
declare function apply(ctx: Context, config: Config): void;
|
|
444
1050
|
//#endregion
|
|
445
|
-
export { Config, FALLBACK_WORKBUDDY_MODELS, type UpstreamErrorKind, WORKBUDDY_AUTH_FILENAME, WORKBUDDY_AUTH_FILE_ENV, WORKBUDDY_HOST_HEARTBEAT_FILENAME, WORKBUDDY_PROVIDER, WORKBUDDY_SETTINGS_NS, WORKBUDDY_STREAM_IDLE_TIMEOUT_MS, type WorkBuddyAdapter, type WorkBuddyAuthStatus, WorkBuddyCatalog, type WorkBuddyChatResult, type WorkBuddyCredential, WorkBuddyCredentialStore, type WorkBuddyCredits, type WorkBuddyEffort, type WorkBuddyHostHeartbeat, type WorkBuddyModelBilling, type WorkBuddyModelInfo, type WorkBuddyModelReasoning, type WorkBuddyRefreshOutcome, type WorkBuddyShim, WorkBuddyUpstreamClient, type WorkBuddyUpstreamModel, apply, classifyUpstreamError, clearHostHeartbeat, createWorkBuddyAdapter, createWorkBuddyShim, defaultDesktopAuthCandidates, defaultDesktopAuthPath, inject, isHeartbeatProcessAlive, name, normalizeCredits, parseWorkBuddyAuth, prepareChatBody, processStartTimeMs, readHostHeartbeat, regionOf, workbuddyHostHeartbeatPath, workbuddyOwnAuthPath };
|
|
1051
|
+
export { AI_VARIANT, type AppVersionInfo, CN_VARIANT, Config, FALLBACK_WORKBUDDY_AI_MODELS, FALLBACK_WORKBUDDY_MODELS, PROBE_EFFORT_CANDIDATES, type ProbeAttempt, type ProbeOutcome, type ProbeSender, type UpstreamErrorKind, WORKBUDDY_AI_SETTINGS_NS, WORKBUDDY_APP_VERSION_FILENAME, WORKBUDDY_AUTH_FILENAME, WORKBUDDY_AUTH_FILE_ENV, WORKBUDDY_CATALOG_FILENAME, WORKBUDDY_HOST_HEARTBEAT_FILENAME, WORKBUDDY_PROBE_FILENAME, WORKBUDDY_PROVIDER, WORKBUDDY_SETTINGS_NS, WORKBUDDY_STREAM_IDLE_TIMEOUT_MS, WORKBUDDY_VARIANTS, type WorkBuddyAdapter, type WorkBuddyAppVersionSource, type WorkBuddyAuthStatus, WorkBuddyCatalog, type WorkBuddyCatalogFetch, WorkBuddyCatalogStore, type WorkBuddyChatResult, type WorkBuddyCredential, WorkBuddyCredentialStore, type WorkBuddyCredits, type WorkBuddyEffort, type WorkBuddyHostHeartbeat, type WorkBuddyModelBilling, type WorkBuddyModelInfo, type WorkBuddyModelReasoning, type WorkBuddyProbeRecord, WorkBuddyProbeService, type WorkBuddyProbeStatus, WorkBuddyProbeStore, type WorkBuddyProbeValidation, type WorkBuddyPromotion, type WorkBuddyRefreshOutcome, type WorkBuddyShim, WorkBuddyUpstreamClient, type WorkBuddyUpstreamModel, type WorkBuddyVariant, appUserAgent, apply, classifyUpstreamError, clearHostHeartbeat, createWorkBuddyAdapter, createWorkBuddyShim, defaultDesktopAuthCandidates, defaultDesktopAuthPath, desktopAuthCandidatesFor, fingerprintModel, inject, installedAppVersion, isHeartbeatProcessAlive, modelWithCurrentPromotion, name, normalizeCredits, parseModelCatalog, parseWorkBuddyAuth, prepareChatBody, prepareInternationalChatBody, probeModel, processStartTimeMs, randomSentinel, readBundleVersion, readHostHeartbeat, regionOf, resolveAppVersion, validAppVersion, variantFor, workbuddyCatalogPath, workbuddyHostHeartbeatPath, workbuddyOwnAuthPath, workbuddyProbePath };
|