samagotchi 0.22.0 → 0.23.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.
Files changed (154) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -1
  3. data/bin/chi +9 -4
  4. data/docs/configuration.md +4 -4
  5. data/docs/releasing.md +1 -1
  6. data/docs/testing.md +6 -0
  7. data/lib/samagotchi/answer_command.rb +4 -2
  8. data/lib/samagotchi/bootstrap/config_writer.rb +2 -1
  9. data/lib/samagotchi/bootstrap/probe.rb +1 -1
  10. data/lib/samagotchi/bootstrap_command.rb +2 -2
  11. data/lib/samagotchi/bridge/bounded_queue.rb +0 -2
  12. data/lib/samagotchi/bridge/sse_writer.rb +0 -6
  13. data/lib/samagotchi/bridge/turn_accumulator.rb +2 -2
  14. data/lib/samagotchi/bridge.rb +12 -9
  15. data/lib/samagotchi/bridge_client/event_stream.rb +2 -2
  16. data/lib/samagotchi/bridge_client.rb +1 -1
  17. data/lib/samagotchi/bundle_command.rb +39 -29
  18. data/lib/samagotchi/bundles/btw/manifest.yml +2 -2
  19. data/lib/samagotchi/bundles/btw/plugin.rb +2 -0
  20. data/lib/samagotchi/bundles/check-in/manifest.yml +2 -2
  21. data/lib/samagotchi/bundles/check-in/plugin.rb +2 -0
  22. data/lib/samagotchi/bundles/known-names/hooks/known_names.rb +6 -5
  23. data/lib/samagotchi/bundles/known-names/manifest.yml +2 -2
  24. data/lib/samagotchi/bundles/loop-guard/manifest.yml +2 -2
  25. data/lib/samagotchi/bundles/loop-guard/plugin.rb +2 -0
  26. data/lib/samagotchi/bundles/mcp/manifest.yml +2 -2
  27. data/lib/samagotchi/bundles/mcp/plugin.rb +2 -0
  28. data/lib/samagotchi/bundles/skills/manifest.yml +2 -2
  29. data/lib/samagotchi/bundles/skills/plugin.rb +5 -3
  30. data/lib/samagotchi/bundles/source-links/hooks/source_links.rb +7 -7
  31. data/lib/samagotchi/bundles/source-links/manifest.yml +2 -2
  32. data/lib/samagotchi/bundles/system/config_modification_protocol.md +1 -1
  33. data/lib/samagotchi/bundles/system/manifest.yml +2 -2
  34. data/lib/samagotchi/cancellation_controller.rb +1 -1
  35. data/lib/samagotchi/cli/command.rb +1 -1
  36. data/lib/samagotchi/client.rb +3 -5
  37. data/lib/samagotchi/commands/registry.rb +2 -2
  38. data/lib/samagotchi/config.rb +38 -14
  39. data/lib/samagotchi/context_note.rb +1 -1
  40. data/lib/samagotchi/context_status.rb +6 -6
  41. data/lib/samagotchi/continue_offer.rb +15 -8
  42. data/lib/samagotchi/debug_log.rb +1 -1
  43. data/lib/samagotchi/desktop/macos.rb +5 -4
  44. data/lib/samagotchi/empty_answer_retry.rb +1 -1
  45. data/lib/samagotchi/engine.rb +17 -17
  46. data/lib/samagotchi/gem_update.rb +2 -1
  47. data/lib/samagotchi/guardrail_wiring.rb +1 -1
  48. data/lib/samagotchi/guardrails/approval.rb +5 -5
  49. data/lib/samagotchi/guardrails/approvals.rb +2 -2
  50. data/lib/samagotchi/guardrails/gate.rb +2 -2
  51. data/lib/samagotchi/guardrails/read_only_shell.rb +5 -3
  52. data/lib/samagotchi/guardrails/shell_git_dirs.rb +1 -1
  53. data/lib/samagotchi/guardrails/shell_lex.rb +2 -2
  54. data/lib/samagotchi/guardrails/shell_paths.rb +2 -2
  55. data/lib/samagotchi/hooks/bundle_loader.rb +9 -6
  56. data/lib/samagotchi/hooks/loader.rb +18 -16
  57. data/lib/samagotchi/hooks/registry.rb +10 -2
  58. data/lib/samagotchi/host_registry.rb +1 -3
  59. data/lib/samagotchi/idle_recap.rb +18 -15
  60. data/lib/samagotchi/idle_reminders.rb +6 -3
  61. data/lib/samagotchi/image_store.rb +5 -2
  62. data/lib/samagotchi/kernel_loop.rb +31 -31
  63. data/lib/samagotchi/llm/chat_loop.rb +9 -6
  64. data/lib/samagotchi/llm/errors.rb +2 -2
  65. data/lib/samagotchi/llm/http.rb +12 -12
  66. data/lib/samagotchi/llm/openai_chat.rb +39 -28
  67. data/lib/samagotchi/llm/prompt_cache.rb +1 -1
  68. data/lib/samagotchi/log.rb +2 -2
  69. data/lib/samagotchi/log_subscriber.rb +2 -1
  70. data/lib/samagotchi/memory_bundle/builder.rb +9 -3
  71. data/lib/samagotchi/memory_bundle/index_updater.rb +13 -1
  72. data/lib/samagotchi/memory_bundle/installer.rb +67 -57
  73. data/lib/samagotchi/memory_bundle/listing.rb +5 -1
  74. data/lib/samagotchi/memory_bundle/manifest.rb +14 -4
  75. data/lib/samagotchi/memory_bundle/merger.rb +6 -4
  76. data/lib/samagotchi/memory_bundle/provenance.rb +16 -13
  77. data/lib/samagotchi/memory_bundle/source.rb +7 -3
  78. data/lib/samagotchi/memory_bundle/status.rb +3 -1
  79. data/lib/samagotchi/memory_bundle/system_bundle.rb +3 -2
  80. data/lib/samagotchi/memory_bundle/trash.rb +5 -2
  81. data/lib/samagotchi/memory_bundle/uninstaller.rb +9 -6
  82. data/lib/samagotchi/memory_bundle.rb +1 -0
  83. data/lib/samagotchi/model_overlay.rb +3 -5
  84. data/lib/samagotchi/model_profile.rb +12 -8
  85. data/lib/samagotchi/note_command.rb +2 -1
  86. data/lib/samagotchi/output_formatter.rb +18 -17
  87. data/lib/samagotchi/owner_lock.rb +2 -1
  88. data/lib/samagotchi/plugin/api.rb +8 -5
  89. data/lib/samagotchi/plugin/context.rb +1 -3
  90. data/lib/samagotchi/plugin/loader.rb +1 -1
  91. data/lib/samagotchi/plugin/service.rb +1 -1
  92. data/lib/samagotchi/plugin/sessions.rb +1 -0
  93. data/lib/samagotchi/plugin_tasks.rb +1 -1
  94. data/lib/samagotchi/prompt.rb +68 -12
  95. data/lib/samagotchi/prompt_literal_guard.rb +1 -1
  96. data/lib/samagotchi/question_desk.rb +7 -7
  97. data/lib/samagotchi/recap_setup.rb +1 -1
  98. data/lib/samagotchi/relay_desk.rb +1 -1
  99. data/lib/samagotchi/reminder_store.rb +2 -1
  100. data/lib/samagotchi/send_command.rb +4 -2
  101. data/lib/samagotchi/session.rb +2 -2
  102. data/lib/samagotchi/session_archive_command.rb +5 -1
  103. data/lib/samagotchi/session_commands.rb +1 -3
  104. data/lib/samagotchi/session_manager.rb +2 -4
  105. data/lib/samagotchi/session_metrics.rb +10 -10
  106. data/lib/samagotchi/session_observer.rb +3 -2
  107. data/lib/samagotchi/session_retention.rb +2 -2
  108. data/lib/samagotchi/sessions_command.rb +14 -5
  109. data/lib/samagotchi/system_prompt.rb +19 -8
  110. data/lib/samagotchi/terminal_ui/attach_launcher.rb +5 -5
  111. data/lib/samagotchi/terminal_ui/attached_loop.rb +2 -2
  112. data/lib/samagotchi/terminal_ui/event_renderer.rb +1 -2
  113. data/lib/samagotchi/terminal_ui/formatting.rb +10 -10
  114. data/lib/samagotchi/terminal_ui/input_support.rb +2 -2
  115. data/lib/samagotchi/terminal_ui/line_reader.rb +3 -3
  116. data/lib/samagotchi/terminal_ui/question_prompt.rb +23 -23
  117. data/lib/samagotchi/terminal_ui/question_slot.rb +10 -10
  118. data/lib/samagotchi/terminal_ui/reline_seam.rb +1 -1
  119. data/lib/samagotchi/terminal_ui/repl_input.rb +3 -2
  120. data/lib/samagotchi/terminal_ui.rb +9 -5
  121. data/lib/samagotchi/text_diff.rb +12 -12
  122. data/lib/samagotchi/thinking.rb +6 -2
  123. data/lib/samagotchi/thought_stream_splitter.rb +6 -3
  124. data/lib/samagotchi/tool_activity.rb +1 -0
  125. data/lib/samagotchi/tool_call_parser.rb +13 -14
  126. data/lib/samagotchi/tool_declarations.rb +36 -35
  127. data/lib/samagotchi/tools/ask_user_question.rb +3 -4
  128. data/lib/samagotchi/tools/builtin_calls.rb +1 -1
  129. data/lib/samagotchi/tools/delegate.rb +1 -1
  130. data/lib/samagotchi/tools/delegate_relay.rb +1 -1
  131. data/lib/samagotchi/tools/delegate_wait.rb +0 -1
  132. data/lib/samagotchi/tools/edit.rb +14 -13
  133. data/lib/samagotchi/tools/execute.rb +3 -5
  134. data/lib/samagotchi/tools/list_reminders.rb +1 -1
  135. data/lib/samagotchi/tools/memory.rb +21 -22
  136. data/lib/samagotchi/tools/read.rb +7 -7
  137. data/lib/samagotchi/tools/task_create.rb +1 -1
  138. data/lib/samagotchi/tools/task_get.rb +1 -1
  139. data/lib/samagotchi/tools/task_list.rb +1 -1
  140. data/lib/samagotchi/tools/task_runtime.rb +8 -9
  141. data/lib/samagotchi/tools/task_stop.rb +1 -1
  142. data/lib/samagotchi/tools/task_wait.rb +3 -4
  143. data/lib/samagotchi/tools/web_fetch.rb +2 -4
  144. data/lib/samagotchi/tools/write.rb +1 -1
  145. data/lib/samagotchi/turn_flow.rb +8 -8
  146. data/lib/samagotchi/turn_note.rb +5 -1
  147. data/lib/samagotchi/version.rb +1 -1
  148. data/lib/samagotchi/vision_support.rb +2 -2
  149. data/lib/samagotchi/web/app.rb +13 -6
  150. data/lib/samagotchi/web/markdown_renderer.rb +2 -1
  151. data/lib/samagotchi/web/qr.rb +7 -1
  152. data/lib/samagotchi/web/server.rb +6 -2
  153. data/lib/samagotchi/worker.rb +10 -2
  154. metadata +20 -20
@@ -27,10 +27,10 @@ module Samagotchi
27
27
  return [:resume, nil] if normalized.empty?
28
28
 
29
29
  lowered = normalized.downcase
30
- return [:resume, nil] if lowered == CONTINUE_COMMAND || lowered == "yes" || lowered == "y"
31
- return [:abort, nil] if lowered == "no" || lowered == "n"
30
+ return [:resume, nil] if [CONTINUE_COMMAND, "yes", "y"].include?(lowered)
31
+ return [:abort, nil] if %w[no n].include?(lowered)
32
32
 
33
- reason_match = normalized.match(/\A(?:no|n)\s*[,:\-]\s*(.+)\z/i)
33
+ reason_match = normalized.match(/\A(?:no|n)\s*[,:-]\s*(.+)\z/i)
34
34
  if reason_match
35
35
  reason = reason_match[1].to_s.strip
36
36
  return [:abort, nil] if reason.empty?
@@ -220,11 +220,11 @@ module Samagotchi
220
220
  lines << "- original_prompt: #{original_prompt.to_s.empty? ? "(unavailable)" : original_prompt}"
221
221
 
222
222
  tool_trace = context ? Array(context[:tool_trace]) : []
223
- if tool_trace.empty?
224
- lines << "- interrupted_tools: (none)"
225
- else
226
- lines << "- interrupted_tools: #{tool_trace.join("; ")}"
227
- end
223
+ lines << if tool_trace.empty?
224
+ "- interrupted_tools: (none)"
225
+ else
226
+ "- interrupted_tools: #{tool_trace.join("; ")}"
227
+ end
228
228
 
