Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/agent/completionHandlerRegistry.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { ConsoleCompletedHandler } from '#agent/autonomous/agentCompletion';
import { SlackChatBotService } from '#modules/slack/slackChatBotService';
import { logger } from '#o11y/logger';
import { GitLabNoteCompletedHandler } from '#routes/webhooks/gitlab/gitlabNoteHandler';
import type { AgentCompleted } from '#shared/agent/agent.model';

// Use a Map for easier addition/removal during tests
let handlersMap = new Map<string, new () => AgentCompleted>();

// Initialize with default handlers
handlersMap.set(new ConsoleCompletedHandler().agentCompletedHandlerId(), ConsoleCompletedHandler);
handlersMap.set(new SlackChatBotService().agentCompletedHandlerId(), SlackChatBotService);
handlersMap.set(new GitLabNoteCompletedHandler().agentCompletedHandlerId(), GitLabNoteCompletedHandler);
function initHandlers() {
// Initialize with default handlers
handlersMap.set(new ConsoleCompletedHandler().agentCompletedHandlerId(), ConsoleCompletedHandler);
handlersMap.set(new GitLabNoteCompletedHandler().agentCompletedHandlerId(), GitLabNoteCompletedHandler);
}

/**
* Return the AgentCompleted callback object from its id.
Expand All @@ -20,6 +20,8 @@ handlersMap.set(new GitLabNoteCompletedHandler().agentCompletedHandlerId(), GitL
export function getCompletedHandler(handlerId: string): AgentCompleted | null {
if (!handlerId) return null;

if (handlersMap.size === 0) initHandlers();

const HandlerCtor = handlersMap.get(handlerId);
if (HandlerCtor) return new HandlerCtor();

Expand Down Expand Up @@ -47,5 +49,4 @@ export function clearCompletedHandlers(): void {
handlersMap = new Map<string, new () => AgentCompleted>();
// Re-initialize with default handlers
handlersMap.set(new ConsoleCompletedHandler().agentCompletedHandlerId(), ConsoleCompletedHandler);
handlersMap.set(new SlackChatBotService().agentCompletedHandlerId(), SlackChatBotService);
}
2 changes: 0 additions & 2 deletions src/cli/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ import { logger } from '#o11y/logger';
import type { AgentContext } from '#shared/agent/agent.model';
import { registerErrorHandlers } from '../errorHandlers';
import { parseProcessArgs, saveAgentId } from './cli';
import { loadCliEnvironment } from './envLoader';
import { resolveFunctionClasses } from './functionAliases';

export async function main(): Promise<void> {
loadCliEnvironment();
registerErrorHandlers();
await initApplicationContext();
const llms = defaultLLMs();
Expand Down
2 changes: 0 additions & 2 deletions src/cli/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ import { getMarkdownFormatPrompt } from '#routes/chat/chatPromptUtils';
import { LLM, LlmMessage, UserContentExt, contentText, messageText, user } from '#shared/llm/llm.model';
import { currentUser } from '#user/userContext';
import { parseProcessArgs, saveAgentId } from './cli';
import { loadCliEnvironment } from './envLoader';
import { LLM_CLI_ALIAS } from './llmAliases';

async function main() {
loadCliEnvironment();
await initApplicationContext();

const { initialPrompt: rawPrompt, resumeAgentId, flags } = parseProcessArgs();
Expand Down
2 changes: 0 additions & 2 deletions src/cli/code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@ import { contentText, messageText } from '#shared/llm/llm.model';
import { CodeEditingAgent } from '#swe/codeEditingAgent';
import { beep } from '#utils/beep';
import { parseProcessArgs, saveAgentId } from './cli';
import { loadCliEnvironment } from './envLoader';
import { parsePromptWithImages } from './promptParser';

async function main() {
loadCliEnvironment();
await initApplicationContext();
const agentLlms: AgentLLMs = defaultLLMs();

Expand Down
2 changes: 0 additions & 2 deletions src/cli/codeAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { CodeFunctions } from '#swe/codeFunctions';
import { MorphEditor } from '#swe/morph/morphEditor';
import { registerErrorHandlers } from '../errorHandlers';
import { parseProcessArgs, saveAgentId } from './cli';
import { loadCliEnvironment } from './envLoader';
import { resolveFunctionClasses } from './functionAliases';

async function resumeAgent(resumeAgentId: string, initialPrompt: string) {
Expand All @@ -44,7 +43,6 @@ async function resumeAgent(resumeAgentId: string, initialPrompt: string) {
}

export async function main(): Promise<void> {
loadCliEnvironment();
registerErrorHandlers();
await initApplicationContext();
const llms = defaultLLMs();
Expand Down
2 changes: 0 additions & 2 deletions src/cli/commit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import { shutdownTrace } from '#fastify/trace-init/trace-init';
import { Git } from '#functions/scm/git';
import { FileSystemRead } from '#functions/storage/fileSystemRead';
import { defaultLLMs } from '#llm/services/defaultLlms';
import { loadCliEnvironment } from './envLoader';

async function main() {
loadCliEnvironment();
await initApplicationContext();
console.log('Commit command starting...');

Expand Down
2 changes: 0 additions & 2 deletions src/cli/debate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ import { logger } from '#o11y/logger';
import type { AgentLLMs } from '#shared/agent/agent.model';
import { messageText } from '#shared/llm/llm.model';
import { parseProcessArgs } from './cli';
import { loadCliEnvironment } from './envLoader';
import { parsePromptWithImages } from './promptParser';

async function main() {
loadCliEnvironment();
await initApplicationContext();
const agentLLMs: AgentLLMs = defaultLLMs();
const { initialPrompt: rawPrompt, resumeAgentId, flags } = parseProcessArgs();
Expand Down
2 changes: 0 additions & 2 deletions src/cli/easy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ import { mockLLMs } from '#llm/services/mock-llm';
import { vertexGemini_2_5_Flash } from '#llm/services/vertexai';
import type { AgentContext } from '#shared/agent/agent.model';
import { parseProcessArgs } from './cli';
import { loadCliEnvironment } from './envLoader';

// See https://arxiv.org/html/2405.19616v1 https://github.com/autogenai/easy-problems-that-llms-get-wrong
// Usage:
// npm run easy

async function main() {
loadCliEnvironment();
await initApplicationContext();

const context: AgentContext = createContext({
Expand Down
11 changes: 7 additions & 4 deletions src/cli/envLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
* When using git worktrees enables using the local.env from the main repository
* Extracted from startLocal.ts to be shared across all CLI tools.
*/

