dsh-grok-provider 0.1.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/CONTRIBUTING.md +51 -0
  3. package/LICENSE +21 -0
  4. package/README.en.md +200 -0
  5. package/README.md +200 -0
  6. package/SECURITY.md +35 -0
  7. package/dist/client/client.js +215 -0
  8. package/dist/host/index.mjs +147 -0
  9. package/dist/internal/account-dashboard.mjs +67 -0
  10. package/dist/internal/auth-controller.mjs +184 -0
  11. package/dist/internal/auth-registry.mjs +64 -0
  12. package/dist/internal/auth-rpc.mjs +118 -0
  13. package/dist/internal/billing-summary.mjs +105 -0
  14. package/dist/internal/credential-source.mjs +168 -0
  15. package/dist/internal/grok-adapter.mjs +160 -0
  16. package/dist/internal/grok-command-handler.mjs +62 -0
  17. package/dist/internal/grok-command.mjs +17 -0
  18. package/dist/internal/grok-transport.mjs +279 -0
  19. package/dist/internal/model-catalog.mjs +142 -0
  20. package/dist/internal/official-auth-driver.mjs +40 -0
  21. package/dist/internal/official-cli-auth.mjs +231 -0
  22. package/dist/internal/official-cli-verifier.mjs +62 -0
  23. package/dist/internal/official-credential-loader.mjs +64 -0
  24. package/dist/internal/provider-runtime.mjs +43 -0
  25. package/dist/internal/responses-codec.mjs +357 -0
  26. package/dist/internal/responses-request.mjs +246 -0
  27. package/dist/internal/responses-sse.mjs +123 -0
  28. package/docs/01-product-requirements.md +128 -0
  29. package/docs/02-architecture-options.md +180 -0
  30. package/docs/03-security-threat-model.md +243 -0
  31. package/docs/04-harness-contract.md +325 -0
  32. package/docs/05-test-plan.md +224 -0
  33. package/docs/06-release-plan.md +182 -0
  34. package/docs/07-decision-gate.md +76 -0
  35. package/docs/08-upstream-cli-1.0.5-evidence.md +98 -0
  36. package/docs/09-implementation-status.md +37 -0
  37. package/docs/README.md +60 -0
  38. package/docs/adr/0001-auth-and-transport-route.md +86 -0
  39. package/docs/adr/0002-v0.1-scope.md +46 -0
  40. package/docs/adr/0003-dual-authentication.md +77 -0
  41. package/docs/adr/0004-dynamic-model-catalog.md +34 -0
  42. package/docs/adr/0005-official-cli-only-authentication.md +36 -0
  43. package/docs/adr/0006-account-dashboard.md +84 -0
  44. package/grok-provider.patch.yml +3 -0
  45. package/package.json +92 -0
  46. package/types/index.d.ts +9 -0
