mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-25 08:48:08 +02:00
feat(cli): stream plain ktx ingest progress to stderr (KLO-726) (#251)
* feat(cli): share public ingest progress adapter * feat(cli): stream plain public ingest progress * test(cli): update plain ingest progress assertions * chore(cli): satisfy plain ingest progress checks * fix(artifacts): expect plain ingest stderr progress in installed-CLI smoke * ci(coverage): make Codecov upload non-fatal and fix repo slug The Coverage job failed because the Codecov upload returned 'Repository not found' while fail_ci_if_error was true, turning a Codecov-side issue into a hard CI failure even though all tests pass. - Set fail_ci_if_error: false on both uploads so Codecov outages or an unlinked repo no longer break CI (upload stays best-effort). - Correct the stale slug Kaelio/ktx -> Kaelio/ktx-ai-data-agents-context to match the actual GitHub repo (aligns with main). * fix(cli): isolate query-history failure capture from scan output The plain public-ingest progress path passes one captured IO as the target-level `io`. With progress deps set, both the schema scan and the query-history ingest resolved their capture to that same shared buffer, so a non-actionable query-history failure surfaced leftover scan report text (e.g. "Mode: enriched") as the skipped-facet detail instead of the real query-history message. Give the query-history ingest a phase-local capture while preserving the flow-to-io branch the foreground context-build view relies on. --------- Co-authored-by: Andrey Avtomonov <7889985+andreybavt@users.noreply.github.com>
This commit is contained in:
parent
d01abe6f3c
commit
13774bfcef
8 changed files with 445 additions and 49 deletions
|
|
@ -1,8 +1,6 @@
|
|||
import type { KtxProgressPort, KtxProgressUpdateOptions } from './context/scan/types.js';
|
||||
import type { KtxCliIo } from './index.js';
|
||||
import type { KtxIngestProgressUpdate } from './ingest.js';
|
||||
import type { KtxManagedPythonInstallPolicy } from './managed-python-command.js';
|
||||
import { publicDatabaseIngestMessage, publicQueryHistoryMessage } from './public-ingest-copy.js';
|
||||
import type {
|
||||
KtxPublicIngestArgs,
|
||||
KtxPublicIngestDeps,
|
||||
|
|
@ -10,7 +8,8 @@ import type {
|
|||
KtxPublicIngestProject,
|
||||
KtxPublicIngestTargetResult,
|
||||
} from './public-ingest.js';
|
||||
import { buildPublicIngestPlan, executePublicIngestTarget } from './public-ingest.js';
|
||||
import { buildPublicIngestPlan, executePublicIngestTarget, publicProgressMessage } from './public-ingest.js';
|
||||
import { createAggregateProgressPort } from './progress-port-adapter.js';
|
||||
import { formatDuration } from './demo-metrics.js';
|
||||
import { profileMark } from './startup-profile.js';
|
||||
|
||||
|
|
@ -810,17 +809,6 @@ export function initViewState(targets: KtxPublicIngestPlanTarget[]): ContextBuil
|
|||
};
|
||||
}
|
||||
|
||||
function publicProgressMessage(message: string, target: KtxPublicIngestPlanTarget): string {
|
||||
let current = message;
|
||||
if (target.operation === 'database-ingest') {
|
||||
current = publicDatabaseIngestMessage(current);
|
||||
}
|
||||
if (target.steps.includes('query-history')) {
|
||||
current = publicQueryHistoryMessage(current, target.connectionId);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
function formatProgressDetail(
|
||||
update: Pick<KtxIngestProgressUpdate, 'percent' | 'message'>,
|
||||
target: KtxPublicIngestPlanTarget,
|
||||
|
|
@ -829,29 +817,6 @@ function formatProgressDetail(
|
|||
return `[${percent}%] ${publicProgressMessage(update.message, target)}`;
|
||||
}
|
||||
|
||||
function createContextBuildProgressPort(
|
||||
onProgress: (update: KtxIngestProgressUpdate) => void,
|
||||
state: { progress: number } = { progress: 0 },
|
||||
start = 0,
|
||||
weight = 1,
|
||||
): KtxProgressPort {
|
||||
return {
|
||||
async update(value: number, message?: string, options?: KtxProgressUpdateOptions): Promise<void> {
|
||||
const absoluteValue = start + Math.max(0, Math.min(1, value)) * weight;
|
||||
state.progress = Math.max(state.progress, Math.min(1, absoluteValue));
|
||||
if (!message) return;
|
||||
onProgress({
|
||||
percent: Math.max(0, Math.min(100, Math.round(state.progress * 100))),
|
||||
message,
|
||||
...(options?.transient !== undefined ? { transient: options.transient } : {}),
|
||||
});
|
||||
},
|
||||
startPhase(phaseWeight: number): KtxProgressPort {
|
||||
return createContextBuildProgressPort(onProgress, state, state.progress, weight * phaseWeight);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function runContextBuild(
|
||||
project: KtxPublicIngestProject,
|
||||
args: ContextBuildArgs,
|
||||
|
|
@ -1022,7 +987,7 @@ export async function runContextBuild(
|
|||
};
|
||||
|
||||
const progressDeps: KtxPublicIngestDeps = {
|
||||
scanProgress: createContextBuildProgressPort(updateSchemaPhase),
|
||||
scanProgress: createAggregateProgressPort(updateSchemaPhase),
|
||||
ingestProgress: updateIngestPhase,
|
||||
runtimeIo: io,
|
||||
onPhaseStart,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue