ollama_chat 0.0.122 → 0.0.123
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/CHANGES.md +94 -0
- data/README.md +65 -9
- data/Rakefile +0 -1
- data/lib/ollama_chat/asr.rb +2 -2
- data/lib/ollama_chat/commands.rb +6 -7
- data/lib/ollama_chat/conversation.rb +3 -2
- data/lib/ollama_chat/kramdown_ansi.rb +22 -11
- data/lib/ollama_chat/redis_cache.rb +1 -1
- data/lib/ollama_chat/session_management.rb +28 -39
- data/lib/ollama_chat/tools/compute_bmi.rb +2 -2
- data/lib/ollama_chat/tools/execute_grep.rb +4 -0
- data/lib/ollama_chat/tts.rb +1 -1
- data/lib/ollama_chat/version.rb +1 -1
- data/ollama_chat.gemspec +2 -3
- data/spec/ollama_chat/asr_spec.rb +2 -2
- data/spec/ollama_chat/commands_spec.rb +2 -15
- data/spec/ollama_chat/conversation_spec.rb +1 -1
- data/spec/ollama_chat/kramdown_ansi_spec.rb +60 -0
- data/spec/ollama_chat/session_management_spec.rb +21 -14
- data/spec/ollama_chat/tts_spec.rb +2 -2
- metadata +1 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f2d0c5676e03433f245a21795872a9d7bd64357306ec691de3012195b5403bef
|
|
4
|
+
data.tar.gz: 933dca2b53647c523b9849d958cc1625106c97500caf2814bc731458a0e683f4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4589b5f1cf689bb35bdf26c288e59f40b87ef926eaf7f91e187c3fa729958c9d042f784eb3bf9a4b6e64966c201312713c2e20607291c6aabc10d306cf4cf272
|
|
7
|
+
data.tar.gz: 19102c3d01a2ebb4bb14b8ea617b09a7e168d0175225024a490dc85e23b41ce3c7eba249d82cc671f5530da0090e945f8f6358d17ca7f6b7587a413002e27dc2
|
data/CHANGES.md
CHANGED
|
@@ -1,5 +1,99 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-09-25 v0.0.123
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
* README section 5 documenting `/conversation compact`: token-aware
|
|
8
|
+
keep-recent budget, safe & retryable behavior, visible before/after
|
|
9
|
+
metrics, and iterative re-compaction.
|
|
10
|
+
* Three-step context escalation ladder in the README: `/conversation
|
|
11
|
+
compact` first, then `/conversation report` + `/clear` + `/input path`
|
|
12
|
+
as the preferred second step, and `/conversation clean` as the emergency
|
|
13
|
+
exit.
|
|
14
|
+
* `execute_shell` tool to the Filesystem row in the README, noted as running
|
|
15
|
+
shell commands as a last resort.
|
|
16
|
+
* `execute_jira_twg` tool to the Web/External row in the README for running
|
|
17
|
+
Jira CLI queries via `twg`.
|
|
18
|
+
* `lookup_group` tool to the Knowledge row in the README for retrieving prior
|
|
19
|
+
conversation groups by UUID.
|
|
20
|
+
* Speech Services (ASR) section documenting `OLLAMA_CHAT_ASR_URL`,
|
|
21
|
+
`OLLAMA_CHAT_ASR_CONVERT_COMMAND`, and `OLLAMA_CHAT_ASR_MODEL`.
|
|
22
|
+
* Audio Playback section documenting `OLLAMA_CHAT_AUDIO_PLAYER_CONFIG`.
|
|
23
|
+
* Invidious (YouTube Proxy) section documenting `OLLAMA_CHAT_INVIDIOUS_URL`,
|
|
24
|
+
`OLLAMA_CHAT_INVIDIOUS_COMPANION_KEY`, and
|
|
25
|
+
`OLLAMA_CHAT_INVIDIOUS_CAPTION_LANGUAGES`.
|
|
26
|
+
* `markdown:` keyword argument (default `true`) to
|
|
27
|
+
`kramdown_markdown_remove`; when `false`, skips the `kramdown_ansi_parse`
|
|
28
|
+
step while still removing emoji, ANSI, and box-drawing characters.
|
|
29
|
+
* Explanatory comment block to `eval_template` in
|
|
30
|
+
`lib/ollama_chat/tools/execute_grep.rb` clarifying that the `cmd` config
|
|
31
|
+
value is a Ruby string template whose `#{...}` interpolations are resolved
|
|
32
|
+
against the method's local parameters via `eval`.
|
|
33
|
+
* `cleaned` string prefix in `save_conversation` so the `STDOUT`/`STDERR`
|
|
34
|
+
confirmation messages read "Saved cleaned conversation to…" when `clean:
|
|
35
|
+
true` is passed.
|
|
36
|
+
* "Cancelled." message when the user skips saving in conversation report and
|
|
37
|
+
summarize flows.
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
* Renamed `report_session` to `generate_conversation_report` to clarify it
|
|
42
|
+
only builds the report text.
|
|
43
|
+
* Reworked `report_conversation` to always display in the pager first, then
|
|
44
|
+
optionally save to a file; removed the `save:` keyword argument.
|
|
45
|
+
* Reworked `summarize_conversation` in `session_management.rb` to always
|
|
46
|
+
render via `use_pager` first, then optionally save via `ask_for_filename?`
|
|
47
|
+
and `should_overwrite?`.
|
|
48
|
+
* Removed the `save:` keyword argument from `summarize_conversation` and the
|
|
49
|
+
`-f` flag from the `/conversation` command dispatch in `commands.rb`.
|
|
50
|
+
* Tightened the `/conversation` regex from `(?:[sf]|c)` to `[sc]` and updated
|
|
51
|
+
the `options:` help text to drop `-f save`.
|
|
52
|
+
* Changed "Nothing to summarize!" and "Nothing to report!" output from
|
|
53
|
+
`STDERR` to `STDOUT`.
|
|
54
|
+
* `kramdown_markdown_remove` now strips `\p{Extended_Pictographic}` emoji
|
|
55
|
+
before any further processing, preventing TTS engines from vocalizing them.
|
|
56
|
+
* `kramdown_markdown_remove` in `lib/ollama_chat/kramdown_ansi.rb` now strips
|
|
57
|
+
Unicode box-drawing characters (`U+2500`..`U+257F`) that kramdown renders
|
|
58
|
+
as table borders, preventing TTS engines from stammering on them.
|
|
59
|
+
* Collapses resulting multi-space runs and strips leading/trailing whitespace
|
|
60
|
+
in `kramdown_markdown_remove`.
|
|
61
|
+
* Moved the `kramdown_markdown_remove` call from `flush_buffer` into
|
|
62
|
+
`enqueue_tts` in `lib/ollama_chat/tts.rb` so all enqueue paths are covered,
|
|
63
|
+
passing `markdown: @chat.markdown.on?`.
|
|
64
|
+
* `multipart_form_data` in `lib/ollama_chat/asr.rb` now returns a hash
|
|
65
|
+
containing only `headers:`, `expects:`, and `body:`, which are the actual
|
|
66
|
+
Excon request options, instead of merging `rest` (`model:`, `language:`)
|
|
67
|
+
into the returned options hash.
|
|
68
|
+
* Updated YARD documentation to reflect the new parameter and emoji stripping
|
|
69
|
+
behavior.
|
|
70
|
+
* Updated `spec/ollama_chat/asr_spec.rb` expectations from
|
|
71
|
+
`hash_including(model: ...)` / `hash_including(language: ...)` to
|
|
72
|
+
`hash_including(body: kind_of(String))` to match the new option shape.
|
|
73
|
+
* Updated `commands_spec.rb` to remove the obsolete `/conversation summarize
|
|
74
|
+
-f` and `/conversation report -f` specs and drop `save:` from expectations.
|
|
75
|
+
* Updated `session_management_spec.rb` for the new show-then-save flow,
|
|
76
|
+
`STDOUT` stream, and `Cancelled.` expectation.
|
|
77
|
+
* Updated the corresponding expectation in `conversation_spec.rb` to match
|
|
78
|
+
the new message text.
|
|
79
|
+
* Renamed former section 5 "Session Reports" to section 6 "Conversation
|
|
80
|
+
Reports" to match the actual command name.
|
|
81
|
+
* Updated Conversation Archiving section from `/session summarize` to
|
|
82
|
+
`/conversation summarize`, removed obsolete `-f` flag reference, and
|
|
83
|
+
described the show-then-save flow.
|
|
84
|
+
|
|
85
|
+
### Fixed
|
|
86
|
+
* Fixed `TTS_URL` to `OLLAMA_CHAT_TTS_URL` to match the actual env var name
|
|
87
|
+
in `oc.rb`.
|
|
88
|
+
* Wrapped `@prefix` with `Regexp.quote()` in `RedisCache#unpre` to ensure the
|
|
89
|
+
prefix is always matched as a literal string.
|
|
90
|
+
* Fixed typos in height validation error message.
|
|
91
|
+
|
|
92
|
+
### Removed
|
|
93
|
+
* `context_spook` from development dependencies in `Rakefile` and
|
|
94
|
+
`ollama_chat.gemspec`.
|
|
95
|
+
* The `-f` flag from the `/report` command in `commands.rb`.
|
|
96
|
+
|
|
3
97
|
## 2026-09-25 v0.0.122
|
|
4
98
|
|
|
5
99
|
## Features
|
data/README.md
CHANGED
|
@@ -62,7 +62,7 @@ The following environment variables can be used to configure behavior:
|
|
|
62
62
|
- `OLLAMA_URL` - Base URL for Ollama server (default: `http://localhost:11434`)
|
|
63
63
|
- `OLLAMA_HOST` - Base hostname for Ollama server (default: `localhost:11434`)
|
|
64
64
|
- `OLLAMA_SEARXNG_URL` - SearxNG search endpoint URL
|
|
65
|
-
- `
|
|
65
|
+
- `OLLAMA_CHAT_TTS_URL` - Base URL for the [audio.cpp](https://github.com/0xshug0/audio.cpp) TTS server (default: `http://localhost:8880`)
|
|
66
66
|
|
|
67
67
|
#### Chat Settings
|
|
68
68
|
- `OLLAMA_CHAT_MODEL` - Default model to use (e.g., `llama3.1`)
|
|
@@ -75,6 +75,19 @@ The following environment variables can be used to configure behavior:
|
|
|
75
75
|
- `OLLAMA_CHAT_LOG_DATABASE` - Database log file path (default: `$XDG_STATE_HOME/database.log`)
|
|
76
76
|
- `OLLAMA_CHAT_LOG_TAIL_LINES` - Max lines to retain in log files (default: `10000`)
|
|
77
77
|
|
|
78
|
+
#### Speech Services (ASR)
|
|
79
|
+
- `OLLAMA_CHAT_ASR_URL` - Base URL for the ASR (Speech-to-Text) service (default: `http://localhost:8880`)
|
|
80
|
+
- `OLLAMA_CHAT_ASR_CONVERT_COMMAND` - Shell command template to convert video to 16 kHz mono PCM WAV; use `%{input}` / `%{output}` as placeholders (default: `ffmpeg -y -i %{input} -vn -acodec pcm_s16le -ar 16000 -ac 1 %{output}`)
|
|
81
|
+
- `OLLAMA_CHAT_ASR_MODEL` - ASR model identifier (default: `qwen3-asr-1.7b`)
|
|
82
|
+
|
|
83
|
+
#### Audio Playback
|
|
84
|
+
- `OLLAMA_CHAT_AUDIO_PLAYER_CONFIG` - JSON object with `command`, `frequency`, `bits`, `pause` keys controlling the ffplay-based TTS audio player
|
|
85
|
+
|
|
86
|
+
#### Invidious (YouTube Proxy)
|
|
87
|
+
- `OLLAMA_CHAT_INVIDIOUS_URL` - Base URL for an Invidious instance
|
|
88
|
+
- `OLLAMA_CHAT_INVIDIOUS_COMPANION_KEY` - Bearer token for the Invidious companion player API (required when `URL` is set)
|
|
89
|
+
- `OLLAMA_CHAT_INVIDIOUS_CAPTION_LANGUAGES` - JSON array of language-code regexes for caption selection priority (default: `["\\Aen\\z","\\Aen-","\\Ade\\z","\\Ade-"]`)
|
|
90
|
+
|
|
78
91
|
#### Tool Configuration
|
|
79
92
|
- `OLLAMA_CHAT_TOOLS_TEST_RUNNER` - Configured test runner for `run_tests` (default: `rspec`)
|
|
80
93
|
- `OLLAMA_CHAT_TOOLS_CTAGS_TOOL` - Path to the ctags tool
|
|
@@ -243,14 +256,57 @@ switch. The profile system allows you to manage "Live" vs "Saved" settings:
|
|
|
243
256
|
"bake" those live settings into a permanent profile using `options from
|
|
244
257
|
session`.
|
|
245
258
|
|
|
246
|
-
#### 4. Conversation Archiving (`/
|
|
259
|
+
#### 4. Conversation Archiving (`/conversation summarize`)
|
|
247
260
|
|
|
248
261
|
Turn your long-form brainstorming sessions into structured documents. The
|
|
249
|
-
`/
|
|
250
|
-
summary.
|
|
262
|
+
`/conversation summarize` command distills an entire conversation into a
|
|
263
|
+
concise summary, displayed in the pager first, then optionally saved.
|
|
251
264
|
* **Quick View**: Use `-s` for a one-sentence executive summary.
|
|
252
|
-
* **Archiving**:
|
|
253
|
-
Markdown file, creating an automatic journal
|
|
265
|
+
* **Archiving**: After the summary is displayed, you are prompted for a
|
|
266
|
+
filename to save it as a Markdown file, creating an automatic journal
|
|
267
|
+
of your project's evolution.
|
|
268
|
+
|
|
269
|
+
#### 5. Context Compaction (`/conversation compact`)
|
|
270
|
+
|
|
271
|
+
Long sessions inevitably fill up the model's context window. The
|
|
272
|
+
`/conversation compact` command summarizes older messages into a single
|
|
273
|
+
compact summary while preserving recent exchanges, freeing up space for
|
|
274
|
+
continued work.
|
|
275
|
+
|
|
276
|
+
* **Token-aware**: The keep-recent budget is derived from the active
|
|
277
|
+
model's context length, so it adapts automatically.
|
|
278
|
+
* **Safe & retryable**: If the LLM summarization fails, the message list
|
|
279
|
+
is left untouched and you can simply retry.
|
|
280
|
+
* **Visible metrics**: After compaction, a report shows summarized
|
|
281
|
+
message count, summary size, and context usage before/after.
|
|
282
|
+
* **Iterative**: Repeated compactions merge into the existing summary
|
|
283
|
+
rather than stacking multiple summary messages.
|
|
284
|
+
|
|
285
|
+
Run it whenever context usage climbs into the red zone (visible in the
|
|
286
|
+
runtime info gauge) — the model stays sharp and the conversation keeps
|
|
287
|
+
flowing.
|
|
288
|
+
|
|
289
|
+
If compaction alone isn't enough, a practical escalation ladder:
|
|
290
|
+
|
|
291
|
+
1. **`/conversation compact`** — summarize old messages, keep recent tail.
|
|
292
|
+
Try this first; it's the least destructive.
|
|
293
|
+
2. **`/conversation report`** → **`/clear`** → **`/input path
|
|
294
|
+
standup.md`** — generate a standup-style report, save it, clear
|
|
295
|
+
the messages, then feed the report back as context. Do this
|
|
296
|
+
before `clean`, because `clean` strips the tool output and
|
|
297
|
+
thinking that make a good report.
|
|
298
|
+
3. **`/conversation clean`** — strips tool results, images, and
|
|
299
|
+
thinking content from all messages. More radical, but the
|
|
300
|
+
conversation structure and text remain intact. The emergency
|
|
301
|
+
exit: if context is so stuffed that even a report can't fit,
|
|
302
|
+
`clean` carves out enough room for anything to work again.
|
|
303
|
+
|
|
304
|
+
#### 6. Conversation Reports (`/conversation report`)
|
|
305
|
+
|
|
306
|
+
Generate a structured report from your conversation using configurable
|
|
307
|
+
prompt templates. The report is displayed in the pager first, then
|
|
308
|
+
optionally saved to a file. Particularly useful for daily standup summaries
|
|
309
|
+
— run it at the end of the day and save the output for your team sync.
|
|
254
310
|
|
|
255
311
|
### Using a Persona
|
|
256
312
|
|
|
@@ -467,12 +523,12 @@ context, manipulate files, and retrieve external information.
|
|
|
467
523
|
|
|
468
524
|
| Category | Tools | Description |
|
|
469
525
|
| :--- | :--- | :--- |
|
|
470
|
-
| **Filesystem** | `read_file`, `write_file`, `patch_file`, `delete_file`, `move_file`, `directory_structure`, `execute_grep` | Read, write, and search files within allowed directories. |
|
|
526
|
+
| **Filesystem** | `read_file`, `write_file`, `patch_file`, `delete_file`, `move_file`, `directory_structure`, `execute_grep`, `execute_shell` | Read, write, and search files within allowed directories; run shell commands as a last resort. |
|
|
471
527
|
| **Ruby/Dev** | `resolve_tag`, `execute_ri`, `gem_path_lookup`, `run_tests`, `eval_ruby` | Introspect Ruby code, check documentation, and run test suites. |
|
|
472
|
-
| **Web/External** | `search_web`, `get_url`, `browse`, `get_rfc`, `get_cve`, `get_endoflife`, `get_ghr`, `get_jira_issue` | Access the internet, fetch specific URLs, and look up technical standards
|
|
528
|
+
| **Web/External** | `search_web`, `get_url`, `browse`, `get_rfc`, `get_cve`, `get_endoflife`, `get_ghr`, `get_jira_issue`, `execute_jira_twg` | Access the internet, fetch specific URLs, and look up technical standards; run Jira CLI queries via `twg`. |
|
|
473
529
|
| **System/Util** | `get_time`, `get_location`, `get_current_weather`, `generate_password`, `compute_bmi`, `roll_dice` | General utility functions for time, location, and simple calculations. |
|
|
474
530
|
| **Editor/Clip** | `copy_to_clipboard`, `paste_from_clipboard`, `paste_into_editor`, `open_file_in_editor` | Bridge the gap between the chat and the system clipboard or editor. |
|
|
475
|
-
| **Knowledge** | `search_knowledge`, `file_context` | Semantic search for specific snippets
|
|
531
|
+
| **Knowledge** | `search_knowledge`, `file_context`, `lookup_group` | Semantic search for specific snippets, broad retrieval of structured project context, or retrieving prior message groups by UUID. |
|
|
476
532
|
| **Multimodal** | `generate_image` | Generate images via a local ComfyUI server. |
|
|
477
533
|
|
|
478
534
|
***Note on Knowledge Tools**: Use `search_knowledge` for precise,
|
data/Rakefile
CHANGED
data/lib/ollama_chat/asr.rb
CHANGED
|
@@ -99,10 +99,10 @@ module OllamaChat
|
|
|
99
99
|
body << Excon::CR_NL
|
|
100
100
|
body << "--#{boundary}--" << Excon::CR_NL
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
{
|
|
103
103
|
headers: { 'Content-Type' => %{multipart/form-data; boundary="#{boundary}"} },
|
|
104
104
|
expects: 200,
|
|
105
|
-
body
|
|
105
|
+
body: ,
|
|
106
106
|
}
|
|
107
107
|
end
|
|
108
108
|
end
|
data/lib/ollama_chat/commands.rb
CHANGED
|
@@ -374,15 +374,15 @@ module OllamaChat::Commands
|
|
|
374
374
|
|
|
375
375
|
command(
|
|
376
376
|
name: :conversation,
|
|
377
|
-
regexp: %r(^/conversation\s+(clean|compact|save|load|summarize|report)((?:\s+-
|
|
377
|
+
regexp: %r(^/conversation\s+(clean|compact|save|load|summarize|report)((?:\s+-[sc])*)(?:\s+([^-].*\.jsonl?))?$),
|
|
378
378
|
complete: [ 'conversation', %w[ save load clean compact summarize report ] ],
|
|
379
|
-
options: '[-s|-
|
|
379
|
+
options: '[-s|-c] [FILENAME]',
|
|
380
380
|
help: <<~EOT
|
|
381
381
|
💾 Manage conversation content:
|
|
382
382
|
- save/load: Export/import as .json or .jsonl
|
|
383
383
|
- clean: Remove tool content, images, thinking
|
|
384
384
|
- compact: Summarize old messages, keep recent
|
|
385
|
-
- summarize: Per-message narrative (-s sentence
|
|
385
|
+
- summarize: Per-message narrative (-s sentence)
|
|
386
386
|
- report: Generate a session report document
|
|
387
387
|
EOT
|
|
388
388
|
) do |subcommand,opts,path|
|
|
@@ -420,11 +420,10 @@ module OllamaChat::Commands
|
|
|
420
420
|
STDOUT.puts 'Cancelled.'
|
|
421
421
|
end
|
|
422
422
|
when 'summarize'
|
|
423
|
-
opts = go_command('
|
|
424
|
-
summarize_conversation(
|
|
423
|
+
opts = go_command('s', opts)
|
|
424
|
+
summarize_conversation(sentence: opts[?s])
|
|
425
425
|
when 'report'
|
|
426
|
-
|
|
427
|
-
report_conversation(save: opts[?f])
|
|
426
|
+
report_conversation
|
|
428
427
|
end
|
|
429
428
|
:next
|
|
430
429
|
end
|
|
@@ -26,12 +26,13 @@ module OllamaChat::Conversation
|
|
|
26
26
|
# @example Save conversation with explicit filename
|
|
27
27
|
# chat.save_conversation('conversations/2023-10-15_my_session.json')
|
|
28
28
|
def save_conversation(filename, clean: false)
|
|
29
|
+
cleaned = 'cleaned ' if clean
|
|
29
30
|
filename = Pathname.new(filename)
|
|
30
31
|
should_overwrite?(filename) or return
|
|
31
32
|
if messages.save_conversation(filename, messages: clean ? messages.clean_messages : messages.messages)
|
|
32
|
-
STDOUT.puts "Saved conversation to #{filename.to_s.inspect}."
|
|
33
|
+
STDOUT.puts "Saved #{cleaned}conversation to #{filename.to_s.inspect}."
|
|
33
34
|
else
|
|
34
|
-
STDERR.puts "Saving conversation to #{filename.to_s.inspect} failed."
|
|
35
|
+
STDERR.puts "Saving #{cleaned}conversation to #{filename.to_s.inspect} failed."
|
|
35
36
|
end
|
|
36
37
|
end
|
|
37
38
|
|
|
@@ -49,18 +49,29 @@ module OllamaChat::KramdownANSI
|
|
|
49
49
|
retry
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
# The kramdown_markdown_remove method strips
|
|
53
|
-
#
|
|
54
|
-
#
|
|
52
|
+
# The kramdown_markdown_remove method strips markdown formatting, emoji,
|
|
53
|
+
# ANSI escape sequences, and box-drawing characters from content, yielding
|
|
54
|
+
# plain text suitable for TTS playback.
|
|
55
55
|
#
|
|
56
|
-
# @param content [ String, nil ] the
|
|
57
|
-
# If nil, returns an empty string.
|
|
56
|
+
# @param content [ String, nil ] the content to strip.
|
|
57
|
+
# If nil or empty, returns an empty string.
|
|
58
|
+
# @param markdown [ Boolean] if true (default), runs the full kramdown
|
|
59
|
+
# ANSI parse before stripping; if false, only removes emoji, ANSI,
|
|
60
|
+
# and box-drawing characters without markdown rendering.
|
|
58
61
|
#
|
|
59
|
-
# @return [ String ] the content with all markdown and
|
|
60
|
-
# formatting removed, suitable for TTS playback
|
|
61
|
-
def kramdown_markdown_remove(content)
|
|
62
|
-
content
|
|
63
|
-
content.
|
|
64
|
-
|
|
62
|
+
# @return [ String ] the content with all markdown, ANSI, emoji, and
|
|
63
|
+
# box-drawing formatting removed, suitable for TTS playback
|
|
64
|
+
def kramdown_markdown_remove(content, markdown: true)
|
|
65
|
+
content.full? or return ''
|
|
66
|
+
content = content.gsub(/\p{Extended_Pictographic}/, '').full? or return ''
|
|
67
|
+
if markdown
|
|
68
|
+
content = kramdown_ansi_parse(content).full? or return ''
|
|
69
|
+
end
|
|
70
|
+
content = OllamaChat::Utils::StripANSI.strip_ansi(content)
|
|
71
|
+
# Remove box-drawing characters (U+2500..U+257F) that kramdown uses
|
|
72
|
+
# for table borders/separators — TTS engines stammer on these.
|
|
73
|
+
content.gsub(/[\u2500-\u257F]/, ' ')
|
|
74
|
+
.gsub(/\s{2,}/, ' ')
|
|
75
|
+
.strip
|
|
65
76
|
end
|
|
66
77
|
end
|
|
@@ -384,34 +384,27 @@ module OllamaChat::SessionManagement
|
|
|
384
384
|
contents * "\n\n"
|
|
385
385
|
end
|
|
386
386
|
|
|
387
|
-
# Summarizes the conversation and displays
|
|
387
|
+
# Summarizes the conversation and displays / saves the result.
|
|
388
388
|
#
|
|
389
389
|
# @param sentence [Boolean] summarize each message in one sentence (default: false)
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
390
|
+
def summarize_conversation(sentence: false)
|
|
391
|
+
summary = summarize_session(sentence:) do |content|
|
|
392
|
+
infobar.puts kramdown_ansi_parse(content) << ?\n
|
|
393
|
+
end
|
|
394
|
+
if summary.full?
|
|
395
|
+
use_pager do |output|
|
|
396
|
+
output.puts kramdown_ansi_parse(summary)
|
|
397
397
|
end
|
|
398
|
-
if
|
|
398
|
+
if filename = ask_for_filename?(action: 'for summarization') and
|
|
399
|
+
should_overwrite?(filename)
|
|
400
|
+
then
|
|
399
401
|
filename.write(summary)
|
|
400
402
|
STDOUT.puts "File successfully written."
|
|
401
403
|
else
|
|
402
|
-
|
|
404
|
+
STDOUT.puts "Cancelled."
|
|
403
405
|
end
|
|
404
406
|
else
|
|
405
|
-
|
|
406
|
-
infobar.puts kramdown_ansi_parse(content) << ?\n
|
|
407
|
-
end
|
|
408
|
-
if summary.full?
|
|
409
|
-
use_pager do |output|
|
|
410
|
-
output.puts kramdown_ansi_parse(summary)
|
|
411
|
-
end
|
|
412
|
-
else
|
|
413
|
-
STDERR.puts "Nothing to summarize!"
|
|
414
|
-
end
|
|
407
|
+
STDOUT.puts "Nothing to summarize!"
|
|
415
408
|
end
|
|
416
409
|
end
|
|
417
410
|
|
|
@@ -425,7 +418,7 @@ module OllamaChat::SessionManagement
|
|
|
425
418
|
#
|
|
426
419
|
# @param name [String, nil] specific template name (skips chooser)
|
|
427
420
|
# @return [String, nil] the report or nil if empty
|
|
428
|
-
def
|
|
421
|
+
def generate_conversation_report(name: nil)
|
|
429
422
|
content = messages.compacted_messages.inject('') do |c, message|
|
|
430
423
|
message.content.present? or next c
|
|
431
424
|
sender = sender_name_displayed(message)
|
|
@@ -446,7 +439,7 @@ module OllamaChat::SessionManagement
|
|
|
446
439
|
system = prompt(:report, context: 'system').to_s
|
|
447
440
|
|
|
448
441
|
Infobar.busy(
|
|
449
|
-
label: 'Generating
|
|
442
|
+
label: 'Generating conversation report…',
|
|
450
443
|
frames: :braille7,
|
|
451
444
|
output: STDOUT,
|
|
452
445
|
) do
|
|
@@ -454,30 +447,26 @@ module OllamaChat::SessionManagement
|
|
|
454
447
|
end
|
|
455
448
|
end
|
|
456
449
|
|
|
457
|
-
# Generates a report and displays
|
|
450
|
+
# Generates a report and displays / saves the result.
|
|
458
451
|
#
|
|
459
452
|
# @param name [String, nil] specific report template name (skips chooser)
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
if
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
if
|
|
453
|
+
def report_conversation(name: nil)
|
|
454
|
+
result = generate_conversation_report(name:)
|
|
455
|
+
if result.full?
|
|
456
|
+
use_pager do |output|
|
|
457
|
+
output.puts kramdown_ansi_parse(result)
|
|
458
|
+
end
|
|
459
|
+
if filename = ask_for_filename?(action: 'for report') and
|
|
460
|
+
should_overwrite?(filename)
|
|
461
|
+
then
|
|
467
462
|
filename.write(result)
|
|
468
463
|
STDOUT.puts "File successfully written."
|
|
469
464
|
else
|
|
470
|
-
|
|
465
|
+
STDOUT.puts "Cancelled."
|
|
471
466
|
end
|
|
472
467
|
else
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
use_pager do |output|
|
|
476
|
-
output.puts kramdown_ansi_parse(result)
|
|
477
|
-
end
|
|
478
|
-
else
|
|
479
|
-
STDERR.puts "Nothing to report!"
|
|
480
|
-
end
|
|
468
|
+
STDOUT.puts "Nothing to report!"
|
|
469
|
+
return
|
|
481
470
|
end
|
|
482
471
|
end
|
|
483
472
|
|
|
@@ -82,8 +82,8 @@ class OllamaChat::Tools::ComputeBMI
|
|
|
82
82
|
units = 'SI'
|
|
83
83
|
end
|
|
84
84
|
|
|
85
|
-
raise OllamaChat::ToolFunctionArgumentError, 'Height must be greater than zero and in
|
|
86
|
-
raise OllamaChat::ToolFunctionArgumentError, '
|
|
85
|
+
raise OllamaChat::ToolFunctionArgumentError, 'Height must be greater than zero and in meter/feet' if height <= 0
|
|
86
|
+
raise OllamaChat::ToolFunctionArgumentError, 'Height must be less than 3m and in meter/feet' if height > 3
|
|
87
87
|
|
|
88
88
|
bmi = ( weight / height**2 ).round(2)
|
|
89
89
|
category = calculate_category(bmi)
|
|
@@ -125,6 +125,10 @@ class OllamaChat::Tools::ExecuteGrep
|
|
|
125
125
|
# Evaluates a template string using the provided configuration and
|
|
126
126
|
# parameters.
|
|
127
127
|
#
|
|
128
|
+
# The `cmd` config value is a Ruby string template — its `#{...}`
|
|
129
|
+
# interpolations are resolved against the local parameters via `eval`,
|
|
130
|
+
# so all arguments below serve as the interpolation context.
|
|
131
|
+
#
|
|
128
132
|
# @param config [Object] the configuration object containing tool settings
|
|
129
133
|
# @param pattern [String] the regex pattern to search for
|
|
130
134
|
# @param path [String] the file or directory path to search in
|
data/lib/ollama_chat/tts.rb
CHANGED
|
@@ -132,7 +132,6 @@ class OllamaChat::TTS
|
|
|
132
132
|
size = match[0].size
|
|
133
133
|
|
|
134
134
|
chunk = @buffer.slice!(0, size).full?(:strip) or next
|
|
135
|
-
chunk = kramdown_markdown_remove(chunk) if @chat.markdown.on?
|
|
136
135
|
enqueue_tts(chunk)
|
|
137
136
|
end
|
|
138
137
|
end
|
|
@@ -147,6 +146,7 @@ class OllamaChat::TTS
|
|
|
147
146
|
#
|
|
148
147
|
# @return [Thread] the spawned TTS fetch thread
|
|
149
148
|
def enqueue_tts(block)
|
|
149
|
+
block = kramdown_markdown_remove(block, markdown: @chat.markdown.on?)
|
|
150
150
|
thread_id = @id_mutex.synchronize { @next_id += 1 }
|
|
151
151
|
@chat.log(:info, "TTS: Enqueueing block for synthesis", data: { thread_id:, block: })
|
|
152
152
|
@id_mutex.synchronize { @enqueued_count += 1 }
|
data/lib/ollama_chat/version.rb
CHANGED
data/ollama_chat.gemspec
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# stub: ollama_chat 0.0.
|
|
2
|
+
# stub: ollama_chat 0.0.123 ruby lib
|
|
3
3
|
|
|
4
4
|
Gem::Specification.new do |s|
|
|
5
5
|
s.name = "ollama_chat".freeze
|
|
6
|
-
s.version = "0.0.
|
|
6
|
+
s.version = "0.0.123".freeze
|
|
7
7
|
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
9
9
|
s.require_paths = ["lib".freeze]
|
|
@@ -31,7 +31,6 @@ Gem::Specification.new do |s|
|
|
|
31
31
|
s.add_development_dependency(%q<webmock>.freeze, [">= 0".freeze])
|
|
32
32
|
s.add_development_dependency(%q<debug>.freeze, [">= 0".freeze])
|
|
33
33
|
s.add_development_dependency(%q<simplecov>.freeze, [">= 0".freeze])
|
|
34
|
-
s.add_development_dependency(%q<context_spook>.freeze, [">= 0".freeze])
|
|
35
34
|
s.add_development_dependency(%q<utils>.freeze, [">= 0".freeze])
|
|
36
35
|
s.add_runtime_dependency(%q<excon>.freeze, ["~> 1.0".freeze])
|
|
37
36
|
s.add_runtime_dependency(%q<ollama-ruby>.freeze, ["~> 1.23".freeze])
|
|
@@ -23,7 +23,7 @@ describe OllamaChat::ASR do
|
|
|
23
23
|
.with(
|
|
24
24
|
:post,
|
|
25
25
|
'http://localhost:8880/v1/audio/transcriptions',
|
|
26
|
-
hash_including(
|
|
26
|
+
hash_including(body: kind_of(String))
|
|
27
27
|
).and_yield(double(body: '{"text": "Hello Florian"}'))
|
|
28
28
|
|
|
29
29
|
result = described_class.transcribe(audio_io, chat:)
|
|
@@ -35,7 +35,7 @@ describe OllamaChat::ASR do
|
|
|
35
35
|
.with(
|
|
36
36
|
:post,
|
|
37
37
|
'http://localhost:8880/v1/audio/transcriptions',
|
|
38
|
-
hash_including(
|
|
38
|
+
hash_including(body: kind_of(String))
|
|
39
39
|
).and_yield(double(body: '{"text": "Hallo"}'))
|
|
40
40
|
|
|
41
41
|
described_class.transcribe(audio_io, chat:, language: 'de')
|
|
@@ -675,33 +675,20 @@ describe OllamaChat::Commands, protect_env: true do
|
|
|
675
675
|
|
|
676
676
|
it 'returns :next when input is "/conversation summarize"' do
|
|
677
677
|
expect(chat).to receive(:summarize_conversation)
|
|
678
|
-
.with(
|
|
678
|
+
.with(sentence: false)
|
|
679
679
|
expect(chat.handle_input("/conversation summarize")).to eq :next
|
|
680
680
|
end
|
|
681
681
|
|
|
682
682
|
it 'returns :next when input is "/conversation summarize -s"' do
|
|
683
683
|
expect(chat).to receive(:summarize_conversation)
|
|
684
|
-
.with(
|
|
684
|
+
.with(sentence: 1)
|
|
685
685
|
expect(chat.handle_input("/conversation summarize -s")).to eq :next
|
|
686
686
|
end
|
|
687
687
|
|
|
688
|
-
it 'returns :next when input is "/conversation summarize -f"' do
|
|
689
|
-
expect(chat).to receive(:summarize_conversation)
|
|
690
|
-
.with(save: 1, sentence: false)
|
|
691
|
-
expect(chat.handle_input("/conversation summarize -f")).to eq :next
|
|
692
|
-
end
|
|
693
|
-
|
|
694
688
|
it 'returns :next when input is "/conversation report"' do
|
|
695
689
|
expect(chat).to receive(:report_conversation)
|
|
696
|
-
.with(save: false)
|
|
697
690
|
expect(chat.handle_input("/conversation report")).to eq :next
|
|
698
691
|
end
|
|
699
|
-
|
|
700
|
-
it 'returns :next when input is "/conversation report -f"' do
|
|
701
|
-
expect(chat).to receive(:report_conversation).
|
|
702
|
-
with(save: 1)
|
|
703
|
-
expect(chat.handle_input("/conversation report -f")).to eq :next
|
|
704
|
-
end
|
|
705
692
|
end
|
|
706
693
|
|
|
707
694
|
describe 'tools' do
|
|
@@ -20,7 +20,7 @@ describe OllamaChat::Conversation do
|
|
|
20
20
|
.with(Pathname.new('./new_chat.jsonl'), messages: chat.messages.clean_messages)
|
|
21
21
|
.and_return(true)
|
|
22
22
|
expect(STDOUT).to receive(:puts)
|
|
23
|
-
.with('Saved conversation to "./new_chat.jsonl".')
|
|
23
|
+
.with('Saved cleaned conversation to "./new_chat.jsonl".')
|
|
24
24
|
chat.save_conversation('./new_chat.jsonl', clean: true)
|
|
25
25
|
end
|
|
26
26
|
|
|
@@ -40,4 +40,64 @@ describe OllamaChat::KramdownANSI do
|
|
|
40
40
|
expect(chat.kramdown_ansi_parse(nil)).to eq ''
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
|
+
|
|
44
|
+
describe '#kramdown_markdown_remove' do
|
|
45
|
+
it 'returns empty string for nil' do
|
|
46
|
+
expect(chat.kramdown_markdown_remove(nil)).to eq ''
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'returns empty string for empty string' do
|
|
50
|
+
expect(chat.kramdown_markdown_remove('')).to eq ''
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'removes table separator rows' do
|
|
54
|
+
input = "Name | Age\n------|-----\nFoo | 42"
|
|
55
|
+
result = chat.kramdown_markdown_remove(input)
|
|
56
|
+
expect(result).not_to include('-')
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'replaces box-drawing characters from rendered tables' do
|
|
60
|
+
input = "| Name | Age |\n|------|-----|\n| Foo | 42 |"
|
|
61
|
+
result = chat.kramdown_markdown_remove(input)
|
|
62
|
+
expect(result).not_to include("│")
|
|
63
|
+
expect(result).not_to include("╭")
|
|
64
|
+
expect(result).to include('Name')
|
|
65
|
+
expect(result).to include('Foo')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'preserves ASCII pipes in non-table lines (code, formulas)' do
|
|
69
|
+
input = 'look at this shell command `ls | grep foo`'
|
|
70
|
+
result = chat.kramdown_markdown_remove(input)
|
|
71
|
+
expect(result).to include('|')
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'collapses multiple spaces in table rows' do
|
|
75
|
+
input = '| Name | Age |'
|
|
76
|
+
result = chat.kramdown_markdown_remove(input)
|
|
77
|
+
expect(result).not_to match(/ {2,}/)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'strips bold and other markdown formatting' do
|
|
81
|
+
input = '**hello** world'
|
|
82
|
+
result = chat.kramdown_markdown_remove(input)
|
|
83
|
+
expect(result).to eq 'hello world'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it 'removes emoji before processing' do
|
|
87
|
+
input = 'what is this? 🍓'
|
|
88
|
+
result = chat.kramdown_markdown_remove(input)
|
|
89
|
+
expect(result).to eq 'what is this?'
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'returns empty string when only emoji are present' do
|
|
93
|
+
expect(chat.kramdown_markdown_remove('🍓✨')).to eq ''
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'skips kramdown parse when markdown: false' do
|
|
97
|
+
input = '**bold** text'
|
|
98
|
+
expect(chat).not_to receive(:kramdown_ansi_parse)
|
|
99
|
+
result = chat.kramdown_markdown_remove(input, markdown: false)
|
|
100
|
+
expect(result).to include('**bold**')
|
|
101
|
+
end
|
|
102
|
+
end
|
|
43
103
|
end
|
|
@@ -278,6 +278,7 @@ describe OllamaChat::SessionManagement do
|
|
|
278
278
|
|
|
279
279
|
it 'returns nil if the user provides an empty string (cancel)' do
|
|
280
280
|
expect(chat).to receive(:ask?).and_return('')
|
|
281
|
+
expect(STDOUT).to receive(:puts).with('Cancelled.')
|
|
281
282
|
expect(chat.determine_valid_new_name_for_session('to create')).to be_nil
|
|
282
283
|
end
|
|
283
284
|
end
|
|
@@ -321,27 +322,30 @@ describe OllamaChat::SessionManagement do
|
|
|
321
322
|
end
|
|
322
323
|
|
|
323
324
|
describe '#summarize_conversation' do
|
|
324
|
-
it 'displays summary in pager
|
|
325
|
+
it 'displays summary in pager and offers save' do
|
|
325
326
|
chat.messages << OllamaChat::Message.new(role: 'user', content: 'hello')
|
|
326
327
|
expect(chat).to receive(:summarize_session).and_return('# Summary content')
|
|
327
328
|
expect(chat).to receive(:use_pager)
|
|
329
|
+
expect(chat).to receive(:ask_for_filename?).and_return(nil)
|
|
330
|
+
expect(STDOUT).to receive(:puts).with('Cancelled.')
|
|
328
331
|
chat.summarize_conversation
|
|
329
332
|
end
|
|
330
333
|
|
|
331
334
|
it 'reports nothing when no messages' do
|
|
332
335
|
expect(chat).to receive(:summarize_session).and_return(nil)
|
|
333
|
-
expect(
|
|
336
|
+
expect(STDOUT).to receive(:puts).with('Nothing to summarize!')
|
|
334
337
|
chat.summarize_conversation
|
|
335
338
|
end
|
|
336
339
|
|
|
337
|
-
it 'saves summary to file when
|
|
340
|
+
it 'saves summary to file when user provides a filename' do
|
|
338
341
|
chat.messages << OllamaChat::Message.new(role: 'user', content: 'hello')
|
|
339
342
|
tmpfile = Pathname.new(File.join(Dir.tmpdir, "summ_#{$$}_test.md"))
|
|
343
|
+
expect(chat).to receive(:summarize_session).and_return('# Summary content')
|
|
344
|
+
expect(chat).to receive(:use_pager)
|
|
340
345
|
expect(chat).to receive(:ask_for_filename?).and_return(tmpfile)
|
|
341
346
|
expect(chat).to receive(:should_overwrite?).and_return(true)
|
|
342
|
-
expect(chat).to receive(:summarize_session).and_return('# Summary content')
|
|
343
347
|
expect(STDOUT).to receive(:puts).with('File successfully written.')
|
|
344
|
-
chat.summarize_conversation
|
|
348
|
+
chat.summarize_conversation
|
|
345
349
|
expect(tmpfile.exist?).to be_truthy
|
|
346
350
|
expect(tmpfile.read).to include('Summary content')
|
|
347
351
|
ensure
|
|
@@ -349,20 +353,20 @@ describe OllamaChat::SessionManagement do
|
|
|
349
353
|
end
|
|
350
354
|
end
|
|
351
355
|
|
|
352
|
-
describe '#
|
|
356
|
+
describe '#generate_conversation_report' do
|
|
353
357
|
it 'generates a report from compacted messages' do
|
|
354
358
|
chat.messages << OllamaChat::Message.new(role: 'user', content: 'hello world')
|
|
355
359
|
expect(chat).to receive(:sender_name_displayed).and_return('User')
|
|
356
360
|
expect(chat).to receive(:choose_prompt).and_return(double(to_s: '%{content}'))
|
|
357
361
|
expect(chat).to receive(:generate).and_return('Generated report')
|
|
358
362
|
|
|
359
|
-
result = chat.
|
|
363
|
+
result = chat.generate_conversation_report
|
|
360
364
|
expect(result).to eq('Generated report')
|
|
361
365
|
end
|
|
362
366
|
|
|
363
367
|
it 'returns nil when no messages have content' do
|
|
364
368
|
expect(chat.messages).to receive(:compacted_messages).and_return([])
|
|
365
|
-
expect(chat.
|
|
369
|
+
expect(chat.generate_conversation_report).to be_nil
|
|
366
370
|
end
|
|
367
371
|
|
|
368
372
|
it 'uses named prompt when name is provided' do
|
|
@@ -373,21 +377,23 @@ describe OllamaChat::SessionManagement do
|
|
|
373
377
|
expect(chat).to receive(:prompt).with(:report, context: 'system')
|
|
374
378
|
.and_return(double(to_s: '%{content}'))
|
|
375
379
|
expect(chat).to receive(:generate).and_return('Brief')
|
|
376
|
-
expect(chat.
|
|
380
|
+
expect(chat.generate_conversation_report(name: 'coding_brief')).to eq('Brief')
|
|
377
381
|
end
|
|
378
382
|
end
|
|
379
383
|
|
|
380
384
|
describe '#report_conversation' do
|
|
381
385
|
it 'displays report in pager when not saving' do
|
|
382
386
|
chat.messages << OllamaChat::Message.new(role: 'user', content: 'hello')
|
|
383
|
-
expect(chat).to receive(:
|
|
387
|
+
expect(chat).to receive(:generate_conversation_report).and_return('# Report content')
|
|
384
388
|
expect(chat).to receive(:use_pager)
|
|
389
|
+
expect(chat).to receive(:ask_for_filename?).and_return(nil)
|
|
390
|
+
expect(STDOUT).to receive(:puts).with('Cancelled.')
|
|
385
391
|
chat.report_conversation
|
|
386
392
|
end
|
|
387
393
|
|
|
388
394
|
it 'reports nothing when no content' do
|
|
389
|
-
expect(chat).to receive(:
|
|
390
|
-
expect(
|
|
395
|
+
expect(chat).to receive(:generate_conversation_report).and_return(nil)
|
|
396
|
+
expect(STDOUT).to receive(:puts).with('Nothing to report!')
|
|
391
397
|
chat.report_conversation
|
|
392
398
|
end
|
|
393
399
|
|
|
@@ -396,9 +402,10 @@ describe OllamaChat::SessionManagement do
|
|
|
396
402
|
tmpfile = Pathname.new(File.join(Dir.tmpdir, "report_#{$$}_test.md"))
|
|
397
403
|
expect(chat).to receive(:ask_for_filename?).and_return(tmpfile)
|
|
398
404
|
expect(chat).to receive(:should_overwrite?).and_return(true)
|
|
399
|
-
expect(chat).to receive(:
|
|
405
|
+
expect(chat).to receive(:generate_conversation_report).and_return('# Report content')
|
|
406
|
+
expect(STDOUT).to receive(:puts).with(/Report content/)
|
|
400
407
|
expect(STDOUT).to receive(:puts).with('File successfully written.')
|
|
401
|
-
chat.report_conversation
|
|
408
|
+
chat.report_conversation
|
|
402
409
|
expect(tmpfile.exist?).to be_truthy
|
|
403
410
|
expect(tmpfile.read).to include('Report content')
|
|
404
411
|
ensure
|
|
@@ -123,7 +123,7 @@ describe OllamaChat::TTS do
|
|
|
123
123
|
|
|
124
124
|
tts.expose(:process_pending_blocks)
|
|
125
125
|
|
|
126
|
-
expect(enqueued).to eq ["first paragraph
|
|
126
|
+
expect(enqueued).to eq ["first paragraph", "second paragraph"]
|
|
127
127
|
expect(tts.instance_variable_get(:@buffer)).to eq 'incomplete'
|
|
128
128
|
end
|
|
129
129
|
|
|
@@ -134,7 +134,7 @@ describe OllamaChat::TTS do
|
|
|
134
134
|
|
|
135
135
|
tts.expose(:process_pending_blocks)
|
|
136
136
|
|
|
137
|
-
expect(enqueued).to eq ["real text
|
|
137
|
+
expect(enqueued).to eq ["real text", "more"]
|
|
138
138
|
expect(tts.instance_variable_get(:@buffer)).to eq ''
|
|
139
139
|
end
|
|
140
140
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ollama_chat
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.123
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Florian Frank
|
|
@@ -107,20 +107,6 @@ dependencies:
|
|
|
107
107
|
- - ">="
|
|
108
108
|
- !ruby/object:Gem::Version
|
|
109
109
|
version: '0'
|
|
110
|
-
- !ruby/object:Gem::Dependency
|
|
111
|
-
name: context_spook
|
|
112
|
-
requirement: !ruby/object:Gem::Requirement
|
|
113
|
-
requirements:
|
|
114
|
-
- - ">="
|
|
115
|
-
- !ruby/object:Gem::Version
|
|
116
|
-
version: '0'
|
|
117
|
-
type: :development
|
|
118
|
-
prerelease: false
|
|
119
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
-
requirements:
|
|
121
|
-
- - ">="
|
|
122
|
-
- !ruby/object:Gem::Version
|
|
123
|
-
version: '0'
|
|
124
110
|
- !ruby/object:Gem::Dependency
|
|
125
111
|
name: utils
|
|
126
112
|
requirement: !ruby/object:Gem::Requirement
|