package/docs/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # Grok Build Provider 文档索引
2
+
3
+ - 状态:**方案已确认,`0.1.0` 收敛为官方 CLI 浏览器登录单路径**
4
+ - 目标版本:`0.1.0`
5
+ - 兼容基线:DeepSeek Harness `0.1.1-rc.2`
6
+ - 目标平台:macOS arm64、Windows x64
7
+
8
+ 本仓库是一次 clean-room 重写。设计只依据 DeepSeek Harness 的公开接口、xAI 官方 Grok Build 文档和通用协议标准;不会复制、移植或修改 `dsh-llm-grok` 的源码、目录结构或实现细节。
9
+
10
+ ## 推荐结论
11
+
12
+ 首版采用单一认证路线:插件发起官方 Grok Build CLI 浏览器登录并复用由官方 CLI 持久化的会话。插件不注册独立 OAuth client,也不持久化第二份 token。
13
+
14
+ 1. 用户在 Harness 设置页点击“使用 Grok 登录”,或在 TUI 输入 `/grok login`。
15
+ 2. 插件 Host 通过 Harness `ctx.subprocess` 以固定 argv 启动经路径/版本约束的 Grok CLI 候选;该启动层不经过 shell。标准配置下由官方 CLI 完成系统浏览器、OAuth、loopback callback 和凭据写入。
16
+ 3. 插件只读官方凭据文件并接受绑定 schema;token 不进入 renderer、settings、RPC、本插件日志或 workspace。
17
+ 4. 模型目录只请求固定 `GET /v1/models`;推理按目录中经过验证的 `api_backend` 选择闭合 endpoint。当前真实模型都走固定 `POST /v1/responses`;拒绝重定向和自定义 endpoint。
18
+ 5. 模型目录从固定 `/v1/models` 动态发现账号当前可用的全部 Grok Build 模型;本机当前快照为 `grok-4.6` 与 `grok-4.5`。
19
+ 6. 包内不存在 OAuth client ID、client secret、device flow、插件实现的 refresh/revoke 或 Harness credential grant;浏览器登录、refresh grant 与持久化完全由官方 CLI 负责。
20
+
21
+ 该路径要求本机安装受支持版本的官方 CLI。仓库所有者在 2026-08-26 将“插件自管 OAuth”要求改为“能跳转浏览器登录即可”,详见 ADR-0005。
22
+
23
+ 安全边界需要说清楚:`--oauth` 只选择 loopback 浏览器 transport,不会强制官方 CLI 忽略其有效配置。官方 CLI 可能按用户/企业配置运行外部认证命令(其内部可使用 `sh -c` 或 `cmd /C`)或企业 OIDC。因此“无 shell”只适用于本插件到 CLI 的启动层,不是端到端保证。`0.1.0` 把官方 CLI 及其有效配置视为用户管理的可信组件,并在读取凭据后失败关闭:外部 provider、API key、企业 issuer、旧式或歧义记录都不允许进入固定 xAI Proxy。该本地 metadata 未签名,所以这是严格兼容性筛选,不是密码学来源证明。
24
+
25
+ 还需接受这些共享副作用和残余风险:官方 login 可能先清除已有 credential,取消或失败也可能使旧会话失效;logout 会影响所有共享同一 `GROK_HOME` 的应用。官方 CLI 的 proxy、managed-config sync、更新检查与已启用遥测不受插件固定推理 transport 约束。当前第一方 token 可能具有 conversation/workspace read-write 等较宽 scope,泄漏影响不只一次聊天。Web `loopback` RPC 是浏览器 reachability/trust fence,不是本机进程身份认证;同一 OS 用户下的恶意进程不在本插件可防御边界内。
26
+
27
+ ## 文档顺序
28
+
29
+ - [产品需求](./01-product-requirements.md)
30
+ - [架构候选与推荐路线](./02-architecture-options.md)
31
+ - [安全与威胁模型](./03-security-threat-model.md)
32
+ - [Harness rc.2 接口契约](./04-harness-contract.md)
33
+ - [兼容性与测试计划](./05-test-plan.md)
34
+ - [npm `0.1.0` 发布计划](./06-release-plan.md)
35
+ - [开发前决策门](./07-decision-gate.md)
36
+ - [Grok CLI 1.0.5 上游证据](./08-upstream-cli-1.0.5-evidence.md)
37
+ - [当前实现与发布阻断项](./09-implementation-status.md)
38
+ - [ADR-0001:认证与传输路线](./adr/0001-auth-and-transport-route.md)
39
+ - [ADR-0002:首版能力边界](./adr/0002-v0.1-scope.md)
40
+ - [ADR-0003:已被取代的双认证设计](./adr/0003-dual-authentication.md)
41
+ - [ADR-0004:动态全模型目录](./adr/0004-dynamic-model-catalog.md)
42
+ - [ADR-0005:官方 CLI 单一认证路径](./adr/0005-official-cli-only-authentication.md)
43
+ - [ADR-0006:账户额度与模型能力面板](./adr/0006-account-dashboard.md)
44
+
45
+ ## 开发门禁
46
+
47
+ 原开发门已由仓库所有者确认。最终 package identity、macOS 真机门禁和发布链全部满足前,不进行 npm 发布;Windows x64 首次真机验证安排在 `0.1.0` 发布后,完成前标注“代码支持、真机未验证”。`0.1.1` 及后续版本以自动化矩阵、契约、干净安装和制品校验替代重复真机门禁。独立 xAI OAuth client 授权已不再属于首版范围。
48
+
49
+ ## 官方依据
50
+
51
+ - [xAI Grok Build 官方仓库](https://github.com/xai-org/grok-build)
52
+ - [Grok Build 官方 billing extension:额度比例、周期与固定 CLI Proxy 请求](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-shell/src/extensions/billing.rs)
53
+ - [Grok Build 官方 README:认证、auth.json API 调用、Headless 与 ACP](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-shell/README.md)
54
+ - [Grok Build 官方认证指南:browser login 与凭据边界](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-pager/docs/user-guide/02-authentication.md)
55
+ - [`dsh-codex`:Web/TUI 登录体验参考,不作为代码来源](https://github.com/Yan-Zero/dsh-codex)
56
+ - [RFC 8252:Native Apps OAuth 2.0](https://www.rfc-editor.org/rfc/rfc8252)
57
+ - [RFC 9700:OAuth 2.0 Security Best Current Practice](https://www.rfc-editor.org/rfc/rfc9700)
58
+ - DeepSeek Harness `0.1.1-rc.2` 内置公开类型:`@deepseek-ai/dsh-llm`、`@deepseek-ai/dsh-subprocess`、`@deepseek-ai/dsh-settings`、`@deepseek-ai/dsh-client-connection`
59
+
60
+ 外部文档核对日期:2026-08-26。正式发布前必须重新核对上游接口与服务条款。
@@ -0,0 +1,86 @@
1
+ # ADR-0001:认证与传输路线
2
+
3
+ > 修订说明:官方 CLI 路径仍有效;“不自行 OAuth”的结论已由 ADR-0003 部分取代。动态模型目录见 ADR-0004。
4
+
5
+ - 状态:Accepted,已由 ADR-0003/0004 修订
6
+ - 日期:2026-08-25
7
+ - 决策者:仓库所有者
8
+
9
+ ## 背景
10
+
11
+ 项目需要把 Grok Build 模型接入 DeepSeek Harness,同时支持 macOS 和 Windows。第三方实现暴露出跨平台浏览器命令不完整、凭据边界过宽以及可能把 Bearer token 发送给远端返回 URL 等问题。本项目必须 clean-room 重写,不能以修补第三方代码为基础。
12
+
13
+ xAI 官方 Grok Build 文档提供三类可用集成面:
14
+
15
+ - `grok -p` Headless。
16
+ - `grok agent stdio` ACP。
17
+ - 登录后读取官方 `auth.json`,使用指定 headers 调用 CLI Chat Proxy。
18
+
19
+ Harness 需要的是 LLM adapter,而不是第二套 agent runtime。
20
+
21
+ ## 决策
22
+
23
+ `0.1.0` 采用以下组合:
24
+
25
+ - Web 设置页和 TUI 可以发起登录;Host 只通过 Harness `ctx.subprocess`,以固定 argv 启动经路径/版本约束的 `grok login --oauth`。插件启动层不经过 shell。
26
+ - 标准配置下,系统浏览器、OAuth、loopback callback、refresh grant 和官方凭据写入全部由 xAI 官方 Grok Build CLI 完成;首版在匹配的 access token 失效时只委托固定 `grok models` 命令静默续期,插件本身不实现 OAuth refresh。
27
+ - 官方 CLI 及其有效 user/system/MDM 配置是明确的 vendor trust boundary。`--oauth` 只固定 loopback transport,不保证绕过 external auth provider、devbox 或企业 OIDC,也不保证 CLI 内部不用 `sh -c`/`cmd /C`。
28
+ - 插件只读 Grok 会话凭据,不实现 OAuth,不持久化第二份 token;只接受与绑定 CLI 版本的 xAI 生产 OIDC schema 相符的唯一候选。该 metadata 未签名,筛选用于失败关闭,不是密码学来源证明。
29
+ - 目录仅访问固定 `GET /v1/models`;推理按验证过的 catalog `api_backend` 访问闭合 endpoint。当前真实模型走固定 `POST /v1/responses`,不再假设单一 Chat Completions 方言。
30
+ - 只使用协议 spike 对绑定版本验证过的 xAI headers,并加入 Harness 要求的 attribution headers;所选动态模型不得被固定 override 偷换。
31
+ - 所有带凭据请求禁止重定向,不支持自定义 endpoint。
32
+ - 插件自身不启动 shell 或通用浏览器 opener;只允许通过 `ctx.subprocess` 启动 `grok login --oauth`、`grok logout`,并对候选路径、参数、输出、超时、并发与取消做闭合约束。
33
+
34
+ ## 结果
35
+
36
+ 正面结果:
37
+
38
+ - 不复制 OAuth Client ID,不承担 client secret、PKCE、loopback 和 refresh token 实现。
39
+ - 不引入 `open`、直接 `node:child_process` 或平台 shell 依赖;进程树生命周期由 Harness subprocess seam 管理。
40
+ - macOS 与 Windows 的登录差异由官方客户端处理。
41
+ - 官方 CLI 路径不产生第二份落盘凭据;ADR-0003 的独立 grant 设计已被 ADR-0005 取代。
42
+ - 依赖图可以保持接近零 runtime dependencies。
43
+ - 用户可像 `dsh-codex` 的 Web/TUI 流程一样,直接从 Harness 发起浏览器登录。
44
+
45
+ 负面结果:
46
+
47
+ - 用户必须先安装官方 Grok Build CLI。
48
+ - 插件新增一个以当前 OS 用户权限运行、但调用面窄化的官方 CLI 子进程边界,必须覆盖路径劫持、输出超限、超时、取消和卸载测试。
49
+ - 官方 CLI 可能根据可信配置执行 external helper/企业 OIDC、同步 managed config 或发送其自身已启用的遥测;本项目不能承诺端到端无 shell或单一网络 origin。
50
+ - 重新登录可能替换/清除共享 Grok credential,取消或失败也可能使旧会话失效;logout 影响共享同一 `GROK_HOME` 的其他应用。
51
+ - 官方凭据过期时需要从 Harness 再次触发 `grok login --oauth`。
52
+ - 官方 CLI 浏览器登录要求 Host 与浏览器处于同一本机桌面会话;首版不支持远端浏览器/device-code 登录。
53
+ - 插件依赖官方凭据文件格式和 CLI Chat Proxy 契约。
54
+ - 官方文档的技术示例不等于永久服务条款授权;公开发布前仍需重新核对条款。
55
+ - `0.1.0` 当前只承诺官方支持的 macOS arm64 与 Windows x64。
56
+
57
+ ## 失效条件
58
+
59
+ 任一情况出现时必须重新评审本 ADR:
60
+
61
+ - xAI 移除或反对 auth.json API Access 文档。
62
+ - 服务条款明确禁止此类第三方集成。
63
+ - 官方凭据改为插件不可安全读取的存储。
64
+ - Chat Proxy 不再支持 Harness 所需的工具调用或流式协议。
65
+ - DeepSeek Harness 提供官方 OAuth/credential bridge,可在不复制凭据的情况下直接委托登录。
66
+ - xAI 提供可验证的 builtin-only/no-config 登录参数;届时应收窄 vendor trust boundary。
67
+
68
+ ## 未采用方案
69
+
70
+ - 插件自建 OAuth:本 ADR 当时拒绝;ADR-0003 曾采纳,随后又由 ADR-0005 从 `0.1.0` 删除。
71
+ - Headless:无法保真映射 Harness LLM/tool 语义。
72
+ - ACP:引入第二套 agent、权限与会话生命周期。
73
+ - API Key:单独计费语义,不等价于 Grok Build 订阅路线。
74
+
75
+ ## 依据
76
+
77
+ - [xAI Grok Build 官方 README](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-shell/README.md)
78
+ - [官方认证 flow:`--oauth` 仅固定 loopback,external/devbox 仍优先](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-shell/src/auth/flow.rs#L904-L909)
79
+ - [官方 external auth 实现:Unix `sh -c` / Windows `cmd /C`](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-shell/src/auth/flow.rs#L193-L217)
80
+ - [官方 auth scope 生成规则](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-shell/src/auth/config.rs#L200-L251)
81
+ - [官方凭据模型:issuer 是 client-side hint,不是 trust assertion](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-shell/src/auth/model.rs#L123-L139)
82
+ - [官方 npm 支持平台](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-pager/npm/grok/README.md)
83
+ - [RFC 8252](https://www.rfc-editor.org/rfc/rfc8252)
84
+ - [RFC 9700](https://www.rfc-editor.org/rfc/rfc9700)
85
+
86
+ 上述 `main` 链接只用于方案阶段说明;Gate 1 必须替换/补充为实际支持 CLI 版本的 immutable tag/commit 链接后,才能形成发布证据。
@@ -0,0 +1,46 @@
1
+ # ADR-0002:`0.1.0` 能力边界
2
+
3
+ > 修订说明:单一模型与仅官方 CLI 登录的范围已由 ADR-0003、ADR-0004 扩展;其余内容边界继续有效。
4
+
5
+ - 状态:Accepted,已由 ADR-0003/0004 修订
6
+ - 日期:2026-08-25
7
+ - 决策者:仓库所有者
8
+
9
+ ## 背景
10
+
11
+ 首版需要先证明核心模型协议、安全边界、跨平台认证识别和受管 npm 安装。搜索、生图、任意文件下载、多账号和企业 OIDC 会显著扩大权限与测试矩阵,并重现已知高风险区域。
12
+
13
+ ## 决策
14
+
15
+ `0.1.0` 只发布:
16
+
17
+ - 动态发现账号当前可用的全部 Grok Build 模型;当前 fixture 为 `grok-4.6`、`grok-4.5`。
18
+ - 文本、多轮消息、reasoning、流式输出。
19
+ - Harness 工具调用。
20
+ - 官方 CLI 会话状态检查。
21
+ - Web/TUI 只提供官方 CLI 浏览器认证路径,命令语法见 ADR-0005 与 Harness 契约。
22
+ - macOS 与 Windows 支持。
23
+
24
+ 明确不发布:
25
+
26
+ - Web Search、X Search 和 vendor server tools。
27
+ - 图片生成、图片下载、图片输入和文件写入。
28
+ - 自定义 endpoint、API Key、企业 OIDC、多账号。
29
+ - 自动安装或更新 CLI;浏览器由用户触发登录后由官方 CLI 打开,插件不直接打开 URL。
30
+ - ACP、Headless 和 Linux 支持承诺。
31
+
32
+ ## 结果
33
+
34
+ - 安全评审集中在凭据读取、固定网络 origin、SSE 资源上限和 Harness 流契约。
35
+ - 不存在把 Bearer token 带到远端图片 URL 的代码路径。
36
+ - 所有联网能力都来自一次用户可见的模型调用;没有默认开启的额外搜索调用。
37
+ - 功能少于某些第三方实现,但发布质量和边界更清晰。
38
+
39
+ ## 后续能力门禁
40
+
41
+ 任何新增能力都需要独立 ADR:
42
+
43
+ - 图片输入必须只通过 Harness attachment service,并同时限制单图字节、总字节、像素与数量。
44
+ - 图片生成必须优先使用直接字节/base64;若使用 signed URL,只允许固定 CDN origin,下载请求不带 Authorization/Cookie/Referer,并有双服务器泄漏测试。
45
+ - 搜索能力必须由用户分别显式开启,默认关闭,未开启时请求中完全不存在对应工具。
46
+ - API Key 必须明确显示“独立计费”,不能作为订阅会话失败后的静默 fallback。
@@ -0,0 +1,77 @@
1
+ # ADR-0003:双认证路径与自管 OAuth 凭据(已被取代)
2
+
3
+ > 状态:Superseded by ADR-0005。以下内容仅保留为历史设计记录,不属于 `0.1.0` 当前实现、接口或发布门禁。
4
+
5
+ - 状态:已接受,带发布阻断项
6
+ - 日期:2026-08-25
7
+ - 决策者:仓库所有者
8
+
9
+ ## 背景
10
+
11
+ 仓库所有者在接受“官方 CLI 登录 + 复用官方会话”后,进一步要求插件也能自行完成并持久化 OAuth token。两条路径服务不同需求,不能静默互相回退:
12
+
13
+ 1. `official-cli`:插件启动官方 `grok login --oauth`,复用 `~/.grok/auth.json`;
14
+ 2. `managed-device`:插件实现 OAuth 2.0 Device Authorization Grant,自行持久化、刷新和撤销 token。
15
+
16
+ 本 ADR 替代 ADR-0001 中“首版拒绝自行 OAuth”的部分;固定 Proxy、失败关闭和 Host-only token 边界仍有效。
17
+
18
+ ## 决策
19
+
20
+ ### 1. 明确选择,不静默混用
21
+
22
+ 设置 `authMode` 只能是 `official-cli` 或 `managed-device`。每次 `prepareCall()` 冻结认证 generation;同一请求不能从一条路径取模型目录、再从另一条路径取 token。401、缺失或过期都不得自动切换认证来源。
23
+
24
+ ### 2. 自管路径使用 device flow
25
+
26
+ `managed-device` 使用固定 issuer `https://auth.x.ai` 的 discovery 文档,并只接受以下精确端点:
27
+
28
+ - device authorization:`https://auth.x.ai/oauth2/device/code`
29
+ - token:`https://auth.x.ai/oauth2/token`
30
+ - revoke:`https://auth.x.ai/oauth2/revoke`
31
+ - JWKS:`https://auth.x.ai/.well-known/jwks.json`
32
+
33
+ grant type 固定为 RFC 8628 device code;不启动 loopback listener,不接收粘贴 code,不使用 client secret。Web 只在明确用户手势后打开经过固定 origin/path 校验的 verification URI;TUI 显示脱敏的固定 xAI 地址与一次性 user code。轮询严格处理 `authorization_pending`、`slow_down`、过期、拒绝、取消与绝对超时。
34
+
35
+ ### 3. Client ID 是发布阻断项
36
+
37
+ 生产包只能内置 xAI 明确授权给本插件/第三方集成使用的 public client ID。不得直接把 Grok CLI 的 `b1a00492-073a-47ea-816f-4c329264a828` 当作本插件身份,也不得复制其他插件的 Client ID。
38
+
39
+ 当前 xAI discovery 证明 public-client、device-code、refresh-token 与 PKCE 能力存在,但公开文档没有提供第三方 client 注册流程。开发可通过注入 fake OAuth boundary 完成全部单元/集成测试;真实自管 OAuth smoke 和 npm 发布必须等待 xAI 授权的 client ID 或明确书面许可。该阻断不能用隐藏设置、环境变量或用户粘贴第三方 Client ID 绕过。
40
+
41
+ ### 4. 最小 scope
42
+
43
+ 当前官方 CLI access token 的脱敏 claim 显示其 scopes 包含:
44
+
45
+ ```text
46
+ openid profile email offline_access grok-cli:access api:access
47
+ conversations:read conversations:write workspaces:read workspaces:write
48
+ ```
49
+
50
+ 这只是上游 CLI 的现状,不是本插件应复制的最小集合。自管客户端首先请求 `openid offline_access grok-cli:access`,再通过 xAI 授权文件和真实 Proxy 门禁确认是否必须增加 scope。不得请求 `api-keys:*`、`logs:read` 或与 LLM Provider 无关的权限。scope 不足必须明确失败,不能暗中扩大授权。
51
+
52
+ ### 5. 使用 Harness credential record
53
+
54
+ 自管 grant 只通过 `ctx.credentials` 的 owner-scoped record 持久化:
55
+
56
+ ```text
57
+ credentialKey(<最终 package owner>, "grok-oauth")
58
+ ```
59
+
60
+ payload 使用版本化闭合 schema,只保存协议所需的 `accessToken`、`refreshToken`、`expiresAt`、`issuer`、`clientId`、`scopes` 和 `generation`;不保存 email、姓名、头像、team/org、ID token 或 userinfo。刷新必须在 `modifyRecord()` 的跨进程排他读改写中完成,以兼容 refresh-token rotation。
61
+
62
+ Harness rc.2 的默认 `dsh-credentials-local` 会把 grant 明文保存在 `$DSH_HOME/.credentials.yaml`:POSIX 为 `0700` 目录和 `0600` 文件、原子写入并拒绝宽权限;Windows 无法用 POSIX mode 验证 ACL。同一 OS 用户及其 agent 工具进程仍可能读取文件。这是明确披露的边界,不得称为 Keychain、Credential Manager、DPAPI 或“加密存储”。未来 Harness 提供 OS-keychain provider 时无需改变本插件 record 接口即可获得更强存储。
63
+
64
+ ### 6. 刷新与注销
65
+
66
+ - 发送前进入固定 skew 时,在 credential record 的原子 mutation 内刷新一次;并发进程不能各自覆盖旋转后的 refresh token。
67
+ - token 响应、错误 body 与 JWT 均有字节/字段上限;不得记录原文。
68
+ - 已发送 POST 收到 401 后不自动重放;使 generation 失效,下一次明确请求才尝试刷新或返回 `AUTH`。
69
+ - managed logout 先在原子 mutation 中把 grant 替换为不可用于推理/刷新的 revocation marker,再调用固定 revoke endpoint。远端撤销成功后删除本地 record;失败时原子恢复原 grant 以便用户明确重试。若恢复本身失败则保留不可用 marker,绝不能让待撤销 token 重新进入推理路径。
70
+ - official-cli logout 仍调用受限官方 CLI,绝不删除自管 record;两种 logout 必须显示作用域并分别二次确认。
71
+
72
+ ## 后果
73
+
74
+ - 用户可以选择共享官方 CLI 会话,或使用插件独立会话。
75
+ - 插件承担 OAuth 协议、refresh rotation 和持久化安全责任;安全测试面显著扩大。
76
+ - `@deepseek-ai/dsh-credentials@0.1.1-rc.2` 成为自管模式的 required capability;缺失时该模式禁用,但 official-cli 模式仍可启动。
77
+ - 没有 xAI 授权的 client ID 时,自管模式不得进行生产真机登录,整个 `0.1.0` 也不得按当前用户要求发布。
@@ -0,0 +1,34 @@
1
+ # ADR-0004:动态支持账号可用的全部 Grok Build 模型
2
+
3
+ - 状态:已接受
4
+ - 日期:2026-08-25
5
+
6
+ ## 背景
7
+
8
+ 仓库所有者要求插件可调用 Grok Build 支持的全部模型。模型集合会随账号、团队、区域和上游发布变化,静态只注册 `grok-build` 会漏模型。
9
+
10
+ 2026-08-26 在本机官方 Grok CLI `1.0.5` 的真实账号发现结果为:
11
+
12
+ - `grok-4.6`(默认)
13
+ - `grok-4.5`
14
+
15
+ 该结果是账号/时点快照,不是永久白名单。
16
+
17
+ ## 决策
18
+
19
+ - Provider ID 保持 `grok`。
20
+ - `LlmAdapter.listModels()` 通过固定 `GET https://cli-chat-proxy.grok.com/v1/models` 动态发现当前所选认证来源实际可用的全部模型。
21
+ - 使用有界、严格 schema 的内存 TTL cache;认证 generation、logout、401 或 credential record 变化立即失效。不同账号或 credential generation 不能共享 catalog。
22
+ - 列表按上游默认模型优先,其余使用稳定排序;去重后返回 Harness `LlmModelInfo`。模型 ID、名称和显式能力来自经过验证的上游字段,不根据名字猜 context、最大输出或 reasoning effort。
23
+ - `resolveModel()` 对明确选择但暂未出现在缓存目录中的 ID执行一次可取消刷新。Harness 的 catalog 是 discovery surface,不是路由白名单;仍必须让 Proxy 对账号权限做最终判定。
24
+ - 上游模型新增时无需发布新 npm 版本;未知字段有界忽略,未知模型能力保持 absent,而不是伪造默认值。
25
+ - 当前两个模型都声明 backend `responses` 与 500000 context;`grok-4.6` efforts 为 `xhigh|high|medium|low`,`grok-4.5` 为 `high|medium|low`,两者默认 `high`。这些值来自动态 schema,不硬编码成所有账号/未来版本的事实。
26
+ - 一个模型只有在其目录 `api_backend` 有已验证 codec 时才能真正调用;真实目录若出现 unsupported backend,发布门禁必须失败并明确列出,不能静默删掉该模型来伪称“全部支持”。
27
+ - 无认证时返回空目录并给出脱敏 auth 状态;网络失败时只可返回同一 auth generation 的短期 last-known-good 内存快照,进程重启后不持久化旧目录。
28
+ - `grok-4.6` 和 `grok-4.5` 仅作为协议测试与离线 UI fixture,不作为生产硬编码的完整集合。
29
+
30
+ ## 测试门禁
31
+
32
+ - fake `/v1/models` 覆盖 0/1/N、重复 ID、恶意长字段、未知字段、错误类型、超限、401、重定向、取消和换账号竞态。
33
+ - 真实 macOS/Windows smoke 比较插件目录与同一账号同时刻的官方 `grok models` 输出;插件不得漏掉官方列表中的模型。
34
+ - 对每个真实发现模型至少完成一次最小流式文本请求;工具、reasoning 和 usage 能力只在该模型实际声明/验证后曝光。
@@ -0,0 +1,36 @@
1
+ # ADR-0005:`0.1.0` 收敛为官方 CLI 单一认证路径
2
+
3
+ - 状态:Accepted
4
+ - 日期:2026-08-26
5
+ - 取代:ADR-0003 在 `0.1.0` 中关于 `managed-device`、插件持久化 OAuth grant 和双认证选择的决定
6
+
7
+ ## 背景
8
+
9
+ 仓库所有者将首版要求调整为“能够从 Harness 跳转浏览器登录即可”。xAI 当前没有公开的第三方 OAuth client 自助注册入口;复制官方 Grok CLI 或其他应用的 client ID 会让本插件冒充另一客户端,也会增加无法独立审计的授权与封禁风险。
10
+
11
+ 官方 Grok CLI 已提供浏览器 OAuth 登录并负责自己的 token 持久化。插件只需要从 Host 经 Harness subprocess seam 调用固定的 `grok login --oauth`,无需拥有第二套 OAuth 身份或 refresh token 生命周期。
12
+
13
+ ## 决定
14
+
15
+ `0.1.0` 只提供官方 CLI 认证:
16
+
17
+ - Web 设置页只有一张官方 CLI 登录卡;不显示模式选择或 device-code UI。
18
+ - TUI 语法只有 `/grok status|login|cancel|logout`。
19
+ - RPC 只有 `status`、`login`、`cancel`、`logout`;请求中不存在 `authMode`。
20
+ - Host 不注入 Harness credentials capability,不包含 OAuth client ID、client secret、device flow、插件实现的 refresh/revoke 或独立 grant store。
21
+ - 官方 CLI 通过系统浏览器完成授权并持久化 `auth.json`。插件只做有界、只读、版本/schema/权限约束的 credential snapshot,并且不提取、使用或写回其中的 refresh token。完全匹配的 access token 过期时,插件可 single-flight 启动固定、30 秒有界的 `grok models`,由官方 CLI 完成 refresh grant 和文件写回;随后只重读、重新校验并重试一次。
22
+ - 模型发现与推理仍使用固定 Grok Build HTTPS endpoints,并动态暴露账号目录中的全部受支持模型。
23
+
24
+ ## 后果
25
+
26
+ - xAI 独立 OAuth Client ID 不再是 `0.1.0` 发布阻断项。
27
+ - 用户必须安装并信任受支持版本的官方 Grok CLI;登录与注销会影响共享同一 Grok home 的其他客户端。
28
+ - 插件不能承诺在没有官方 CLI 的环境中登录或续期,也不拥有 OAuth refresh token 协议或凭据迁移能力。
29
+ - 如果未来取得 xAI 明确授权的独立 public client,需要新的 ADR、独立安全评审和新的版本;不得在 `0.1.x` 中以隐藏配置恢复已删除路径。
30
+
31
+ ## 非方案
32
+
33
+ - 不复制、提取或反编译官方 CLI 的 OAuth client ID。
34
+ - 不接受用户粘贴任意第三方 client ID。
35
+ - 不把官方 refresh token 复制到 Harness credentials、settings、环境变量或 workspace。
36
+ - 不用 API key 冒充浏览器 OAuth 登录。
@@ -0,0 +1,84 @@
1
+ # ADR-0006:账户额度与模型能力面板
2
+
3
+ - 状态:Accepted
4
+ - 日期:2026-08-26
5
+ - 适用版本:`0.1.0`
6
+
7
+ ## 背景
8
+
9
+ 设置页需要提供接近 Harness 现有 Provider 页面的一屏式账户概览:登录状态、真实使用额度、额度周期结束时间,以及账号当前可见模型的能力。视觉参考只定义信息层级和交互密度,不构成协议或字段定义。
10
+
11
+ xAI 官方 Grok Build 源码公开了两条可复用的 CLI Proxy 能力:
12
+
13
+ - `GET /v1/models`:返回账号当前可见模型与 capability metadata。
14
+ - `GET /v1/billing?format=credits`:返回 included credit 使用百分比与当前周/月周期;周期 `end` 是额度重置时间。旧账号可能只返回 `monthlyLimit`、`used` 与 `billingPeriodEnd`。
15
+
16
+ 官方 billing 请求还要求 credential 中的 `user_id` 作为 `x-userid` header。它只在 Host credential lease 内使用,不进入 renderer。
17
+
18
+ 官方实现依据:[`extensions/billing.rs`](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-shell/src/extensions/billing.rs)。2026-08-26 的本机真实响应确认周期与 reset 可用,但未携带使用百分比;同一账号的官方移动端在完全相同的周期结束时间显示 `0% 已使用`。这符合 proto3 JSON 省略默认标量零值的行为,因此只有完整、类型化的新周期能把缺失百分比解释为零。
19
+
20
+ ## 决策
21
+
22
+ ### 1. Host 直接访问固定官方端点
23
+
24
+ 额度与模型查询都复用现有 `OfficialSessionCredentialSource` 和 `PinnedGrokTransport`:
25
+
26
+ - origin 固定为 `https://cli-chat-proxy.grok.com`;
27
+ - path 固定,禁止 renderer、settings 或配置传入 URL;
28
+ - `redirect: "error"`,15–30 秒 deadline,JSON 响应 256 KiB 上限;
29
+ - Bearer token 与 `user_id` 只存在于一次 Host callback 和请求 headers 中。
30
+
31
+ 不启动 Grok agent、不解析 TUI 文本、不抓取日志,也不读取浏览器 cookie。
32
+
33
+ ### 2. 页面只接收脱敏 dashboard DTO
34
+
35
+ 新增闭合 RPC action `dashboard`,只接受空对象。成功 DTO 仅包含:
36
+
37
+ - `models[]`:`id`、`name`、可选 `description`、`contextWindow`、reasoning efforts/default;
38
+ - `quota`:闭合状态与可选 `usedPercent`、`remainingPercent`、`periodKind`、`periodStart`、`resetsAt`;
39
+ - `fetchedAt`。
40
+
41
+ 禁止返回 access/refresh token、credential path、`user_id`、email、姓名、team/principal ID、原始上游 JSON、任意 URL、请求 headers 或原始错误。
42
+
43
+ ### 3. 额度语义
44
+
45
+ - 优先使用 `creditUsagePercent`。
46
+ - 若百分比缺失,但 `currentPeriod.type` 是官方 weekly/monthly 枚举,且 `start`、`end` 都是有效时间,则解释为 protobuf 省略的 `0% 已使用`。这是新版 credits shape 的零值恢复,不是通用缺省值。
47
+ - 若不存在上述完整周期,只有 `monthlyLimit.val > 0`、`used.val >= 0` 时才计算旧格式百分比。
48
+ - UI 同时显示“已使用”和“剩余”;进度条填充表示剩余额度,与参考 UI 一致。
49
+ - `currentPeriod.end` 或旧格式 `billingPeriodEnd` 才能显示为“重置时间”。OAuth `expires_at` 绝不当作额度刷新时间。
50
+ - 周期类型只接受官方 weekly/monthly 枚举;未知类型显示“当前额度周期”,不猜测。
51
+ - 不满足新版零值恢复或旧版计数条件时,百分比显示“上游未提供使用比例”;周期结束缺失时显示“上游未提供重置时间”。
52
+ - 页面提供手动刷新;初次进入自动获取一次。登录进行中的每秒轮询只调用轻量 `status`,不轮询 billing/models。
53
+
54
+ ### 4. 模型能力语义
55
+
56
+ 模型必须来自本次动态 catalog;不维护静态模型白名单。首版展示已验证的 capability:
57
+
58
+ - 文本输入;
59
+ - 上下文窗口;
60
+ - reasoning efforts 与默认 effort;
61
+ - Responses 流式输出;
62
+ - function tools(Provider transport 已覆盖)。
63
+
64
+ 模型列表是能力展示,不在 `0.1.0` 增加隐藏/禁用模型设置。所有账号可见模型继续出现在 Harness 模型选择器中,避免 UI 过滤与“支持所有模型”的产品要求冲突。
65
+
66
+ ## 失败行为
67
+
68
+ - 未登录:只展示登录引导,不发 billing/models 请求。
69
+ - billing 失败但 models 成功:模型卡正常显示,额度卡显示不可用。
70
+ - models 失败但 billing 成功:额度卡正常显示,模型卡显示不可用。
71
+ - 401/403:dashboard 返回固定的 unavailable 状态,不泄露上游正文;认证状态在下次刷新时重新校验。
72
+ - 旧/新增字段:严格抽取已知安全字段,忽略 history、balances、identity 和未知字段;已知字段类型不合法时该分支失败关闭。
73
+
74
+ ## 安全影响
75
+
76
+ 该功能扩大了固定 xAI Proxy path 集合,并在 credential lease 内新增 `user_id` metadata。renderer 可看到订阅使用比例与周期,这属于用户主动打开本机设置页时要求展示的账号信息;RPC 仍受 loopback authority 限制。额度不持久化到插件配置或 workspace。
77
+
78
+ ## 验证门禁
79
+
80
+ - parser fixture 覆盖新 credits、完整类型化周期的 protobuf 零值恢复、不完整/未知周期、旧 monthly、字段缺失、越界百分比、超大/错误 JSON。
81
+ - transport 测试断言固定 URL、method、redirect、headers、deadline 与响应上限。
82
+ - RPC 测试断言闭合 payload、64 KiB 序列化边界和原始错误折叠。
83
+ - client bundle 测试断言无 token/path/identity 字段,并渲染 dashboard 关键文案。
84
+ - macOS 使用本机已授权 Grok Build 做脱敏真值 smoke;Windows 首版发布后真机验证,发布前保持“代码支持、真机未验证”。
@@ -0,0 +1,3 @@
1
+ - insert:
2
+ - id: llm-grok
3
+ name: dsh-grok-provider
package/package.json ADDED
@@ -0,0 +1,92 @@
1
+ {
2
+ "name": "dsh-grok-provider",
3
+ "version": "0.1.0",
4
+ "description": "Clean-room Grok Build provider for DeepSeek Harness with official CLI browser authentication",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "YukiRyou",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/yoshino-xiao7/dsh-grok-provider.git"
11
+ },
12
+ "homepage": "https://github.com/yoshino-xiao7/dsh-grok-provider#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/yoshino-xiao7/dsh-grok-provider/issues"
15
+ },
16
+ "engines": {
17
+ "node": ">=24.19.0"
18
+ },
19
+ "exports": {
20
+ ".": {
21
+ "types": "./types/index.d.ts",
22
+ "default": "./dist/host/index.mjs"
23
+ },
24
+ "./client": {
25
+ "default": "./dist/client/client.js"
26
+ },
27
+ "./package.json": "./package.json"
28
+ },
29
+ "dsh": {
30
+ "bundle": {
31
+ "patch": "grok-provider.patch.yml"
32
+ },
33
+ "client": {
34
+ "inject": [
35
+ "@deepseek-ai/dsh-client-connection",
36
+ "@deepseek-ai/dsh-client-locale",
37
+ "@deepseek-ai/dsh-client-runtime",
38
+ "@deepseek-ai/dsh-client-ui-settings"
39
+ ],
40
+ "platform": "web"
41
+ }
42
+ },
43
+ "files": [
44
+ "dist",
45
+ "docs",
46
+ "types",
47
+ "grok-provider.patch.yml",
48
+ "README.md",
49
+ "README.en.md",
50
+ "CONTRIBUTING.md",
51
+ "SECURITY.md",
52
+ "LICENSE",
53
+ "CHANGELOG.md"
54
+ ],
55
+ "scripts": {
56
+ "build": "node scripts/build.mjs",
57
+ "test": "npm run build && node --test spikes/protocol/test/*.test.mjs test/*.test.mjs",
58
+ "prepack": "npm run build",
59
+ "pack:check": "npm pack --dry-run --json"
60
+ },
61
+ "peerDependencies": {
62
+ "@deepseek-ai/cordis": "4.0.1",
63
+ "@deepseek-ai/dsh-client-connection": "0.1.1-rc.2",
64
+ "@deepseek-ai/dsh-client-locale": "0.1.1-rc.2",
65
+ "@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
66
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.1-rc.2",
67
+ "@deepseek-ai/dsh-commands": "0.1.1-rc.2",
68
+ "@deepseek-ai/dsh-llm": "0.1.1-rc.2",
69
+ "@deepseek-ai/dsh-subprocess": "0.1.1-rc.2",
70
+ "@deepseek-ai/schemastery": "3.18.1"
71
+ },
72
+ "peerDependenciesMeta": {
73
+ "@deepseek-ai/dsh-client-connection": { "optional": true },
74
+ "@deepseek-ai/dsh-client-locale": { "optional": true },
75
+ "@deepseek-ai/dsh-client-runtime": { "optional": true },
76
+ "@deepseek-ai/dsh-client-ui-settings": { "optional": true },
77
+ "@deepseek-ai/dsh-commands": { "optional": true },
78
+ "@deepseek-ai/dsh-subprocess": { "optional": true }
79
+ },
80
+ "devDependencies": {
81
+ "@deepseek-ai/cordis": "4.0.1",
82
+ "@deepseek-ai/dsh-commands": "0.1.1-rc.2",
83
+ "@deepseek-ai/dsh-llm": "0.1.1-rc.2",
84
+ "@deepseek-ai/dsh-subprocess": "0.1.1-rc.2",
85
+ "@deepseek-ai/schemastery": "3.18.1"
86
+ },
87
+ "publishConfig": {
88
+ "access": "public",
89
+ "registry": "https://registry.npmjs.org/",
90
+ "provenance": true
91
+ }
92
+ }
@@ -0,0 +1,9 @@
1
+ import type { Context } from "@deepseek-ai/cordis"
2
+ import type Schema from "@deepseek-ai/schemastery"
3
+
4
+ export interface Config {}
5
+
6
+ export declare const name: "llm-grok"
7
+ export declare const inject: readonly ["llm"]
8
+ export declare const Config: Schema<Config>
9
+ export declare function apply(ctx: Context): void