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
5 changes: 4 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,11 @@
"handlebars": "^4.7.8",
"ora": "^8.0.1",
"sqlite-vec": "^0.1.3",
"sqlite-vec-windows-x64": "^0.1.7-alpha.2",
"zod": "^3.22.4"
},
"optionalDependencies": {
"sqlite-vec-windows-x64": "^0.1.7-alpha.2"
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.8",
"@types/blessed": "^0.1.27",
Expand Down
4 changes: 2 additions & 2 deletions src/agent-system/todolist-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ All tasks for "${session.name}" completed at ${session.updatedAt}.
let name = 'Unknown Session';
let status: TodoSession['status'] = 'active';
let createdAt = new Date().toISOString();
let updatedAt = new Date().toISOString();
const updatedAt = new Date().toISOString();

const tasks: TodoTask[] = [];

Expand All @@ -543,7 +543,7 @@ All tasks for "${session.name}" completed at ${session.updatedAt}.
if (createdMatch) createdAt = createdMatch[1];

// Parse tasks
const taskMatch = line.match(/^[\[\~x\s\-\]]\s+Task\s+([a-f0-9]+):\s*(.+)$/);
const taskMatch = line.match(/^[[~x\s\-\]]\s+Task\s+([a-f0-9]+):\s*(.+)$/);
if (taskMatch) {
const taskId = taskMatch[1];
const subject = taskMatch[2];
Expand Down
92 changes: 45 additions & 47 deletions src/agents/drift-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import fs from 'fs/promises';
import path from 'path';
import { glob } from 'glob';
import { OpenRouterClient } from '../embeddings/openrouter.js';
import { K0NTEXT_MODELS, MODEL_CONFIG, getModelFor } from '../config/models.js';
import { MODEL_CONFIG, getModelFor } from '../config/models.js';

/**
* A detected drift issue
Expand Down Expand Up @@ -151,33 +151,43 @@ export class DriftAgent {
// Discover relevant source code for comparison
const sourceFiles = await this.discoverSourceFiles();

// Analyze each file for drift
for (const relativePath of filesToProcess) {
try {
const drift = await this.checkFileForDrift(relativePath, sourceFiles);
if (drift) {
drifts.push(drift);
// Analyze files for drift in parallel with concurrency limit
const CONCURRENCY_LIMIT = 5;
const queue = [...filesToProcess];

const workers = Array(Math.min(CONCURRENCY_LIMIT, queue.length)).fill(null).map(async () => {
while (queue.length > 0) {
const relativePath = queue.shift();
if (!relativePath) break;

if (options.autoFix && drift.suggestion) {
const didFix = await this.fixDrift(relativePath, drift);
if (didFix) fixed++;
try {
const drift = await this.checkFileForDrift(relativePath, sourceFiles);
if (drift) {
drifts.push(drift);

if (options.autoFix && drift.suggestion) {
const didFix = await this.fixDrift(relativePath, drift);
if (didFix) fixed++;
}
}
} catch (error) {
// Check for authentication errors
const errorMessage = error instanceof Error ? error.message : String(error);
if (errorMessage.includes('401') ||
errorMessage.includes('Authentication') ||
errorMessage.includes('Unauthorized') ||
errorMessage.includes('API key')) {
authFailures.push(relativePath);
} else {
errors.push({ file: relativePath, error: errorMessage });
}
// Log error but continue
console.error(`Failed to analyze ${relativePath}: ${errorMessage}`);
}
} catch (error) {
// Check for authentication errors
const errorMessage = error instanceof Error ? error.message : String(error);
if (errorMessage.includes('401') ||
errorMessage.includes('Authentication') ||
errorMessage.includes('Unauthorized') ||
errorMessage.includes('API key')) {
authFailures.push(relativePath);
} else {
errors.push({ file: relativePath, error: errorMessage });
}
// Log error but continue
console.error(`Failed to analyze ${relativePath}: ${errorMessage}`);
}
}
});

await Promise.all(workers);

return {
drifts,
Expand Down Expand Up @@ -389,37 +399,25 @@ Severity guidelines:
'**/*.java'
];

const allFiles: string[] = [];

for (const pattern of patterns) {
const files = await glob(pattern, {
cwd: this.projectRoot,
ignore: DEFAULT_IGNORE,
absolute: false
});
allFiles.push(...files);
}

return allFiles;
return await glob(patterns, {
cwd: this.projectRoot,
ignore: DEFAULT_IGNORE,
absolute: false
});
}

