@kalenkevich/agent_007 0.0.1

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 (247) hide show
  1. package/dist/agent/agent.d.ts +17 -0
  2. package/dist/agent/agent.js +6 -0
  3. package/dist/agent/agent.js.map +1 -0
  4. package/dist/agent/agent_event.d.ts +108 -0
  5. package/dist/agent/agent_event.js +56 -0
  6. package/dist/agent/agent_event.js.map +1 -0
  7. package/dist/agent/agent_event_utils.d.ts +5 -0
  8. package/dist/agent/agent_event_utils.js +66 -0
  9. package/dist/agent/agent_event_utils.js.map +1 -0
  10. package/dist/agent/cli_agent/cli_agent.d.ts +41 -0
  11. package/dist/agent/cli_agent/cli_agent.js +324 -0
  12. package/dist/agent/cli_agent/cli_agent.js.map +1 -0
  13. package/dist/agent/cli_agent/system_prompt.d.ts +1 -0
  14. package/dist/agent/cli_agent/system_prompt.js +58 -0
  15. package/dist/agent/cli_agent/system_prompt.js.map +1 -0
  16. package/dist/agent/cli_agent.d.ts +34 -0
  17. package/dist/agent/cli_agent.js +91 -0
  18. package/dist/agent/cli_agent.js.map +1 -0
  19. package/dist/agent/planner_agent/planner_agent.d.ts +28 -0
  20. package/dist/agent/planner_agent/planner_agent.js +102 -0
  21. package/dist/agent/planner_agent/planner_agent.js.map +1 -0
  22. package/dist/agent/request_processor/basic_request_processor.d.ts +17 -0
  23. package/dist/agent/request_processor/basic_request_processor.js +28 -0
  24. package/dist/agent/request_processor/basic_request_processor.js.map +1 -0
  25. package/dist/agent/request_processor/compaction_processor.d.ts +17 -0
  26. package/dist/agent/request_processor/compaction_processor.js +118 -0
  27. package/dist/agent/request_processor/compaction_processor.js.map +1 -0
  28. package/dist/agent/request_processor/request_processor.d.ts +11 -0
  29. package/dist/agent/request_processor/request_processor.js +2 -0
  30. package/dist/agent/request_processor/request_processor.js.map +1 -0
  31. package/dist/cli/init_project_command_handler.d.ts +3 -0
  32. package/dist/cli/init_project_command_handler.js +58 -0
  33. package/dist/cli/init_project_command_handler.js.map +1 -0
  34. package/dist/cli/loader.d.ts +6 -0
  35. package/dist/cli/loader.js +27 -0
  36. package/dist/cli/loader.js.map +1 -0
  37. package/dist/cli/prompt_utils.d.ts +11 -0
  38. package/dist/cli/prompt_utils.js +18 -0
  39. package/dist/cli/prompt_utils.js.map +1 -0
  40. package/dist/cli/run_command.d.ts +6 -0
  41. package/dist/cli/run_command.js +72 -0
  42. package/dist/cli/run_command.js.map +1 -0
  43. package/dist/cli/run_interactive_command.d.ts +6 -0
  44. package/dist/cli/run_interactive_command.js +282 -0
  45. package/dist/cli/run_interactive_command.js.map +1 -0
  46. package/dist/cli/run_noninteractive_command.d.ts +6 -0
  47. package/dist/cli/run_noninteractive_command.js +60 -0
  48. package/dist/cli/run_noninteractive_command.js.map +1 -0
  49. package/dist/cli_entrypoint.d.ts +2 -0
  50. package/dist/cli_entrypoint.js +110 -0
  51. package/dist/cli_entrypoint.js.map +1 -0
  52. package/dist/command/commnad_handler.d.ts +3 -0
  53. package/dist/command/commnad_handler.js +2 -0
  54. package/dist/command/commnad_handler.js.map +1 -0
  55. package/dist/command/init_project_command_handler.d.ts +4 -0
  56. package/dist/command/init_project_command_handler.js +58 -0
  57. package/dist/command/init_project_command_handler.js.map +1 -0
  58. package/dist/config/app_dir.d.ts +1 -0
  59. package/dist/config/app_dir.js +4 -0
  60. package/dist/config/app_dir.js.map +1 -0
  61. package/dist/config/config.d.ts +21 -0
  62. package/dist/config/config.js +2 -0
  63. package/dist/config/config.js.map +1 -0
  64. package/dist/config/config_loader.d.ts +2 -0
  65. package/dist/config/config_loader.js +47 -0
  66. package/dist/config/config_loader.js.map +1 -0
  67. package/dist/config/config_store.d.ts +10 -0
  68. package/dist/config/config_store.js +44 -0
  69. package/dist/config/config_store.js.map +1 -0
  70. package/dist/content.d.ts +51 -0
  71. package/dist/content.js +16 -0
  72. package/dist/content.js.map +1 -0
  73. package/dist/core/functions.d.ts +1 -0
  74. package/dist/core/functions.js +6 -0
  75. package/dist/core/functions.js.map +1 -0
  76. package/dist/core/loop.d.ts +20 -0
  77. package/dist/core/loop.js +121 -0
  78. package/dist/core/loop.js.map +1 -0
  79. package/dist/core/project_service.d.ts +11 -0
  80. package/dist/core/project_service.js +26 -0
  81. package/dist/core/project_service.js.map +1 -0
  82. package/dist/core/run.d.ts +6 -0
  83. package/dist/core/run.js +25 -0
  84. package/dist/core/run.js.map +1 -0
  85. package/dist/index.d.ts +1 -0
  86. package/dist/index.js +2 -0
  87. package/dist/index.js.map +1 -0
  88. package/dist/logger.d.ts +27 -0
  89. package/dist/logger.js +98 -0
  90. package/dist/logger.js.map +1 -0
  91. package/dist/model/adaptive_model.d.ts +16 -0
  92. package/dist/model/adaptive_model.js +57 -0
  93. package/dist/model/adaptive_model.js.map +1 -0
  94. package/dist/model/google/gemini_model.d.ts +15 -0
  95. package/dist/model/google/gemini_model.js +131 -0
  96. package/dist/model/google/gemini_model.js.map +1 -0
  97. package/dist/model/google/gemini_response_utils.d.ts +3 -0
  98. package/dist/model/google/gemini_response_utils.js +36 -0
  99. package/dist/model/google/gemini_response_utils.js.map +1 -0
  100. package/dist/model/google/gemini_streaming_utils.d.ts +28 -0
  101. package/dist/model/google/gemini_streaming_utils.js +235 -0
  102. package/dist/model/google/gemini_streaming_utils.js.map +1 -0
  103. package/dist/model/google/gen_ai_convert_utils.d.ts +6 -0
  104. package/dist/model/google/gen_ai_convert_utils.js +117 -0
  105. package/dist/model/google/gen_ai_convert_utils.js.map +1 -0
  106. package/dist/model/model.d.ts +11 -0
  107. package/dist/model/model.js +2 -0
  108. package/dist/model/model.js.map +1 -0
  109. package/dist/model/registry.d.ts +19 -0
  110. package/dist/model/registry.js +47 -0
  111. package/dist/model/registry.js.map +1 -0
  112. package/dist/model/request.d.ts +13 -0
  113. package/dist/model/request.js +2 -0
  114. package/dist/model/request.js.map +1 -0
  115. package/dist/model/request_builder_utils.d.ts +19 -0
  116. package/dist/model/request_builder_utils.js +43 -0
  117. package/dist/model/request_builder_utils.js.map +1 -0
  118. package/dist/model/response.d.ts +60 -0
  119. package/dist/model/response.js +2 -0
  120. package/dist/model/response.js.map +1 -0
  121. package/dist/model/util_llm.d.ts +10 -0
  122. package/dist/model/util_llm.js +149 -0
  123. package/dist/model/util_llm.js.map +1 -0
  124. package/dist/session/session.d.ts +14 -0
  125. package/dist/session/session.js +2 -0
  126. package/dist/session/session.js.map +1 -0
  127. package/dist/session/session_file_service.d.ts +23 -0
  128. package/dist/session/session_file_service.js +147 -0
  129. package/dist/session/session_file_service.js.map +1 -0
  130. package/dist/skills/skill.d.ts +23 -0
  131. package/dist/skills/skill.js +12 -0
  132. package/dist/skills/skill.js.map +1 -0
  133. package/dist/tools/build_in/find.d.ts +3 -0
  134. package/dist/tools/build_in/find.js +71 -0
  135. package/dist/tools/build_in/find.js.map +1 -0
  136. package/dist/tools/build_in/grep.d.ts +3 -0
  137. package/dist/tools/build_in/grep.js +97 -0
  138. package/dist/tools/build_in/grep.js.map +1 -0
  139. package/dist/tools/build_in/index.d.ts +1 -0
  140. package/dist/tools/build_in/index.js +13 -0
  141. package/dist/tools/build_in/index.js.map +1 -0
  142. package/dist/tools/build_in/list_dir.d.ts +3 -0
  143. package/dist/tools/build_in/list_dir.js +46 -0
  144. package/dist/tools/build_in/list_dir.js.map +1 -0
  145. package/dist/tools/build_in/view_file.d.ts +3 -0
  146. package/dist/tools/build_in/view_file.js +44 -0
  147. package/dist/tools/build_in/view_file.js.map +1 -0
  148. package/dist/tools/build_in/write_file.d.ts +3 -0
  149. package/dist/tools/build_in/write_file.js +50 -0
  150. package/dist/tools/build_in/write_file.js.map +1 -0
  151. package/dist/tools/functional_tool.d.ts +18 -0
  152. package/dist/tools/functional_tool.js +20 -0
  153. package/dist/tools/functional_tool.js.map +1 -0
  154. package/dist/tools/schema.d.ts +86 -0
  155. package/dist/tools/schema.js +37 -0
  156. package/dist/tools/schema.js.map +1 -0
  157. package/dist/tools/tool.d.ts +30 -0
  158. package/dist/tools/tool.js +9 -0
  159. package/dist/tools/tool.js.map +1 -0
  160. package/dist/tools/tool_call_policy.d.ts +4 -0
  161. package/dist/tools/tool_call_policy.js +4 -0
  162. package/dist/tools/tool_call_policy.js.map +1 -0
  163. package/dist/tools/tool_policy.d.ts +4 -0
  164. package/dist/tools/tool_policy.js +4 -0
  165. package/dist/tools/tool_policy.js.map +1 -0
  166. package/dist/ui/ui.d.ts +1 -0
  167. package/dist/ui/ui.js +2 -0
  168. package/dist/ui/ui.js.map +1 -0
  169. package/dist/user_input.d.ts +20 -0
  170. package/dist/user_input.js +21 -0
  171. package/dist/user_input.js.map +1 -0
  172. package/package.json +44 -0
  173. package/src/agent/agent.ts +18 -0
  174. package/src/agent/agent_event.ts +171 -0
  175. package/src/agent/agent_event_utils.ts +87 -0
  176. package/src/agent/cli_agent/cli_agent.ts +418 -0
  177. package/src/agent/cli_agent/system_prompt.ts +57 -0
  178. package/src/agent/planner_agent/planner_agent.ts +136 -0
  179. package/src/agent/request_processor/basic_request_processor.ts +46 -0
  180. package/src/agent/request_processor/compaction_processor.ts +164 -0
  181. package/src/agent/request_processor/request_processor.ts +13 -0
  182. package/src/cli/loader.ts +27 -0
  183. package/src/cli/prompt_utils.ts +19 -0
  184. package/src/cli/run_interactive_command.ts +337 -0
  185. package/src/cli/run_noninteractive_command.ts +74 -0
  186. package/src/cli_entrypoint.ts +128 -0
  187. package/src/command/commnad_handler.ts +3 -0
  188. package/src/command/init_project_command_handler.ts +66 -0
  189. package/src/config/app_dir.ts +4 -0
  190. package/src/config/config.ts +24 -0
  191. package/src/config/config_loader.ts +57 -0
  192. package/src/config/config_store.ts +50 -0
  193. package/src/content.ts +87 -0
  194. package/src/core/functions.ts +7 -0
  195. package/src/core/loop.ts +165 -0
  196. package/src/core/project_service.ts +38 -0
  197. package/src/core/run.ts +36 -0
  198. package/src/index.ts +1 -0
  199. package/src/logger.ts +128 -0
  200. package/src/model/adaptive_model.ts +77 -0
  201. package/src/model/google/gemini_model.ts +194 -0
  202. package/src/model/google/gemini_response_utils.ts +46 -0
  203. package/src/model/google/gemini_streaming_utils.ts +294 -0
  204. package/src/model/google/gen_ai_convert_utils.ts +149 -0
  205. package/src/model/model.ts +18 -0
  206. package/src/model/registry.ts +61 -0
  207. package/src/model/request.ts +15 -0
  208. package/src/model/request_builder_utils.ts +79 -0
  209. package/src/model/response.ts +66 -0
  210. package/src/model/util_llm.ts +167 -0
  211. package/src/session/session.ts +16 -0
  212. package/src/session/session_file_service.ts +207 -0
  213. package/src/skills/skill.ts +38 -0
  214. package/src/tools/build_in/find.ts +80 -0
  215. package/src/tools/build_in/grep.ts +101 -0
  216. package/src/tools/build_in/index.ts +13 -0
  217. package/src/tools/build_in/list_dir.ts +50 -0
  218. package/src/tools/build_in/view_file.ts +47 -0
  219. package/src/tools/build_in/write_file.ts +53 -0
  220. package/src/tools/functional_tool.ts +59 -0
  221. package/src/tools/schema.ts +87 -0
  222. package/src/tools/tool.ts +68 -0
  223. package/src/tools/tool_call_policy.ts +7 -0
  224. package/src/ui/ui.ts +0 -0
  225. package/src/user_input.ts +51 -0
  226. package/tests/integration/util_llm_test.ts +42 -0
  227. package/tests/unit/adaptive_model_test.ts +122 -0
  228. package/tests/unit/agent/request_processor/compaction_processor_test.ts +121 -0
  229. package/tests/unit/cli/prompt_utils_test.ts +47 -0
  230. package/tests/unit/cli_agent_test.ts +476 -0
  231. package/tests/unit/content_test.ts +56 -0
  232. package/tests/unit/logger_test.ts +109 -0
  233. package/tests/unit/loop_test.ts +141 -0
  234. package/tests/unit/model/gemini_model_test.ts +111 -0
  235. package/tests/unit/planner_agent_test.ts +52 -0
  236. package/tests/unit/project_service_test.ts +102 -0
  237. package/tests/unit/session_file_service_test.ts +160 -0
  238. package/tests/unit/tools/find_test.ts +40 -0
  239. package/tests/unit/tools/grep_test.ts +43 -0
  240. package/tests/unit/tools/list_dir_test.ts +32 -0
  241. package/tests/unit/tools/view_file_test.ts +32 -0
  242. package/tests/unit/tools/write_file_test.ts +44 -0
  243. package/tests/unit/user_input_test.ts +55 -0
  244. package/tests/unit/util_llm_test.ts +61 -0
  245. package/todo.md +29 -0
  246. package/tsconfig.json +33 -0
  247. package/vitest.config.ts +33 -0