229
229
  model_intent = context && context[:last_model_intent]
230
230
  lines << "- last_model_intent: #{model_intent.to_s.empty? ? "(unavailable)" : model_intent}"
@@ -98,7 +98,11 @@ module Samagotchi
98
98
  # emptyAnswerLine words it the same).
99
99
  def empty_answer_line(retries)
100
100
  count = retries.to_i
101
- after = count.positive? ? " (after #{count} #{count == 1 ? "retry" : "retries"})" : ""
101
+ after = if count.positive?
102
+ " (after #{count} #{count == 1 ? "retry" : "retries"})"
103
+ else
104
+ ""
105
+ end
102
106
  "no answer: the model returned nothing#{after}"
103
107
  end
104
108
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Samagotchi
4
- VERSION = "0.22.0"
4
+ VERSION = "0.23.0"
5
5
  # Sent as the User-Agent of every HTTP request chi makes.
6
6
  USER_AGENT = "chi/#{VERSION}"
7
7
  end
@@ -45,7 +45,7 @@ module Samagotchi
45
45
  marker.is_a?(String) && !marker.empty? ? marker : nil
46
46
  end
47
47
 
48
- def self.configured(target, entry, models, names)
48
+ def self.configured(_target, entry, models, names)
49
49
  models ||= begin
