dsh-workbuddy-bridge 0.3.0 → 0.3.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.
@@ -2342,6 +2342,107 @@ function discoveryIncomplete(detail) {
2342
2342
  const HELPER_SCRIPT = "process.stdout.write(String(process._linkedBinding(\"electron_browser_workbuddy_storage\").loggerGet()))";
2343
2343
  const HELPER_SCRIPT_ARGUMENT_FLAG = "-e";
2344
2344
  //#endregion
2345
+ //#region src/shared/paths.ts
2346
+ /** Node-free constants and types shared by the Host and browser halves. */
2347
+ /** Plugin-owned status endpoint consumed by its browser half. */
2348
+ const WORKBUDDY_STATUS_PATH = "/plugins/dsh-workbuddy-bridge/status";
2349
+ /**
2350
+ * Plugin-owned probe control endpoint.
2351
+ *
2352
+ * Separate from the status route because it accepts writes: the status route's
2353
+ * loopback Host/Origin guard protects against a DNS-rebinding *page*, which is
2354
+ * not the same as authorizing a state-changing action. This route therefore
2355
+ * also requires the in-memory key the browser half receives with the status
2356
+ * document.
2357
+ */
2358
+ const WORKBUDDY_PROBE_PATH = "/plugins/dsh-workbuddy-bridge/probe";
2359
+ /**
2360
+ * The international (WorkBuddy AI) variant's own pair of routes.
2361
+ *
2362
+ * Kept as separate constants rather than a computed suffix so both halves
2363
+ * reference literal strings: the browser bundle and the host bundle are built
2364
+ * independently, and a shared expression is one build-config drift away from
2365
+ * the desk asking a route the host never mounted.
2366
+ */
2367
+ const WORKBUDDY_AI_STATUS_PATH = "/plugins/dsh-workbuddy-bridge/ai/status";
2368
+ const WORKBUDDY_AI_PROBE_PATH = "/plugins/dsh-workbuddy-bridge/ai/probe";
2369
+ /**
2370
+ * Plugin-owned per-message credit route.
2371
+ *
2372
+ * A read-only GET taking `?sessionId=…`, answering `messageId → credit` for one
2373
+ * Session. It is its own route rather than a field of the status document
2374
+ * because the two have different lifetimes: the status document is per
2375
+ * *account* and is re-read when the account changes, while credit accounting
2376
+ * is per *Session* and grows as messages are sent.
2377
+ *
2378
+ * **One route for both variants, on purpose.** The accounting is attributed to
2379
+ * a DSH `messageId` before it is stored, and a message id belongs to one
2380
+ * Session regardless of which provider served it — a conversation can switch
2381
+ * between the two WorkBuddy products (or away from both) mid-thread. A route
2382
+ * per variant would force the message row to know which provider answered a
2383
+ * message *it is merely labelling*, and would strand every message whose turn
2384
+ * ran under the other variant.
2385
+ *
2386
+ * No key is required: the route only reads what this plugin already observed on
2387
+ * its own loopback stream, carries no credential material, and answers loopback
2388
+ * requests through the same Host/Origin guard as the status route.
2389
+ */
2390
+ const WORKBUDDY_CREDIT_PATH = "/plugins/dsh-workbuddy-bridge/credit";
2391
+ //#endregion
2392
+ //#region src/variants.ts
2393
+ /**
2394
+ * The two WorkBuddy desktop apps this one plugin serves.
2395
+ *
2396
+ * Both products are the same client framework in different regions, and both
2397
+ * write their sign-in into the *same* shared `CodeBuddyExtension` auth
2398
+ * directory — they differ by file basename, base URL, catalog endpoint, and
2399
+ * display identity. Everything that varies between them is collected here as
2400
+ * one descriptor, so no module has to carry its own `if (international)`
2401
+ * branch and a third variant would be a data change rather than a refactor.
2402
+ *
2403
+ * This module is host-side (it names files and env vars). The browser half
2404
+ * takes the same ids and routes from the Node-free `status-paths.ts`, which
2405
+ * stays the single source shared by both halves.
2406
+ *
2407
+ * @module dsh-workbuddy-bridge/variants
2408
+ */
2409
+ /** CN WorkBuddy first: the existing provider keeps its id, paths, and copy. */
2410
+ const WORKBUDDY_VARIANTS = [{
2411
+ id: "workbuddy",
2412
+ displayName: "WorkBuddy",
2413
+ appName: "WorkBuddy",
2414
+ region: "cn",
2415
+ env: "WORKBUDDY_AUTH_FILE",
2416
+ desktopFilename: "workbuddy-desktop.info",
2417
+ ownFilename: ".workbuddy-auth.json",
2418
+ probeFilename: ".workbuddy-probe.json",
2419
+ catalogFilename: ".workbuddy-catalog.json",
2420
+ visibilityFilename: ".workbuddy-model-visibility.json",
2421
+ statusPath: WORKBUDDY_STATUS_PATH,
2422
+ probePath: WORKBUDDY_PROBE_PATH
2423
+ }, {
2424
+ id: "workbuddy-ai",
2425
+ displayName: "WorkBuddy AI",
2426
+ appName: "WorkBuddy AI",
2427
+ region: "global",
2428
+ env: "WORKBUDDY_AI_AUTH_FILE",
2429
+ desktopFilename: "workbuddy-desktop-ai.info",
2430
+ ownFilename: ".workbuddy-ai-auth.json",
2431
+ probeFilename: ".workbuddy-ai-probe.json",
2432
+ catalogFilename: ".workbuddy-ai-catalog.json",
2433
+ visibilityFilename: ".workbuddy-ai-model-visibility.json",
2434
+ statusPath: WORKBUDDY_AI_STATUS_PATH,
2435
+ probePath: WORKBUDDY_AI_PROBE_PATH
2436
+ }];
2437
+ /** The CN variant; the plugin's long-standing default and compatibility anchor. */
2438
+ const CN_VARIANT = WORKBUDDY_VARIANTS[0];
2439
+ /** The international variant. */
2440
+ const AI_VARIANT = WORKBUDDY_VARIANTS[1];
2441
+ /** Look up a variant by provider id. */
2442
+ function variantFor(id) {
2443
+ return WORKBUDDY_VARIANTS.find((variant) => variant.id === id);
2444
+ }
2445
+ //#endregion
2345
2446
  //#region src/credential/store.ts
2346
2447
  /**
2347
2448
  * WorkBuddy credential resolution. The primary source is the WorkBuddy
@@ -2528,6 +2629,38 @@ function isENOENT(error) {
2528
2629
  return error?.code === "ENOENT";
2529
2630
  }
2530
2631
  /**
2632
+ * Which automatic at-rest key discovery this store may run, by variant.
2633
+ *
2634
+ * **One home for a rule that had three.** The choice used to be made at every
2635
+ * call site — `src/index.ts` and `src/cli/bin.ts` each spelled out
2636
+ * `discovery: variant.id === CN_VARIANT.id ? cnAppDiscovery() : 'none'` — and the
2637
+ * store's own default was a bare `new WorkBuddyAtRestKeyProvider()`, whose
2638
+ * discovery is `'none'`. So a caller that did neither got a provider that could
2639
+ * never open an encrypted credential: `scripts/live-e2e.mjs` was exactly that
2640
+ * caller, and it failed with `electron-binary-unavailable` on every platform
2641
+ * (2026-10-03, found by the release checklist). The store knows its variant, so
2642
+ * the choice belongs here.
2643
+ *
2644
+ * Why the difference is deliberate:
2645
+ *
2646
+ * - Only the CN WorkBuddy install has been verified to hold the key its envelopes
2647
+ * name, and only its macOS/Windows layout is known, so CN may look for the app.
2648
+ * - A Global (WorkBuddy AI) encrypted credential has never been seen live, so that
2649
+ * variant runs at `'none'` — no default path and no app search. A Global unlock
2650
+ * must not silently execute the *CN* app's Electron. An explicit
2651
+ * `WORKBUDDY_ELECTRON_BIN` still works for Global.
2652
+ *
2653
+ * **No variant** means the CN product's own default file —
2654
+ * `defaultDesktopAuthCandidates()` is the `workbuddy-desktop.info` path, never the
2655
+ * AI one — so it gets the same discovery CN does.
2656
+ *
2657
+ * A keyId mismatch is still reported as a diagnosis rather than a wrong open, and
2658
+ * the helper only runs if an encrypted credential is actually read.
2659
+ */
2660
+ function atRestDiscoveryFor(variant) {
2661
+ return variant === void 0 || variant.id === CN_VARIANT.id ? cnAppDiscovery() : "none";
2662
+ }
2663
+ /**
2531
2664
  * Read-only credential store with demand-driven refresh.
2532
2665
  *
2533
2666
  * Refresh policy: refresh only when the access token is inside the margin
@@ -2549,7 +2682,7 @@ var WorkBuddyCredentialStore = class {
2549
2682
  this.refresh = options.refresh;
2550
2683
  this.refreshMarginMs = options.refreshMarginMs ?? 3e5;
2551
2684
  this.ownPath = options.ownPath ?? (options.variant ? join(resolveDshHome(), options.variant.ownFilename) : workbuddyOwnAuthPath());
2552
- this.keyProvider = options.keyProvider ?? new WorkBuddyAtRestKeyProvider();
2685
+ this.keyProvider = options.keyProvider ?? new WorkBuddyAtRestKeyProvider({ discovery: atRestDiscoveryFor(options.variant) });
2553
2686
  this.desktopPathOverride = options.desktopPath;
2554
2687
  }
2555
2688
  /**
@@ -2624,6 +2757,7 @@ var WorkBuddyCredentialStore = class {
2624
2757
  expiresAtMs: credential.expiresAtMs,
2625
2758
  ...credential.refreshExpiresAtMs === void 0 ? {} : { refreshExpiresAtMs: credential.refreshExpiresAtMs },
2626
2759
  ...credential.nickname === void 0 ? {} : { nickname: credential.nickname },
2760
+ ...credential.uid === "" ? {} : { uid: credential.uid },
2627
2761
  ...credential.domain === "" ? {} : { domain: credential.domain },
2628
2762
  source: credential.source
2629
2763
  };
@@ -3553,55 +3687,8 @@ var WorkBuddyCatalog = class {
3553
3687
  }
3554
3688
  };
3555
3689
  //#endregion
3556
- //#region src/shared/paths.ts
3557
- /** Node-free constants and types shared by the Host and browser halves. */
3558
- /** Plugin-owned status endpoint consumed by its browser half. */
3559
- const WORKBUDDY_STATUS_PATH = "/plugins/dsh-workbuddy-bridge/status";
3560
- /**
3561
- * Plugin-owned probe control endpoint.
3562
- *
3563
- * Separate from the status route because it accepts writes: the status route's
3564
- * loopback Host/Origin guard protects against a DNS-rebinding *page*, which is
3565
- * not the same as authorizing a state-changing action. This route therefore
3566
- * also requires the in-memory key the browser half receives with the status
3567
- * document.
3568
- */
3569
- const WORKBUDDY_PROBE_PATH = "/plugins/dsh-workbuddy-bridge/probe";
3570
- /**
3571
- * The international (WorkBuddy AI) variant's own pair of routes.
3572
- *
3573
- * Kept as separate constants rather than a computed suffix so both halves
3574
- * reference literal strings: the browser bundle and the host bundle are built
3575
- * independently, and a shared expression is one build-config drift away from
3576
- * the desk asking a route the host never mounted.
3577
- */
3578
- const WORKBUDDY_AI_STATUS_PATH = "/plugins/dsh-workbuddy-bridge/ai/status";
3579
- const WORKBUDDY_AI_PROBE_PATH = "/plugins/dsh-workbuddy-bridge/ai/probe";
3580
- /**
3581
- * Plugin-owned per-message credit route.
3582
- *
3583
- * A read-only GET taking `?sessionId=…`, answering `messageId → credit` for one
3584
- * Session. It is its own route rather than a field of the status document
3585
- * because the two have different lifetimes: the status document is per
3586
- * *account* and is re-read when the account changes, while credit accounting
3587
- * is per *Session* and grows as messages are sent.
3588
- *
3589
- * **One route for both variants, on purpose.** The accounting is attributed to
3590
- * a DSH `messageId` before it is stored, and a message id belongs to one
3591
- * Session regardless of which provider served it — a conversation can switch
3592
- * between the two WorkBuddy products (or away from both) mid-thread. A route
3593
- * per variant would force the message row to know which provider answered a
3594
- * message *it is merely labelling*, and would strand every message whose turn
3595
- * ran under the other variant.
3596
- *
3597
- * No key is required: the route only reads what this plugin already observed on
3598
- * its own loopback stream, carries no credential material, and answers loopback
3599
- * requests through the same Host/Origin guard as the status route.
3600
- */
3601
- const WORKBUDDY_CREDIT_PATH = "/plugins/dsh-workbuddy-bridge/credit";
3602
- //#endregion
3603
3690
  //#region src/version.ts
3604
- const WORKBUDDY_BRIDGE_VERSION = "0.3.0";
3691
+ const WORKBUDDY_BRIDGE_VERSION = "0.3.1";
3605
3692
  //#endregion
3606
3693
  //#region src/web/heartbeat.ts
3607
3694
  /**
@@ -3772,58 +3859,4 @@ function isHeartbeatProcessAlive(heartbeat) {
3772
3859
  return startAtMs <= heartbeat.registeredAt;
3773
3860
  }
3774
3861
  //#endregion
3775
- //#region src/variants.ts
3776
- /**
3777
- * The two WorkBuddy desktop apps this one plugin serves.
3778
- *
3779
- * Both products are the same client framework in different regions, and both
3780
- * write their sign-in into the *same* shared `CodeBuddyExtension` auth
3781
- * directory — they differ by file basename, base URL, catalog endpoint, and
3782
- * display identity. Everything that varies between them is collected here as
3783
- * one descriptor, so no module has to carry its own `if (international)`
3784
- * branch and a third variant would be a data change rather than a refactor.
3785
- *
3786
- * This module is host-side (it names files and env vars). The browser half
3787
- * takes the same ids and routes from the Node-free `status-paths.ts`, which
3788
- * stays the single source shared by both halves.
3789
- *
3790
- * @module dsh-workbuddy-bridge/variants
3791
- */
3792
- /** CN WorkBuddy first: the existing provider keeps its id, paths, and copy. */
3793
- const WORKBUDDY_VARIANTS = [{
3794
- id: "workbuddy",
3795
- displayName: "WorkBuddy",
3796
- appName: "WorkBuddy",
3797
- region: "cn",
3798
- env: "WORKBUDDY_AUTH_FILE",
3799
- desktopFilename: "workbuddy-desktop.info",
3800
- ownFilename: ".workbuddy-auth.json",
3801
- probeFilename: ".workbuddy-probe.json",
3802
- catalogFilename: ".workbuddy-catalog.json",
3803
- visibilityFilename: ".workbuddy-model-visibility.json",
3804
- statusPath: WORKBUDDY_STATUS_PATH,
3805
- probePath: WORKBUDDY_PROBE_PATH
3806
- }, {
3807
- id: "workbuddy-ai",
3808
- displayName: "WorkBuddy AI",
3809
- appName: "WorkBuddy AI",
3810
- region: "global",
3811
- env: "WORKBUDDY_AI_AUTH_FILE",
3812
- desktopFilename: "workbuddy-desktop-ai.info",
3813
- ownFilename: ".workbuddy-ai-auth.json",
3814
- probeFilename: ".workbuddy-ai-probe.json",
3815
- catalogFilename: ".workbuddy-ai-catalog.json",
3816
- visibilityFilename: ".workbuddy-ai-model-visibility.json",
3817
- statusPath: WORKBUDDY_AI_STATUS_PATH,
3818
- probePath: WORKBUDDY_AI_PROBE_PATH
3819
- }];
3820
- /** The CN variant; the plugin's long-standing default and compatibility anchor. */
3821
- const CN_VARIANT = WORKBUDDY_VARIANTS[0];
3822
- /** The international variant. */
3823
- const AI_VARIANT = WORKBUDDY_VARIANTS[1];
3824
- /** Look up a variant by provider id. */
3825
- function variantFor(id) {
3826
- return WORKBUDDY_VARIANTS.find((variant) => variant.id === id);
3827
- }
3828
- //#endregion
3829
- export { modelWithCurrentPromotion as A, CN_APP_VERSION_FILENAME as B, defaultDesktopAuthPath as C, WorkBuddyAtRestKeyProvider as D, workbuddyOwnAuthPath as E, regionOf as F, resolveChatIdentity as G, chatUserAgent as H, PROBE_EFFORT_CANDIDATES as I, appUserAgent as J, validCliVersion as K, probeModel as L, parseModelCatalog as M, prepareChatBody as N, cnAppDiscovery as O, prepareInternationalChatBody as P, validAppVersion as Q, randomSentinel as R, defaultDesktopAuthCandidates as S, parseWorkBuddyAuth as T, fallbackChatIdentity as U, FALLBACK_CN_APP_VERSION as V, readCliVersion as W, readBundleVersion as X, installedAppVersion as Y, resolveAppVersion as Z, FALLBACK_WORKBUDDY_MODELS as _, WORKBUDDY_HOST_HEARTBEAT_FILENAME as a, WORKBUDDY_AUTH_FILE_ENV as b, processStartTimeMs as c, writeHostHeartbeat as d, WORKBUDDY_BRIDGE_VERSION as f, FALLBACK_WORKBUDDY_AI_MODELS as g, WORKBUDDY_STATUS_PATH as h, variantFor as i, normalizeCredits as j, WorkBuddyUpstreamClient as k, readHostHeartbeat as l, WORKBUDDY_PROBE_PATH as m, CN_VARIANT as n, clearHostHeartbeat as o, WORKBUDDY_CREDIT_PATH as p, WORKBUDDY_APP_VERSION_FILENAME as q, WORKBUDDY_VARIANTS as r, isHeartbeatProcessAlive as s, AI_VARIANT as t, workbuddyHostHeartbeatPath as u, WorkBuddyCatalog as v, desktopAuthCandidatesFor as w, WorkBuddyCredentialStore as x, WORKBUDDY_AUTH_FILENAME as y, classifyUpstreamError as z };
3862
+ export { parseModelCatalog as A, chatUserAgent as B, variantFor as C, WorkBuddyUpstreamClient as D, WORKBUDDY_STATUS_PATH as E, probeModel as F, WORKBUDDY_APP_VERSION_FILENAME as G, readCliVersion as H, randomSentinel as I, readBundleVersion as J, appUserAgent as K, classifyUpstreamError as L, prepareInternationalChatBody as M, regionOf as N, modelWithCurrentPromotion as O, PROBE_EFFORT_CANDIDATES as P, CN_APP_VERSION_FILENAME as R, WORKBUDDY_VARIANTS as S, WORKBUDDY_PROBE_PATH as T, resolveChatIdentity as U, fallbackChatIdentity as V, validCliVersion as W, validAppVersion as X, resolveAppVersion as Y, desktopAuthCandidatesFor as _, readHostHeartbeat as a, AI_VARIANT as b, WORKBUDDY_BRIDGE_VERSION as c, WorkBuddyCatalog as d, WORKBUDDY_AUTH_FILENAME as f, defaultDesktopAuthPath as g, defaultDesktopAuthCandidates as h, processStartTimeMs as i, prepareChatBody as j, normalizeCredits as k, FALLBACK_WORKBUDDY_AI_MODELS as l, WorkBuddyCredentialStore as m, clearHostHeartbeat as n, workbuddyHostHeartbeatPath as o, WORKBUDDY_AUTH_FILE_ENV as p, installedAppVersion as q, isHeartbeatProcessAlive as r, writeHostHeartbeat as s, WORKBUDDY_HOST_HEARTBEAT_FILENAME as t, FALLBACK_WORKBUDDY_MODELS as u, parseWorkBuddyAuth as v, WORKBUDDY_CREDIT_PATH as w, CN_VARIANT as x, workbuddyOwnAuthPath as y, FALLBACK_CN_APP_VERSION as z };
package/lib/index.d.ts CHANGED
@@ -906,6 +906,14 @@ interface WorkBuddyAuthStatus {
906
906
  expiresAtMs?: number;
907
907
  refreshExpiresAtMs?: number;
908
908
  nickname?: string;
909
+ /**
910
+ * The account's own id (`account.uid`), when the credential carries one.
911
+ *
912
+ * The fallback display name: the desktop document is the only source of a
913
+ * nickname, and it does not always have one. Non-secret — the same identity
914
+ * the per-account state is keyed by, sent upstream as `X-User-Id`.
915
+ */
916
+ uid?: string;
909
917
  domain?: string;
910
918
  source?: 'desktop' | 'dsh';
911
919
  /**
@@ -933,9 +941,10 @@ interface WorkBuddyStoreOptions {
933
941
  refreshMarginMs?: number;
934
942
  /**
935
943
  * Resolver for WorkBuddy 5.6's at-rest protector key, needed when the
936
- * desktop file stores encrypted token fields. Defaults to the real
937
- * provider, which spawns the WorkBuddy Electron binary; tests stand in a
938
- * stub. Structural so a store never depends on how the key is reached.
944
+ * desktop file stores encrypted token fields. Defaults to the real provider
945
+ * with the discovery this store's variant may run — see
946
+ * {@link atRestDiscoveryFor}. Tests stand in a stub; the shape is structural
947
+ * so a store never depends on how the key is reached.
939
948
  */
940
949
  keyProvider?: Pick<WorkBuddyAtRestKeyProvider, 'protectorKeyFor' | 'helperPath'>;
941
950
  }
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as modelWithCurrentPromotion, B as CN_APP_VERSION_FILENAME, C as defaultDesktopAuthPath, D as WorkBuddyAtRestKeyProvider, E as workbuddyOwnAuthPath, F as regionOf, G as resolveChatIdentity, H as chatUserAgent, I as PROBE_EFFORT_CANDIDATES, J as appUserAgent, K as validCliVersion, L as probeModel, M as parseModelCatalog, N as prepareChatBody, O as cnAppDiscovery, P as prepareInternationalChatBody, Q as validAppVersion, R as randomSentinel, S as defaultDesktopAuthCandidates, T as parseWorkBuddyAuth, U as fallbackChatIdentity, V as FALLBACK_CN_APP_VERSION, W as readCliVersion, X as readBundleVersion, Y as installedAppVersion, Z as resolveAppVersion, _ as FALLBACK_WORKBUDDY_MODELS, a as WORKBUDDY_HOST_HEARTBEAT_FILENAME, b as WORKBUDDY_AUTH_FILE_ENV, c as processStartTimeMs, d as writeHostHeartbeat, f as WORKBUDDY_BRIDGE_VERSION, g as FALLBACK_WORKBUDDY_AI_MODELS, i as variantFor, j as normalizeCredits, k as WorkBuddyUpstreamClient, l as readHostHeartbeat, n as CN_VARIANT, o as clearHostHeartbeat, p as WORKBUDDY_CREDIT_PATH, q as WORKBUDDY_APP_VERSION_FILENAME, r as WORKBUDDY_VARIANTS, s as isHeartbeatProcessAlive, t as AI_VARIANT, u as workbuddyHostHeartbeatPath, v as WorkBuddyCatalog, w as desktopAuthCandidatesFor, x as WorkBuddyCredentialStore, y as WORKBUDDY_AUTH_FILENAME, z as classifyUpstreamError } from "./variants-3SmUZ0e_.js";
1
+ import { A as parseModelCatalog, B as chatUserAgent, C as variantFor, D as WorkBuddyUpstreamClient, F as probeModel, G as WORKBUDDY_APP_VERSION_FILENAME, H as readCliVersion, I as randomSentinel, J as readBundleVersion, K as appUserAgent, L as classifyUpstreamError, M as prepareInternationalChatBody, N as regionOf, O as modelWithCurrentPromotion, P as PROBE_EFFORT_CANDIDATES, R as CN_APP_VERSION_FILENAME, S as WORKBUDDY_VARIANTS, U as resolveChatIdentity, V as fallbackChatIdentity, W as validCliVersion, X as validAppVersion, Y as resolveAppVersion, _ as desktopAuthCandidatesFor, a as readHostHeartbeat, b as AI_VARIANT, c as WORKBUDDY_BRIDGE_VERSION, d as WorkBuddyCatalog, f as WORKBUDDY_AUTH_FILENAME, g as defaultDesktopAuthPath, h as defaultDesktopAuthCandidates, i as processStartTimeMs, j as prepareChatBody, k as normalizeCredits, l as FALLBACK_WORKBUDDY_AI_MODELS, m as WorkBuddyCredentialStore, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as WORKBUDDY_AUTH_FILE_ENV, q as installedAppVersion, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as FALLBACK_WORKBUDDY_MODELS, v as parseWorkBuddyAuth, w as WORKBUDDY_CREDIT_PATH, x as CN_VARIANT, y as workbuddyOwnAuthPath, z as FALLBACK_CN_APP_VERSION } from "./heartbeat-DihKwwFX.js";
2
2
  import z from "@deepseek-ai/schemastery";
