scout-ai 1.2.3 → 2.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.
Files changed (174) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +138 -50
  3. data/README.md +171 -290
  4. data/Rakefile +17 -1
  5. data/VERSION +1 -1
  6. data/doc/Improvements.md +325 -0
  7. data/doc/StartHere.md +110 -0
  8. data/doc/developer/Architecture.md +126 -0
  9. data/doc/developer/Backends.md +199 -0
  10. data/doc/developer/ChatLifecycle.md +183 -0
  11. data/doc/developer/DelegationInternals.md +295 -0
  12. data/doc/developer/DesignPrinciples.md +245 -0
  13. data/doc/developer/PromptProcessing.md +292 -0
  14. data/doc/developer/Provenance.md +317 -0
  15. data/doc/user/BuildingAgents.md +345 -0
  16. data/doc/user/Cookbook.md +333 -0
  17. data/doc/user/CoreConcepts.md +181 -0
  18. data/doc/user/Delegation.md +191 -0
  19. data/doc/user/GettingStarted.md +159 -0
  20. data/doc/user/ManagingContext.md +163 -0
  21. data/doc/user/MultiAgentWorkflows.md +256 -0
  22. data/doc/user/Python.md +159 -0
  23. data/doc/user/RunningInference.md +200 -0
  24. data/doc/user/ToolCalling.md +193 -0
  25. data/doc/user/WritingChats.md +197 -0
  26. data/lib/scout/llm/agent/chat.rb +61 -11
  27. data/lib/scout/llm/agent/delegate.rb +274 -65
  28. data/lib/scout/llm/agent/iterate.rb +2 -2
  29. data/lib/scout/llm/agent/save.rb +273 -0
  30. data/lib/scout/llm/agent/workflow.rb +164 -0
  31. data/lib/scout/llm/agent.rb +86 -61
  32. data/lib/scout/llm/ask.rb +62 -17
  33. data/lib/scout/llm/backends/anthropic.rb +9 -2
  34. data/lib/scout/llm/backends/bedrock.rb +15 -3
  35. data/lib/scout/llm/backends/default.rb +183 -99
  36. data/lib/scout/llm/backends/glm.rb +58 -0
  37. data/lib/scout/llm/backends/huggingface.rb +196 -26
  38. data/lib/scout/llm/backends/ollama.rb +13 -1
  39. data/lib/scout/llm/backends/openai.rb +0 -2
  40. data/lib/scout/llm/backends/openwebui.rb +20 -13
  41. data/lib/scout/llm/backends/relay.rb +22 -22
  42. data/lib/scout/llm/backends/responses.rb +1 -1
  43. data/lib/scout/llm/chat/agent_meta.rb +264 -0
  44. data/lib/scout/llm/chat/annotation.rb +39 -10
  45. data/lib/scout/llm/chat/parse.rb +28 -6
  46. data/lib/scout/llm/chat/persist.rb +25 -0
  47. data/lib/scout/llm/chat/process/clear.rb +41 -6
  48. data/lib/scout/llm/chat/process/files.rb +21 -6
  49. data/lib/scout/llm/chat/process/meta.rb +421 -34
  50. data/lib/scout/llm/chat/process/options.rb +21 -1
  51. data/lib/scout/llm/chat/process/tools.rb +56 -15
  52. data/lib/scout/llm/chat/process.rb +4 -0
  53. data/lib/scout/llm/chat/prompt/shorten_tools.rb +125 -0
  54. data/lib/scout/llm/chat/prompt/shorten_tools_epoch.rb +365 -0
  55. data/lib/scout/llm/chat/prompt.rb +48 -0
  56. data/lib/scout/llm/chat/provenance.rb +775 -0
  57. data/lib/scout/llm/chat/tool_calls.rb +76 -0
  58. data/lib/scout/llm/chat.rb +18 -2
  59. data/lib/scout/llm/embed.rb +11 -3
  60. data/lib/scout/llm/image.rb +86 -0
  61. data/lib/scout/llm/mcp.rb +10 -2
  62. data/lib/scout/llm/rag.rb +3 -3
  63. data/lib/scout/llm/tools/call.rb +160 -11
  64. data/lib/scout/llm/tools/knowledge_base.rb +1 -1
  65. data/lib/scout/llm/tools/workflow.rb +32 -16
  66. data/lib/scout/model/python/huggingface/causal.rb +23 -5
  67. data/lib/scout/model/python/huggingface.rb +2 -1
  68. data/lib/scout-ai.rb +1 -0
  69. data/python/README.md +197 -14
  70. data/python/scout_ai/huggingface/eval.py +245 -34
  71. data/python/tests/test_huggingface_eval.py +58 -0
  72. data/research/ChatAnalyst-required-changes.md +167 -0
  73. data/research/agent-delegation-analysis.md +810 -0
  74. data/research/agent-meta-provenance-integration-plan.md +622 -0
  75. data/research/agent-workflow-analysis.md +1120 -0
  76. data/research/backends-analysis.md +836 -0
  77. data/research/chat-core-analysis.md +946 -0
  78. data/research/chatanalyst-provenance/00-baseline.md +30 -0
  79. data/research/chatanalyst-provenance/01-repo-map.md +60 -0
  80. data/research/chatanalyst-provenance/02-event-reconstruction.md +55 -0
  81. data/research/chatanalyst-provenance/03-duplication-evidence.md +45 -0
  82. data/research/chatanalyst-provenance/04-tooling-root-cause.md +57 -0
  83. data/research/chatanalyst-provenance/05-fix-plan.md +46 -0
  84. data/research/chatanalyst-provenance/07-critic-review.md +25 -0
  85. data/research/chatanalyst-provenance/final-report.md +45 -0
  86. data/research/chatanalyst-provenance/resumption.md +37 -0
  87. data/research/coding-philosophy-analysis.md +928 -0
  88. data/research/commands-analysis.md +947 -0
  89. data/research/multi-agent-patterns-analysis.md +853 -0
  90. data/research/prompt-strategies-analysis.md +630 -0
  91. data/research/prov-verbosity-fix-notes.md +77 -0
  92. data/research/provenance-analysis.md +469 -0
  93. data/research/provenance-navigation-design.md +640 -0
  94. data/research/synthesis-report.md +487 -0
  95. data/research/tools-system-analysis.md +779 -0
  96. data/scout-ai.gemspec +100 -11
  97. data/scout_commands/agent/ask +13 -3
  98. data/scout_commands/agent/kb +2 -0
  99. data/scout_commands/llm/ask +11 -4
  100. data/scout_commands/llm/md +76 -0
  101. data/scout_commands/llm/process_queries +48 -0
  102. data/scout_commands/llm/prov +602 -0
  103. data/scout_commands/llm/word +71 -0
  104. data/scout_commands/workflow/mcp +43 -0
  105. data/share/word/reference.docx +0 -0
  106. data/test/etc/AI/mock.yaml +11 -0
  107. data/test/fixtures/backends/anthropic.json +19 -0
  108. data/test/fixtures/backends/anthropic_tool_use.json +24 -0
  109. data/test/fixtures/backends/bedrock.json +8 -0
  110. data/test/fixtures/backends/bedrock_embedding.json +3 -0
  111. data/test/fixtures/backends/bedrock_tool_use.json +17 -0
  112. data/test/fixtures/backends/ollama.json +16 -0
  113. data/test/fixtures/backends/ollama_tool_call.json +27 -0
  114. data/test/fixtures/backends/openai_chat.json +21 -0
  115. data/test/fixtures/backends/openai_chat_tool_call.json +31 -0
  116. data/test/fixtures/backends/responses.json +33 -0
  117. data/test/fixtures/backends/responses_tool_call.json +28 -0
  118. data/test/integration/README.md +32 -0
  119. data/test/integration/scout/llm/backends/test_endpoints.rb +34 -0
  120. data/test/integration/scout/llm/backends/test_openwebui.rb +61 -0
  121. data/test/integration/scout/llm/backends/test_relay.rb +52 -0
  122. data/test/integration/scout/llm/test_infrastructure.rb +74 -0
  123. data/test/{scout → integration/scout}/llm/test_mcp.rb +1 -1
  124. data/test/integration/scout/llm/tools/test_mcp.rb +42 -0
  125. data/test/integration/scout/model/test_base.rb +91 -0
  126. data/test/scout/llm/agent/test_chat.rb +8 -2
  127. data/test/scout/llm/agent/test_save.rb +413 -0
  128. data/test/scout/llm/agent/test_workflow.rb +110 -0
  129. data/test/scout/llm/backends/test_anthropic.rb +93 -10
  130. data/test/scout/llm/backends/test_bedrock.rb +118 -2
  131. data/test/scout/llm/backends/test_huggingface.rb +137 -42
  132. data/test/scout/llm/backends/test_ollama.rb +70 -20
  133. data/test/scout/llm/backends/test_openwebui.rb +42 -40
  134. data/test/scout/llm/backends/test_relay.rb +4 -2
  135. data/test/scout/llm/chat/agent_meta_fixtures.rb +131 -0
  136. data/test/scout/llm/chat/process/test_meta.rb +518 -0
  137. data/test/scout/llm/chat/process/test_normalize_usage.rb +183 -0
  138. data/test/scout/llm/chat/test_agent_meta.rb +357 -0
  139. data/test/scout/llm/chat/test_agent_meta_provenance.rb +467 -0
  140. data/test/scout/llm/chat/test_agent_meta_tokens.rb +594 -0
  141. data/test/scout/llm/chat/test_parse.rb +70 -15
  142. data/test/scout/llm/chat/test_prov_cli.rb +274 -0
  143. data/test/scout/llm/chat/test_provenance.rb +240 -0
  144. data/test/scout/llm/chat/test_tool_calls.rb +38 -0
  145. data/test/scout/llm/test_agent.rb +13 -36
  146. data/test/scout/llm/test_ask.rb +75 -52
  147. data/test/scout/llm/test_chat.rb +107 -13
  148. data/test/scout/llm/test_embed.rb +48 -0
  149. data/test/scout/llm/test_rag.rb +23 -16
  150. data/test/scout/llm/test_tools.rb +12 -1
  151. data/test/scout/llm/tools/test_knowledge_base.rb +0 -1
  152. data/test/scout/llm/tools/test_mcp.rb +5 -3
  153. data/test/scout/llm/tools/test_workflow.rb +23 -2
  154. data/test/scout/model/python/huggingface/causal/test_next_token.rb +11 -5
  155. data/test/scout/model/python/huggingface/test_causal.rb +9 -3
  156. data/test/scout/model/python/huggingface/test_classification.rb +11 -2
  157. data/test/scout/model/python/test_torch.rb +2 -0
  158. data/test/scout/model/python/torch/test_helpers.rb +4 -0
  159. data/test/scout/model/test_base.rb +4 -2
  160. data/test/support/availability.rb +231 -0
  161. data/test/support/fake_clients.rb +138 -0
  162. data/test/support/fixtures.rb +21 -0
  163. data/test/support/infrastructure_probes.rb +136 -0
  164. data/test/support/mock_backend.rb +215 -0
  165. data/test/test_helper.rb +32 -2
  166. metadata +99 -10
  167. data/doc/Agent.md +0 -327
  168. data/doc/Chat.md +0 -458
  169. data/doc/LLM.md +0 -340
  170. data/doc/RAG.md +0 -129
  171. data/scout_commands/documenter +0 -148
  172. data/test/scout/llm/backends/test_openai.rb +0 -192
  173. data/test/scout/llm/backends/test_responses.rb +0 -238
  174. data/test/scout/llm/test_parse.rb +0 -98
