Class: RubyRich::AppShell
- Inherits:
-
Object
- Object
- RubyRich::AppShell
show all
- Defined in:
- lib/ruby_rich/app_shell.rb
Defined Under Namespace
Classes: FocusTarget, FramedView, HeaderView, StatusView
Constant Summary
collapse
- DEFAULT_COMMANDS =
[
{ label: "/help", value: "/help", description: "Show commands" },
{ label: "/plan", value: "/plan", description: "Append a plan note" },
{ label: "/thinking", value: "/thinking", description: "Add a thinking block" },
{ label: "/tool", value: "/tool", description: "Add a tool call" },
{ label: "/quit", value: "/quit", description: "Exit demo" }
].freeze
Instance Attribute Summary collapse
Instance Method Summary
collapse
-
#add_assistant(text) ⇒ Object
-
#add_diff(title: nil, content:, language: "diff") ⇒ Object
-
#add_markdown(text) ⇒ Object
-
#add_separator(label = nil) ⇒ Object
-
#add_thinking(text, status: "idle", collapsed: true) ⇒ Object
-
#add_tool(name, status: :running, result: nil, collapsed: false) ⇒ Object
-
#add_user(text) ⇒ Object
-
#confirm(title:, message:, choices:, default: nil, &callback) ⇒ Object
-
#form(title:, fields:, &callback) ⇒ Object
-
#initialize(title: "Agent", subtitle: nil, model: "deepseek-v4-pro", theme: Theme.agent_dark, commands: DEFAULT_COMMANDS, on_submit: nil) ⇒ AppShell
constructor
A new instance of AppShell.
-
#open_pager(text, command: ENV.fetch("PAGER", "less -R")) ⇒ Object
-
#set_tasks(tasks) ⇒ Object
-
#show_token_usage(input: nil, output: nil, total: nil, **extra) ⇒ Object
-
#start(refresh_rate: 24, mouse: true, alt_screen: false) ⇒ Object
-
#start_progress(message = nil, owner: Thread.current.object_id, style: :primary, quiet_on_fast_finish: false) ⇒ Object
-
#status=(text) ⇒ Object
-
#stop ⇒ Object
-
#update_plan(text) ⇒ Object
-
#update_status(text) ⇒ Object
-
#with_progress(message = nil, style: :primary, quiet_on_fast_finish: false, &block) ⇒ Object
Constructor Details
#initialize(title: "Agent", subtitle: nil, model: "deepseek-v4-pro", theme: Theme.agent_dark, commands: DEFAULT_COMMANDS, on_submit: nil) ⇒ AppShell
Returns a new instance of AppShell.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
# File 'lib/ruby_rich/app_shell.rb', line 15
def initialize(title: "Agent", subtitle: nil, model: "deepseek-v4-pro", theme: Theme.agent_dark, commands: DEFAULT_COMMANDS, on_submit: nil)
@title = title
@subtitle = subtitle || "DeepSeek-TUI · #{model}"
@model = model
@theme = theme
@on_submit = on_submit
@status = "agent · #{model}"
@token_usage = nil
@progress_text = nil
@transcript = Transcript.new
@progress_manager = ProgressManager.new(on_change: ->(text) { @progress_text = text })
@viewport = Viewport.new(@transcript, scrollbar: true, auto_scroll: true)
@sidebar = Sidebar.new
@composer = Composer.new(
placeholder: "编写任务或使用 /。",
commands: commands,
on_submit: method(:handle_submit),
on_select: method(:handle_select)
)
@focus_manager = FocusManager.new
@layout = build_layout
attach_components
end
|
Instance Attribute Details
#composer ⇒ Object
Returns the value of attribute composer.
5
6
7
|
# File 'lib/ruby_rich/app_shell.rb', line 5
def composer
@composer
end
|
#focus_manager ⇒ Object
Returns the value of attribute focus_manager.
5
6
7
|
# File 'lib/ruby_rich/app_shell.rb', line 5
def focus_manager
@focus_manager
end
|
#layout ⇒ Object
Returns the value of attribute layout.
5
6
7
|
# File 'lib/ruby_rich/app_shell.rb', line 5
def layout
@layout
end
|
#live ⇒ Object
Returns the value of attribute live.
5
6
7
|
# File 'lib/ruby_rich/app_shell.rb', line 5
def live
@live
end
|
#progress_manager ⇒ Object
Returns the value of attribute progress_manager.
5
6
7
|
# File 'lib/ruby_rich/app_shell.rb', line 5
def progress_manager
@progress_manager
end
|
Returns the value of attribute sidebar.
5
6
7
|
# File 'lib/ruby_rich/app_shell.rb', line 5
def
@sidebar
end
|
#theme ⇒ Object
Returns the value of attribute theme.
5
6
7
|
# File 'lib/ruby_rich/app_shell.rb', line 5
def theme
@theme
end
|
#token_usage ⇒ Object
Returns the value of attribute token_usage.
5
6
7
|
# File 'lib/ruby_rich/app_shell.rb', line 5
def token_usage
@token_usage
end
|
#transcript ⇒ Object
Returns the value of attribute transcript.
5
6
7
|
# File 'lib/ruby_rich/app_shell.rb', line 5
def transcript
@transcript
end
|
#viewport ⇒ Object
Returns the value of attribute viewport.
5
6
7
|
# File 'lib/ruby_rich/app_shell.rb', line 5
def viewport
@viewport
end
|
Instance Method Details
#add_assistant(text) ⇒ Object
46
47
48
49
50
|
# File 'lib/ruby_rich/app_shell.rb', line 46
def add_assistant(text)
@transcript.add_assistant(text)
@viewport.scroll_to_bottom
self
end
|
#add_diff(title: nil, content:, language: "diff") ⇒ Object
76
77
78
79
80
81
|
# File 'lib/ruby_rich/app_shell.rb', line 76
def add_diff(title: nil, content:, language: "diff")
label = title ? "#{title}\n#{content}" : content
@transcript.add_block(:diff, label, language: language)
@viewport.scroll_to_bottom
self
end
|
#add_markdown(text) ⇒ Object
70
71
72
73
74
|
# File 'lib/ruby_rich/app_shell.rb', line 70
def add_markdown(text)
@transcript.add_markdown(text)
@viewport.scroll_to_bottom
self
end
|
#add_separator(label = nil) ⇒ Object
64
65
66
67
68
|
# File 'lib/ruby_rich/app_shell.rb', line 64
def add_separator(label = nil)
@transcript.add_separator(label)
@viewport.scroll_to_bottom
self
end
|
#add_thinking(text, status: "idle", collapsed: true) ⇒ Object
52
53
54
55
56
|
# File 'lib/ruby_rich/app_shell.rb', line 52
def add_thinking(text, status: "idle", collapsed: true)
@transcript.add_thinking(text, status: status, collapsed: collapsed)
@viewport.scroll_to_bottom
self
end
|
58
59
60
61
62
|
# File 'lib/ruby_rich/app_shell.rb', line 58
def add_tool(name, status: :running, result: nil, collapsed: false)
@transcript.add_tool(name, status: status, result: result, collapsed: collapsed)
@viewport.scroll_to_bottom
self
end
|
#add_user(text) ⇒ Object
40
41
42
43
44
|
# File 'lib/ruby_rich/app_shell.rb', line 40
def add_user(text)
@transcript.add_user(text)
@viewport.scroll_to_bottom
self
end
|
#confirm(title:, message:, choices:, default: nil, &callback) ⇒ Object
119
120
121
122
123
|
# File 'lib/ruby_rich/app_shell.rb', line 119
def confirm(title:, message:, choices:, default: nil, &callback)
result = default || choices.first&.fetch(:key)
callback.call(result) if callback
result
end
|
125
126
127
128
129
130
131
132
133
|
# File 'lib/ruby_rich/app_shell.rb', line 125
def form(title:, fields:, &callback)
values = {}
fields.each do |field|
name = field.fetch(:name).to_sym
values[name] = field.key?(:default) ? field[:default] : default_field_value(field)
end
callback.call(values) if callback
values
end
|
135
136
137
138
139
140
141
142
|
# File 'lib/ruby_rich/app_shell.rb', line 135
def (text, command: ENV.fetch("PAGER", "less -R"))
Terminal.with_cooked(mouse: true) do
IO.popen(command, "w") { |io| io.write(text.to_s) }
end
true
rescue
false
end
|
#set_tasks(tasks) ⇒ Object
88
89
90
91
|
# File 'lib/ruby_rich/app_shell.rb', line 88
def set_tasks(tasks)
@sidebar.set_tasks(tasks)
self
end
|
#show_token_usage(input: nil, output: nil, total: nil, **extra) ⇒ Object
102
103
104
105
|
# File 'lib/ruby_rich/app_shell.rb', line 102
def show_token_usage(input: nil, output: nil, total: nil, **)
@token_usage = { input: input, output: output, total: total }.merge().compact
self
end
|
#start(refresh_rate: 24, mouse: true, alt_screen: false) ⇒ Object
144
145
146
147
148
149
150
151
|
# File 'lib/ruby_rich/app_shell.rb', line 144
def start(refresh_rate: 24, mouse: true, alt_screen: false)
Live.start(@layout, refresh_rate: refresh_rate, mouse: mouse, alt_screen: alt_screen, autowrap: false) do |live|
@live = live
live.listening = true
end
ensure
@live = nil
end
|
#start_progress(message = nil, owner: Thread.current.object_id, style: :primary, quiet_on_fast_finish: false) ⇒ Object
107
108
109
110
111
|
# File 'lib/ruby_rich/app_shell.rb', line 107
def start_progress(message = nil, owner: Thread.current.object_id, style: :primary, quiet_on_fast_finish: false)
_ = style
_ = quiet_on_fast_finish
@progress_manager.start(message, owner: owner)
end
|
#status=(text) ⇒ Object
93
94
95
|
# File 'lib/ruby_rich/app_shell.rb', line 93
def status=(text)
@status = text.to_s
end
|
#stop ⇒ Object
153
154
155
156
157
|
# File 'lib/ruby_rich/app_shell.rb', line 153
def stop
return false unless @live
@live.post { |live| live.stop } || false
end
|
#update_plan(text) ⇒ Object
83
84
85
86
|
# File 'lib/ruby_rich/app_shell.rb', line 83
def update_plan(text)
@sidebar.update_plan(text)
self
end
|
#update_status(text) ⇒ Object
97
98
99
100
|
# File 'lib/ruby_rich/app_shell.rb', line 97
def update_status(text)
self.status = text
self
end
|
#with_progress(message = nil, style: :primary, quiet_on_fast_finish: false, &block) ⇒ Object
113
114
115
116
117
|
# File 'lib/ruby_rich/app_shell.rb', line 113
def with_progress(message = nil, style: :primary, quiet_on_fast_finish: false, &block)
_ = style
_ = quiet_on_fast_finish
@progress_manager.with_progress(message, &block)
end
|