3
3
  import { dirname, join, resolve } from "node:path";
4
4
  import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
@@ -1467,6 +1467,7 @@ async function workBuddyWebStatus(deps) {
1467
1467
  const status = {
1468
1468
  status: "signed-in",
1469
1469
  ...authStatus.nickname === void 0 ? {} : { nickname: authStatus.nickname },
1470
+ ...authStatus.uid === void 0 ? {} : { uid: authStatus.uid },
1470
1471
  ...authStatus.domain === void 0 || authStatus.domain === "" ? {} : { domain: authStatus.domain },
1471
1472
  ...authStatus.source === void 0 ? {} : { source: authStatus.source },
1472
1473
  ...authStatus.expiresAtMs === void 0 ? {} : { expiresAt: authStatus.expiresAtMs }
@@ -1913,13 +1914,12 @@ function fallbackFor(variant) {
1913
1914
  return variant.id === CN_VARIANT.id ? FALLBACK_WORKBUDDY_MODELS : FALLBACK_WORKBUDDY_AI_MODELS;
1914
1915
  }
1915
1916
  /** Build one variant's stores and probe state. */
1916
- function createVariantRuntime(config, variant, identityOf, accountOf, keyProvider, creditIndex) {
1917
+ function createVariantRuntime(config, variant, identityOf, accountOf, creditIndex) {
1917
1918
  const client = new WorkBuddyUpstreamClient();
1918
1919
  const configured = configuredAuthFile(config, variant);
1919
1920
  const store = new WorkBuddyCredentialStore({
1920
1921
  variant,
1921
1922
  ...configured === void 0 ? {} : { desktopPath: configured },
1922
- ...keyProvider === void 0 ? {} : { keyProvider },
1923
1923
  refresh: (credential) => client.refreshToken(credential)
1924
1924
  });
1925
1925
  const fallback = fallbackFor(variant);
@@ -2121,9 +2121,8 @@ function apply(ctx, refs) {
2121
2121
  * case that must not fall back to a shared preference bucket.
2122
2122
  */
2123
2123
  const lastAccounts = /* @__PURE__ */ new Map();
2124
- const atRestKeysFor = (variant) => new WorkBuddyAtRestKeyProvider({ discovery: variant.id === CN_VARIANT.id ? cnAppDiscovery() : "none" });
2125
2124
  const creditIndex = new WorkBuddySessionCreditIndex();
2126
- const runtimes = WORKBUDDY_VARIANTS.map((variant) => createVariantRuntime(config(), variant, (id) => lastIdentities.get(id), (id) => lastAccounts.get(id), atRestKeysFor(variant), creditIndex));
2125
+ const runtimes = WORKBUDDY_VARIANTS.map((variant) => createVariantRuntime(config(), variant, (id) => lastIdentities.get(id), (id) => lastAccounts.get(id), creditIndex));
2127
2126
  const probeKey = createProbeKey();
2128
2127
  /**
2129
2128
  * Point a variant at an account identity, invalidating whatever the previous
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "dsh-workbuddy-bridge",
3
3
  "displayName": "DSH WorkBuddy Bridge",
4
4
  "description": "将 WorkBuddy 桌面 App 包含的模型自动接入 DeepSeek Harness — bring WorkBuddy desktop app models into DeepSeek Harness with zero configuration.",
5
- "version": "0.3.0",
5
+ "version": "0.3.1",
6
6
  "author": "zlZayn",
7
7
  "keywords": [
8
8
  "dsh",