dsh-cloudq 0.1.2 → 0.1.4

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.md CHANGED
@@ -1,67 +1,69 @@
1
1
  # dsh-cloudq
2
2
 
3
- 面向 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 的 CloudQ 集成插件。插件为 Web Profile 提供 CloudQ 模式,内置 `cloudq` Skill,并提供 CloudQ 用量、架构视图、本地凭证配置和插件管理能力。
3
+ English | [简体中文](README-zh.md)
4
4
 
5
- ## 截图
5
+ CloudQ integration for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness). It adds a CloudQ mode to the Web profile, bundles the `cloudq` skill, and provides CloudQ usage and architecture views, local credential setup, and plugin management.
6
6
 
7
- ![CloudQ 风险分析对话](assets/screenshots/chat-risk-analysis.png)
7
+ ## Screenshots
8
8
 
9
- ![CloudQ 设置与插件管理](assets/screenshots/settings.png)
9
+ ![CloudQ risk analysis conversation](assets/screenshots/chat-risk-analysis.png)
10
10
 
11
- ## 环境要求
11
+ ![CloudQ settings and plugin management](assets/screenshots/settings.png)
12
+
13
+ ## Requirements
12
14
 
13
15
  - Node.js `>=22.19.0`
14
- - DeepSeek Harness `0.1.1-rc.2` 或兼容的更高 `0.1.x` 版本
15
- - `dsh plugin` 命令可调用 `pnpm`
16
- - 可通过 `python3` 命令运行 Python 3
17
- - macOS Linux
16
+ - DeepSeek Harness `0.1.1-rc.2` or a compatible newer `0.1.x` release
17
+ - `pnpm` available to the `dsh plugin` command
18
+ - Python 3 available as `python3`
19
+ - macOS or Linux
18
20
 
19
- ## 安装
21
+ ## Install
20
22
 
21
23
  ```sh
22
24
  dsh plugin --profile web add dsh-cloudq
23
25
  ```
24
26
 
25
- 安装完成后重启 Web Profile:
27
+ Restart the Web profile after installation:
26
28
 
27
29
  ```sh
28
30
  dsh --profile web
29
31
  ```
30
32
 
31
- 打开 DSH 输出的访问地址,即可在对话输入区和侧边栏看到 CloudQ 入口。也可以通过 `/cloudq` 显式调用内置 Skill。
33
+ Open the URL printed by DSH. The conversation input area and sidebar will expose the CloudQ entry. You can also invoke the bundled skill explicitly with `/cloudq`.
32
34
 
33
- ## 升级与卸载
35
+ ## Upgrade and remove
34
36
 
35
37
  ```sh
36
38
  dsh plugin --profile web update dsh-cloudq
37
39
  dsh plugin --profile web remove dsh-cloudq
38
40
  ```
39
41
 
40
- 修改已安装的插件后,需要重启 Web Profile。
42
+ Restart the Web profile after changing the installed package set.
41
43
 
42
- ## 凭证配置
44
+ ## Credentials
43
45
 
44
- 设置卡片支持配置腾讯云 `SecretId` `SecretKey` 凭证。
46
+ The settings card accepts a Tencent Cloud `SecretId`/`SecretKey` pair.
45
47
 
46
- - 凭证保存在本机 `~/.tencent-cloudq/credential.json`,文件权限仅允许当前用户访问。
47
- - 敏感凭证通过标准输入传递给 Python 辅助脚本,不会放入命令行参数。
48
- - 浏览器接口仅返回凭证状态和脱敏标识,不返回凭证内容或本地凭证路径。
49
- - 可通过退出登录操作删除本地凭证。
48
+ - Credentials are stored locally at `~/.tencent-cloudq/credential.json` with owner-only permissions.
49
+ - Secret values are sent to Python helpers through standard input, never command-line arguments.
50
+ - Browser APIs return only credential state and masked identifiers; local credential paths and secret values are not returned.
51
+ - Use the logout action to remove the stored credential.
50
52
 
51
- 请遵循最小权限原则,只授予 CloudQ 操作所需的权限。内置 Skill 可以调用云管理的读写操作,请在批准前检查每项操作的具体内容。
53
+ Follow least-privilege: grant only the permissions required for the CloudQ operations you intend to run. The bundled skill can invoke read and write cloud-management operations; review each action before approving it.
52
54
 
53
- ## 安全机制
55
+ ## Security model
54
56
 
55
- - Host API 只接受来自回环地址的同源请求。
56
- - JSON 请求体大小限制为 64 KiB
57
- - Python 辅助脚本的输出大小受到限制,非预期的内部错误不会返回到浏览器。
58
- - 远程数据通过 DOM 文本节点渲染,不使用 HTML 注入。
59
- - 下载链接必须使用 HTTPS
60
- - npm 包不包含凭证、Token 或本地环境文件。
57
+ - Host APIs accept only loopback, same-origin requests.
58
+ - JSON request bodies are limited to 64 KiB.
59
+ - Python helper output is bounded, and unexpected internal errors are not returned to the browser.
60
+ - Remote values are inserted with DOM text nodes rather than HTML injection.
61
+ - Download links require HTTPS.
62
+ - No credentials, tokens, or local environment files are included in the npm package.
61
63
 
