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
20 changes: 0 additions & 20 deletions bin/aider

This file was deleted.

2 changes: 1 addition & 1 deletion bin/path/taider
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export OPENROUTER_API_KEY=$OPENROUTER_API_KEY
export GEMINI_API_KEY=$GEMINI_API_KEY

MODEL=gpt-5
#MODEL=
MODEL=openrouter/openai/gpt-5
EDITOR_MODEL=vertex_ai/gemini-2.5-flash
WEAK_MODEL=vertex_ai/gemini-2.5-flash

Expand Down
1 change: 1 addition & 0 deletions bin/post_install
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# TODO: Check front-end and backend ai and @sinclair/typebox versions in package-lock.json are identical
2 changes: 0 additions & 2 deletions docs/docs/about.md

This file was deleted.

12 changes: 0 additions & 12 deletions docs/docs/authentication.md

This file was deleted.

2 changes: 0 additions & 2 deletions docs/docs/contributing.md

This file was deleted.

24 changes: 24 additions & 0 deletions frontend/bin/find-problematic-test
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash

# Save this script as find-problematic-test.sh
# Make it executable: chmod +x find-problematic-test.sh

# Find all spec files
SPEC_FILES=$(find src -name "*.spec.ts")

echo "Found $(echo "$SPEC_FILES" | wc -l) spec files"
echo ""

# Run each spec file individually
for spec in $SPEC_FILES; do
echo "Testing: $spec"
npm run env:test && ng test --include="$spec" --browsers=ChromeHeadless --watch=false

# Check if the test failed with non-zero exit code
if [ $? -ne 0 ]; then
echo "FOUND PROBLEMATIC TEST: $spec"
break
fi

echo "------------------------------------"
done
4 changes: 2 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
"ng": "ng",
"pnpm": " ng config -g cli.packageManager pnpm",
"start": "ng serve --host 0.0.0.0",
"start:local": "pnpm run env:local && pnpm run start",
"start:local": "node scripts/start-local.js",
"build": " pnpm run env:local && ng build",
"build:stage": "pnpm run env:stage && ng build",
"build:prod": " pnpm run env:prod && ng build --configuration production",
"env:local": "node --env-file=../variables/local.env scripts/env.js",
"env:local": "node scripts/env.js",
"env:test": " node --env-file=../variables/test.env scripts/env.js",
"env:stage": "node --env-file=../variables/stage.env scripts/env.js",
"env:prod": " node --env-file=../variables/prod.env scripts/env.js",
Expand Down
84 changes: 84 additions & 0 deletions frontend/scripts/env-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
const fs = require('fs');
const path = require('path');

function resolveEnvFilePath() {
const cwd = process.cwd();
const envFile = process.env.ENV_FILE;
if (envFile) {
const candidate = path.isAbsolute(envFile) ? envFile : path.resolve(cwd, envFile);
if (fs.existsSync(candidate)) return candidate;
}
const localEnv = path.resolve(cwd, '../variables/local.env');
if (fs.existsSync(localEnv)) return localEnv;
if (process.env.TYPEDAI_HOME) {
const typedAiEnv = path.resolve(process.env.TYPEDAI_HOME, 'variables/local.env');
if (fs.existsSync(typedAiEnv)) return typedAiEnv;
}
return null;
}

function loadEnvFile(filePath) {
if (!filePath) return {};
const contents = fs.readFileSync(filePath, 'utf8');
const lines = contents.split(/\r?\n/);
const env = {};
for (const rawLine of lines) {
const line = rawLine.trim();
if (!line || line.startsWith('#')) continue;
const equalIndex = line.indexOf('=');
if (equalIndex <= 0) continue;
const key = line.substring(0, equalIndex).trim().replace(/^export\s+/, '');
if (!key) continue;
let value = line.substring(equalIndex + 1).trim();
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
value = value.slice(1, -1);
}
env[key] = value.replace(/\\n/g, '\n');
}
return env;
}

function hydrateProcessEnv() {
const envPath = resolveEnvFilePath();
if (!envPath) {
console.warn('No environment file found; relying on existing environment variables.');
return;
}
const vars = loadEnvFile(envPath);
for (const [key, value] of Object.entries(vars)) {
if (process.env[key] === undefined) process.env[key] = value;
}
}