@@ -0,0 +1,47 @@
1
+ import { FunctionalTool } from "../functional_tool.js";
2
+ import { type Schema, Type } from "../schema.js";
3
+ import * as fs from "node:fs/promises";
4
+ import * as path from "node:path";
5
+
6
+ export const VIEW_FILE_TOOL = new FunctionalTool({
7
+ name: "view_file",
8
+ description: "Reads the content of a file.",
9
+ params: {
10
+ type: Type.OBJECT,
11
+ properties: {
12
+ path: {
13
+ type: Type.STRING,
14
+ description: "The path to the file to read.",
15
+ },
16
+ },
17
+ required: ["path"],
18
+ } as Schema,
19
+ output: {
20
+ type: Type.OBJECT,
21
+ properties: {
22
+ content: {
23
+ type: Type.STRING,
24
+ description: "The content of the file",
25
+ },
26
+ },
27
+ } as Schema,
28
+ execute: async (input: unknown) => {
29
+ const typedInput = input as { path: string };
30
+ const filePath = typedInput.path;
31
+ const resolvedPath = path.resolve(filePath);
32
+ const cwd = process.cwd();
33
+
34
+ if (!resolvedPath.startsWith(cwd)) {
35
+ throw new Error(
36
+ `Access denied: Path ${resolvedPath} is outside the project directory.`,
37
+ );
38
+ }
39
+
40
+ try {
41
+ const content = await fs.readFile(resolvedPath, "utf-8");
42
+ return { content };
43
+ } catch (error: any) {
44
+ throw new Error(`Failed to read file: ${error.message}`);
45
+ }
46
+ },
47
+ });
@@ -0,0 +1,53 @@
1
+ import { FunctionalTool } from "../functional_tool.js";
2
+ import { type Schema, Type } from "../schema.js";
3
+ import * as fs from "node:fs/promises";
4
+ import * as path from "node:path";
5
+
6
+ export const WRITE_FILE_TOOL = new FunctionalTool({
7
+ name: "write_file",
8
+ description: "Writes content to a file.",
9
+ params: {
10
+ type: Type.OBJECT,
11
+ properties: {
12
+ path: {
13
+ type: Type.STRING,
14
+ description: "The path to the file to write.",
15
+ },
16
+ content: {
17
+ type: Type.STRING,
18
+ description: "The content to write to the file.",
19
+ },
20
+ },
21
+ required: ["path", "content"],
22
+ } as Schema,
23
+ output: {
24
+ type: Type.OBJECT,
25
+ properties: {
26
+ success: {
27
+ type: Type.BOOLEAN,
28
+ description: "Whether the operation was successful",
29
+ },
30
+ },
31
+ } as Schema,
32
+ execute: async (input: unknown) => {
33
+ const typedInput = input as { path: string; content: string };
34
+ const filePath = typedInput.path;
35
+ const content = typedInput.content;
36
+ const resolvedPath = path.resolve(filePath);
37
+ const cwd = process.cwd();
38
+
39
+ if (!resolvedPath.startsWith(cwd)) {
40
+ throw new Error(
41
+ `Access denied: Path ${resolvedPath} is outside the project directory.`,
42
+ );
43
+ }
44
+
45
+ try {
46
+ await fs.mkdir(path.dirname(resolvedPath), { recursive: true });
47
+ await fs.writeFile(resolvedPath, content, "utf-8");
48
+ return { success: true };
49
+ } catch (error: any) {
50
+ throw new Error(`Failed to write file: ${error.message}`);
51
+ }
52
+ },
53
+ });
@@ -0,0 +1,59 @@
1
+ import type {
2
+ Tool,
3
+ FunctionDeclaration,
4
+ ToolInputSchema,
5
+ ToolOutputSchema,
6
+ ToolInput,
7
+ ToolOutput,
8
+ } from "./tool.js";
9
+ import type { Schema } from "./schema.js";
10
+
11
+ export interface FunctionalToolParams<
12
+ TInputParameters extends ToolInputSchema = ToolInputSchema,
13
+ TOutputParameters extends ToolOutputSchema = ToolOutputSchema,
14
+ > {
15
+ name: string;
16
+ description: string;
17
+ params: TInputParameters;
18
+ output: TOutputParameters;
19
+ execute: (
20
+ input: ToolInput<TInputParameters>,
21
+ ) => Promise<ToolOutput<TOutputParameters>> | ToolOutput<TOutputParameters>;
22
+ }
23
+
24
+ export class FunctionalTool<
25
+ TInputParameters extends ToolInputSchema = ToolInputSchema,
26
+ TOutputParameters extends ToolOutputSchema = ToolOutputSchema,
27
+ > implements Tool<TInputParameters, TOutputParameters> {
28
+ public readonly name: string;
29
+ public readonly description: string;
30
+ public readonly params: TInputParameters;
31
+ public readonly output: TOutputParameters;
32
+ private readonly executeFn: (
33
+ input: ToolInput<TInputParameters>,
34
+ ) => Promise<ToolOutput<TOutputParameters>> | ToolOutput<TOutputParameters>;
35
+
36
+ constructor(
37
+ params: FunctionalToolParams<TInputParameters, TOutputParameters>,
38
+ ) {
39
+ this.name = params.name;
40
+ this.description = params.description;
41
+ this.params = params.params;
42
+ this.output = params.output;
43
+ this.executeFn = params.execute;
44
+ }
45
+
46
+ async execute(
47
+ input: ToolInput<TInputParameters>,
48
+ ): Promise<ToolOutput<TOutputParameters>> {
49
+ return this.executeFn(input);
50
+ }
51
+
52
+ toFunctionDeclaration(): FunctionDeclaration {
53
+ return {
54
+ name: this.name,
55
+ description: this.description,
56
+ parameters: this.params as unknown as Schema,
57
+ };
58
+ }
59
+ }
@@ -0,0 +1,87 @@
1
+ /** Data type of the schema field. */
2
+ export enum Type {
3
+ /**
4
+ * Not specified, should not be used.
5
+ */
6
+ TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED",
7
+ /**
8
+ * OpenAPI string type
9
+ */
10
+ STRING = "STRING",
11
+ /**
12
+ * OpenAPI number type
13
+ */
14
+ NUMBER = "NUMBER",
15
+ /**
16
+ * OpenAPI integer type
17
+ */
18
+ INTEGER = "INTEGER",
19
+ /**
20
+ * OpenAPI boolean type
21
+ */
22
+ BOOLEAN = "BOOLEAN",
23
+ /**
24
+ * OpenAPI array type
25
+ */
26
+ ARRAY = "ARRAY",
27
+ /**
28
+ * OpenAPI object type
29
+ */
30
+ OBJECT = "OBJECT",
31
+ /**
32
+ * Null type
33
+ */
34
+ NULL = "NULL",
35
+ }
36
+
37
+ /** Schema is used to define the format of input/output data.
38
+
39
+ Represents a select subset of an [OpenAPI 3.0 schema
40
+ object](https://spec.openapis.org/oas/v3.0.3#schema-object). More fields may
41
+ be added in the future as needed. */
42
+ export interface Schema {
43
+ /** Optional. The instance must be valid against any (one or more) of the subschemas listed in `any_of`. */
44
+ anyOf?: Schema[];
45
+ /** Optional. Default value to use if the field is not specified. */
46
+ default?: unknown;
47
+ /** Optional. Describes the data. The model uses this field to understand the purpose of the schema and how to use it. It is a best practice to provide a clear and descriptive explanation for the schema and its properties here, rather than in the prompt. */
48
+ description?: string;
49
+ /** Optional. Possible values of the field. This field can be used to restrict a value to a fixed set of values. To mark a field as an enum, set `format` to `enum` and provide the list of possible values in `enum`. For example: 1. To define directions: `{type:STRING, format:enum, enum:["EAST", "NORTH", "SOUTH", "WEST"]}` 2. To define apartment numbers: `{type:INTEGER, format:enum, enum:["101", "201", "301"]}` */
50
+ enum?: string[];
51
+ /** Optional. Example of an instance of this schema. */
52
+ example?: unknown;
53
+ /** Optional. The format of the data. For `NUMBER` type, format can be `float` or `double`. For `INTEGER` type, format can be `int32` or `int64`. For `STRING` type, format can be `email`, `byte`, `date`, `date-time`, `password`, and other formats to further refine the data type. */
54
+ format?: string;
55
+ /** Optional. If type is `ARRAY`, `items` specifies the schema of elements in the array. */
56
+ items?: Schema;
57
+ /** Optional. If type is `ARRAY`, `max_items` specifies the maximum number of items in an array. */
58
+ maxItems?: string;
59
+ /** Optional. If type is `STRING`, `max_length` specifies the maximum length of the string. */
60
+ maxLength?: string;
61
+ /** Optional. If type is `OBJECT`, `max_properties` specifies the maximum number of properties that can be provided. */
62
+ maxProperties?: string;
63
+ /** Optional. If type is `INTEGER` or `NUMBER`, `maximum` specifies the maximum allowed value. */
64
+ maximum?: number;
65
+ /** Optional. If type is `ARRAY`, `min_items` specifies the minimum number of items in an array. */
66
+ minItems?: string;
67
+ /** Optional. If type is `STRING`, `min_length` specifies the minimum length of the string. */
68
+ minLength?: string;
69
+ /** Optional. If type is `OBJECT`, `min_properties` specifies the minimum number of properties that can be provided. */
70
+ minProperties?: string;
71
+ /** Optional. If type is `INTEGER` or `NUMBER`, `minimum` specifies the minimum allowed value. */
72
+ minimum?: number;
73
+ /** Optional. Indicates if the value of this field can be null. */
74
+ nullable?: boolean;
75
+ /** Optional. If type is `STRING`, `pattern` specifies a regular expression that the string must match. */
76
+ pattern?: string;
77
+ /** Optional. If type is `OBJECT`, `properties` is a map of property names to schema definitions for each property of the object. */
78
+ properties?: Record<string, Schema>;
79
+ /** Optional. Order of properties displayed or used where order matters. This is not a standard field in OpenAPI specification, but can be used to control the order of properties. */
80
+ propertyOrdering?: string[];
81
+ /** Optional. If type is `OBJECT`, `required` lists the names of properties that must be present. */
82
+ required?: string[];
83
+ /** Optional. Title for the schema. */
84
+ title?: string;
85
+ /** Optional. Data type of the schema field. */
86
+ type?: Type;
87
+ }
@@ -0,0 +1,68 @@
1
+ import { z as z3 } from "zod/v3";
2
+ import { z as z4 } from "zod/v4";
3
+ import type { Schema } from "./schema.js";
4
+
5
+ export enum Behavior {
6
+ UNSPECIFIED = "UNSPECIFIED",
7
+ BLOCKING = "BLOCKING",
8
+ NON_BLOCKING = "NON_BLOCKING",
9
+ }
10
+
11
+ export interface FunctionDeclaration {
12
+ description?: string;
13
+ name?: string;
14
+ parameters?: Schema;
15
+ parametersJsonSchema?: unknown;
16
+ response?: Schema;
17
+ responseJsonSchema?: unknown;
18
+ behavior?: Behavior;
19
+ }
20
+
21
+ export type ToolInputSchema =
22
+ | z3.ZodObject<z3.ZodRawShape>
23
+ | z4.ZodObject<z4.ZodRawShape>
24
+ | Schema
25
+ | undefined;
26
+
27
+ export type ToolOutputSchema =
28
+ | z3.ZodObject<z3.ZodRawShape>
29
+ | z4.ZodObject<z4.ZodRawShape>
30
+ | Schema
31
+ | undefined;
32
+
33
+ export type ToolInput<TParameters extends ToolInputSchema> =
34
+ TParameters extends z3.ZodObject<infer T, infer U, infer V>
35
+ ? z3.infer<z3.ZodObject<T, U, V>>
36
+ : TParameters extends z4.ZodObject<infer T>
37
+ ? z4.infer<z4.ZodObject<T>>
38
+ : TParameters extends Schema
39
+ ? unknown
40
+ : string;
41
+
42
+ export type ToolOutput<TOutputParameters extends ToolOutputSchema> =
43
+ TOutputParameters extends z3.ZodObject<infer T, infer U, infer V>
44
+ ? z3.infer<z3.ZodObject<T, U, V>>
45
+ : TOutputParameters extends z4.ZodObject<infer T>
46
+ ? z4.infer<z4.ZodObject<T>>
47
+ : TOutputParameters extends Schema
48
+ ? unknown
49
+ : string;
50
+
51
+ export type ToolExecuteFunction<
52
+ TInputParameters extends ToolInputSchema = ToolInputSchema,
53
+ TOutputParameters extends ToolOutputSchema = ToolOutputSchema,
54
+ > = (
55
+ input: ToolInput<TInputParameters>,
56
+ ) => Promise<ToolOutput<TOutputParameters>> | ToolOutput<TOutputParameters>;
57
+
58
+ export interface Tool<
59
+ TInputParameters extends ToolInputSchema = ToolInputSchema,
60
+ TOutputParameters extends ToolOutputSchema = ToolOutputSchema,
61
+ > {
62
+ name: string;
63
+ description: string;
64
+ params: ToolInputSchema;
65
+ output: ToolOutputSchema;
66
+ execute: ToolExecuteFunction<TInputParameters, TOutputParameters>;
67
+ toFunctionDeclaration(): FunctionDeclaration;
68
+ }
@@ -0,0 +1,7 @@
1
+ export interface ToolCallPolicy {
2
+ confirmationRequired: boolean;
3
+ }
4
+
5
+ export const DEFAULT_POLICY: ToolCallPolicy = {
6
+ confirmationRequired: true,
7
+ };
package/src/ui/ui.ts ADDED
File without changes
@@ -0,0 +1,51 @@
1
+ import type { ModelConfig } from "./config/config.js";
2
+ import type { Content, ContentPart } from "./content.js";
3
+ import type { UserInputResponseEvent } from "./agent/agent_event.js";
4
+
5
+ export type UserCommand = SetModelCommand | PlanCommand;
6
+
7
+ export enum UserCommandType {
8
+ SET_MODEL = "set_model",
9
+ PLAN = "plan",
10
+ }
11
+
12
+ export interface SetModelCommand {
13
+ command: UserCommandType.SET_MODEL;
14
+ modelName: string;
15
+ config?: ModelConfig;
16
+ }
17
+
18
+ export interface PlanCommand {
19
+ command: UserCommandType.PLAN;
20
+ task: string;
21
+ }
22
+
23
+ export type UserInput =
24
+ | string
25
+ | Content
26
+ | ContentPart
27
+ | ContentPart[]
28
+ | UserCommand
29
+ | UserInputResponseEvent;
30
+
31
+ export function isUserCommand(userInput: UserInput): userInput is UserCommand {
32
+ return (userInput as UserCommand).command !== undefined;
33
+ }
34
+
35
+ export function toContentParts(
36
+ userInput: string | Content | ContentPart | ContentPart[],
37
+ ): ContentPart[] {
38
+ if (typeof userInput === "string") {
39
+ return [{ type: "text", text: userInput }];
40
+ }
41
+
42
+ if (Array.isArray(userInput)) {
43
+ return userInput;
44
+ }
45
+
46
+ if ("parts" in userInput) {
47
+ return userInput.parts;
48
+ }
49
+
50
+ return [userInput];
51
+ }
@@ -0,0 +1,42 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { UtilLlm } from "../../src/model/util_llm.js";
3
+ import { AdaptiveLlmModel } from "../../src/model/adaptive_model.js";
4
+ import { loadConfig } from "../../src/config/config_loader.js";
5
+ import { AgentEventType, type AgentEvent } from "../../src/agent/agent_event.js";
6
+
7
+ describe("UtilLlm Integration", () => {
8
+ it("should generate a session title using real model", async () => {
9
+ const config = await loadConfig();
10
+ if (!config.models.main.apiKey) {
11
+ console.warn("Skipping integration test: GEMINI_API_KEY is not set.");
12
+ return;
13
+ }
14
+ const model = new AdaptiveLlmModel(config.models);
15
+ const utilLlm = new UtilLlm(model);
16
+
17
+ const events: AgentEvent[] = [
18
+ {
19
+ id: "1",
20
+ streamId: "s1",
21
+ timestamp: new Date().toISOString(),
22
+ role: "user",
23
+ type: AgentEventType.MESSAGE,
24
+ parts: [{ type: "text", text: "How do I write a file in Node.js?" }],
25
+ },
26
+ {
27
+ id: "2",
28
+ streamId: "s1",
29
+ timestamp: new Date().toISOString(),
30
+ role: "agent",
31
+ type: AgentEventType.MESSAGE,
32
+ parts: [{ type: "text", text: "You can use the `fs` module. For example, `fs.writeFileSync('file.txt', 'content')`." }],
33
+ },
34
+ ];
35
+
36
+ const title = await utilLlm.generateSessionTitle(events);
37
+ console.log("Generated Title:", title);
38
+
39
+ expect(title).toBeTruthy();
40
+ expect(title).not.toBe("New Session");
41
+ }, 30000); // Extend timeout for API call
42
+ });
@@ -0,0 +1,122 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { AdaptiveLlmModel } from "../../src/model/adaptive_model.js";
3
+ import { resolveLlmModel } from "../../src/model/registry.js";
4
+
5
+ vi.mock("../../src/model/registry.js");
6
+
7
+ describe("AdaptiveLlmModel", () => {
8
+ beforeEach(() => {
9
+ vi.clearAllMocks();
10
+ });
11
+
12
+ it("should use main model on success", async () => {
13
+ const mockMainModel = {
14
+ run: vi.fn().mockImplementation(async function* () {
15
+ yield { text: "hello" };
16
+ }),
17
+ };
18
+ const MockMainClass = vi.fn().mockImplementation(function () {
19
+ return mockMainModel;
20
+ });
21
+
22
+ vi.mocked(resolveLlmModel).mockReturnValue(MockMainClass as any);
23
+
24
+ const model = new AdaptiveLlmModel({
25
+ main: { modelName: "main-model", apiKey: "key" },
26
+ });
27
+
28
+ const generator = model.run({ prompt: "test" } as any);
29
+ const results = [];
30
+ for await (const res of generator) {
31
+ results.push(res);
32
+ }
33
+
34
+ expect(results).toEqual([{ text: "hello" }]);
35
+ expect(mockMainModel.run).toHaveBeenCalled();
36
+ });
37
+
38
+ it("should fallback to next model on failure", async () => {
39
+ const mockMainModel = {
40
+ run: vi.fn().mockImplementation(async function* () {
41
+ throw new Error("Main model failed");
42
+ }),
43
+ };
44
+ const mockFallbackModel = {
45
+ run: vi.fn().mockImplementation(async function* () {
46
+ yield { text: "fallback success" };
47
+ }),
48
+ };
49
+
50
+ const MockMainClass = vi.fn().mockImplementation(function () {
51
+ return mockMainModel;
52
+ });
53
+ const MockFallbackClass = vi.fn().mockImplementation(function () {
54
+ return mockFallbackModel;
55
+ });
56
+
57
+ vi.mocked(resolveLlmModel).mockImplementation((name) => {
58
+ if (name === "main-model") return MockMainClass as any;
59
+ if (name === "fallback-model") return MockFallbackClass as any;
60
+ throw new Error("Unknown model");
61
+ });
62
+
63
+ const model = new AdaptiveLlmModel({
64
+ main: { modelName: "main-model", apiKey: "key" },
65
+ fallback: [{ modelName: "fallback-model", apiKey: "key" }],
66
+ });
67
+
68
+ const generator = model.run({ prompt: "test" } as any);
69
+ const results = [];
70
+ for await (const res of generator) {
71
+ results.push(res);
72
+ }
73
+
74
+ expect(results).toEqual([{ text: "fallback success" }]);
75
+ expect(mockMainModel.run).toHaveBeenCalled();
76
+ expect(mockFallbackModel.run).toHaveBeenCalled();
77
+ });
78
+
79
+ it("should fail if all models fail", async () => {
80
+ const mockMainModel = {
81
+ run: vi.fn().mockImplementation(async function* () {
82
+ throw new Error("Main model failed");
83
+ }),
84
+ };
85
+ const mockFallbackModel = {
86
+ run: vi.fn().mockImplementation(async function* () {
87
+ throw new Error("Fallback model failed");
88
+ }),
89
+ };
90
+
91
+ const MockMainClass = vi.fn().mockImplementation(function () {
92
+ return mockMainModel;
93
+ });
94
+ const MockFallbackClass = vi.fn().mockImplementation(function () {
95
+ return mockFallbackModel;
96
+ });
97
+
98
+ vi.mocked(resolveLlmModel).mockImplementation((name) => {
99
+ if (name === "main-model") return MockMainClass as any;
100
+ if (name === "fallback-model") return MockFallbackClass as any;
101
+ throw new Error("Unknown model");
102
+ });
103
+
104
+ const model = new AdaptiveLlmModel({
105
+ main: { modelName: "main-model", apiKey: "key" },
106
+ fallback: [{ modelName: "fallback-model", apiKey: "key" }],
107
+ });
108
+
109
+ const generator = model.run({ prompt: "test" } as any);
110
+ const results = [];
111
+ for await (const res of generator) {
112
+ results.push(res);
113
+ }
114
+
115
+ expect(results).toEqual([
116
+ {
117
+ errorCode: "ADAPTIVE_MODEL_ALL_FALLBACKS_FAILED",
118
+ errorMessage: "All fallback models failed.",
119
+ },
120
+ ]);
121
+ });
122
+ });
@@ -0,0 +1,121 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { CompactionProcessor } from "../../../../src/agent/request_processor/compaction_processor.js";
3
+ import { AgentEventType } from "../../../../src/agent/agent_event.js";
4
+
5
+ describe("CompactionProcessor", () => {
6
+ const mockModel = {
7
+ countTokens: vi.fn().mockResolvedValue(100),
8
+ run: vi.fn(),
9
+ };
10
+
11
+ beforeEach(() => {
12
+ vi.clearAllMocks();
13
+ });
14
+
15
+ it("should do nothing if disabled", async () => {
16
+ const processor = new CompactionProcessor({
17
+ model: mockModel as any,
18
+ compactionConfig: {
19
+ enabled: false,
20
+ strategy: "truncate",
21
+ maxTokens: 1000,
22
+ },
23
+ requestBuilderOptions: {} as any,
24
+ streamId: "123",
25
+ });
26
+
27
+ const state = {
28
+ historyContent: [
29
+ {
30
+ role: "user" as const,
31
+ parts: [{ type: "text" as const, text: "hi" }],
32
+ },
33
+ ],
34
+ llmRequest: {} as any,
35
+ events: [],
36
+ };
37
+
38
+ const newState = await processor.process(state);
39
+ expect(newState).toBe(state);
40
+ });
41
+
42
+ it("should do nothing if below threshold", async () => {
43
+ const processor = new CompactionProcessor({
44
+ model: mockModel as any,
45
+ compactionConfig: {
46
+ enabled: true,
47
+ strategy: "truncate",
48
+ maxTokens: 1000,
49
+ triggerThreshold: 0.8,
50
+ },
51
+ requestBuilderOptions: {} as any,
52
+ streamId: "123",
53
+ });
54
+
55
+ const state = {
56
+ historyContent: [
57
+ {
58
+ role: "user" as const,
59
+ parts: [{ type: "text" as const, text: "hi" }],
60
+ },
61
+ ],
62
+ llmRequest: {} as any,
63
+ events: [],
64
+ };
65
+
66
+ mockModel.countTokens.mockResolvedValue(500); // 500 < 800
67
+
68
+ const newState = await processor.process(state);
69
+ expect(newState).toBe(state);
70
+ });
71
+
72
+ it("should truncate history when exceeded", async () => {
73
+ const processor = new CompactionProcessor({
74
+ model: mockModel as any,
75
+ compactionConfig: {
76
+ enabled: true,
77
+ strategy: "truncate",
78
+ maxTokens: 1000,
79
+ triggerThreshold: 0.8,
80
+ },
81
+ requestBuilderOptions: {
82
+ agentName: "test",
83
+ instructions: "test",
84
+ tools: [],
85
+ } as any,
86
+ streamId: "123",
87
+ });
88
+
89
+ const state = {
90
+ historyContent: [
91
+ {
92
+ role: "user" as const,
93
+ parts: [{ type: "text" as const, text: "m1" }],
94
+ },
95
+ {
96
+ role: "agent" as const,
97
+ parts: [{ type: "text" as const, text: "r1" }],
98
+ },
99
+ {
100
+ role: "user" as const,
101
+ parts: [{ type: "text" as const, text: "m2" }],
102
+ },
103
+ {
104
+ role: "agent" as const,
105
+ parts: [{ type: "text" as const, text: "r2" }],
106
+ },
107
+ ],
108
+ llmRequest: { contents: [] } as any,
109
+ events: [],
110
+ };
111
+
112
+ mockModel.countTokens.mockResolvedValue(900); // 900 > 800
113
+
114
+ const newState = await processor.process(state);
115
+ expect(newState.historyContent.length).toBeLessThan(
116
+ state.historyContent.length,
117
+ );
118
+ expect(newState.events.length).toBe(1);
119
+ expect(newState.events[0].type).toBe(AgentEventType.COMPACTION);
120
+ });
121
+ });