62
- 如需报告安全问题,请通过 [GitHub Issues](https://github.com/TencentCloud/cloudq-for-dsh/issues) 提交,且不要附带真实凭证。
64
+ Report security issues through [GitHub Issues](https://github.com/TencentCloud/cloudq-for-dsh/issues) without including live credentials.
63
65
 
64
- ## 本地开发
66
+ ## Development
65
67
 
66
68
  ```sh
67
69
  pnpm install
@@ -73,28 +75,28 @@ pnpm run check:client
73
75
  npm pack --dry-run --registry=https://registry.npmjs.org/
74
76
  ```
75
77
 
76
- npm 包内包含预构建的 Host Web Client 产物、Bundle Patch、CloudQ 运行时图标以及内置 Skill。用户从 Registry 安装时不需要执行构建脚本。
78
+ The npm package ships prebuilt Host and Web client artifacts, the bundle patch, the runtime logo, and the bundled skill. Registry installation runs no build scripts.
77
79
 
78
- ## 目录结构
80
+ ## Repository layout
79
81
 
80
82
  ```text
81
- src/ Host Web Client 源码
82
- skills/cloudq/ 内置 CloudQ Skill Python 辅助脚本
83
- assets/cloudq.png Host 提供的运行时图标
84
- scripts/ 构建和发布检查脚本
85
- tests/ 单元测试、集成测试与包契约测试
86
- cordis.patch.yml DSH Bundle 配置层
83
+ src/ Host and Web client source
84
+ skills/cloudq/ Bundled CloudQ skill and Python helpers
85
+ assets/cloudq.png Runtime logo served by the Host
86
+ scripts/ Build and release checks
87
+ tests/ Unit, integration, and package-contract tests
88
+ cordis.patch.yml DSH bundle layer
87
89
  ```
88
90
 
89
- ## 发布
91
+ ## Release
90
92
 
91
- 源码在 [TencentCloud/cloudq-for-dsh](https://github.com/TencentCloud/cloudq-for-dsh) 完成评审和版本管理。只有仓库检查与安装包冒烟测试全部通过后,才可将 npm 版本发布到官方 Registry。
93
+ Source is reviewed and versioned in [TencentCloud/cloudq-for-dsh](https://github.com/TencentCloud/cloudq-for-dsh). An npm version is published to the official registry only after the repository checks and the package-install smoke test pass.
92
94
 
93
- ## 更多文档
95
+ ## More documentation
94
96
 
95
- - 更新日志:[`CHANGELOG.md`](CHANGELOG.md)
96
- - 开发与维护指南:[`DEVELOPMENT.md`](DEVELOPMENT.md)
97
+ - Changelog: [`CHANGELOG.md`](CHANGELOG.md)
98
+ - Development & maintenance guide: [`DEVELOPMENT.md`](DEVELOPMENT.md)
97
99
 
98
- ## 许可证
100
+ ## License
99
101
 
100
- 本项目采用 MIT 许可证,详情请参阅 [`LICENSE`](LICENSE)
102
+ MIT. See [`LICENSE`](LICENSE).
package/lib/client.js CHANGED
@@ -2134,7 +2134,7 @@ display: none;
2134
2134
  hint.className = "dsh-cloudq-panel__hint";
2135
2135
  hint.textContent = "正在加载用量…";
2136
2136
  tableWrap.appendChild(hint);
2137
- cloudqRequest(`${API_USAGE}?start=${encodeURIComponent(range.start)}&end=${encodeURIComponent(range.end)}`).then((data) => {
2137
+ requireCloudqCredential().then(() => cloudqRequest(`${API_USAGE}?start=${encodeURIComponent(range.start)}&end=${encodeURIComponent(range.end)}`)).then((data) => {
2138
2138
  if (panelView !== "usage" || !panelExpanded) return;
2139
2139
  value.textContent = formatCredits(data.overview?.TotalCredits);
2140
2140
  const rows = Array.isArray(data.detail) ? data.detail : [];
@@ -2300,7 +2300,7 @@ display: none;
2300
2300
  hint.className = "dsh-cloudq-panel__hint";
2301
2301
  hint.textContent = "正在加载灵感…";
2302
2302
  list.appendChild(hint);
2303
- cloudqRequest(API_INSPIRATIONS).then((data) => {
2303
+ requireCloudqCredential().then(() => cloudqRequest(API_INSPIRATIONS)).then((data) => {
2304
2304
  inspirationCache = Array.isArray(data.inspirations) ? data.inspirations : [];
2305
2305
  paint(inspirationCache);
2306
2306
  }).catch((error) => {
@@ -2442,7 +2442,7 @@ display: none;
2442
2442
  hint.className = "dsh-cloudq-panel__hint";
2443
2443
  hint.textContent = "正在加载制品…";
2444
2444
  panelBody.appendChild(hint);
2445
- cloudqRequest(API_ARTIFACTS).then((data) => {
2445
+ requireCloudqCredential().then(() => cloudqRequest(API_ARTIFACTS)).then((data) => {
2446
2446
  artifactCache = Array.isArray(data?.sessions) ? data.sessions : [];
2447
2447
  artifactTotal = Number(data?.total) || artifactCache.length;
2448
2448
  paint(artifactCache, artifactTotal);
@@ -2742,7 +2742,7 @@ display: none;
2742
2742
  paintDirectories(architectureDirectoriesCache, architectureFirstFolderId);
2743
2743
  return;
2744
2744
  }
2745
- cloudqRequest(API_ARCH_DIRECTORIES).then((data) => {
2745
+ requireCloudqCredential().then(() => cloudqRequest(API_ARCH_DIRECTORIES)).then((data) => {
2746
2746
  architectureDirectoriesCache = Array.isArray(data?.folders) ? data.folders : [];
2747
2747
  architectureFirstFolderId = Number(data?.firstFolderId) || null;
2748
2748
  paintDirectories(architectureDirectoriesCache, architectureFirstFolderId);
@@ -3041,14 +3041,32 @@ display: none;
3041
3041
  this.code = code;
3042
3042
  }
3043
3043
  };
3044
+ const CLOUDQ_AUTH_ERROR_CODES = /* @__PURE__ */ new Set([
3045
+ "NeedAuth",
3046
+ "CredentialExpired",
3047
+ "AuthFailure"
3048
+ ]);
3044
3049
  /**
3045
- * Panel-facing error text. A missing credential gets an actionable pointer to
3046
- * the settings card instead of a raw load failure message.
3050
+ * Panel-facing error text. Credential problems carry an actionable Host
3051
+ * message and are shown directly instead of a raw load failure prefix.
3047
3052
  */
3048
3053
  function cloudqPanelErrorText(error, prefix) {
3049
- if (error instanceof CloudQApiError && error.code === "NeedAuth") return "尚未配置 AK/SK,请前往「设置 → 插件 → CloudQ」完成配置后重试。";
3054
+ if (error instanceof CloudQApiError && CLOUDQ_AUTH_ERROR_CODES.has(error.code)) return error.message;
3050
3055
  return `${prefix}:${error instanceof Error ? error.message : "未知错误"}`;
3051
3056
  }
3057
+ /**
3058
+ * Reject with an actionable NeedAuth error when no credential is configured,
3059
+ * so data views show the settings guide without calling the CloudQ APIs.
3060
+ * Returns undefined when the status check itself fails, letting the data
3061
+ * request surface its own error.
3062
+ */
3063
+ function requireCloudqCredential() {
3064
+ return cloudqRequest(API_CREDENTIAL).then((response) => {
3065
+ if (response.status?.logged_in !== true) throw new CloudQApiError("尚未配置 AK/SK,请前往「设置 → 插件 → CloudQ」完成配置后重试。", "NeedAuth");
3066
+ }).catch((error) => {
3067
+ if (error instanceof CloudQApiError && error.code === "NeedAuth") throw error;
3068
+ });
3069
+ }
3052
3070
  async function cloudqRequest(url, init, timeoutMs = 2e4) {
3053
3071
  const controller = new AbortController();
3054
3072
  const timeout = window.setTimeout(() => controller.abort(), timeoutMs);
package/lib/index.js CHANGED
@@ -424,7 +424,11 @@ async function runScript(scriptName, args, options) {
424
424
  try {
425
425
  return await runScript$1(resolve(skillDirectory(), "scripts"), scriptName, args, options);
426
426
  } catch (error) {
427
- if (error instanceof HttpError && error.code === "NeedAuth") throw new HttpError(401, "NeedAuth", "尚未配置 AK/SK,请前往「设置 → 插件 → CloudQ」完成配置。");
427
+ if (error instanceof HttpError) {
428
+ if (error.code === "NeedAuth") throw new HttpError(401, "NeedAuth", "尚未配置 AK/SK,请前往「设置 → 插件 → CloudQ」完成配置。");
429
+ if (error.code === "CredentialExpired") throw new HttpError(401, "CredentialExpired", "凭证已过期,请前往「设置 → 插件 → CloudQ」重新配置。");
430
+ if (typeof error.code === "string" && error.code.startsWith("AuthFailure")) throw new HttpError(401, "AuthFailure", "AK/SK 无效或权限不足,请前往「设置 → 插件 → CloudQ」检查配置。");
431
+ }
428
432
  throw error;
429
433
  }
430
434
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-cloudq",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "CloudQ integration for DeepSeek Harness with secure credential, workspace, and plugin-management surfaces",
5
5
  "license": "MIT",
6
6
  "type": "module",