@kaelio/ktx 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/assets/python/{kaelio_ktx-0.8.0-py3-none-any.whl → kaelio_ktx-0.10.0-py3-none-any.whl} +0 -0
  2. package/assets/python/manifest.json +4 -4
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/clack.d.ts +6 -0
  5. package/dist/clack.js +17 -2
  6. package/dist/cli-program.d.ts +3 -0
  7. package/dist/cli-program.js +42 -2
  8. package/dist/cli-runtime.d.ts +3 -0
  9. package/dist/cli-runtime.js +94 -3
  10. package/dist/commands/setup-commands.js +3 -4
  11. package/dist/connection-recovery.d.ts +34 -0
  12. package/dist/connection-recovery.js +82 -0
  13. package/dist/connection.js +26 -2
  14. package/dist/connectors/bigquery/connector.d.ts +2 -5
  15. package/dist/connectors/bigquery/connector.js +2 -2
  16. package/dist/connectors/clickhouse/connector.d.ts +2 -5
  17. package/dist/connectors/clickhouse/connector.js +2 -2
  18. package/dist/connectors/mysql/connector.d.ts +7 -6
  19. package/dist/connectors/mysql/connector.js +25 -5
  20. package/dist/connectors/mysql/dialect.d.ts +1 -1
  21. package/dist/connectors/mysql/dialect.js +12 -2
  22. package/dist/connectors/postgres/connector.d.ts +2 -5
  23. package/dist/connectors/postgres/connector.js +2 -2
  24. package/dist/connectors/snowflake/connector.d.ts +2 -5
  25. package/dist/connectors/snowflake/connector.js +2 -2
  26. package/dist/connectors/sqlite/connector.d.ts +2 -5
  27. package/dist/connectors/sqlite/connector.js +2 -2
  28. package/dist/connectors/sqlserver/connector.d.ts +2 -5
  29. package/dist/connectors/sqlserver/connector.js +2 -2
  30. package/dist/context/connections/drivers.d.ts +0 -1
  31. package/dist/context/connections/drivers.js +0 -7
  32. package/dist/context/connections/query-executor.d.ts +2 -1
  33. package/dist/context/core/abort.d.ts +9 -0
  34. package/dist/context/core/abort.js +36 -0
  35. package/dist/context/ingest/adapters/historic-sql/bigquery-query-history-reader.js +71 -20
  36. package/dist/context/ingest/adapters/historic-sql/chunk-unified.js +2 -1
  37. package/dist/context/ingest/adapters/historic-sql/connection-dialect.d.ts +9 -0
  38. package/dist/context/ingest/adapters/historic-sql/connection-dialect.js +15 -4
  39. package/dist/context/ingest/adapters/historic-sql/pattern-inputs.js +8 -2
  40. package/dist/context/ingest/adapters/historic-sql/query-history-filter-picker.d.ts +30 -0
  41. package/dist/context/ingest/adapters/historic-sql/query-history-filter-picker.js +194 -0
  42. package/dist/context/ingest/adapters/historic-sql/scope-floor.d.ts +18 -0
  43. package/dist/context/ingest/adapters/historic-sql/scope-floor.js +229 -0
  44. package/dist/context/ingest/adapters/historic-sql/scope-membership.d.ts +8 -0
  45. package/dist/context/ingest/adapters/historic-sql/scope-membership.js +29 -0
  46. package/dist/context/ingest/adapters/historic-sql/snowflake-query-history-reader.js +68 -19
  47. package/dist/context/ingest/adapters/historic-sql/stage-unified.js +57 -50
  48. package/dist/context/ingest/adapters/historic-sql/types.d.ts +36 -3
  49. package/dist/context/ingest/adapters/historic-sql/types.js +14 -2
  50. package/dist/context/ingest/context-candidates/curator-pagination.service.d.ts +1 -5
  51. package/dist/context/ingest/context-candidates/curator-pagination.service.js +1 -3
  52. package/dist/context/ingest/context-evidence/sqlite-context-evidence-store.d.ts +1 -1
  53. package/dist/context/ingest/final-gate-repair.d.ts +1 -0
  54. package/dist/context/ingest/final-gate-repair.js +1 -0
  55. package/dist/context/ingest/ingest-bundle.runner.d.ts +3 -0
  56. package/dist/context/ingest/ingest-bundle.runner.js +127 -53
  57. package/dist/context/ingest/isolated-diff/patch-integrator.js +75 -5
  58. package/dist/context/ingest/isolated-diff/textual-conflict-resolver.d.ts +1 -0
  59. package/dist/context/ingest/isolated-diff/textual-conflict-resolver.js +1 -0
  60. package/dist/context/ingest/isolated-diff/work-unit-executor.d.ts +1 -0
  61. package/dist/context/ingest/local-adapters.js +21 -4
  62. package/dist/context/ingest/local-bundle-runtime.js +13 -5
  63. package/dist/context/ingest/local-ingest.d.ts +1 -0
  64. package/dist/context/ingest/local-ingest.js +13 -3
  65. package/dist/context/ingest/memory-flow/events.js +1 -1
  66. package/dist/context/ingest/memory-flow/schema.js +8 -3
  67. package/dist/context/ingest/memory-flow/types.d.ts +7 -3
  68. package/dist/context/ingest/ports.d.ts +3 -5
  69. package/dist/context/ingest/stages/stage-3-work-units.d.ts +1 -4
  70. package/dist/context/ingest/stages/stage-3-work-units.js +5 -1
  71. package/dist/context/ingest/stages/stage-4-reconciliation.d.ts +1 -4
  72. package/dist/context/ingest/stages/stage-4-reconciliation.js +1 -1
  73. package/dist/context/ingest/types.d.ts +1 -0
  74. package/dist/context/llm/ai-sdk-runtime.d.ts +3 -0
  75. package/dist/context/llm/ai-sdk-runtime.js +152 -16
  76. package/dist/context/llm/claude-code-runtime.d.ts +6 -4
  77. package/dist/context/llm/claude-code-runtime.js +127 -48
  78. package/dist/context/llm/codex-exec-events.d.ts +20 -0
  79. package/dist/context/llm/codex-exec-events.js +155 -0
  80. package/dist/context/llm/codex-isolation.d.ts +3 -0
  81. package/dist/context/llm/codex-isolation.js +5 -0
  82. package/dist/context/llm/codex-mcp-runtime-server.d.ts +24 -0
  83. package/dist/context/llm/codex-mcp-runtime-server.js +51 -0
  84. package/dist/context/llm/codex-models.d.ts +2 -0
  85. package/dist/context/llm/codex-models.js +17 -0
  86. package/dist/context/llm/codex-runtime-config.d.ts +16 -0
  87. package/dist/context/llm/codex-runtime-config.js +19 -0
  88. package/dist/context/llm/codex-runtime.d.ts +37 -0
  89. package/dist/context/llm/codex-runtime.js +347 -0
  90. package/dist/context/llm/codex-sdk-runner.d.ts +21 -0
  91. package/dist/context/llm/codex-sdk-runner.js +63 -0
  92. package/dist/context/llm/local-config.d.ts +16 -4
  93. package/dist/context/llm/local-config.js +18 -2
  94. package/dist/context/llm/rate-limit-governor.d.ts +103 -0
  95. package/dist/context/llm/rate-limit-governor.js +285 -0
  96. package/dist/context/llm/runtime-port.d.ts +3 -6
  97. package/dist/context/mcp/context-tools.js +43 -13
  98. package/dist/context/project/config.d.ts +14 -0
  99. package/dist/context/project/config.js +37 -2
  100. package/dist/context/scan/types.d.ts +15 -2
  101. package/dist/context/scan/types.js +12 -0
  102. package/dist/context/sl/description-normalization.js +4 -14
  103. package/dist/context/sql-analysis/http-sql-analysis-port.js +32 -2
  104. package/dist/context/sql-analysis/ports.d.ts +12 -2
  105. package/dist/context/tools/context-candidate-mark.tool.d.ts +2 -2
  106. package/dist/context-build-view.d.ts +13 -0
  107. package/dist/context-build-view.js +63 -32
  108. package/dist/demo-metrics.d.ts +0 -2
  109. package/dist/demo-metrics.js +1 -11
  110. package/dist/ingest.d.ts +1 -0
  111. package/dist/ingest.js +32 -3
  112. package/dist/io/buffered-command-io.d.ts +11 -0
  113. package/dist/io/buffered-command-io.js +28 -0
  114. package/dist/io/symbols.d.ts +2 -0
  115. package/dist/io/symbols.js +2 -0
  116. package/dist/llm/types.d.ts +1 -1
  117. package/dist/local-adapters.d.ts +10 -2
  118. package/dist/local-adapters.js +19 -3
  119. package/dist/memory-flow-hud.js +8 -16
  120. package/dist/next-steps.js +1 -2
  121. package/dist/progress-port-adapter.d.ts +6 -0
  122. package/dist/progress-port-adapter.js +18 -0
  123. package/dist/public-ingest.d.ts +20 -1
  124. package/dist/public-ingest.js +228 -42
  125. package/dist/reveal-password-prompt.d.ts +24 -0
  126. package/dist/reveal-password-prompt.js +78 -0
  127. package/dist/scan.js +21 -3
  128. package/dist/setup-context.d.ts +2 -0
  129. package/dist/setup-context.js +133 -27
  130. package/dist/setup-databases.d.ts +18 -1
  131. package/dist/setup-databases.js +378 -249
  132. package/dist/setup-demo-tour.js +1 -0
  133. package/dist/setup-embeddings.js +1 -1
  134. package/dist/setup-models.d.ts +11 -15
  135. package/dist/setup-models.js +140 -276
  136. package/dist/setup-prompts.js +3 -2
  137. package/dist/setup-ready-menu.d.ts +16 -2
  138. package/dist/setup-ready-menu.js +37 -5
  139. package/dist/setup-sources.js +115 -35
  140. package/dist/setup.d.ts +1 -1
  141. package/dist/setup.js +23 -11
  142. package/dist/sl.d.ts +2 -2
  143. package/dist/sl.js +20 -4
  144. package/dist/sql.js +18 -2
  145. package/dist/star-prompt/cache.d.ts +16 -0
  146. package/dist/star-prompt/cache.js +45 -0
  147. package/dist/star-prompt/star-count.d.ts +7 -0
  148. package/dist/star-prompt/star-count.js +66 -0
  149. package/dist/star-prompt/star-line.d.ts +12 -0
  150. package/dist/star-prompt/star-line.js +26 -0
  151. package/dist/status-project.d.ts +11 -0
  152. package/dist/status-project.js +50 -1
  153. package/dist/telemetry/command-hook.d.ts +1 -0
  154. package/dist/telemetry/command-hook.js +3 -1
  155. package/dist/telemetry/emitter.d.ts +10 -0
  156. package/dist/telemetry/emitter.js +31 -0
  157. package/dist/telemetry/events.d.ts +35 -6
  158. package/dist/telemetry/events.js +25 -2
  159. package/dist/telemetry/exception.d.ts +18 -0
  160. package/dist/telemetry/exception.js +162 -0
  161. package/dist/telemetry/identity.d.ts +0 -1
  162. package/dist/telemetry/identity.js +6 -6
  163. package/dist/telemetry/index.d.ts +15 -2
  164. package/dist/telemetry/index.js +15 -3
  165. package/dist/telemetry/redaction-secrets.d.ts +11 -0
  166. package/dist/telemetry/redaction-secrets.js +92 -0
  167. package/dist/telemetry/scrubber.d.ts +10 -0
  168. package/dist/telemetry/scrubber.js +20 -0
  169. package/dist/update-check/cache.d.ts +21 -0
  170. package/dist/update-check/cache.js +38 -0
  171. package/dist/update-check/channel.d.ts +15 -0
  172. package/dist/update-check/channel.js +30 -0
  173. package/dist/update-check/registry.d.ts +1 -0
  174. package/dist/update-check/registry.js +45 -0
  175. package/dist/update-check/update-check.d.ts +43 -0
  176. package/dist/update-check/update-check.js +116 -0
  177. package/package.json +12 -4
  178. package/dist/context/connections/local-query-executor.d.ts +0 -6
  179. package/dist/context/connections/local-query-executor.js +0 -39
  180. package/dist/context/connections/postgres-query-executor.d.ts +0 -25
  181. package/dist/context/connections/postgres-query-executor.js +0 -53
  182. package/dist/context/connections/sqlite-query-executor.d.ts +0 -4
  183. package/dist/context/connections/sqlite-query-executor.js +0 -74
