@edge-sky/dsh-oauth-adapter 0.1.1-rc.9 → 0.1.2-beta.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/README.i18n.yaml CHANGED
@@ -1,4 +1,4 @@
1
1
  # Bilingual-pair consistency record: the git blob hash of each side as of the
2
2
  # last confirmed-consistent state. Both languages carry equal authority.
3
- README.md: a39895b8270728ff304536ba2df6d927e21f6f20
4
- README.zh.md: b2d5ac29a0087cf4df1f7a7ce7757acbe780fc3c
3
+ README.md: c4642ceaea18fbc2482a1a121893d9e5ee2662c4
4
+ README.zh.md: 7641d4bdcd89a0bfa9a247a4dc59013c0614e434
package/README.md CHANGED
@@ -4,8 +4,17 @@ English | [中文](README.zh.md)
4
4
 
5
5
  An OAuth account page for the DSH Web profile. It supports:
6
6
 
7
- - [x] OpenAI Codex
8
- - [x] GitHub Copilot
7
+ | Provider | pi-ai sign-in path |
8
+ | --- | --- |
9
+ | OpenAI Codex | Browser callback or device code |
10
+ | GitHub Copilot | GitHub or GitHub Enterprise device code |
11
+ | Anthropic | Browser callback with manual code/redirect fallback |
12
+ | Kimi For Coding | Device code |
13
+ | OpenRouter | Browser PKCE callback |
14
+ | Radius | Browser PKCE callback or device code |
15
+ | xAI | Device code |
16
+
17
+ Each account is shown only as available when the installed `@deepseek-ai/dsh-llm-pi-ai` actually registers its OAuth flow. This keeps older or differently bundled pi-ai versions fail-closed instead of exposing a login button that cannot work.
9
18
 
10
19
  The adapter has only been tested with DSH `0.1.1-rc.2`; compatibility with future versions is not guaranteed.
11
20
 
@@ -27,9 +36,14 @@ Start DSH:
27
36
  npx @deepseek-ai/dsh web
28
37
  ```
29
38
 
39
+ <img width="2270" height="1524" alt="image" src="https://github.com/user-attachments/assets/78a59190-8029-4c60-bc50-b763312540f7" />
40
+
41
+ <img width="2270" height="1524" alt="image" src="https://github.com/user-attachments/assets/e0cc6591-73a4-4e87-9ef6-68950126b290" />
42
+
43
+
30
44
  ## How it works
31
45
 
32
- DSH integrates pi-ai through the `@deepseek-ai/dsh-llm-pi-ai` adapter, but does not provide an OAuth entry point. `@edge-sky/dsh-oauth-adapter` registers pi-ai's existing Codex and Copilot login flows with the DSH Authorization Service.
46
+ DSH integrates pi-ai through the `@deepseek-ai/dsh-llm-pi-ai` adapter, but does not provide an OAuth entry point. `@edge-sky/dsh-oauth-adapter` exposes pi-ai's existing provider login flows through the DSH Authorization Service. Browser links, device codes, text and secret input, method selection, cancellation, and withdrawn prompts all use the same provider-neutral transport.
33
47
 
34
48
  Because DSH does not currently mount the `ctx.authorization` service, this plugin also mounts it manually.
35
49
 
package/README.zh.md CHANGED
@@ -4,8 +4,17 @@
4
4
 
5
5
  为 DSH Web profile 提供独立的 OAuth 账户页面。当前支持:
6
6
 
7
- - [x] OpenAI Codex
8
- - [x] GitHub Copilot
7
+ | 提供商 | pi-ai 登录路径 |
8
+ | --- | --- |
9
+ | OpenAI Codex | 浏览器回调或设备码 |
10
+ | GitHub Copilot | GitHub 或 GitHub Enterprise 设备码 |
11
+ | Anthropic | 浏览器回调,并支持手工粘贴授权码/重定向地址 |
12
+ | Kimi For Coding | 设备码 |
13
+ | OpenRouter | 浏览器 PKCE 回调 |
14
+ | Radius | 浏览器 PKCE 回调或设备码 |
15
+ | xAI | 设备码 |
16
+
17
+ 只有当当前安装的 `@deepseek-ai/dsh-llm-pi-ai` 确实注册了对应 OAuth 流程时,账户才会显示为可用。这样旧版或采用不同 pi-ai bundle 的 DSH 会安全地禁用登录按钮,而不会暴露无法完成的流程。
9
18
 
10
19
  当前仅对 DSH`0.1.1-rc.2`进行了测试,不保证未来版本的兼容性
11
20
 
@@ -27,9 +36,14 @@ npx @deepseek-ai/dsh plugin --profile web add @edge-sky/dsh-oauth-adapter
27
36
  npx @deepseek-ai/dsh web
28
37
  ```
29
38
 
39
+ <img width="2270" height="1524" alt="image" src="https://github.com/user-attachments/assets/134ec856-e17b-4800-bb87-069851986d3e" />
40
+
41
+ <img width="2270" height="1524" alt="image" src="https://github.com/user-attachments/assets/8007002a-a036-4cf4-b015-d4e50eff25d9" />
42
+
43
+
30
44
  ## 工作原理
31
45
 
32
- DSH 通过 `@deepseek-ai/dsh-llm-pi-ai` 适配器接入 pi-ai,但并没有提供 OAuth 的入口。`@edge-sky/dsh-oauth-adapter` 将 pi-ai 已有的 Codex 与 Copilot 登录流程注册到 DSH Authorization Service。
46
+ DSH 通过 `@deepseek-ai/dsh-llm-pi-ai` 适配器接入 pi-ai,但并没有提供 OAuth 的入口。`@edge-sky/dsh-oauth-adapter` 通过 DSH Authorization Service 暴露 pi-ai 已有的 provider 登录流程。浏览器链接、设备码、文本与密码输入、登录方式选择、取消和撤回提示均通过同一套 provider-neutral 传输完成。
33
47
 
34
48
  由于 DSH 目前并没有挂载`ctx.authorization`服务,因此该插件同时手动对其进行了挂载
