@nogataka/smart-edit 0.0.14

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 (186) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +244 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +7 -0
  5. package/dist/devtools/generate_prompt_factory.d.ts +5 -0
  6. package/dist/devtools/generate_prompt_factory.js +114 -0
  7. package/dist/index.d.ts +34 -0
  8. package/dist/index.js +34 -0
  9. package/dist/interprompt/index.d.ts +2 -0
  10. package/dist/interprompt/index.js +1 -0
  11. package/dist/interprompt/jinja_template.d.ts +10 -0
  12. package/dist/interprompt/jinja_template.js +174 -0
  13. package/dist/interprompt/multilang_prompt.d.ts +54 -0
  14. package/dist/interprompt/multilang_prompt.js +302 -0
  15. package/dist/interprompt/prompt_factory.d.ts +16 -0
  16. package/dist/interprompt/prompt_factory.js +189 -0
  17. package/dist/interprompt/util/class_decorators.d.ts +1 -0
  18. package/dist/interprompt/util/class_decorators.js +1 -0
  19. package/dist/interprompt/util/index.d.ts +1 -0
  20. package/dist/interprompt/util/index.js +1 -0
  21. package/dist/serena/agent.d.ts +118 -0
  22. package/dist/serena/agent.js +675 -0
  23. package/dist/serena/agno.d.ts +111 -0
  24. package/dist/serena/agno.js +278 -0
  25. package/dist/serena/analytics.d.ts +24 -0
  26. package/dist/serena/analytics.js +119 -0
  27. package/dist/serena/cli.d.ts +9 -0
  28. package/dist/serena/cli.js +731 -0
  29. package/dist/serena/code_editor.d.ts +42 -0
  30. package/dist/serena/code_editor.js +239 -0
  31. package/dist/serena/config/context_mode.d.ts +41 -0
  32. package/dist/serena/config/context_mode.js +239 -0
  33. package/dist/serena/config/serena_config.d.ts +134 -0
  34. package/dist/serena/config/serena_config.js +718 -0
  35. package/dist/serena/constants.d.ts +18 -0
  36. package/dist/serena/constants.js +27 -0
  37. package/dist/serena/dashboard.d.ts +55 -0
  38. package/dist/serena/dashboard.js +472 -0
  39. package/dist/serena/generated/generated_prompt_factory.d.ts +27 -0
  40. package/dist/serena/generated/generated_prompt_factory.js +42 -0
  41. package/dist/serena/gui_log_viewer.d.ts +41 -0
  42. package/dist/serena/gui_log_viewer.js +436 -0
  43. package/dist/serena/mcp.d.ts +118 -0
  44. package/dist/serena/mcp.js +904 -0
  45. package/dist/serena/project.d.ts +62 -0
  46. package/dist/serena/project.js +321 -0
  47. package/dist/serena/prompt_factory.d.ts +20 -0
  48. package/dist/serena/prompt_factory.js +42 -0
  49. package/dist/serena/resources/config/contexts/agent.yml +8 -0
  50. package/dist/serena/resources/config/contexts/chatgpt.yml +28 -0
  51. package/dist/serena/resources/config/contexts/codex.yml +27 -0
  52. package/dist/serena/resources/config/contexts/context.template.yml +11 -0
  53. package/dist/serena/resources/config/contexts/desktop-app.yml +17 -0
  54. package/dist/serena/resources/config/contexts/ide-assistant.yml +26 -0
  55. package/dist/serena/resources/config/contexts/oaicompat-agent.yml +8 -0
  56. package/dist/serena/resources/config/internal_modes/jetbrains.yml +15 -0
  57. package/dist/serena/resources/config/modes/editing.yml +112 -0
  58. package/dist/serena/resources/config/modes/interactive.yml +11 -0
  59. package/dist/serena/resources/config/modes/mode.template.yml +7 -0
  60. package/dist/serena/resources/config/modes/no-onboarding.yml +8 -0
  61. package/dist/serena/resources/config/modes/onboarding.yml +16 -0
  62. package/dist/serena/resources/config/modes/one-shot.yml +15 -0
  63. package/dist/serena/resources/config/modes/planning.yml +15 -0
  64. package/dist/serena/resources/config/prompt_templates/simple_tool_outputs.yml +75 -0
  65. package/dist/serena/resources/config/prompt_templates/system_prompt.yml +66 -0
  66. package/dist/serena/resources/dashboard/dashboard.js +815 -0
  67. package/dist/serena/resources/dashboard/index.html +314 -0
  68. package/dist/serena/resources/dashboard/jquery.min.js +3 -0
  69. package/dist/serena/resources/dashboard/serena-icon-16.png +0 -0
  70. package/dist/serena/resources/dashboard/serena-icon-32.png +0 -0
  71. package/dist/serena/resources/dashboard/serena-icon-48.png +0 -0
  72. package/dist/serena/resources/dashboard/serena-logs-dark-mode.png +0 -0
  73. package/dist/serena/resources/dashboard/serena-logs.png +0 -0
  74. package/dist/serena/resources/project.template.yml +67 -0
  75. package/dist/serena/resources/serena_config.template.yml +85 -0
  76. package/dist/serena/symbol.d.ts +199 -0
  77. package/dist/serena/symbol.js +616 -0
  78. package/dist/serena/text_utils.d.ts +51 -0
  79. package/dist/serena/text_utils.js +267 -0
  80. package/dist/serena/tools/cmd_tools.d.ts +31 -0
  81. package/dist/serena/tools/cmd_tools.js +48 -0
  82. package/dist/serena/tools/config_tools.d.ts +53 -0
  83. package/dist/serena/tools/config_tools.js +176 -0
  84. package/dist/serena/tools/file_tools.d.ts +231 -0
  85. package/dist/serena/tools/file_tools.js +511 -0
  86. package/dist/serena/tools/index.d.ts +7 -0
  87. package/dist/serena/tools/index.js +7 -0
  88. package/dist/serena/tools/memory_tools.d.ts +60 -0
  89. package/dist/serena/tools/memory_tools.js +135 -0
  90. package/dist/serena/tools/symbol_tools.d.ts +165 -0
  91. package/dist/serena/tools/symbol_tools.js +362 -0
  92. package/dist/serena/tools/tools_base.d.ts +162 -0
  93. package/dist/serena/tools/tools_base.js +378 -0
  94. package/dist/serena/tools/workflow_tools.d.ts +35 -0
  95. package/dist/serena/tools/workflow_tools.js +161 -0
  96. package/dist/serena/util/class_decorators.d.ts +7 -0
  97. package/dist/serena/util/class_decorators.js +37 -0
  98. package/dist/serena/util/exception.d.ts +8 -0
  99. package/dist/serena/util/exception.js +53 -0
  100. package/dist/serena/util/file_system.d.ts +30 -0
  101. package/dist/serena/util/file_system.js +352 -0
  102. package/dist/serena/util/general.d.ts +11 -0
  103. package/dist/serena/util/general.js +42 -0
  104. package/dist/serena/util/git.d.ts +11 -0
  105. package/dist/serena/util/git.js +37 -0
  106. package/dist/serena/util/inspection.d.ts +45 -0
  107. package/dist/serena/util/inspection.js +221 -0
  108. package/dist/serena/util/logging.d.ts +46 -0
  109. package/dist/serena/util/logging.js +205 -0
  110. package/dist/serena/util/shell.d.ts +21 -0
  111. package/dist/serena/util/shell.js +95 -0
  112. package/dist/serena/util/thread.d.ts +23 -0
  113. package/dist/serena/util/thread.js +88 -0
  114. package/dist/serena/version.d.ts +1 -0
  115. package/dist/serena/version.js +23 -0
  116. package/dist/solidlsp/language_servers/autoload.d.ts +23 -0
  117. package/dist/solidlsp/language_servers/autoload.js +25 -0
  118. package/dist/solidlsp/language_servers/bash_language_server.d.ts +10 -0
  119. package/dist/solidlsp/language_servers/bash_language_server.js +64 -0
  120. package/dist/solidlsp/language_servers/clangd_language_server.d.ts +13 -0
  121. package/dist/solidlsp/language_servers/clangd_language_server.js +110 -0
  122. package/dist/solidlsp/language_servers/clojure_lsp.d.ts +13 -0
  123. package/dist/solidlsp/language_servers/clojure_lsp.js +137 -0
  124. package/dist/solidlsp/language_servers/common.d.ts +41 -0
  125. package/dist/solidlsp/language_servers/common.js +365 -0
  126. package/dist/solidlsp/language_servers/csharp_language_server.d.ts +21 -0
  127. package/dist/solidlsp/language_servers/csharp_language_server.js +694 -0
  128. package/dist/solidlsp/language_servers/dart_language_server.d.ts +10 -0
  129. package/dist/solidlsp/language_servers/dart_language_server.js +122 -0
  130. package/dist/solidlsp/language_servers/eclipse_jdtls.d.ts +24 -0
  131. package/dist/solidlsp/language_servers/eclipse_jdtls.js +671 -0
  132. package/dist/solidlsp/language_servers/erlang_language_server.d.ts +22 -0
  133. package/dist/solidlsp/language_servers/erlang_language_server.js +327 -0
  134. package/dist/solidlsp/language_servers/gopls.d.ts +12 -0
  135. package/dist/solidlsp/language_servers/gopls.js +59 -0
  136. package/dist/solidlsp/language_servers/intelephense.d.ts +13 -0
  137. package/dist/solidlsp/language_servers/intelephense.js +121 -0
  138. package/dist/solidlsp/language_servers/jedi_server.d.ts +18 -0
  139. package/dist/solidlsp/language_servers/jedi_server.js +234 -0
  140. package/dist/solidlsp/language_servers/kotlin_language_server.d.ts +19 -0
  141. package/dist/solidlsp/language_servers/kotlin_language_server.js +474 -0
  142. package/dist/solidlsp/language_servers/lua_ls.d.ts +18 -0
  143. package/dist/solidlsp/language_servers/lua_ls.js +319 -0
  144. package/dist/solidlsp/language_servers/nixd_language_server.d.ts +17 -0
  145. package/dist/solidlsp/language_servers/nixd_language_server.js +341 -0
  146. package/dist/solidlsp/language_servers/pyright_server.d.ts +19 -0
  147. package/dist/solidlsp/language_servers/pyright_server.js +180 -0
  148. package/dist/solidlsp/language_servers/r_language_server.d.ts +19 -0
  149. package/dist/solidlsp/language_servers/r_language_server.js +184 -0
  150. package/dist/solidlsp/language_servers/ruby_common.d.ts +10 -0
  151. package/dist/solidlsp/language_servers/ruby_common.js +136 -0
  152. package/dist/solidlsp/language_servers/ruby_lsp.d.ts +18 -0
  153. package/dist/solidlsp/language_servers/ruby_lsp.js +230 -0
  154. package/dist/solidlsp/language_servers/rust_analyzer.d.ts +13 -0
  155. package/dist/solidlsp/language_servers/rust_analyzer.js +96 -0
  156. package/dist/solidlsp/language_servers/solargraph.d.ts +18 -0
  157. package/dist/solidlsp/language_servers/solargraph.js +208 -0
  158. package/dist/solidlsp/language_servers/sourcekit_lsp.d.ts +24 -0
  159. package/dist/solidlsp/language_servers/sourcekit_lsp.js +449 -0
  160. package/dist/solidlsp/language_servers/terraform_ls.d.ts +13 -0
  161. package/dist/solidlsp/language_servers/terraform_ls.js +139 -0
  162. package/dist/solidlsp/language_servers/typescript_language_server.d.ts +20 -0
  163. package/dist/solidlsp/language_servers/typescript_language_server.js +237 -0
  164. package/dist/solidlsp/language_servers/vts_language_server.d.ts +13 -0
  165. package/dist/solidlsp/language_servers/vts_language_server.js +121 -0
  166. package/dist/solidlsp/language_servers/zls.d.ts +20 -0
  167. package/dist/solidlsp/language_servers/zls.js +254 -0
  168. package/dist/solidlsp/ls.d.ts +197 -0
  169. package/dist/solidlsp/ls.js +507 -0
  170. package/dist/solidlsp/ls_config.d.ts +43 -0
  171. package/dist/solidlsp/ls_config.js +157 -0
  172. package/dist/solidlsp/ls_exceptions.d.ts +5 -0
  173. package/dist/solidlsp/ls_exceptions.js +14 -0
  174. package/dist/solidlsp/ls_handler.d.ts +54 -0
  175. package/dist/solidlsp/ls_handler.js +406 -0
  176. package/dist/solidlsp/ls_request.d.ts +31 -0
  177. package/dist/solidlsp/ls_request.js +42 -0
  178. package/dist/solidlsp/ls_types.d.ts +7 -0
  179. package/dist/solidlsp/ls_types.js +8 -0
  180. package/dist/solidlsp/lsp_protocol_handler/server.d.ts +61 -0
  181. package/dist/solidlsp/lsp_protocol_handler/server.js +68 -0
  182. package/dist/solidlsp/util/subprocess_util.d.ts +6 -0
  183. package/dist/solidlsp/util/subprocess_util.js +11 -0
  184. package/dist/solidlsp/util/zip.d.ts +25 -0
  185. package/dist/solidlsp/util/zip.js +188 -0
  186. package/package.json +65 -0
