dsh-my-observability 0.3.0 → 0.3.2

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/lib/parts/git.js DELETED
@@ -1,298 +0,0 @@
1
- // ── Git 工具 + 增量 diff 审查面板 ──────────────────────────────────
2
- const REPO_KEY = 'dsh-my-observability:repo'
3
- const COMMIT_TYPES = ['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore']
4
-
5
- function loadRepoKey() {
6
- try {
7
- const value = window.localStorage.getItem(REPO_KEY)
8
- return typeof value === 'string' ? value : ''
9
- } catch {
10
- return ''
11
- }
12
- }
13
-
14
- function saveRepoKey(repo) {
15
- try {
16
- window.localStorage.setItem(REPO_KEY, repo)
17
- } catch {
18
- // storage is best-effort
19
- }
20
- }
21
-
22
- /** 状态条:分支 + 变更计数。 */
23
- function StatusBar({ status }) {
24
- if (status === null) return null
25
- const parts = [`${strings.branch()} ${status.branch}`]
26
- if (status.clean) parts.push(strings.clean())
27
- else {
28
- if (status.stagedCount > 0) parts.push(`${status.stagedCount} ${strings.staged()}`)
29
- if (status.unstagedCount > 0) parts.push(`${status.unstagedCount} ${strings.unstaged()}`)
30
- }
31
- return createElement('div', { className: 'dsh-my-observability-status' }, parts.join(' · '))
32
- }
33
-
34
- /** 差异文本预览。 */
35
- function DiffView({ diff }) {
36
- return createElement(
37
- 'div',
38
- { className: 'dsh-my-observability-section' },
39
- createElement('div', { className: 'dsh-my-observability-section-title' }, strings.diffTitle()),
40
- createElement('pre', { className: 'dsh-my-observability-diff' }, diff !== '' ? diff : strings.emptyDiff()),
41
- )
42
- }
43
-
44
- /** 严重级别 → 中文。 */
45
- function severityText(severity) {
46
- if (severity === 'error') return strings.severityError()
47
- if (severity === 'warning') return strings.severityWarning()
48
- return strings.severityInfo()
49
- }
50
-
51
- /** AI 结论文本(未启用/失败/成功三态,尽力而为)。 */
52
- function aiTextOf(ai) {
53
- if (ai === undefined || ai === null || !ai.enabled) return ''
54
- if (ai.failed) return `${strings.aiFailed()}(${ai.note ?? ''})`
55
- return ai.verdict === 'approve' ? strings.aiVerdictApprove() : strings.aiVerdictChanges()
56
- }
57
-
58
- /** 审查报告:问题列表 + AI 结论。 */
59
- function ReviewReport({ report }) {
60
- if (report === null) return null
61
- const issues = report.issues || []
62
- const rows = issues.map((issue, index) =>
63
- createElement(
64
- 'div',
65
- {
66
- key: index,
67
- className: `dsh-my-observability-issue dsh-my-observability-issue-${issue.severity}`,
68
- },
69
- createElement('span', { className: 'dsh-my-observability-issue-sev' }, severityText(issue.severity)),
70
- createElement(
71
- 'span',
72
- { className: 'dsh-my-observability-issue-rule' },
73
- `${issue.rule}${issue.file !== '' ? ` ${issue.file}:${issue.line}` : ''}`,
74
- ),
75
- createElement('span', { className: 'dsh-my-observability-issue-msg' }, issue.message),
76
- ),
77
- )
78
- const aiText = aiTextOf(report.ai)
79
- return createElement(
80
- 'div',
81
- { className: 'dsh-my-observability-section' },
82
- createElement('div', { className: 'dsh-my-observability-section-title' }, strings.reviewResult()),
83
- issues.length === 0
84
- ? createElement('div', { className: 'dsh-my-observability-review-ok' }, strings.reviewPass())
85
- : null,
86
- rows,
87
- aiText !== '' ? createElement('div', { className: 'dsh-my-observability-ai' }, aiText) : null,
88
- )
89
- }
90
-
91
- /** 提交表单字段(type/scope/description/body + 提交按钮)。 */
92
- function CommitFields({ form, update, busy, submit }) {
93
- return createElement(
94
- 'div',
95
- { className: 'dsh-my-observability-form' },
96
- createElement(
97
- 'select',
98
- {
99
- className: 'dsh-my-observability-select dsh-my-observability-type',
100
- value: form.type,
101
- onChange: update('type'),
102
- },
103
- COMMIT_TYPES.map((type) => createElement('option', { key: type, value: type }, type)),
104
- ),
105
- createElement('input', {
106
- className: 'dsh-my-observability-input',
107
- placeholder: strings.commitScope(),
108
- value: form.scope,
109
- onChange: update('scope'),
110
- }),
111
- createElement('input', {
112
- className: 'dsh-my-observability-input',
113
- placeholder: strings.commitDesc(),
114
- value: form.description,
115
- onChange: update('description'),
116
- }),
117
- createElement('textarea', {
118
- className: 'dsh-my-observability-input dsh-my-observability-textarea',
119
- placeholder: strings.commitBody(),
120
- value: form.body,
121
- onChange: update('body'),
122
- }),
123
- createElement(
124
- 'div',
125
- { className: 'dsh-my-observability-actions' },
126
- createElement(
127
- 'button',
128
- {
129
- className: 'dsh-my-observability-btn dsh-my-observability-btn-primary',
130
- disabled: busy,
131
- onClick: submit,
132
- },
133
- strings.commit(),
134
- ),
135
- ),
136
- )
137
- }
138
-
139
- /** 类型化提交表单:type/scope/description/body → POST /git/commit。 */
140
- function CommitForm({ repo, onCommitted }) {
141
- const [form, setForm] = useState({ type: 'feat', scope: '', description: '', body: '' })
142
- const [busy, setBusy] = useState(false)
143
- const [feedback, setFeedback] = useState('')
144
- const [feedbackKind, setFeedbackKind] = useState('ok')
145
- const update = (key) => (e) => setForm({ ...form, [key]: e.target.value })
146
- const submit = async () => {
147
- if (form.description.trim() === '') {
148
- setFeedback(strings.commitError())
149
- setFeedbackKind('error')
150
- return
151
- }
152
- setBusy(true)
153
- try {
154
- const value = await apiJson('/observability/api/git/commit', {
155
- method: 'POST',
156
- headers: { 'content-type': 'application/json' },
157
- body: JSON.stringify({ repoPath: repo, ...form }),
158
- })
159
- setFeedback(`${strings.committed()}:${value.hash} ${value.message}`)
160
- setFeedbackKind('ok')
161
- setForm({ ...form, scope: '', description: '', body: '' })
162
- onCommitted()
163
- } catch (err) {
164
- setFeedback(`${strings.commitError()}:${err instanceof Error ? err.message : String(err)}`)
165
- setFeedbackKind('error')
166
- } finally {
167
- setBusy(false)
168
- }
169
- }
170
- return createElement(
171
- 'div',
172
- { className: 'dsh-my-observability-section' },
173
- createElement('div', { className: 'dsh-my-observability-section-title' }, strings.commitTitle()),
174
- createElement(CommitFields, { form, update, busy, submit }),
175
- feedback !== ''
176
- ? createElement(
177
- 'div',
178
- { className: `dsh-my-observability-feedback dsh-my-observability-feedback-${feedbackKind}` },
179
- feedback,
180
- )
181
- : null,
182
- )
183
- }
184
-
185
- /** 仓库路径行:输入 + 加载按钮。 */
186
- function RepoRow({ repo, onRepoChange, onLoad }) {
187
- return createElement(
188
- 'div',
189
- { className: 'dsh-my-observability-repo-row' },
190
- createElement('input', {
191
- className: 'dsh-my-observability-input dsh-my-observability-repo-input',
192
- placeholder: strings.repoPlaceholder(),
193
- value: repo,
194
- onChange: (e) => onRepoChange(e.target.value),
195
- }),
196
- createElement('button', { className: 'dsh-my-observability-btn', onClick: onLoad }, strings.loadRepo()),
197
- )
198
- }
199
-
200
- /** 操作按钮组:diff / staged diff / 审查。 */
201
- function GitActions({ onDiff, onReview }) {
202
- return createElement(
203
- 'div',
204
- { className: 'dsh-my-observability-actions' },
205
- createElement(
206
- 'button',
207
- { className: 'dsh-my-observability-btn', onClick: () => onDiff(false) },
208
- strings.showDiff(),
209
- ),
210
- createElement(
211
- 'button',
212
- { className: 'dsh-my-observability-btn', onClick: () => onDiff(true) },
213
- strings.showStagedDiff(),
214
- ),
215
- createElement(
216
- 'button',
217
- { className: 'dsh-my-observability-btn dsh-my-observability-btn-primary', onClick: onReview },
218
- strings.review(),
219
- ),
220
- )
221
- }
222
-
223
- /** 拉取仓库状态(错误写入 setError)。 */
224
- async function fetchStatus(path, setStatus, setError) {
225
- if (path === '') return
226
- try {
227
- setStatus(await apiJson(`/observability/api/git/status?repo=${encodeURIComponent(path)}`))
228
- setError('')
229
- } catch (err) {
230
- setError(err instanceof Error ? err.message : String(err))
231
- }
232
- }
233
-
234
- /** 拉取差异文本(staged 切换;错误写入 setError)。 */
235
- async function fetchDiff(path, staged, setDiff, setError) {
236
- if (path === '') return
237
- try {
238
- const value = await apiJson(`/observability/api/git/diff?repo=${encodeURIComponent(path)}&staged=${staged ? 1 : 0}`)
239
- setDiff(value.text)
240
- setError('')
241
- } catch (err) {
242
- setError(err instanceof Error ? err.message : String(err))
243
- }
244
- }
245
-
246
- /** 运行提交前审查(错误写入 setError)。 */
247
- async function runReview(path, setReport, setError) {
248
- if (path === '') return
249
- try {
250
- setReport(
251
- await apiJson('/observability/api/review', {
252
- method: 'POST',
253
- headers: { 'content-type': 'application/json' },
254
- body: JSON.stringify({ repoPath: path }),
255
- }),
256
- )
257
- setError('')
258
- } catch (err) {
259
- setError(err instanceof Error ? err.message : String(err))
260
- }
261
- }
262
-
263
- /** Git 面板主组件:仓库状态 / diff / 审查 / 类型化提交。 */
264
- function GitPanel() {
265
- const [repo, setRepo] = useState(loadRepoKey)
266
- const [status, setStatus] = useState(null)
267
- const [diff, setDiff] = useState('')
268
- const [report, setReport] = useState(null)
269
- const [error, setError] = useState('')
270
-
271
- const onCommitted = async () => {
272
- setDiff('')
273
- setReport(null)
274
- await fetchStatus(repo, setStatus, setError)
275
- }
276
-
277
- return createElement(
278
- 'div',
279
- { className: 'dsh-my-observability-panel' },
280
- createElement(RepoRow, {
281
- repo,
282
- onRepoChange: (value) => {
283
- setRepo(value)
284
- saveRepoKey(value)
285
- },
286
- onLoad: () => fetchStatus(repo, setStatus, setError),
287
- }),
288
- error !== '' ? createElement('div', { className: 'dsh-my-observability-empty' }, error) : null,
289
- createElement(StatusBar, { status }),
290
- createElement(GitActions, {
291
- onDiff: (staged) => fetchDiff(repo, staged, setDiff, setError),
292
- onReview: () => runReview(repo, setReport, setError),
293
- }),
294
- createElement(DiffView, { diff }),
295
- createElement(ReviewReport, { report }),
296
- createElement(CommitForm, { repo, onCommitted }),
297
- )
298
- }
package/lib/parts/i18n.js DELETED
@@ -1,104 +0,0 @@
1
- // ── i18n(浏览器语言判定)──────────────────────────────────────────
2
- function isZh() {
3
- try {
4
- const lang = (navigator.language || 'en').toLowerCase()
5
- return lang.startsWith('zh')
6
- } catch {
7
- return false
8
- }
9
- }
10
-
11
- const strings = {
12
- replayTitle: () => (isZh() ? '轨迹回放' : 'Trajectory'),
13
- resourceTitle: () => (isZh() ? '资源监控' : 'Resources'),
14
- resourceLoading: () => (isZh() ? '资源采样中…' : 'Sampling…'),
15
- resourceFile: () => (isZh() ? '审计文件' : 'Audit file'),
16
- resourceRate: () => (isZh() ? '写入速率' : 'Write rate'),
17
- resourceCpu: () => (isZh() ? 'CPU' : 'CPU'),
18
- resourceMem: () => (isZh() ? '内存' : 'Memory'),
19
- gitTitle: () => (isZh() ? 'Git 工具' : 'Git Tools'),
20
- allSessions: () => (isZh() ? '全部会话' : 'All sessions'),
21
- // ── 会话下拉可读性(issue #1xx:只能看到 UUID)────────────────────────
22
- eventCount: (n) => (isZh() ? `${n} 事件` : `${n} events`),
23
- sessionFallback: (shortId) => (isZh() ? `会话 ${shortId}` : `session ${shortId}`),
24
- filterAll: () => (isZh() ? '全部' : 'All'),
25
- filterStatus: () => (isZh() ? '状态' : 'Status'),
26
- filterLlm: () => (isZh() ? '模型流' : 'LLM'),
27
- filterTools: () => (isZh() ? '工具' : 'Tools'),
28
- filterPlugin: () => (isZh() ? '插件' : 'Plugins'),
29
- typePluginEvent: () => (isZh() ? '插件事件' : 'plugin event'),
30
- detailReason: () => (isZh() ? '原因' : 'reason'),
31
- emptyEvents: () => (isZh() ? '暂无审计事件' : 'No audit events yet'),
32
- emptyEventsHint: () =>
33
- isZh()
34
- ? '开始一段对话后,agent 的状态、模型流与工具调用会按时间记录在这里'
35
- : 'Start a conversation — agent status, LLM streams and tool calls are recorded here in time order',
36
- refresh: () => (isZh() ? '刷新' : 'Refresh'),
37
- retry: () => (isZh() ? '重试' : 'Retry'),
38
- loadError: () => (isZh() ? '加载失败' : 'Load failed'),
39
- typeAgentStatus: () => (isZh() ? 'agent 状态' : 'agent status'),
40
- typeLlmStream: () => (isZh() ? '模型流' : 'LLM stream'),
41
- typeToolCall: () => (isZh() ? '工具调用' : 'tool call'),
42
- typeToolResult: () => (isZh() ? '工具结果' : 'tool result'),
43
- phaseStart: () => (isZh() ? '开始' : 'start'),
44
- phaseEnd: () => (isZh() ? '结束' : 'end'),
45
- phaseError: () => (isZh() ? '错误' : 'error'),
46
- agentTop: () => (isZh() ? '顶层' : 'top'),
47
- agentSub: () => (isZh() ? '子代理' : 'subagent'),
48
- agentUnknown: () => (isZh() ? '未知' : 'unknown'),
49
- toolOk: () => (isZh() ? '成功' : 'ok'),
50
- toolFail: () => (isZh() ? '失败' : 'failed'),
51
- // 审计日志搜索 / 过滤 / 导出 / 统计
52
- searchPlaceholder: () => (isZh() ? '搜索工具名/参数/错误…' : 'Search tool/args/error…'),
53
- filterAllResult: () => (isZh() ? '全部结果' : 'All results'),
54
- filterSuccess: () => (isZh() ? '成功' : 'Ok'),
55
- filterFail: () => (isZh() ? '失败' : 'Failed'),
56
- timeStartLabel: () => (isZh() ? '开始' : 'Start'),
57
- timeEndLabel: () => (isZh() ? '结束' : 'End'),
58
- clearFilters: () => (isZh() ? '清除' : 'Clear'),
59
- exportJson: () => (isZh() ? '导出 JSON' : 'Export JSON'),
60
- exportCsv: () => (isZh() ? '导出 CSV' : 'Export CSV'),
61
- scopeSession: () => (isZh() ? '当前会话' : 'This session'),
62
- scopeAll: () => (isZh() ? '全部会话' : 'All sessions'),
63
- statsTitle: () => (isZh() ? '工具统计' : 'Tool stats'),
64
- statsTool: () => (isZh() ? '工具' : 'Tool'),
65
- statsCalls: () => (isZh() ? '调用' : 'Calls'),
66
- statsFailRate: () => (isZh() ? '失败率' : 'Fail rate'),
67
- statsEmpty: () => (isZh() ? '暂无工具调用数据' : 'No tool call data'),
68
- noMatches: () => (isZh() ? '无匹配事件' : 'No matching events'),
69
- exportFileName: () => (isZh() ? 'dsh-observability-审计导出' : 'dsh-observability-audit-export'),
70
- // Git 面板
71
- repoLabel: () => (isZh() ? '仓库路径' : 'Repo path'),
72
- repoPlaceholder: () => (isZh() ? '如 /path/to/project' : 'e.g. /path/to/project'),
73
- loadRepo: () => (isZh() ? '加载' : 'Load'),
74
- branch: () => (isZh() ? '分支' : 'Branch'),
75
- staged: () => (isZh() ? '已暂存' : 'staged'),
76
- unstaged: () => (isZh() ? '未暂存' : 'unstaged'),
77
- clean: () => (isZh() ? '工作区干净' : 'Working tree clean'),
78
- diffTitle: () => (isZh() ? '差异' : 'Diff'),
79
- showDiff: () => (isZh() ? '查看差异' : 'Show diff'),
80
- showStagedDiff: () => (isZh() ? '查看暂存差异' : 'Staged diff'),
81
- noChanges: () => (isZh() ? '没有变更' : 'No changes'),
82
- review: () => (isZh() ? '提交前审查' : 'Review'),
83
- reviewAi: () => (isZh() ? 'AI 审查' : 'AI review'),
84
- reviewResult: () => (isZh() ? '审查结果' : 'Review result'),
85
- reviewPass: () => (isZh() ? '未发现问题' : 'No issues found'),
86
- issues: (count) => (isZh() ? `${count} 个问题` : `${count} issue(s)`),
87
- commitTitle: () => (isZh() ? '类型化提交' : 'Typed commit'),
88
- commitType: () => (isZh() ? '类型' : 'Type'),
89
- commitScope: () => (isZh() ? '范围(可选)' : 'Scope (optional)'),
90
- commitDesc: () => (isZh() ? '描述' : 'Description'),
91
- commitBody: () => (isZh() ? '正文(可选)' : 'Body (optional)'),
92
- commit: () => (isZh() ? '提交' : 'Commit'),
93
- committed: () => (isZh() ? '已提交' : 'Committed'),
94
- commitError: () => (isZh() ? '提交失败' : 'Commit failed'),
95
- severityError: () => (isZh() ? '错误' : 'Error'),
96
- severityWarning: () => (isZh() ? '警告' : 'Warning'),
97
- severityInfo: () => (isZh() ? '提示' : 'Info'),
98
- aiVerdictApprove: () => (isZh() ? 'AI 结论:可以提交' : 'AI verdict: approve'),
99
- aiVerdictChanges: () => (isZh() ? 'AI 结论:建议修改' : 'AI verdict: changes'),
100
- aiFailed: () => (isZh() ? 'AI 审查不可用' : 'AI review unavailable'),
101
- loading: () => (isZh() ? '加载中…' : 'Loading…'),
102
- emptyDiff: () => (isZh() ? '(空)' : '(empty)'),
103
- noRepo: () => (isZh() ? '请输入仓库路径' : 'Enter a repo path'),
104
- }