@@ -1,192 +0,0 @@
1
- require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
2
- require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
3
-
4
- class TestLLMOpenAI < Test::Unit::TestCase
5
- def test_ask
6
- prompt =<<-EOF
7
- system: you are a coding helper that only write code and comments without formatting so that it can work directly, avoid the initial and end commas ```.
8
- user: write a script that sorts files in a directory
9
- EOF
10
- sss 0
11
- ppp LLM::OpenAI.ask prompt
12
- end
13
-
14
- def _test_embeddings
15
- Log.severity = 0
16
- text =<<-EOF
17
- Some text
18
- EOF
19
- emb = LLM::OpenAI.embed text, log_errors: true, model: 'embedding-model'
20
-
21
- assert(Float === emb.first)
22
- end
23
-
24
- def _test_tool_call_output
25
- Log.severity = 0
26
- prompt =<<-EOF
27
- function_call:
28
-
29
- {"type":"function","function":{"name":"Baking-bake_muffin_tray","arguments":"{}"},"id":"Baking_bake_muffin_tray_Default"}
30
-
31
- function_call_output:
32
-
33
- {"id":"Baking_bake_muffin_tray_Default","role":"tool","content":"Baking batter (Mixing base (Whisking eggs from share/pantry/eggs) with mixer (share/pantry/flour))"}
34
-
35
- user:
36
-
37
- How do you bake muffins, according to the tool I provided you. Don't
38
- tell me the recipe you already know, use the tool call output. Let me
39
- know if you didn't get it.
40
- EOF
41
- ppp LLM::OpenAI.ask prompt, model: 'gpt-4.1-nano'
42
- end
43
-
44
- def _test_tool_call_output_2
45
- Log.severity = 0
46
- prompt =<<-EOF
47
- function_call:
48
-
49
- {"name":"get_current_temperature", "arguments":{"location":"London","unit":"Celsius"},"id":"tNTnsQq2s6jGh0npOh43AwDD"}
50
-
51
- function_call_output:
52
-
53
- {"id":"tNTnsQq2s6jGh0npOh43AwDD", "content":"It's 15 degrees and raining."}
54
-
55
- user:
56
-
57
- should i take an umbrella?
58
- EOF
59
- ppp LLM::OpenAI.ask prompt, model: 'gpt-4.1-nano'
60
- end
61
-
62
- def _test_tool_call_output_features
63
- Log.severity = 0
64
- prompt =<<-EOF
65
- function_call:
66
-
67
- {"name":"Baking-bake_muffin_tray","arguments":{},"id":"Baking_bake_muffin_tray_Default"}
68
-
69
- function_call_output:
70
-
71
- {"id":"Baking_bake_muffin_tray_Default","content":"Baking batter (Mixing base (Whisking eggs from share/pantry/eggs) with mixer (share/pantry/flour))"}
72
-
73
- user:
74
-
75
- How do you bake muffins, according to the tool I provided you. Don't
76
- tell me the recipe you already know, use the tool call output. Let me
77
- know if you didn't get it.
78
- EOF
79
- ppp LLM::OpenAI.ask prompt, model: 'gpt-4.1-nano'
80
- end
81
-
82
- def _test_tool_call_output_weather
83
- Log.severity = 0
84
- prompt =<<-EOF
85
- function_call:
86
-
87
- {"name":"get_current_temperature", "arguments":{"location":"London","unit":"Celsius"},"id":"tNTnsQq2s6jGh0npOh43AwDD"}
88
-
89
- function_call_output:
90
-
91
- {"id":"tNTnsQq2s6jGh0npOh43AwDD", "content":"It's 15 degrees and raining."}
92
-
93
- user:
94
-
95
- should i take an umbrella?
96
- EOF
97
- ppp LLM::OpenAI.ask prompt, model: 'gpt-4.1-nano'
98
- end
99
-
100
-
101
- def _test_tool_gpt5
102
- prompt =<<-EOF
103
- user:
104
- What is the weather in London. Should I take my umbrella?
105
- EOF
106
-
107
- tools = [
108
- {
109
- "type": "function",
110
- "function": {
111
- "name": "get_current_temperature",
112
- "description": "Get the current temperature and raining conditions for a specific location",
113
- "parameters": {
114
- "type": "object",
115
- "properties": {
116
- "location": {
117
- "type": "string",
118
- "description": "The city and state, e.g., San Francisco, CA"
119
- },
120
- "unit": {
121
- "type": "string",
122
- "enum": ["Celsius", "Fahrenheit"],
123
- "description": "The temperature unit to use. Infer this from the user's location."
124
- }
125
- },
126
- "required": ["location", "unit"]
127
- }
128
- }
129
- },
130
- ]
131
-
132
- respose = LLM::OpenAI.ask prompt, tool_choice: 'required', tools: tools, model: "gpt-5", log_errors: true do |name,arguments|
133
- "It's 15 degrees and raining."
134
- end
135
-
136
- ppp respose
137
- end
138
-
139
- def _test_tool
140
- prompt =<<-EOF
141
- user:
142
- What is the weather in London. Should I take my umbrella?
143
- EOF
144
-
145
- tools = [
146
- {
147
- "type": "function",
148
- "function": {
149
- "name": "get_current_temperature",
150
- "description": "Get the current temperature and raining conditions for a specific location",
151
- "parameters": {
152
- "type": "object",
153
- "properties": {
154
- "location": {
155
- "type": "string",
156
- "description": "The city and state, e.g., San Francisco, CA"
157
- },
158
- "unit": {
159
- "type": "string",
160
- "enum": ["Celsius", "Fahrenheit"],
161
- "description": "The temperature unit to use. Infer this from the user's location."
162
- }
163
- },
164
- "required": ["location", "unit"]
165
- }
166
- }
167
- },
168
- ]
169
-
170
- sss 0
171
- respose = LLM::OpenAI.ask prompt, tool_choice: 'required', tools: tools, model: "gpt-4.1-mini", log_errors: true do |name,arguments|
172
- "It's 15 degrees and raining."
173
- end
174
-
175
- ppp respose
176
- end
177
-
178
- def _test_json_output
179
- prompt =<<-EOF
180
- system:
181
-
182
- Respond in json format with a hash of strings as keys and string arrays as values, at most three in length
183
-
184
- user:
185
-
186
- What other movies have the protagonists of the original gost busters played on, just the top.
187
- EOF
188
- sss 0
189
- ppp LLM::OpenAI.ask prompt, format: :json
190
- end
191
- end
192
-
@@ -1,238 +0,0 @@
1
- require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
2
- require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
3
-
4
- class TestLLMResponses < Test::Unit::TestCase
5
- def test_ask
6
- prompt =<<-EOF
7
- system: you are a coding helper that only write code and comments without formatting so that it can work directly, avoid the initial and end commas ```.
8
- user: write a script that sorts files in a directory
9
- EOF
10
- ppp LLM::Responses.ask prompt, model: 'gpt-4.1-nano'
11
- end
12
-
13
- def _test_embeddings
14
- Log.severity = 0
15
- text =<<-EOF
16
- Some text
17
- EOF
18
- emb = LLM::Responses.embed text, log_errors: true
19
- assert(Float === emb.first)
20
- end
21
-
22
- def _test_tool_call_output_weather
23
- Log.severity = 0
24
- prompt =<<-EOF
25
- function_call:
26
-
27
- {"name":"get_current_temperature", "arguments":{"location":"London","unit":"Celsius"},"id":"tNTnsQq2s6jGh0npOh43AwDD"}
28
-
29
- function_call_output:
30
-
31
- {"id":"tNTnsQq2s6jGh0npOh43AwDD", "content":"It's 15 degrees and raining."}
32
-
33
- user:
34
-
35
- should i take an umbrella?
36
- EOF
37
- ppp LLM::Responses.ask prompt, model: 'gpt-4.1-nano'
38
- end
39
-
40
- def _test_tool
41
- prompt =<<-EOF
42
- user:
43
- What is the weather in London. Should I take my umbrella?
44
- EOF
45
-
46
- tools = [
47
- {
48
- "type": "function",
49
- "name": "get_current_temperature",
50
- "description": "Get the current temperature and raining conditions for a specific location",
51
- "parameters": {
52
- "type": "object",
53
- "properties": {
54
- "location": {
55
- "type": "string",
56
- "description": "The city and state, e.g., San Francisco, CA"
57
- },
58
- "unit": {
59
- "type": "string",
60
- "enum": ["Celsius", "Fahrenheit"],
61
- "description": "The temperature unit to use. Infer this from the user's location."
62
- }
63
- },
64
- "required": ["location", "unit"]
65
- }
66
- },
67
- ]
68
-
69
- sss 1
70
- respose = LLM::Responses.ask prompt, tool_choice: 'required', tools: tools, model: "gpt-4.1-nano", log_errors: true do |name,arguments|
71
- "It's 15 degrees and raining."
72
- end
73
-
74
- ppp respose
75
- end
76
-
77
- def _test_news
78
- prompt =<<-EOF
79
- websearch: true
80
-
81
- user:
82
-
83
- What was the top new in the US today?
84
- EOF
85
- ppp LLM::Responses.ask prompt
86
- end
87
-
88
- def _test_image
89
- prompt =<<-EOF
90
- image: #{datafile_test 'cat.jpg'}
91
-
92
- user:
93
-
94
- What animal is represented in the image?
95
- EOF
96
- sss 0
97
- ppp LLM::Responses.ask prompt
98
- end
99
-
100
- def _test_json_output
101
- prompt =<<-EOF
102
- system:
103
-
104
- Respond in json format with a hash of strings as keys and string arrays as values, at most three in length
105
-
106
- user:
107
-
108
- What other movies have the protagonists of the original gost busters played on, just the top.
109
- EOF
110
- sss 0
111
- ppp LLM::Responses.ask prompt, format: :json
112
- end
113
-
114
- def _test_json_format
115
- prompt =<<-EOF
116
- user:
117
-
118
- What other movies have the protagonists of the original gost busters played on.
119
- Name each actor and the top movie they took part of
120
- EOF
121
- sss 0
122
-
123
- format = {
124
- name: 'actors_and_top_movies',
125
- type: 'object',
126
- properties: {},
127
- additionalProperties: {type: :string}
128
- }
129
- ppp LLM::Responses.ask prompt, format: format
130
- end
131
-
132
- def _test_json_format_list
133
- prompt =<<-EOF
134
- user:
135
-
136
- What other movies have the protagonists of the original gost busters played on.
137
- Name each actor as keys and the top 3 movies they took part of as values
138
- EOF
139
- sss 0
140
-
141
- format = {
142
- name: 'actors_and_top_movies',
143
- type: 'object',
144
- properties: {},
145
- additionalProperties: {type: :array, items: {type: :string}}
146
- }
147
- ppp LLM::Responses.ask prompt, format: format
148
- end
149
-
150
- def _test_json_format_actor_list
151
- prompt =<<-EOF
152
- user:
153
-
154
- What other movies have the protagonists of the original gost busters played on.
155
- Name each actor as keys and the top 3 movies they took part of as values
156
- EOF
157
- sss 0
158
-
159
- format = {
160
- name: 'actors_and_top_movies',
161
- type: 'object',
162
- properties: {},
163
- additionalProperties: false,
164
- items: {
165
- type: 'object',
166
- properties: {
167
- name: {type: :string, description: 'actor name'},
168
- movies: {type: :array, description: 'list of top 3 movies', items: {type: :string, description: 'movie title plus year in parenthesis'} },
169
- additionalProperties: false
170
- }
171
- }
172
- }
173
-
174
- schema = {
175
- "type": "object",
176
- "properties": {
177
- "people": {
178
- "type": "array",
179
- "items": {
180
- "type": "object",
181
- "properties": {
182
- "name": { "type": "string" },
183
- "movies": {
184
- "type": "array",
185
- "items": { "type": "string" },
186
- "minItems": 3,
187
- "maxItems": 3
188
- }
189
- },
190
- "required": ["name", "movies"],
191
- additionalProperties: false
192
- }
193
- }
194
- },
195
- additionalProperties: false,
196
- "required": ["people"]
197
- }
198
- ppp LLM::Responses.ask prompt, format: schema
199
- end
200
-
201
- def _test_tool_gpt5
202
- prompt =<<-EOF
203
- user:
204
- What is the weather in London. Should I take my umbrella?
205
- EOF
206
-
207
- tools = [
208
- {
209
- "type": "function",
210
- "name": "get_current_temperature",
211
- "description": "Get the current temperature and raining conditions for a specific location",
212
- "parameters": {
213
- "type": "object",
214
- "properties": {
215
- "location": {
216
- "type": "string",
217
- "description": "The city and state, e.g., San Francisco, CA"
218
- },
219
- "unit": {
220
- "type": "string",
221
- "enum": ["Celsius", "Fahrenheit"],
222
- "description": "The temperature unit to use. Infer this from the user's location."
223
- }
224
- },
225
- "required": ["location", "unit"]
226
- }
227
- },
228
- ]
229
-
230
- sss 0
231
- respose = LLM::Responses.ask prompt, tool_choice: 'required', tools: tools, model: "gpt-5", log_errors: true do |name,arguments|
232
- "It's 15 degrees and raining."
233
- end
234
-
235
- ppp respose
236
- end
237
- end
238
-
@@ -1,98 +0,0 @@
1
- require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
2
- require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
3
-
4
- class TestLLMParse < Test::Unit::TestCase
5
- def test_parse
6
- text=<<-EOF
7
- hi
8
- system: you are an asistant
9
- user: Given the contents of this file:[[
10
- line 1: 1
11
- line 2: 2
12
- line 3: 3
13
- ]]
14
- Show me the lines in reverse order
15
- EOF
16
-
17
- assert_include LLM.parse(text).first[:content], 'hi'
18
- assert_include LLM.parse(text).last[:content], 'reverse'
19
- end
20
-
21
- def test_code
22
- text=<<-EOF
23
- hi
24
- system: you are an asistant
25
- user: Given the contents of this file:
26
- ```yaml
27
- key: value
28
- key2: value2
29
- ```
30
- Show me the lines in reverse order
31
- EOF
32
-
33
- assert_include LLM.parse(text).last[:content], 'key2'
34
- end
35
-
36
- def test_lines
37
- text=<<-EOF
38
- system: you are an asistant
39
- user: I have a question
40
- EOF
41
-
42
- assert_include LLM.parse(text).last[:content], 'question'
43
- end
44
-
45
- def test_blocks
46
- text=<<-EOF
47
- system:
48
-
49
- you are an asistant
50
-
51
- user:
52
-
53
- I have a question
54
-
55
- EOF
56
-
57
- assert_include LLM.parse(text).last[:content], 'question'
58
- end
59
-
60
- def test_no_role
61
- text=<<-EOF
62
- I have a question
63
- EOF
64
-
65
- assert_include LLM.parse(text).last[:content], 'question'
66
- end
67
-
68
-
69
- def test_cmd
70
- text=<<-EOF
71
- How many files are there:
72
-
73
- [[cmd list of files
74
- echo "file1 file2"
75
- ]]
76
- EOF
77
-
78
- assert_equal :user, LLM.parse(text).last[:role]
79
- assert_include LLM.parse(text).first[:content], 'file1'
80
- end
81
-
82
- def test_directory
83
- TmpFile.with_path do |tmpdir|
84
- tmpdir.file1.write "foo"
85
- tmpdir.file2.write "bar"
86
- text=<<-EOF
87
- How many files are there:
88
-
89
- [[directory DIR
90
- #{tmpdir}
91
- ]]
92
- EOF
93
-
94
- assert_include LLM.parse(text).first[:content], 'file1'
95
- end
96
- end
97
- end
98
-