cline-rb 1.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +139 -0
- data/README.md +1216 -0
- data/TODO.md +2 -0
- data/lib/cline/cli.rb +373 -0
- data/lib/cline/config.rb +100 -0
- data/lib/cline/configuration.rb +23 -0
- data/lib/cline/data.rb +119 -0
- data/lib/cline/file_content.rb +33 -0
- data/lib/cline/global_settings.rb +17 -0
- data/lib/cline/global_state/api_providers.rb +48 -0
- data/lib/cline/global_state/auto_approval.rb +73 -0
- data/lib/cline/global_state/browser.rb +52 -0
- data/lib/cline/global_state/features.rb +56 -0
- data/lib/cline/global_state/general.rb +77 -0
- data/lib/cline/global_state/models.rb +127 -0
- data/lib/cline/global_state/toggles.rb +33 -0
- data/lib/cline/global_state/workspace.rb +41 -0
- data/lib/cline/global_state.rb +16 -0
- data/lib/cline/log.rb +288 -0
- data/lib/cline/logs.rb +136 -0
- data/lib/cline/mcp_settings.rb +30 -0
- data/lib/cline/model.rb +47 -0
- data/lib/cline/models.rb +11 -0
- data/lib/cline/overlay_hash.rb +125 -0
- data/lib/cline/providers.rb +59 -0
- data/lib/cline/schema.rb +144 -0
- data/lib/cline/secret_string.rb +83 -0
- data/lib/cline/secrets.rb +119 -0
- data/lib/cline/serializable/cline_data.rb +131 -0
- data/lib/cline/serializable/dir.rb +81 -0
- data/lib/cline/serializable/file.rb +106 -0
- data/lib/cline/session.rb +87 -0
- data/lib/cline/session_data.rb +154 -0
- data/lib/cline/session_message.rb +178 -0
- data/lib/cline/session_messages.rb +61 -0
- data/lib/cline/sessions.rb +30 -0
- data/lib/cline/skill.rb +148 -0
- data/lib/cline/skills.rb +8 -0
- data/lib/cline/task.rb +75 -0
- data/lib/cline/task_message.rb +247 -0
- data/lib/cline/task_messages.rb +11 -0
- data/lib/cline/tasks.rb +30 -0
- data/lib/cline/usage.rb +37 -0
- data/lib/cline/utils/enumerable_dir_objects.rb +103 -0
- data/lib/cline/utils/file.rb +71 -0
- data/lib/cline/utils/file_monitor.rb +56 -0
- data/lib/cline/utils/logger.rb +37 -0
- data/lib/cline/utils/os/linux.rb +43 -0
- data/lib/cline/utils/os/mingw32.rb +46 -0
- data/lib/cline/utils/os.rb +31 -0
- data/lib/cline/utils/schema.rb +290 -0
- data/lib/cline/version.rb +6 -0
- data/lib/cline/workspace.rb +25 -0
- data/lib/cline/workspace_settings.rb +29 -0
- data/lib/cline/workspaces.rb +8 -0
- data/lib/cline.rb +22 -0
- metadata +249 -0
data/lib/cline/log.rb
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
module Cline
|
|
2
|
+
# Cline Log entry
|
|
3
|
+
class Log < Schema
|
|
4
|
+
# @!group Public API
|
|
5
|
+
|
|
6
|
+
# Cause of an API call error
|
|
7
|
+
class ErrorCause < Schema
|
|
8
|
+
# @!group Public API
|
|
9
|
+
|
|
10
|
+
# @return [String, nil] Error code (e.g. "ConnectionRefused")
|
|
11
|
+
attribute :code, :string
|
|
12
|
+
|
|
13
|
+
# @return [String, nil] URL path that caused the error
|
|
14
|
+
attribute :path, :string
|
|
15
|
+
|
|
16
|
+
# @return [Integer, nil] Error number
|
|
17
|
+
attribute :errno, :integer
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Individual API call error (used in errors[], aggregateErrors[], and lastError)
|
|
21
|
+
class ApiError < Schema
|
|
22
|
+
# @!group Public API
|
|
23
|
+
|
|
24
|
+
# @return [String, nil] Error type identifier
|
|
25
|
+
attribute :type, :string
|
|
26
|
+
|
|
27
|
+
# @return [String, nil] Human-readable error message
|
|
28
|
+
attribute :message, :string
|
|
29
|
+
|
|
30
|
+
# @return [String, nil] Error stack trace
|
|
31
|
+
attribute :stack, :string
|
|
32
|
+
|
|
33
|
+
# @return [String, nil] Error class name (e.g. "AI_APICallError")
|
|
34
|
+
attribute :name, :string
|
|
35
|
+
|
|
36
|
+
# @return [String, nil] API endpoint URL
|
|
37
|
+
attribute :url, :string
|
|
38
|
+
|
|
39
|
+
# @return [Boolean, nil] Whether the request is retryable
|
|
40
|
+
attribute :is_retryable, :boolean
|
|
41
|
+
|
|
42
|
+
# @return [ErrorCause, nil] Underlying cause of the error
|
|
43
|
+
attribute :cause, ErrorCause
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Top-level error wrapper (the err field in error logs)
|
|
47
|
+
class Error < Schema
|
|
48
|
+
# @!group Public API
|
|
49
|
+
|
|
50
|
+
# @return [String, nil] Error type identifier
|
|
51
|
+
attribute :type, :string
|
|
52
|
+
|
|
53
|
+
# @return [String, nil] Human-readable error message
|
|
54
|
+
attribute :message, :string
|
|
55
|
+
|
|
56
|
+
# @return [String, nil] Error stack trace
|
|
57
|
+
attribute :stack, :string
|
|
58
|
+
|
|
59
|
+
# @return [String, nil] Error class name (e.g. "AI_RetryError")
|
|
60
|
+
attribute :name, :string
|
|
61
|
+
|
|
62
|
+
# @return [String, nil] Reason for the error (e.g. "maxRetriesExceeded")
|
|
63
|
+
attribute :reason, :string
|
|
64
|
+
|
|
65
|
+
# @return [Array<ApiError>, nil] Individual errors in a retry chain
|
|
66
|
+
attribute :errors, Utils::Schema.collection(ApiError)
|
|
67
|
+
|
|
68
|
+
# @return [Array<ApiError>, nil] Aggregate errors from retry attempts
|
|
69
|
+
attribute :aggregate_errors, Utils::Schema.collection(ApiError)
|
|
70
|
+
|
|
71
|
+
# @return [ApiError, nil] Last error in a retry chain
|
|
72
|
+
attribute :last_error, ApiError
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Event-specific properties for telemetry entries
|
|
76
|
+
class Properties < Schema
|
|
77
|
+
# @!group Public API
|
|
78
|
+
|
|
79
|
+
# @return [String, nil] Unique identifier for tasks and sessions
|
|
80
|
+
attribute :ulid, :string
|
|
81
|
+
|
|
82
|
+
# @return [String, nil] API provider name (e.g. "cline")
|
|
83
|
+
attribute :api_provider, :string
|
|
84
|
+
|
|
85
|
+
# @return [String, nil] Agent identifier
|
|
86
|
+
attribute :agent_id, :string
|
|
87
|
+
|
|
88
|
+
# @return [String, nil] Agent kind (e.g. "team_lead")
|
|
89
|
+
attribute :agent_kind, :string
|
|
90
|
+
|
|
91
|
+
# @return [String, nil] Conversation identifier
|
|
92
|
+
attribute :conversation_id, :string
|
|
93
|
+
|
|
94
|
+
# @return [Boolean, nil] Whether this is a subagent
|
|
95
|
+
attribute :is_subagent, :boolean
|
|
96
|
+
|
|
97
|
+
# @return [String, nil] Team identifier
|
|
98
|
+
attribute :team_id, :string
|
|
99
|
+
|
|
100
|
+
# @return [String, nil] Team name
|
|
101
|
+
attribute :team_name, :string
|
|
102
|
+
|
|
103
|
+
# @return [String, nil] Team role (e.g. "lead")
|
|
104
|
+
attribute :team_role, :string
|
|
105
|
+
|
|
106
|
+
# @return [String, nil] Lead agent identifier for teams
|
|
107
|
+
attribute :lead_agent_id, :string
|
|
108
|
+
|
|
109
|
+
# @return [String, nil] Model provider (e.g. "cline")
|
|
110
|
+
attribute :provider, :string
|
|
111
|
+
|
|
112
|
+
# @return [String, nil] Model identifier (e.g. "deepseek/deepseek-v4-flash")
|
|
113
|
+
attribute :model_id, :string
|
|
114
|
+
|
|
115
|
+
# @return [String, nil] Model name (e.g. "deepseek/deepseek-v4-flash")
|
|
116
|
+
attribute :model, :string
|
|
117
|
+
|
|
118
|
+
# @return [String, nil] Source of the conversation turn (e.g. "user", "assistant")
|
|
119
|
+
attribute :source, :string
|
|
120
|
+
|
|
121
|
+
# @return [String, nil] Mode of operation (e.g. "act")
|
|
122
|
+
attribute :mode, :string
|
|
123
|
+
|
|
124
|
+
# @return [String, nil] Timestamp in ISO 8601 format
|
|
125
|
+
attribute :timestamp, :string
|
|
126
|
+
|
|
127
|
+
# @return [String, nil] Run identifier for agent runs
|
|
128
|
+
attribute :run_id, :string
|
|
129
|
+
|
|
130
|
+
# @return [String, nil] Status of a run or task (e.g. "running", "completed")
|
|
131
|
+
attribute :status, :string
|
|
132
|
+
|
|
133
|
+
# @return [Integer, nil] Iteration number
|
|
134
|
+
attribute :iteration, :integer
|
|
135
|
+
|
|
136
|
+
# @return [String, nil] Event type (e.g. "run-started", "turn-started")
|
|
137
|
+
attribute :event_type, :string
|
|
138
|
+
|
|
139
|
+
# @return [String, nil] Session identifier
|
|
140
|
+
attribute :session_id, :string
|
|
141
|
+
|
|
142
|
+
# @return [Boolean, nil] Whether tools are enabled
|
|
143
|
+
attribute :enable_tools, :boolean
|
|
144
|
+
|
|
145
|
+
# @return [Boolean, nil] Whether spawn agent is enabled
|
|
146
|
+
attribute :enable_spawn_agent, :boolean
|
|
147
|
+
|
|
148
|
+
# @return [Boolean, nil] Whether agent teams are enabled
|
|
149
|
+
attribute :enable_agent_teams, :boolean
|
|
150
|
+
|
|
151
|
+
# @return [Integer, nil] Input tokens count
|
|
152
|
+
attribute :tokens_in, :integer
|
|
153
|
+
|
|
154
|
+
# @return [Integer, nil] Output tokens count
|
|
155
|
+
attribute :tokens_out, :integer
|
|
156
|
+
|
|
157
|
+
# @return [Float, nil] Total cost of the API call
|
|
158
|
+
attribute :total_cost, :float
|
|
159
|
+
|
|
160
|
+
# @return [Integer, nil] Cache read tokens count
|
|
161
|
+
attribute :cache_read_tokens, :integer
|
|
162
|
+
|
|
163
|
+
# @return [Integer, nil] Cache write tokens count
|
|
164
|
+
attribute :cache_write_tokens, :integer
|
|
165
|
+
|
|
166
|
+
# @return [String, nil] Tool name used (e.g. "ask_question", "run_commands")
|
|
167
|
+
attribute :tool, :string
|
|
168
|
+
|
|
169
|
+
# @return [Boolean, nil] Whether the tool use was successful
|
|
170
|
+
attribute :success, :boolean
|
|
171
|
+
|
|
172
|
+
# @return [Integer, nil] Duration in milliseconds
|
|
173
|
+
attribute :duration_ms, :integer
|
|
174
|
+
|
|
175
|
+
# @return [String, nil] Provider identifier
|
|
176
|
+
attribute :provider_id, :string
|
|
177
|
+
|
|
178
|
+
# Workspace initialization properties
|
|
179
|
+
|
|
180
|
+
# @return [Integer, nil] Number of workspace roots
|
|
181
|
+
attribute :root_count, :integer
|
|
182
|
+
|
|
183
|
+
# @return [Array<String>, nil] VCS types (e.g. ["git"])
|
|
184
|
+
attribute :vcs_types, Utils::Schema.collection(:string)
|
|
185
|
+
|
|
186
|
+
# @return [Boolean, nil] Whether the workspace has multiple roots
|
|
187
|
+
attribute :is_multi_root, :boolean
|
|
188
|
+
|
|
189
|
+
# @return [Boolean, nil] Whether the workspace has git
|
|
190
|
+
attribute :has_git, :boolean
|
|
191
|
+
|
|
192
|
+
# @return [Boolean, nil] Whether the workspace has mercurial
|
|
193
|
+
attribute :has_mercurial, :boolean
|
|
194
|
+
|
|
195
|
+
# @return [Float, nil] Initialization duration in milliseconds
|
|
196
|
+
attribute :init_duration_ms, :float
|
|
197
|
+
|
|
198
|
+
# @return [Boolean, nil] Whether feature flags are enabled
|
|
199
|
+
attribute :feature_flag_enabled, :boolean
|
|
200
|
+
|
|
201
|
+
# @return [String, nil] Extension version (e.g. "3.0.7")
|
|
202
|
+
attribute :extension_version, :string
|
|
203
|
+
|
|
204
|
+
# @return [String, nil] Cline type (e.g. "cli")
|
|
205
|
+
attribute :cline_type, :string
|
|
206
|
+
|
|
207
|
+
# @return [String, nil] Platform name (e.g. "cline")
|
|
208
|
+
attribute :platform, :string
|
|
209
|
+
|
|
210
|
+
# @return [String, nil] Platform version (e.g. "v24.3.0")
|
|
211
|
+
attribute :platform_version, :string
|
|
212
|
+
|
|
213
|
+
# @return [String, nil] Operating system type (e.g. "win32")
|
|
214
|
+
attribute :os_type, :string
|
|
215
|
+
|
|
216
|
+
# @return [String, nil] Operating system version (e.g. "Windows 11 Pro")
|
|
217
|
+
attribute :os_version, :string
|
|
218
|
+
|
|
219
|
+
# @return [String, nil] Distinct identifier
|
|
220
|
+
attribute :distinct_id, :string
|
|
221
|
+
|
|
222
|
+
# @return [String, nil] Whether the session was restored from persistence
|
|
223
|
+
attribute :restored_from_persistence, :boolean
|
|
224
|
+
|
|
225
|
+
# All attributes are already snake case
|
|
226
|
+
cline_snake_attributes(*attributes.keys)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# @!group Public API
|
|
230
|
+
|
|
231
|
+
# @return [Integer] Log level number (e.g. 30 for info, 40 for warn)
|
|
232
|
+
attribute :level, :integer
|
|
233
|
+
|
|
234
|
+
# @return [String] Timestamp in ISO 8601 format
|
|
235
|
+
attribute :time, :string
|
|
236
|
+
|
|
237
|
+
# @return [Integer] Process ID
|
|
238
|
+
attribute :pid, :integer
|
|
239
|
+
|
|
240
|
+
# @return [String] Hostname of the machine
|
|
241
|
+
attribute :hostname, :string
|
|
242
|
+
|
|
243
|
+
# @return [String] Logger name (e.g. "cline.cli")
|
|
244
|
+
attribute :name, :string
|
|
245
|
+
|
|
246
|
+
# @return [String] Component name (e.g. "main")
|
|
247
|
+
attribute :component, :string
|
|
248
|
+
|
|
249
|
+
# @return [String] Log message
|
|
250
|
+
attribute :msg, :string
|
|
251
|
+
|
|
252
|
+
# @return [Boolean, nil] Whether the session is interactive
|
|
253
|
+
attribute :interactive, :boolean
|
|
254
|
+
|
|
255
|
+
# @return [Boolean, nil] Whether a prompt is present
|
|
256
|
+
attribute :has_prompt, :boolean
|
|
257
|
+
|
|
258
|
+
# @return [String, nil] Current working directory
|
|
259
|
+
attribute :cwd, :string
|
|
260
|
+
|
|
261
|
+
# @return [String, nil] Reason for a fallback or decision
|
|
262
|
+
attribute :reason, :string
|
|
263
|
+
|
|
264
|
+
# @return [String, nil] Backend routing mode (e.g. "env-managed", "auto")
|
|
265
|
+
attribute :backend_mode, :string
|
|
266
|
+
|
|
267
|
+
# @return [Boolean, nil] Whether the local backend is forced
|
|
268
|
+
attribute :force_local_backend, :boolean
|
|
269
|
+
|
|
270
|
+
# @return [String, nil] Telemetry sink name (e.g. "TelemetryLoggerSink")
|
|
271
|
+
attribute :telemetry_sink, :string
|
|
272
|
+
|
|
273
|
+
# @return [String, nil] Event name for telemetry entries (e.g. "workspace.initialized")
|
|
274
|
+
attribute :event, :string
|
|
275
|
+
|
|
276
|
+
# @return [Properties, nil] Event-specific properties for telemetry entries
|
|
277
|
+
attribute :properties, Properties
|
|
278
|
+
|
|
279
|
+
# @return [String, nil] Severity level for error/warn logs (e.g. "error", "warn")
|
|
280
|
+
attribute :severity, :string
|
|
281
|
+
|
|
282
|
+
# @return [String, nil] Provider identifier (e.g. "cline")
|
|
283
|
+
attribute :provider_id, :string
|
|
284
|
+
|
|
285
|
+
# @return [Error, nil] Error details for error logs
|
|
286
|
+
attribute :err, Error
|
|
287
|
+
end
|
|
288
|
+
end
|
data/lib/cline/logs.rb
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
module Cline
|
|
5
|
+
# Cline Logs file content
|
|
6
|
+
class Logs
|
|
7
|
+
extend Forwardable
|
|
8
|
+
include Serializable::File
|
|
9
|
+
|
|
10
|
+
# @!group Public API
|
|
11
|
+
|
|
12
|
+
# Fetch logs
|
|
13
|
+
#
|
|
14
|
+
# @param from [Time, String, nil] The horizon (exclusive) from which we select lines. Can be one of:
|
|
15
|
+
# - [Time] The timestamp to get lines from
|
|
16
|
+
# - [String] The exact log line to start after
|
|
17
|
+
# - [nil] Get all log lines
|
|
18
|
+
# @return [Array<Log>] Logs list
|
|
19
|
+
def logs(from: nil)
|
|
20
|
+
logs_lines_from(from).map { |line| line.start_with?('{') ? Log.of_hash(JSON.parse(line)) : line }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Delegates enumerating methods to the internal logs
|
|
24
|
+
def_delegators :logs, *%i[[] each empty? first last size]
|
|
25
|
+
|
|
26
|
+
# Add a new log line to the logs
|
|
27
|
+
#
|
|
28
|
+
# @param line [Log, String] The log entry to add (either a Log object or a raw string)
|
|
29
|
+
# @return [Logs] self
|
|
30
|
+
def <<(line)
|
|
31
|
+
logs_lines << (
|
|
32
|
+
if line.is_a?(Log)
|
|
33
|
+
line.to_cline_json
|
|
34
|
+
elsif line.is_a?(Hash)
|
|
35
|
+
Log.cast(line).to_cline_json
|
|
36
|
+
else
|
|
37
|
+
line
|
|
38
|
+
end
|
|
39
|
+
)
|
|
40
|
+
self
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Save the logs lines to the file
|
|
44
|
+
def save
|
|
45
|
+
raise 'This instance has not been initialized from a file' unless file
|
|
46
|
+
|
|
47
|
+
FileUtils.mkdir_p(::File.dirname(file))
|
|
48
|
+
::File.write(file, logs_lines.map { |line| "#{line}\n" }.join)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Monitor logs with a callback called when new or updated logs arrive
|
|
52
|
+
#
|
|
53
|
+
# @param on_log [#call] Block called each time there is a new log.
|
|
54
|
+
# * Param log [Log, String] Log that has happened, either as a Log object or as a String if it is not JSON.
|
|
55
|
+
# * Param last [Boolean] Is this the last log fetched from the logs?
|
|
56
|
+
# @param from [Time, String, nil] The horizon (exclusive) from which we select lines (see #logs)
|
|
57
|
+
# @param monitoring_interval_secs [Float] The monitoring interval in seconds
|
|
58
|
+
# @yield Optional code called while monitoring is in place.
|
|
59
|
+
# If used then monitoring is stopped at the end of the block's execution.
|
|
60
|
+
# @return [FileMonitor, nil] If no block has been given, return the monitor that needs to be
|
|
61
|
+
# stopped by the caller when monitoring should end.
|
|
62
|
+
def monitor(on_log:, from: nil, monitoring_interval_secs: 1, &)
|
|
63
|
+
# Keep the last log line that we have read
|
|
64
|
+
last_log = from
|
|
65
|
+
Logs.monitor_file_changes(
|
|
66
|
+
file,
|
|
67
|
+
on_change: proc do |_mtime|
|
|
68
|
+
refresh!
|
|
69
|
+
new_lines = logs_lines_from(last_log)
|
|
70
|
+
unless new_lines.empty?
|
|
71
|
+
last_idx = new_lines.size - 1
|
|
72
|
+
new_lines.each.with_index do |line, idx|
|
|
73
|
+
on_log.call(line.start_with?('{') ? Log.of_hash(JSON.parse(line)) : line, idx == last_idx)
|
|
74
|
+
end
|
|
75
|
+
last_log = new_lines.last
|
|
76
|
+
end
|
|
77
|
+
end,
|
|
78
|
+
monitoring_interval_secs:,
|
|
79
|
+
&
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Clear the cache in case the log file has changed
|
|
84
|
+
def refresh!
|
|
85
|
+
@logs_lines = nil
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Equality check
|
|
89
|
+
#
|
|
90
|
+
# @param other [Object] The other to check equality with
|
|
91
|
+
# @return [Boolean] True if objects are equal
|
|
92
|
+
def ==(other)
|
|
93
|
+
other.is_a?(Logs) &&
|
|
94
|
+
other.logs_lines == logs_lines
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
protected
|
|
98
|
+
|
|
99
|
+
# Get the logs lines
|
|
100
|
+
#
|
|
101
|
+
# @return [Array<String>] Logs lines
|
|
102
|
+
def logs_lines
|
|
103
|
+
@logs_lines ||= Utils::File.safe_read(file).split("\n")
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
# @!group Internal
|
|
109
|
+
|
|
110
|
+
# The regexp used to match string timestamps from log lines
|
|
111
|
+
LOG_ENTRY_TIME_REGEXP = /"time":"(\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d\.\d\d\dZ)"/
|
|
112
|
+
private_constant :LOG_ENTRY_TIME_REGEXP
|
|
113
|
+
|
|
114
|
+
# Get the logs lines from a given time or line
|
|
115
|
+
#
|
|
116
|
+
# @param from [Time, String, nil] The horizon (exclusive) from which we select lines (see #logs)
|
|
117
|
+
# @return [Array<String>] Selected logs lines
|
|
118
|
+
def logs_lines_from(from = nil)
|
|
119
|
+
if from
|
|
120
|
+
found_reverse_idx =
|
|
121
|
+
if from.is_a?(String)
|
|
122
|
+
logs_lines.reverse_each.find_index(from)
|
|
123
|
+
else
|
|
124
|
+
horizon = from.utc.strftime('%FT%T.%LZ')
|
|
125
|
+
logs_lines.reverse_each.find_index do |line|
|
|
126
|
+
match = line.match(LOG_ENTRY_TIME_REGEXP)
|
|
127
|
+
!match.nil? && match[1] <= horizon
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
found_reverse_idx ? logs_lines[(logs_lines.size - found_reverse_idx)..] : logs_lines
|
|
131
|
+
else
|
|
132
|
+
logs_lines
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Cline
|
|
2
|
+
# MCP settings
|
|
3
|
+
class McpSettings < Schema
|
|
4
|
+
# @!group Public API
|
|
5
|
+
Serializable::ClineData.include_for(self, 'settings/cline_mcp_settings.json')
|
|
6
|
+
|
|
7
|
+
# Settings associated to 1 MCP server
|
|
8
|
+
class McpServer < Schema
|
|
9
|
+
# @!group Public API
|
|
10
|
+
|
|
11
|
+
# @return [Array<String>] List of tools that are automatically approved for this server
|
|
12
|
+
attribute :auto_approve, Utils::Schema.collection(:string)
|
|
13
|
+
|
|
14
|
+
# @return [Boolean] Flag indicating if this server is disabled
|
|
15
|
+
attribute :disabled, :boolean
|
|
16
|
+
|
|
17
|
+
# @return [Integer] Server timeout in seconds
|
|
18
|
+
attribute :timeout, :integer
|
|
19
|
+
|
|
20
|
+
# @return [String] Server connection type (e.g. "sse", "stdio")
|
|
21
|
+
attribute :type, :string
|
|
22
|
+
|
|
23
|
+
# @return [String] Server URL for SSE connections
|
|
24
|
+
attribute :url, :string
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @return [Hash] Set of MCP servers settings
|
|
28
|
+
attribute :mcp_servers, Utils::Schema.map(McpServer)
|
|
29
|
+
end
|
|
30
|
+
end
|
data/lib/cline/model.rb
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Cline
|
|
2
|
+
# Cline model information
|
|
3
|
+
class Model < Schema
|
|
4
|
+
# @!group Public API
|
|
5
|
+
|
|
6
|
+
# @return [String] Model display name
|
|
7
|
+
attribute :name, :string
|
|
8
|
+
|
|
9
|
+
# @return [Integer] Maximum tokens output for this model
|
|
10
|
+
attribute :max_tokens, :integer
|
|
11
|
+
|
|
12
|
+
# @return [Integer] Context window size in tokens
|
|
13
|
+
attribute :context_window, :integer
|
|
14
|
+
|
|
15
|
+
# @return [Boolean] True if this model supports image inputs
|
|
16
|
+
attribute :supports_images, :boolean
|
|
17
|
+
|
|
18
|
+
# @return [Boolean] True if this model supports prompt caching
|
|
19
|
+
attribute :supports_prompt_cache, :boolean
|
|
20
|
+
|
|
21
|
+
# @return [Float] Input price per million tokens
|
|
22
|
+
attribute :input_price, :float
|
|
23
|
+
|
|
24
|
+
# @return [Float] Output price per million tokens
|
|
25
|
+
attribute :output_price, :float
|
|
26
|
+
|
|
27
|
+
# @return [Float, nil] Cache reads price per million tokens
|
|
28
|
+
attribute :cache_reads_price, :float
|
|
29
|
+
|
|
30
|
+
# @return [Float, nil] Cache writes price per million tokens
|
|
31
|
+
attribute :cache_writes_price, :float
|
|
32
|
+
|
|
33
|
+
# @return [String, nil] Model description
|
|
34
|
+
attribute :description, :string
|
|
35
|
+
|
|
36
|
+
# Thinking configuration for this model
|
|
37
|
+
class ThinkingConfig < Schema
|
|
38
|
+
# @!group Public API
|
|
39
|
+
|
|
40
|
+
# @return [Integer] Maximum thinking budget in tokens
|
|
41
|
+
attribute :max_budget, :integer
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @return [ThinkingConfig, nil] Thinking configuration
|
|
45
|
+
attribute :thinking_config, ThinkingConfig
|
|
46
|
+
end
|
|
47
|
+
end
|
data/lib/cline/models.rb
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
|
|
3
|
+
module Cline
|
|
4
|
+
# Class merging several Hash-like objects to give a uniform view of them through another Hash-like interface.
|
|
5
|
+
# This is used to provide unifide representations of objects present in both project and global configs.
|
|
6
|
+
# Write operations are performed on the top layer only.
|
|
7
|
+
class OverlayHash
|
|
8
|
+
extend Forwardable
|
|
9
|
+
|
|
10
|
+
# @!group Public API
|
|
11
|
+
|
|
12
|
+
include Enumerable
|
|
13
|
+
|
|
14
|
+
# Loop over all elements.
|
|
15
|
+
#
|
|
16
|
+
# @yield Optional code called for each key and value.
|
|
17
|
+
# @yieldparam key [Object] The key being iterated on.
|
|
18
|
+
# @yieldparam value [Object] The value being iterated on.
|
|
19
|
+
# @return [Enumerator] The enumerator if no block is given.
|
|
20
|
+
def each
|
|
21
|
+
return enum_for(:each) unless block_given?
|
|
22
|
+
|
|
23
|
+
seen = {}
|
|
24
|
+
@layers.each do |layer|
|
|
25
|
+
layer.each do |key, value|
|
|
26
|
+
next if seen.key?(key)
|
|
27
|
+
|
|
28
|
+
seen[key] = true
|
|
29
|
+
yield key, value
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Retrieve the value for a given key from the first layer that contains it.
|
|
35
|
+
#
|
|
36
|
+
# @param key [Object] The key to look up.
|
|
37
|
+
# @return [Object, nil] The value associated with the key, or +nil+ if not found in any layer.
|
|
38
|
+
def [](key)
|
|
39
|
+
@layers.each do |layer|
|
|
40
|
+
return layer[key] if layer.key?(key)
|
|
41
|
+
end
|
|
42
|
+
nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Check whether the given key exists in any layer.
|
|
46
|
+
#
|
|
47
|
+
# @param key [Object] The key to check for.
|
|
48
|
+
# @return [Boolean] +true+ if the key is present in at least one layer, +false+ otherwise.
|
|
49
|
+
def key?(key)
|
|
50
|
+
@layers.any? { |layer| layer.key?(key) }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Return all unique keys across all layers, in priority order.
|
|
54
|
+
#
|
|
55
|
+
# @return [Array<Object>] The list of unique keys.
|
|
56
|
+
def keys
|
|
57
|
+
map { |k, _v| k }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Return all values across all layers, in priority order.
|
|
61
|
+
#
|
|
62
|
+
# @return [Array<Object>] The list of values corresponding to the unique keys.
|
|
63
|
+
def values
|
|
64
|
+
map { |_k, v| v }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Return the number of unique keys across all layers.
|
|
68
|
+
#
|
|
69
|
+
# @return [Integer] The total count of unique keys.
|
|
70
|
+
def size
|
|
71
|
+
keys.size
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Check whether the overlay hash contains any entries.
|
|
75
|
+
#
|
|
76
|
+
# @return [Boolean] +true+ if there are no entries across all layers, +false+ otherwise.
|
|
77
|
+
def empty?
|
|
78
|
+
none?
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Convert the overlay hash into a plain Ruby Hash.
|
|
82
|
+
#
|
|
83
|
+
# @return [Hash] A new hash containing all unique key-value pairs in priority order.
|
|
84
|
+
def to_h
|
|
85
|
+
each_with_object({}) do |(key, value), h|
|
|
86
|
+
h[key] = value
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Equality check
|
|
91
|
+
#
|
|
92
|
+
# @param other [Object] The other to check equality with
|
|
93
|
+
# @return [Boolean] True if objects are equal
|
|
94
|
+
def ==(other)
|
|
95
|
+
other.is_a?(OverlayHash) &&
|
|
96
|
+
other.layers == layers
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Delegate all write and singleton operations to the first layer
|
|
100
|
+
def_delegators :first_layer, *%i[dir new]
|
|
101
|
+
|
|
102
|
+
# @!group Internal
|
|
103
|
+
|
|
104
|
+
# Constructor
|
|
105
|
+
#
|
|
106
|
+
# @param layers [Array] List of Hash-like objects that should be served.
|
|
107
|
+
# In case of conflicting keys, the first ones in the list get priority.
|
|
108
|
+
# Write operations are performed on the first one only.
|
|
109
|
+
def initialize(*layers)
|
|
110
|
+
@layers = layers
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
protected
|
|
114
|
+
|
|
115
|
+
# @return [Array<Object>] The list of layers
|
|
116
|
+
attr_reader :layers
|
|
117
|
+
|
|
118
|
+
private
|
|
119
|
+
|
|
120
|
+
# @return [Object] First layer
|
|
121
|
+
def first_layer
|
|
122
|
+
@layers.first
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Cline
|
|
2
|
+
# Providers configuration stored in settings/providers.json
|
|
3
|
+
class Providers < Schema
|
|
4
|
+
# @!group Public API
|
|
5
|
+
|
|
6
|
+
Serializable::ClineData.include_for(self, 'settings/providers.json')
|
|
7
|
+
|
|
8
|
+
# A provider entry with settings, update timestamp and token source
|
|
9
|
+
class ProviderEntry < Schema
|
|
10
|
+
# @!group Public API
|
|
11
|
+
|
|
12
|
+
# Settings for a single provider entry
|
|
13
|
+
class ProviderSettings < Schema
|
|
14
|
+
# @!group Public API
|
|
15
|
+
|
|
16
|
+
# Settings specific to a provider's reasoning configuration
|
|
17
|
+
class ReasoningSettings < Schema
|
|
18
|
+
# @!group Public API
|
|
19
|
+
|
|
20
|
+
# @return [Boolean] Whether reasoning is enabled
|
|
21
|
+
attribute :enabled, :boolean
|
|
22
|
+
|
|
23
|
+
# @return [String] The reasoning effort level (e.g. "xhigh")
|
|
24
|
+
attribute :effort, :string
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @return [String] The provider name
|
|
28
|
+
attribute :provider, :string
|
|
29
|
+
|
|
30
|
+
# @return [SecretString, nil] The API key for this provider
|
|
31
|
+
attribute :api_key, SecretString
|
|
32
|
+
|
|
33
|
+
# @return [String] The model identifier
|
|
34
|
+
attribute :model, :string
|
|
35
|
+
|
|
36
|
+
# @return [ReasoningSettings, nil] Optional reasoning configuration
|
|
37
|
+
attribute :reasoning, ReasoningSettings
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @return [ProviderSettings] The provider settings
|
|
41
|
+
attribute :settings, ProviderSettings
|
|
42
|
+
|
|
43
|
+
# @return [String] The timestamp when this provider was last updated
|
|
44
|
+
attribute :updated_at, :string
|
|
45
|
+
|
|
46
|
+
# @return [String] The token source (e.g. "manual")
|
|
47
|
+
attribute :token_source, :string
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @return [Integer] The version of the providers configuration
|
|
51
|
+
attribute :version, :integer
|
|
52
|
+
|
|
53
|
+
# @return [String] The last used provider identifier
|
|
54
|
+
attribute :last_used_provider, :string
|
|
55
|
+
|
|
56
|
+
# @return [Hash] The map of provider entries keyed by provider name
|
|
57
|
+
attribute :providers, Utils::Schema.map(ProviderEntry)
|
|
58
|
+
end
|
|
59
|
+
end
|