dsh-arcvista 0.1.1 → 0.1.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.3
4
+
5
+ - 健康检查与设置页现在报告实际使用的 SQLite 数据目录和包版本。
6
+
7
+ ## 0.1.2
8
+
9
+ - 设置页不再展示模型配置、环境变量或 Key 相关信息;模型统一由 DSH 提供。
10
+
3
11
  ## 0.1.1
4
12
 
5
13
  - 项目仓库统一为 GitHub,移除已失效的 Gitee 镜像与相关元数据。
package/README.md CHANGED
@@ -24,7 +24,7 @@ ArcVista 把这些问题做成一个可以直接下钻的看板,而不是一
24
24
  ![DSH 中的 ArcVista](docs/screenshots/dsh-plugin.png)
25
25
 
26
26
  - **不需要单独启动 Node 服务**:ArcVista 的 API 和静态页面由 DSH Host 插件直接挂载在 `/arcvista` 路径下;
27
- - **不需要配置模型**:分析使用 DSH 当前选择的默认模型(例如 `deepseek-flash`),模型调用通过 DSH 的 `llm` 服务完成;设置页会自动隐藏原来的模型 / API Key 配置;
27
+ - **不需要配置模型**:分析使用 DSH 当前选择的默认模型(例如 `deepseek-flash`),模型调用通过 DSH 的 `llm` 服务完成;设置页不提供模型配置;
28
28
  - 数据仍保存在本机:默认写在 `~/.dsh/arcvista/`(SQLite、备份和仓库镜像),不会写进 `node_modules`;
29
29
  - 面板顶部显示运行状态,右上角可以刷新或在独立浏览器窗口打开;
30
30
  - 主题跟随 DSH 的浅色 / 深色模式(映射到 `daylight` / `obsidian`),内嵌页面隐藏了 ArcVista 原来的左侧栏;
@@ -50,6 +50,32 @@ dsh plugin --profile web add dsh-arcvista
50
50
  dsh plugin --profile web add /absolute/path/to/arc-vista
