@sagmans/dsh-tui 0.9.0 → 0.11.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/.agents/skills/dsh-tui-dogfood/SKILL.md +6 -1
- package/.agents/skills/dsh-tui-dogfood/scripts/run-plugin-from-worktree.sh +8 -0
- package/.agents/skills/dsh-tui-update-models/references/model-wiring.md +2 -2
- package/README.md +30 -19
- package/cordis.patch.yml +23 -100
- package/lib/agent/presets.d.ts.map +1 -1
- package/lib/agent/presets.js +8 -3
- package/lib/agent/presets.js.map +1 -1
- package/lib/compat/probe.js +1 -1
- package/lib/compat/probe.js.map +1 -1
- package/lib/compat/section.d.ts +8 -1
- package/lib/compat/section.d.ts.map +1 -1
- package/lib/compat/section.js +3 -2
- package/lib/compat/section.js.map +1 -1
- package/lib/herdr/client.d.ts +16 -0
- package/lib/herdr/client.d.ts.map +1 -1
- package/lib/herdr/client.js +60 -19
- package/lib/herdr/client.js.map +1 -1
- package/lib/herdr/constants.d.ts +11 -0
- package/lib/herdr/constants.d.ts.map +1 -1
- package/lib/herdr/constants.js +11 -0
- package/lib/herdr/constants.js.map +1 -1
- package/lib/herdr/reporter.d.ts +8 -0
- package/lib/herdr/reporter.d.ts.map +1 -1
- package/lib/herdr/reporter.js +58 -1
- package/lib/herdr/reporter.js.map +1 -1
- package/lib/herdr/state.d.ts +8 -4
- package/lib/herdr/state.d.ts.map +1 -1
- package/lib/herdr/state.js +10 -6
- package/lib/herdr/state.js.map +1 -1
- package/lib/host/preset-files.d.ts +27 -0
- package/lib/host/preset-files.d.ts.map +1 -0
- package/lib/host/preset-files.js +40 -0
- package/lib/host/preset-files.js.map +1 -0
- package/lib/host/roster.d.ts +17 -0
- package/lib/host/roster.d.ts.map +1 -0
- package/lib/host/roster.js +42 -0
- package/lib/host/roster.js.map +1 -0
- package/lib/host/runner.d.ts +15 -0
- package/lib/host/runner.d.ts.map +1 -0
- package/lib/host/runner.js +17 -0
- package/lib/host/runner.js.map +1 -0
- package/lib/index.d.ts +4 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +5 -2
- package/lib/index.js.map +1 -1
- package/lib/surface/appearance-preferences.d.ts.map +1 -1
- package/lib/surface/appearance-preferences.js +3 -2
- package/lib/surface/appearance-preferences.js.map +1 -1
- package/lib/surface/preset-choice.d.ts.map +1 -1
- package/lib/surface/preset-choice.js +38 -2
- package/lib/surface/preset-choice.js.map +1 -1
- package/lib/todo-guard.d.ts +17 -0
- package/lib/todo-guard.d.ts.map +1 -1
- package/lib/todo-guard.js +3 -1
- package/lib/todo-guard.js.map +1 -1
- package/lib/transcript/tool-calls.d.ts.map +1 -1
- package/lib/transcript/tool-calls.js +16 -2
- package/lib/transcript/tool-calls.js.map +1 -1
- package/package.json +40 -29
- package/presets/cordis.patch.yml +14 -0
- package/presets/minimal.patch.yml +14 -0
- package/presets/ptc.patch.yml +24 -0
- package/presets/standard.patch.yml +14 -0
- package/themes/deepseek-blue.yaml +6 -4
- package/themes/marine-static.yaml +201 -0
- package/themes/pine-slope.yaml +203 -0
- package/themes/polar-drift.yaml +194 -0
- package/themes/wine-thicket.yaml +205 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Agent preset standard: the mode this bundle's roster registers, and the whole
|
|
2
|
+
# of what it declares.
|
|
3
|
+
#
|
|
4
|
+
# A mode is a selection, not a composition. The rows that make up an agent's
|
|
5
|
+
# tools, prompt sections, skills and planning live in the bundle each of them
|
|
6
|
+
# belongs to, so listing them here would register a plugin this bundle does not
|
|
7
|
+
# own a second time and fail composition in a profile that already has it.
|
|
8
|
+
- insert:
|
|
9
|
+
- id: preset-standard
|
|
10
|
+
name: '@deepseek-ai/dsh-agent-preset'
|
|
11
|
+
config:
|
|
12
|
+
id: standard
|
|
13
|
+
order: 1
|
|
14
|
+
plugins: []
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# warn state-warn amber-500 #f59e0b
|
|
14
14
|
# added state-success green-500 #22c55e
|
|
15
15
|
# removed state-error red-400 #f25a5a
|
|
16
|
-
# user bubble neutral-bluish-850 #2c2c2e
|
|
16
|
+
# user bubble neutral-bluish-850 #2c2c2e (a panel border, not a fill)
|
|
17
17
|
#
|
|
18
18
|
# The brand itself is deepseek-500 #3964fe, drawn as deepseek-450 #5686fe on a
|
|
19
19
|
# dark surface. The accent is one step lighter than either because what it paints
|
|
@@ -38,12 +38,14 @@ palette:
|
|
|
38
38
|
warn: '#f59e0b' # state-warn, amber-500
|
|
39
39
|
added: '#22c55e' # state-success, green-500
|
|
40
40
|
removed: '#f25a5a' # state-error on a dark surface, red-400
|
|
41
|
-
user: '#2c2c2e' # the bubble fill, neutral-bluish-850
|
|
41
|
+
user: '#2c2c2e' # the product's bubble fill, neutral-bluish-850: only a panel border names it now
|
|
42
42
|
assistant: '#f9fafb' # label-primary, neutral-bluish-50
|
|
43
43
|
|
|
44
44
|
tokens:
|
|
45
|
-
# A row of the conversation.
|
|
46
|
-
|
|
45
|
+
# A row of the conversation. The product fills this one, but this surface
|
|
46
|
+
# already frames it, and a band inside the frame treats one fact twice: it reads
|
|
47
|
+
# as a selected row rather than as what the reader typed.
|
|
48
|
+
transcript.user: { fg: default }
|
|
47
49
|
# The sent prompt keeps the brand shade without inheriting editor overrides.
|
|
48
50
|
transcript.user.border: { fg: accent }
|
|
49
51
|
# The reply's own frame. A border is a container rather than a fact, so it may
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# marine-static — the shipped table, anchored on the deep teal #041F21.
|
|
2
|
+
#
|
|
3
|
+
# The anchor is a fill weight rather than a text weight: at 1.08:1 against a dark
|
|
4
|
+
# terminal it marks the row a picker has selected by its hue and adds almost no
|
|
5
|
+
# contrast of its own, which is why the accent is that same hue lifted to where
|
|
6
|
+
# text reads. Every neutral is the anchor's hue at a low saturation, so the surface
|
|
7
|
+
# reads as one family rather than as grey rows with a teal link on them.
|
|
8
|
+
#
|
|
9
|
+
# The shades hold the shipped table's own ladder — each role takes the same share
|
|
10
|
+
# of the theme's text luminance (muted 0.63, faint 0.42, arg 0.25, accent 0.57,
|
|
11
|
+
# warn 0.61, added 0.56, removed 0.25) — so this theme is dimmer in absolute terms
|
|
12
|
+
# and identical in structure to any other, and a reader who knows one knows this
|
|
13
|
+
# one. Only the level and the chroma are its own.
|
|
14
|
+
#
|
|
15
|
+
# This family stands in the same water as polar-drift's cyan, so the accent is held
|
|
16
|
+
# well back from the neon: the same hue with far less chroma at a lower level is
|
|
17
|
+
# what keeps the two from reading as one theme drawn twice. Green and amber sit far
|
|
18
|
+
# from the family and stay where every surface keeps them.
|
|
19
|
+
#
|
|
20
|
+
# Every element below names a palette entry rather than a shade of its own, so
|
|
21
|
+
# the anchor and the accent it lifts to are one line each to move. The three that
|
|
22
|
+
# name a literal say why there.
|
|
23
|
+
#
|
|
24
|
+
# This file is a reference and a layer, not a workspace: it ships inside the
|
|
25
|
+
# package and a new version replaces it. /theme export marine-static writes a full copy
|
|
26
|
+
# into your own themes directory to edit.
|
|
27
|
+
|
|
28
|
+
palette:
|
|
29
|
+
default: '#adbbbc' # the anchor's hue at 10% saturation: the level every other shade is a share of
|
|
30
|
+
muted: '#809a9b' # 0.63 of the text's luminance: labels and scaffolding
|
|
31
|
+
faint: '#638184' # 0.42: reasoning, which is meant to recede
|
|
32
|
+
accent: '#2e9ca4' # 0.56: the anchor's hue lifted to text weight for headings, links, code, frames
|
|
33
|
+
arg: '#3f686a' # 0.25: an argument recedes under the label of the call it belongs to
|
|
34
|
+
warn: '#bf8a1f' # 0.61, in amber: a call that has not answered
|
|
35
|
+
added: '#3b9f65' # 0.56, in green: something that arrived
|
|
36
|
+
removed: '#b03236' # 0.25, in red: something taken away
|
|
37
|
+
user: '#041f21' # the anchor itself: the band under a selected row, and one panel border
|
|
38
|
+
assistant: '#adbbbc' # the reply's text stays plain, so the frame is what marks it
|
|
39
|
+
|
|
40
|
+
tokens:
|
|
41
|
+
# A row of the conversation. The reader's own turn keeps its frame and carries
|
|
42
|
+
# no band: a filled row inside that frame reads as a selected row, and the
|
|
43
|
+
# anchor's own weight would swallow the text it is meant to hold.
|
|
44
|
+
transcript.user: { fg: default }
|
|
45
|
+
# A sent prompt keeps the accent shade without inheriting the editor's setting.
|
|
46
|
+
transcript.user.border: { fg: accent }
|
|
47
|
+
# The reply's own frame. It holds the family's hue at container weight rather
|
|
48
|
+
# than the accent the prompt is framed in: the two frames then differ by how
|
|
49
|
+
# loud they are instead of by hue, and a long answer never wears the shade that
|
|
50
|
+
# means "this is what you typed".
|
|
51
|
+
transcript.assistant.border: { fg: '#416265' }
|
|
52
|
+
transcript.notice: { fg: muted }
|
|
53
|
+
transcript.marker: { fg: muted }
|
|
54
|
+
transcript.reasoning.summary: { fg: faint, italic: true }
|
|
55
|
+
transcript.reasoning.body: { fg: faint }
|
|
56
|
+
transcript.reasoning.hint: { fg: faint, italic: true }
|
|
57
|
+
# A tool card, drawn in layers: every card, then one kind of card.
|
|
58
|
+
# A call is not a warning, so the label takes the accent rather than the amber
|
|
59
|
+
# the surface reserves for a call that has not answered — the label is the
|
|
60
|
+
# loudest thing on the row, and loudness is what the accent is for.
|
|
61
|
+
tool.title: { fg: accent }
|
|
62
|
+
tool.glyph: { fg: accent } # follows the label it sits beside
|
|
63
|
+
tool.skill: { fg: accent } # follows the label it sits beside
|
|
64
|
+
tool.args: { fg: arg } # below the reasoning shade: an argument is quieter than what the call is doing
|
|
65
|
+
tool.stat.added: { fg: added }
|
|
66
|
+
tool.stat.changed: { fg: warn }
|
|
67
|
+
tool.stat.removed: { fg: removed }
|
|
68
|
+
tool.stat.size: { fg: muted }
|
|
69
|
+
tool.stat.separator: { fg: muted }
|
|
70
|
+
tool.detail: { fg: muted }
|
|
71
|
+
tool.hint: { fg: muted }
|
|
72
|
+
tool.failed.title: { fg: removed }
|
|
73
|
+
tool.failed.glyph: { fg: removed }
|
|
74
|
+
# A call still in flight is state, which is amber's job here; the failed row
|
|
75
|
+
# stays red so the two can never be read as each other.
|
|
76
|
+
tool.running.title: { fg: warn }
|
|
77
|
+
tool.running.elapsed: { fg: warn }
|
|
78
|
+
tool.elapsed.done: { fg: muted, italic: true }
|
|
79
|
+
tool.subcall.title: { fg: muted }
|
|
80
|
+
tool.subcall.running: { fg: warn }
|
|
81
|
+
tool.subcall.args: { fg: arg }
|
|
82
|
+
tool.diff.header: { fg: muted }
|
|
83
|
+
tool.diff.hunk: { fg: muted }
|
|
84
|
+
tool.diff.added: { fg: added }
|
|
85
|
+
tool.diff.removed: { fg: removed }
|
|
86
|
+
tool.read.header: { fg: muted }
|
|
87
|
+
tool.read.lineNumber: { fg: muted }
|
|
88
|
+
tool.read.line: { fg: muted }
|
|
89
|
+
tool.search.path: { fg: muted }
|
|
90
|
+
tool.search.lineNumber: { fg: muted }
|
|
91
|
+
tool.search.match: { fg: muted }
|
|
92
|
+
tool.search.truncated: { fg: muted }
|
|
93
|
+
tool.terminal.cwd: { fg: muted }
|
|
94
|
+
tool.terminal.status: { fg: muted }
|
|
95
|
+
tool.terminal.output: { fg: muted }
|
|
96
|
+
tool.web.url: { fg: muted }
|
|
97
|
+
tool.web.source: { fg: muted }
|
|
98
|
+
tool.web.truncated: { fg: muted }
|
|
99
|
+
tool.generic.detail: { fg: muted }
|
|
100
|
+
# A reply, which is markdown, and the diagrams in it.
|
|
101
|
+
markdown.heading: { fg: accent, bold: true }
|
|
102
|
+
markdown.link: { fg: accent, underline: true }
|
|
103
|
+
markdown.linkUrl: { fg: muted }
|
|
104
|
+
markdown.code: { fg: accent }
|
|
105
|
+
markdown.codeBlock: {}
|
|
106
|
+
markdown.codeBlockBorder: { fg: muted }
|
|
107
|
+
markdown.quote: { fg: muted }
|
|
108
|
+
markdown.quoteBorder: { fg: muted }
|
|
109
|
+
markdown.hr: { fg: muted }
|
|
110
|
+
markdown.listBullet: { fg: accent }
|
|
111
|
+
markdown.bold: { bold: true }
|
|
112
|
+
markdown.italic: { italic: true }
|
|
113
|
+
markdown.strikethrough: { strike: true }
|
|
114
|
+
markdown.underline: { underline: true }
|
|
115
|
+
# A fenced diff: the scaffolding recedes, the rows carry the semantic shades,
|
|
116
|
+
# and the characters that changed sit on a band of the row's own colour. The
|
|
117
|
+
# band is a shade derived from that colour rather than a palette entry, so it
|
|
118
|
+
# stays a literal, and the foreground inherits so a palette move carries both.
|
|
119
|
+
markdown.diff.header: { fg: muted }
|
|
120
|
+
markdown.diff.hunk: { fg: muted }
|
|
121
|
+
markdown.diff.context: {}
|
|
122
|
+
markdown.diff.added: { fg: added }
|
|
123
|
+
markdown.diff.removed: { fg: removed }
|
|
124
|
+
markdown.diff.addedEmphasis: { inherit: markdown.diff.added, bg: '#11291b' }
|
|
125
|
+
markdown.diff.removedEmphasis: { inherit: markdown.diff.removed, bg: '#301415' }
|
|
126
|
+
markdown.diagram.border: { fg: muted }
|
|
127
|
+
markdown.diagram.text: {}
|
|
128
|
+
markdown.diagram.edge: { fg: accent }
|
|
129
|
+
markdown.diagram.edgeLabel: { fg: muted }
|
|
130
|
+
markdown.diagram.title: { fg: accent, bold: true }
|
|
131
|
+
markdown.diagram.warning: { fg: warn }
|
|
132
|
+
# A list drawn over the transcript.
|
|
133
|
+
picker.title: { bold: true }
|
|
134
|
+
picker.glyph: { bold: true }
|
|
135
|
+
picker.note: { bold: true }
|
|
136
|
+
picker.filter: { fg: muted }
|
|
137
|
+
# A list is read by moving one row, so the rows the cursor is not on recede:
|
|
138
|
+
# the selected row is then found by its own shade rather than by hunting for
|
|
139
|
+
# the mark in front of it, which is what a bold row alone leaves a reader doing.
|
|
140
|
+
picker.row: { fg: muted }
|
|
141
|
+
picker.rowCurrent: { fg: accent, bold: true, bg: user }
|
|
142
|
+
picker.scrollNewer: { fg: muted }
|
|
143
|
+
picker.scrollOlder: { fg: muted }
|
|
144
|
+
picker.hint: { fg: muted }
|
|
145
|
+
picker.cursor: {}
|
|
146
|
+
picker.border: { fg: muted }
|
|
147
|
+
# A question or an approval, which stops the turn until it is answered.
|
|
148
|
+
gate.title: { bold: true }
|
|
149
|
+
gate.glyphApproval: { bold: true }
|
|
150
|
+
gate.glyphQuestion: { bold: true }
|
|
151
|
+
gate.detail: { fg: muted }
|
|
152
|
+
gate.option: {}
|
|
153
|
+
gate.optionCurrent: { bold: true }
|
|
154
|
+
gate.cursor: {}
|
|
155
|
+
gate.hint: { fg: muted }
|
|
156
|
+
# The work panel above the editor. Each panel is a bordered box, so the border
|
|
157
|
+
# is what says which panel a row belongs to and the rows themselves stay quiet.
|
|
158
|
+
dock.goal: { bold: true }
|
|
159
|
+
dock.planMode: { bold: true }
|
|
160
|
+
dock.todos.border: { fg: accent }
|
|
161
|
+
dock.todos.heading: { bold: true }
|
|
162
|
+
dock.todos.pending: { fg: muted }
|
|
163
|
+
dock.todos.inProgress: { fg: muted }
|
|
164
|
+
dock.todos.overflow: { fg: muted }
|
|
165
|
+
dock.subagents.border: { fg: user }
|
|
166
|
+
dock.subagents.heading: { bold: true }
|
|
167
|
+
dock.subagents.running: { fg: muted }
|
|
168
|
+
dock.subagents.overflow: { fg: muted }
|
|
169
|
+
dock.jobs.border: { fg: warn }
|
|
170
|
+
dock.jobs.heading: { bold: true }
|
|
171
|
+
dock.jobs.running: { fg: muted }
|
|
172
|
+
dock.jobs.overflow: { fg: muted }
|
|
173
|
+
# The footer.
|
|
174
|
+
status.prefix: { fg: accent }
|
|
175
|
+
status.back: { fg: accent }
|
|
176
|
+
# A turn in flight is the one state a reader waits on, so it takes the accent
|
|
177
|
+
# and the weight; ready stays quiet because it is where the surface rests.
|
|
178
|
+
status.activity.working: { fg: accent, bold: true }
|
|
179
|
+
status.activity.ready: { fg: muted }
|
|
180
|
+
status.elapsed: { fg: muted }
|
|
181
|
+
status.agentPreset: { fg: muted }
|
|
182
|
+
status.model: { fg: muted }
|
|
183
|
+
status.effort: { fg: muted }
|
|
184
|
+
status.permission: { fg: muted }
|
|
185
|
+
status.context: { fg: muted }
|
|
186
|
+
status.cache: { fg: muted }
|
|
187
|
+
status.stash: { fg: accent }
|
|
188
|
+
status.cwd: { fg: muted }
|
|
189
|
+
status.separator: { fg: muted }
|
|
190
|
+
# The prompt bar.
|
|
191
|
+
# The one border in the surface that is not a divider: it holds what the reader
|
|
192
|
+
# is writing, which is where the brand belongs on a send affordance.
|
|
193
|
+
editor.border: { fg: accent }
|
|
194
|
+
editor.queued: { dim: true, italic: true }
|
|
195
|
+
editor.queued.more: { fg: muted }
|
|
196
|
+
editor.ghost: { dim: true }
|
|
197
|
+
editor.selectList.selectedPrefix: { fg: accent }
|
|
198
|
+
editor.selectList.selectedText: { bold: true }
|
|
199
|
+
editor.selectList.description: { fg: muted }
|
|
200
|
+
editor.selectList.scrollInfo: { fg: muted }
|
|
201
|
+
editor.selectList.noMatch: { fg: muted }
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# pine-slope — the shipped table, anchored on the pine #173802.
|
|
2
|
+
#
|
|
3
|
+
# The anchor is a fill weight rather than a text weight: at 1.41:1 against a dark
|
|
4
|
+
# terminal it paints the band under a selected row and the one panel border that
|
|
5
|
+
# names it, and the accent is that same hue lifted to where text reads. Every
|
|
6
|
+
# neutral is the anchor's hue at a low saturation, so the surface reads as one
|
|
7
|
+
# family rather than as grey rows with a green link on them.
|
|
8
|
+
#
|
|
9
|
+
# The shades hold the shipped table's own ladder — each role takes the same share
|
|
10
|
+
# of the theme's text luminance (muted 0.63, faint 0.42, arg 0.25, accent 0.57,
|
|
11
|
+
# warn 0.61, added 0.56, removed 0.25) — so this theme is dimmer in absolute terms
|
|
12
|
+
# and identical in structure to any other, and a reader who knows one knows this
|
|
13
|
+
# one. Only the level and the chroma are its own, which is what keeps it soft
|
|
14
|
+
# beside a bright terminal instead of competing with it.
|
|
15
|
+
#
|
|
16
|
+
# Green is the family here, and green is also what an added line means. The
|
|
17
|
+
# accent therefore stays a lime while the semantic green is pushed toward grass:
|
|
18
|
+
# a reader never has to ask whether a green row is the theme or the change. Red
|
|
19
|
+
# and amber stay where every surface keeps them — something removed, a call that
|
|
20
|
+
# has not answered.
|
|
21
|
+
#
|
|
22
|
+
# Every element below names a palette entry rather than a shade of its own, so
|
|
23
|
+
# the anchor and the accent it lifts to are one line each to move. The three that
|
|
24
|
+
# name a literal say why there.
|
|
25
|
+
#
|
|
26
|
+
# This file is a reference and a layer, not a workspace: it ships inside the
|
|
27
|
+
# package and a new version replaces it. /theme export pine-slope writes a full
|
|
28
|
+
# copy into your own themes directory to edit.
|
|
29
|
+
|
|
30
|
+
palette:
|
|
31
|
+
default: '#bac1b3' # the anchor's hue at 7% saturation: the level every other shade is a share of
|
|
32
|
+
muted: '#939f89' # 0.63 of the text's luminance: labels and scaffolding
|
|
33
|
+
faint: '#738768' # 0.42: reasoning, which is meant to recede
|
|
34
|
+
accent: '#69a33a' # 0.57: the anchor's hue lifted to text weight for headings, links, code, frames
|
|
35
|
+
arg: '#506d3c' # 0.25: an argument recedes under the label of the call it belongs to
|
|
36
|
+
warn: '#c59021' # 0.61, in amber: a call that has not answered
|
|
37
|
+
added: '#41a477' # 0.56, pushed toward grass: a change is not the theme's own green
|
|
38
|
+
removed: '#b43937' # 0.25, in red: something taken away
|
|
39
|
+
user: '#173802' # the anchor itself: the band under a selected row, and one panel border
|
|
40
|
+
assistant: '#bac1b3' # the reply's text stays plain, so the frame is what marks it
|
|
41
|
+
|
|
42
|
+
tokens:
|
|
43
|
+
# A row of the conversation. The reader's own turn keeps its frame and carries
|
|
44
|
+
# no band: a filled row inside that frame reads as a selected row, and the
|
|
45
|
+
# anchor's own weight would swallow the text it is meant to hold.
|
|
46
|
+
transcript.user: { fg: default }
|
|
47
|
+
# A sent prompt keeps the accent shade without inheriting the editor's setting.
|
|
48
|
+
transcript.user.border: { fg: accent }
|
|
49
|
+
# The reply's own frame. It holds the family's hue at container weight rather
|
|
50
|
+
# than the accent the prompt is framed in: the two frames then differ by how
|
|
51
|
+
# loud they are instead of by hue, and a long answer never wears the shade that
|
|
52
|
+
# means "this is what you typed".
|
|
53
|
+
transcript.assistant.border: { fg: '#526646' }
|
|
54
|
+
transcript.notice: { fg: muted }
|
|
55
|
+
transcript.marker: { fg: muted }
|
|
56
|
+
transcript.reasoning.summary: { fg: faint, italic: true }
|
|
57
|
+
transcript.reasoning.body: { fg: faint }
|
|
58
|
+
transcript.reasoning.hint: { fg: faint, italic: true }
|
|
59
|
+
# A tool card, drawn in layers: every card, then one kind of card.
|
|
60
|
+
# A call is not a warning, so the label takes the accent rather than the amber
|
|
61
|
+
# the surface reserves for a call that has not answered — the label is the
|
|
62
|
+
# loudest thing on the row, and loudness is what the accent is for.
|
|
63
|
+
tool.title: { fg: accent }
|
|
64
|
+
tool.glyph: { fg: accent } # follows the label it sits beside
|
|
65
|
+
tool.skill: { fg: accent } # follows the label it sits beside
|
|
66
|
+
tool.args: { fg: arg } # below the reasoning shade: an argument is quieter than what the call is doing
|
|
67
|
+
tool.stat.added: { fg: added }
|
|
68
|
+
tool.stat.changed: { fg: warn }
|
|
69
|
+
tool.stat.removed: { fg: removed }
|
|
70
|
+
tool.stat.size: { fg: muted }
|
|
71
|
+
tool.stat.separator: { fg: muted }
|
|
72
|
+
tool.detail: { fg: muted }
|
|
73
|
+
tool.hint: { fg: muted }
|
|
74
|
+
tool.failed.title: { fg: removed }
|
|
75
|
+
tool.failed.glyph: { fg: removed }
|
|
76
|
+
# A call still in flight is state, which is amber's job here; the failed row
|
|
77
|
+
# stays red so the two can never be read as each other.
|
|
78
|
+
tool.running.title: { fg: warn }
|
|
79
|
+
tool.running.elapsed: { fg: warn }
|
|
80
|
+
tool.elapsed.done: { fg: muted, italic: true }
|
|
81
|
+
tool.subcall.title: { fg: muted }
|
|
82
|
+
tool.subcall.running: { fg: warn }
|
|
83
|
+
tool.subcall.args: { fg: arg }
|
|
84
|
+
tool.diff.header: { fg: muted }
|
|
85
|
+
tool.diff.hunk: { fg: muted }
|
|
86
|
+
tool.diff.added: { fg: added }
|
|
87
|
+
tool.diff.removed: { fg: removed }
|
|
88
|
+
tool.read.header: { fg: muted }
|
|
89
|
+
tool.read.lineNumber: { fg: muted }
|
|
90
|
+
tool.read.line: { fg: muted }
|
|
91
|
+
tool.search.path: { fg: muted }
|
|
92
|
+
tool.search.lineNumber: { fg: muted }
|
|
93
|
+
tool.search.match: { fg: muted }
|
|
94
|
+
tool.search.truncated: { fg: muted }
|
|
95
|
+
tool.terminal.cwd: { fg: muted }
|
|
96
|
+
tool.terminal.status: { fg: muted }
|
|
97
|
+
tool.terminal.output: { fg: muted }
|
|
98
|
+
tool.web.url: { fg: muted }
|
|
99
|
+
tool.web.source: { fg: muted }
|
|
100
|
+
tool.web.truncated: { fg: muted }
|
|
101
|
+
tool.generic.detail: { fg: muted }
|
|
102
|
+
# A reply, which is markdown, and the diagrams in it.
|
|
103
|
+
markdown.heading: { fg: accent, bold: true }
|
|
104
|
+
markdown.link: { fg: accent, underline: true }
|
|
105
|
+
markdown.linkUrl: { fg: muted }
|
|
106
|
+
markdown.code: { fg: accent }
|
|
107
|
+
markdown.codeBlock: {}
|
|
108
|
+
markdown.codeBlockBorder: { fg: muted }
|
|
109
|
+
markdown.quote: { fg: muted }
|
|
110
|
+
markdown.quoteBorder: { fg: muted }
|
|
111
|
+
markdown.hr: { fg: muted }
|
|
112
|
+
markdown.listBullet: { fg: accent }
|
|
113
|
+
markdown.bold: { bold: true }
|
|
114
|
+
markdown.italic: { italic: true }
|
|
115
|
+
markdown.strikethrough: { strike: true }
|
|
116
|
+
markdown.underline: { underline: true }
|
|
117
|
+
# A fenced diff: the scaffolding recedes, the rows carry the semantic shades,
|
|
118
|
+
# and the characters that changed sit on a band of the row's own colour. The
|
|
119
|
+
# band is a shade derived from that colour rather than a palette entry, so it
|
|
120
|
+
# stays a literal, and the foreground inherits so a palette move carries both.
|
|
121
|
+
markdown.diff.header: { fg: muted }
|
|
122
|
+
markdown.diff.hunk: { fg: muted }
|
|
123
|
+
markdown.diff.context: {}
|
|
124
|
+
markdown.diff.added: { fg: added }
|
|
125
|
+
markdown.diff.removed: { fg: removed }
|
|
126
|
+
markdown.diff.addedEmphasis: { inherit: markdown.diff.added, bg: '#112a1f' }
|
|
127
|
+
markdown.diff.removedEmphasis: { inherit: markdown.diff.removed, bg: '#381211' }
|
|
128
|
+
markdown.diagram.border: { fg: muted }
|
|
129
|
+
markdown.diagram.text: {}
|
|
130
|
+
markdown.diagram.edge: { fg: accent }
|
|
131
|
+
markdown.diagram.edgeLabel: { fg: muted }
|
|
132
|
+
markdown.diagram.title: { fg: accent, bold: true }
|
|
133
|
+
markdown.diagram.warning: { fg: warn }
|
|
134
|
+
# A list drawn over the transcript.
|
|
135
|
+
picker.title: { bold: true }
|
|
136
|
+
picker.glyph: { bold: true }
|
|
137
|
+
picker.note: { bold: true }
|
|
138
|
+
picker.filter: { fg: muted }
|
|
139
|
+
# A list is read by moving one row, so the rows the cursor is not on recede:
|
|
140
|
+
# the selected row is then found by its own shade rather than by hunting for
|
|
141
|
+
# the mark in front of it, which is what a bold row alone leaves a reader doing.
|
|
142
|
+
picker.row: { fg: muted }
|
|
143
|
+
picker.rowCurrent: { fg: accent, bold: true, bg: user }
|
|
144
|
+
picker.scrollNewer: { fg: muted }
|
|
145
|
+
picker.scrollOlder: { fg: muted }
|
|
146
|
+
picker.hint: { fg: muted }
|
|
147
|
+
picker.cursor: {}
|
|
148
|
+
picker.border: { fg: muted }
|
|
149
|
+
# A question or an approval, which stops the turn until it is answered.
|
|
150
|
+
gate.title: { bold: true }
|
|
151
|
+
gate.glyphApproval: { bold: true }
|
|
152
|
+
gate.glyphQuestion: { bold: true }
|
|
153
|
+
gate.detail: { fg: muted }
|
|
154
|
+
gate.option: {}
|
|
155
|
+
gate.optionCurrent: { bold: true }
|
|
156
|
+
gate.cursor: {}
|
|
157
|
+
gate.hint: { fg: muted }
|
|
158
|
+
# The work panel above the editor. Each panel is a bordered box, so the border
|
|
159
|
+
# is what says which panel a row belongs to and the rows themselves stay quiet.
|
|
160
|
+
dock.goal: { bold: true }
|
|
161
|
+
dock.planMode: { bold: true }
|
|
162
|
+
dock.todos.border: { fg: accent }
|
|
163
|
+
dock.todos.heading: { bold: true }
|
|
164
|
+
dock.todos.pending: { fg: muted }
|
|
165
|
+
dock.todos.inProgress: { fg: muted }
|
|
166
|
+
dock.todos.overflow: { fg: muted }
|
|
167
|
+
dock.subagents.border: { fg: user }
|
|
168
|
+
dock.subagents.heading: { bold: true }
|
|
169
|
+
dock.subagents.running: { fg: muted }
|
|
170
|
+
dock.subagents.overflow: { fg: muted }
|
|
171
|
+
dock.jobs.border: { fg: warn }
|
|
172
|
+
dock.jobs.heading: { bold: true }
|
|
173
|
+
dock.jobs.running: { fg: muted }
|
|
174
|
+
dock.jobs.overflow: { fg: muted }
|
|
175
|
+
# The footer.
|
|
176
|
+
status.prefix: { fg: accent }
|
|
177
|
+
status.back: { fg: accent }
|
|
178
|
+
# A turn in flight is the one state a reader waits on, so it takes the accent
|
|
179
|
+
# and the weight; ready stays quiet because it is where the surface rests.
|
|
180
|
+
status.activity.working: { fg: accent, bold: true }
|
|
181
|
+
status.activity.ready: { fg: muted }
|
|
182
|
+
status.elapsed: { fg: muted }
|
|
183
|
+
status.agentPreset: { fg: muted }
|
|
184
|
+
status.model: { fg: muted }
|
|
185
|
+
status.effort: { fg: muted }
|
|
186
|
+
status.permission: { fg: muted }
|
|
187
|
+
status.context: { fg: muted }
|
|
188
|
+
status.cache: { fg: muted }
|
|
189
|
+
status.stash: { fg: accent }
|
|
190
|
+
status.cwd: { fg: muted }
|
|
191
|
+
status.separator: { fg: muted }
|
|
192
|
+
# The prompt bar.
|
|
193
|
+
# The one border in the surface that is not a divider: it holds what the reader
|
|
194
|
+
# is writing, which is where the brand belongs on a send affordance.
|
|
195
|
+
editor.border: { fg: accent }
|
|
196
|
+
editor.queued: { dim: true, italic: true }
|
|
197
|
+
editor.queued.more: { fg: muted }
|
|
198
|
+
editor.ghost: { dim: true }
|
|
199
|
+
editor.selectList.selectedPrefix: { fg: accent }
|
|
200
|
+
editor.selectList.selectedText: { bold: true }
|
|
201
|
+
editor.selectList.description: { fg: muted }
|
|
202
|
+
editor.selectList.scrollInfo: { fg: muted }
|
|
203
|
+
editor.selectList.noMatch: { fg: muted }
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# polar-drift — the shipped table, anchored on the cyan #27CFF5.
|
|
2
|
+
#
|
|
3
|
+
# The anchor is the accent, and its hue is where every other shade comes from:
|
|
4
|
+
# the neutrals are that hue at a low saturation, and the argument sits light
|
|
5
|
+
# enough to recede under the label beside it. A surface tinted this way reads as
|
|
6
|
+
# one family, where literal greys under a cyan link read as two.
|
|
7
|
+
#
|
|
8
|
+
# The semantic shades are the deliberate exception. Something added is green and
|
|
9
|
+
# something removed is red on every surface a reader already uses, and amber is
|
|
10
|
+
# what says a call has not answered yet; a theme that moved them would make a
|
|
11
|
+
# reader learn each fact again per theme, on the screen where misreading them
|
|
12
|
+
# costs the most.
|
|
13
|
+
#
|
|
14
|
+
# Every element below names a palette entry rather than a shade of its own, so
|
|
15
|
+
# the anchor is one line to move. The three that name a literal say why there.
|
|
16
|
+
#
|
|
17
|
+
# This file is a reference and a layer, not a workspace: it ships inside the
|
|
18
|
+
# package and a new version replaces it. /theme export polar-drift writes a full
|
|
19
|
+
# copy into your own themes directory to edit.
|
|
20
|
+
|
|
21
|
+
palette:
|
|
22
|
+
default: '#f4f5f6' # #27CFF5's hue at 5% saturation: text that carries a trace of the anchor
|
|
23
|
+
muted: '#bfc9cc' # the same hue, one step down: labels and scaffolding
|
|
24
|
+
faint: '#8eacb1' # the same hue again: reasoning, which is meant to recede
|
|
25
|
+
accent: '#27CFF5' # the anchor: headings, links, code, and the frames that hold a turn
|
|
26
|
+
arg: '#5f8a95' # the anchor's hue a step below the reasoning shade: an argument recedes under the label
|
|
27
|
+
warn: '#faba42' # state-warn, left in amber: a call still in flight
|
|
28
|
+
added: '#29d96a' # state-success, left in green
|
|
29
|
+
removed: '#e35048' # state-error, left in red
|
|
30
|
+
user: '#1c3136' # the anchor's hue at its darkest: the band behind a selected row, and one panel border
|
|
31
|
+
assistant: '#f4f5f6' # the reply's text stays plain, so the frame is what marks it
|
|
32
|
+
|
|
33
|
+
tokens:
|
|
34
|
+
# A row of the conversation. The reader's own turn keeps its frame and carries
|
|
35
|
+
# no band: a filled row inside that frame reads as a selected row, and a band
|
|
36
|
+
# here would send the anchor's family a second, quieter meaning than the accent.
|
|
37
|
+
transcript.user: { fg: default }
|
|
38
|
+
# A sent prompt keeps the anchor shade without inheriting the editor's setting.
|
|
39
|
+
transcript.user.border: { fg: accent }
|
|
40
|
+
# The reply's own frame. It holds the family's hue at container weight rather
|
|
41
|
+
# than the accent the prompt is framed in: the two frames then differ by how
|
|
42
|
+
# loud they are instead of by hue, and a long answer never wears the shade that
|
|
43
|
+
# means "this is what you typed".
|
|
44
|
+
transcript.assistant.border: { fg: '#4f8593' }
|
|
45
|
+
transcript.notice: { fg: muted }
|
|
46
|
+
transcript.marker: { fg: muted }
|
|
47
|
+
transcript.reasoning.summary: { fg: faint, italic: true }
|
|
48
|
+
transcript.reasoning.body: { fg: faint }
|
|
49
|
+
transcript.reasoning.hint: { fg: faint, italic: true }
|
|
50
|
+
# A tool card, drawn in layers: every card, then one kind of card.
|
|
51
|
+
# A call is not a warning, so the label takes the anchor rather than the amber
|
|
52
|
+
# the surface reserves for a call that has not answered — the label is the
|
|
53
|
+
# loudest thing on the row, and loudness is what the anchor is for.
|
|
54
|
+
tool.title: { fg: accent }
|
|
55
|
+
tool.glyph: { fg: accent } # follows the label it sits beside
|
|
56
|
+
tool.skill: { fg: accent } # follows the label it sits beside
|
|
57
|
+
tool.args: { fg: arg } # below the reasoning shade: an argument is quieter than what the call is doing
|
|
58
|
+
tool.stat.added: { fg: added }
|
|
59
|
+
tool.stat.changed: { fg: warn }
|
|
60
|
+
tool.stat.removed: { fg: removed }
|
|
61
|
+
tool.stat.size: { fg: muted }
|
|
62
|
+
tool.stat.separator: { fg: muted }
|
|
63
|
+
tool.detail: { fg: muted }
|
|
64
|
+
tool.hint: { fg: muted }
|
|
65
|
+
tool.failed.title: { fg: removed }
|
|
66
|
+
tool.failed.glyph: { fg: removed }
|
|
67
|
+
# A call still in flight is state, which is amber's job here; the failed row
|
|
68
|
+
# stays red so the two can never be read as each other.
|
|
69
|
+
tool.running.title: { fg: warn }
|
|
70
|
+
tool.running.elapsed: { fg: warn }
|
|
71
|
+
tool.elapsed.done: { fg: muted, italic: true }
|
|
72
|
+
tool.subcall.title: { fg: muted }
|
|
73
|
+
tool.subcall.running: { fg: warn }
|
|
74
|
+
tool.subcall.args: { fg: arg }
|
|
75
|
+
tool.diff.header: { fg: muted }
|
|
76
|
+
tool.diff.hunk: { fg: muted }
|
|
77
|
+
tool.diff.added: { fg: added }
|
|
78
|
+
tool.diff.removed: { fg: removed }
|
|
79
|
+
tool.read.header: { fg: muted }
|
|
80
|
+
tool.read.lineNumber: { fg: muted }
|
|
81
|
+
tool.read.line: { fg: muted }
|
|
82
|
+
tool.search.path: { fg: muted }
|
|
83
|
+
tool.search.lineNumber: { fg: muted }
|
|
84
|
+
tool.search.match: { fg: muted }
|
|
85
|
+
tool.search.truncated: { fg: muted }
|
|
86
|
+
tool.terminal.cwd: { fg: muted }
|
|
87
|
+
tool.terminal.status: { fg: muted }
|
|
88
|
+
tool.terminal.output: { fg: muted }
|
|
89
|
+
tool.web.url: { fg: muted }
|
|
90
|
+
tool.web.source: { fg: muted }
|
|
91
|
+
tool.web.truncated: { fg: muted }
|
|
92
|
+
tool.generic.detail: { fg: muted }
|
|
93
|
+
# A reply, which is markdown, and the diagrams in it.
|
|
94
|
+
markdown.heading: { fg: accent, bold: true }
|
|
95
|
+
markdown.link: { fg: accent, underline: true }
|
|
96
|
+
markdown.linkUrl: { fg: muted }
|
|
97
|
+
markdown.code: { fg: accent }
|
|
98
|
+
markdown.codeBlock: {}
|
|
99
|
+
markdown.codeBlockBorder: { fg: muted }
|
|
100
|
+
markdown.quote: { fg: muted }
|
|
101
|
+
markdown.quoteBorder: { fg: muted }
|
|
102
|
+
markdown.hr: { fg: muted }
|
|
103
|
+
markdown.listBullet: { fg: accent }
|
|
104
|
+
markdown.bold: { bold: true }
|
|
105
|
+
markdown.italic: { italic: true }
|
|
106
|
+
markdown.strikethrough: { strike: true }
|
|
107
|
+
markdown.underline: { underline: true }
|
|
108
|
+
# A fenced diff: the scaffolding recedes, the rows carry the semantic shades,
|
|
109
|
+
# and the characters that changed sit on a band of the row's own colour. The
|
|
110
|
+
# band is a shade derived from that colour rather than a palette entry, so it
|
|
111
|
+
# stays a literal, and the foreground inherits so a palette move carries both.
|
|
112
|
+
markdown.diff.header: { fg: muted }
|
|
113
|
+
markdown.diff.hunk: { fg: muted }
|
|
114
|
+
markdown.diff.context: {}
|
|
115
|
+
markdown.diff.added: { fg: added }
|
|
116
|
+
markdown.diff.removed: { fg: removed }
|
|
117
|
+
markdown.diff.addedEmphasis: { inherit: markdown.diff.added, bg: '#183a24' }
|
|
118
|
+
markdown.diff.removedEmphasis: { inherit: markdown.diff.removed, bg: '#461d1b' }
|
|
119
|
+
markdown.diagram.border: { fg: muted }
|
|
120
|
+
markdown.diagram.text: {}
|
|
121
|
+
markdown.diagram.edge: { fg: accent }
|
|
122
|
+
markdown.diagram.edgeLabel: { fg: muted }
|
|
123
|
+
markdown.diagram.title: { fg: accent, bold: true }
|
|
124
|
+
markdown.diagram.warning: { fg: warn }
|
|
125
|
+
# A list drawn over the transcript.
|
|
126
|
+
picker.title: { bold: true }
|
|
127
|
+
picker.glyph: { bold: true }
|
|
128
|
+
picker.note: { bold: true }
|
|
129
|
+
picker.filter: { fg: muted }
|
|
130
|
+
# A list is read by moving one row, so the rows the cursor is not on recede:
|
|
131
|
+
# the selected row is then found by its own shade rather than by hunting for
|
|
132
|
+
# the mark in front of it, which is what a bold row alone leaves a reader doing.
|
|
133
|
+
picker.row: { fg: muted }
|
|
134
|
+
picker.rowCurrent: { fg: accent, bold: true, bg: user }
|
|
135
|
+
picker.scrollNewer: { fg: muted }
|
|
136
|
+
picker.scrollOlder: { fg: muted }
|
|
137
|
+
picker.hint: { fg: muted }
|
|
138
|
+
picker.cursor: {}
|
|
139
|
+
picker.border: { fg: muted }
|
|
140
|
+
# A question or an approval, which stops the turn until it is answered.
|
|
141
|
+
gate.title: { bold: true }
|
|
142
|
+
gate.glyphApproval: { bold: true }
|
|
143
|
+
gate.glyphQuestion: { bold: true }
|
|
144
|
+
gate.detail: { fg: muted }
|
|
145
|
+
gate.option: {}
|
|
146
|
+
gate.optionCurrent: { bold: true }
|
|
147
|
+
gate.cursor: {}
|
|
148
|
+
gate.hint: { fg: muted }
|
|
149
|
+
# The work panel above the editor. Each panel is a bordered box, so the border
|
|
150
|
+
# is what says which panel a row belongs to and the rows themselves stay quiet.
|
|
151
|
+
dock.goal: { bold: true }
|
|
152
|
+
dock.planMode: { bold: true }
|
|
153
|
+
dock.todos.border: { fg: accent }
|
|
154
|
+
dock.todos.heading: { bold: true }
|
|
155
|
+
dock.todos.pending: { fg: muted }
|
|
156
|
+
dock.todos.inProgress: { fg: muted }
|
|
157
|
+
dock.todos.overflow: { fg: muted }
|
|
158
|
+
dock.subagents.border: { fg: user }
|
|
159
|
+
dock.subagents.heading: { bold: true }
|
|
160
|
+
dock.subagents.running: { fg: muted }
|
|
161
|
+
dock.subagents.overflow: { fg: muted }
|
|
162
|
+
dock.jobs.border: { fg: warn }
|
|
163
|
+
dock.jobs.heading: { bold: true }
|
|
164
|
+
dock.jobs.running: { fg: muted }
|
|
165
|
+
dock.jobs.overflow: { fg: muted }
|
|
166
|
+
# The footer.
|
|
167
|
+
status.prefix: { fg: accent }
|
|
168
|
+
status.back: { fg: accent }
|
|
169
|
+
# A turn in flight is the one state a reader waits on, so it takes the anchor
|
|
170
|
+
# and the weight; ready stays quiet because it is where the surface rests.
|
|
171
|
+
status.activity.working: { fg: accent, bold: true }
|
|
172
|
+
status.activity.ready: { fg: muted }
|
|
173
|
+
status.elapsed: { fg: muted }
|
|
174
|
+
status.agentPreset: { fg: muted }
|
|
175
|
+
status.model: { fg: muted }
|
|
176
|
+
status.effort: { fg: muted }
|
|
177
|
+
status.permission: { fg: muted }
|
|
178
|
+
status.context: { fg: muted }
|
|
179
|
+
status.cache: { fg: muted }
|
|
180
|
+
status.stash: { fg: accent }
|
|
181
|
+
status.cwd: { fg: muted }
|
|
182
|
+
status.separator: { fg: muted }
|
|
183
|
+
# The prompt bar.
|
|
184
|
+
# The one border in the surface that is not a divider: it holds what the reader
|
|
185
|
+
# is writing, which is where the brand belongs on a send affordance.
|
|
186
|
+
editor.border: { fg: accent }
|
|
187
|
+
editor.queued: { dim: true, italic: true }
|
|
188
|
+
editor.queued.more: { fg: muted }
|
|
189
|
+
editor.ghost: { dim: true }
|
|
190
|
+
editor.selectList.selectedPrefix: { fg: accent }
|
|
191
|
+
editor.selectList.selectedText: { bold: true }
|
|
192
|
+
editor.selectList.description: { fg: muted }
|
|
193
|
+
editor.selectList.scrollInfo: { fg: muted }
|
|
194
|
+
editor.selectList.noMatch: { fg: muted }
|