35
49
 
package/lib/client.js CHANGED
@@ -6,6 +6,49 @@ window.__ModuleLoader__.load({
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
7
  let react = require("react");
8
8
  let react_jsx_runtime = require("react/jsx-runtime");
9
+ //#region src/protocol.ts
10
+ /** Shared browser/Host wire vocabulary for the OAuth account surface. */
11
+ const OAUTH_SOCKET_PATH = "/_edge-sky/dsh-oauth";
12
+ const OAUTH_SOCKET_PROTOCOL = "dsh-oauth-v1";
13
+ const PROVIDERS = [
14
+ {
15
+ id: "openai-codex",
16
+ key: "llm-pi-ai/openai-codex",
17
+ fallbackLabel: "OpenAI Codex",
18
+ modelGroupLabel: "OpenAI Codex (OAuth)"
19
+ },
20
+ {
21
+ id: "github-copilot",
22
+ key: "llm-pi-ai/github-copilot",
23
+ fallbackLabel: "GitHub Copilot",
24
+ modelGroupLabel: "GitHub Copilot (OAuth)"
25
+ },
26
+ {
27
+ id: "anthropic",
28
+ key: "llm-pi-ai/anthropic",
29
+ fallbackLabel: "Anthropic",
30
+ modelGroupLabel: "Anthropic (OAuth)"
31
+ },
32
+ {
33
+ id: "kimi-coding",
34
+ key: "llm-pi-ai/kimi-coding",
35
+ fallbackLabel: "Kimi For Coding",
36
+ modelGroupLabel: "Kimi For Coding (OAuth)"
37
+ },
38
+ {
39
+ id: "openrouter",
40
+ key: "llm-pi-ai/openrouter",
41
+ fallbackLabel: "OpenRouter",
42
+ modelGroupLabel: "OpenRouter (OAuth)"
43
+ },
44
+ {
45
+ id: "xai",
46
+ key: "llm-pi-ai/xai",
47
+ fallbackLabel: "xAI",
48
+ modelGroupLabel: "xAI (OAuth)"
49
+ }
50
+ ];
51
+ //#endregion
9
52
  //#region src/client/OAuthAccountsSection.tsx
10
53
  /** OAuth account settings page. */
11
54
  function safeHttpUrl(value) {
@@ -92,6 +135,16 @@ window.__ModuleLoader__.load({
92
135
  ]
93
136
  });
94
137
  }
138
+ function ErrorPanel(props) {
139
+ const collapsible = props.detail !== void 0 && (props.detail.includes("\n") || props.detail.length > 240);
140
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
141
+ className: "dsh-oauth-error",
142
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: props.message }), props.detail !== void 0 && (collapsible ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
143
+ className: "dsh-oauth-error-details",
144
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: props.t("technicalDetails") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { children: props.detail })]
145
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { children: props.detail }))]
146
+ });
147
+ }
95
148
  function AttemptPanel(props) {
96
149
  const [copied, setCopied] = (0, react.useState)(false);
97
150
  const url = safeHttpUrl(props.attempt.notice?.url);
@@ -125,9 +178,10 @@ window.__ModuleLoader__.load({
125
178
  controller: props.controller,
126
179
  t: props.t
127
180
  }, props.attempt.prompt.id),
128
- props.attempt.error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
129
- className: "dsh-oauth-error",
130
- children: props.attempt.error
181
+ props.attempt.error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorPanel, {
182
+ message: props.attempt.error,
183
+ ...props.attempt.errorDetail === void 0 ? {} : { detail: props.attempt.errorDetail },
184
+ t: props.t
131
185
  }),
132
186
  props.attempt.id !== void 0 && (props.attempt.phase === "running" || props.attempt.phase === "starting") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
133
187
  className: "dsh-oauth-button",
@@ -158,9 +212,10 @@ window.__ModuleLoader__.load({
158
212
  className: "dsh-oauth-intro",
159
213
  children: t("intro")
160
214
  }),
161
- snapshot.error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
162
- className: "dsh-oauth-error",
163
- children: snapshot.error
215
+ snapshot.error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorPanel, {
216
+ message: snapshot.error,
217
+ ...snapshot.errorDetail === void 0 ? {} : { detail: snapshot.errorDetail },
218
+ t
164
219
  }),
165
220
  snapshot.connection !== "open" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
166
221
  className: "dsh-oauth-button",
@@ -177,7 +232,7 @@ window.__ModuleLoader__.load({
177
232
  }),
178
233
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
179
234
  className: "dsh-oauth-list",
