martty 0.2.29 → 0.2.30
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/acp-session-stats.js +14 -0
- package/lib/agents-view.js +34 -9
- package/lib/boot.js +6 -0
- package/lib/one.js +21 -0
- package/lib/palettes/one.json +44 -0
- package/lib/palettes/tomorrow.json +44 -0
- package/lib/plan-view.js +15 -5
- package/lib/stats-view.js +20 -28
- package/lib/status-view.js +3 -2
- package/lib/tomorrow.js +22 -0
- package/package.json +1 -1
- package/vendor/darwin-arm64/martty +0 -0
- package/vendor/darwin-x64/martty +0 -0
- package/vendor/linux-arm64/martty +0 -0
- package/vendor/linux-x64/martty +0 -0
- package/vendor/win32-x64/martty.exe +0 -0
package/lib/acp-session-stats.js
CHANGED
|
@@ -25,6 +25,7 @@ function zero(sessionId) {
|
|
|
25
25
|
usage: {
|
|
26
26
|
input: 0, output: 0, cached: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0,
|
|
27
27
|
},
|
|
28
|
+
context: { used: 0, size: 0 },
|
|
28
29
|
stats: {
|
|
29
30
|
turns: 0,
|
|
30
31
|
steps: 0,
|
|
@@ -137,6 +138,19 @@ export function installAcpSessionStats(ctx, options = {}) {
|
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
const type = readString(update, 'sessionUpdate', 'session_update')
|
|
141
|
+
if (type === 'usage_update') {
|
|
142
|
+
// Harness-authoritative context gauge: `used` is the final prompt
|
|
143
|
+
// size (input + cache + output) of the last step and `size` the
|
|
144
|
+
// real model window from `request/context`. Client-side
|
|
145
|
+
// accumulation cannot derive either: per-prompt input sums every
|
|
146
|
+
// step's full context, and standard ACP does not carry the window.
|
|
147
|
+
const size = number(update.size)
|
|
148
|
+
if (size > 0) {
|
|
149
|
+
value.context = { used: number(update.used), size }
|
|
150
|
+
publish()
|
|
151
|
+
}
|
|
152
|
+
return
|
|
153
|
+
}
|
|
140
154
|
const prompt = sessionId === undefined ? undefined : activePrompts.get(sessionId)
|
|
141
155
|
if (prompt !== undefined && prompt.firstToken === undefined
|
|
142
156
|
&& (type === 'agent_message_chunk' || type === 'agent_thought_chunk')
|
package/lib/agents-view.js
CHANGED
|
@@ -5,29 +5,49 @@ export const inject = ['tuiAgents', 'tuiSlots', 'tuiCommands']
|
|
|
5
5
|
|
|
6
6
|
export function apply(ctx) {
|
|
7
7
|
let current = ctx.tuiAgents.current()
|
|
8
|
+
// Issue #80: `/agents` is an on/off switch for the panel. `visible` is
|
|
9
|
+
// the user preference; `forced` remembers `/agents on` so the summary
|
|
10
|
+
// stays open even after every task ended, until the next batch starts.
|
|
11
|
+
let visible = true
|
|
12
|
+
let forced = false
|
|
8
13
|
let panel
|
|
9
14
|
|
|
10
15
|
const stopSlot = ctx.tuiSlots.inject('conversation.navigation.dock', () => {
|
|
11
16
|
panel = ctx.tuiSlots.register(
|
|
12
17
|
{ name: 'conversation.navigation.dock', id: 'agents-view', order: 0 },
|
|
13
|
-
dockNodes(current),
|
|
18
|
+
dockNodes(current, visible, forced),
|
|
14
19
|
)
|
|
15
20
|
return () => panel.dispose()
|
|
16
21
|
})
|
|
17
22
|
const stopAgents = ctx.tuiAgents.subscribe((snapshot) => {
|
|
18
23
|
current = snapshot
|
|
19
|
-
panel
|
|
24
|
+
// A new running batch clears the forced-open state so the panel
|
|
25
|
+
// auto-closes again once this batch ends.
|
|
26
|
+
if (snapshot.items.some((item) => item.kind === 'subagent' && item.status === 'running')) {
|
|
27
|
+
forced = false
|
|
28
|
+
}
|
|
29
|
+
panel?.update(dockNodes(current, visible, forced))
|
|
20
30
|
})
|
|
21
31
|
const stopCommand = ctx.tuiCommands.register({
|
|
22
32
|
name: 'agents',
|
|
23
|
-
description: '
|
|
33
|
+
description: 'Toggle the Agent panel (on/off)',
|
|
34
|
+
input: { hint: '[on|off|agent-id]' },
|
|
24
35
|
}, async (args) => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
36
|
+
const arg = args.trim().toLowerCase()
|
|
37
|
+
if (arg === 'on') {
|
|
38
|
+
visible = true
|
|
39
|
+
forced = true
|
|
40
|
+
} else if (arg === 'off') {
|
|
41
|
+
visible = false
|
|
42
|
+
forced = false
|
|
43
|
+
} else if (arg === '') {
|
|
44
|
+
visible = !visible
|
|
45
|
+
forced = visible
|
|
46
|
+
} else {
|
|
47
|
+
return ctx.tuiAgents.select(args.trim())
|
|
29
48
|
}
|
|
30
|
-
|
|
49
|
+
panel?.update(dockNodes(current, visible, forced))
|
|
50
|
+
return true
|
|
31
51
|
})
|
|
32
52
|
|
|
33
53
|
return () => {
|
|
@@ -37,9 +57,10 @@ export function apply(ctx) {
|
|
|
37
57
|
}
|
|
38
58
|
}
|
|
39
59
|
|
|
40
|
-
function dockNodes(snapshot) {
|
|
60
|
+
function dockNodes(snapshot, visible = true, forced = false) {
|
|
41
61
|
if (!Array.isArray(snapshot?.items) || snapshot.items.length < 2) return []
|
|
42
62
|
const selecting = snapshot.selectedId !== null && snapshot.selectedId !== undefined
|
|
63
|
+
if (!visible && !selecting) return []
|
|
43
64
|
if (!selecting) {
|
|
44
65
|
const agents = snapshot.items.filter((item) => item.kind === 'subagent')
|
|
45
66
|
const marked = agents.filter((item) => item.current !== false)
|
|
@@ -47,6 +68,10 @@ function dockNodes(snapshot) {
|
|
|
47
68
|
const completed = current.filter((item) => item.status === 'finished' || item.status === 'failed').length
|
|
48
69
|
const running = current.some((item) => item.status === 'running')
|
|
49
70
|
const failed = current.some((item) => item.status === 'failed')
|
|
71
|
+
// Issue #80: auto-close once every Agent task has ended. A failed task
|
|
72
|
+
// keeps the summary so the failure stays visible; `/agents on` (forced)
|
|
73
|
+
// holds it open until the next batch starts running.
|
|
74
|
+
if (!running && !failed && !forced) return []
|
|
50
75
|
return [
|
|
51
76
|
{
|
|
52
77
|
id: 'summary', kind: 'generic', title: '· Agents', body: `${completed}/${current.length}`,
|
package/lib/boot.js
CHANGED
|
@@ -42,6 +42,8 @@ import { apply as applyKanagawa, inject as kanagawaInject } from './kanagawa.js'
|
|
|
42
42
|
import { apply as applyEverforest, inject as everforestInject } from './everforest.js'
|
|
43
43
|
import { apply as applyIceberg, inject as icebergInject } from './iceberg.js'
|
|
44
44
|
import { apply as applySolarized, inject as solarizedInject } from './solarized.js'
|
|
45
|
+
import { apply as applyOne, inject as oneInject } from './one.js'
|
|
46
|
+
import { apply as applyTomorrow, inject as tomorrowInject } from './tomorrow.js'
|
|
45
47
|
import { apply as applyCommands } from './tui-commands.js'
|
|
46
48
|
import { apply as applyOverlay } from './tui-overlay.js'
|
|
47
49
|
import { apply as applyAgents } from './tui-agents.js'
|
|
@@ -86,6 +88,8 @@ export async function bootClient(options = {}) {
|
|
|
86
88
|
await ctx.plugin({ name: 'tui-theme-everforest', inject: everforestInject, apply: applyEverforest })
|
|
87
89
|
await ctx.plugin({ name: 'tui-theme-iceberg', inject: icebergInject, apply: applyIceberg })
|
|
88
90
|
await ctx.plugin({ name: 'tui-theme-solarized', inject: solarizedInject, apply: applySolarized })
|
|
91
|
+
await ctx.plugin({ name: 'tui-theme-one', inject: oneInject, apply: applyOne })
|
|
92
|
+
await ctx.plugin({ name: 'tui-theme-tomorrow', inject: tomorrowInject, apply: applyTomorrow })
|
|
89
93
|
restorePreferredTheme(ctx.get('tuiTheme'))
|
|
90
94
|
await ctx.plugin({ name: 'tui-slots', inject: [], apply: applySlots })
|
|
91
95
|
await ctx.plugin({ name: 'tui-commands', inject: [], apply: applyCommands })
|
|
@@ -144,6 +148,8 @@ export async function bootClient(options = {}) {
|
|
|
144
148
|
applyEverforest(ctx)
|
|
145
149
|
applyIceberg(ctx)
|
|
146
150
|
applySolarized(ctx)
|
|
151
|
+
applyOne(ctx)
|
|
152
|
+
applyTomorrow(ctx)
|
|
147
153
|
restorePreferredTheme(ctx.tuiTheme)
|
|
148
154
|
applySlots(ctx)
|
|
149
155
|
applyCommands(ctx)
|
package/lib/one.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gallery palette pack `one`. Registers complete dark/light token maps:
|
|
3
|
+
* dark from One Dark, light from One Light (terminalcolors.com/themes/one). Does not activate:
|
|
4
|
+
* `/theme` covers it. `inject = ['tuiTheme']`: sibling profile row, not
|
|
5
|
+
* `ctx.plugin` inside the runner.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readFileSync } from 'node:fs'
|
|
9
|
+
|
|
10
|
+
const onePalette = JSON.parse(
|
|
11
|
+
readFileSync(new URL('./palettes/one.json', import.meta.url), 'utf8'),
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
export const name = 'tui-theme-one'
|
|
15
|
+
export const inject = ['tuiTheme']
|
|
16
|
+
|
|
17
|
+
export function apply(ctx) {
|
|
18
|
+
ctx.effect(() => ctx.tuiTheme.register(onePalette, { activate: false }))
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { onePalette }
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "one",
|
|
3
|
+
"label": "One",
|
|
4
|
+
"dark": {
|
|
5
|
+
"bg": "#282c34",
|
|
6
|
+
"surface": "#282c34",
|
|
7
|
+
"panel": "#1e2127",
|
|
8
|
+
"fg": "#abb2bf",
|
|
9
|
+
"fg_secondary": "#5c6370",
|
|
10
|
+
"fg_tertiary": "#5c6370",
|
|
11
|
+
"caption": "#5c6370",
|
|
12
|
+
"brand": "#61afef",
|
|
13
|
+
"brand_soft": "#c678dd",
|
|
14
|
+
"bubble_bg": "#abb2bf",
|
|
15
|
+
"bubble_fg": "#282c34",
|
|
16
|
+
"border": "#5c6370",
|
|
17
|
+
"code_bg": "#282c34",
|
|
18
|
+
"ok": "#98c379",
|
|
19
|
+
"warn": "#d19a66",
|
|
20
|
+
"err": "#e06c75",
|
|
21
|
+
"hint": "#56b6c2",
|
|
22
|
+
"chip_bg": "#1e2127"
|
|
23
|
+
},
|
|
24
|
+
"light": {
|
|
25
|
+
"bg": "#f8f8f8",
|
|
26
|
+
"surface": "#f8f8f8",
|
|
27
|
+
"panel": "#bbbbbb",
|
|
28
|
+
"fg": "#2a2b33",
|
|
29
|
+
"fg_secondary": "#5c6370",
|
|
30
|
+
"fg_tertiary": "#5c6370",
|
|
31
|
+
"caption": "#5c6370",
|
|
32
|
+
"brand": "#2f5af3",
|
|
33
|
+
"brand_soft": "#a00095",
|
|
34
|
+
"bubble_bg": "#2a2b33",
|
|
35
|
+
"bubble_fg": "#f8f8f8",
|
|
36
|
+
"border": "#5c6370",
|
|
37
|
+
"code_bg": "#f8f8f8",
|
|
38
|
+
"ok": "#3e953a",
|
|
39
|
+
"warn": "#c18401",
|
|
40
|
+
"err": "#de3d35",
|
|
41
|
+
"hint": "#0184bc",
|
|
42
|
+
"chip_bg": "#bbbbbb"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "tomorrow",
|
|
3
|
+
"label": "Tomorrow",
|
|
4
|
+
"dark": {
|
|
5
|
+
"bg": "#000000",
|
|
6
|
+
"surface": "#000000",
|
|
7
|
+
"panel": "#424242",
|
|
8
|
+
"fg": "#eaeaea",
|
|
9
|
+
"fg_secondary": "#969896",
|
|
10
|
+
"fg_tertiary": "#969896",
|
|
11
|
+
"caption": "#969896",
|
|
12
|
+
"brand": "#7aa6da",
|
|
13
|
+
"brand_soft": "#c397d8",
|
|
14
|
+
"bubble_bg": "#424242",
|
|
15
|
+
"bubble_fg": "#eaeaea",
|
|
16
|
+
"border": "#969896",
|
|
17
|
+
"code_bg": "#000000",
|
|
18
|
+
"ok": "#b9ca4a",
|
|
19
|
+
"warn": "#e7c547",
|
|
20
|
+
"err": "#d54e53",
|
|
21
|
+
"hint": "#70c0b1",
|
|
22
|
+
"chip_bg": "#424242"
|
|
23
|
+
},
|
|
24
|
+
"light": {
|
|
25
|
+
"bg": "#ffffff",
|
|
26
|
+
"surface": "#ffffff",
|
|
27
|
+
"panel": "#d6d6d6",
|
|
28
|
+
"fg": "#4d4d4c",
|
|
29
|
+
"fg_secondary": "#8e908c",
|
|
30
|
+
"fg_tertiary": "#8e908c",
|
|
31
|
+
"caption": "#8e908c",
|
|
32
|
+
"brand": "#4271ae",
|
|
33
|
+
"brand_soft": "#8959a8",
|
|
34
|
+
"bubble_bg": "#d6d6d6",
|
|
35
|
+
"bubble_fg": "#4d4d4c",
|
|
36
|
+
"border": "#8e908c",
|
|
37
|
+
"code_bg": "#ffffff",
|
|
38
|
+
"ok": "#718c00",
|
|
39
|
+
"warn": "#eab700",
|
|
40
|
+
"err": "#c82829",
|
|
41
|
+
"hint": "#3e999f",
|
|
42
|
+
"chip_bg": "#d6d6d6"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/lib/plan-view.js
CHANGED
|
@@ -25,7 +25,7 @@ export function apply(ctx) {
|
|
|
25
25
|
current = ctx.acpSessionPlan.current()
|
|
26
26
|
ctx.tuiOverlay.openView({
|
|
27
27
|
id: 'plan-view',
|
|
28
|
-
title:
|
|
28
|
+
title: viewTitle(current),
|
|
29
29
|
nodes: viewNodes(current),
|
|
30
30
|
})
|
|
31
31
|
})
|
|
@@ -67,6 +67,18 @@ function dockNodes(plan) {
|
|
|
67
67
|
}]
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
// The overlay window title: the `n/m` counter lives in the border, not in
|
|
71
|
+
// the body, so the review never repeats its heading (issue #85).
|
|
72
|
+
function viewTitle(plan) {
|
|
73
|
+
if (plan !== null && plan.kind === 'items') {
|
|
74
|
+
const total = plan.entries.length
|
|
75
|
+
if (total === 0) return 'Plan'
|
|
76
|
+
const completed = plan.entries.filter((entry) => entry.status === 'completed').length
|
|
77
|
+
return `Plan ${completed}/${total}`
|
|
78
|
+
}
|
|
79
|
+
return 'Plan'
|
|
80
|
+
}
|
|
81
|
+
|
|
70
82
|
function viewNodes(plan) {
|
|
71
83
|
if (plan === null) {
|
|
72
84
|
return [{ id: 'empty', kind: 'notice', level: 'info', text: 'No active plan' }]
|
|
@@ -78,10 +90,8 @@ function viewNodes(plan) {
|
|
|
78
90
|
return [{ id: 'file', kind: 'notice', level: 'info', text: plan.uri }]
|
|
79
91
|
}
|
|
80
92
|
// Items render as one markdown node: a task-list review the transcript
|
|
81
|
-
// pipeline can fully render (
|
|
82
|
-
const
|
|
83
|
-
const completed = plan.entries.filter((entry) => entry.status === 'completed').length
|
|
84
|
-
const lines = [`## Plan · ${completed}/${total}`, '']
|
|
93
|
+
// pipeline can fully render (bold, strikethrough).
|
|
94
|
+
const lines = []
|
|
85
95
|
for (const entry of plan.entries) {
|
|
86
96
|
const content = entry.content.replace(/\s*\n\s*/g, ' ')
|
|
87
97
|
let item
|
package/lib/stats-view.js
CHANGED
|
@@ -1,47 +1,38 @@
|
|
|
1
1
|
/** Built-in Client Plugin: standard ACP usage and timing in the composer dock. */
|
|
2
2
|
|
|
3
3
|
export const name = 'stats-view'
|
|
4
|
-
export const inject = ['acpSessionStats', '
|
|
4
|
+
export const inject = ['acpSessionStats', 'tuiSlots']
|
|
5
5
|
|
|
6
6
|
export function apply(ctx) {
|
|
7
7
|
let current = ctx.acpSessionStats.current()
|
|
8
|
-
let status = ctx.acpSessionStatus.current()
|
|
9
8
|
let panel
|
|
10
9
|
const stopSlot = ctx.tuiSlots.inject('conversation.composer.dock', () => {
|
|
11
10
|
panel = ctx.tuiSlots.register(
|
|
12
11
|
{ name: 'conversation.composer.dock', id: 'stats' },
|
|
13
|
-
nodesOf(current
|
|
12
|
+
nodesOf(current),
|
|
14
13
|
)
|
|
15
14
|
return () => panel.dispose()
|
|
16
15
|
})
|
|
17
16
|
const stopStats = ctx.acpSessionStats.subscribe((snapshot) => {
|
|
18
17
|
current = snapshot
|
|
19
|
-
panel?.update(nodesOf(current
|
|
20
|
-
})
|
|
21
|
-
const stopStatus = ctx.acpSessionStatus.subscribe((snapshot) => {
|
|
22
|
-
status = snapshot
|
|
23
|
-
panel?.update(nodesOf(current, status))
|
|
18
|
+
panel?.update(nodesOf(current))
|
|
24
19
|
})
|
|
25
20
|
return () => {
|
|
26
21
|
stopStats?.()
|
|
27
|
-
stopStatus?.()
|
|
28
22
|
stopSlot?.()
|
|
29
23
|
}
|
|
30
24
|
}
|
|
31
25
|
|
|
32
|
-
function nodesOf(snapshot
|
|
26
|
+
function nodesOf(snapshot) {
|
|
33
27
|
const usage = snapshot?.usage ?? {}
|
|
34
28
|
const stats = snapshot?.stats ?? {}
|
|
35
|
-
const model = status?.model
|
|
36
29
|
const nodes = []
|
|
37
30
|
if ((usage.input ?? 0) > 0 || (usage.output ?? 0) > 0) {
|
|
38
31
|
nodes.push(node('tokens', `↑${formatTokens(usage.input)} · ↓${formatTokens(usage.output)}`))
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const pct = Math.min(100, used / size * 100).toFixed(1)
|
|
44
|
-
nodes.push(node('context', `${pct}%/${contextSizeLabel(size)}`))
|
|
32
|
+
const gauge = contextGauge(snapshot)
|
|
33
|
+
if (gauge.used > 0 && gauge.size > 0) {
|
|
34
|
+
const pct = Math.min(100, gauge.used / gauge.size * 100).toFixed(1)
|
|
35
|
+
nodes.push(node('context', `${pct}%/${contextSizeLabel(gauge.size)}`))
|
|
45
36
|
}
|
|
46
37
|
}
|
|
47
38
|
if ((stats.turns ?? 0) > 0 || (stats.steps ?? 0) > 0) {
|
|
@@ -83,18 +74,19 @@ function node(id, title) {
|
|
|
83
74
|
function plural(value, singular) { return value === 1 ? singular : `${singular}s` }
|
|
84
75
|
|
|
85
76
|
/**
|
|
86
|
-
* Context
|
|
87
|
-
*
|
|
88
|
-
*
|
|
77
|
+
* Context-window gauge. Only the harness `usage_update` readout is shown:
|
|
78
|
+
* `used` is the final prompt size and `size` the real model window from
|
|
79
|
+
* `request/context`. Nothing client-side can reproduce either — per-turn
|
|
80
|
+
* usage sums every step's full context (multi-step turns over-report),
|
|
81
|
+
* and a model-name guess does not know the window (the old 128K guess is
|
|
82
|
+
* what pegged the dock at 100% early in issue #77). Without an
|
|
83
|
+
* authoritative readout the gauge is hidden instead of showing a wrong
|
|
84
|
+
* percentage.
|
|
89
85
|
*/
|
|
90
|
-
function
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return 1_000_000
|
|
95
|
-
default:
|
|
96
|
-
return 128_000
|
|
97
|
-
}
|
|
86
|
+
function contextGauge(snapshot) {
|
|
87
|
+
const context = snapshot?.context
|
|
88
|
+
if (context?.size > 0) return { used: context.used ?? 0, size: context.size }
|
|
89
|
+
return { used: 0, size: 0 }
|
|
98
90
|
}
|
|
99
91
|
|
|
100
92
|
/** `1000000` → `1.0M`, `128000` → `128K` — keeps the one-decimal look of
|
package/lib/status-view.js
CHANGED
|
@@ -27,7 +27,8 @@ export function apply(ctx) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* One
|
|
30
|
+
* One markdown node of run-state facts (the window border already names
|
|
31
|
+
* the popup, so no in-body heading). Facts come from
|
|
31
32
|
* `acpSessionStatus`; every token/turn/step/timing fact comes from
|
|
32
33
|
* `acpSessionStats.current()` — the same snapshot `stats-view` renders in
|
|
33
34
|
* the composer dock, so the two readouts can never drift apart.
|
|
@@ -37,7 +38,7 @@ function statusMarkdown(status, stats) {
|
|
|
37
38
|
const folded = stats?.stats ?? {}
|
|
38
39
|
const total = (usage.input ?? 0) + (usage.output ?? 0)
|
|
39
40
|
+ (usage.cached ?? 0) + (usage.reasoning ?? 0)
|
|
40
|
-
const lines = [
|
|
41
|
+
const lines = []
|
|
41
42
|
lines.push(`- state · ${status.state ?? 'idle'}`)
|
|
42
43
|
lines.push(`- acp · ${status.connection ?? 'not attached'}`)
|
|
43
44
|
if (status.auth?.status !== undefined) {
|
package/lib/tomorrow.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gallery palette pack `tomorrow`. Registers complete dark/light token maps:
|
|
3
|
+
* dark from Tomorrow Night Bright, light from Tomorrow
|
|
4
|
+
* (terminalcolors.com/themes/tomorrow). Does not activate:
|
|
5
|
+
* `/theme` covers it. `inject = ['tuiTheme']`: sibling profile row, not
|
|
6
|
+
* `ctx.plugin` inside the runner.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { readFileSync } from 'node:fs'
|
|
10
|
+
|
|
11
|
+
const tomorrowPalette = JSON.parse(
|
|
12
|
+
readFileSync(new URL('./palettes/tomorrow.json', import.meta.url), 'utf8'),
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
export const name = 'tui-theme-tomorrow'
|
|
16
|
+
export const inject = ['tuiTheme']
|
|
17
|
+
|
|
18
|
+
export function apply(ctx) {
|
|
19
|
+
ctx.effect(() => ctx.tuiTheme.register(tomorrowPalette, { activate: false }))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { tomorrowPalette }
|
package/package.json
CHANGED
|
Binary file
|
package/vendor/darwin-x64/martty
CHANGED
|
Binary file
|
|
Binary file
|
package/vendor/linux-x64/martty
CHANGED
|
Binary file
|
|
Binary file
|