rename klo to ktx

This commit is contained in:
Andrey Avtomonov 2026-05-10 23:51:24 +02:00
parent 1a42152e6f
commit 3ce510b55b
704 changed files with 10205 additions and 10255 deletions

View file

@ -21,7 +21,7 @@ type MemoryRunRow = {
};
function localMemoryDbPath(projectDir: string): string {
return join(projectDir, '.klo', 'db.sqlite');
return join(projectDir, '.ktx', 'db.sqlite');
}
function isSafeRunId(runId: string): boolean {

View file

@ -2,7 +2,7 @@ import { access, mkdtemp, readFile, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { initKloProject } from '../project/index.js';
import { initKtxProject } from '../project/index.js';
import { createLocalProjectMemoryCapture } from './local-memory.js';
import { LocalMemoryRunStore } from './local-memory-runs.js';
@ -20,7 +20,7 @@ describe('LocalMemoryRunStore', () => {
let tempDir: string;
beforeEach(async () => {
tempDir = await mkdtemp(join(tmpdir(), 'klo-local-memory-runs-'));
tempDir = await mkdtemp(join(tmpdir(), 'ktx-local-memory-runs-'));
});
afterEach(async () => {
@ -44,8 +44,8 @@ describe('LocalMemoryRunStore', () => {
commitHash: 'abc123',
});
await expect(access(join(tempDir, '.klo/db.sqlite'))).resolves.toBeUndefined();
await expectPathMissing(join(tempDir, '.klo/memory-runs/memory-run-1.json'));
await expect(access(join(tempDir, '.ktx/db.sqlite'))).resolves.toBeUndefined();
await expectPathMissing(join(tempDir, '.ktx/memory-runs/memory-run-1.json'));
await expect(store.findById('memory-run-1')).resolves.toMatchObject({
id: 'memory-run-1',
@ -81,7 +81,7 @@ describe('createLocalProjectMemoryCapture', () => {
let tempDir: string;
beforeEach(async () => {
tempDir = await mkdtemp(join(tmpdir(), 'klo-local-memory-'));
tempDir = await mkdtemp(join(tmpdir(), 'ktx-local-memory-'));
});
afterEach(async () => {
@ -89,7 +89,7 @@ describe('createLocalProjectMemoryCapture', () => {
});
it('captures a wiki page through the local memory agent and persists pollable status', async () => {
const project = await initKloProject({ projectDir: tempDir, projectName: 'warehouse' });
const project = await initKtxProject({ projectDir: tempDir, projectName: 'warehouse' });
const agentRunner = {
runLoop: async ({
toolSet,
@ -126,8 +126,8 @@ describe('createLocalProjectMemoryCapture', () => {
).resolves.toEqual({ runId: 'memory-run-1' });
await capture.waitForRun('memory-run-1');
await expect(access(join(project.projectDir, '.klo/db.sqlite'))).resolves.toBeUndefined();
await expectPathMissing(join(project.projectDir, '.klo/memory-runs/memory-run-1.json'));
await expect(access(join(project.projectDir, '.ktx/db.sqlite'))).resolves.toBeUndefined();
await expectPathMissing(join(project.projectDir, '.ktx/memory-runs/memory-run-1.json'));
await expect(capture.status('memory-run-1')).resolves.toMatchObject({
runId: 'memory-run-1',
@ -144,7 +144,7 @@ describe('createLocalProjectMemoryCapture', () => {
});
it('captures a semantic-layer source for a named local connection id', async () => {
const project = await initKloProject({ projectDir: tempDir, projectName: 'warehouse' });
const project = await initKtxProject({ projectDir: tempDir, projectName: 'warehouse' });
project.config.connections.warehouse = { driver: 'postgres', readonly: true };
const agentRunner = {
runLoop: async ({
@ -187,8 +187,8 @@ describe('createLocalProjectMemoryCapture', () => {
});
await capture.waitForRun('memory-run-2');
await expect(access(join(project.projectDir, '.klo/db.sqlite'))).resolves.toBeUndefined();
await expectPathMissing(join(project.projectDir, '.klo/memory-runs/memory-run-2.json'));
await expect(access(join(project.projectDir, '.ktx/db.sqlite'))).resolves.toBeUndefined();
await expectPathMissing(join(project.projectDir, '.ktx/memory-runs/memory-run-2.json'));
await expect(capture.status('memory-run-2')).resolves.toMatchObject({
runId: 'memory-run-2',

View file

@ -1,19 +1,19 @@
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
import type { KloLlmProvider } from '@klo/llm';
import type { KtxLlmProvider } from '@ktx/llm';
import YAML from 'yaml';
import { AgentRunnerService } from '../agent/index.js';
import { localConnectionInfoFromConfig } from '../connections/index.js';
import type { KloEmbeddingPort, KloFileStorePort, KloFileWriteResult } from '../core/index.js';
import { type KloLogger, noopLogger, SessionWorktreeService } from '../core/index.js';
import type { KloSemanticLayerComputePort } from '../daemon/index.js';
import { createLocalKloLlmProviderFromConfig } from '../llm/index.js';
import type { KloLocalProject } from '../project/index.js';
import type { KtxEmbeddingPort, KtxFileStorePort, KtxFileWriteResult } from '../core/index.js';
import { type KtxLogger, noopLogger, SessionWorktreeService } from '../core/index.js';
import type { KtxSemanticLayerComputePort } from '../daemon/index.js';
import { createLocalKtxLlmProviderFromConfig } from '../llm/index.js';
import type { KtxLocalProject } from '../project/index.js';
import { PromptService } from '../prompts/index.js';
import { SkillsRegistryService } from '../skills/index.js';
import {
type KloConnectionInfo,
type KloQueryResult,
type KtxConnectionInfo,
type KtxQueryResult,
SemanticLayerService,
type SemanticLayerSource,
type SlConnectionCatalogPort,
@ -58,21 +58,21 @@ import type {
const promptsDir = fileURLToPath(new URL('../../prompts', import.meta.url));
const skillsDir = fileURLToPath(new URL('../../skills', import.meta.url));
const LOCAL_AUTHOR = { name: 'KLO Local', email: 'local@klo.local' };
const LOCAL_AUTHOR = { name: 'KTX Local', email: 'local@ktx.local' };
const LOCAL_SHAPE_WARNING = 'Local memory capture validates semantic-layer YAML shape only.';
export interface CreateLocalProjectMemoryCaptureOptions {
llmProvider?: KloLlmProvider;
llmProvider?: KtxLlmProvider;
agentRunner?: AgentRunnerService;
memoryModel?: string;
semanticLayerCompute?: KloSemanticLayerComputePort;
queryExecutor?: { execute(input: { connectionId: string; sql: string; maxRows?: number }): Promise<KloQueryResult> };
semanticLayerCompute?: KtxSemanticLayerComputePort;
queryExecutor?: { execute(input: { connectionId: string; sql: string; maxRows?: number }): Promise<KtxQueryResult> };
runIdFactory?: () => string;
logger?: KloLogger;
logger?: KtxLogger;
}
export function createLocalProjectMemoryCapture(
project: KloLocalProject,
project: KtxLocalProject,
options: CreateLocalProjectMemoryCaptureOptions = {},
): MemoryCaptureService {
const logger = options.logger ?? noopLogger;
@ -84,11 +84,11 @@ export function createLocalProjectMemoryCapture(
const connections = new LocalMemoryConnections(project, options.queryExecutor);
const slPython = new LocalSlPythonPort(options.semanticLayerCompute);
const semanticLayerService = new SemanticLayerService(rootFileStore, connections, slPython, logger);
const slSourcesRepository = new SqliteSlSourcesIndex({ dbPath: join(project.projectDir, '.klo', 'db.sqlite') });
const slSourcesRepository = new SqliteSlSourcesIndex({ dbPath: join(project.projectDir, '.ktx', 'db.sqlite') });
const slSearchService = new SlSearchService(embedding, slSourcesRepository, logger);
const wikiService = new KnowledgeWikiService(rootFileStore, embedding, knowledgeIndex, project.git, logger);
const authorResolver = new LocalAuthorResolver();
const llmProvider = options.llmProvider ?? createLocalKloLlmProviderFromConfig(project.config.llm);
const llmProvider = options.llmProvider ?? createLocalKtxLlmProviderFromConfig(project.config.llm);
const toolsetFactory = new LocalMemoryToolsetFactory({
project,
embedding,
@ -142,7 +142,7 @@ export function createLocalProjectMemoryCapture(
});
}
function requireLlmProvider(provider: KloLlmProvider | null | undefined): KloLlmProvider {
function requireLlmProvider(provider: KtxLlmProvider | null | undefined): KtxLlmProvider {
if (!provider) {
throw new Error('createLocalProjectMemoryCapture requires llm.provider.backend or an injected agentRunner');
}
@ -150,36 +150,36 @@ function requireLlmProvider(provider: KloLlmProvider | null | undefined): KloLlm
}
class LocalMemoryFileStore implements MemoryFileStorePort {
constructor(private readonly fileStore: MemoryFileStorePort | KloFileStorePort) {}
constructor(private readonly fileStore: MemoryFileStorePort | KtxFileStorePort) {}
forWorktree(workdir: string): LocalMemoryFileStore {
return new LocalMemoryFileStore(this.fileStore.forWorktree(workdir) as KloFileStorePort);
return new LocalMemoryFileStore(this.fileStore.forWorktree(workdir) as KtxFileStorePort);
}
writeFile(...args: Parameters<KloFileStorePort['writeFile']>): Promise<KloFileWriteResult> {
writeFile(...args: Parameters<KtxFileStorePort['writeFile']>): Promise<KtxFileWriteResult> {
return this.fileStore.writeFile(...args);
}
readFile(...args: Parameters<KloFileStorePort['readFile']>) {
readFile(...args: Parameters<KtxFileStorePort['readFile']>) {
return this.fileStore.readFile(...args);
}
deleteFile(...args: Parameters<KloFileStorePort['deleteFile']>) {
deleteFile(...args: Parameters<KtxFileStorePort['deleteFile']>) {
return this.fileStore.deleteFile(...args);
}
listFiles(...args: Parameters<KloFileStorePort['listFiles']>) {
listFiles(...args: Parameters<KtxFileStorePort['listFiles']>) {
return this.fileStore.listFiles(...args);
}
getFileHistory(...args: Parameters<KloFileStorePort['getFileHistory']>) {
getFileHistory(...args: Parameters<KtxFileStorePort['getFileHistory']>) {
return this.fileStore.getFileHistory(...args);
}
async enqueueCommitMessageJobForExternalCommit(): Promise<void> {}
}
class NoopEmbeddingPort implements KloEmbeddingPort {
class NoopEmbeddingPort implements KtxEmbeddingPort {
readonly maxBatchSize = 64;
async computeEmbedding(): Promise<number[]> {
@ -192,7 +192,7 @@ class NoopEmbeddingPort implements KloEmbeddingPort {
}
class LocalKnowledgeIndex implements KnowledgeIndexPort {
constructor(private readonly project: KloLocalProject) {}
constructor(private readonly project: KtxLocalProject) {}
async upsertPage(): Promise<void> {}
@ -276,19 +276,19 @@ class NoopKnowledgeSlRefsPort implements MemoryKnowledgeSlRefsPort {
class LocalMemoryConnections implements MemoryConnectionPort, SlConnectionCatalogPort {
constructor(
private readonly project: KloLocalProject,
private readonly project: KtxLocalProject,
private readonly queryExecutor?: {
execute(input: { connectionId: string; sql: string; maxRows?: number }): Promise<KloQueryResult>;
execute(input: { connectionId: string; sql: string; maxRows?: number }): Promise<KtxQueryResult>;
},
) {}
async listEnabledConnections(ids: string[]): Promise<KloConnectionInfo[]> {
async listEnabledConnections(ids: string[]): Promise<KtxConnectionInfo[]> {
return ids
.map((id) => localConnectionInfoFromConfig(id, this.project.config.connections[id]))
.filter((connection): connection is KloConnectionInfo => connection !== null);
.filter((connection): connection is KtxConnectionInfo => connection !== null);
}
async getConnectionById(connectionId: string): Promise<KloConnectionInfo> {
async getConnectionById(connectionId: string): Promise<KtxConnectionInfo> {
const connection = localConnectionInfoFromConfig(connectionId, this.project.config.connections[connectionId]);
if (!connection) {
throw new Error(`Connection not found: ${connectionId}`);
@ -296,7 +296,7 @@ class LocalMemoryConnections implements MemoryConnectionPort, SlConnectionCatalo
return connection;
}
async executeQuery(connectionId: string, sql: string): Promise<KloQueryResult> {
async executeQuery(connectionId: string, sql: string): Promise<KtxQueryResult> {
if (!this.queryExecutor) {
throw new Error('Local memory capture has no query executor configured');
}
@ -305,7 +305,7 @@ class LocalMemoryConnections implements MemoryConnectionPort, SlConnectionCatalo
}
class LocalSlPythonPort implements SlPythonPort {
constructor(private readonly compute?: KloSemanticLayerComputePort) {}
constructor(private readonly compute?: KtxSemanticLayerComputePort) {}
async validateSources(input: Parameters<SlPythonPort['validateSources']>[0]) {
if (!this.compute) {
@ -394,8 +394,8 @@ class LocalMemoryToolsetFactory implements MemoryToolsetFactoryPort {
private readonly slTools: BaseTool[];
constructor(deps: {
project: KloLocalProject;
embedding: KloEmbeddingPort;
project: KtxLocalProject;
embedding: KtxEmbeddingPort;
wikiService: KnowledgeWikiService;
knowledgeIndex: KnowledgeIndexPort;
knowledgeEvents: KnowledgeEventPort;

View file

@ -4,7 +4,7 @@ import { join } from 'node:path';
import { tool } from 'ai';
import * as YAML from 'yaml';
import { z } from 'zod';
import { type KloLogger, noopLogger } from '../core/index.js';
import { type KtxLogger, noopLogger } from '../core/index.js';
import {
revertSourceToPreHead,
type SemanticLayerSource,
@ -41,7 +41,7 @@ import type {
type GateDeps = SlValidationDeps & { slValidator: SlValidatorPort<SlValidationDeps> };
export class MemoryAgentService {
private readonly logger: KloLogger;
private readonly logger: KtxLogger;
constructor(private readonly deps: MemoryAgentServiceDeps) {
this.logger = deps.logger ?? noopLogger;

View file

@ -18,9 +18,9 @@ const expectedAdapterSkillHeadings: Record<string, string> = {
historic_sql_ingest: '# Historic SQL Ingest',
live_database_ingest: '# Live Database Ingest',
looker_ingest: '# Looker Runtime Ingest',
lookml_ingest: '# LookML to KLO Semantic Layer',
metabase_ingest: '# Metabase to KLO Semantic Layer',
metricflow_ingest: '# MetricFlow to KLO Semantic Layer',
lookml_ingest: '# LookML to KTX Semantic Layer',
metabase_ingest: '# Metabase to KTX Semantic Layer',
metricflow_ingest: '# MetricFlow to KTX Semantic Layer',
};
function forbiddenProductPattern() {

View file

@ -1,11 +1,11 @@
import type { Tool } from 'ai';
import type { AgentRunnerService } from '../agent/index.js';
import type { GitService, KloFileStorePort, KloLogger, SessionWorktreeService } from '../core/index.js';
import type { GitService, KtxFileStorePort, KtxLogger, SessionWorktreeService } from '../core/index.js';
import type { PromptService } from '../prompts/index.js';
import type { SkillsRegistryService } from '../skills/index.js';
import type {
KloConnectionInfo,
KloQueryResult,
KtxConnectionInfo,
KtxQueryResult,
SemanticLayerService,
SemanticLayerSource,
SlSearchService,
@ -101,9 +101,9 @@ export interface MemoryKnowledgeSlRefsPort {
}
export interface MemoryConnectionPort {
listEnabledConnections(ids: string[]): Promise<KloConnectionInfo[]>;
getConnectionById(connectionId: string): Promise<KloConnectionInfo>;
executeQuery(connectionId: string, sql: string): Promise<KloQueryResult>;
listEnabledConnections(ids: string[]): Promise<KtxConnectionInfo[]>;
getConnectionById(connectionId: string): Promise<KtxConnectionInfo>;
executeQuery(connectionId: string, sql: string): Promise<KtxQueryResult>;
}
export interface MemoryCommitMessagePort {
@ -114,7 +114,7 @@ export interface MemoryCommitMessagePort {
): Promise<void>;
}
export interface MemoryFileStorePort extends KloFileStorePort<MemoryFileStorePort>, MemoryCommitMessagePort {}
export interface MemoryFileStorePort extends KtxFileStorePort<MemoryFileStorePort>, MemoryCommitMessagePort {}
export interface MemoryToolSetLike {
toAiSdkTools(context: ToolContext): Record<string, Tool>;
@ -153,5 +153,5 @@ export interface MemoryAgentServiceDeps {
slValidator: SlValidatorPort<SlValidationDeps>;
toolsetFactory: MemoryToolsetFactoryPort;
telemetry?: MemoryTelemetryPort;
logger?: KloLogger;
logger?: KtxLogger;
}