mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-28 08:49:38 +02:00
* feat: add telemetry phase 1
* feat: add node telemetry event catalog
* feat: add telemetry event helpers
* feat: emit setup and connection telemetry
* feat: emit connection and stack telemetry
* feat: emit ingest and scan telemetry
* feat: emit query telemetry
* feat: emit sampled mcp telemetry
* docs: expand telemetry event catalog
* feat: add telemetry schema sync artifact
* feat: pass telemetry project id to semantic daemon
* feat: add daemon telemetry foundation
* feat: emit semantic daemon telemetry
* feat: emit daemon lifecycle telemetry
* docs: document full telemetry event catalog
* feat(telemetry): dim first-run notice
* feat(telemetry): show first-run notice before command output
* feat(telemetry): wire ktx PostHog project for live ingestion
* docs(telemetry): drop posthog project name and host from storage section
* docs(telemetry): trim to general overview and disclaimer
* docs(agents): add short telemetry guidelines
* feat(telemetry): enable posthog geoip enrichment
* docs(telemetry): drop ip-geoip note from public overview
* refactor(telemetry): drop no-op groupIdentify, rely on capture groups field
* fix(telemetry): respect CI kill switch in python daemon identity
* fix(sql): route table-count analysis to existing analyze-batch endpoint
* fix(telemetry): emit install_first_run from notice path and derive flagsPresent from commander
* fix(telemetry): read package info via getKtxCliPackageInfo to satisfy boundary check
* fix(telemetry): make python identity env={} bypass os.environ and unset CI in tests
* fix(telemetry): unset CI kill switch in cli-program-telemetry tests
67 lines
2.2 KiB
TypeScript
67 lines
2.2 KiB
TypeScript
import { readdir } from 'node:fs/promises';
|
|
import { join } from 'node:path';
|
|
import type { KtxProjectConfig } from '../context/project/config.js';
|
|
import { resolveProjectRuntimeRequirements } from '../runtime-requirements.js';
|
|
import { isDemoConnection } from './demo-detect.js';
|
|
|
|
async function hasFileWithExtension(dir: string, extensions: Set<string>): Promise<boolean> {
|
|
let entries;
|
|
try {
|
|
entries = await readdir(dir, { withFileTypes: true });
|
|
} catch {
|
|
return false;
|
|
}
|
|
|
|
for (const entry of entries) {
|
|
const path = join(dir, entry.name);
|
|
if (entry.isDirectory() && (await hasFileWithExtension(path, extensions))) {
|
|
return true;
|
|
}
|
|
if (entry.isFile() && extensions.has(entry.name.slice(entry.name.lastIndexOf('.')))) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
async function hasFileNamed(dir: string, filenames: Set<string>): Promise<boolean> {
|
|
let entries;
|
|
try {
|
|
entries = await readdir(dir, { withFileTypes: true });
|
|
} catch {
|
|
return false;
|
|
}
|
|
|
|
return entries.some((entry) => entry.isFile() && filenames.has(entry.name));
|
|
}
|
|
|
|
async function hasMcpConfig(projectDir: string): Promise<boolean> {
|
|
return (
|
|
(await hasFileWithExtension(join(projectDir, '.ktx'), new Set(['.json']))) ||
|
|
(await hasFileWithExtension(join(projectDir, '.cursor'), new Set(['.json']))) ||
|
|
(await hasFileNamed(projectDir, new Set(['.mcp.json'])))
|
|
);
|
|
}
|
|
|
|
export async function buildProjectStackSnapshotFields(input: {
|
|
projectDir: string;
|
|
config: KtxProjectConfig;
|
|
}) {
|
|
const connectors = Object.entries(input.config.connections).map(([connectionId, connection]) => ({
|
|
driver: String(connection.driver ?? 'unknown').trim().toLowerCase() || 'unknown',
|
|
isDemo: isDemoConnection(connectionId, connection),
|
|
}));
|
|
|
|
const runtimeRequirements = resolveProjectRuntimeRequirements(input.config, {
|
|
env: process.env,
|
|
});
|
|
|
|
return {
|
|
connectors,
|
|
connectionCount: connectors.length,
|
|
hasSl: await hasFileWithExtension(join(input.projectDir, 'semantic-layer'), new Set(['.yaml', '.yml'])),
|
|
hasWiki: await hasFileWithExtension(join(input.projectDir, 'wiki'), new Set(['.md', '.mdx'])),
|
|
hasMcp: await hasMcpConfig(input.projectDir),
|
|
hasManagedRuntime: runtimeRequirements.features.length > 0,
|
|
};
|
|
}
|