@edge-sky/dsh-oauth-adapter 0.1.1-rc.9 → 0.1.2-beta.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.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: ca7554635b97303928fe3ad09f3ee53c9ce96e94
4
+ README.zh.md: 8e53233889cfe60ca4c0c19b2a26064400eceaf4
package/README.md CHANGED
@@ -2,10 +2,19 @@
2
2
 
3
3
  English | [中文](README.zh.md)
4
4
 
5
- An OAuth account page for the DSH Web profile. It supports:
5
+ An OAuth account page for the DSH Web profile. With the pi-ai catalog bundled by DSH `0.1.1-rc.2`, 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,10 +36,15 @@ 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
 
36
- The plugin itself does not manage OAuth credentials or maintain login state. Maybe DSH support this sign-in method in the future; but for now, this plugin lets you enjoy it.
50
+ The plugin itself does not implement provider OAuth protocols, manage OAuth credentials, or maintain login state. pi-ai owns login and token refresh; the DSH Credentials Service owns persistence; this adapter owns only the local Web UI bridge and model-route activation.
package/README.zh.md CHANGED
@@ -2,10 +2,19 @@
2
2
 
3
3
  [English](README.md) | 中文
4
4
 
5
- 为 DSH Web profile 提供独立的 OAuth 账户页面。当前支持:
5
+ 为 DSH Web profile 提供独立的 OAuth 账户页面。配合 DSH `0.1.1-rc.2` 内置的 pi-ai catalog,当前支持:
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,10 +36,15 @@ 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
 
36
- 插件本身并不承担 OAuth 凭证管理与维持登录态的职责,或许将来 DSH 会官方支持这一登录方式,但至少现在你可以通过这个插件体验它
50
+ 插件本身不实现各提供商的 OAuth 协议,也不管理 OAuth 凭证或维持登录态。登录与 token 刷新由 pi-ai 负责,持久化由 DSH Credentials Service 负责,本适配器只负责本机 Web UI 桥接和模型路由启用。
package/lib/client.js CHANGED
@@ -6,6 +6,55 @@ 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: "radius",
46
+ key: "llm-pi-ai/radius",
47
+ fallbackLabel: "Radius",
48
+ modelGroupLabel: "Radius (OAuth)"
49
+ },
50
+ {
51
+ id: "xai",
52
+ key: "llm-pi-ai/xai",
53
+ fallbackLabel: "xAI",
54
+ modelGroupLabel: "xAI (OAuth)"
55
+ }
56
+ ];
57
+ //#endregion
9
58
  //#region src/client/OAuthAccountsSection.tsx
10
59
  /** OAuth account settings page. */
11
60
  function safeHttpUrl(value) {
@@ -92,6 +141,16 @@ window.__ModuleLoader__.load({
92
141
  ]
93
142
  });
94
143
  }
144
+ function ErrorPanel(props) {
145
+ const collapsible = props.detail !== void 0 && (props.detail.includes("\n") || props.detail.length > 240);
146
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
147
+ className: "dsh-oauth-error",
148
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: props.message }), props.detail !== void 0 && (collapsible ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
149
+ className: "dsh-oauth-error-details",
150
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: props.t("technicalDetails") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { children: props.detail })]
151
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { children: props.detail }))]
152
+ });
153
+ }
95
154
  function AttemptPanel(props) {
96
155
  const [copied, setCopied] = (0, react.useState)(false);
97
156
  const url = safeHttpUrl(props.attempt.notice?.url);
@@ -125,9 +184,10 @@ window.__ModuleLoader__.load({
125
184
  controller: props.controller,
126
185
  t: props.t
127
186
  }, 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
187
+ props.attempt.error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorPanel, {
188
+ message: props.attempt.error,
189
+ ...props.attempt.errorDetail === void 0 ? {} : { detail: props.attempt.errorDetail },
190
+ t: props.t
131
191
  }),
132
192
  props.attempt.id !== void 0 && (props.attempt.phase === "running" || props.attempt.phase === "starting") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
133
193
  className: "dsh-oauth-button",
@@ -158,9 +218,10 @@ window.__ModuleLoader__.load({
158
218
  className: "dsh-oauth-intro",
159
219
  children: t("intro")
160
220
  }),
161
- snapshot.error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
162
- className: "dsh-oauth-error",
163
- children: snapshot.error
221
+ snapshot.error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorPanel, {
222
+ message: snapshot.error,
223
+ ...snapshot.errorDetail === void 0 ? {} : { detail: snapshot.errorDetail },
224
+ t
164
225
  }),
165
226
  snapshot.connection !== "open" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
166
227
  className: "dsh-oauth-button",