@@ -0,0 +1,66 @@
1
+ import { request as httpsRequest } from 'node:https';
2
+ import { URL } from 'node:url';
3
+ import { z } from 'zod';
4
+ const GITHUB_REPO_URL = new URL('https://api.github.com/repos/Kaelio/ktx');
5
+ const DEFAULT_TIMEOUT_MS = 5000;
6
+ const githubRepoSchema = z.object({
7
+ stargazers_count: z.number().int().nonnegative(),
8
+ });
9
+ function parseStarCount(raw) {
10
+ return githubRepoSchema.parse(JSON.parse(raw)).stargazers_count;
11
+ }
12
+ export function fetchGitHubStarCount(options = {}) {
13
+ const requestImpl = options.request ?? httpsRequest;
14
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
15
+ return new Promise((resolve) => {
16
+ let settled = false;
17
+ const finish = (count) => {
18
+ if (settled) {
19
+ return;
20
+ }
21
+ settled = true;
22
+ resolve(count);
23
+ };
24
+ try {
25
+ const request = requestImpl(GITHUB_REPO_URL, {
26
+ method: 'GET',
27
+ headers: {
28
+ accept: 'application/vnd.github+json',
29
+ 'user-agent': 'ktx-star-prompt',
30
+ },
31
+ }, (response) => {
32
+ const chunks = [];
33
+ response.on('data', (chunk) => {
34
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
35
+ });
36
+ response.on('end', () => {
37
+ const statusCode = response.statusCode ?? 0;
38
+ if (statusCode < 200 || statusCode >= 300) {
39
+ finish(null);
40
+ return;
41
+ }
42
+ try {
43
+ finish(parseStarCount(Buffer.concat(chunks).toString('utf8')));
44
+ }
45
+ catch {
46
+ finish(null);
47
+ }
48
+ });
49
+ });
50
+ request.on('socket', (socket) => {
51
+ socket.unref();
52
+ });
53
+ request.on('error', () => {
54
+ finish(null);
55
+ });
56
+ request.setTimeout(timeoutMs, () => {
57
+ request.destroy(new Error('GitHub star count request timed out'));
58
+ finish(null);
59
+ });
60
+ request.end();
61
+ }
62
+ catch {
63
+ finish(null);
64
+ }
65
+ });
66
+ }
@@ -0,0 +1,12 @@
1
+ interface StarPromptSymbols {
2
+ star: string;
3
+ middot: string;
4
+ rightArrow: string;
5
+ }
6
+ export interface RenderStarPromptLineOptions {
7
+ columns: number;
8
+ count?: number | null;
9
+ symbols?: StarPromptSymbols;
10
+ }
11
+ export declare function renderStarPromptLine(options: RenderStarPromptLineOptions): string;
12
+ export {};
@@ -0,0 +1,26 @@
1
+ import { SYMBOLS } from '../io/symbols.js';
2
+ const STAR_PROMPT_URL = 'github.com/Kaelio/ktx';
3
+ const STAR_PROMPT_TEXT = 'This takes a few minutes - mind giving ktx a star while you wait?';
4
+ function usableColumns(columns) {
5
+ return Number.isFinite(columns) && columns > 0 ? Math.floor(columns) : 80;
6
+ }
7
+ function starCountSegment(count, symbols) {
8
+ if (typeof count !== 'number' || !Number.isFinite(count)) {
9
+ return '';
10
+ }
11
+ const formatted = new Intl.NumberFormat('en-US').format(count);
12
+ return ` ${symbols.middot} ${formatted} ${symbols.star}`;
13
+ }
14
+ export function renderStarPromptLine(options) {
15
+ const symbols = options.symbols ?? SYMBOLS;
16
+ const columns = usableColumns(options.columns);
17
+ const base = ` ${symbols.star} ${STAR_PROMPT_TEXT} ${STAR_PROMPT_URL}`;
18
+ const withCount = `${base}${starCountSegment(options.count, symbols)}`;
19
+ if (withCount.length <= columns) {
20
+ return withCount;
21
+ }
22
+ if (base.length <= columns) {
23
+ return base;
24
+ }
25
+ return ` ${symbols.star} Star ktx ${symbols.rightArrow} ${STAR_PROMPT_URL}`;
26
+ }
@@ -62,6 +62,16 @@ type ClaudeCodeAuthProbe = (input: {
62
62
  ok: false;
63
63
  message: string;
64
64
  }>;
65
+ type CodexAuthProbe = (input: {
66
+ projectDir: string;
67
+ model: string;
68
+ }) => Promise<{
69
+ ok: true;
70
+ } | {
71
+ ok: false;
72
+ message: string;
73
+ fix: string;
74
+ }>;
65
75
  interface LocalStatsIngestPerConnection {
66
76
  connectionId: string;
67
77
  adapter: string;
@@ -135,6 +145,7 @@ export interface BuildProjectStatusOptions {
135
145
  env?: NodeJS.ProcessEnv;
136
146
  queryHistoryReadinessProbe?: HistoricSqlReadinessProbe;
137
147
  claudeCodeAuthProbe?: ClaudeCodeAuthProbe;
148
+ codexAuthProbe?: CodexAuthProbe;
138
149
  configIssues?: KtxConfigIssue[];
139
150
  fast?: boolean;
140
151
  useSpinner?: boolean;
@@ -1,6 +1,8 @@
1
1
  import { stat as statAsync, readdir as readdirAsync } from 'node:fs/promises';
2
2
  import { basename, join } from 'node:path';
3
3
  import { runClaudeCodeAuthProbe } from './context/llm/claude-code-runtime.js';
4
+ import { CODEX_ISOLATION_WARNING, CODEX_ISOLATION_WARNING_FIX, } from './context/llm/codex-isolation.js';
5
+ import { runCodexAuthProbe } from './context/llm/codex-runtime.js';
4
6
  import { ktxLocalStateDbPath } from './context/project/local-state-db.js';
5
7
  import { isQueryHistoryEnabled, queryHistoryDialectForConnection, } from './context/ingest/adapters/historic-sql/connection-dialect.js';
6
8
  import { historicSqlProbeCatalogName, runHistoricSqlReadinessProbe, } from './context/ingest/historic-sql-probes.js';
@@ -49,6 +51,18 @@ async function buildLlmStatus(config, options) {
49
51
  fix: 'Run: ktx setup (choose an LLM provider)',
50
52
  };
51
53
  }
54
+ // The runtime (resolveModelSlots) hard-requires llm.models.default for every
55
+ // non-none backend; without it ingest/scan/memory throw. Report that here so
56
+ // status never marks a project ready that the runtime would refuse to run.
57
+ if (!model || model.trim().length === 0) {
58
+ return {
59
+ backend,
60
+ model,
61
+ status: 'fail',
62
+ detail: `llm.models.default is required for backend "${backend}"`,
63
+ fix: 'Set llm.models.default in ktx.yaml, then rerun `ktx status` (or rerun `ktx setup`).',
64
+ };
65
+ }
52
66
  if (backend === 'anthropic') {
53
67
  const ref = config.provider.anthropic?.api_key;
54
68
  const resolved = resolveRef(ref, env);
@@ -90,7 +104,7 @@ async function buildLlmStatus(config, options) {
90
104
  };
91
105
  }
92
106
  if (backend === 'claude-code') {
93
- const modelName = model ?? 'sonnet';
107
+ const modelName = model;
94
108
  if (options.fast === true) {
95
109
  return {
96
110
  backend,
@@ -117,6 +131,34 @@ async function buildLlmStatus(config, options) {
117
131
  fix: 'Authenticate Claude Code locally with the Claude Code CLI, then rerun `ktx status`.',
118
132
  };
119
133
  }
134
+ if (backend === 'codex') {
135
+ const modelName = model;
136
+ if (options.fast === true) {
137
+ return {
138
+ backend,
139
+ model: modelName,
140
+ status: 'skipped',
141
+ detail: 'auth probe skipped (--fast)',
142
+ };
143
+ }
144
+ const probe = options.codexAuthProbe ?? runCodexAuthProbe;
145
+ const auth = await withSpinner(options.useSpinner === true, 'Probing Codex authentication', () => probe({ projectDir: options.projectDir, model: modelName }));
146
+ if (auth.ok) {
147
+ return {
148
+ backend,
149
+ model: modelName,
150
+ status: 'ok',
151
+ detail: 'local Codex session authenticated',
152
+ };
153
+ }
154
+ return {
155
+ backend,
156
+ model: modelName,
157
+ status: 'fail',
158
+ detail: auth.message,
159
+ fix: auth.fix,
160
+ };
161
+ }
120
162
  return { backend, model, status: 'warn', detail: 'unknown LLM backend' };
121
163
  }
122
164
  function buildEmbeddingsStatus(config, env) {
@@ -378,6 +420,12 @@ function buildWarnings(config, connections, llm, embeddings) {
378
420
  fix: formatClaudeCodePromptCachingFix(),
379
421
  });
380
422
  }
423
+ if (llm.backend === 'codex') {
424
+ warnings.push({
425
+ message: CODEX_ISOLATION_WARNING,
426
+ fix: CODEX_ISOLATION_WARNING_FIX,
427
+ });
428
+ }
381
429
  return warnings;
382
430
  }
383
431
  function buildVerdict(llm, embeddings, connections, queryHistory, warnings) {
@@ -625,6 +673,7 @@ export async function buildProjectStatus(project, options = {}) {
625
673
  projectDir: project.projectDir,
626
674
  env,
627
675
  claudeCodeAuthProbe: options.claudeCodeAuthProbe,
676
+ codexAuthProbe: options.codexAuthProbe,
628
677
  fast: options.fast,
629
678
  useSpinner: options.useSpinner,
630
679
  });
@@ -12,6 +12,7 @@ export interface CompletedCommandSpan {
12
12
  durationMs: number;
13
13
  outcome: CommandOutcome;
14
14
  errorClass?: string;
15
+ errorDetail?: string;
15
16
  flagsPresent: Record<string, boolean>;
16
17
  hasProject: boolean;
17
18
  projectDir?: string;
@@ -1,4 +1,4 @@
1
- import { scrubErrorClass } from './scrubber.js';
1
+ import { formatErrorDetail, scrubErrorClass } from './scrubber.js';
2
2
  let activeCommandSpan;
3
3
  export function beginCommandSpan(input) {
4
4
  activeCommandSpan = input;
@@ -10,11 +10,13 @@ export function completeCommandSpan(input) {
10
10
  return undefined;
11
11
  }
12
12
  const errorClass = input.error ? scrubErrorClass(input.error) : undefined;
13
+ const errorDetail = input.error ? formatErrorDetail(input.error) : undefined;
13
14
  return {
14
15
  commandPath: span.commandPath,
15
16
  durationMs: Math.max(0, input.completedAt - span.startedAt),
16
17
  outcome: input.outcome,
17
18
  ...(errorClass ? { errorClass } : {}),
19
+ ...(errorDetail ? { errorDetail } : {}),
18
20
  flagsPresent: span.flagsPresent,
19
21
  hasProject: span.hasProject,
20
22
  projectDir: span.projectDir,
@@ -15,6 +15,16 @@ export declare function trackTelemetryEvent(input: {
15
15
  projectApiKey?: string;
16
16
  host?: string;
17
17
  }): Promise<void>;
18
+ export declare function trackTelemetryException(input: {
19
+ error: Error;
20
+ distinctId: string;
21
+ properties: Record<string, unknown>;
22
+ env?: TelemetryEmitterEnv;
23
+ stderr: TelemetrySink;
24
+ projectApiKey?: string;
25
+ host?: string;
26
+ immediate?: boolean;
27
+ }): Promise<void>;
18
28
  export declare function shutdownTelemetryEmitter(): Promise<void>;
19
29
  /** @internal */
20
30
  export declare function __resetTelemetryEmitterForTests(): void;
@@ -56,6 +56,37 @@ export async function trackTelemetryEvent(input) {
56
56
  return;
57
57
  }
58
58
  }
59
+ function writeDebugExceptionPayload(input) {
60
+ input.stderr.write(`[telemetry-exception] ${JSON.stringify({
61
+ distinctId: input.distinctId,
62
+ message: input.error.message,
63
+ name: input.error.name,
64
+ properties: input.properties,
65
+ })}\n`);
66
+ }
67
+ export async function trackTelemetryException(input) {
68
+ const env = input.env ?? process.env;
69
+ if (debugEnabled(env)) {
70
+ writeDebugExceptionPayload(input);
71
+ return;
72
+ }
73
+ const projectApiKey = telemetryProjectApiKey(input.projectApiKey);
74
+ const host = telemetryHost(env, input.host);
75
+ const client = await getPostHogClient(projectApiKey, host);
76
+ if (!client) {
77
+ return;
78
+ }
79
+ try {
80
+ if (input.immediate) {
81
+ await client.captureExceptionImmediate(input.error, input.distinctId, input.properties);
82
+ return;
83
+ }
84
+ client.captureException(input.error, input.distinctId, input.properties);
85
+ }
86
+ catch {
87
+ return;
88
+ }
89
+ }
59
90
  export async function shutdownTelemetryEmitter() {
60
91
  const client = await clientPromise;
61
92
  if (!client) {
@@ -44,6 +44,7 @@ export declare const telemetryEventSchemas: {
44
44
  aborted: "aborted";
45
45
  }>;
46
46
  errorClass: z.ZodOptional<z.ZodString>;
47
+ errorDetail: z.ZodOptional<z.ZodString>;
47
48
  flagsPresent: z.ZodRecord<z.ZodString, z.ZodBoolean>;
48
49
  hasProject: z.ZodBoolean;
49
50
  projectGroupAttached: z.ZodBoolean;
@@ -67,8 +68,8 @@ export declare const telemetryEventSchemas: {
67
68
  databases: "databases";
68
69
  context: "context";
69
70
  runtime: "runtime";
70
- agents: "agents";
71
71
  secrets: "secrets";
72
+ agents: "agents";
72
73
  "demo-tour": "demo-tour";
73
74
  }>;
74
75
  outcome: z.ZodEnum<{
@@ -77,6 +78,7 @@ export declare const telemetryEventSchemas: {
77
78
  abandoned: "abandoned";
78
79
  }>;
79
80
  durationMs: z.ZodNumber;
81
+ errorDetail: z.ZodOptional<z.ZodString>;
80
82
  }, z.core.$strict>;
81
83
  readonly connection_added: z.ZodObject<{
82
84
  cliVersion: z.ZodString;
@@ -110,6 +112,7 @@ export declare const telemetryEventSchemas: {
110
112
  error: "error";
111
113
  }>;
112
114
  errorClass: z.ZodOptional<z.ZodString>;
115
+ errorDetail: z.ZodOptional<z.ZodString>;
113
116
  durationMs: z.ZodNumber;
114
117
  serverVersion: z.ZodOptional<z.ZodString>;
115
118
  }, z.core.$strict>;
@@ -163,6 +166,7 @@ export declare const telemetryEventSchemas: {
163
166
  error: "error";
164
167
  }>;
165
168
  errorClass: z.ZodOptional<z.ZodString>;
169
+ errorDetail: z.ZodOptional<z.ZodString>;
166
170
  }, z.core.$strict>;
167
171
  readonly scan_completed: z.ZodObject<{
168
172
  cliVersion: z.ZodString;
@@ -186,6 +190,7 @@ export declare const telemetryEventSchemas: {
186
190
  error: "error";
187
191
  }>;
188
192
  errorClass: z.ZodOptional<z.ZodString>;
193
+ errorDetail: z.ZodOptional<z.ZodString>;
189
194
  }, z.core.$strict>;
190
195
  readonly sl_validate_completed: z.ZodObject<{
191
196
  cliVersion: z.ZodString;
@@ -381,6 +386,26 @@ export declare const telemetryEventSchemas: {
381
386
  errorClass: z.ZodOptional<z.ZodString>;
382
387
  durationMs: z.ZodNumber;
383
388
  }, z.core.$strict>;
389
+ readonly query_history_filter_completed: z.ZodObject<{
390
+ cliVersion: z.ZodString;
391
+ nodeVersion: z.ZodString;
392
+ osPlatform: z.ZodString;
393
+ osRelease: z.ZodString;
394
+ arch: z.ZodString;
395
+ runtime: z.ZodEnum<{
396
+ node: "node";
397
+ "daemon-py": "daemon-py";
398
+ }>;
399
+ isCi: z.ZodBoolean;
400
+ dialect: z.ZodString;
401
+ consideredRoleCount: z.ZodNumber;
402
+ excludedRoleCount: z.ZodNumber;
403
+ parseFailedCount: z.ZodNumber;
404
+ outcome: z.ZodEnum<{
405
+ ok: "ok";
406
+ error: "error";
407
+ }>;
408
+ }, z.core.$strict>;
384
409
  };
385
410
  /** @internal */
386
411
  export declare const telemetryEventCatalog: readonly [{
@@ -390,11 +415,11 @@ export declare const telemetryEventCatalog: readonly [{
390
415
  }, {
391
416
  readonly name: "command";
392
417
  readonly description: "Emitted once for each Commander action that reaches preAction.";
393
- readonly fields: readonly ["commandPath", "durationMs", "outcome", "errorClass", "flagsPresent", "hasProject", "projectGroupAttached"];
418
+ readonly fields: readonly ["commandPath", "durationMs", "outcome", "errorClass", "errorDetail", "flagsPresent", "hasProject", "projectGroupAttached"];
394
419
  }, {
395
420
  readonly name: "setup_step";
396
421
  readonly description: "Emitted after an interactive setup step completes, skips, or aborts.";
397
- readonly fields: readonly ["step", "outcome", "durationMs"];
422
+ readonly fields: readonly ["step", "outcome", "durationMs", "errorDetail"];
398
423
  }, {
399
424
  readonly name: "connection_added";
400
425
  readonly description: "Emitted when setup writes a database, source, or demo connection.";
@@ -402,7 +427,7 @@ export declare const telemetryEventCatalog: readonly [{
402
427
  }, {
403
428
  readonly name: "connection_test";
404
429
  readonly description: "Emitted after ktx connection test completes.";
405
- readonly fields: readonly ["driver", "isDemoConnection", "outcome", "errorClass", "durationMs", "serverVersion"];
430
+ readonly fields: readonly ["driver", "isDemoConnection", "outcome", "errorClass", "errorDetail", "durationMs", "serverVersion"];
406
431
  }, {
407
432
  readonly name: "project_stack_snapshot";
408
433
  readonly description: "Emitted after commands that can summarize the local project stack.";
@@ -410,11 +435,11 @@ export declare const telemetryEventCatalog: readonly [{
410
435
  }, {
411
436
  readonly name: "ingest_completed";
412
437
  readonly description: "Emitted after a public ingest target completes.";
413
- readonly fields: readonly ["driver", "isDemoConnection", "schemaCount", "tableCount", "columnCount", "rowsBucket", "durationMs", "outcome", "errorClass"];
438
+ readonly fields: readonly ["driver", "isDemoConnection", "schemaCount", "tableCount", "columnCount", "rowsBucket", "durationMs", "outcome", "errorClass", "errorDetail"];
414
439
  }, {
415
440
  readonly name: "scan_completed";
416
441
  readonly description: "Emitted after schema scan or relationship inference completes.";
417
- readonly fields: readonly ["driver", "tableCount", "columnCount", "inferredFkCount", "declaredFkCount", "durationMs", "outcome", "errorClass"];
442
+ readonly fields: readonly ["driver", "tableCount", "columnCount", "inferredFkCount", "declaredFkCount", "durationMs", "outcome", "errorClass", "errorDetail"];
418
443
  }, {
419
444
  readonly name: "sl_validate_completed";
420
445
  readonly description: "Emitted after ktx sl validate completes.";
@@ -451,6 +476,10 @@ export declare const telemetryEventCatalog: readonly [{
451
476
  readonly name: "sql_gen_completed";
452
477
  readonly description: "Emitted after daemon SQL generation completes.";
453
478
  readonly fields: readonly ["outcome", "dialect", "errorClass", "durationMs"];
479
+ }, {
480
+ readonly name: "query_history_filter_completed";
481
+ readonly description: "Emitted after the setup query-history service-account filter picker runs.";
482
+ readonly fields: readonly ["dialect", "consideredRoleCount", "excludedRoleCount", "parseFailedCount", "outcome"];
454
483
  }];
455
484
  export type TelemetryEventName = keyof typeof telemetryEventSchemas;
456
485
  export type TelemetryCommonEnvelope = z.infer<typeof telemetryCommonEnvelopeSchema>;
@@ -18,6 +18,7 @@ const commandSchema = telemetryCommonEnvelopeSchema
18
18
  durationMs: z.number().nonnegative(),
19
19
  outcome: z.enum(['ok', 'error', 'aborted']),
20
20
  errorClass: z.string().optional(),
21
+ errorDetail: z.string().max(1000).optional(),
21
22
  flagsPresent: z.record(z.string(), z.boolean()),
22
23
  hasProject: z.boolean(),
23
24
  projectGroupAttached: z.boolean(),
@@ -40,6 +41,7 @@ const setupStepSchema = telemetryCommonEnvelopeSchema
40
41
  ]),
41
42
  outcome: z.enum(['completed', 'skipped', 'abandoned']),
42
43
  durationMs: z.number().nonnegative(),
44
+ errorDetail: z.string().max(1000).optional(),
43
45
  })
44
46
  .strict();
45
47
  const connectionAddedSchema = telemetryCommonEnvelopeSchema
@@ -54,6 +56,7 @@ const connectionTestSchema = telemetryCommonEnvelopeSchema
54
56
  isDemoConnection: z.boolean(),
55
57
  outcome: outcomeSchema,
56
58
  errorClass: z.string().optional(),
59
+ errorDetail: z.string().max(1000).optional(),
57
60
  durationMs: z.number().nonnegative(),
58
61
  serverVersion: z.string().optional(),
59
62
  })
@@ -80,6 +83,7 @@ const ingestCompletedSchema = telemetryCommonEnvelopeSchema
80
83
  durationMs: z.number().nonnegative(),
81
84
  outcome: outcomeSchema,
82
85
  errorClass: z.string().optional(),
86
+ errorDetail: z.string().max(1000).optional(),
83
87
  })
84
88
  .strict();
85
89
  const scanCompletedSchema = telemetryCommonEnvelopeSchema
@@ -92,6 +96,7 @@ const scanCompletedSchema = telemetryCommonEnvelopeSchema
92
96
  durationMs: z.number().nonnegative(),
93
97
  outcome: outcomeSchema,
94
98
  errorClass: z.string().optional(),
99
+ errorDetail: z.string().max(1000).optional(),
95
100
  })
96
101
  .strict();
97
102
  const slValidateCompletedSchema = telemetryCommonEnvelopeSchema
@@ -180,6 +185,15 @@ const sqlGenCompletedSchema = telemetryCommonEnvelopeSchema
180
185
  durationMs: z.number().nonnegative(),
181
186
  })