/**
* Get all context files to check
*/
private async getContextFiles(): Promise<string[]> {
const files: string[] = [];

for (const pattern of DEFAULT_CONTEXT_FILES) {
const matched = await glob(pattern, {
cwd: this.projectRoot,
ignore: DEFAULT_IGNORE,
absolute: false
});
files.push(...matched);
}
const matched = await glob(DEFAULT_CONTEXT_FILES, {
cwd: this.projectRoot,
ignore: DEFAULT_IGNORE,
absolute: false
});

// Deduplicate
return Array.from(new Set(files));
return Array.from(new Set(matched));
}

/**
Expand Down
18 changes: 10 additions & 8 deletions src/cli/repl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* Interactive shell for managing k0ntext context
*/

import fs from 'fs';
import path from 'path';
import readline from 'readline';
import { REPLSessionManager, ProjectType } from './core/session.js';
import { REPLCommandParser } from './core/parser.js';
Expand Down Expand Up @@ -210,10 +212,10 @@ export class REPLShell {

// Index docs
for (const doc of docs) {
const content = require('fs').readFileSync(doc.path, 'utf-8').slice(0, 50000);
const content = fs.readFileSync(doc.path, 'utf-8').slice(0, 50000);
db.upsertItem({
type: 'doc',
name: require('path').basename(doc.relativePath),
name: path.basename(doc.relativePath),
content,
filePath: doc.relativePath,
metadata: { size: doc.size }
Expand All @@ -225,13 +227,13 @@ export class REPLShell {

// Index code
for (const codeFile of code.slice(0, 500)) {
const content = require('fs').existsSync(codeFile.path)
? require('fs').readFileSync(codeFile.path, 'utf-8').slice(0, 20000)
const content = fs.existsSync(codeFile.path)
? fs.readFileSync(codeFile.path, 'utf-8').slice(0, 20000)
: '';
if (content) {
db.upsertItem({
type: 'code',
name: require('path').basename(codeFile.relativePath),
name: path.basename(codeFile.relativePath),
content,
filePath: codeFile.relativePath,
metadata: { size: codeFile.size }
Expand All @@ -244,13 +246,13 @@ export class REPLShell {

// Index tools
for (const tool of tools) {
const content = require('fs').existsSync(tool.path)
? require('fs').readFileSync(tool.path, 'utf-8').slice(0, 50000)
const content = fs.existsSync(tool.path)
? fs.readFileSync(tool.path, 'utf-8').slice(0, 50000)
: '';
if (content) {
db.upsertItem({
type: 'tool_config',
name: `${tool.tool}:${require('path').basename(tool.relativePath)}`,
name: `${tool.tool}:${path.basename(tool.relativePath)}`,
content,
filePath: tool.relativePath,
metadata: { tool: tool.tool, size: tool.size }
Expand Down
3 changes: 2 additions & 1 deletion src/cli/repl/tui/panels/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ export class ConfigPanel {
default: String(currentValue || key.defaultValue || '')
});

case 'number':
case 'number': {
const inputResult = await input({
message: key.description,
default: String(currentValue || key.defaultValue || ''),
Expand All @@ -298,6 +298,7 @@ export class ConfigPanel {
}
});
return Number(inputResult);
}

default:
return currentValue;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/repl/tui/panels/drift.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import fs from 'fs';
import path from 'path';
import { execSync } from 'child_process';
import chalk from 'chalk';
import { K0NTEXT_THEME } from '../theme.js';
import { DatabaseClient } from '../../../../db/client.js';
Expand Down Expand Up @@ -212,7 +213,6 @@ export class DriftDetectionPanel {

try {
// Use git diff to check for changes
const { execSync } = require('child_process');

// Check for modified files
const modified = execSync('git diff --name-only', {
Expand Down
6 changes: 4 additions & 2 deletions src/cli/repl/tui/panels/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,16 +183,18 @@ export class AdvancedSearchPanel {
case 'name':
comparison = a.item.name.localeCompare(b.item.name);
break;
case 'date':
case 'date': {
const aDate = a.item.updatedAt ? new Date(a.item.updatedAt).getTime() : 0;
const bDate = b.item.updatedAt ? new Date(b.item.updatedAt).getTime() : 0;
comparison = bDate - aDate;
break;
case 'size':
}
case 'size': {
const aSize = (a.item.metadata as Record<string, unknown>)?.size || 0;
const bSize = (b.item.metadata as Record<string, unknown>)?.size || 0;
comparison = Number(bSize) - Number(aSize);
break;
}
}

return order === 'desc' ? -comparison : comparison;
Expand Down
2 changes: 1 addition & 1 deletion src/template-sync/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export class TemplateSyncEngine {
const stats = TemplateMerger.getStatistics(mergeResults);

// Step 4: Handle conflicts
let conflictResolutions = new Map<string, 'keep-local' | 'overwrite'>();
const conflictResolutions = new Map<string, 'keep-local' | 'overwrite'>();
let resolvedConflicts: FileComparison[] = [];

if (conflicts.length > 0 && !options.force) {
Expand Down
Loading