51
51
  ```
52
52
 
53
+ ### 内网离线安装
54
+
55
+ 内网(无外网、无 npm registry)环境使用离线安装包,由仓库内的构建脚本生成:
56
+
57
+ ```bash
58
+ npm run package:intranet # 生成 ../arc-vista-intranet-installer/ 与 ../arc-vista-intranet-installer.zip
59
+ ```
60
+
61
+ 把 zip 拷进内网后解压:
62
+
63
+ - Windows:双击 `install.bat`;
64
+ - macOS:双击 `install.command`;
65
+ - 任意平台:`node install.mjs`(加 `--dry-run` 先看计划,`--verify` 检查状态,`--uninstall` 卸载)。
66
+
67
+ 安装器只做本地文件复制与 DSH profile 注册,不联网、不需要 pnpm;离线 tarball 会留在 profile 的
68
+ `.dsh-offline-plugins/` 里,之后用 pnpm 也能离线解析。装完重启 DSH Web,左侧栏出现「ArcVista 观界」。
69
+ 安装包自身说明见 `packaging/intranet/README.md`。
70
+
71
+ 内网安全团队需要审查时,生成配套的安全审查材料包:
72
+
73
+ ```bash
74
+ npm run package:security-review
75
+ # 生成 ../arc-vista-security-review/ 与 ../arc-vista-security-review.zip
76
+ # 含文件清单、SHA-256、SBOM、静态扫描证据、可复现构建步骤与审批申请模板
77
+ ```
78
+
53
79
  ### 发布与商店
54
80
 
55
81
  - 发布包名:`dsh-arcvista`
@@ -124,7 +150,7 @@ npm start
124
150
  - 由仓库结构、构建清单、网关路由、Feign 声明、编排配置与依赖推断生成的分层架构图:客户端 → 接入层 → 服务层 → 数据层 → 基础设施 / 外部系统。
125
151
  - 拖拽平移、滚轮缩放、节点悬停高亮依赖链路;点击节点打开节点详情(指标、复杂度驱动、上下游依赖、下钻入口)。
126
152
  - **下钻分析**:进入单个模块的内部结构(按 Controller / Service / Domain / DTO / 事件 / 配置等职责聚合的依赖子图)、关键流程、对外接口、调用方/被依赖方、数据组件、模块风险与改进建议;支持继续追问该模块。
127
- - 配置大模型后,架构的命名、业务职责、外部系统与连接会由模型基于代码证据做语义增强;没有模型时启发式结果同样完整可用。
153
+ - 模型由 DSH 统一提供,架构的命名、业务职责、外部系统与连接会基于代码证据做语义增强;没有模型时启发式结果同样完整可用。
128
154
 
129
155
  ### 2. 安全架构守护
130
156
 
@@ -142,7 +168,7 @@ npm start
142
168
  - 业务域来自服务边界;能力来自 Controller 聚合;实体来自领域模型;事件来自 Kafka / RabbitMQ 主题与监听器;数据组件来自依赖与编排配置;参与者来自客户端入口。
143
169
  - 卡片式业务域泳道:业务能力、领域实体、事件、数据组件、参与者分别用不同类型卡片呈现;接口与领域实体默认收起避免过密,可在筛选器中展开。
144
170
  - 普通滚动只滚动页面,`Ctrl/⌘ + 滚轮`或工具条缩放;点击节点查看业务含义,并从业务域下钻到对应代码模块。
145
- - 配置大模型后自动补充业务语义、业务能力、主业务流程(如"下单 → 支付 → 扣减库存 → 发货签收")与跨域事实。
171
+ - 模型由 DSH 统一提供,自动补充业务语义、业务能力、主业务流程(如"下单 → 支付 → 扣减库存 → 发货签收")与跨域事实。
146
172
 
147
173
  ### 4. 复杂度
148
174
 
@@ -170,27 +196,13 @@ npm start
170
196
  - **架构与业务 diff**:架构节点增减、业务域/实体/接口/事件变化。
171
197
  - **风险清单**:只把本次变更引入的风险计入结论;目标分支的历史高危单独列为"存量风险",避免把老问题算到新分支头上。
172
198
 
173
- ## 配置大模型
174
-
175
- 支持所有 OpenAI 兼容接口(DeepSeek / OpenAI / Moonshot / 通义千问 / 本地 Ollama 等)。
176
-
177
- 在页面左下角进入「模型设置」,填写 Base URL、模型名与 API Key,可一键测试连接。也可以用环境变量启动,环境变量优先级更高:
178
-
179
- ```bash
180
- ARCVISTA_LLM_API_KEY=sk-xxx \
181
- ARCVISTA_LLM_BASE_URL=https://api.deepseek.com/v1 \
182
- ARCVISTA_LLM_MODEL=deepseek-chat \
183
- npm start
184
- ```
199
+ ## 模型
185
200
 
186
- 模型会被用于:
201
+ 作为 DSH 插件运行时,分析始终使用 **DSH 当前选择的默认模型**(例如 `deepseek-flash`),不需要在 ArcVista 里配置 Base URL、模型名或 API Key。
187
202
 
188
- - 架构图的业务命名、分层语义、外部系统补全;
189
- - 业务知识图谱的业务域/能力/流程;
190
- - 基于指标的架构风险与治理建议;
191
- - 模块下钻的职责说明、内部结构与追问回答。
203
+ 模型用于:架构图的业务命名、分层语义与外部系统补全;业务知识图谱的业务域/能力/流程;架构风险与治理建议;模块下钻的职责说明与追问回答。
192
204
 
193
- **没有配置 Key 也能完整使用**:架构、依赖、安全守护、复杂度、覆盖率、知识图谱全部由静态分析引擎生成,风险规则照常运行。快照会记录当次使用的引擎(`LLM 语义增强` / `启发式`)。
205
+ 没有可用模型时,架构、依赖、安全守护、复杂度、覆盖率与知识图谱仍由静态分析引擎完整生成,风险规则照常运行。
194
206
 
195
207
  ## 工作方式
196
208
 
@@ -225,14 +237,13 @@ Git 仓库 ──► 本地镜像(bare)──► 按提交检出 worktree
225
237
 
226
238
  ## 数据、备份与隐私
227
239
 
228
- - 所有数据(产品、快照、下钻缓存、设置)保存在 `data/arcvista.db`(SQLite)。
229
- - 仓库镜像与检出代码在 `data/repos/`、`data/worktrees/`,可随时删除,重新分析会重建。
230
- - **自动备份**:启动时、每次分析完成以及删除产品前,会把 SQLite 快照写入 项目根目录的 `backups/`(默认保留 12 份,文件权限 600;可用 `ARCVISTA_BACKUP_DIR` 修改位置,`ARCVISTA_BACKUP_KEEP` 修改保留数量)。
231
- - **自动恢复**:如果 `data/arcvista.db` 缺失或无法打开,启动时会自动从最近一份包含产品的备份恢复,并在启动日志和设置页提示恢复来源。
240
+ - DSH 插件模式下,所有数据保存在 `~/.dsh/arcvista/arcvista.db`(SQLite);独立 CLI 模式使用 `data/`。
241
+ - 仓库镜像与检出代码在数据目录的 `repos/`、`worktrees/`,可随时删除,重新分析会重建。
242
+ - **自动备份**:启动时、每次分析完成以及删除产品前,会把 SQLite 快照写入数据目录的 `backups/`(默认保留 12 份,文件权限 600;可用 `ARCVISTA_BACKUP_DIR` 修改位置,`ARCVISTA_BACKUP_KEEP` 修改保留数量)。
243
+ - **自动恢复**:如果数据目录里的 `arcvista.db` 缺失或无法打开,启动时会自动从最近一份包含产品的备份恢复,并在启动日志和设置页提示恢复来源。
232
244
  - 设置页「当前状态」可以看到数据目录、备份目录和最近备份时间,也可以点「立即备份数据」手动备份。
233
245
  - 仓库镜像体积可能较大;备份只包含数据库(产品、快照、设置),不会重复备份仓库镜像。
234
- - API Key 只写入本地 SQLite(也会进入上述备份文件,文件权限 600,仅保存在本机),接口返回时脱敏;服务仅监听 `127.0.0.1`。
235
- - 只有配置大模型并执行分析时,才会把**仓库证据摘要**(模块、依赖、路由、配置、指标等,不含完整源码)发送给你配置的模型服务。
246
+ - 模型调用通过 DSH 的 `llm` 服务完成,ArcVista 不保存 API Key;分析时只把**仓库证据摘要**(模块、依赖、路由、配置、指标等,不含完整源码)发送给 DSH 当前模型。
236
247
 
237
248
  ## 环境变量
238
249
 
@@ -249,9 +260,6 @@ Git 仓库 ──► 本地镜像(bare)──► 按提交检出 worktree
249
260
  | `ARCVISTA_GIT_CLONE_TIMEOUT_MS` | `900000` | 单次克隆超时(默认 15 分钟) |
250
261
  | `ARCVISTA_GIT_FETCH_TIMEOUT_MS` | `300000` | 单次拉取超时(默认 5 分钟) |
251
262
  | `ARCVISTA_GIT_WORKTREE_TIMEOUT_MS` | `300000` | 单次检出超时(默认 5 分钟) |
252
- | `ARCVISTA_LLM_API_KEY` | — | 大模型 API Key(优先于页面设置) |
253
- | `ARCVISTA_LLM_BASE_URL` | — | 大模型 Base URL |
254
- | `ARCVISTA_LLM_MODEL` | — | 模型名 |
255
263
  | `ARCVISTA_DEBUG` | — | 打印异常堆栈 |
256
264
 
257
265
  ## API 一览
@@ -266,8 +274,6 @@ Git 仓库 ──► 本地镜像(bare)──► 按提交检出 worktree
266
274
  | `POST` | `/api/products/:id/modules/analyze` | 模块下钻(异步任务) |
267
275
  | `GET` | `/api/products/:id/compare` | 分支/快照对比 |
268
276
  | `GET` | `/api/jobs/:id` | 任务进度与日志 |
269
- | `GET/PUT` | `/api/settings` | 模型配置 |
270
- | `POST` | `/api/settings/test` | 测试模型连接 |
271
277
 
272
278
  ## 目录结构
273
279
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-arcvista",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "ArcVista 观界 —— DSH 内的架构观测台:架构图、安全守护、业务知识图谱、复杂度与分支风险对比",
@@ -54,7 +54,9 @@
54
54
  "start": "node --disable-warning=ExperimentalWarning server.js",
55
55
  "dev": "node --disable-warning=ExperimentalWarning --watch server.js",
56
56
  "test": "node --disable-warning=ExperimentalWarning --test tests/*.test.js",
57
- "prepack": "node --disable-warning=ExperimentalWarning scripts/check-package.mjs"
57
+ "prepack": "node --disable-warning=ExperimentalWarning scripts/check-package.mjs",
58
+ "package:intranet": "node --disable-warning=ExperimentalWarning scripts/build-intranet-package.mjs",
59
+ "package:security-review": "node --disable-warning=ExperimentalWarning scripts/build-intranet-package.mjs && node --disable-warning=ExperimentalWarning scripts/build-security-review.mjs"
58
60
  },
59
61
  "dsh": {
60
62
  "bundle": {
@@ -21,7 +21,7 @@ export async function renderSettings(main, ctx) {
21
21
  <div>
22
22
  <div class="eyebrow">CONFIGURATION · 观测参数</div>
23
23
  <h1 class="page-title">${dshManaged ? '观测<em>配置</em>' : '模型与<em>观测配置</em>'}</h1>
24
- <p class="page-sub">${dshManaged ? 'ArcVista 现在运行在 DSH 插件中,模型由 DSH 统一提供,不需要单独配置 API Key。分析结论与快照仍保存在本机。' : 'ArcVista 是本地工具,分析结论与快照全部保存在你自己的机器上。配置一个 OpenAI 兼容的大模型后,架构语义、业务知识图谱、风险判断与模块下钻会由模型增强;不配置也能使用完整的启发式分析。'}</p>
24
+ <p class="page-sub">${dshManaged ? 'ArcVista 现在运行在 DSH 插件中,模型由 DSH 统一提供,无需单独设置。分析结论与快照仍保存在本机。' : 'ArcVista 是本地工具,分析结论与快照全部保存在你自己的机器上。配置一个 OpenAI 兼容的大模型后,架构语义、业务知识图谱、风险判断与模块下钻会由模型增强;不配置也能使用完整的启发式分析。'}</p>
25
25
  </div>
26
26
  <div class="masthead-right">
27
27
  <div class="masthead-meta">${dshManaged ? 'DSH MODEL' : llm.enabled ? 'MODEL ONLINE' : 'HEURISTIC MODE'}<br/><b>${dshManaged ? esc(llm.model || 'DSH') : llm.enabled ? esc(llm.model || '') : '需要在下方配置 Key'}</b></div>
@@ -48,7 +48,7 @@ export async function renderSettings(main, ctx) {
48
48
  </div>
49
49
  </div>
50
50
 
51
- ${dshManaged ? `<div class="banner banner--teal mb-24"><span>${icon('shield', 16)}</span><div><strong>模型由 DSH 统一提供</strong> 当前使用 <span class="mono">${esc(llm.model || 'DSH')}</span>,无需配置 API Key;密钥由 DSH 管理。</div></div>` : ''}
51
+ ${dshManaged ? `<div class="banner banner--teal mb-24"><span>${icon('shield', 16)}</span><div><strong>模型由 DSH 统一提供</strong> 当前使用 <span class="mono">${esc(llm.model || 'DSH')}</span>;无需在 ArcVista 内配置。</div></div>` : ''}
52
52
  <div class="settings-grid">
53
53
  <div class="panel" ${dshManaged ? 'style="display:none"' : ''}>
54
54
  <div class="panel-head">
@@ -113,10 +113,12 @@ export async function renderSettings(main, ctx) {
113
113
  <div class="panel-head"><div><div class="panel-title">当前状态</div></div></div>
114
114
  <div class="panel-body">
115
115
  <dl class="kv-list">
116
- <div class="kv"><dt>模型增强</dt><dd>${dshManaged ? '<span class="teal">由 DSH 提供</span>' : llm.enabled ? '<span class="teal">已启用</span>' : '<span class="amber">启发式模式</span>'}</dd></div>
117
- <div class="kv"><dt>Base URL</dt><dd class="mono" style="font-size:10px;word-break:break-all">${dshManaged ? 'DSH 内置' : esc(llm.baseUrl || '—')}</dd></div>
116
+ ${dshManaged
117
+ ? '<div class="kv"><dt>模型(DSH 提供)</dt><dd class="mono">' + esc(llm.model || 'DSH') + '</dd></div>'
118
+ : `<div class="kv"><dt>模型增强</dt><dd>${llm.enabled ? '<span class="teal">已启用</span>' : '<span class="amber">启发式模式</span>'}</dd></div>
119
+ <div class="kv"><dt>Base URL</dt><dd class="mono" style="font-size:10px;word-break:break-all">${esc(llm.baseUrl || '—')}</dd></div>
118
120
  <div class="kv"><dt>模型</dt><dd class="mono">${esc(llm.model || '—')}</dd></div>