function determineBackendPort() {
if (process.env.BACKEND_PORT) return process.env.BACKEND_PORT;
if (process.env.PORT) return process.env.PORT;
try {
const runtimePath = path.resolve(process.cwd(), '../.typedai/runtime/backend.json');
if (fs.existsSync(runtimePath)) {
const { backendPort } = JSON.parse(fs.readFileSync(runtimePath, 'utf8'));
if (backendPort) return String(backendPort);
}
} catch (error) {
console.warn('Unable to read backend runtime metadata.', error);
}
return null;
}

function determineFrontendPort() {
if (process.env.FRONTEND_PORT) return process.env.FRONTEND_PORT;
if (process.env.UI_PORT) return process.env.UI_PORT;
if (process.env.UI_URL) {
const match = process.env.UI_URL.match(/:(\d+)/);
if (match) return match[1];
}
return null;
}

module.exports = {
resolveEnvFilePath,
loadEnvFile,
hydrateProcessEnv,
determineBackendPort,
determineFrontendPort,
};
26 changes: 17 additions & 9 deletions frontend/scripts/env.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
const fs = require('fs');
const path = require('path');
const fs = require('fs');
const {
hydrateProcessEnv,
determineBackendPort,
determineFrontendPort,
} = require('./env-utils');

function generateEnvironmentFile() {
hydrateProcessEnv();

const backendPort = determineBackendPort();
const resolvedApiBase = process.env.API_BASE_URL || (backendPort ? `http://localhost:${backendPort}/api/` : 'http://localhost:3000/api/');
const frontPort = determineFrontendPort();
const resolvedUiUrl = process.env.UI_URL || `http://localhost:${frontPort ?? '4200'}/`;

const envVars = {
version: process.env.npm_package_version,
API_BASE_URL: process.env.API_BASE_URL,
API_BASE_URL: resolvedApiBase,
GCLOUD_PROJECT: process.env.GCLOUD_PROJECT,
DATABASE_NAME: process.env.DATABASE_NAME,
DATABASE_TYPE: process.env.DATABASE_TYPE,
AUTH: process.env.AUTH,
MODULES: process.env.MODULES,
};
console.log(envVars)
for ([k,v] of Object.entries(envVars)) {
if (!v) console.info(`No value provided for ${k}`);
}

const environmentFile = `// This file is auto-generated by ${__filename}
export const env = ${JSON.stringify(envVars, null, 2)};
`;
console.log('[frontend env] configuration', { API_BASE_URL: envVars.API_BASE_URL, UI_URL: resolvedUiUrl });

const environmentFile = `// This file is auto-generated by ${__filename}\nexport const env = ${JSON.stringify(envVars, null, 2)};\n`;

const targetPath = path.join(__dirname, '../src/environments/.env.ts');

Expand Down
128 changes: 128 additions & 0 deletions frontend/scripts/start-local.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
const net = require('net');
const {
hydrateProcessEnv,
determineBackendPort,
determineFrontendPort,
resolveEnvFilePath,
loadEnvFile,
} = require('./env-utils');

function findAvailablePort(preferred, attempts = 20) {
const ports = [];
if (preferred && Number(preferred) > 0) {
const base = Number(preferred);
for (let i = 0; i < attempts; i += 1) ports.push(base + i);
}
ports.push(0);

return new Promise((resolve, reject) => {
const tryNext = () => {
if (ports.length === 0) {
reject(new Error('Unable to find available port for frontend dev server.'));
return;
}
const port = ports.shift();
const server = net.createServer();
server.once('error', () => {
server.close();
tryNext();
});
server.listen({ port, host: '0.0.0.0', exclusive: true }, () => {
const address = server.address();
server.close(() => {
if (address && typeof address === 'object') {
resolve(address.port);
} else {
resolve(port);
}
});
});
};
tryNext();
});
}

function ensurePortAvailable(port) {
return new Promise((resolve, reject) => {
const server = net.createServer();
server.once('error', (error) => {
server.close();
reject(new Error(`Port ${port} is unavailable: ${error.message}`));
});
server.listen({ port, host: '0.0.0.0', exclusive: true }, () => {
server.close(resolve);
});
});
}

function applyEnvFile(filePath) {
if (!filePath || !fs.existsSync(filePath)) return;
const vars = loadEnvFile(filePath);
for (const [key, value] of Object.entries(vars)) {
if (process.env[key] === undefined) process.env[key] = value;
}
}

function writeRuntimeMetadata(filePath, data) {
const dir = path.dirname(filePath);
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
fs.writeFileSync(filePath, JSON.stringify({ ...data, updatedAt: new Date().toISOString() }, null, 2));
}

async function main() {
hydrateProcessEnv();
applyEnvFile(resolveEnvFilePath());

const backendPort = determineBackendPort();
const preferredFrontendPort = determineFrontendPort();
const repoRoot = path.resolve(process.cwd(), '..');
const typedAiHome = process.env.TYPEDAI_HOME ? path.resolve(process.env.TYPEDAI_HOME) : null;
const isDefaultRepo = typedAiHome ? repoRoot === typedAiHome : false;

let frontendPort;
if (isDefaultRepo) {
frontendPort = 4200;
await ensurePortAvailable(frontendPort);
} else {
frontendPort = await findAvailablePort(preferredFrontendPort ? Number(preferredFrontendPort) : 4200);
}

process.env.FRONTEND_PORT = String(frontendPort);
process.env.UI_URL = `http://localhost:${frontendPort}/`;
if (!process.env.API_BASE_URL && backendPort) {
process.env.API_BASE_URL = `http://localhost:${backendPort}/api/`;
}

console.log('[frontend start] backend port:', backendPort || 'unknown');
console.log('[frontend start] frontend port:', frontendPort);

// Generate Angular runtime env file with the resolved variables.
require('./env.js');

writeRuntimeMetadata(
path.resolve(process.cwd(), '../.typedai/runtime/frontend.json'),
{
backendPort: backendPort ? Number(backendPort) : undefined,
frontendPort,
},
);

const ngArgs = ['serve', '--host', '0.0.0.0', '--port', String(frontendPort)];
const child = spawn('ng', ngArgs, { stdio: 'inherit', shell: process.platform === 'win32' });

child.on('exit', (code, signal) => {
if (signal) process.kill(process.pid, signal);
process.exit(typeof code === 'number' ? code : 0);
});

process.on('SIGINT', () => child.kill('SIGINT'));
process.on('SIGTERM', () => child.kill('SIGTERM'));
}

main().catch((error) => {
console.error('[frontend start] failed to launch Angular dev server:', error);
process.exit(1);
});
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"initTiktokenizer": "node --env-file=variables/local.env -r esbuild-register src/initTiktokenizer.ts",
"functionSchemas": "node --env-file=variables/local.env -r esbuild-register src/functionSchema/generateFunctionSchemas.ts",
"start": " node -r ts-node/register --env-file=variables/.env src/index.ts",
"start:local": "node -r ts-node/register --env-file=variables/local.env --inspect=0.0.0.0:9229 src/index.ts",
"start:local": "node -r esbuild-register src/cli/startLocal.ts",
"emulators": "gcloud emulators firestore start --host-port=127.0.0.1:8243",
"test": " pnpm run test:unit && pnpm run test:db",
"test:unit": " node --env-file=variables/test.env ./node_modules/mocha/bin/mocha -r esbuild-register -r \"./src/test/testSetup.ts\" \"src/**/*.test.[jt]s\" --exclude \"src/modules/{firestore,mongo,postgres}/*.test.ts\" --timeout 10000",
Expand Down Expand Up @@ -103,7 +103,7 @@
"@grpc/grpc-js": "^1.13.4",
"@microsoft/tiktokenizer": "^1.0.10",
"@mistralai/mistralai": "^1.7.1",
"@modelcontextprotocol/sdk": "^1.18.0",
"@modelcontextprotocol/sdk": "1.20.0",
"@mozilla/readability": "^0.6.0",
"@octokit/request": "^5.1.0",
"@openrouter/ai-sdk-provider": "1.1.2",
Expand Down Expand Up @@ -180,7 +180,8 @@
"tslib": "^2.6.2",
"turndown": "^7.1.3",
"uuid": "^9.0.1",
"xmldom": "^0.6.0"
"xmldom": "^0.6.0",
"yaml": "^2.8.1"
},
"devDependencies": {
"@biomejs/biome": "1.9.4",
Expand Down
Loading