50
50
  ConfigFile.model_settings
51
51
  rescue StandardError
@@ -58,7 +58,7 @@ module Samagotchi
58
58
  Answer.new(value: entry.vision, reason: entry.vision ? nil : "hosts.#{entry.name} sets vision: false")
59
59
  end
60
60
 
61
- def self.native(target, entry, profile, trust_config:)
61
+ def self.native(target, _entry, profile, trust_config:)
62
62
  client = target.client
63
63
  transport = client.transport.name
64
64
  return no("#{transport} hosts take no images (only llama.cpp does)") unless transport == :llama_cpp
@@ -157,6 +157,7 @@ module Samagotchi
157
157
  req = Rack::Request.new(env)
158
158
  return forbidden unless local_host_header?(env)
159
159
  return cross_origin if cross_site?(env)
160
+
160
161
  if @lan && !LOOPBACK_PEERS.include?(env["REMOTE_ADDR"].to_s)
161
162
  denied = token_gate(req)
162
163
  return denied if denied
@@ -506,13 +507,16 @@ module Samagotchi
506
507
 
507
508
  def sanitize_limit(val)
508
509
  return nil if val.nil? || val.to_s.strip.empty?
510
+
509
511
  n = val.to_i
510
512
  return nil if n <= 0
513
+
511
514
  [n, 1000].min
512
515
  end
513
516
 
514
517
  def sanitize_offset(val)
515
518
  return 0 if val.nil? || val.to_s.strip.empty?
519
+
516
520
  n = val.to_i
517
521
  n.positive? ? n : 0
518
522
  end
@@ -522,6 +526,7 @@ module Samagotchi
522
526
  unless body.is_a?(Hash)
523
527
  return error_response(400, "invalid_json", "invalid JSON body")
524
528
  end
529
+
525
530
  prompt = body["prompt"] || body[:prompt]
526
531
  # idle: a session with no first turn, for a first message with
527
532
  # images (the page uploads them into it, then sends the turn).
@@ -529,6 +534,7 @@ module Samagotchi
529
534
  if prompt.to_s.strip.empty? && !idle
530
535
  return error_response(400, "missing_fields", "prompt is required")
531
536
  end
537
+
532
538
  # dir: the folder the chat starts in (the page's scope); without it,
533
539
  # the server's own cwd.
534
540
  dir, error = scope_dir(body["dir"])
@@ -891,11 +897,13 @@ module Samagotchi
891
897
  unless body.is_a?(Hash)
892
898
  return error_response(400, "invalid_json", "invalid JSON body")
893
899
  end
900
+
894
901
  prompt = body["prompt"] || body[:prompt]
895
902
  client_id = body["client_id"] || body[:client_id]
896
903
  if prompt.to_s.strip.empty?
897
904
  return error_response(400, "missing_fields", "prompt is required")
898
905
  end
906
+
899
907
  images = turn_images(id, body["images"])
900
908
  return error_response(400, "bad_images", images) if images.is_a?(String)
901
909
 
@@ -1173,7 +1181,7 @@ module Samagotchi
1173
1181
  lambda do |io|
1174
1182
  query = req.query_string.to_s.empty? ? "" : "?#{req.query_string}"