119
- ${dshManaged ? '' : `<div class="kv"><dt>Key</dt><dd class="mono">${llm.hasKey ? esc(llm.apiKeyMasked || '已保存') : llm.envKey ? '来自环境变量' : '未配置'}</dd></div>`}
121
+ <div class="kv"><dt>Key</dt><dd class="mono">${llm.hasKey ? esc(llm.apiKeyMasked || '已保存') : llm.envKey ? '来自环境变量' : '未配置'}</dd></div>`}
120
122
  <div class="kv"><dt>数据目录</dt><dd class="mono" style="font-size:10px;word-break:break-all">${esc(health?.dataDir || '—')}</dd></div>
121
123
  <div class="kv"><dt>备份目录</dt><dd class="mono" style="font-size:10px;word-break:break-all">${esc(health?.backups?.dir || '—')}</dd></div>
122
124
  <div class="kv"><dt>最近备份</dt><dd>${health?.backups?.latest ? `${esc(timeAgo(health.backups.latest.at))} · ${esc(fmtBytes(health.backups.latest.size))}` : '暂无'}</dd></div>
@@ -128,7 +130,7 @@ export async function renderSettings(main, ctx) {
128
130
  </div>
129
131
  </div>
130
132
  </div>
131
- <div class="panel">
133
+ <div class="panel" ${dshManaged ? 'style="display:none"' : ''}>
132
134
  <div class="panel-head"><div><div class="panel-title">模型增强了什么</div></div></div>
133
135
  <div class="panel-body">
134
136
  <ul class="bullet-list">
@@ -141,7 +143,7 @@ export async function renderSettings(main, ctx) {
141
143
  <div class="help">没有 Key 时,架构、依赖、安全守护、复杂度、覆盖率、知识图谱仍由静态分析引擎生成,风险规则照常运行。快照会记录当次使用的引擎,可随时重新分析。</div>
142
144
  </div>
143
145
  </div>
144
- <div class="panel">
146
+ <div class="panel" ${dshManaged ? 'style="display:none"' : ''}>
145
147
  <div class="panel-head"><div><div class="panel-title">环境变量方式</div></div></div>
146
148
  <div class="panel-body">
147
149
  <div class="help" style="line-height:2">
package/server.js CHANGED
@@ -11,6 +11,12 @@ import { analyzeModule } from './lib/analyze/drilldown.js';
11
11
  import { diffSnapshots } from './lib/diff.js';
12
12
 
13
13
  const ROOT = path.dirname(fileURLToPath(import.meta.url));
14
+ let VERSION = '0.0.0';
15
+ try {
16
+ VERSION = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8')).version || VERSION;
17
+ } catch {
18
+ /* package metadata is optional at runtime */
19
+ }
14
20
  const PUBLIC_DIR = path.join(ROOT, 'public');
15
21
  const DATA_DIR = process.env.ARCVISTA_DATA ? path.resolve(process.env.ARCVISTA_DATA) : path.join(ROOT, 'data');
16
22
  const PORT = Number(
@@ -254,9 +260,9 @@ function snapshotOption(snapshot) {
254
260
  router.get('/api/health', () => ({
255
261
  ok: true,
256
262
  name: 'ArcVista',
257
- version: '0.1.0',
263
+ version: VERSION,
258
264
  node: process.version,
259
- dataDir: DATA_DIR,
265
+ dataDir: path.dirname(store.file),
260
266
  backups: store.backups.info(),
261
267
  llm: publicLlmSettings(),
262
268
  uptime: Math.round(process.uptime()),