@@ -177,7 +238,7 @@ window.__ModuleLoader__.load({
177
238
  }),
178
239
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
179
240
  className: "dsh-oauth-list",
180
- children: ["openai-codex", "github-copilot"].map((provider) => {
241
+ children: PROVIDERS.map(({ id: provider }) => {
181
242
  const account = accountByProvider.get(provider);
182
243
  const attempt = snapshot.attempt?.provider === provider ? snapshot.attempt : void 0;
183
244
  const busy = account?.inFlight === true || attempt?.phase === "running" || attempt?.phase === "starting";
@@ -261,6 +322,7 @@ window.__ModuleLoader__.load({
261
322
  authorized: "Sign-in completed.",
262
323
  cancelled: "Sign-in was cancelled.",
263
324
  failed: "Sign-in failed.",
325
+ technicalDetails: "Technical details",
264
326
  submit: "Continue",
265
327
  copy: "Copy code",
266
328
  copied: "Copied",
@@ -292,6 +354,7 @@ window.__ModuleLoader__.load({
292
354
  authorized: "登录已完成。",
293
355
  cancelled: "登录已取消。",
294
356
  failed: "登录失败。",
357
+ technicalDetails: "技术详情",
295
358
  submit: "继续",
296
359
  copy: "复制代码",
297
360
  copied: "已复制",
@@ -303,11 +366,6 @@ window.__ModuleLoader__.load({
303
366
  hostDisconnected: "与 DSH 的 OAuth 连接已中断。"
304
367
  };
305
368
  //#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
369
  //#region src/client/store.ts
312
370
  /** Browser state machine for the plugin-owned OAuth WebSocket. */
313
371
  function socketUrl() {
@@ -355,7 +413,7 @@ window.__ModuleLoader__.load({
355
413
  getSnapshot = () => this.snapshot;
356
414
  begin(provider) {
357
415
  if (this.snapshot.attempt?.phase === "starting" || this.snapshot.attempt?.phase === "running") return;
358
- const { error: _error, ...current } = this.snapshot;
416
+ const { error: _error, errorDetail: _errorDetail, ...current } = this.snapshot;
359
417
  this.update({
360
418
  ...current,
361
419
  attempt: {
@@ -426,7 +484,7 @@ window.__ModuleLoader__.load({
426
484
  socket.addEventListener("open", () => {
427
485
  if (this.socket !== socket) return;
428
486
  this.reconnectDelay = 500;
429
- const { error: _error, ...current } = this.snapshot;
487
+ const { error: _error, errorDetail: _errorDetail, ...current } = this.snapshot;
430
488
  this.update({
431
489
  ...current,
432
490
  connection: "open"
@@ -442,10 +500,12 @@ window.__ModuleLoader__.load({
442
500
  try {
443
501
  value = JSON.parse(event.data);
444
502
  } catch {
445
- this.update({
503
+ const next = {
446
504
  ...this.snapshot,
447
505
  error: "DSH returned an invalid OAuth message."
448
- });
506
+ };
507
+ delete next.errorDetail;
508
+ this.update(next);
449
509
  return;
450
510
  }
451
511
  if (isServerMessage(value)) this.receive(value);
@@ -461,7 +521,7 @@ window.__ModuleLoader__.load({
461
521
  return;
462
522
  }
463
523
  const attempt = this.snapshot.attempt;
464
- this.update({
524
+ const interrupted = {
465
525
  ...this.snapshot,
466
526
  connection: "reconnecting",
467
527
  error: "The OAuth connection to DSH was interrupted.",
@@ -470,7 +530,10 @@ window.__ModuleLoader__.load({
470
530
  phase: "failed",
471
531
  error: "The OAuth connection to DSH was interrupted."
472
532
  } }
473
- });
533
+ };
534
+ delete interrupted.errorDetail;
535
+ if (interrupted.attempt?.error === "The OAuth connection to DSH was interrupted.") delete interrupted.attempt.errorDetail;
536
+ this.update(interrupted);
474
537
  const delay = this.reconnectDelay;
475
538
  this.reconnectDelay = Math.min(this.reconnectDelay * 2, 5e3);
476
539
  this.reconnectTimer = window.setTimeout(() => {
@@ -482,10 +545,12 @@ window.__ModuleLoader__.load({
482
545
  }
483
546
  send(command) {
484
547
  if (this.socket?.readyState !== WebSocket.OPEN) {
485
- this.update({
548
+ const next = {
486
549
  ...this.snapshot,
487
550
  error: "The OAuth connection to DSH is not ready."
488
- });
551
+ };
552
+ delete next.errorDetail;
553
+ this.update(next);
489
554
  return;
490
555
  }
491
556
  this.socket.send(JSON.stringify(command));
@@ -504,7 +569,7 @@ window.__ModuleLoader__.load({
504
569
  this.update(nextSnapshot);
505
570
  return;
506
571
  case "started":
507
- const { error: _error, ...current } = this.snapshot;
572
+ const { error: _error, errorDetail: _errorDetail, ...current } = this.snapshot;
508
573
  this.update({
509
574
  ...current,
510
575
  attempt: {
@@ -567,17 +632,26 @@ window.__ModuleLoader__.load({
567
632
  }
568
633
  case "error": {
569
634
  const attempt = this.snapshot.attempt;
570
- if (message.attemptId !== void 0 && attempt?.id === message.attemptId) this.update({
571
- ...this.snapshot,
572
- attempt: {
635
+ if (message.attemptId !== void 0 && attempt?.id === message.attemptId) {
636
+ const nextAttempt = {
573
637
  ...attempt,
574
638
  error: message.message
575
- }
576
- });
577
- else this.update({
578
- ...this.snapshot,
579
- error: message.message
580
- });
639
+ };
640
+ if (message.detail === void 0) delete nextAttempt.errorDetail;
641
+ else nextAttempt.errorDetail = message.detail;
642
+ this.update({
643
+ ...this.snapshot,
644
+ attempt: nextAttempt
645
+ });
646
+ } else {
647
+ const next = {
648
+ ...this.snapshot,
649
+ error: message.message
650
+ };
651
+ if (message.detail === void 0) delete next.errorDetail;
652
+ else next.errorDetail = message.detail;
653
+ this.update(next);
654
+ }
581
655
  return;
582
656
  }
583
657
  case "ack": return;
@@ -595,7 +669,7 @@ window.__ModuleLoader__.load({
595
669
  .dsh-oauth-section{display:flex;flex-direction:column;gap:12px;max-width:720px;color:var(--dsw-alias-label-primary)}
596
670
  .dsh-oauth-title{margin:0;font-size:16px;line-height:24px;font-weight:500}
597
671
  .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}
672
+ .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
673
  .dsh-oauth-list{display:flex;flex-direction:column;gap:8px;margin:4px 0 0;padding:0;list-style:none}
600
674
  .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
675
  .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)}
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,31 @@ 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: "radius";
33
+ readonly key: "llm-pi-ai/radius";
34
+ readonly fallbackLabel: "Radius";
35
+ readonly modelGroupLabel: "Radius (OAuth)";
36
+ }, {
37
+ readonly id: "xai";
38
+ readonly key: "llm-pi-ai/xai";
39
+ readonly fallbackLabel: "xAI";
40
+ readonly modelGroupLabel: "xAI (OAuth)";
16
41
  }];
17
42
  export type ProviderId = (typeof PROVIDERS)[number]['id'];
18
43
  export interface AccountView {
@@ -104,6 +129,8 @@ export type ServerMessage = {
104
129
  attemptId?: string;
105
130
  code: OAuthErrorCode;
106
131
  message: string;
132
+ /** Bounded, credential-redacted Host diagnostic for optional UI expansion. */
133
+ detail?: string;
107
134
  };
108
135
  export type CommandParseResult = {
109
136
  ok: true;
package/lib/protocol.js CHANGED
@@ -12,6 +12,26 @@ 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: 'radius', key: 'llm-pi-ai/radius', fallbackLabel: 'Radius',
29
+ modelGroupLabel: 'Radius (OAuth)',
30
+ },
31
+ {
32
+ id: 'xai', key: 'llm-pi-ai/xai', fallbackLabel: 'xAI',
33
+ modelGroupLabel: 'xAI (OAuth)',
34
+ },
15
35
  ];
16
36
  const ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
17
37
  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,31 @@ 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: "radius";
33
+ readonly key: "llm-pi-ai/radius";
34
+ readonly fallbackLabel: "Radius";
35
+ readonly modelGroupLabel: "Radius (OAuth)";
36
+ }, {
37
+ readonly id: "xai";
38
+ readonly key: "llm-pi-ai/xai";
39
+ readonly fallbackLabel: "xAI";
40
+ readonly modelGroupLabel: "xAI (OAuth)";
16
41
  }];
17
42
  export type ProviderId = (typeof PROVIDERS)[number]['id'];
18
43
  export interface AccountView {
@@ -104,6 +129,8 @@ export type ServerMessage = {
104
129
  attemptId?: string;
105
130
  code: OAuthErrorCode;
106
131
  message: string;
132
+ /** Bounded, credential-redacted Host diagnostic for optional UI expansion. */
133
+ detail?: string;
107
134
  };
108
135
  export type CommandParseResult = {
109
136
  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.0",
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
+ }