1175
1183
  body = ProxyStreamBody.new(host: DEFAULT_HOST, port: port, session_id: id, query: query, headers: req.env,
1176
- server_running: @server_running)
1184
+ server_running: @server_running)
1177
1185
  body.each { |chunk| io.write(chunk) }
1178
1186
  rescue Errno::EPIPE, Errno::ECONNRESET, IOError
1179
1187
  nil # client went away — end the stream quietly
@@ -1249,7 +1257,7 @@ module Samagotchi
1249
1257
  def serve_static(req)
1250
1258
  # Serve files under public_dir for /assets/* and bare paths
1251
1259
  rel = req.path_info.sub(%r{\A/(assets|public)/}, "")
1252
- rel = req.path_info.sub(%r{\A/}, "") if rel == req.path_info
1260
+ rel = req.path_info.delete_prefix("/") if rel == req.path_info
1253
1261
  # Prevent directory traversal
1254
1262
  rel = rel.split("/").reject { |p| p == ".." || p.empty? }.join("/")
1255
1263
  full = File.join(@public_dir, rel)
@@ -1483,7 +1491,7 @@ module Samagotchi
1483
1491
 
1484
1492
  norm_role = role == "model" ? "assistant" : role
1485
1493
  # normalize assistant vs model, keep user as is
1486
- norm_role = "assistant" if norm_role == "assistant" || norm_role == "model"
1494
+ norm_role = "assistant" if %w[assistant model].include?(norm_role)
1487
1495
  norm_role = "user" if norm_role == "user"
1488
1496
  next unless %w[user assistant].include?(norm_role)
1489
1497
 
@@ -1644,7 +1652,6 @@ module Samagotchi
1644
1652
  json_response(status, { error: code, detail: detail })
1645
1653
  end
1646
1654
 
1647
-
1648
1655
  def not_found(path:)
1649
1656
  error_response(404, "not_found", "not found: #{path}")
1650
1657
  end
@@ -1740,12 +1747,12 @@ module Samagotchi
1740
1747
  @server_running = server_running
1741
1748
  end
1742
1749
 
1743
- def each(&block)
1750
+ def each(&)
1744
1751
  # Forward the browser's auto-reconnect cursor: the bridge prefers the
1745
1752
  # Last-Event-ID header over ?from_seq, and the reconnect URL carries a
1746
1753
  # stale initial cursor — without this the bridge would replay content
1747
1754
  # already delivered (duplicate bubbles).
1748
- @client.stream(query: @query, last_event_id: @headers["HTTP_LAST_EVENT_ID"], running: @server_running, &block)
1755
+ @client.stream(query: @query, last_event_id: @headers["HTTP_LAST_EVENT_ID"], running: @server_running, &)
1749
1756
  end
1750
1757
  end
1751
1758
  end
@@ -34,7 +34,7 @@ module Samagotchi
34
34
 
35
35
  html = Commonmarker.to_html(markdown.to_s, options: {
36
36
  render: { escape: true }, # escape raw HTML from source; highlighter output is still emitted
37
- extension: { header_ids: nil },
37
+ extension: { header_ids: nil }
38
38
  })
39
39
  return nil unless html
40
40
 
@@ -71,6 +71,7 @@ module Samagotchi
71
71
  def sanitize_attributes(node)
72
72
  node.attribute_nodes.each do |attribute|
73
73
  next if allowed_attribute?(node, attribute.name)
74
+
74
75
  node.remove_attribute(attribute.name)
75
76
  end
76
77
  return unless node.name == "a"
@@ -21,7 +21,13 @@ module Samagotchi
21
21
  rows = matrix(text, quiet: quiet)
22
22
  rows << Array.new(rows.first.size, false) if rows.size.odd?
23
23
  rows.each_slice(2).map do |top, bottom|
24
- line = top.zip(bottom).map { |t, b| t ? (b ? "█" : "▀") : (b ? "▄" : " ") }.join
24
+ line = top.zip(bottom).map do |t, b|
25
+ if t
26
+ b ? "█" : "▀"
27
+ else
28
+ (b ? "▄" : " ")
29
+ end
30
+ end.join
25
31
  color ? "#{COLORS}#{line}#{RESET}" : line
26
32
  end
27
33
  end
@@ -94,8 +94,12 @@ module Samagotchi
94
94
  puts lan_off_line(setting)
95
95
  return 0
96
96
  end
