aia 0.9.23 → 0.10.2

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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.version +1 -1
  3. data/CHANGELOG.md +95 -3
  4. data/README.md +187 -60
  5. data/bin/aia +6 -0
  6. data/docs/cli-reference.md +145 -72
  7. data/docs/configuration.md +156 -19
  8. data/docs/directives-reference.md +28 -8
  9. data/docs/examples/tools/index.md +2 -2
  10. data/docs/faq.md +11 -11
  11. data/docs/guides/available-models.md +11 -11
  12. data/docs/guides/basic-usage.md +18 -17
  13. data/docs/guides/chat.md +57 -11
  14. data/docs/guides/executable-prompts.md +15 -15
  15. data/docs/guides/first-prompt.md +2 -2
  16. data/docs/guides/getting-started.md +6 -6
  17. data/docs/guides/image-generation.md +24 -24
  18. data/docs/guides/local-models.md +2 -2
  19. data/docs/guides/models.md +96 -18
  20. data/docs/guides/tools.md +4 -4
  21. data/docs/index.md +2 -2
  22. data/docs/installation.md +2 -2
  23. data/docs/prompt_management.md +11 -11
  24. data/docs/security.md +3 -3
  25. data/docs/workflows-and-pipelines.md +1 -1
  26. data/examples/README.md +6 -6
  27. data/examples/headlines +3 -3
  28. data/lib/aia/aia_completion.bash +2 -2
  29. data/lib/aia/aia_completion.fish +4 -4
  30. data/lib/aia/aia_completion.zsh +2 -2
  31. data/lib/aia/chat_processor_service.rb +31 -21
  32. data/lib/aia/config/cli_parser.rb +403 -403
  33. data/lib/aia/config/config_section.rb +87 -0
  34. data/lib/aia/config/defaults.yml +219 -0
  35. data/lib/aia/config/defaults_loader.rb +147 -0
  36. data/lib/aia/config/mcp_parser.rb +151 -0
  37. data/lib/aia/config/model_spec.rb +67 -0
  38. data/lib/aia/config/validator.rb +185 -136
  39. data/lib/aia/config.rb +336 -17
  40. data/lib/aia/directive_processor.rb +14 -6
  41. data/lib/aia/directives/checkpoint.rb +283 -0
  42. data/lib/aia/directives/configuration.rb +27 -98
  43. data/lib/aia/directives/models.rb +15 -9
  44. data/lib/aia/directives/registry.rb +2 -0
  45. data/lib/aia/directives/utility.rb +25 -9
  46. data/lib/aia/directives/web_and_file.rb +50 -47
  47. data/lib/aia/logger.rb +328 -0
  48. data/lib/aia/prompt_handler.rb +18 -22
  49. data/lib/aia/ruby_llm_adapter.rb +584 -65
  50. data/lib/aia/session.rb +49 -156
  51. data/lib/aia/topic_context.rb +125 -0
  52. data/lib/aia/ui_presenter.rb +20 -16
  53. data/lib/aia/utility.rb +50 -18
  54. data/lib/aia.rb +91 -66
  55. data/lib/extensions/ruby_llm/modalities.rb +2 -0
  56. data/mcp_servers/apple-mcp.json +8 -0
  57. data/mcp_servers/mcp_server_chart.json +11 -0
  58. data/mcp_servers/playwright_one.json +8 -0
  59. data/mcp_servers/playwright_two.json +8 -0
  60. data/mcp_servers/tavily_mcp_server.json +8 -0
  61. metadata +85 -26
  62. data/lib/aia/config/base.rb +0 -288
  63. data/lib/aia/config/defaults.rb +0 -91
  64. data/lib/aia/config/file_loader.rb +0 -163
  65. data/lib/aia/context_manager.rb +0 -134
  66. data/mcp_servers/imcp.json +0 -7
  67. data/mcp_servers/launcher.json +0 -11
  68. data/mcp_servers/timeserver.json +0 -8
