1#pragma once
2
3#include "chat.h"
4#include "json-partial.h"
5#include "regex-partial.h"
6
7#include <nlohmann/json.hpp>
8
9#include <optional>
10#include <string>
11#include <vector>
12
13class common_chat_msg_partial_exception : public std::runtime_error {
14 public:
15 common_chat_msg_partial_exception(const std::string & message) : std::runtime_error(message) {}
16};
17
18class common_chat_msg_parser {
19 std::string input_;
20 bool is_partial_;
21 common_chat_syntax syntax_;
22 std::string healing_marker_;
23
24 size_t pos_ = 0;
25 common_chat_msg result_;
26
27 public:
28 common_chat_msg_parser(const std::string & input, bool is_partial, const common_chat_syntax & syntax);
29 const std::string & input() const { return input_; }
30 size_t pos() const { return pos_; }
31 const std::string & healing_marker() const { return healing_marker_; }
32 const bool & is_partial() const { return is_partial_; }
33 const common_chat_msg & result() const { return result_; }
34 const common_chat_syntax & syntax() const { return syntax_; }
35
36 void move_to(size_t pos) {
37 if (pos > input_.size()) {
38 throw std::runtime_error("Invalid position!");
39 }
40 pos_ = pos;
41 }
42 void move_back(size_t n) {
43 if (pos_ < n) {
44 throw std::runtime_error("Can't move back that far!");
45 }
46 pos_ -= n;
47 }
48
49 // Get the substring of the input at the given range
50 std::string str(const common_string_range & rng) const;
51
52 // Appends to the result.content field
53 void add_content(const std::string & content);
54
55 // Appends to the result.reasoning_content field
56 void add_reasoning_content(const std::string & reasoning_content);
57
58 // Adds a tool call to the result. If the tool call is too incomplete (e.g. name empty), it won't add anything.
59 bool add_tool_call(const std::string & name, const std::string & id, const std::string & arguments);
60
61 // Adds a tool call using the "name", "id" and "arguments" fields of the json object
62 bool add_tool_call(const nlohmann::ordered_json & tool_call);
63
64 // Adds an array of tool calls using their "name", "id" and "arguments" fields.
65 bool add_tool_calls(const nlohmann::ordered_json & arr);
66
67 // Adds a tool call using the short form: { "tool_name": { "arg1": val, "arg2": val } }
68 bool add_tool_call_short_form(const nlohmann::ordered_json & tool_call);
69
70 void finish();
71
72 bool consume_spaces();
73
74 void consume_literal(const std::string & literal);
75
76 bool try_parse_reasoning(const std::string & start_think, const std::string & end_think);
77
78 std::string consume_rest();
79
80 struct find_regex_result {
81 std::string prelude;
82 std::vector<common_string_range> groups;
83 };
84
85 std::optional<find_regex_result> try_find_regex(const common_regex & regex, size_t from = std::string::npos, bool add_prelude_to_content = true);
86
87 bool try_consume_literal(const std::string & literal);
88
89 std::optional<find_regex_result> try_find_literal(const std::string & literal);
90
91 find_regex_result consume_regex(const common_regex & regex);
92
93 std::optional<find_regex_result> try_consume_regex(const common_regex & regex);
94
95 std::optional<common_json> try_consume_json();
96 common_json consume_json();
97
98 struct consume_json_result {
99 nlohmann::ordered_json value;
100 bool is_partial;
101 };
102
103 /*
104 Consume (possibly partial) json and converts specific subtrees to (possibly truncated) JSON strings.
105
106 By default, object keys can't be truncated, nor can string values (their corresponding key is removed,
107 e.g. `{"foo": "bar", "baz": "b` -> `{"foo": "bar"}`
108
109 But one can allow subpaths to be kept truncated, and possibly json-dumped to truncated json strings
110 - with `content_paths={{"foo"}}` -> `{"foo": "b` -> {"foo": "b"}`
111 - with `args_paths={{"foo"}}` -> `{"foo": {"b` -> `{"foo": "{b"}`
112 */
113 consume_json_result consume_json_with_dumped_args(
114 const std::vector<std::vector<std::string>> & args_paths = {},
115 const std::vector<std::vector<std::string>> & content_paths = {}
116 );
117 std::optional<consume_json_result> try_consume_json_with_dumped_args(
118 const std::vector<std::vector<std::string>> & args_paths = {},
119 const std::vector<std::vector<std::string>> & content_paths = {}
120 );
121
122 void clear_tools();
123};
124