97
- start(port: port, host: host, url: url, open_browser: open_browser, markdown: markdown, view: view,
98
- annotate_presets: annotate_presets, lan: lan) ? 0 : 1
97
+ if start(port: port, host: host, url: url, open_browser: open_browser, markdown: markdown, view: view,
98
+ annotate_presets: annotate_presets, lan: lan)
99
+ 0
100
+ else
101
+ 1
102
+ end
99
103
  end
100
104
  rescue Lan::Error => e
101
105
  warn "Error: #{e.message}"
@@ -166,6 +166,7 @@ module Samagotchi
166
166
  # A session stopped before this worker took the lock (e.g. a stop
167
167
  # right after create) must not run its initial prompt.
168
168
  return :stopped if stopped_on_disk?
169
+
169
170
  # Plugins' slow setup (chi.init: an MCP server's first start), in
170
171
  # the background, shown by the UIs; a turn waits only for the ones
171
172
  # that bring tools.
@@ -483,15 +484,22 @@ module Samagotchi
483
484
  # queued while it ran are refused, then the caller's block takes the
484
485
  # result (or the error the Engine announced as :turn_failed), the
485
486
  # answer goes to the output file and the session is saved.
487
+ # A failure before the Engine's turn began (this save, say) goes to the
488
+ # block too, with no :turn_failed: it is logged, the session idle again.
486
489
  # @yieldparam result [Object, nil] Engine#run_turn's, nil on a failure
487
490
  # @yieldparam error [StandardError, nil]
488
491
  def run_engine_turn(prompt, **turn_args)
489
- @session.status = Session::STATUS_RUNNING
490
- @session.save(state_dir: @state_dir)
491
492
  begin
493
+ @session.status = Session::STATUS_RUNNING
494
+ @session.save(state_dir: @state_dir)
492
495
  result = @engine.run_turn(@session, prompt, pending_input: pending_input_drain, **turn_args)
493
496
  rescue StandardError => e
494
497
  error = e
498
+ # Still running: no turn of the Engine's ended (it never began).
499
+ if @session.status == Session::STATUS_RUNNING
500
+ @session.status = Session::STATUS_IDLE
501
+ Log.warn(:worker, "turn_not_begun", error: e.class.name, msg: e.message)
502
+ end
495
503
  ensure
496
504
  refuse_queued_commands
497
505
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: samagotchi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.22.0
4
+ version: 0.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Dedov
@@ -9,20 +9,6 @@ bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
- - !ruby/object:Gem::Dependency
13
- name: reline
14
- requirement: !ruby/object:Gem::Requirement
15
- requirements:
16
- - - "~>"
17
- - !ruby/object:Gem::Version
18
- version: 0.6.3
19
- type: :runtime
20
- prerelease: false
21
- version_requirements: !ruby/object:Gem::Requirement
22
- requirements:
23
- - - "~>"
24
- - !ruby/object:Gem::Version
25
- version: 0.6.3
26
12
  - !ruby/object:Gem::Dependency
27
13
  name: json
28
14
  requirement: !ruby/object:Gem::Requirement
@@ -80,19 +66,19 @@ dependencies:
80
66
  - !ruby/object:Gem::Version
81
67
  version: '0'
82
68
  - !ruby/object:Gem::Dependency
83
- name: webrick
69
+ name: reline
84
70
  requirement: !ruby/object:Gem::Requirement
85
71
  requirements:
86
- - - ">="
72
+ - - "~>"
87
73
  - !ruby/object:Gem::Version
88
- version: '0'
74
+ version: 0.6.3
89
75
  type: :runtime
90
76
  prerelease: false
91
77
  version_requirements: !ruby/object:Gem::Requirement
92
78
  requirements:
93
- - - ">="
79
+ - - "~>"
94
80
  - !ruby/object:Gem::Version
95
- version: '0'
81
+ version: 0.6.3
96
82
  - !ruby/object:Gem::Dependency
97
83
  name: rqrcode_core
98
84
  requirement: !ruby/object:Gem::Requirement
@@ -107,6 +93,20 @@ dependencies:
107
93
  - - "~>"
108
94
  - !ruby/object:Gem::Version
109
95
  version: '2.0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: webrick
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
110
  description: chi is an agent harness for local and OpenAI-compatible models (llama.cpp,
111
111
  mlx, oMLX, hosted APIs). It runs sessions in a terminal REPL or in background workers
112
112
  you can attach to from the terminal and a web UI, keeps memories in plain files