@@ -1,288 +0,0 @@
1
- # lib/aia/config/base.rb
2
-
3
- require 'ostruct'
4
- require 'date'
5
- require_relative 'defaults'
6
- require_relative 'cli_parser'
7
- require_relative 'file_loader'
8
- require_relative 'validator'
9
-
10
- module AIA
11
- module ConfigModules
12
- module Base
13
- class << self
14
- # Delegate to other config modules
15
- def cli_options
16
- CLIParser.cli_options
17
- end
18
-
19
- def cf_options(file)
20
- FileLoader.cf_options(file)
21
- end
22
-
23
- def dump_config(config, file)
24
- FileLoader.dump_config(config, file)
25
- end
26
-
27
- def generate_completion_script(shell)
28
- FileLoader.generate_completion_script(shell)
29
- end
30
-
31
- def tailor_the_config(config)
32
- Validator.tailor_the_config(config)
33
- end
34
-
35
- def validate_pipeline_prompts(config)
36
- Validator.validate_pipeline_prompts(config)
37
- end
38
-
39
- def normalize_boolean_flag(config, flag)
40
- Validator.normalize_boolean_flag(config, flag)
41
- end
42
-
43
- def process_tools_option(path_list, config)
44
- CLIParser.process_tools_option(path_list, config)
45
- end
46
-
47
- def validate_and_set_context_files(config, remaining_args)
48
- Validator.validate_and_set_context_files(config, remaining_args)
49
- end
50
-
51
- def setup_mode_options(opts, config)
52
- CLIParser.setup_mode_options(opts, config)
53
- end
54
-
55
- def parse_config_content(content, ext)
56
- FileLoader.parse_config_content(content, ext)
57
- end
58
-
59
- def normalize_last_refresh_date(config)
60
- FileLoader.normalize_last_refresh_date(config)
61
- end
62
-
63
- def process_prompt_id_from_args(config, remaining_args)
64
- Validator.process_prompt_id_from_args(config, remaining_args)
65
- end
66
-
67
- def process_role_configuration(config)
68
- Validator.process_role_configuration(config)
69
- end
70
-
71
- def prepare_pipeline(config)
72
- Validator.prepare_pipeline(config)
73
- end
74
-
75
- def setup_model_options(opts, config)
76
- CLIParser.setup_model_options(opts, config)
77
- end
78
-
79
- def setup_ai_parameters(opts, config)
80
- CLIParser.setup_ai_parameters(opts, config)
81
- end
82
-
83
- def read_and_process_config_file(file)
84
- FileLoader.read_and_process_config_file(file)
85
- end
86
-
87
- def process_stdin_content
88
- Validator.process_stdin_content
89
- end
90
-
91
- def process_allowed_tools_option(tools_list, config)
92
- CLIParser.process_allowed_tools_option(tools_list, config)
93
- end
94
-
95
- def process_rejected_tools_option(tools_list, config)
96
- CLIParser.process_rejected_tools_option(tools_list, config)
97
- end
98
-
99
- def normalize_boolean_flags(config)
100
- Validator.normalize_boolean_flags(config)
101
- end
102
-
103
- def handle_executable_prompt(config)
104
- Validator.handle_executable_prompt(config)
105
- end
106
-
107
- def handle_fuzzy_search_prompt_id(config)
108
- Validator.handle_fuzzy_search_prompt_id(config)
109
- end
110
-
111
- def create_option_parser(config)
112
- CLIParser.create_option_parser(config)
113
- end
114
-
115
- def apply_file_config_to_struct(config, file_config)
116
- FileLoader.apply_file_config_to_struct(config, file_config)
117
- end
118
-
119
- def configure_prompt_manager(config)
120
- Validator.configure_prompt_manager(config)
121
- end
122
-
123
- def setup
124
- default_config = Defaults::DEFAULT_CONFIG.dup
125
- cli_config = cli_options
126
- envar_config = envar_options(default_config, cli_config)
127
-
128
- file = envar_config.config_file unless envar_config.config_file.nil?
129
- file = cli_config.config_file unless cli_config.config_file.nil?
130
-
131
- cf_config = cf_options(file)
132
-
133
- config = OpenStruct.merge(
134
- default_config,
135
- cf_config || {},
136
- envar_config || {},
137
- cli_config || {}
138
- )
139
-
140
- config = tailor_the_config(config)
141
- load_libraries(config)
142
- load_tools(config)
143
- load_mcp_servers(config)
144
-
145
- if config.dump_file
146
- dump_config(config, config.dump_file)
147
- end
148
-
149
- config
150
- end
151
-
152
- def load_libraries(config)
153
- return if config.require_libs.empty?
154
-
155
- exit_on_error = false
156
-
157
- config.require_libs.each do |library|
158
- begin
159
- require(library)
160
- rescue => e
161
- STDERR.puts "Error loading library '#{library}' #{e.message}"
162
- exit_on_error = true
163
- end
164
- end
165
-
166
- exit(1) if exit_on_error
167
-
168
- config
169
- end
170
-
171
- def load_tools(config)
172
- return if config.tool_paths.empty?
173
-
174
- require_all_tools(config)
175
-
176
- config
177
- end
178
-
179
- def require_all_tools(config)
180
- exit_on_error = false
181
-
182
- config.tool_paths.each do |tool_path|
183
- begin
184
- # expands path based on PWD
185
- absolute_tool_path = File.expand_path(tool_path)
186
- require(absolute_tool_path)
187
- rescue => e
188
- STDERR.puts "Error loading tool '#{tool_path}' #{e.message}"
189
- exit_on_error = true
190
- end
191
- end
192
-
193
- exit(1) if exit_on_error
194
- end
195
-
196
- def load_mcp_servers(config)
197
- servers = config.mcp_servers
198
-
199
- return config if servers.nil? || (servers.respond_to?(:empty?) && servers.empty?)
200
-
201
- servers.each do |server|
202
- name = server[:name] || server["name"]
203
- command = server[:command] || server["command"]
204
- args = server[:args] || server["args"] || []
205
- env = server[:env] || server["env"] || {}
206
- timeout = server[:timeout] || server["timeout"] || 8000 # default 8 seconds in ms
207
-
208
- unless name && command
209
- STDERR.puts "WARNING: MCP server entry missing name or command: #{server.inspect}"
210
- next
211
- end
212
-
213
- # Resolve command path if not absolute
214
- resolved_command = resolve_command_path(command)
215
- unless resolved_command
216
- STDERR.puts "WARNING: MCP server '#{name}' command not found: #{command}"
217
- next
218
- end
219
-
220
- begin
221
- RubyLLM::MCP.add_client(
222
- name: name,
223
- transport_type: :stdio,
224
- request_timeout: timeout,
225
- config: {
226
- command: resolved_command,
227
- args: args,
228
- env: env
229
- }
230
- )
231
- rescue => e
232
- STDERR.puts "ERROR: Failed to load MCP server '#{name}': #{e.message}"
233
- end
234
- end
235
-
236
- config
237
- end
238
-
239
- def resolve_command_path(command)
240
- # If already absolute path, verify it exists
241
- if command.start_with?('/')
242
- return File.executable?(command) ? command : nil
243
- end
244
-
245
- # Search in PATH
246
- ENV['PATH'].split(File::PATH_SEPARATOR).each do |dir|
247
- full_path = File.join(dir, command)
248
- return full_path if File.executable?(full_path)
249
- end
250
-
251
- nil
252
- end
253
-
254
- # envar values are always String object so need other config
255
- # layers to know the prompter type for each key's value
256
- def envar_options(default, cli_config)
257
- config = OpenStruct.merge(default, cli_config)
258
- envars = ENV.keys.select { |key, _| key.start_with?('AIA_') }
259
- envars.each do |envar|
260
- key = envar.sub(/^AIA_/, '').downcase.to_sym
261
- value = ENV[envar]
262
-
263
- value = case config[key]
264
- when TrueClass, FalseClass
265
- value.downcase == 'true'
266
- when Integer
267
- value.to_i
268
- when Float
269
- value.to_f
270
- when Array
271
- # Special handling for :model to support inline role syntax (ADR-005 v2)
272
- if key == :model && value.include?('=')
273
- CLIParser.parse_models_with_roles(value)
274
- else
275
- value.split(',').map(&:strip)
276
- end
277
- else
278
- value # defaults to String
279
- end
280
- config[key] = value
281
- end
282
-
283
- config
284
- end
285
- end
286
- end
287
- end
288
- end
@@ -1,91 +0,0 @@
1
- # lib/aia/config/defaults.rb
2
-
3
- require 'yaml'
4
- require 'toml-rb'
5
- require 'date'
6
- require 'prompt_manager'
7
-
8
- module AIA
9
- module ConfigModules
10
- module Defaults
11
- DEFAULT_CONFIG = OpenStruct.new({
12
- adapter: 'ruby_llm', # 'ruby_llm' or ???
13
- #
14
- aia_dir: File.join(ENV['HOME'], '.aia'),
15
- config_file: File.join(ENV['HOME'], '.aia', 'config.yml'),
16
- out_file: 'temp.md',
17
- log_file: File.join(ENV['HOME'], '.prompts', '_prompts.log'),
18
- context_files: [],
19
- #
20
- prompts_dir: File.join(ENV['HOME'], '.prompts'),
21
- prompt_extname: PromptManager::Storage::FileSystemAdapter::PROMPT_EXTENSION,
22
- #
23
- roles_prefix: 'roles',
24
- roles_dir: File.join(ENV['HOME'], '.prompts', 'roles'),
25
- role: '',
26
-
27
- #
28
- system_prompt: '',
29
-
30
- # Tools
31
- tools: '', # Comma-separated string of loaded tool names (set by adapter)
32
- allowed_tools: nil, # nil means all tools are allowed; otherwise an Array of Strings which are the tool names
33
- rejected_tools: nil, # nil means no tools are rejected
34
- tool_paths: [], # Strings - absolute and relative to tools
35
-
36
- # Flags
37
- markdown: true,
38
- shell: true,
39
- erb: true,
40
- chat: false,
41
- clear: false,
42
- terse: false,
43
- verbose: false,
44
- debug: $DEBUG_ME,
45
- fuzzy: false,
46
- speak: false,
47
- append: false, # Default to not append to existing out_file
48
-
49
- # workflow
50
- pipeline: [],
51
-
52
- # PromptManager::Prompt Tailoring
53
- parameter_regex: PromptManager::Prompt.parameter_regex.to_s,
54
-
55
- # LLM tuning parameters
56
- temperature: 0.7,
57
- max_tokens: 2048,
58
- top_p: 1.0,
59
- frequency_penalty: 0.0,
60
- presence_penalty: 0.0,
61
-
62
- # Audio Parameters
63
- voice: 'alloy',
64
- speak_command: 'afplay', # 'afplay' for audio files on MacOS
65
-
66
- # Image Parameters
67
- image_size: '1024x1024',
68
- image_quality: 'standard',
69
- image_style: 'vivid',
70
-
71
- # Models
72
- model: ['gpt-4o-mini'],
73
- consensus: nil, # nil/false = individual responses; true = consensus response
74
- speech_model: 'tts-1',
75
- transcription_model: 'whisper-1',
76
- embedding_model: 'text-embedding-ada-002',
77
- image_model: 'dall-e-3',
78
-
79
- # Model Regristery
80
- refresh: 7, # days between refreshes of model info; 0 means every startup
81
- last_refresh: Date.today - 1,
82
-
83
- # Ruby libraries to require for Ruby binding
84
- require_libs: [],
85
-
86
- # MCP Servers (nil means not configured, set in config file)
87
- mcp_servers: nil,
88
- }).freeze
89
- end
90
- end
91
- end
@@ -1,163 +0,0 @@
1
- # lib/aia/config/file_loader.rb
2
-
3
- require 'yaml'
4
- require 'toml-rb'
5
- require 'erb'
6
- require 'date'
7
-
8
- module AIA
9
- module ConfigModules
10
- module FileLoader
11
- class << self
12
- def load_config_file(file, config)
13
- if File.exist?(file)
14
- ext = File.extname(file).downcase
15
- content = File.read(file)
16
-
17
- # Process ERB if filename ends with .erb
18
- if file.end_with?('.erb')
19
- content = ERB.new(content).result
20
- file = file.chomp('.erb')
21
- File.write(file, content)
22
- end
23
-
24
- file_config = case ext
25
- when '.yml', '.yaml'
26
- YAML.safe_load(content, permitted_classes: [Symbol], symbolize_names: true)
27
- when '.toml'
28
- TomlRB.parse(content)
29
- else
30
- raise "Unsupported config file format: #{ext}"
31
- end
32
-
33
- file_config.each do |key, value|
34
- config[key.to_sym] = value
35
- end
36
- else
37
- raise "Config file not found: #{file}"
38
- end
39
- end
40
-
41
- def cf_options(file)
42
- config = OpenStruct.new
43
-
44
- if File.exist?(file)
45
- content = read_and_process_config_file(file)
46
- file_config = parse_config_content(content, File.extname(file).downcase)
47
- apply_file_config_to_struct(config, file_config)
48
- else
49
- STDERR.puts "WARNING:Config file not found: #{file}"
50
- end
51
-
52
- normalize_last_refresh_date(config)
53
- config
54
- end
55
-
56
- def read_and_process_config_file(file)
57
- content = File.read(file)
58
-
59
- # Process ERB if filename ends with .erb
60
- if file.end_with?('.erb')
61
- content = ERB.new(content).result
62
- processed_file = file.chomp('.erb')
63
- File.write(processed_file, content)
64
- end
65
-
66
- content
67
- end
68
-
69
- def parse_config_content(content, ext)
70
- case ext
71
- when '.yml', '.yaml'
72
- YAML.safe_load(content, permitted_classes: [Symbol], symbolize_names: true)
73
- when '.toml'
74
- TomlRB.parse(content)
75
- else
76
- raise "Unsupported config file format: #{ext}"
77
- end
78
- end
79
-
80
- def apply_file_config_to_struct(config, file_config)
81
- file_config.each do |key, value|
82
- # Special handling for model array with roles (ADR-005 v2)
83
- if (key == :model || key == 'model') && value.is_a?(Array) && value.first.is_a?(Hash)
84
- config[:model] = process_model_array_with_roles(value)
85
- else
86
- config[key] = value
87
- end
88
- end
89
- end
90
-
91
- # Process model array with roles from config file (ADR-005 v2)
92
- # Format: [{model: "gpt-4o", role: "architect"}, ...]
93
- # Also supports models without roles: [{model: "gpt-4o"}, ...]
94
- def process_model_array_with_roles(models_array)
95
- return [] if models_array.nil? || models_array.empty?
96
-
97
- model_specs = []
98
- model_counts = Hash.new(0)
99
-
100
- models_array.each do |spec|
101
- model_name = spec[:model] || spec['model']
102
- role_name = spec[:role] || spec['role']
103
-
104
- model_counts[model_name] += 1
105
- instance = model_counts[model_name]
106
-
107
- model_specs << {
108
- model: model_name,
109
- role: role_name,
110
- instance: instance,
111
- internal_id: instance > 1 ? "#{model_name}##{instance}" : model_name
112
- }
113
- end
114
-
115
- model_specs
116
- end
117
-
118
- def normalize_last_refresh_date(config)
119
- return unless config.last_refresh&.is_a?(String)
120
-
121
- config.last_refresh = Date.strptime(config.last_refresh, '%Y-%m-%d')
122
- end
123
-
124
- def dump_config(config, file)
125
- # Implementation for config dump
126
- ext = File.extname(file).downcase
127
-
128
- config.last_refresh = config.last_refresh.to_s if config.last_refresh.is_a? Date
129
-
130
- config_hash = config.to_h
131
-
132
- # Remove prompt_id to prevent automatic initial pompting in --chat mode
133
- config_hash.delete(:prompt_id)
134
-
135
- # Remove dump_file key to prevent automatic exit on next load
136
- config_hash.delete(:dump_file)
137
-
138
- content = case ext
139
- when '.yml', '.yaml'
140
- YAML.dump(config_hash)
141
- when '.toml'
142
- TomlRB.dump(config_hash)
143
- else
144
- raise "Unsupported config file format: #{ext}"
145
- end
146
-
147
- File.write(file, content)
148
- puts "Config successfully dumped to #{file}"
149
- end
150
-
151
- def generate_completion_script(shell)
152
- script_path = File.join(File.dirname(__FILE__), "../../aia_completion.#{shell}")
153
-
154
- if File.exist?(script_path)
155
- puts File.read(script_path)
156
- else
157
- STDERR.puts "ERROR: The shell '#{shell}' is not supported or the completion script is missing."
158
- end
159
- end
160
- end
161
- end
162
- end
163
- end
@@ -1,134 +0,0 @@
1
- # lib/aia/context_manager.rb
2
-
3
- module AIA
4
- # Manages the conversation context for chat sessions.
5
- class ContextManager
6
- attr_reader :context, :checkpoints
7
-
8
- # Initializes the ContextManager with an optional system prompt.
9
- def initialize(system_prompt: nil)
10
- @context = []
11
- @checkpoints = {}
12
- @checkpoint_counter = 0
13
- add_system_prompt(system_prompt) if system_prompt && !system_prompt.strip.empty?
14
- end
15
-
16
- # Adds a message to the conversation context.
17
- #
18
- # @param role [String] The role of the message sender ('user' or 'assistant').
19
- # @param content [String] The content of the message.
20
- def add_to_context(role:, content:)
21
- @context << { role: role, content: content }
22
- end
23
-
24
- # Returns the current conversation context.
25
- # Optionally adds the system prompt if it wasn't added during initialization
26
- # or needs to be re-added after clearing.
27
- #
28
- # @param system_prompt [String, nil] The system prompt to potentially prepend.
29
- # @return [Array<Hash>] The conversation context array.
30
- def get_context(system_prompt: nil)
31
- # Add or replace system prompt if provided and not empty
32
- if system_prompt && !system_prompt.strip.empty?
33
- add_system_prompt(system_prompt)
34
- end
35
- @context
36
- end
37
-
38
- # Clears the conversation context, optionally keeping the system prompt.
39
- #
40
- # @param keep_system_prompt [Boolean] Whether to retain the initial system prompt.
41
- def clear_context(keep_system_prompt: true)
42
- if keep_system_prompt && !@context.empty? && @context.first[:role] == 'system'
43
- @context = [@context.first]
44
- else
45
- @context = []
46
- end
47
-
48
- # Clear all checkpoints when clearing context
49
- @checkpoints.clear
50
- @checkpoint_counter = 0
51
-
52
- # Attempt to clear the LLM client's context as well
53
- begin
54
- if AIA.config.client && AIA.config.client.respond_to?(:clear_context)
55
- AIA.config.client.clear_context
56
- end
57
-
58
- if AIA.config.respond_to?(:llm) && AIA.config.llm && AIA.config.llm.respond_to?(:clear_context)
59
- AIA.config.llm.clear_context
60
- end
61
-
62
- if defined?(RubyLLM) && RubyLLM.respond_to?(:chat) && RubyLLM.chat.respond_to?(:clear_history)
63
- RubyLLM.chat.clear_history
64
- end
65
- rescue => e
66
- STDERR.puts "ERROR: context_manager clear_context error #{e.message}"
67
- end
68
- end
69
-
70
- # Creates a checkpoint of the current context with an optional name.
71
- #
72
- # @param name [String, nil] The name of the checkpoint. If nil, uses an incrementing integer.
73
- # @return [String] The name of the created checkpoint.
74
- def create_checkpoint(name: nil)
75
- if name.nil?
76
- @checkpoint_counter += 1
77
- name = @checkpoint_counter.to_s
78
- end
79
-
80
- # Store a deep copy of the current context and its position
81
- @checkpoints[name] = {
82
- context: @context.map(&:dup),
83
- position: @context.size
84
- }
85
- @last_checkpoint_name = name
86
- name
87
- end
88
-
89
- # Restores the context to a previously saved checkpoint.
90
- #
91
- # @param name [String, nil] The name of the checkpoint to restore. If nil, uses the last checkpoint.
92
- # @return [Boolean] True if restore was successful, false otherwise.
93
- def restore_checkpoint(name: nil)
94
- name = @last_checkpoint_name if name.nil?
95
-
96
- return false if name.nil? || !@checkpoints.key?(name)
97
-
98
- # Restore the context from the checkpoint
99
- checkpoint_data = @checkpoints[name]
100
- @context = checkpoint_data[:context].map(&:dup)
101
- true
102
- end
103
-
104
- # Returns the list of available checkpoint names.
105
- #
106
- # @return [Array<String>] The names of all checkpoints.
107
- def checkpoint_names
108
- @checkpoints.keys
109
- end
110
-
111
- # Returns checkpoint information mapped to context positions.
112
- #
113
- # @return [Hash<Integer, Array<String>>] Position to checkpoint names mapping.
114
- def checkpoint_positions
115
- positions = {}
116
- @checkpoints.each do |name, data|
117
- position = data[:position]
118
- positions[position] ||= []
119
- positions[position] << name
120
- end
121
- positions
122
- end
123
-
124
- private
125
-
126
- # Adds or replaces the system prompt at the beginning of the context.
127
- def add_system_prompt(system_prompt)
128
- # Remove existing system prompt if present
129
- @context.shift if !@context.empty? && @context.first[:role] == 'system'
130
- # Add the new system prompt at the beginning
131
- @context.unshift({ role: 'system', content: system_prompt })
132
- end
133
- end
134
- end
@@ -1,7 +0,0 @@
1
- {
2
- "mcpServers" : {
3
- "iMCP" : {
4
- "command" : "/Applications/iMCP.app/Contents/MacOS/imcp-server"
5
- }
6
- }
7
- }
@@ -1,11 +0,0 @@
1
- {
2
- "mcpServers": {
3
- "launcher": {
4
- "command": "npx",
5
- "args": [
6
- "y",
7
- "@joshuarileydev/mac-apps-launcher-mcp-server"
8
- ]
9
- }
10
- }
11
- }
@@ -1,8 +0,0 @@
1
- {
2
- "mcpServers": {
3
- "timeserver": {
4
- "command": "python",
5
- "args": ["-m", "mcp_simple_timeserver"]
6
- }
7
- }
8
- }