180
- children: ["openai-codex", "github-copilot"].map((provider) => {
235
+ children: PROVIDERS.map(({ id: provider }) => {
181
236
  const account = accountByProvider.get(provider);
182
237
  const attempt = snapshot.attempt?.provider === provider ? snapshot.attempt : void 0;
183
238
  const busy = account?.inFlight === true || attempt?.phase === "running" || attempt?.phase === "starting";
@@ -261,6 +316,7 @@ window.__ModuleLoader__.load({
261
316
  authorized: "Sign-in completed.",
262
317
  cancelled: "Sign-in was cancelled.",
263
318
  failed: "Sign-in failed.",
319
+ technicalDetails: "Technical details",
264
320
  submit: "Continue",
265
321
  copy: "Copy code",
266
322
  copied: "Copied",
@@ -292,6 +348,7 @@ window.__ModuleLoader__.load({
292
348
  authorized: "登录已完成。",
293
349
  cancelled: "登录已取消。",
294
350
  failed: "登录失败。",
351
+ technicalDetails: "技术详情",
295
352
  submit: "继续",
296
353
  copy: "复制代码",
297
354
  copied: "已复制",
@@ -303,11 +360,6 @@ window.__ModuleLoader__.load({
303
360
  hostDisconnected: "与 DSH 的 OAuth 连接已中断。"
304
361
  };
305
362
  //#endregion
306
- //#region src/protocol.ts
307
- /** Shared browser/Host wire vocabulary for the OAuth account surface. */
308
- const OAUTH_SOCKET_PATH = "/_edge-sky/dsh-oauth";
309
- const OAUTH_SOCKET_PROTOCOL = "dsh-oauth-v1";
310
- //#endregion
311
363
  //#region src/client/store.ts
312
364
  /** Browser state machine for the plugin-owned OAuth WebSocket. */
313
365
  function socketUrl() {
@@ -355,7 +407,7 @@ window.__ModuleLoader__.load({
355
407
  getSnapshot = () => this.snapshot;
356
408
  begin(provider) {
357
409
  if (this.snapshot.attempt?.phase === "starting" || this.snapshot.attempt?.phase === "running") return;
358
- const { error: _error, ...current } = this.snapshot;
410
+ const { error: _error, errorDetail: _errorDetail, ...current } = this.snapshot;
359
411
  this.update({
360
412
  ...current,
361
413
  attempt: {
@@ -426,7 +478,7 @@ window.__ModuleLoader__.load({
426
478
  socket.addEventListener("open", () => {
427
479
  if (this.socket !== socket) return;
428
480
  this.reconnectDelay = 500;
429
- const { error: _error, ...current } = this.snapshot;
481
+ const { error: _error, errorDetail: _errorDetail, ...current } = this.snapshot;
430
482
  this.update({
431
483
  ...current,
432
484
  connection: "open"
@@ -442,10 +494,12 @@ window.__ModuleLoader__.load({
442
494
  try {
443
495
  value = JSON.parse(event.data);
444
496
  } catch {
445
- this.update({
497
+ const next = {
446
498
  ...this.snapshot,
447
499
  error: "DSH returned an invalid OAuth message."
448
- });
500
+ };
501
+ delete next.errorDetail;
502
+ this.update(next);
449
503
  return;
450
504
  }
451
505
  if (isServerMessage(value)) this.receive(value);
@@ -461,7 +515,7 @@ window.__ModuleLoader__.load({
461
515
  return;
462
516
  }
463
517
  const attempt = this.snapshot.attempt;
464
- this.update({
518
+ const interrupted = {
465
519
  ...this.snapshot,
466
520
  connection: "reconnecting",
467
521
  error: "The OAuth connection to DSH was interrupted.",
@@ -470,7 +524,10 @@ window.__ModuleLoader__.load({
470
524
  phase: "failed",
471
525
  error: "The OAuth connection to DSH was interrupted."
472
526
  } }
473
- });
527
+ };
528
+ delete interrupted.errorDetail;
529
+ if (interrupted.attempt?.error === "The OAuth connection to DSH was interrupted.") delete interrupted.attempt.errorDetail;
530
+ this.update(interrupted);
474
531
  const delay = this.reconnectDelay;
475
532
  this.reconnectDelay = Math.min(this.reconnectDelay * 2, 5e3);
476
533
  this.reconnectTimer = window.setTimeout(() => {
@@ -482,10 +539,12 @@ window.__ModuleLoader__.load({
482
539
  }
483
540
  send(command) {
484
541
  if (this.socket?.readyState !== WebSocket.OPEN) {
485
- this.update({
542
+ const next = {
486
543
  ...this.snapshot,
487
544
  error: "The OAuth connection to DSH is not ready."
488
- });
545
+ };
546
+ delete next.errorDetail;
547
+ this.update(next);
489
548
  return;
490
549
  }
491
550
  this.socket.send(JSON.stringify(command));
@@ -504,7 +563,7 @@ window.__ModuleLoader__.load({
504
563
  this.update(nextSnapshot);
505
564
  return;
506
565
  case "started":
507
- const { error: _error, ...current } = this.snapshot;
566
+ const { error: _error, errorDetail: _errorDetail, ...current } = this.snapshot;
508
567
  this.update({
509
568
  ...current,
510
569
  attempt: {
@@ -567,17 +626,26 @@ window.__ModuleLoader__.load({
567
626
  }
568
627
  case "error": {
569
628
  const attempt = this.snapshot.attempt;
570
- if (message.attemptId !== void 0 && attempt?.id === message.attemptId) this.update({
571
- ...this.snapshot,
572
- attempt: {
629
+ if (message.attemptId !== void 0 && attempt?.id === message.attemptId) {
630
+ const nextAttempt = {
573
631
  ...attempt,
574
632
  error: message.message
575
- }
576
- });
577
- else this.update({
578
- ...this.snapshot,
579
- error: message.message
580
- });
633
+ };
634
+ if (message.detail === void 0) delete nextAttempt.errorDetail;
635
+ else nextAttempt.errorDetail = message.detail;
636
+ this.update({
637
+ ...this.snapshot,
638
+ attempt: nextAttempt
639
+ });
640
+ } else {
641
+ const next = {
642
+ ...this.snapshot,
643
+ error: message.message
644
+ };
645
+ if (message.detail === void 0) delete next.errorDetail;
646
+ else next.errorDetail = message.detail;
647
+ this.update(next);
648
+ }
581
649
  return;
582
650
  }
583
651
  case "ack": return;
@@ -595,7 +663,7 @@ window.__ModuleLoader__.load({
595
663
  .dsh-oauth-section{display:flex;flex-direction:column;gap:12px;max-width:720px;color:var(--dsw-alias-label-primary)}
596
664
  .dsh-oauth-title{margin:0;font-size:16px;line-height:24px;font-weight:500}
597
665
  .dsh-oauth-intro,.dsh-oauth-muted{margin:0;font-size:13px;line-height:20px;color:var(--dsw-alias-label-tertiary)}
598
- .dsh-oauth-error{margin:0;padding:8px 10px;border-radius:8px;background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}
666
+ .dsh-oauth-error{display:flex;flex-direction:column;gap:6px;margin:0;padding:8px 10px;border-radius:8px;background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}.dsh-oauth-error p{margin:0}.dsh-oauth-error pre{box-sizing:border-box;max-width:100%;max-height:320px;margin:0;padding:8px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;overflow:auto;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);font:11px/17px ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.dsh-oauth-error-details summary{cursor:pointer;color:var(--dsw-alias-label-secondary);user-select:none}.dsh-oauth-error-details[open] summary{margin-bottom:6px}
599
667
  .dsh-oauth-list{display:flex;flex-direction:column;gap:8px;margin:4px 0 0;padding:0;list-style:none}
600
668
  .dsh-oauth-card{display:flex;flex-direction:column;gap:10px;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px}
601
669
  .dsh-oauth-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.dsh-oauth-name{font-size:14px;font-weight:500}.dsh-oauth-state{display:inline-flex;align-items:center;gap:6px;padding:3px 8px;border-radius:999px;background:var(--dsw-alias-interactive-bg-hover);font-size:12px;color:var(--dsw-alias-label-secondary)}
@@ -607,6 +675,7 @@ window.__ModuleLoader__.load({
607
675
  //#endregion
608
676
  //#region src/client/index.ts
609
677
  const NS = "settings.oauth-accounts";
678
+ const MODEL_SETTINGS_VISIBILITY = "modelSettingsVisibility";
610
679
  /** Required browser services for settings placement and localized copy. */
611
680
  const inject = ["slots", "locale"];
612
681
  /** Register the OAuth account page and its app-lifetime connection controller. */
@@ -628,6 +697,10 @@ window.__ModuleLoader__.load({
628
697
  ctx.effect(() => () => {
629
698
  controller.dispose();
630
699
  }, "dsh-oauth-adapter: controller");
700
+ ctx.inject([MODEL_SETTINGS_VISIBILITY], (scope) => {
701
+ const visibility = scope.get(MODEL_SETTINGS_VISIBILITY);
702
+ scope.effect(() => visibility.registerHiddenProviders(PROVIDERS.map((provider) => provider.id)), "dsh-oauth-adapter: hide OAuth providers from Models settings");
703
+ });
631
704
  const t = ctx.locale.bind(NS);
632
705
  ctx.slots.inject("settings.section", () => ctx.slots.register({
633
706
  name: "settings.section",
package/lib/index.d.ts CHANGED
@@ -33,6 +33,8 @@ export declare function isLoopbackAddress(address: string | undefined): boolean;
33
33
  export declare function safeNoticeUrl(value: string | undefined): string | undefined;
34
34
  /** Validate the browser handshake before `ws` takes ownership of the socket. */
35
35
  export declare function acceptsBrowserUpgrade(request: IncomingMessage): boolean;
36
+ /** Format one Host failure for browser diagnostics without forwarding credentials or unbounded data. */
37
+ export declare function formatErrorDetail(error: unknown): string;
36
38
  /** Mount the loopback-only OAuth WebSocket over official rc2 services. */
37
39
  export declare function apply(ctx: OAuthContext, config: Config): () => Promise<void>;
38
40
  export {};
package/lib/index.js CHANGED
@@ -4,6 +4,7 @@
4
4
  * @module @edge-sky/dsh-oauth-adapter
5
5
  */
6
6
  import { randomUUID } from 'node:crypto';
7
+ import { inspect } from 'node:util';
7
8
  import { settingsNamespace } from '@deepseek-ai/dsh-settings';
8
9
  import z from '@deepseek-ai/schemastery';
9
10
  import WebSocket, { WebSocketServer } from 'ws';
@@ -55,6 +56,13 @@ function promptView(prompt, provider) {
55
56
  : {},
56
57
  };
57
58
  }
59
+ function providerPromptAnswer(prompt, provider, value) {
60
+ if (provider === 'github-copilot' && prompt.kind === 'text'
61
+ && prompt.message === GITHUB_DOMAIN_PROMPT && value.trim().length === 0) {
62
+ return 'github.com';
63
+ }
64
+ return value;
65
+ }
58
66
  /** Whether a socket address belongs to the local host. */
59
67
  export function isLoopbackAddress(address) {
60
68
  return address === '127.0.0.1' || address === '::1' || address === '::ffff:127.0.0.1';
@@ -101,6 +109,67 @@ function rawLength(raw) {
101
109
  return raw.reduce((total, chunk) => total + chunk.byteLength, 0);
102
110
  return raw.byteLength;
103
111
  }
112
+ const MAX_ERROR_DETAIL_LENGTH = 12 * 1024;
113
+ const MAX_ERROR_CAUSE_DEPTH = 6;
114
+ function redactErrorDetail(value) {
115
+ return value
116
+ .replace(/(\bAuthorization\b\s*["']?\s*[:=]\s*["']?)(?:Bearer\s+)?([^"'\s,}&]+)/giu, '$1[REDACTED]')
117
+ .replace(/\bBearer\s+[A-Za-z0-9._~+/=-]+/giu, 'Bearer [REDACTED]')
118
+ .replace(/(\b(?:access[_-]?token|refresh[_-]?token|id[_-]?token|client[_-]?secret|api[_-]?key)\b\s*["']?\s*[:=]\s*["']?)([^"'\s,}&]+)/giu, '$1[REDACTED]')
119
+ .replace(/\b(?:github_pat_|gh[opusr]_|sk-)[A-Za-z0-9_-]{12,}\b/gu, '[REDACTED]');
120
+ }
121
+ function errorProperties(value) {
122
+ const record = value;
123
+ const properties = ['code', 'status', 'statusCode']
124
+ .flatMap((key) => {
125
+ const entry = record[key];
126
+ return typeof entry === 'string' || typeof entry === 'number' ? [`${key}: ${String(entry)}`] : [];
127
+ });
128
+ return properties.length === 0 ? undefined : properties.join(', ');
129
+ }
130
+ /** Format one Host failure for browser diagnostics without forwarding credentials or unbounded data. */
131
+ export function formatErrorDetail(error) {
132
+ const sections = [];
133
+ const seen = new Set();
134
+ let current = error;
135
+ for (let depth = 0; current !== undefined && depth < MAX_ERROR_CAUSE_DEPTH; depth += 1) {
136
+ if (typeof current === 'object' && current !== null) {
137
+ if (seen.has(current)) {
138
+ sections.push('Caused by: [circular error cause]');
139
+ current = undefined;
140
+ break;
141
+ }
142
+ seen.add(current);
143
+ }
144
+ const prefix = depth === 0 ? '' : 'Caused by: ';
145
+ if (current instanceof Error) {
146
+ const properties = errorProperties(current);
147
+ const rendered = current.stack ?? `${current.name}: ${current.message}`;
148
+ sections.push(`${prefix}${rendered}${properties === undefined ? '' : `\n${properties}`}`);
149
+ current = current.cause;
150
+ continue;
151
+ }
152
+ sections.push(prefix + (typeof current === 'string'
153
+ ? current
154
+ : inspect(current, {
155
+ breakLength: 120,
156
+ compact: false,
157
+ customInspect: false,
158
+ depth: 4,
159
+ maxArrayLength: 40,
160
+ maxStringLength: 4096,
161
+ sorted: true,
162
+ })));
163
+ current = undefined;
164
+ break;
165
+ }
166
+ if (current !== undefined)
167
+ sections.push('Caused by: [additional causes omitted]');
168
+ const redacted = redactErrorDetail(sections.join('\n'));
169
+ if (redacted.length <= MAX_ERROR_DETAIL_LENGTH)
170
+ return redacted;
171
+ return `${redacted.slice(0, MAX_ERROR_DETAIL_LENGTH)}\n[diagnostic truncated]`;
172
+ }
104
173
  /** One ownership-scoped browser authorization connection. */
105
174
  class OAuthConnection {
106
175
  ctx;
@@ -124,7 +193,7 @@ class OAuthConnection {
124
193
  this.queue = this.queue.then(() => this.receive(raw.toString())).catch((error) => {
125
194
  this.ctx.logger.warn('dsh-oauth-adapter: command handling failed');
126
195
  this.ctx.logger.warn(error);
127
- this.sendError('operation-failed', 'the OAuth operation failed');
196
+ this.sendError('operation-failed', 'the OAuth operation failed', undefined, undefined, formatErrorDetail(error));
128
197
  });
129
198
  });
130
199
  socket.on('close', () => {
@@ -150,11 +219,12 @@ class OAuthConnection {
150
219
  if (this.socket.readyState === WebSocket.OPEN)
151
220
  this.socket.send(JSON.stringify(message));
152
221
  }
153
- sendError(code, message, requestId, attemptId) {
222
+ sendError(code, message, requestId, attemptId, detail) {
154
223
  this.send({
155
224
  type: 'error', code, message,
156
225
  ...requestId === undefined ? {} : { requestId },
157
226
  ...attemptId === undefined ? {} : { attemptId },
227
+ ...detail === undefined ? {} : { detail },
158
228
  });
159
229
  }
160
230
  async receive(raw) {
@@ -226,7 +296,7 @@ class OAuthConnection {
226
296
  catch (error) {
227
297
  this.ctx.logger.warn('dsh-oauth-adapter: credential status read failed');
228
298
  this.ctx.logger.warn(error);
229
- this.sendError('operation-failed', 'account status is unavailable', requestId);
299
+ this.sendError('operation-failed', 'account status is unavailable', requestId, undefined, formatErrorDetail(error));
230
300
  }
231
301
  }
232
302
  begin(command) {
@@ -278,14 +348,14 @@ class OAuthConnection {
278
348
  catch (error) {
279
349
  this.ctx.logger.warn('dsh-oauth-adapter: model route activation failed for %s', provider.id);
280
350
  this.ctx.logger.warn(error);
281
- this.sendError('model-route-unavailable', 'sign-in completed, but the OAuth model route could not be enabled', undefined, attempt.id);
351
+ this.sendError('model-route-unavailable', 'sign-in completed, but the OAuth model route could not be enabled', undefined, attempt.id, formatErrorDetail(error));
282
352
  }
283
353
  }
284
354
  this.finish(attempt, outcome.status);
285
355
  }, (error) => {
286
356
  this.ctx.logger.warn('dsh-oauth-adapter: provider sign-in failed for %s', attempt.provider);
287
357
  this.ctx.logger.warn(error);
288
- this.sendError('sign-in-failed', 'sign-in failed; inspect the DSH Host log', undefined, attempt.id);
358
+ this.sendError('sign-in-failed', 'sign-in failed', undefined, attempt.id, formatErrorDetail(error));
289
359
  this.finish(attempt, 'failed');
290
360
  });
291
361
  }
@@ -310,7 +380,7 @@ class OAuthConnection {
310
380
  });
311
381
  };
312
382
  attempt.prompts.set(promptId, {
313
- resolve: value => { finish(() => { resolve(value); }); },
383
+ resolve: value => { finish(() => { resolve(providerPromptAnswer(prompt, attempt.provider, value)); }); },
314
384
  reject: reason => { finish(() => { reject(reason); }); },
315
385
  });
316
386
  prompt.signal?.addEventListener('abort', withdraw, { once: true });
@@ -370,7 +440,7 @@ class OAuthConnection {
370
440
  catch (error) {
371
441
  this.ctx.logger.warn('dsh-oauth-adapter: sign-out failed for %s', provider.id);
372
442
  this.ctx.logger.warn(error);
373
- this.sendError('operation-failed', 'sign-out failed; inspect the DSH Host log', command.requestId);
443
+ this.sendError('operation-failed', 'sign-out failed', command.requestId, undefined, formatErrorDetail(error));
374
444
  }
375
445
  }
376
446
  finish(attempt, status) {
package/lib/protocol.d.ts CHANGED
@@ -13,6 +13,26 @@ export declare const PROVIDERS: readonly [{
13
13
  readonly key: "llm-pi-ai/github-copilot";
14
14
  readonly fallbackLabel: "GitHub Copilot";
15
15
  readonly modelGroupLabel: "GitHub Copilot (OAuth)";
16
+ }, {
17
+ readonly id: "anthropic";
18
+ readonly key: "llm-pi-ai/anthropic";
19
+ readonly fallbackLabel: "Anthropic";
20
+ readonly modelGroupLabel: "Anthropic (OAuth)";
21
+ }, {
22
+ readonly id: "kimi-coding";
23
+ readonly key: "llm-pi-ai/kimi-coding";
24
+ readonly fallbackLabel: "Kimi For Coding";
25
+ readonly modelGroupLabel: "Kimi For Coding (OAuth)";
26
+ }, {
27
+ readonly id: "openrouter";
28
+ readonly key: "llm-pi-ai/openrouter";
29
+ readonly fallbackLabel: "OpenRouter";
30
+ readonly modelGroupLabel: "OpenRouter (OAuth)";
31
+ }, {
32
+ readonly id: "xai";
33
+ readonly key: "llm-pi-ai/xai";
34
+ readonly fallbackLabel: "xAI";
35
+ readonly modelGroupLabel: "xAI (OAuth)";
16
36
  }];
17
37
  export type ProviderId = (typeof PROVIDERS)[number]['id'];
18
38
  export interface AccountView {
@@ -104,6 +124,8 @@ export type ServerMessage = {
104
124
  attemptId?: string;
105
125
  code: OAuthErrorCode;
106
126
  message: string;
127
+ /** Bounded, credential-redacted Host diagnostic for optional UI expansion. */
128
+ detail?: string;
107
129
  };
108
130
  export type CommandParseResult = {
109
131
  ok: true;
package/lib/protocol.js CHANGED
@@ -12,6 +12,22 @@ export const PROVIDERS = [
12
12
  id: 'github-copilot', key: 'llm-pi-ai/github-copilot', fallbackLabel: 'GitHub Copilot',
13
13
  modelGroupLabel: 'GitHub Copilot (OAuth)',
14
14
  },
15
+ {
16
+ id: 'anthropic', key: 'llm-pi-ai/anthropic', fallbackLabel: 'Anthropic',
17
+ modelGroupLabel: 'Anthropic (OAuth)',
18
+ },
19
+ {
20
+ id: 'kimi-coding', key: 'llm-pi-ai/kimi-coding', fallbackLabel: 'Kimi For Coding',
21
+ modelGroupLabel: 'Kimi For Coding (OAuth)',
22
+ },
23
+ {
24
+ id: 'openrouter', key: 'llm-pi-ai/openrouter', fallbackLabel: 'OpenRouter',
25
+ modelGroupLabel: 'OpenRouter (OAuth)',
26
+ },
27
+ {
28
+ id: 'xai', key: 'llm-pi-ai/xai', fallbackLabel: 'xAI',
29
+ modelGroupLabel: 'xAI (OAuth)',
30
+ },
15
31
  ];
16
32
  const ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
17
33
  function isRecord(value) {
@@ -19,6 +19,7 @@ export declare const en: {
19
19
  readonly authorized: "Sign-in completed.";
20
20
  readonly cancelled: "Sign-in was cancelled.";
21
21
  readonly failed: "Sign-in failed.";
22
+ readonly technicalDetails: "Technical details";
22
23
  readonly submit: "Continue";
23
24
  readonly copy: "Copy code";
24
25
  readonly copied: "Copied";
@@ -16,12 +16,14 @@ export interface AttemptView {
16
16
  notice?: NoticeView;
17
17
  prompt?: ActivePromptView;
18
18
  error?: string;
19
+ errorDetail?: string;
19
20
  }
20
21
  export interface OAuthAccountsSnapshot {
21
22
  connection: 'connecting' | 'open' | 'reconnecting' | 'closed';
22
23
  accounts: readonly AccountView[];
23
24
  attempt?: AttemptView;
24
25
  error?: string;
26
+ errorDetail?: string;
25
27
  }
26
28
  type Listener = () => void;
27
29
  /** Remove interaction-only content once an authorization attempt settles. */
@@ -1,3 +1,3 @@
1
1
  /** Plugin-owned styles, injected and removed with the browser Cordis fiber. */
2
- export declare const styles = "\n.dsh-oauth-section{display:flex;flex-direction:column;gap:12px;max-width:720px;color:var(--dsw-alias-label-primary)}\n.dsh-oauth-title{margin:0;font-size:16px;line-height:24px;font-weight:500}\n.dsh-oauth-intro,.dsh-oauth-muted{margin:0;font-size:13px;line-height:20px;color:var(--dsw-alias-label-tertiary)}\n.dsh-oauth-error{margin:0;padding:8px 10px;border-radius:8px;background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}\n.dsh-oauth-list{display:flex;flex-direction:column;gap:8px;margin:4px 0 0;padding:0;list-style:none}\n.dsh-oauth-card{display:flex;flex-direction:column;gap:10px;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px}\n.dsh-oauth-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.dsh-oauth-name{font-size:14px;font-weight:500}.dsh-oauth-state{display:inline-flex;align-items:center;gap:6px;padding:3px 8px;border-radius:999px;background:var(--dsw-alias-interactive-bg-hover);font-size:12px;color:var(--dsw-alias-label-secondary)}\n.dsh-oauth-dot{width:7px;height:7px;border-radius:50%;background:var(--dsw-alias-label-tertiary)}.dsh-oauth-state[data-state=ready] .dsh-oauth-dot{background:var(--dsw-alias-state-success-primary)}.dsh-oauth-state[data-state=warning] .dsh-oauth-dot{background:var(--dsw-alias-state-error-primary)}.dsh-oauth-state[data-state=authorizing] .dsh-oauth-dot{background:var(--dsw-alias-button-info-fill)}\n.dsh-oauth-actions{display:flex;gap:6px;margin-left:auto}.dsh-oauth-button{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;min-height:30px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:15px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;line-height:18px;cursor:pointer}.dsh-oauth-button[data-variant=primary]{border-color:transparent;background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.dsh-oauth-button[data-variant=danger]{border-color:transparent;color:var(--dsw-alias-state-error-primary)}.dsh-oauth-button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.dsh-oauth-button[data-variant=primary]:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover);color:var(--dsw-alias-label-primary-foreground)}.dsh-oauth-button[data-variant=danger]:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.dsh-oauth-button:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}.dsh-oauth-button:disabled{cursor:not-allowed;opacity:.4}\n.dsh-oauth-flow{display:flex;flex-direction:column;gap:8px;padding-top:10px;border-top:1px solid var(--dsw-alias-border-l3);font-size:13px;line-height:20px}.dsh-oauth-link{display:grid;grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:8px;padding:9px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);text-decoration:none}.dsh-oauth-link:hover{background:var(--dsw-alias-interactive-bg-hover-solid)}.dsh-oauth-link-label{font-weight:500}.dsh-oauth-link-host{max-width:240px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:12px}.dsh-oauth-link-icon{color:var(--dsw-alias-brand-text)}.dsh-oauth-code{display:flex;align-items:center;gap:8px}.dsh-oauth-code code{padding:5px 8px;border-radius:6px;background:var(--dsw-alias-bg-module-platform);font-size:14px;letter-spacing:.08em}\n.dsh-oauth-prompt{display:flex;flex-direction:column;gap:7px}.dsh-oauth-input,.dsh-oauth-select{box-sizing:border-box;width:100%;height:34px;padding:0 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary)}\n";
2
+ export declare const styles = "\n.dsh-oauth-section{display:flex;flex-direction:column;gap:12px;max-width:720px;color:var(--dsw-alias-label-primary)}\n.dsh-oauth-title{margin:0;font-size:16px;line-height:24px;font-weight:500}\n.dsh-oauth-intro,.dsh-oauth-muted{margin:0;font-size:13px;line-height:20px;color:var(--dsw-alias-label-tertiary)}\n.dsh-oauth-error{display:flex;flex-direction:column;gap:6px;margin:0;padding:8px 10px;border-radius:8px;background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}.dsh-oauth-error p{margin:0}.dsh-oauth-error pre{box-sizing:border-box;max-width:100%;max-height:320px;margin:0;padding:8px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;overflow:auto;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);font:11px/17px ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.dsh-oauth-error-details summary{cursor:pointer;color:var(--dsw-alias-label-secondary);user-select:none}.dsh-oauth-error-details[open] summary{margin-bottom:6px}\n.dsh-oauth-list{display:flex;flex-direction:column;gap:8px;margin:4px 0 0;padding:0;list-style:none}\n.dsh-oauth-card{display:flex;flex-direction:column;gap:10px;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px}\n.dsh-oauth-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.dsh-oauth-name{font-size:14px;font-weight:500}.dsh-oauth-state{display:inline-flex;align-items:center;gap:6px;padding:3px 8px;border-radius:999px;background:var(--dsw-alias-interactive-bg-hover);font-size:12px;color:var(--dsw-alias-label-secondary)}\n.dsh-oauth-dot{width:7px;height:7px;border-radius:50%;background:var(--dsw-alias-label-tertiary)}.dsh-oauth-state[data-state=ready] .dsh-oauth-dot{background:var(--dsw-alias-state-success-primary)}.dsh-oauth-state[data-state=warning] .dsh-oauth-dot{background:var(--dsw-alias-state-error-primary)}.dsh-oauth-state[data-state=authorizing] .dsh-oauth-dot{background:var(--dsw-alias-button-info-fill)}\n.dsh-oauth-actions{display:flex;gap:6px;margin-left:auto}.dsh-oauth-button{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;min-height:30px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:15px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;line-height:18px;cursor:pointer}.dsh-oauth-button[data-variant=primary]{border-color:transparent;background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.dsh-oauth-button[data-variant=danger]{border-color:transparent;color:var(--dsw-alias-state-error-primary)}.dsh-oauth-button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.dsh-oauth-button[data-variant=primary]:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover);color:var(--dsw-alias-label-primary-foreground)}.dsh-oauth-button[data-variant=danger]:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.dsh-oauth-button:focus-visible{outline:none;box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}.dsh-oauth-button:disabled{cursor:not-allowed;opacity:.4}\n.dsh-oauth-flow{display:flex;flex-direction:column;gap:8px;padding-top:10px;border-top:1px solid var(--dsw-alias-border-l3);font-size:13px;line-height:20px}.dsh-oauth-link{display:grid;grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:8px;padding:9px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);text-decoration:none}.dsh-oauth-link:hover{background:var(--dsw-alias-interactive-bg-hover-solid)}.dsh-oauth-link-label{font-weight:500}.dsh-oauth-link-host{max-width:240px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:12px}.dsh-oauth-link-icon{color:var(--dsw-alias-brand-text)}.dsh-oauth-code{display:flex;align-items:center;gap:8px}.dsh-oauth-code code{padding:5px 8px;border-radius:6px;background:var(--dsw-alias-bg-module-platform);font-size:14px;letter-spacing:.08em}\n.dsh-oauth-prompt{display:flex;flex-direction:column;gap:7px}.dsh-oauth-input,.dsh-oauth-select{box-sizing:border-box;width:100%;height:34px;padding:0 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary)}\n";
3
3
  //# sourceMappingURL=styles.d.ts.map
@@ -13,6 +13,26 @@ export declare const PROVIDERS: readonly [{
13
13
  readonly key: "llm-pi-ai/github-copilot";
14
14
  readonly fallbackLabel: "GitHub Copilot";
15
15
  readonly modelGroupLabel: "GitHub Copilot (OAuth)";
16
+ }, {
17
+ readonly id: "anthropic";
18
+ readonly key: "llm-pi-ai/anthropic";
19
+ readonly fallbackLabel: "Anthropic";
20
+ readonly modelGroupLabel: "Anthropic (OAuth)";
21
+ }, {
22
+ readonly id: "kimi-coding";
23
+ readonly key: "llm-pi-ai/kimi-coding";
24
+ readonly fallbackLabel: "Kimi For Coding";
25
+ readonly modelGroupLabel: "Kimi For Coding (OAuth)";
26
+ }, {
27
+ readonly id: "openrouter";
28
+ readonly key: "llm-pi-ai/openrouter";
29
+ readonly fallbackLabel: "OpenRouter";
30
+ readonly modelGroupLabel: "OpenRouter (OAuth)";
31
+ }, {
32
+ readonly id: "xai";
33
+ readonly key: "llm-pi-ai/xai";
34
+ readonly fallbackLabel: "xAI";
35
+ readonly modelGroupLabel: "xAI (OAuth)";
16
36
  }];
17
37
  export type ProviderId = (typeof PROVIDERS)[number]['id'];
18
38
  export interface AccountView {
@@ -104,6 +124,8 @@ export type ServerMessage = {
104
124
  attemptId?: string;
105
125
  code: OAuthErrorCode;
106
126
  message: string;
127
+ /** Bounded, credential-redacted Host diagnostic for optional UI expansion. */
128
+ detail?: string;
107
129
  };
108
130
  export type CommandParseResult = {
109
131
  ok: true;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@edge-sky/dsh-oauth-adapter",
3
3
  "description": "Web OAuth account surface for official DSH authorization flows",
4
- "version": "0.1.1-rc.9",
4
+ "version": "0.1.2-beta.1",
5
5
  "author": {
6
6
  "name": "edge-sky",
7
7
  "url": "https://github.com/edge-sky"
@@ -11,8 +11,9 @@
11
11
  },
12
12
  "repository": {
13
13
  "type": "git",
14
- "url": "git+https://github.com/edge-sky/dsh-oauth.git"
14
+ "url": "git+https://github.com/edge-sky/dsh-oauth-adapter.git"
15
15
  },
16
+ "packageManager": "pnpm@11.7.0",
16
17
  "engines": {
17
18
  "node": "^22.19.0 || >=24.0.0"
18
19
  },
@@ -44,6 +45,13 @@
44
45
  "lib/**/*.js",
45
46
  "lib/**/*.d.ts"
46
47
  ],
48
+ "scripts": {
49
+ "build": "tsdown && pnpm run build:host && pnpm run build:client:types",
50
+ "build:host": "tsc -p tsconfig.json",
51
+ "build:client:types": "tsc -p tsconfig.client.json",
52
+ "test": "pnpm run build && vitest run",
53
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit"
54
+ },
47
55
  "license": "MIT",
48
56
  "dsh": {
49
57
  "bundle": {
@@ -60,16 +68,17 @@
60
68
  },
61
69
  "peerDependencies": {
62
70
  "@deepseek-ai/cordis": ">=4.0.1",
63
- "@deepseek-ai/dsh-client-locale": ">=0.1.1-rc.2",
64
- "@deepseek-ai/dsh-client-runtime": ">=0.1.1-rc.2",
65
- "@deepseek-ai/dsh-client-ui-settings": ">=0.1.1-rc.2",
66
- "@deepseek-ai/dsh-client-ui-slots": ">=0.1.1-rc.2",
67
- "@deepseek-ai/dsh-credentials": ">=0.1.1-rc.2",
68
- "@deepseek-ai/dsh-host-webserver": ">=0.1.1-rc.2",
69
- "@deepseek-ai/dsh-invariants": ">=0.1.1-rc.2",
70
- "@deepseek-ai/dsh-llm": ">=0.1.1-rc.2",
71
- "@deepseek-ai/dsh-llm-pi-ai": ">=0.1.1-rc.2",
72
- "@deepseek-ai/dsh-settings": ">=0.1.1-rc.2",
71
+ "@deepseek-ai/dsh-authorization": ">=0.1.1-rc.2 <0.2.0-0",
72
+ "@deepseek-ai/dsh-client-locale": ">=0.1.1-rc.2 <0.2.0-0",
73
+ "@deepseek-ai/dsh-client-runtime": ">=0.1.1-rc.2 <0.2.0-0",
74
+ "@deepseek-ai/dsh-client-ui-settings": ">=0.1.1-rc.2 <0.2.0-0",
75
+ "@deepseek-ai/dsh-client-ui-slots": ">=0.1.1-rc.2 <0.2.0-0",
76
+ "@deepseek-ai/dsh-credentials": ">=0.1.1-rc.2 <0.2.0-0",
77
+ "@deepseek-ai/dsh-host-webserver": ">=0.1.1-rc.2 <0.2.0-0",
78
+ "@deepseek-ai/dsh-invariants": ">=0.1.1-rc.2 <0.2.0-0",
79
+ "@deepseek-ai/dsh-llm": ">=0.1.1-rc.2 <0.2.0-0",
80
+ "@deepseek-ai/dsh-llm-pi-ai": ">=0.1.1-rc.2 <0.2.0-0",
81
+ "@deepseek-ai/dsh-settings": ">=0.1.1-rc.2 <0.2.0-0",
73
82
  "react": ">=18.2.0"
74
83
  },
75
84
  "peerDependenciesMeta": {
@@ -111,12 +120,12 @@
111
120
  }
112
121
  },
113
122
  "dependencies": {
114
- "@deepseek-ai/dsh-authorization": ">=0.1.1-rc.2",
115
123
  "@deepseek-ai/schemastery": "^3.18.1",
116
124
  "ws": "^8.18.3"
117
125
  },
118
126
  "devDependencies": {
119
127
  "@deepseek-ai/cordis": "^4.0.1",
128
+ "@deepseek-ai/dsh-authorization": "0.1.1-rc.2",
120
129
  "@deepseek-ai/dsh-client-locale": "0.1.1-rc.2",
121
130
  "@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
122
131
  "@deepseek-ai/dsh-client-ui-settings": "0.1.1-rc.2",
@@ -136,12 +145,5 @@
136
145
  "tsdown": "^0.22.2",
137
146
  "typescript": "^6.0.3",
138
147
  "vitest": "^4.1.8"
139
- },
140
- "scripts": {
141
- "build": "tsdown && pnpm run build:host && pnpm run build:client:types",
142
- "build:host": "tsc -p tsconfig.json",
143
- "build:client:types": "tsc -p tsconfig.client.json",
144
- "test": "pnpm run build && vitest run",
145
- "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit"
146
148
  }
147
- }
149
+ }