dsh-tower 2.1.0 → 2.4.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/CHANGELOG.md +137 -0
- package/COMPATIBILITY.md +6 -1
- package/CONTRIBUTING.md +78 -5
- package/PRINCIPLES.md +163 -0
- package/README.en.md +35 -19
- package/README.md +28 -18
- package/SECURITY.md +6 -0
- package/{lib → adapters}/archive.js +1 -1
- package/{lib → adapters}/caseSensitivity.js +1 -1
- package/adapters/default.js +51 -10
- package/{lib → adapters}/git.js +1 -1
- package/{lib → adapters}/leases.js +1 -1
- package/{lib → adapters}/legacy.js +1 -1
- package/adapters/persistence.js +543 -0
- package/adapters/store-fs.js +28 -1
- package/adapters/store.js +204 -0
- package/{lib → adapters}/tests.js +9 -5
- package/adapters/vcs-git.js +15 -1
- package/{lib → adapters}/workspaceLock.js +1 -1
- package/{lib → adapters}/worktreeOwnership.js +1 -1
- package/app/archive.js +4 -6
- package/app/batch.js +9 -10
- package/app/board.js +2 -4
- package/app/checkCompletion.js +9 -10
- package/app/enrichedMissions.js +2 -4
- package/app/findings.js +6 -7
- package/app/gate.js +1 -2
- package/app/init.js +24 -29
- package/app/merge.js +58 -51
- package/app/messages.js +7 -8
- package/app/mission.js +5 -5
- package/app/plan.js +8 -5
- package/app/provision.js +12 -14
- package/app/read.js +6 -3
- package/app/rebase.js +14 -16
- package/app/recording.js +7 -8
- package/app/review.js +15 -8
- package/app/roster.js +14 -15
- package/{lib → app}/spawn-prechecks.js +4 -3
- package/app/spawn.js +12 -13
- package/app/teardown.js +8 -9
- package/app/tower.js +89 -35
- package/cordis.patch.yml +56 -28
- package/docs/README.md +7 -2
- package/docs/adr/0001-ports-adapters-as-data.md +49 -0
- package/docs/adr/0002-single-state-json.md +50 -0
- package/docs/adr/0003-allow-agent-control-default-true.md +48 -0
- package/docs/adr/0004-surface-budget.md +70 -0
- package/docs/adr/0005-component-surface.md +130 -0
- package/docs/adr/README.md +52 -0
- package/docs/agents/workflow.md +51 -0
- package/docs/architecture/overview.md +192 -43
- package/docs/guide/hot-reload.md +5 -5
- package/docs/guide/install-upgrade-migration.md +13 -0
- package/docs/guide/release.md +1 -1
- package/docs/operations/incident.md +82 -0
- package/docs/operations/runbook.md +12 -3
- package/docs/operations/security.md +1 -1
- package/docs/reference/blockers.md +2 -2
- package/docs/reference/component-surface.md +135 -0
- package/docs/reference/config.generated.md +2 -9
- package/docs/reference/config.md +11 -9
- package/docs/reference/doctor.md +53 -2
- package/docs/reference/errors.generated.md +41 -37
- package/docs/reference/errors.md +53 -41
- package/docs/reference/events.md +38 -6
- package/docs/reference/surface-budget.md +157 -0
- package/docs/reference/tools.generated.md +8 -5
- package/docs/reference/tools.md +10 -7
- package/docs/zh/README.md +1 -1
- package/docs/zh/guide/hot-reload.md +4 -4
- package/docs/zh/guide/install-upgrade-migration.md +10 -0
- package/docs/zh/operations/security.md +1 -1
- package/docs/zh/reference/blockers.md +2 -2
- package/docs/zh/reference/config.md +9 -9
- package/docs/zh/reference/doctor.md +29 -1
- package/docs/zh/reference/tools.md +10 -8
- package/domain/batch.js +2 -2
- package/domain/components.js +641 -0
- package/domain/config/schema.js +62 -28
- package/domain/contracts/outputs.js +16 -2
- package/domain/contracts/tool-inputs/ops.js +1 -0
- package/domain/errors.js +308 -43
- package/domain/events.js +207 -0
- package/domain/integration/gate.js +17 -2
- package/domain/integration/merge.js +35 -0
- package/domain/lockBudget.js +30 -0
- package/domain/mission.js +12 -1
- package/domain/missions/completion.js +14 -0
- package/domain/missions/lifecycle.js +9 -3
- package/domain/missions/plan.js +14 -0
- package/domain/missions/review.js +90 -7
- package/domain/read/views.js +3 -0
- package/domain/state/archive.js +1 -1
- package/domain/state.js +1 -1
- package/domain/surface.js +347 -0
- package/host/capability-batch.js +15 -0
- package/host/capability-hmr.js +30 -0
- package/host/capability-import.js +11 -0
- package/host/capability-leases.js +11 -0
- package/host/capability-registry.js +149 -0
- package/host/capability-tests.js +16 -0
- package/{lib → host}/doctor.js +157 -18
- package/{lib → host}/hmr.js +2 -4
- package/{lib → host}/modeStore.js +1 -1
- package/host/presets.js +77 -0
- package/{lib → host}/tool-registry.js +235 -44
- package/host/tower.js +32 -0
- package/index.js +40 -25
- package/locale/en.json +31 -11
- package/locale/zh.json +30 -10
- package/package.json +24 -4
- package/ports/archive.js +18 -0
- package/ports/caseSensitivity.js +15 -0
- package/ports/clock.js +10 -2
- package/ports/config.js +19 -0
- package/ports/contract.js +38 -0
- package/ports/events.js +24 -0
- package/ports/ids.js +10 -2
- package/ports/index.js +54 -2
- package/ports/ownership.js +17 -0
- package/ports/state.js +16 -0
- package/ports/store.js +52 -3
- package/ports/vcs.js +25 -4
- package/scripts/architecture-waivers.json +19 -0
- package/scripts/architecture.mjs +634 -23
- package/scripts/check-components.mjs +235 -0
- package/scripts/check-docs.mjs +8 -35
- package/scripts/check-pack.mjs +68 -39
- package/scripts/check-philosophy.mjs +266 -0
- package/scripts/component-surface.json +395 -0
- package/scripts/domain-metrics.mjs +13 -4
- package/scripts/generate-component-surface.mjs +59 -0
- package/scripts/generate-config-reference.mjs +14 -1
- package/scripts/generate-error-reference.mjs +68 -14
- package/scripts/generate-events-reference.mjs +83 -0
- package/scripts/generate-tools-reference.mjs +18 -25
- package/scripts/generate-types.mjs +127 -0
- package/scripts/issue-audit.mjs +2 -2
- package/scripts/lib/surface.mjs +87 -0
- package/scripts/lib/tool-surface.mjs +85 -0
- package/scripts/mount-smoke/fixtures.mjs +3 -3
- package/scripts/mount-smoke/surface.mjs +96 -27
- package/scripts/mount-smoke.mjs +3 -1
- package/scripts/pack-manifest.txt +75 -22
- package/scripts/regression-audit.mjs +164 -0
- package/scripts/release-check.mjs +1 -1
- package/scripts/surface-baseline.json +52 -0
- package/scripts/surface-baseline.mjs +118 -0
- package/scripts/types-coverage.mjs +184 -0
- package/scripts/types-strict-manifest.txt +10 -0
- package/scripts/types-strict.mjs +141 -0
- package/skills.js +8 -1
- package/tools/adopt.js +2 -3
- package/tools/batch.js +2 -3
- package/tools/complete.js +2 -3
- package/tools/diff.js +3 -3
- package/tools/doctor.js +7 -10
- package/tools/finding.js +2 -3
- package/tools/findings.js +3 -3
- package/tools/import-legacy.js +3 -5
- package/tools/inbox.js +3 -3
- package/tools/index.js +9 -8
- package/tools/init.js +3 -6
- package/tools/interrupt.js +2 -3
- package/tools/legacy-map.js +3 -5
- package/tools/merge.js +3 -3
- package/tools/mission.js +2 -3
- package/tools/plan.js +6 -5
- package/tools/preflight.js +2 -3
- package/tools/rebase.js +3 -3
- package/tools/recover.js +38 -13
- package/tools/reload.js +36 -40
- package/tools/resource.js +3 -5
- package/tools/review.js +3 -4
- package/tools/roster.js +2 -3
- package/tools/send.js +2 -2
- package/tools/spawn.js +8 -5
- package/tools/status.js +11 -4
- package/tools/teardown.js +2 -3
- package/tools/test.js +2 -2
- package/types/index.d.ts +29 -13
- package/ui-bundle/README.md +37 -3
- package/ui-bundle/client.cards.js +356 -0
- package/ui-bundle/client.denied.js +142 -0
- package/ui-bundle/client.dock.js +333 -0
- package/ui-bundle/client.helpers.js +271 -0
- package/ui-bundle/client.js +79 -1747
- package/ui-bundle/client.locales.js +247 -0
- package/ui-bundle/client.mode.js +206 -0
- package/ui-bundle/client.overlay.js +64 -0
- package/ui-bundle/client.styles.js +151 -0
- package/ui-bundle/client.toolview.js +82 -0
- package/ui-bundle/package.json +1 -0
- package/lib/persistence.js +0 -356
- package/lib/presets.js +0 -35
- package/lib/store.js +0 -133
- /package/{lib → adapters}/stateFile.js +0 -0
- /package/{lib → app}/briefing.js +0 -0
- /package/{lib → app}/spawn-support.js +0 -0
- /package/{lib → host}/compatibility.js +0 -0
- /package/{lib → host}/config.js +0 -0
- /package/{lib → host}/modeState.js +0 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// dsh-tower-ui 0.2.2 — locale dictionaries and the translation helpers.
|
|
2
|
+
//
|
|
3
|
+
// Package-local chunk: client.js loads it once through require.async() before
|
|
4
|
+
// the first slot registration. The Client locale service owns activation and
|
|
5
|
+
// language; each slot registration's `locale` option supplies the bound `t`
|
|
6
|
+
// seat, and `EN` is the fallback for a missing seat (#71).
|
|
7
|
+
window.__ModuleLoader__.load({
|
|
8
|
+
id: 'dsh-tower-ui',
|
|
9
|
+
chunk: 'client.locales.js',
|
|
10
|
+
factory() {
|
|
11
|
+
const TOOL_LABEL_KEYS = {
|
|
12
|
+
tower_status: 'tool.status',
|
|
13
|
+
tower_roster: 'tool.roster',
|
|
14
|
+
tower_spawn: 'tool.spawn',
|
|
15
|
+
tower_mission: 'tool.mission',
|
|
16
|
+
tower_complete: 'tool.complete',
|
|
17
|
+
tower_review: 'tool.review',
|
|
18
|
+
tower_preflight: 'tool.preflight',
|
|
19
|
+
tower_merge: 'tool.merge',
|
|
20
|
+
tower_teardown: 'tool.teardown',
|
|
21
|
+
tower_interrupt: 'tool.interrupt',
|
|
22
|
+
tower_doctor: 'tool.doctor',
|
|
23
|
+
tower_batch: 'tool.batch',
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const EN = {
|
|
27
|
+
'card.title': 'Tower',
|
|
28
|
+
'card.running': 'running…',
|
|
29
|
+
'card.done': 'done',
|
|
30
|
+
'card.failed': 'failed',
|
|
31
|
+
'card.error': 'Error',
|
|
32
|
+
'card.blockers': 'Blockers',
|
|
33
|
+
'card.noBlockers': 'no blockers',
|
|
34
|
+
'card.checks': 'Checks',
|
|
35
|
+
'card.warnings': 'Warnings',
|
|
36
|
+
'card.checkOk': '{name} ✓',
|
|
37
|
+
'card.checkFail': '{name} (exit {code})',
|
|
38
|
+
'card.checksCount': '{passed}/{total} checks passed',
|
|
39
|
+
'card.tasks': 'tasks {done}/{total}',
|
|
40
|
+
'card.openTasks': '{count} open task(s)',
|
|
41
|
+
'card.noOpenTasks': 'no open tasks',
|
|
42
|
+
'card.statusHeadline': '{total} missions · {active} active',
|
|
43
|
+
'card.statusDetail': 'roster {roster} · findings {findings} · rev {revision}',
|
|
44
|
+
'card.rosterHeadline': '{live} live / {total} agents',
|
|
45
|
+
'card.staleCount': '{count} stale',
|
|
46
|
+
'card.otherCount': '{count} inactive',
|
|
47
|
+
'card.agentLine': '{name} · {role} · {mission} · {activity}',
|
|
48
|
+
'card.reviewLine': '{status} · merge {merge} · round {round}',
|
|
49
|
+
'card.mergeReady': 'ready to merge',
|
|
50
|
+
'card.mergeBlocked': '{count} blocker(s)',
|
|
51
|
+
'card.merged': 'merged {commit}',
|
|
52
|
+
'card.alreadyMerged': 'already merged',
|
|
53
|
+
'card.spawnLine': '{role} {name} → {mission}',
|
|
54
|
+
'card.worktreeLine': 'worktree {branch}',
|
|
55
|
+
'card.completeLine': '{mission} completed · {commits} commit(s)',
|
|
56
|
+
'card.unread': '{count} unread',
|
|
57
|
+
'card.interruptYes': 'interrupted {name}',
|
|
58
|
+
'card.interruptNo': '{name} is not running',
|
|
59
|
+
'card.previousActivity': 'previous activity {activity}',
|
|
60
|
+
'card.teardownLine': '{removed} removed · {kept} kept',
|
|
61
|
+
'card.dryRun': 'dry run',
|
|
62
|
+
'card.doctorLine': 'doctor {status}',
|
|
63
|
+
'card.doctorChecks': '{pass} pass · {warn} warn · {fail} fail',
|
|
64
|
+
'card.batchLine': 'batch {status}',
|
|
65
|
+
'card.batchMembers': '{count} member(s) · batch {status}',
|
|
66
|
+
'card.batchMissing': '{count} missing check(s)',
|
|
67
|
+
'card.batchFailed': '{count} failed check(s)',
|
|
68
|
+
'card.missionLine': '{id} {status}',
|
|
69
|
+
'card.missionMissing': 'mission',
|
|
70
|
+
'card.reviewPolicy': 'review {policy}',
|
|
71
|
+
'card.owner': 'owner {owner}',
|
|
72
|
+
'card.unknown': 'unknown',
|
|
73
|
+
'card.summary': '{text}',
|
|
74
|
+
'card.sep': ' · ',
|
|
75
|
+
'tool.status': 'Status',
|
|
76
|
+
'tool.roster': 'Roster',
|
|
77
|
+
'tool.spawn': 'Spawn',
|
|
78
|
+
'tool.mission': 'Mission',
|
|
79
|
+
'tool.complete': 'Complete',
|
|
80
|
+
'tool.review': 'Review',
|
|
81
|
+
'tool.preflight': 'Preflight',
|
|
82
|
+
'tool.merge': 'Merge',
|
|
83
|
+
'tool.teardown': 'Teardown',
|
|
84
|
+
'tool.interrupt': 'Interrupt',
|
|
85
|
+
'tool.doctor': 'Doctor',
|
|
86
|
+
'tool.batch': 'Batch',
|
|
87
|
+
'dock.hint.title': '/tower · /tower on [message] · /tower off [message]',
|
|
88
|
+
'dock.running': '{tool} running…',
|
|
89
|
+
'dock.statusCounts': '{total} missions · {active} active · {open} open',
|
|
90
|
+
'dock.rosterCounts': '{live} live / {total} agents',
|
|
91
|
+
'dock.review': 'review {status} · {merge}',
|
|
92
|
+
'dock.ready': 'ready to merge',
|
|
93
|
+
'dock.blocked': '{count} blocker(s)',
|
|
94
|
+
'dock.merged': 'merged {commit}',
|
|
95
|
+
'dock.complete': '{mission} completed · {commits} commit(s)',
|
|
96
|
+
'dock.spawn': '{role} {name} → {mission}',
|
|
97
|
+
'dock.removed': '{count} worktree(s) removed',
|
|
98
|
+
'dock.interrupt': '{name} interrupted',
|
|
99
|
+
'dock.mission': '{id} {status}',
|
|
100
|
+
'dock.preflight': 'preflight {status}',
|
|
101
|
+
'dock.batch': 'batch {status}',
|
|
102
|
+
'dock.doctor': 'doctor {status}',
|
|
103
|
+
'dock.generic': 'done',
|
|
104
|
+
'dock.mode.onLabel': 'on',
|
|
105
|
+
'dock.mode.unknownLabel': 'mode unknown',
|
|
106
|
+
'dock.mode.unknownTooltip': 'The loaded history has Tower activity but no mode event. Run /tower or tower_mode to confirm the current stance.',
|
|
107
|
+
'dock.mode.tooltip': 'Tower mode is on for this session. Run /tower off in the composer to leave Tower mode.',
|
|
108
|
+
'dock.mode.lastKnown': 'last known from this browser session; run /tower or tower_mode to confirm',
|
|
109
|
+
'dock.mode.repo': 'repo {repo}',
|
|
110
|
+
'dock.mode.lockHeld': 'workspace lock held',
|
|
111
|
+
'dock.mode.lockFree': 'workspace lock free',
|
|
112
|
+
'dock.mode.lastBy': 'last change by {by}',
|
|
113
|
+
'deny.label': 'Tower mode · disabled',
|
|
114
|
+
'deny.hint': 'Run /tower off in the composer to use this tool again.',
|
|
115
|
+
'deny.running': 'Tower mode blocks this tool while it is active',
|
|
116
|
+
'deny.generic': '{tool} (Tower mode active)',
|
|
117
|
+
'deny.error': 'Tool error while Tower mode is active',
|
|
118
|
+
'strip.started': 'Tower · {tool} started',
|
|
119
|
+
'strip.finished': 'Tower · {tool} finished',
|
|
120
|
+
'strip.failed': 'Tower · {tool} failed',
|
|
121
|
+
}
|
|
122
|
+
const ZH = {
|
|
123
|
+
'card.title': 'Tower',
|
|
124
|
+
'card.running': '运行中…',
|
|
125
|
+
'card.done': '已完成',
|
|
126
|
+
'card.failed': '失败',
|
|
127
|
+
'card.error': '错误',
|
|
128
|
+
'card.blockers': '阻塞项',
|
|
129
|
+
'card.noBlockers': '无阻塞',
|
|
130
|
+
'card.checks': '检查',
|
|
131
|
+
'card.warnings': '警告',
|
|
132
|
+
'card.checkOk': '{name} ✓',
|
|
133
|
+
'card.checkFail': '{name}(退出码 {code})',
|
|
134
|
+
'card.checksCount': '通过 {passed}/{total} 项检查',
|
|
135
|
+
'card.tasks': '任务 {done}/{total}',
|
|
136
|
+
'card.openTasks': '{count} 个未完成任务',
|
|
137
|
+
'card.noOpenTasks': '无未完成任务',
|
|
138
|
+
'card.statusHeadline': '{total} 个任务线 · {active} 活跃',
|
|
139
|
+
'card.statusDetail': '名册 {roster} · 发现 {findings} · 修订 {revision}',
|
|
140
|
+
'card.rosterHeadline': '{live} 个运行中 / 共 {total} 个',
|
|
141
|
+
'card.staleCount': '{count} 个疑似停滞',
|
|
142
|
+
'card.otherCount': '{count} 个非活跃',
|
|
143
|
+
'card.agentLine': '{name} · {role} · {mission} · {activity}',
|
|
144
|
+
'card.reviewLine': '{status} · 合并建议 {merge} · 第 {round} 轮',
|
|
145
|
+
'card.mergeReady': '可以合并',
|
|
146
|
+
'card.mergeBlocked': '{count} 个阻塞',
|
|
147
|
+
'card.merged': '已合并 {commit}',
|
|
148
|
+
'card.alreadyMerged': '已合并(补记录)',
|
|
149
|
+
'card.spawnLine': '{role} {name} → {mission}',
|
|
150
|
+
'card.worktreeLine': '工作树 {branch}',
|
|
151
|
+
'card.completeLine': '{mission} 已完成 · {commits} 个提交',
|
|
152
|
+
'card.unread': '{count} 条未读',
|
|
153
|
+
'card.interruptYes': '已中断 {name}',
|
|
154
|
+
'card.interruptNo': '{name} 未在运行',
|
|
155
|
+
'card.previousActivity': '先前活动 {activity}',
|
|
156
|
+
'card.teardownLine': '移除 {removed} · 保留 {kept}',
|
|
157
|
+
'card.dryRun': '演练',
|
|
158
|
+
'card.doctorLine': '体检 {status}',
|
|
159
|
+
'card.doctorChecks': '通过 {pass} · 警告 {warn} · 失败 {fail}',
|
|
160
|
+
'card.batchLine': '批量 {status}',
|
|
161
|
+
'card.batchMembers': '{count} 个成员 · 批次 {status}',
|
|
162
|
+
'card.batchMissing': '{count} 项缺失检查',
|
|
163
|
+
'card.batchFailed': '{count} 项失败检查',
|
|
164
|
+
'card.missionLine': '{id} {status}',
|
|
165
|
+
'card.missionMissing': '任务线',
|
|
166
|
+
'card.reviewPolicy': '评审 {policy}',
|
|
167
|
+
'card.owner': '负责人 {owner}',
|
|
168
|
+
'card.unknown': '未知',
|
|
169
|
+
'card.summary': '{text}',
|
|
170
|
+
'card.sep': ' · ',
|
|
171
|
+
'tool.status': '状态',
|
|
172
|
+
'tool.roster': '名册',
|
|
173
|
+
'tool.spawn': '派发',
|
|
174
|
+
'tool.mission': '任务线',
|
|
175
|
+
'tool.complete': '完成',
|
|
176
|
+
'tool.review': '评审',
|
|
177
|
+
'tool.preflight': '预检',
|
|
178
|
+
'tool.merge': '合并',
|
|
179
|
+
'tool.teardown': '清理',
|
|
180
|
+
'tool.interrupt': '中断',
|
|
181
|
+
'tool.doctor': '体检',
|
|
182
|
+
'tool.batch': '批量',
|
|
183
|
+
'dock.hint.title': '/tower · /tower on [message] · /tower off [message]',
|
|
184
|
+
'dock.running': '{tool} 运行中…',
|
|
185
|
+
'dock.statusCounts': '{total} 个任务线 · {active} 活跃 · {open} 未完成',
|
|
186
|
+
'dock.rosterCounts': '{live} 个运行中 / 共 {total} 个',
|
|
187
|
+
'dock.review': '评审 {status} · {merge}',
|
|
188
|
+
'dock.ready': '可以合并',
|
|
189
|
+
'dock.blocked': '{count} 个阻塞',
|
|
190
|
+
'dock.merged': '已合并 {commit}',
|
|
191
|
+
'dock.complete': '{mission} 已完成 · {commits} 个提交',
|
|
192
|
+
'dock.spawn': '{role} {name} → {mission}',
|
|
193
|
+
'dock.removed': '移除 {count} 个工作树',
|
|
194
|
+
'dock.interrupt': '已中断 {name}',
|
|
195
|
+
'dock.mission': '{id} {status}',
|
|
196
|
+
'dock.preflight': '预检 {status}',
|
|
197
|
+
'dock.batch': '批量 {status}',
|
|
198
|
+
'dock.doctor': '体检 {status}',
|
|
199
|
+
'dock.generic': '已完成',
|
|
200
|
+
'dock.mode.onLabel': '已开启',
|
|
201
|
+
'dock.mode.unknownLabel': '模式未知',
|
|
202
|
+
'dock.mode.unknownTooltip': '已加载的历史中有 Tower 活动,但没有模式事件。执行 /tower 或 tower_mode 以确认当前状态。',
|
|
203
|
+
'dock.mode.tooltip': '此会话已开启 Tower 模式。在输入框中执行 /tower off 可退出。',
|
|
204
|
+
'dock.mode.lastKnown': '来自此浏览器会话的最后已知状态;请执行 /tower 或 tower_mode 确认',
|
|
205
|
+
'dock.mode.repo': '仓库 {repo}',
|
|
206
|
+
'dock.mode.lockHeld': '工作区锁已持有',
|
|
207
|
+
'dock.mode.lockFree': '工作区锁空闲',
|
|
208
|
+
'dock.mode.lastBy': '最近变更者 {by}',
|
|
209
|
+
'deny.label': 'Tower 模式 · 已禁用',
|
|
210
|
+
'deny.hint': '在输入框中执行 /tower off 后即可重新使用该工具。',
|
|
211
|
+
'deny.running': 'Tower 模式启用期间该工具被禁用',
|
|
212
|
+
'deny.generic': '{tool}(Tower 模式启用中)',
|
|
213
|
+
'deny.error': 'Tower 模式启用期间的工具错误',
|
|
214
|
+
'strip.started': 'Tower · {tool} 开始',
|
|
215
|
+
'strip.finished': 'Tower · {tool} 完成',
|
|
216
|
+
'strip.failed': 'Tower · {tool} 失败',
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function fill(template, params) {
|
|
220
|
+
if (typeof template !== 'string') return String(template)
|
|
221
|
+
if (params === undefined || params === null) return template
|
|
222
|
+
return template.replace(/\{(\w+)\}/g, (match, name) =>
|
|
223
|
+
Object.prototype.hasOwnProperty.call(params, name) ? String(params[name]) : match,
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
function translate(t, key, params) {
|
|
227
|
+
if (typeof t === 'function') {
|
|
228
|
+
try {
|
|
229
|
+
const value = t(key, params)
|
|
230
|
+
if (typeof value === 'string') return value
|
|
231
|
+
} catch (error) {
|
|
232
|
+
/* fall through to the bundled English dictionary */
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return fill(EN[key] !== undefined ? EN[key] : key, params)
|
|
236
|
+
}
|
|
237
|
+
function seatT(props) {
|
|
238
|
+
return props && typeof props.t === 'function' ? props.t : null
|
|
239
|
+
}
|
|
240
|
+
function toolLabel(t, name) {
|
|
241
|
+
if (typeof name !== 'string' || name === '') return translate(t, 'card.title')
|
|
242
|
+
return translate(t, TOOL_LABEL_KEYS[name] || 'card.title')
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return { EN, ZH, fill, translate, seatT, toolLabel }
|
|
246
|
+
},
|
|
247
|
+
})
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// dsh-tower-ui 0.2.2 — the history-derived Tower-mode model and observable.
|
|
2
|
+
//
|
|
3
|
+
// The dock folds the durable history into one stance model; the store publishes
|
|
4
|
+
// it so the denied-tool toolviews can be added/disposed. No Host state is read
|
|
5
|
+
// or fetched. Package-local chunk (#71).
|
|
6
|
+
window.__ModuleLoader__.load({
|
|
7
|
+
id: 'dsh-tower-ui',
|
|
8
|
+
chunk: 'client.mode.js',
|
|
9
|
+
factory() {
|
|
10
|
+
function towerCommandAction(args) {
|
|
11
|
+
const raw = String(args === undefined || args === null ? '' : args).trim()
|
|
12
|
+
if (/^reload$/i.test(raw)) return null
|
|
13
|
+
if (/^base\s+\S+\s*$/i.test(raw)) return null
|
|
14
|
+
const match = /^(on|off)(?:\s+[\s\S]*)?$/i.exec(raw)
|
|
15
|
+
if (match) return match[1].toLowerCase()
|
|
16
|
+
// Bare `/tower` and `/tower <message>` both mean "ensure on".
|
|
17
|
+
return 'on'
|
|
18
|
+
}
|
|
19
|
+
function repoNameOf(value) {
|
|
20
|
+
if (typeof value !== 'string' || value === '') return null
|
|
21
|
+
let cleaned = value.replace(/[\\/]+$/, '')
|
|
22
|
+
if (/[\\/]\.git$/i.test(cleaned)) cleaned = cleaned.replace(/[\\/]\.git$/i, '')
|
|
23
|
+
const index = Math.max(cleaned.lastIndexOf('/'), cleaned.lastIndexOf('\\'))
|
|
24
|
+
const name = index >= 0 ? cleaned.slice(index + 1) : cleaned
|
|
25
|
+
return name === '' ? null : name
|
|
26
|
+
}
|
|
27
|
+
// Fold the visible history into one model: the last recognized event wins,
|
|
28
|
+
// and `/tower reload|base` or a failed command leaves the stance unchanged.
|
|
29
|
+
function modeModelFromLegacy(legacy, helpers) {
|
|
30
|
+
const { isPlainObject, parsePayload } = helpers
|
|
31
|
+
const model = {
|
|
32
|
+
known: false,
|
|
33
|
+
on: null,
|
|
34
|
+
denied: null,
|
|
35
|
+
repo: null,
|
|
36
|
+
lock: null,
|
|
37
|
+
lastBy: null,
|
|
38
|
+
lastReason: null,
|
|
39
|
+
source: null,
|
|
40
|
+
}
|
|
41
|
+
const nodes = isPlainObject(legacy) && Array.isArray(legacy.nodes) ? legacy.nodes : []
|
|
42
|
+
for (const node of nodes) {
|
|
43
|
+
if (!isPlainObject(node)) continue
|
|
44
|
+
if (node.kind === 'command') {
|
|
45
|
+
if (node.name !== 'tower') continue
|
|
46
|
+
const outcome = isPlainObject(node.outcome) ? node.outcome : null
|
|
47
|
+
if (outcome !== null && outcome.kind === 'error') continue
|
|
48
|
+
const action = towerCommandAction(node.args)
|
|
49
|
+
if (action === null) continue
|
|
50
|
+
model.known = true
|
|
51
|
+
model.on = action === 'on'
|
|
52
|
+
model.source = 'command'
|
|
53
|
+
model.lastBy = 'user'
|
|
54
|
+
model.lastReason = null
|
|
55
|
+
continue
|
|
56
|
+
}
|
|
57
|
+
const toolName = isPlainObject(node.call) ? node.call.name : null
|
|
58
|
+
if (toolName === 'tower_mode') {
|
|
59
|
+
const payload = parsePayload(node)
|
|
60
|
+
if (!isPlainObject(payload) || payload.__error === true) continue
|
|
61
|
+
if (payload.mode === 'on' || payload.mode === 'off') {
|
|
62
|
+
model.known = true
|
|
63
|
+
model.on = payload.mode === 'on'
|
|
64
|
+
model.source = 'tower_mode'
|
|
65
|
+
}
|
|
66
|
+
if (Array.isArray(payload.deniedWhileActive)) {
|
|
67
|
+
const names = []
|
|
68
|
+
for (const entry of payload.deniedWhileActive) {
|
|
69
|
+
if (typeof entry !== 'string') continue
|
|
70
|
+
const name = entry.trim()
|
|
71
|
+
if (name !== '' && !names.includes(name)) names.push(name)
|
|
72
|
+
}
|
|
73
|
+
if (names.length > 0) model.denied = names
|
|
74
|
+
}
|
|
75
|
+
const workspace = isPlainObject(payload.workspaceLock) ? payload.workspaceLock : null
|
|
76
|
+
if (workspace !== null) {
|
|
77
|
+
model.lock = { enabled: workspace.enabled === true, held: workspace.held === true }
|
|
78
|
+
const name = repoNameOf(workspace.commonDir)
|
|
79
|
+
if (name !== null) model.repo = name
|
|
80
|
+
}
|
|
81
|
+
if (isPlainObject(payload.lastChange)) {
|
|
82
|
+
if (typeof payload.lastChange.by === 'string') model.lastBy = payload.lastChange.by
|
|
83
|
+
if (typeof payload.lastChange.reason === 'string' && payload.lastChange.reason.trim() !== '') {
|
|
84
|
+
model.lastReason = payload.lastChange.reason.trim()
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
continue
|
|
88
|
+
}
|
|
89
|
+
if (toolName === 'tower_control') {
|
|
90
|
+
const payload = parsePayload(node)
|
|
91
|
+
if (!isPlainObject(payload) || payload.__error === true || payload.ok === false) continue
|
|
92
|
+
const mode =
|
|
93
|
+
payload.mode === 'on' || payload.mode === 'off'
|
|
94
|
+
? payload.mode
|
|
95
|
+
: payload.action === 'enter'
|
|
96
|
+
? 'on'
|
|
97
|
+
: payload.action === 'exit'
|
|
98
|
+
? 'off'
|
|
99
|
+
: null
|
|
100
|
+
if (mode === null) continue
|
|
101
|
+
model.known = true
|
|
102
|
+
model.on = mode === 'on'
|
|
103
|
+
model.source = 'tower_control'
|
|
104
|
+
if (typeof payload.changedBy === 'string') model.lastBy = payload.changedBy
|
|
105
|
+
if (typeof payload.reason === 'string' && payload.reason.trim() !== '') model.lastReason = payload.reason.trim()
|
|
106
|
+
continue
|
|
107
|
+
}
|
|
108
|
+
if (toolName === 'tower_status') {
|
|
109
|
+
const payload = parsePayload(node)
|
|
110
|
+
if (isPlainObject(payload)) {
|
|
111
|
+
const name = repoNameOf(payload.repoRoot)
|
|
112
|
+
if (name !== null) model.repo = name
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return model
|
|
117
|
+
}
|
|
118
|
+
const EMPTY_MODE = {
|
|
119
|
+
writer: null,
|
|
120
|
+
known: false,
|
|
121
|
+
on: null,
|
|
122
|
+
denied: null,
|
|
123
|
+
repo: null,
|
|
124
|
+
lock: null,
|
|
125
|
+
lastBy: null,
|
|
126
|
+
lastReason: null,
|
|
127
|
+
source: null,
|
|
128
|
+
}
|
|
129
|
+
function createModeStore(diagnostics, helpers) {
|
|
130
|
+
const { isPlainObject } = helpers
|
|
131
|
+
// All mutable client state lives in this closure, never at module scope
|
|
132
|
+
// (client-ambient).
|
|
133
|
+
const state = { value: Object.assign({}, EMPTY_MODE), seq: 0 }
|
|
134
|
+
const listeners = new Set()
|
|
135
|
+
|
|
136
|
+
function nextDockWriter() {
|
|
137
|
+
state.seq += 1
|
|
138
|
+
return 'dock-' + state.seq
|
|
139
|
+
}
|
|
140
|
+
function modeSnapshot() {
|
|
141
|
+
return state.value
|
|
142
|
+
}
|
|
143
|
+
function subscribeMode(listener) {
|
|
144
|
+
listeners.add(listener)
|
|
145
|
+
return function () {
|
|
146
|
+
listeners.delete(listener)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function sameMode(left, right) {
|
|
150
|
+
return (
|
|
151
|
+
left.known === right.known &&
|
|
152
|
+
left.on === right.on &&
|
|
153
|
+
JSON.stringify(left.denied) === JSON.stringify(right.denied) &&
|
|
154
|
+
left.repo === right.repo &&
|
|
155
|
+
JSON.stringify(left.lock) === JSON.stringify(right.lock) &&
|
|
156
|
+
left.lastBy === right.lastBy &&
|
|
157
|
+
left.source === right.source
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
function notifyMode() {
|
|
161
|
+
for (const listener of Array.from(listeners)) {
|
|
162
|
+
try {
|
|
163
|
+
listener()
|
|
164
|
+
} catch (error) {
|
|
165
|
+
/* a broken registration reconciler must not break the dock */
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function publishMode(writer, next) {
|
|
170
|
+
const value = {
|
|
171
|
+
writer,
|
|
172
|
+
known: next.known === true,
|
|
173
|
+
on: next.known === true && next.on === true,
|
|
174
|
+
denied: Array.isArray(next.denied) ? next.denied.slice() : null,
|
|
175
|
+
repo: typeof next.repo === 'string' && next.repo !== '' ? next.repo : null,
|
|
176
|
+
lock: isPlainObject(next.lock) ? { enabled: next.lock.enabled === true, held: next.lock.held === true } : null,
|
|
177
|
+
lastBy: typeof next.lastBy === 'string' && next.lastBy !== '' ? next.lastBy : null,
|
|
178
|
+
lastReason: typeof next.lastReason === 'string' && next.lastReason !== '' ? next.lastReason : null,
|
|
179
|
+
source: typeof next.source === 'string' ? next.source : null,
|
|
180
|
+
}
|
|
181
|
+
diagnostics.mode = { known: value.known, on: value.on, denied: value.denied }
|
|
182
|
+
if (sameMode(value, state.value)) {
|
|
183
|
+
state.value = value
|
|
184
|
+
return
|
|
185
|
+
}
|
|
186
|
+
state.value = value
|
|
187
|
+
notifyMode()
|
|
188
|
+
}
|
|
189
|
+
function clearMode(writer) {
|
|
190
|
+
if (state.value.writer !== writer) return
|
|
191
|
+
const empty = Object.assign({}, EMPTY_MODE, { writer })
|
|
192
|
+
if (sameMode(empty, state.value)) {
|
|
193
|
+
state.value = empty
|
|
194
|
+
return
|
|
195
|
+
}
|
|
196
|
+
state.value = empty
|
|
197
|
+
diagnostics.mode = { known: false, on: null, denied: null }
|
|
198
|
+
notifyMode()
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return { nextDockWriter, modeSnapshot, subscribeMode, publishMode, clearMode, sameMode }
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return { EMPTY_MODE, towerCommandAction, repoNameOf, modeModelFromLegacy, createModeStore }
|
|
205
|
+
},
|
|
206
|
+
})
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// dsh-tower-ui 0.2.2 — the transient shell.overlay status strip.
|
|
2
|
+
//
|
|
3
|
+
// Root-scoped (no chat hooks), so the toolview publishes a notice into this
|
|
4
|
+
// observable and the strip injects it; the timer is owned by apply's ctx.effect.
|
|
5
|
+
// Package-local chunk (#71).
|
|
6
|
+
window.__ModuleLoader__.load({
|
|
7
|
+
id: 'dsh-tower-ui',
|
|
8
|
+
chunk: 'client.overlay.js',
|
|
9
|
+
factory() {
|
|
10
|
+
function createOverlay(env) {
|
|
11
|
+
const { h, translate, toolLabel, seatT, ST, dotStyle, helpers } = env
|
|
12
|
+
const { isPlainObject } = helpers
|
|
13
|
+
// Mutable state lives in this closure; the module has no top-level state.
|
|
14
|
+
const state = { value: null }
|
|
15
|
+
const listeners = new Set()
|
|
16
|
+
|
|
17
|
+
function snapshot() {
|
|
18
|
+
return state.value
|
|
19
|
+
}
|
|
20
|
+
function subscribe(listener) {
|
|
21
|
+
listeners.add(listener)
|
|
22
|
+
return function () {
|
|
23
|
+
listeners.delete(listener)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function setNotice(next) {
|
|
27
|
+
if (Object.is(next, state.value)) return
|
|
28
|
+
state.value = next
|
|
29
|
+
for (const listener of Array.from(listeners)) {
|
|
30
|
+
try {
|
|
31
|
+
listener()
|
|
32
|
+
} catch (error) {
|
|
33
|
+
/* a broken subscriber must not break the strip */
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const source = { getSnapshot: snapshot, subscribe: subscribe }
|
|
38
|
+
|
|
39
|
+
function TowerStatusStrip(props) {
|
|
40
|
+
const t = seatT(props)
|
|
41
|
+
if (!props || typeof props.useTowerNotice !== 'function') return null
|
|
42
|
+
const notice = props.useTowerNotice(function (value) {
|
|
43
|
+
return value
|
|
44
|
+
})
|
|
45
|
+
if (!isPlainObject(notice)) return null
|
|
46
|
+
const running = notice.running === true
|
|
47
|
+
const failed = notice.ok === false
|
|
48
|
+
const tone = running ? 'idle' : failed ? 'error' : 'ok'
|
|
49
|
+
const text = translate(t, running ? 'strip.started' : failed ? 'strip.failed' : 'strip.finished', {
|
|
50
|
+
tool: toolLabel(t, notice.tool),
|
|
51
|
+
})
|
|
52
|
+
return h(
|
|
53
|
+
'div',
|
|
54
|
+
{ 'data-tower-ui': 'status-strip', role: 'status', 'aria-live': 'polite', style: ST.stripWrap },
|
|
55
|
+
h('div', { style: ST.stripCard }, h('span', { 'aria-hidden': true, style: dotStyle(tone) }, null), h('span', null, text)),
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return { source, setNotice, TowerStatusStrip }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return { createOverlay }
|
|
63
|
+
},
|
|
64
|
+
})
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// dsh-tower-ui 0.2.2 — the inline style table.
|
|
2
|
+
//
|
|
3
|
+
// Theme references are restricted to `--dsw-alias-*` tokens. Chunk (#71).
|
|
4
|
+
window.__ModuleLoader__.load({
|
|
5
|
+
id: 'dsh-tower-ui',
|
|
6
|
+
chunk: 'client.styles.js',
|
|
7
|
+
factory() {
|
|
8
|
+
const TONE = {
|
|
9
|
+
ok: 'var(--dsw-alias-state-success-primary)',
|
|
10
|
+
warn: 'var(--dsw-alias-state-warn-primary)',
|
|
11
|
+
error: 'var(--dsw-alias-state-error-primary)',
|
|
12
|
+
idle: 'var(--dsw-alias-state-idle-primary)',
|
|
13
|
+
none: 'var(--dsw-alias-label-tertiary)',
|
|
14
|
+
}
|
|
15
|
+
const ST = {
|
|
16
|
+
card: {
|
|
17
|
+
display: 'flex',
|
|
18
|
+
flexDirection: 'column',
|
|
19
|
+
gap: '4px',
|
|
20
|
+
minWidth: 0,
|
|
21
|
+
maxWidth: '100%',
|
|
22
|
+
boxSizing: 'border-box',
|
|
23
|
+
margin: '2px 0 2px 4px',
|
|
24
|
+
padding: '8px 10px',
|
|
25
|
+
border: '0.5px solid var(--dsw-alias-border-l1)',
|
|
26
|
+
borderRadius: '8px',
|
|
27
|
+
background: 'var(--dsw-alias-bg-layer-1)',
|
|
28
|
+
color: 'var(--dsw-alias-label-secondary)',
|
|
29
|
+
fontSize: '12px',
|
|
30
|
+
lineHeight: '18px',
|
|
31
|
+
},
|
|
32
|
+
header: { display: 'flex', alignItems: 'center', gap: '6px', minWidth: 0 },
|
|
33
|
+
title: { color: 'var(--dsw-alias-label-primary)', flex: 'none' },
|
|
34
|
+
dim: {
|
|
35
|
+
color: 'var(--dsw-alias-label-tertiary)',
|
|
36
|
+
minWidth: 0,
|
|
37
|
+
overflow: 'hidden',
|
|
38
|
+
textOverflow: 'ellipsis',
|
|
39
|
+
whiteSpace: 'nowrap',
|
|
40
|
+
},
|
|
41
|
+
row: { minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' },
|
|
42
|
+
rowError: { color: 'var(--dsw-alias-state-error-primary)' },
|
|
43
|
+
rowWarn: { color: 'var(--dsw-alias-state-warn-primary)' },
|
|
44
|
+
rowOk: { color: 'var(--dsw-alias-state-success-primary)' },
|
|
45
|
+
hint: {
|
|
46
|
+
display: 'inline-flex',
|
|
47
|
+
alignItems: 'center',
|
|
48
|
+
gap: '4px',
|
|
49
|
+
padding: '0 6px',
|
|
50
|
+
fontSize: '11px',
|
|
51
|
+
lineHeight: '18px',
|
|
52
|
+
color: 'inherit',
|
|
53
|
+
opacity: 0.55,
|
|
54
|
+
userSelect: 'none',
|
|
55
|
+
whiteSpace: 'nowrap',
|
|
56
|
+
},
|
|
57
|
+
dock: {
|
|
58
|
+
display: 'inline-flex',
|
|
59
|
+
alignItems: 'center',
|
|
60
|
+
gap: '6px',
|
|
61
|
+
minWidth: 0,
|
|
62
|
+
maxWidth: '100%',
|
|
63
|
+
padding: '1px 8px',
|
|
64
|
+
fontSize: '11px',
|
|
65
|
+
lineHeight: '18px',
|
|
66
|
+
color: 'var(--dsw-alias-label-tertiary)',
|
|
67
|
+
whiteSpace: 'nowrap',
|
|
68
|
+
},
|
|
69
|
+
dockTool: { color: 'var(--dsw-alias-label-secondary)', flex: 'none' },
|
|
70
|
+
dockText: {
|
|
71
|
+
minWidth: 0,
|
|
72
|
+
overflow: 'hidden',
|
|
73
|
+
textOverflow: 'ellipsis',
|
|
74
|
+
color: 'var(--dsw-alias-label-tertiary)',
|
|
75
|
+
},
|
|
76
|
+
stripWrap: {
|
|
77
|
+
position: 'fixed',
|
|
78
|
+
left: '50%',
|
|
79
|
+
bottom: '16px',
|
|
80
|
+
transform: 'translateX(-50%)',
|
|
81
|
+
display: 'flex',
|
|
82
|
+
justifyContent: 'center',
|
|
83
|
+
pointerEvents: 'none',
|
|
84
|
+
zIndex: 9100,
|
|
85
|
+
maxWidth: 'calc(100vw - 32px)',
|
|
86
|
+
},
|
|
87
|
+
stripCard: {
|
|
88
|
+
pointerEvents: 'none',
|
|
89
|
+
display: 'inline-flex',
|
|
90
|
+
alignItems: 'center',
|
|
91
|
+
gap: '6px',
|
|
92
|
+
maxWidth: '100%',
|
|
93
|
+
padding: '4px 10px',
|
|
94
|
+
border: '0.5px solid var(--dsw-alias-border-l1)',
|
|
95
|
+
borderRadius: '999px',
|
|
96
|
+
background: 'var(--dsw-alias-bg-overlay)',
|
|
97
|
+
color: 'var(--dsw-alias-label-secondary)',
|
|
98
|
+
fontSize: '12px',
|
|
99
|
+
lineHeight: '18px',
|
|
100
|
+
whiteSpace: 'nowrap',
|
|
101
|
+
overflow: 'hidden',
|
|
102
|
+
textOverflow: 'ellipsis',
|
|
103
|
+
},
|
|
104
|
+
modeChip: {
|
|
105
|
+
display: 'inline-flex',
|
|
106
|
+
alignItems: 'center',
|
|
107
|
+
gap: '6px',
|
|
108
|
+
padding: '0 8px',
|
|
109
|
+
border: '0.5px solid var(--dsw-alias-border-l2)',
|
|
110
|
+
borderRadius: '999px',
|
|
111
|
+
background: 'var(--dsw-alias-bg-layer-1)',
|
|
112
|
+
color: 'var(--dsw-alias-label-secondary)',
|
|
113
|
+
fontSize: '11px',
|
|
114
|
+
lineHeight: '18px',
|
|
115
|
+
whiteSpace: 'nowrap',
|
|
116
|
+
userSelect: 'none',
|
|
117
|
+
},
|
|
118
|
+
modeChipLabel: { color: 'var(--dsw-alias-label-primary)' },
|
|
119
|
+
modeChipOn: { color: 'var(--dsw-alias-state-success-primary)' },
|
|
120
|
+
denyCard: {
|
|
121
|
+
display: 'flex',
|
|
122
|
+
flexDirection: 'column',
|
|
123
|
+
gap: '4px',
|
|
124
|
+
minWidth: 0,
|
|
125
|
+
maxWidth: '100%',
|
|
126
|
+
boxSizing: 'border-box',
|
|
127
|
+
margin: '2px 0 2px 4px',
|
|
128
|
+
padding: '8px 10px',
|
|
129
|
+
border: '0.5px solid var(--dsw-alias-border-l2)',
|
|
130
|
+
borderRadius: '8px',
|
|
131
|
+
background: 'var(--dsw-alias-bg-layer-1)',
|
|
132
|
+
color: 'var(--dsw-alias-label-secondary)',
|
|
133
|
+
fontSize: '12px',
|
|
134
|
+
lineHeight: '18px',
|
|
135
|
+
},
|
|
136
|
+
denyLabel: { color: 'var(--dsw-alias-state-warn-primary)', flex: 'none' },
|
|
137
|
+
denyHint: { color: 'var(--dsw-alias-label-tertiary)' },
|
|
138
|
+
}
|
|
139
|
+
function dotStyle(tone) {
|
|
140
|
+
return {
|
|
141
|
+
width: '6px',
|
|
142
|
+
height: '6px',
|
|
143
|
+
flex: 'none',
|
|
144
|
+
borderRadius: '999px',
|
|
145
|
+
background: TONE[tone] || TONE.none,
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return { TONE, ST, dotStyle }
|
|
150
|
+
},
|
|
151
|
+
})
|