@@ -0,0 +1,111 @@
1
+ import type { Tool, ToolApplyFunction, ToolApplyMetadata } from './tools/tools_base.js';
2
+ import { SerenaAgent } from './agent.js';
3
+ export interface SerenaAgnoFunctionDefinition {
4
+ readonly name: string;
5
+ readonly apply: ToolApplyFunction<Record<string, unknown>, string>;
6
+ readonly entrypoint: (args: Record<string, unknown>) => Promise<string>;
7
+ readonly skipEntrypointProcessing: boolean;
8
+ readonly metadata: ToolApplyMetadata;
9
+ readonly tool: Tool;
10
+ }
11
+ export interface SerenaAgnoToolkitData {
12
+ readonly name: string;
13
+ readonly functions: Record<string, SerenaAgnoFunctionDefinition>;
14
+ readonly functionList: SerenaAgnoFunctionDefinition[];
15
+ }
16
+ export interface SerenaAgnoAgentFactoryOptions {
17
+ name: string;
18
+ model: unknown;
19
+ description: string;
20
+ toolkits: unknown[];
21
+ storage: unknown;
22
+ systemMessage: string;
23
+ showToolCalls: boolean;
24
+ markdown: boolean;
25
+ telemetry: boolean;
26
+ memory: unknown;
27
+ addHistoryToMessages: boolean;
28
+ numHistoryResponses: number;
29
+ }
30
+ export interface SerenaAgnoIntegration {
31
+ createToolkit(data: SerenaAgnoToolkitData): unknown;
32
+ createAgent(options: SerenaAgnoAgentFactoryOptions): unknown;
33
+ createMemory(): unknown;
34
+ createStorage(options: {
35
+ tableName: string;
36
+ dbFile: string;
37
+ }): unknown;
38
+ }
39
+ export declare class DefaultAgnoFunction {
40
+ readonly name: string;
41
+ entrypoint: (args: Record<string, unknown>) => Promise<string>;
42
+ skipEntrypointProcessing: boolean;
43
+ readonly apply: ToolApplyFunction<Record<string, unknown>, string>;
44
+ readonly metadata: ToolApplyMetadata;
45
+ constructor(definition: SerenaAgnoFunctionDefinition);
46
+ }
47
+ export declare class DefaultAgnoToolkit {
48
+ readonly name: string;
49
+ readonly functions: Record<string, DefaultAgnoFunction>;
50
+ constructor(data: SerenaAgnoToolkitData);
51
+ }
52
+ export declare class DefaultAgnoAgentMemory {
53
+ }
54
+ export declare class DefaultAgnoSqliteStorage {
55
+ readonly tableName: string;
56
+ readonly dbFile: string;
57
+ constructor(options: {
58
+ tableName: string;
59
+ dbFile: string;
60
+ });
61
+ }
62
+ export declare class DefaultAgnoAgent {
63
+ readonly name: string;
64
+ readonly model: unknown;
65
+ readonly description: string;
66
+ readonly toolkits: DefaultAgnoToolkit[];
67
+ readonly storage: DefaultAgnoSqliteStorage;
68
+ readonly systemMessage: string;
69
+ readonly options: Omit<SerenaAgnoAgentFactoryOptions, 'name' | 'model' | 'description' | 'toolkits' | 'storage' | 'systemMessage'>;
70
+ constructor(config: SerenaAgnoAgentFactoryOptions & {
71
+ toolkits: DefaultAgnoToolkit[];
72
+ storage: DefaultAgnoSqliteStorage;
73
+ });
74
+ toString(): string;
75
+ }
76
+ export declare class DefaultSerenaAgnoIntegration implements SerenaAgnoIntegration {
77
+ createToolkit(data: SerenaAgnoToolkitData): DefaultAgnoToolkit;
78
+ createAgent(options: SerenaAgnoAgentFactoryOptions): DefaultAgnoAgent;
79
+ createMemory(): DefaultAgnoAgentMemory;
80
+ createStorage(options: {
81
+ tableName: string;
82
+ dbFile: string;
83
+ }): DefaultAgnoSqliteStorage;
84
+ }
85
+ export declare function configureSerenaAgnoIntegration(integration: SerenaAgnoIntegration): void;
86
+ export declare function getSerenaAgnoIntegration(): SerenaAgnoIntegration;
87
+ export declare class SerenaAgnoToolkit {
88
+ readonly name: string;
89
+ readonly functions: Record<string, SerenaAgnoFunctionDefinition>;
90
+ constructor(serenaAgent: {
91
+ getExposedToolInstances(): Iterable<Tool>;
92
+ });
93
+ toToolkitData(): SerenaAgnoToolkitData;
94
+ buildToolkit(integration?: SerenaAgnoIntegration): unknown;
95
+ static createFunctionDefinition(tool: Tool): SerenaAgnoFunctionDefinition;
96
+ }
97
+ export interface SerenaAgnoAgentProviderOptions {
98
+ argv?: string[];
99
+ integration?: SerenaAgnoIntegration;
100
+ projectFileOverride?: string | null;
101
+ serenaAgentFactory?: (projectFile: string | null) => SerenaAgent;
102
+ }
103
+ export declare class SerenaAgnoAgentProvider {
104
+ private static agent;
105
+ private static serenaAgentFactoryOverride;
106
+ static configure(options?: {
107
+ serenaAgentFactory?: (projectFile: string | null) => SerenaAgent;
108
+ }): void;
109
+ static reset(): void;
110
+ static getAgent(model: unknown, options?: SerenaAgnoAgentProviderOptions): unknown;
111
+ }
@@ -0,0 +1,278 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import process from 'node:process';
4
+ import { createRequire } from 'node:module';
5
+ import { createSerenaLogger } from './util/logging.js';
6
+ import { REPO_ROOT } from './constants.js';
7
+ import { SerenaAgent } from './agent.js';
8
+ import { SerenaAgentContext } from './config/context_mode.js';
9
+ import { showFatalExceptionSafe } from './util/exception.js';
10
+ const { logger: log } = createSerenaLogger({ name: 'serena.agno' });
11
+ const DEFAULT_TOOLKIT_NAME = 'Serena';
12
+ const DEFAULT_SQLITE_TABLE_NAME = 'serena_agent_sessions';
13
+ const DEFAULT_SQLITE_RELATIVE_PATH = path.join('temp', 'agno_agent_storage.db');
14
+ function now() {
15
+ return process.hrtime.bigint();
16
+ }
17
+ function formatDurationMs(start, end) {
18
+ const durationMs = Number(end - start) / 1_000_000;
19
+ return `${durationMs.toFixed(2)}ms`;
20
+ }
21
+ function loadDotenvIfAvailable() {
22
+ try {
23
+ const require = createRequire(import.meta.url);
24
+ const maybeDotenv = require('dotenv');
25
+ if (maybeDotenv && typeof maybeDotenv.config === 'function') {
26
+ maybeDotenv.config();
27
+ log.debug('Loaded environment variables using dotenv.');
28
+ }
29
+ }
30
+ catch (error) {
31
+ log.debug(`dotenv not available or failed to load: ${String(error)}`);
32
+ }
33
+ }
34
+ export class DefaultAgnoFunction {
35
+ name;
36
+ entrypoint;
37
+ skipEntrypointProcessing;
38
+ apply;
39
+ metadata;
40
+ constructor(definition) {
41
+ this.name = definition.name;
42
+ this.apply = definition.apply;
43
+ this.entrypoint = definition.entrypoint;
44
+ this.skipEntrypointProcessing = definition.skipEntrypointProcessing;
45
+ this.metadata = definition.metadata;
46
+ }
47
+ }
48
+ export class DefaultAgnoToolkit {
49
+ name;
50
+ functions = {};
51
+ constructor(data) {
52
+ this.name = data.name;
53
+ for (const definition of data.functionList) {
54
+ this.functions[definition.name] = new DefaultAgnoFunction(definition);
55
+ }
56
+ }
57
+ }
58
+ export class DefaultAgnoAgentMemory {
59
+ }
60
+ export class DefaultAgnoSqliteStorage {
61
+ tableName;
62
+ dbFile;
63
+ constructor(options) {
64
+ this.tableName = options.tableName;
65
+ this.dbFile = options.dbFile;
66
+ }
67
+ }
68
+ export class DefaultAgnoAgent {
69
+ name;
70
+ model;
71
+ description;
72
+ toolkits;
73
+ storage;
74
+ systemMessage;
75
+ options;
76
+ constructor(config) {
77
+ this.name = config.name;
78
+ this.model = config.model;
79
+ this.description = config.description;
80
+ this.toolkits = config.toolkits;
81
+ this.storage = config.storage;
82
+ this.systemMessage = config.systemMessage;
83
+ this.options = {
84
+ addHistoryToMessages: config.addHistoryToMessages,
85
+ markdown: config.markdown,
86
+ memory: config.memory,
87
+ numHistoryResponses: config.numHistoryResponses,
88
+ showToolCalls: config.showToolCalls,
89
+ telemetry: config.telemetry
90
+ };
91
+ }
92
+ toString() {
93
+ return `${this.name} Agent (toolkits=${this.toolkits.length})`;
94
+ }
95
+ }
96
+ export class DefaultSerenaAgnoIntegration {
97
+ createToolkit(data) {
98
+ return new DefaultAgnoToolkit(data);
99
+ }
100
+ createAgent(options) {
101
+ const storage = options.storage instanceof DefaultAgnoSqliteStorage
102
+ ? options.storage
103
+ : new DefaultAgnoSqliteStorage({
104
+ tableName: DEFAULT_SQLITE_TABLE_NAME,
105
+ dbFile: path.resolve(REPO_ROOT, DEFAULT_SQLITE_RELATIVE_PATH)
106
+ });
107
+ const toolkits = options.toolkits.map((toolkit) => toolkit instanceof DefaultAgnoToolkit
108
+ ? toolkit
109
+ : new DefaultAgnoToolkit({ name: DEFAULT_TOOLKIT_NAME, functions: {}, functionList: [] }));
110
+ const configWithDefaults = {
111
+ name: options.name,
112
+ model: options.model,
113
+ description: options.description,
114
+ toolkits,
115
+ storage,
116
+ systemMessage: options.systemMessage,
117
+ showToolCalls: options.showToolCalls,
118
+ markdown: options.markdown,
119
+ telemetry: options.telemetry,
120
+ memory: options.memory,
121
+ addHistoryToMessages: options.addHistoryToMessages,
122
+ numHistoryResponses: options.numHistoryResponses
123
+ };
124
+ return new DefaultAgnoAgent(configWithDefaults);
125
+ }
126
+ createMemory() {
127
+ return new DefaultAgnoAgentMemory();
128
+ }
129
+ createStorage(options) {
130
+ return new DefaultAgnoSqliteStorage(options);
131
+ }
132
+ }
133
+ let activeIntegration = new DefaultSerenaAgnoIntegration();
134
+ export function configureSerenaAgnoIntegration(integration) {
135
+ activeIntegration = integration;
136
+ }
137
+ export function getSerenaAgnoIntegration() {
138
+ return activeIntegration;
139
+ }
140
+ function normalizeKwargs(rawArgs) {
141
+ if (!('kwargs' in rawArgs)) {
142
+ return { ...rawArgs };
143
+ }
144
+ const { kwargs, ...rest } = rawArgs;
145
+ if (kwargs && typeof kwargs === 'object' && !Array.isArray(kwargs)) {
146
+ return { ...rest, ...kwargs };
147
+ }
148
+ return rest;
149
+ }
150
+ function resolveProjectArgument(argv) {
151
+ let pendingFlag = null;
152
+ for (const arg of argv) {
153
+ if (pendingFlag) {
154
+ return typeof arg === 'string' ? arg : null;
155
+ }
156
+ if (arg.startsWith('--project=')) {
157
+ return arg.slice('--project='.length);
158
+ }
159
+ if (arg.startsWith('--project-file=')) {
160
+ return arg.slice('--project-file='.length);
161
+ }
162
+ if (arg === '--project' || arg === '--project-file') {
163
+ pendingFlag = arg;
164
+ }
165
+ }
166
+ return null;
167
+ }
168
+ export class SerenaAgnoToolkit {
169
+ name = DEFAULT_TOOLKIT_NAME;
170
+ functions = {};
171
+ constructor(serenaAgent) {
172
+ const toolInstances = serenaAgent.getExposedToolInstances();
173
+ for (const tool of toolInstances) {
174
+ const definition = SerenaAgnoToolkit.createFunctionDefinition(tool);
175
+ this.functions[definition.name] = definition;
176
+ }
177
+ log.info(`Agno agent functions: ${Object.keys(this.functions).join(', ')}`);
178
+ }
179
+ toToolkitData() {
180
+ const functionList = Object.values(this.functions);
181
+ return {
182
+ name: this.name,
183
+ functions: { ...this.functions },
184
+ functionList
185
+ };
186
+ }
187
+ buildToolkit(integration = getSerenaAgnoIntegration()) {
188
+ return integration.createToolkit(this.toToolkitData());
189
+ }
190
+ static createFunctionDefinition(tool) {
191
+ const toolClass = tool.constructor;
192
+ const name = toolClass.getNameFromCls();
193
+ const applyFn = tool.getApplyFn();
194
+ const metadata = tool.getApplyFnMetadata();
195
+ const entrypoint = async (rawArgs) => {
196
+ const normalizedArgs = normalizeKwargs(rawArgs);
197
+ log.info(`Calling tool ${toolClass.name}`);
198
+ return tool.applyEx(normalizedArgs, {
199
+ logCall: true,
200
+ catchExceptions: true
201
+ });
202
+ };
203
+ return {
204
+ name,
205
+ apply: applyFn,
206
+ entrypoint,
207
+ skipEntrypointProcessing: true,
208
+ metadata,
209
+ tool
210
+ };
211
+ }
212
+ }
213
+ export class SerenaAgnoAgentProvider {
214
+ static agent = null;
215
+ static serenaAgentFactoryOverride = null;
216
+ static configure(options = {}) {
217
+ this.serenaAgentFactoryOverride = options.serenaAgentFactory ?? null;
218
+ }
219
+ static reset() {
220
+ this.agent = null;
221
+ }
222
+ static getAgent(model, options = {}) {
223
+ if (this.agent) {
224
+ return this.agent;
225
+ }
226
+ process.chdir(REPO_ROOT);
227
+ loadDotenvIfAvailable();
228
+ const argv = options.argv ?? process.argv.slice(2);
229
+ const projectFlagValue = options.projectFileOverride ?? resolveProjectArgument(argv);
230
+ const projectFile = projectFlagValue ? path.resolve(projectFlagValue) : null;
231
+ const start = now();
232
+ let serenaAgent;
233
+ try {
234
+ const factory = options.serenaAgentFactory ?? this.serenaAgentFactoryOverride ?? ((project) => new SerenaAgent({
235
+ project: project ?? undefined,
236
+ context: SerenaAgentContext.load('agent')
237
+ }));
238
+ serenaAgent = factory(projectFile);
239
+ }
240
+ catch (error) {
241
+ void showFatalExceptionSafe(error);
242
+ throw error;
243
+ }
244
+ const end = now();
245
+ log.info(`Loading Serena agent finished in ${formatDurationMs(start, end)}`);
246
+ const toolkit = new SerenaAgnoToolkit(serenaAgent);
247
+ const integration = options.integration ?? getSerenaAgnoIntegration();
248
+ const toolkitInstance = toolkit.buildToolkit(integration);
249
+ const sqlitePath = path.resolve(REPO_ROOT, DEFAULT_SQLITE_RELATIVE_PATH);
250
+ fs.mkdirSync(path.dirname(sqlitePath), { recursive: true });
251
+ log.info(`Deleting DB from PID ${process.pid}`);
252
+ if (fs.existsSync(sqlitePath)) {
253
+ fs.rmSync(sqlitePath);
254
+ }
255
+ const storage = integration.createStorage({
256
+ tableName: DEFAULT_SQLITE_TABLE_NAME,
257
+ dbFile: sqlitePath
258
+ });
259
+ const memory = integration.createMemory();
260
+ const agent = integration.createAgent({
261
+ name: DEFAULT_TOOLKIT_NAME,
262
+ model,
263
+ description: 'A fully-featured coding assistant',
264
+ toolkits: [toolkitInstance],
265
+ storage,
266
+ systemMessage: serenaAgent.createSystemPrompt(),
267
+ showToolCalls: false,
268
+ markdown: true,
269
+ telemetry: false,
270
+ memory,
271
+ addHistoryToMessages: true,
272
+ numHistoryResponses: 100
273
+ });
274
+ this.agent = agent;
275
+ log.info(`Agent instantiated: ${String(agent)}`);
276
+ return agent;
277
+ }
278
+ }
@@ -0,0 +1,24 @@
1
+ import { RegisteredTokenCountEstimator } from './config/serena_config.js';
2
+ export interface TokenCountEstimator {
3
+ estimateTokenCount(text: string): number;
4
+ }
5
+ export declare class ToolUsageStatsEntry {
6
+ numTimesCalled: number;
7
+ inputTokens: number;
8
+ outputTokens: number;
9
+ constructor(numTimesCalled?: number, inputTokens?: number, outputTokens?: number);
10
+ updateOnCall(inputTokens: number, outputTokens: number): void;
11
+ clone(): ToolUsageStatsEntry;
12
+ }
13
+ export declare class ToolUsageStats {
14
+ private readonly estimator;
15
+ private readonly estimatorName;
16
+ private readonly stats;
17
+ constructor(registry?: RegisteredTokenCountEstimator);
18
+ get tokenEstimatorName(): string;
19
+ clear(): void;
20
+ getStats(toolName: string): ToolUsageStatsEntry;
21
+ getToolStatsDict(): Record<string, Record<string, number>>;
22
+ recordToolUsage(toolName: string, input: string, output: string): void;
23
+ }
24
+ export declare function __internalResetEstimatorCacheForTests(): void;
@@ -0,0 +1,119 @@
1
+ import { encoding_for_model } from '@dqbd/tiktoken';
2
+ import { createSerenaLogger } from './util/logging.js';
3
+ import { RegisteredTokenCountEstimator } from './config/serena_config.js';
4
+ const { logger } = createSerenaLogger({ name: 'serena.analytics', emitToConsole: false, level: 'info' });
5
+ const DEFAULT_TIKTOKEN_MODEL = 'gpt-4o';
6
+ class ApproximateTokenCountEstimator {
7
+ estimateTokenCount(text) {
8
+ const normalized = text.replace(/\s+/g, ' ').trim();
9
+ if (normalized.length === 0) {
10
+ return 0;
11
+ }
12
+ const roughWordCount = normalized.split(' ').length;
13
+ return Math.max(1, Math.round((normalized.length + roughWordCount * 2) / 4));
14
+ }
15
+ }
16
+ class TiktokenCountEstimator {
17
+ modelName;
18
+ encoding;
19
+ constructor(modelName) {
20
+ this.modelName = modelName;
21
+ this.encoding = encoding_for_model(modelName);
22
+ logger.info(`Loading tiktoken encoding for model ${modelName}, this may take a while on the first run.`);
23
+ }
24
+ estimateTokenCount(text) {
25
+ if (text.length === 0) {
26
+ return 0;
27
+ }
28
+ return this.encoding.encode(text).length;
29
+ }
30
+ }
31
+ class AnthropicTokenCountEstimator {
32
+ estimateTokenCount(text) {
33
+ logger.warn('Anthropic token counting is not yet implemented in Node; using approximate estimator.');
34
+ return approximateEstimator.estimateTokenCount(text);
35
+ }
36
+ }
37
+ const approximateEstimator = new ApproximateTokenCountEstimator();
38
+ const estimatorCache = new Map();
39
+ function createEstimator(registry) {
40
+ try {
41
+ switch (registry) {
42
+ case RegisteredTokenCountEstimator.TIKTOKEN_GPT4O:
43
+ return new TiktokenCountEstimator(DEFAULT_TIKTOKEN_MODEL);
44
+ case RegisteredTokenCountEstimator.ANTHROPIC_CLAUDE_SONNET_4:
45
+ return new AnthropicTokenCountEstimator();
46
+ default:
47
+ logger.warn(`Unknown token count estimator '${String(registry)}', using approximate fallback.`);
48
+ return approximateEstimator;
49
+ }
50
+ }
51
+ catch (error) {
52
+ logger.error(`Failed to initialize estimator '${String(registry)}': ${error.message}. Falling back to approximate estimator.`);
53
+ return approximateEstimator;
54
+ }
55
+ }
56
+ export class ToolUsageStatsEntry {
57
+ numTimesCalled;
58
+ inputTokens;
59
+ outputTokens;
60
+ constructor(numTimesCalled = 0, inputTokens = 0, outputTokens = 0) {
61
+ this.numTimesCalled = numTimesCalled;
62
+ this.inputTokens = inputTokens;
63
+ this.outputTokens = outputTokens;
64
+ }
65
+ updateOnCall(inputTokens, outputTokens) {
66
+ this.numTimesCalled += 1;
67
+ this.inputTokens += inputTokens;
68
+ this.outputTokens += outputTokens;
69
+ }
70
+ clone() {
71
+ return new ToolUsageStatsEntry(this.numTimesCalled, this.inputTokens, this.outputTokens);
72
+ }
73
+ }
74
+ export class ToolUsageStats {
75
+ estimator;
76
+ estimatorName;
77
+ stats = new Map();
78
+ constructor(registry = RegisteredTokenCountEstimator.TIKTOKEN_GPT4O) {
79
+ let estimator = estimatorCache.get(registry);
80
+ if (!estimator) {
81
+ estimator = createEstimator(registry);
82
+ estimatorCache.set(registry, estimator);
83
+ }
84
+ this.estimator = estimator;
85
+ this.estimatorName = registry;
86
+ }
87
+ get tokenEstimatorName() {
88
+ return this.estimatorName;
89
+ }
90
+ clear() {
91
+ this.stats.clear();
92
+ }
93
+ getStats(toolName) {
94
+ const entry = this.stats.get(toolName);
95
+ if (entry) {
96
+ return entry.clone();
97
+ }
98
+ return new ToolUsageStatsEntry();
99
+ }
100
+ getToolStatsDict() {
101
+ const result = {};
102
+ for (const [toolName, entry] of this.stats) {
103
+ result[toolName] = {
104
+ numTimesCalled: entry.numTimesCalled,
105
+ inputTokens: entry.inputTokens,
106
+ outputTokens: entry.outputTokens
107
+ };
108
+ }
109
+ return result;
110
+ }
111
+ recordToolUsage(toolName, input, output) {
112
+ const entry = this.stats.get(toolName) ?? new ToolUsageStatsEntry();
113
+ entry.updateOnCall(this.estimator.estimateTokenCount(input), this.estimator.estimateTokenCount(output));
114
+ this.stats.set(toolName, entry);
115
+ }
116
+ }
117
+ export function __internalResetEstimatorCacheForTests() {
118
+ estimatorCache.clear();
119
+ }
@@ -0,0 +1,9 @@
1
+ import { Command } from 'commander';
2
+ interface CreateCliOptions {
3
+ writeOut?: (str: string) => void;
4
+ writeErr?: (str: string) => void;
5
+ enableExitOverride?: boolean;
6
+ }
7
+ export declare function createSerenaCli(options?: CreateCliOptions): Command;
8
+ export declare function runSerenaCli(argv?: readonly string[]): Promise<void>;
9
+ export default runSerenaCli;