language-operator 0.1.61 → 0.1.62
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.
- checksums.yaml +4 -4
- data/.claude/commands/persona.md +9 -0
- data/.claude/commands/task.md +46 -1
- data/.rubocop.yml +13 -0
- data/.rubocop_custom/use_ux_helper.rb +44 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +12 -1
- data/Makefile +26 -7
- data/Makefile.common +50 -0
- data/bin/aictl +8 -1
- data/components/agent/Gemfile +1 -1
- data/components/agent/bin/langop-agent +7 -0
- data/docs/README.md +58 -0
- data/docs/{dsl/best-practices.md → best-practices.md} +4 -4
- data/docs/cli-reference.md +274 -0
- data/docs/{dsl/constraints.md → constraints.md} +5 -5
- data/docs/how-agents-work.md +156 -0
- data/docs/installation.md +218 -0
- data/docs/quickstart.md +299 -0
- data/docs/understanding-generated-code.md +265 -0
- data/docs/using-tools.md +457 -0
- data/docs/webhooks.md +509 -0
- data/examples/ux_helpers_demo.rb +296 -0
- data/lib/language_operator/agent/base.rb +11 -1
- data/lib/language_operator/agent/executor.rb +23 -6
- data/lib/language_operator/agent/safety/safe_executor.rb +41 -39
- data/lib/language_operator/agent/task_executor.rb +346 -63
- data/lib/language_operator/agent/web_server.rb +110 -14
- data/lib/language_operator/agent/webhook_authenticator.rb +39 -5
- data/lib/language_operator/agent.rb +88 -2
- data/lib/language_operator/cli/base_command.rb +17 -11
- data/lib/language_operator/cli/command_loader.rb +72 -0
- data/lib/language_operator/cli/commands/agent/base.rb +837 -0
- data/lib/language_operator/cli/commands/agent/code_operations.rb +102 -0
- data/lib/language_operator/cli/commands/agent/helpers/cluster_llm_client.rb +116 -0
- data/lib/language_operator/cli/commands/agent/helpers/code_parser.rb +115 -0
- data/lib/language_operator/cli/commands/agent/helpers/synthesis_watcher.rb +96 -0
- data/lib/language_operator/cli/commands/agent/learning.rb +289 -0
- data/lib/language_operator/cli/commands/agent/lifecycle.rb +102 -0
- data/lib/language_operator/cli/commands/agent/logs.rb +125 -0
- data/lib/language_operator/cli/commands/agent/workspace.rb +327 -0
- data/lib/language_operator/cli/commands/cluster.rb +129 -84
- data/lib/language_operator/cli/commands/install.rb +1 -1
- data/lib/language_operator/cli/commands/model/base.rb +215 -0
- data/lib/language_operator/cli/commands/model/test.rb +165 -0
- data/lib/language_operator/cli/commands/persona.rb +16 -34
- data/lib/language_operator/cli/commands/quickstart.rb +3 -2
- data/lib/language_operator/cli/commands/status.rb +40 -67
- data/lib/language_operator/cli/commands/system/base.rb +44 -0
- data/lib/language_operator/cli/commands/system/exec.rb +147 -0
- data/lib/language_operator/cli/commands/system/helpers/llm_synthesis.rb +183 -0
- data/lib/language_operator/cli/commands/system/helpers/pod_manager.rb +212 -0
- data/lib/language_operator/cli/commands/system/helpers/template_loader.rb +57 -0
- data/lib/language_operator/cli/commands/system/helpers/template_validator.rb +174 -0
- data/lib/language_operator/cli/commands/system/schema.rb +92 -0
- data/lib/language_operator/cli/commands/system/synthesis_template.rb +151 -0
- data/lib/language_operator/cli/commands/system/synthesize.rb +224 -0
- data/lib/language_operator/cli/commands/system/validate_template.rb +130 -0
- data/lib/language_operator/cli/commands/tool/base.rb +271 -0
- data/lib/language_operator/cli/commands/tool/install.rb +255 -0
- data/lib/language_operator/cli/commands/tool/search.rb +69 -0
- data/lib/language_operator/cli/commands/tool/test.rb +115 -0
- data/lib/language_operator/cli/commands/use.rb +29 -6
- data/lib/language_operator/cli/errors/handler.rb +20 -17
- data/lib/language_operator/cli/errors/suggestions.rb +3 -5
- data/lib/language_operator/cli/errors/thor_errors.rb +55 -0
- data/lib/language_operator/cli/formatters/code_formatter.rb +4 -11
- data/lib/language_operator/cli/formatters/log_formatter.rb +8 -15
- data/lib/language_operator/cli/formatters/progress_formatter.rb +6 -8
- data/lib/language_operator/cli/formatters/status_formatter.rb +26 -7
- data/lib/language_operator/cli/formatters/table_formatter.rb +47 -36
- data/lib/language_operator/cli/formatters/value_formatter.rb +75 -0
- data/lib/language_operator/cli/helpers/cluster_context.rb +5 -3
- data/lib/language_operator/cli/helpers/kubeconfig_validator.rb +2 -1
- data/lib/language_operator/cli/helpers/label_utils.rb +97 -0
- data/lib/language_operator/{ux/concerns/provider_helpers.rb → cli/helpers/provider_helper.rb} +10 -29
- data/lib/language_operator/cli/helpers/schedule_builder.rb +21 -1
- data/lib/language_operator/cli/helpers/user_prompts.rb +19 -11
- data/lib/language_operator/cli/helpers/ux_helper.rb +538 -0
- data/lib/language_operator/{ux/concerns/input_validation.rb → cli/helpers/validation_helper.rb} +13 -66
- data/lib/language_operator/cli/main.rb +50 -40
- data/lib/language_operator/cli/templates/tools/generic.yaml +3 -0
- data/lib/language_operator/cli/wizards/agent_wizard.rb +12 -20
- data/lib/language_operator/cli/wizards/model_wizard.rb +271 -0
- data/lib/language_operator/cli/wizards/quickstart_wizard.rb +8 -34
- data/lib/language_operator/client/base.rb +28 -0
- data/lib/language_operator/client/config.rb +4 -1
- data/lib/language_operator/client/mcp_connector.rb +1 -1
- data/lib/language_operator/config/cluster_config.rb +3 -2
- data/lib/language_operator/config.rb +38 -11
- data/lib/language_operator/constants/kubernetes_labels.rb +80 -0
- data/lib/language_operator/constants.rb +13 -0
- data/lib/language_operator/dsl/http.rb +127 -10
- data/lib/language_operator/dsl.rb +153 -6
- data/lib/language_operator/errors.rb +50 -0
- data/lib/language_operator/kubernetes/client.rb +11 -6
- data/lib/language_operator/kubernetes/resource_builder.rb +58 -84
- data/lib/language_operator/templates/schema/agent_dsl_openapi.yaml +1 -1
- data/lib/language_operator/templates/schema/agent_dsl_schema.json +1 -1
- data/lib/language_operator/type_coercion.rb +118 -34
- data/lib/language_operator/utils/secure_path.rb +74 -0
- data/lib/language_operator/utils.rb +7 -0
- data/lib/language_operator/validators.rb +54 -2
- data/lib/language_operator/version.rb +1 -1
- data/synth/001/Makefile +10 -2
- data/synth/001/agent.rb +16 -15
- data/synth/001/output.log +27 -10
- data/synth/002/Makefile +10 -2
- data/synth/003/Makefile +1 -1
- data/synth/003/README.md +205 -133
- data/synth/003/agent.optimized.rb +66 -0
- data/synth/003/agent.synthesized.rb +41 -0
- metadata +111 -35
- data/docs/dsl/agent-reference.md +0 -604
- data/docs/dsl/mcp-integration.md +0 -1177
- data/docs/dsl/webhooks.md +0 -932
- data/docs/dsl/workflows.md +0 -744
- data/lib/language_operator/cli/commands/agent.rb +0 -1712
- data/lib/language_operator/cli/commands/model.rb +0 -366
- data/lib/language_operator/cli/commands/system.rb +0 -1259
- data/lib/language_operator/cli/commands/tool.rb +0 -654
- data/lib/language_operator/cli/formatters/optimization_formatter.rb +0 -226
- data/lib/language_operator/cli/helpers/pastel_helper.rb +0 -24
- data/lib/language_operator/learning/adapters/base_adapter.rb +0 -149
- data/lib/language_operator/learning/adapters/jaeger_adapter.rb +0 -221
- data/lib/language_operator/learning/adapters/signoz_adapter.rb +0 -435
- data/lib/language_operator/learning/adapters/tempo_adapter.rb +0 -239
- data/lib/language_operator/learning/optimizer.rb +0 -319
- data/lib/language_operator/learning/pattern_detector.rb +0 -260
- data/lib/language_operator/learning/task_synthesizer.rb +0 -288
- data/lib/language_operator/learning/trace_analyzer.rb +0 -285
- data/lib/language_operator/templates/task_synthesis.tmpl +0 -98
- data/lib/language_operator/ux/base.rb +0 -81
- data/lib/language_operator/ux/concerns/README.md +0 -155
- data/lib/language_operator/ux/concerns/headings.rb +0 -90
- data/lib/language_operator/ux/create_agent.rb +0 -255
- data/lib/language_operator/ux/create_model.rb +0 -267
- data/lib/language_operator/ux/quickstart.rb +0 -594
- data/synth/003/agent.rb +0 -41
- data/synth/003/output.log +0 -68
- /data/docs/{architecture/agent-runtime.md → agent-internals.md} +0 -0
- /data/docs/{dsl/chat-endpoints.md → chat-endpoints.md} +0 -0
- /data/docs/{dsl/SCHEMA_VERSION.md → schema-versioning.md} +0 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'open3'
|
|
4
|
+
require 'shellwords'
|
|
5
|
+
require_relative '../../helpers/label_utils'
|
|
6
|
+
require_relative '../../../constants/kubernetes_labels'
|
|
7
|
+
|
|
8
|
+
module LanguageOperator
|
|
9
|
+
module CLI
|
|
10
|
+
module Commands
|
|
11
|
+
module Agent
|
|
12
|
+
# Workspace management for agents
|
|
13
|
+
module Workspace
|
|
14
|
+
def self.included(base)
|
|
15
|
+
base.class_eval do
|
|
16
|
+
desc 'workspace NAME', 'Browse agent workspace files'
|
|
17
|
+
long_desc <<-DESC
|
|
18
|
+
Browse and manage the workspace files for an agent.
|
|
19
|
+
|
|
20
|
+
Workspaces provide persistent storage for agents to maintain state,
|
|
21
|
+
cache data, and remember information across executions.
|
|
22
|
+
|
|
23
|
+
Examples:
|
|
24
|
+
aictl agent workspace my-agent # List all files
|
|
25
|
+
aictl agent workspace my-agent --path /workspace/state.json # View specific file
|
|
26
|
+
aictl agent workspace my-agent --clean # Clear workspace
|
|
27
|
+
DESC
|
|
28
|
+
option :cluster, type: :string, desc: 'Override current cluster context'
|
|
29
|
+
option :path, type: :string, desc: 'View specific file contents'
|
|
30
|
+
option :clean, type: :boolean, desc: 'Clear workspace (with confirmation)'
|
|
31
|
+
def workspace(name)
|
|
32
|
+
handle_command_error('access workspace') do
|
|
33
|
+
ctx = CLI::Helpers::ClusterContext.from_options(options)
|
|
34
|
+
|
|
35
|
+
# Get agent to verify it exists
|
|
36
|
+
agent = get_resource_or_exit(LanguageOperator::Constants::RESOURCE_AGENT, name)
|
|
37
|
+
|
|
38
|
+
# Check if workspace is enabled
|
|
39
|
+
workspace_enabled = agent.dig('spec', 'workspace', 'enabled')
|
|
40
|
+
unless workspace_enabled
|
|
41
|
+
Formatters::ProgressFormatter.warn("Workspace is not enabled for agent '#{name}'")
|
|
42
|
+
puts
|
|
43
|
+
puts 'Enable workspace in agent configuration:'
|
|
44
|
+
puts ' spec:'
|
|
45
|
+
puts ' workspace:'
|
|
46
|
+
puts ' enabled: true'
|
|
47
|
+
puts ' size: 10Gi'
|
|
48
|
+
exit 1
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
if options[:path]
|
|
52
|
+
view_workspace_file(ctx, name, options[:path])
|
|
53
|
+
elsif options[:clean]
|
|
54
|
+
clean_workspace(ctx, name)
|
|
55
|
+
else
|
|
56
|
+
list_workspace_files(ctx, name)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def get_agent_pod(ctx, agent_name)
|
|
64
|
+
# Validate agent name for label compatibility
|
|
65
|
+
unless CLI::Helpers::LabelUtils.valid_label_value?(agent_name)
|
|
66
|
+
Formatters::ProgressFormatter.error("Agent name '#{agent_name}' is not valid for Kubernetes labels")
|
|
67
|
+
puts
|
|
68
|
+
puts 'Agent names must:'
|
|
69
|
+
puts ' - Be 63 characters or less'
|
|
70
|
+
puts ' - Contain only lowercase letters, numbers, hyphens, and dots'
|
|
71
|
+
puts ' - Start and end with alphanumeric characters'
|
|
72
|
+
exit 1
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Find pod for this agent using normalized label selector
|
|
76
|
+
label_selector = CLI::Helpers::LabelUtils.agent_pod_selector(agent_name)
|
|
77
|
+
pods = ctx.client.list_resources('Pod', namespace: ctx.namespace, label_selector: label_selector)
|
|
78
|
+
|
|
79
|
+
if pods.empty?
|
|
80
|
+
debug_info = CLI::Helpers::LabelUtils.debug_pod_search(ctx, agent_name)
|
|
81
|
+
|
|
82
|
+
Formatters::ProgressFormatter.error("No running pods found for agent '#{agent_name}'")
|
|
83
|
+
puts
|
|
84
|
+
puts 'Possible reasons:'
|
|
85
|
+
puts ' - Agent pod has not started yet'
|
|
86
|
+
puts ' - Agent is paused or stopped'
|
|
87
|
+
puts ' - Agent failed to deploy'
|
|
88
|
+
puts ' - Label mismatch (debugging info below)'
|
|
89
|
+
puts
|
|
90
|
+
puts 'Debug information:'
|
|
91
|
+
puts " Agent name: #{debug_info[:agent_name]}"
|
|
92
|
+
puts " Normalized: #{debug_info[:normalized_name]}"
|
|
93
|
+
puts " Label selector: #{debug_info[:label_selector]}"
|
|
94
|
+
puts " Namespace: #{debug_info[:namespace]}"
|
|
95
|
+
puts
|
|
96
|
+
puts 'Check agent status with:'
|
|
97
|
+
puts " aictl agent inspect #{agent_name}"
|
|
98
|
+
puts
|
|
99
|
+
puts 'List all pods in namespace:'
|
|
100
|
+
puts " kubectl get pods -n #{ctx.namespace} -l #{Constants::KubernetesLabels::COMPONENT}=#{Constants::KubernetesLabels::COMPONENT_AGENT}"
|
|
101
|
+
exit 1
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Find a running pod
|
|
105
|
+
running_pod = pods.find do |pod|
|
|
106
|
+
pod.dig('status', 'phase') == 'Running'
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
unless running_pod
|
|
110
|
+
Formatters::ProgressFormatter.error('Agent pod exists but is not running')
|
|
111
|
+
puts
|
|
112
|
+
puts "Current pod status: #{pods.first.dig('status', 'phase')}"
|
|
113
|
+
puts
|
|
114
|
+
puts 'Check pod logs with:'
|
|
115
|
+
puts " aictl agent logs #{agent_name}"
|
|
116
|
+
exit 1
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
running_pod.dig('metadata', 'name')
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def exec_in_pod(ctx, pod_name, command)
|
|
123
|
+
# Build command as array to prevent shell injection
|
|
124
|
+
kubectl_prefix_array = Shellwords.shellsplit(ctx.kubectl_prefix)
|
|
125
|
+
cmd_array = kubectl_prefix_array + ['exec', pod_name, '--']
|
|
126
|
+
|
|
127
|
+
# Add command arguments
|
|
128
|
+
cmd_array += if command.is_a?(Array)
|
|
129
|
+
command
|
|
130
|
+
else
|
|
131
|
+
[command]
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Execute with array to avoid shell interpolation
|
|
135
|
+
stdout, stderr, status = Open3.capture3(*cmd_array)
|
|
136
|
+
|
|
137
|
+
raise "Command failed: #{stderr}" unless status.success?
|
|
138
|
+
|
|
139
|
+
stdout
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def list_workspace_files(ctx, agent_name)
|
|
143
|
+
pod_name = get_agent_pod(ctx, agent_name)
|
|
144
|
+
|
|
145
|
+
# Check if workspace directory exists
|
|
146
|
+
begin
|
|
147
|
+
exec_in_pod(ctx, pod_name, 'test -d /workspace')
|
|
148
|
+
rescue StandardError
|
|
149
|
+
Formatters::ProgressFormatter.error('Workspace directory not found in agent pod')
|
|
150
|
+
puts
|
|
151
|
+
puts 'The /workspace directory does not exist in the agent pod.'
|
|
152
|
+
puts 'This agent may not have workspace support enabled.'
|
|
153
|
+
exit 1
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Get workspace usage
|
|
157
|
+
usage_output = exec_in_pod(
|
|
158
|
+
ctx,
|
|
159
|
+
pod_name,
|
|
160
|
+
'du -sh /workspace 2>/dev/null || echo "0\t/workspace"'
|
|
161
|
+
)
|
|
162
|
+
workspace_size = usage_output.split("\t").first.strip
|
|
163
|
+
|
|
164
|
+
# List files with details
|
|
165
|
+
file_list = exec_in_pod(
|
|
166
|
+
ctx,
|
|
167
|
+
pod_name,
|
|
168
|
+
'find /workspace -ls 2>/dev/null | tail -n +2'
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
puts
|
|
172
|
+
puts pastel.cyan("Workspace for agent '#{agent_name}' (#{workspace_size})")
|
|
173
|
+
puts '=' * 60
|
|
174
|
+
puts
|
|
175
|
+
|
|
176
|
+
if file_list.strip.empty?
|
|
177
|
+
puts pastel.dim('Workspace is empty')
|
|
178
|
+
puts
|
|
179
|
+
puts 'The agent will create files here as it runs.'
|
|
180
|
+
puts
|
|
181
|
+
return
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Parse and display file list
|
|
185
|
+
file_list.each_line do |line|
|
|
186
|
+
parts = line.strip.split(/\s+/, 11)
|
|
187
|
+
next if parts.length < 11
|
|
188
|
+
|
|
189
|
+
# Extract relevant parts
|
|
190
|
+
# Format: inode blocks perms links user group size month day time path
|
|
191
|
+
perms = parts[2]
|
|
192
|
+
size = parts[6]
|
|
193
|
+
month = parts[7]
|
|
194
|
+
day = parts[8]
|
|
195
|
+
time_or_year = parts[9]
|
|
196
|
+
path = parts[10]
|
|
197
|
+
|
|
198
|
+
# Skip the /workspace directory itself
|
|
199
|
+
next if path == '/workspace'
|
|
200
|
+
|
|
201
|
+
# Determine file type and icon
|
|
202
|
+
icon = if perms.start_with?('d')
|
|
203
|
+
pastel.blue('📁')
|
|
204
|
+
else
|
|
205
|
+
pastel.white('📄')
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Format path relative to workspace
|
|
209
|
+
relative_path = path.sub('/workspace/', '')
|
|
210
|
+
indent = ' ' * relative_path.count('/')
|
|
211
|
+
|
|
212
|
+
# Format size
|
|
213
|
+
formatted_size = format_file_size(size.to_i).rjust(8)
|
|
214
|
+
|
|
215
|
+
# Format time
|
|
216
|
+
formatted_time = "#{month} #{day.rjust(2)} #{time_or_year}"
|
|
217
|
+
|
|
218
|
+
puts "#{indent}#{icon} #{File.basename(relative_path).ljust(30)} #{pastel.dim(formatted_size)} #{pastel.dim(formatted_time)}"
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
puts
|
|
222
|
+
puts pastel.dim('Commands:')
|
|
223
|
+
puts pastel.dim(" aictl agent workspace #{agent_name} --path /workspace/<file> # View file")
|
|
224
|
+
puts pastel.dim(" aictl agent workspace #{agent_name} --clean # Clear workspace")
|
|
225
|
+
puts
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def view_workspace_file(ctx, agent_name, file_path)
|
|
229
|
+
pod_name = get_agent_pod(ctx, agent_name)
|
|
230
|
+
|
|
231
|
+
# Check if file exists
|
|
232
|
+
begin
|
|
233
|
+
exec_in_pod(ctx, pod_name, "test -f #{file_path}")
|
|
234
|
+
rescue StandardError
|
|
235
|
+
Formatters::ProgressFormatter.error("File not found: #{file_path}")
|
|
236
|
+
puts
|
|
237
|
+
puts 'List available files with:'
|
|
238
|
+
puts " aictl agent workspace #{agent_name}"
|
|
239
|
+
exit 1
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# Get file metadata
|
|
243
|
+
stat_output = exec_in_pod(
|
|
244
|
+
ctx,
|
|
245
|
+
pod_name,
|
|
246
|
+
"stat -c '%s %Y' #{file_path}"
|
|
247
|
+
)
|
|
248
|
+
size, mtime = stat_output.strip.split
|
|
249
|
+
|
|
250
|
+
# Get file contents
|
|
251
|
+
contents = exec_in_pod(
|
|
252
|
+
ctx,
|
|
253
|
+
pod_name,
|
|
254
|
+
"cat #{file_path}"
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
# Display file
|
|
258
|
+
puts
|
|
259
|
+
puts pastel.cyan("File: #{file_path}")
|
|
260
|
+
puts "Size: #{format_file_size(size.to_i)}"
|
|
261
|
+
puts "Modified: #{format_timestamp(Time.at(mtime.to_i))}"
|
|
262
|
+
puts '=' * 60
|
|
263
|
+
puts
|
|
264
|
+
puts contents
|
|
265
|
+
puts
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def clean_workspace(ctx, agent_name)
|
|
269
|
+
pod_name = get_agent_pod(ctx, agent_name)
|
|
270
|
+
|
|
271
|
+
# Get current workspace usage
|
|
272
|
+
usage_output = exec_in_pod(
|
|
273
|
+
ctx,
|
|
274
|
+
pod_name,
|
|
275
|
+
'du -sh /workspace 2>/dev/null || echo "0\t/workspace"'
|
|
276
|
+
)
|
|
277
|
+
workspace_size = usage_output.split("\t").first.strip
|
|
278
|
+
|
|
279
|
+
# Count files
|
|
280
|
+
file_count = exec_in_pod(
|
|
281
|
+
ctx,
|
|
282
|
+
pod_name,
|
|
283
|
+
'find /workspace -type f | wc -l'
|
|
284
|
+
).strip.to_i
|
|
285
|
+
|
|
286
|
+
puts
|
|
287
|
+
puts pastel.yellow("This will delete ALL files in the workspace for '#{agent_name}'")
|
|
288
|
+
puts
|
|
289
|
+
puts 'The agent will lose:'
|
|
290
|
+
puts ' • Execution history'
|
|
291
|
+
puts ' • Cached data'
|
|
292
|
+
puts ' • State information'
|
|
293
|
+
puts
|
|
294
|
+
puts "Current workspace: #{file_count} files, #{workspace_size}"
|
|
295
|
+
puts
|
|
296
|
+
|
|
297
|
+
# Use UserPrompts helper
|
|
298
|
+
return unless CLI::Helpers::UserPrompts.confirm('Are you sure?')
|
|
299
|
+
|
|
300
|
+
# Delete all files in workspace
|
|
301
|
+
Formatters::ProgressFormatter.with_spinner('Cleaning workspace') do
|
|
302
|
+
exec_in_pod(
|
|
303
|
+
ctx,
|
|
304
|
+
pod_name,
|
|
305
|
+
'find /workspace -mindepth 1 -delete'
|
|
306
|
+
)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
Formatters::ProgressFormatter.success("Workspace cleared (freed #{workspace_size})")
|
|
310
|
+
puts
|
|
311
|
+
puts 'The agent will start fresh on its next execution.'
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def format_file_size(bytes)
|
|
315
|
+
Formatters::ValueFormatter.file_size(bytes)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def format_timestamp(time)
|
|
319
|
+
Formatters::ValueFormatter.timestamp(time)
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
end
|