import { existsSync, readFileSync } from 'node:fs';
import { isAbsolute, resolve } from 'node:path';
import { logger } from '#o11y/logger';

interface ResolveEnvFileOptions {
envFile?: string | null;
Expand All @@ -21,6 +19,8 @@ interface ApplyEnvOptions {

type ParsedEnv = Record<string, string>;

export let loadedEnvFilePath: string | undefined;

/**
* Builds an absolute path from a potential relative path.
* @param value The path value (can be null or undefined).
Expand Down Expand Up @@ -125,9 +125,12 @@ export function applyEnvFile(filePath: string, options: ApplyEnvOptions = {}): v
export function loadCliEnvironment(options: ApplyEnvOptions = {}): void {
try {
const envFilePath = resolveEnvFilePath();
loadedEnvFilePath = envFilePath;
applyEnvFile(envFilePath, options);
logger.debug(`Loaded environment from ${envFilePath}`);
console.log(`Loaded environment from ${envFilePath}`);
} catch (err) {
logger.debug(err, 'No environment file found; continuing with existing process.env');
console.log(err, 'No environment file found; continuing with existing process.env');
}
}

loadCliEnvironment();
2 changes: 0 additions & 2 deletions src/cli/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ import micromatch from 'micromatch';
import { FileSystemService } from '#functions/storage/fileSystemService';
import { countTokens } from '#llm/tokens';
import { logger } from '#o11y/logger';
import { loadCliEnvironment } from './envLoader';

/**
* If there are no arguments then only write the exported contents to the console
* If there is the -v arg then write the additional debug info
* If there is the -f arg write it to a file. Default to export.xml. If a value is provided, e.g. -f=export2.xml then write to export2.xml
*/
async function main() {
loadCliEnvironment();
const fileSystemService = new FileSystemService();
const basePath = fileSystemService.getBasePath();

Expand Down
2 changes: 0 additions & 2 deletions src/cli/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ import type { AgentLLMs } from '#shared/agent/agent.model';
import { fastSelectFilesAgent } from '#swe/discovery/fastSelectFilesAgent';
import { selectFilesAgent } from '#swe/discovery/selectFilesAgentWithSearch';
import { parseProcessArgs } from './cli';
import { loadCliEnvironment } from './envLoader';

async function main() {
loadCliEnvironment();
await initApplicationContext();
const agentLLMs: AgentLLMs = defaultLLMs();

Expand Down
2 changes: 0 additions & 2 deletions src/cli/gaia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import type { AgentLLMs } from '#shared/agent/agent.model';
import { lastText } from '#shared/llm/llm.model';
import type { LlmCall } from '#shared/llmCall/llmCall.model';
import { sleep } from '#utils/async-utils';
import { loadCliEnvironment } from './envLoader';

const SYSTEM_PROMPT = `Finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER]. YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string.`;

Expand Down Expand Up @@ -125,7 +124,6 @@ async function answerGaiaQuestion(task: GaiaQuestion): Promise<GaiaResult> {
}

async function main() {
loadCliEnvironment();
await initApplicationContext();
const llms = defaultLLMs();

Expand Down
2 changes: 0 additions & 2 deletions src/cli/gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { countTokens } from '#llm/tokens';
import { LLM, LlmMessage, ThinkingLevel, messageSources, messageText, system, user } from '#shared/llm/llm.model';
import { beep } from '#utils/beep';
import { parseProcessArgs } from './cli';
import { loadCliEnvironment } from './envLoader';
import { LLM_CLI_ALIAS } from './llmAliases';
import { parsePromptWithImages } from './promptParser';
import { terminalLog } from './terminal';
Expand All @@ -17,7 +16,6 @@ import { terminalLog } from './terminal';
// ai gen -s="system prompt" 'input prompt'

async function main() {
loadCliEnvironment();
const { initialPrompt: rawPrompt, llmId, flags } = parseProcessArgs();
const { textPrompt, userContent } = await parsePromptWithImages(rawPrompt);

Expand Down
2 changes: 0 additions & 2 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ import { buildIndexDocs } from '#swe/index/repoIndexDocBuilder';
import { generateRepositoryMaps } from '#swe/index/repositoryMap';
import { getProjectInfos } from '#swe/projectDetection';
import { parseProcessArgs, saveAgentId } from './cli';
import { loadCliEnvironment } from './envLoader';

async function main() {
loadCliEnvironment();
await initApplicationContext();
const agentLlms: AgentLLMs = defaultLLMs();

Expand Down
2 changes: 0 additions & 2 deletions src/cli/morph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { CodeFunctions } from '#swe/codeFunctions';
import { MorphCodeAgent } from '#swe/morph/morphCoder';
import { registerErrorHandlers } from '../errorHandlers';
import { parseProcessArgs, saveAgentId } from './cli';
import { loadCliEnvironment } from './envLoader';
import { resolveFunctionClasses } from './functionAliases';

async function resumeAgent(resumeAgentId: string, initialPrompt: string) {
Expand All @@ -43,7 +42,6 @@ async function resumeAgent(resumeAgentId: string, initialPrompt: string) {
}

export async function main(): Promise<void> {
loadCliEnvironment();
registerErrorHandlers();
await initApplicationContext();
const llms = defaultLLMs();
Expand Down
2 changes: 0 additions & 2 deletions src/cli/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@ import { logger } from '#o11y/logger';
import type { AgentLLMs } from '#shared/agent/agent.model';
import { queryWithFileSelection2 } from '#swe/discovery/selectFilesAgentWithSearch';
import { parseProcessArgs, saveAgentId } from './cli';
import { loadCliEnvironment } from './envLoader';
import { parsePromptWithImages } from './promptParser';

async function main() {
loadCliEnvironment();
await initApplicationContext();
const agentLLMs: AgentLLMs = defaultLLMs();
const { initialPrompt: rawPrompt, resumeAgentId, flags } = parseProcessArgs();
Expand Down
2 changes: 0 additions & 2 deletions src/cli/research.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ import { PublicWeb } from '#functions/web/web';
import { defaultLLMs } from '#llm/services/defaultLlms';
import type { AgentLLMs } from '#shared/agent/agent.model';
import { parseProcessArgs, saveAgentId } from './cli';
import { loadCliEnvironment } from './envLoader';

// Usage:
// npm run research

const llms: AgentLLMs = defaultLLMs();

export async function main(): Promise<void> {
loadCliEnvironment();
const systemPrompt = readFileSync('src/cli/research-system', 'utf-8');

const { initialPrompt, resumeAgentId } = parseProcessArgs();
Expand Down
2 changes: 0 additions & 2 deletions src/cli/review.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ import type { AgentLLMs } from '#shared/agent/agent.model';
import { performLocalBranchCodeReview } from '#swe/codeReview/local/localCodeReview';
import { beep } from '#utils/beep';
import { parseProcessArgs } from './cli';
import { loadCliEnvironment } from './envLoader';

async function main() {
loadCliEnvironment();
await initApplicationContext();
const agentLlms: AgentLLMs = defaultLLMs();

Expand Down
2 changes: 0 additions & 2 deletions src/cli/slack.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { initApplicationContext } from '#app/applicationContext';
import { sleep } from '#utils/async-utils';
import { loadCliEnvironment } from './envLoader';

async function main() {
loadCliEnvironment();
await initApplicationContext();
const { SlackChatBotService } = await import('../modules/slack/slackModule.cjs');
const chatbot = new SlackChatBotService();
Expand Down
33 changes: 14 additions & 19 deletions src/cli/startLocal.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
import { createRequire } from 'node:module';
import { type Server as NetServer, createServer } from 'node:net';
import path from 'node:path';
/**
* @fileoverview
* This script is the entry point for starting the backend server in a local development
Expand All @@ -12,15 +16,7 @@
* frontend dev server) can read to discover the backend's port.
* - Initializes and starts the Fastify server.
*/
import '#fastify/trace-init/trace-init';

import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
import { open } from 'node:inspector';
import { createRequire } from 'node:module';
import { type Server as NetServer, createServer } from 'node:net';
import path from 'node:path';
import { logger } from '#o11y/logger';
import { applyEnvFile, resolveEnvFilePath } from './envLoader';
import { loadedEnvFilePath } from './envLoader';

type ServerFactory = () => NetServer;

Expand All @@ -41,19 +37,16 @@ function setServerFactory(factory: ServerFactory | null): void {
* This function orchestrates the entire startup sequence for local development.
*/
async function main(): Promise<void> {
let envFilePath: string | undefined;
try {
// 1. Resolve and apply environment variables from a `.env` file.
envFilePath = resolveEnvFilePath();
applyEnvFile(envFilePath);
} catch (err) {
logger.warn(err, '[start-local] no environment file found; continuing with existing process.env');
}
const envFilePath = loadedEnvFilePath;

process.env.NODE_ENV ??= 'development';

const { logger } = await import('../o11y/ollyModule.cjs');
const { initTrace } = await import('../fastify/trace-init/traceModule.cjs');
initTrace();

// Determine if this is the "default" repository setup (e.g., the main repo at $TYPEDAI_HOME)
// or a worktree or seperate clone. This affects port handling.
// or a worktree or separate clone. This affects port handling.
// In the default setup, we use fixed ports (3000/9229) and fail if they're taken.
// In a worktree/forked setup, we find the next available port to avoid conflicts.
const repoRoot = path.resolve(process.cwd());
Expand Down Expand Up @@ -126,7 +119,9 @@ async function main(): Promise<void> {
require('../index');
}

main().catch((error) => {
main().catch(async (error) => {
// We need to import logger here again because the main() function might fail before the initial import is complete.
const { logger } = await import('../o11y/ollyModule.cjs');
logger.fatal(error, '[start-local] failed to start backend');
process.exitCode = 1;
});
Expand Down
2 changes: 0 additions & 2 deletions src/cli/summarize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ import { SummarizerAgent } from '#functions/text/summarizer';
import { defaultLLMs } from '#llm/services/defaultLlms';
import type { AgentLLMs } from '#shared/agent/agent.model';
import { parseProcessArgs, saveAgentId } from './cli';
import { loadCliEnvironment } from './envLoader';

async function main() {
loadCliEnvironment();
const agentLlms: AgentLLMs = defaultLLMs();
await initApplicationContext();

Expand Down
2 changes: 0 additions & 2 deletions src/cli/swe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@ import type { AgentContext, AgentLLMs } from '#shared/agent/agent.model';
import { CodeEditingAgent } from '#swe/codeEditingAgent';
import { SoftwareDeveloperAgent } from '#swe/softwareDeveloperAgent';
import { parseProcessArgs, saveAgentId } from './cli';
import { loadCliEnvironment } from './envLoader';

// Used to test the SoftwareDeveloperAgent

// Usage:
// npm run swe

async function main() {
loadCliEnvironment();
await initApplicationContext();
const llms: AgentLLMs = defaultLLMs();

Expand Down
Loading
Loading