182
187
  .strict();
188
+ const queryHistoryFilterCompletedSchema = telemetryCommonEnvelopeSchema
189
+ .extend({
190
+ dialect: z.string(),
191
+ consideredRoleCount: z.number().int().nonnegative(),
192
+ excludedRoleCount: z.number().int().nonnegative(),
193
+ parseFailedCount: z.number().int().nonnegative(),
194
+ outcome: outcomeSchema,
195
+ })
196
+ .strict();
183
197
  /** @internal */
184
198
  export const telemetryEventSchemas = {
185
199
  install_first_run: installFirstRunSchema,
@@ -199,6 +213,7 @@ export const telemetryEventSchemas = {
199
213
  daemon_stopped: daemonStoppedSchema,
200
214
  sl_plan_completed: slPlanCompletedSchema,
201
215
  sql_gen_completed: sqlGenCompletedSchema,
216
+ query_history_filter_completed: queryHistoryFilterCompletedSchema,
202
217
  };
203
218
  /** @internal */
204
219
  export const telemetryEventCatalog = [
@@ -215,6 +230,7 @@ export const telemetryEventCatalog = [
215
230
  'durationMs',
216
231
  'outcome',
217
232
  'errorClass',
233
+ 'errorDetail',
218
234
  'flagsPresent',
219
235
  'hasProject',
220
236
  'projectGroupAttached',
@@ -223,7 +239,7 @@ export const telemetryEventCatalog = [
223
239
  {
224
240
  name: 'setup_step',
225
241
  description: 'Emitted after an interactive setup step completes, skips, or aborts.',
226
- fields: ['step', 'outcome', 'durationMs'],
242
+ fields: ['step', 'outcome', 'durationMs', 'errorDetail'],
227
243
  },
228
244
  {
229
245
  name: 'connection_added',
@@ -233,7 +249,7 @@ export const telemetryEventCatalog = [
233
249
  {
234
250
  name: 'connection_test',
235
251
  description: 'Emitted after ktx connection test completes.',
236
- fields: ['driver', 'isDemoConnection', 'outcome', 'errorClass', 'durationMs', 'serverVersion'],
252
+ fields: ['driver', 'isDemoConnection', 'outcome', 'errorClass', 'errorDetail', 'durationMs', 'serverVersion'],
237
253
  },
238
254
  {
239
255
  name: 'project_stack_snapshot',
@@ -253,6 +269,7 @@ export const telemetryEventCatalog = [
253
269
  'durationMs',
254
270
  'outcome',
255
271
  'errorClass',
272
+ 'errorDetail',
256
273
  ],
257
274
  },
258
275
  {
@@ -267,6 +284,7 @@ export const telemetryEventCatalog = [
267
284
  'durationMs',
268
285
  'outcome',
269
286
  'errorClass',
287
+ 'errorDetail',
270
288
  ],
271
289
  },
272
290
  {
@@ -330,6 +348,11 @@ export const telemetryEventCatalog = [
330
348
  description: 'Emitted after daemon SQL generation completes.',
331
349
  fields: ['outcome', 'dialect', 'errorClass', 'durationMs'],
332
350
  },
351
+ {
352
+ name: 'query_history_filter_completed',
353
+ description: 'Emitted after the setup query-history service-account filter picker runs.',
354
+ fields: ['dialect', 'consideredRoleCount', 'excludedRoleCount', 'parseFailedCount', 'outcome'],
355
+ },
333
356
  ];
334
357
  export function buildCommonEnvelope(input) {
335
358
  return {
@@ -0,0 +1,18 @@
1
+ import { type KtxCliIo, type KtxCliPackageInfo } from '../cli-runtime.js';
2
+ export interface ExceptionContext {
3
+ source: string;
4
+ handled: boolean;
5
+ fatal: boolean;
6
+ extra?: Record<string, string | number | boolean>;
7
+ }
8
+ export declare function reportException(input: {
9
+ error: unknown;
10
+ context: ExceptionContext;
11
+ io: KtxCliIo;
12
+ packageInfo?: KtxCliPackageInfo;
13
+ projectDir?: string;
14
+ immediate?: boolean;
15
+ redactionSecrets?: ReadonlyArray<string>;
16
+ }): Promise<void>;
17
+ /** @internal */
18
+ export declare function __resetTelemetryExceptionStateForTests(): void;