@kaelio/ktx 0.1.0-rc.5 → 0.1.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 (180) hide show
  1. package/assets/python/kaelio_ktx-0.1.0-py3-none-any.whl +0 -0
  2. package/assets/python/manifest.json +2 -2
  3. package/dist/clack.d.ts +6 -0
  4. package/dist/clack.js +23 -0
  5. package/dist/cli-program.js +5 -2
  6. package/dist/cli-program.test.js +7 -1
  7. package/dist/cli-runtime.d.ts +4 -0
  8. package/dist/cli-runtime.js +8 -1
  9. package/dist/command-schemas.d.ts +1 -1
  10. package/dist/commands/ingest-commands.js +1 -0
  11. package/dist/commands/knowledge-commands.js +5 -0
  12. package/dist/commands/mcp-commands.js +11 -3
  13. package/dist/commands/mcp-commands.test.js +30 -1
  14. package/dist/commands/sql-commands.d.ts +3 -0
  15. package/dist/commands/sql-commands.js +43 -0
  16. package/dist/commands/sql-commands.test.d.ts +1 -0
  17. package/dist/commands/sql-commands.test.js +68 -0
  18. package/dist/context-build-view.js +5 -1
  19. package/dist/dev.test.js +27 -0
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.js +1 -0
  22. package/dist/index.test.js +56 -21
  23. package/dist/ingest.js +123 -18
  24. package/dist/ingest.test.js +206 -0
  25. package/dist/io/print-list.d.ts +2 -1
  26. package/dist/io/print-list.js +7 -0
  27. package/dist/io/print-list.test.js +13 -11
  28. package/dist/io/symbols.d.ts +2 -2
  29. package/dist/knowledge.d.ts +1 -0
  30. package/dist/knowledge.js +34 -16
  31. package/dist/knowledge.test.js +27 -0
  32. package/dist/managed-python-command.d.ts +2 -0
  33. package/dist/managed-python-command.js +17 -9
  34. package/dist/managed-python-command.test.js +59 -4
  35. package/dist/next-steps.js +1 -1
  36. package/dist/next-steps.test.js +2 -0
  37. package/dist/print-command-tree.js +7 -1
  38. package/dist/public-ingest.d.ts +9 -1
  39. package/dist/public-ingest.js +50 -7
  40. package/dist/public-ingest.test.js +69 -2
  41. package/dist/release-version.d.ts +5 -0
  42. package/dist/release-version.js +44 -0
  43. package/dist/runtime-requirements.d.ts +23 -0
  44. package/dist/runtime-requirements.js +99 -0
  45. package/dist/runtime-requirements.test.d.ts +1 -0
  46. package/dist/runtime-requirements.test.js +63 -0
  47. package/dist/setup-agents.d.ts +11 -3
  48. package/dist/setup-agents.js +397 -134
  49. package/dist/setup-agents.test.js +359 -61
  50. package/dist/setup-embeddings.js +3 -6
  51. package/dist/setup-embeddings.test.js +18 -2
  52. package/dist/setup-models.js +2 -2
  53. package/dist/setup-models.test.js +5 -3
  54. package/dist/setup-ready-menu.d.ts +1 -1
  55. package/dist/setup-ready-menu.js +2 -0
  56. package/dist/setup-ready-menu.test.js +3 -0
  57. package/dist/setup-runtime.d.ts +45 -0
  58. package/dist/setup-runtime.js +47 -0
  59. package/dist/setup-runtime.test.d.ts +1 -0
  60. package/dist/setup-runtime.test.js +110 -0
  61. package/dist/setup-sources-notion.test.d.ts +1 -0
  62. package/dist/setup-sources-notion.test.js +107 -0
  63. package/dist/setup-sources.js +5 -2
  64. package/dist/setup.d.ts +19 -1
  65. package/dist/setup.js +104 -29
  66. package/dist/setup.test.js +221 -57
  67. package/dist/sl.js +2 -2
  68. package/dist/sl.test.js +10 -0
  69. package/dist/source-mapping.js +9 -1
  70. package/dist/source-mapping.test.d.ts +1 -0
  71. package/dist/source-mapping.test.js +65 -0
  72. package/dist/sql.d.ts +22 -0
  73. package/dist/sql.js +125 -0
  74. package/dist/sql.test.d.ts +1 -0
  75. package/dist/sql.test.js +226 -0
  76. package/node_modules/@ktx/connector-clickhouse/dist/package-exports.test.js +1 -1
  77. package/node_modules/@ktx/context/dist/connections/connection-type.d.ts +4 -4
  78. package/node_modules/@ktx/context/dist/core/git.service.d.ts +3 -0
  79. package/node_modules/@ktx/context/dist/core/git.service.js +47 -1
  80. package/node_modules/@ktx/context/dist/core/git.service.patch.test.d.ts +1 -0
  81. package/node_modules/@ktx/context/dist/core/git.service.patch.test.js +40 -0
  82. package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/types.d.ts +5 -5
  83. package/node_modules/@ktx/context/dist/ingest/adapters/looker/looker.adapter.d.ts +2 -2
  84. package/node_modules/@ktx/context/dist/ingest/adapters/looker/tools/looker-query-to-sl.tool.d.ts +2 -2
  85. package/node_modules/@ktx/context/dist/ingest/adapters/looker/types.d.ts +16 -16
  86. package/node_modules/@ktx/context/dist/ingest/adapters/lookml/pull-config.d.ts +1 -1
  87. package/node_modules/@ktx/context/dist/ingest/adapters/metabase/fetch.js +16 -0
  88. package/node_modules/@ktx/context/dist/ingest/adapters/metabase/fetch.test.js +41 -0
  89. package/node_modules/@ktx/context/dist/ingest/adapters/metricflow/metricflow.adapter.d.ts +2 -1
  90. package/node_modules/@ktx/context/dist/ingest/adapters/metricflow/metricflow.adapter.js +40 -0
  91. package/node_modules/@ktx/context/dist/ingest/adapters/metricflow/metricflow.adapter.test.js +116 -1
  92. package/node_modules/@ktx/context/dist/ingest/adapters/metricflow/projection-config.d.ts +29 -0
  93. package/node_modules/@ktx/context/dist/ingest/adapters/metricflow/projection-config.js +40 -0
  94. package/node_modules/@ktx/context/dist/ingest/adapters/metricflow/pull-config.d.ts +1 -1
  95. package/node_modules/@ktx/context/dist/ingest/artifact-gates.d.ts +25 -0
  96. package/node_modules/@ktx/context/dist/ingest/artifact-gates.js +149 -0
  97. package/node_modules/@ktx/context/dist/ingest/artifact-gates.test.d.ts +1 -0
  98. package/node_modules/@ktx/context/dist/ingest/artifact-gates.test.js +167 -0
  99. package/node_modules/@ktx/context/dist/ingest/final-gate-repair.d.ts +29 -0
  100. package/node_modules/@ktx/context/dist/ingest/final-gate-repair.js +178 -0
  101. package/node_modules/@ktx/context/dist/ingest/final-gate-repair.test.d.ts +1 -0
  102. package/node_modules/@ktx/context/dist/ingest/final-gate-repair.test.js +109 -0
  103. package/node_modules/@ktx/context/dist/ingest/index.d.ts +8 -1
  104. package/node_modules/@ktx/context/dist/ingest/index.js +7 -0
  105. package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.d.ts +18 -2
  106. package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.isolated-diff.test.d.ts +1 -0
  107. package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.isolated-diff.test.js +1761 -0
  108. package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.js +1695 -901
  109. package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.test.js +135 -118
  110. package/node_modules/@ktx/context/dist/ingest/ingest-trace.d.ts +50 -0
  111. package/node_modules/@ktx/context/dist/ingest/ingest-trace.js +88 -0
  112. package/node_modules/@ktx/context/dist/ingest/ingest-trace.test.d.ts +1 -0
  113. package/node_modules/@ktx/context/dist/ingest/ingest-trace.test.js +76 -0
  114. package/node_modules/@ktx/context/dist/ingest/isolated-diff/git-patch.d.ts +16 -0
  115. package/node_modules/@ktx/context/dist/ingest/isolated-diff/git-patch.js +78 -0
  116. package/node_modules/@ktx/context/dist/ingest/isolated-diff/git-patch.test.d.ts +1 -0
  117. package/node_modules/@ktx/context/dist/ingest/isolated-diff/git-patch.test.js +76 -0
  118. package/node_modules/@ktx/context/dist/ingest/isolated-diff/patch-integrator.d.ts +58 -0
  119. package/node_modules/@ktx/context/dist/ingest/isolated-diff/patch-integrator.js +223 -0
  120. package/node_modules/@ktx/context/dist/ingest/isolated-diff/patch-integrator.test.d.ts +1 -0
  121. package/node_modules/@ktx/context/dist/ingest/isolated-diff/patch-integrator.test.js +369 -0
  122. package/node_modules/@ktx/context/dist/ingest/isolated-diff/textual-conflict-resolver.d.ts +23 -0
  123. package/node_modules/@ktx/context/dist/ingest/isolated-diff/textual-conflict-resolver.js +190 -0
  124. package/node_modules/@ktx/context/dist/ingest/isolated-diff/textual-conflict-resolver.test.d.ts +1 -0
  125. package/node_modules/@ktx/context/dist/ingest/isolated-diff/textual-conflict-resolver.test.js +101 -0
  126. package/node_modules/@ktx/context/dist/ingest/isolated-diff/work-unit-executor.d.ts +15 -0
  127. package/node_modules/@ktx/context/dist/ingest/isolated-diff/work-unit-executor.js +61 -0
  128. package/node_modules/@ktx/context/dist/ingest/isolated-diff/work-unit-executor.test.d.ts +1 -0
  129. package/node_modules/@ktx/context/dist/ingest/isolated-diff/work-unit-executor.test.js +137 -0
  130. package/node_modules/@ktx/context/dist/ingest/local-bundle-ingest.test.js +7 -0
  131. package/node_modules/@ktx/context/dist/ingest/local-bundle-runtime.js +54 -10
  132. package/node_modules/@ktx/context/dist/ingest/local-bundle-runtime.test.js +65 -0
  133. package/node_modules/@ktx/context/dist/ingest/memory-flow/schema.d.ts +23 -5
  134. package/node_modules/@ktx/context/dist/ingest/memory-flow/schema.js +17 -0
  135. package/node_modules/@ktx/context/dist/ingest/memory-flow/schema.test.js +1 -0
  136. package/node_modules/@ktx/context/dist/ingest/memory-flow/types.d.ts +6 -0
  137. package/node_modules/@ktx/context/dist/ingest/parsed-target-table.d.ts +1 -1
  138. package/node_modules/@ktx/context/dist/ingest/ports.d.ts +3 -0
  139. package/node_modules/@ktx/context/dist/ingest/report-snapshot.d.ts +32 -7
  140. package/node_modules/@ktx/context/dist/ingest/report-snapshot.js +25 -0
  141. package/node_modules/@ktx/context/dist/ingest/report-snapshot.test.js +124 -0
  142. package/node_modules/@ktx/context/dist/ingest/reports.d.ts +23 -0
  143. package/node_modules/@ktx/context/dist/ingest/semantic-layer-target-policy.d.ts +11 -0
  144. package/node_modules/@ktx/context/dist/ingest/semantic-layer-target-policy.js +26 -0
  145. package/node_modules/@ktx/context/dist/ingest/semantic-layer-target-policy.test.d.ts +1 -0
  146. package/node_modules/@ktx/context/dist/ingest/semantic-layer-target-policy.test.js +25 -0
  147. package/node_modules/@ktx/context/dist/ingest/stages/stage-3-work-units.d.ts +4 -0
  148. package/node_modules/@ktx/context/dist/ingest/stages/stage-3-work-units.js +4 -0
  149. package/node_modules/@ktx/context/dist/ingest/stages/stage-3-work-units.test.js +29 -0
  150. package/node_modules/@ktx/context/dist/ingest/tools/emit-unmapped-fallback.tool.d.ts +1 -1
  151. package/node_modules/@ktx/context/dist/ingest/types.d.ts +24 -0
  152. package/node_modules/@ktx/context/dist/ingest/wiki-body-refs.d.ts +24 -0
  153. package/node_modules/@ktx/context/dist/ingest/wiki-body-refs.js +111 -0
  154. package/node_modules/@ktx/context/dist/ingest/wiki-body-refs.test.d.ts +1 -0
  155. package/node_modules/@ktx/context/dist/ingest/wiki-body-refs.test.js +138 -0
  156. package/node_modules/@ktx/context/dist/llm/claude-code-runtime.js +19 -2
  157. package/node_modules/@ktx/context/dist/llm/claude-code-runtime.test.js +33 -0
  158. package/node_modules/@ktx/context/dist/project/setup-config.d.ts +1 -1
  159. package/node_modules/@ktx/context/dist/project/setup-config.js +10 -1
  160. package/node_modules/@ktx/context/dist/project/setup-config.test.js +3 -2
  161. package/node_modules/@ktx/context/dist/sl/tools/sl-edit-source.tool.js +5 -1
  162. package/node_modules/@ktx/context/dist/sl/tools/sl-edit-source.tool.test.js +15 -0
  163. package/node_modules/@ktx/context/dist/sl/tools/sl-write-source.tool.js +5 -1
  164. package/node_modules/@ktx/context/dist/sl/tools/sl-write-source.tool.test.js +22 -0
  165. package/node_modules/@ktx/context/dist/tools/action-target-connection.d.ts +9 -0
  166. package/node_modules/@ktx/context/dist/tools/action-target-connection.js +14 -0
  167. package/node_modules/@ktx/context/dist/tools/context-candidate-write.tool.d.ts +4 -4
  168. package/node_modules/@ktx/context/dist/tools/index.d.ts +1 -0
  169. package/node_modules/@ktx/context/dist/tools/index.js +1 -0
  170. package/node_modules/@ktx/context/dist/wiki/local-knowledge.js +4 -1
  171. package/node_modules/@ktx/context/dist/wiki/local-knowledge.test.js +44 -0
  172. package/node_modules/@ktx/context/dist/wiki/tools/wiki-write.tool.js +3 -48
  173. package/node_modules/@ktx/context/dist/wiki/tools/wiki-write.tool.test.js +28 -0
  174. package/node_modules/@ktx/context/dist/wiki/wiki-ref-validation.d.ts +17 -0
  175. package/node_modules/@ktx/context/dist/wiki/wiki-ref-validation.js +79 -0
  176. package/node_modules/@ktx/context/dist/wiki/wiki-ref-validation.test.d.ts +1 -0
  177. package/node_modules/@ktx/context/dist/wiki/wiki-ref-validation.test.js +64 -0
  178. package/node_modules/@ktx/context/prompts/memory_agent_bundle_ingest_work_unit.md +23 -4
  179. package/node_modules/@ktx/context/skills/ingest_triage/SKILL.md +7 -3
  180. package/package.json +4 -4
package/dist/setup.js CHANGED
@@ -3,14 +3,18 @@ import { basename, join, resolve } from 'node:path';
3
3
  import { getLatestLocalIngestStatus, savedMemoryCountsForReport } from '@ktx/context/ingest';
4
4
  import { ktxLocalStateDbPath, loadKtxProject, readKtxSetupState, } from '@ktx/context/project';
5
5
  import { formatSetupNextStepLines } from './next-steps.js';
6
+ import { runtimeInstallPolicyFromFlags } from './managed-python-command.js';
7
+ import { readManagedPythonRuntimeStatus } from './managed-python-runtime.js';
8
+ import { resolveProjectRuntimeRequirements } from './runtime-requirements.js';
6
9
  import { isKtxSetupExitError } from './setup-interrupt.js';
7
- import { readKtxAgentInstallManifest, runKtxSetupAgentsStep, } from './setup-agents.js';
10
+ import { readKtxAgentInstallManifest, runKtxSetupAgentsStep, targetDisplayName, } from './setup-agents.js';
8
11
  import { runKtxSetupDatabasesStep, } from './setup-databases.js';
9
12
  import { runKtxSetupEmbeddingsStep } from './setup-embeddings.js';
10
13
  import { isKtxSetupLlmConfigReady, runKtxSetupAnthropicModelStep, } from './setup-models.js';
11
14
  import { runKtxSetupProjectStep } from './setup-project.js';
12
15
  import { isKtxPreAgentSetupReady, isKtxSetupReady, runKtxSetupReadyChangeMenu, } from './setup-ready-menu.js';
13
16
  import { runKtxSetupSourcesStep } from './setup-sources.js';
17
+ import { runKtxSetupRuntimeStep, } from './setup-runtime.js';
14
18
  import { createKtxSetupPromptAdapter, createKtxSetupUiAdapter, } from './setup-prompts.js';
15
19
  import { readKtxSetupContextState, runKtxSetupContextStep, setupContextStatusFromState, } from './setup-context.js';
16
20
  const SOURCE_DRIVERS = new Set(['dbt', 'metricflow', 'metabase', 'looker', 'lookml', 'notion']);
@@ -86,7 +90,7 @@ async function readIngestContextStatus(project) {
86
90
  runId: report.runId,
87
91
  };
88
92
  }
89
- export async function readKtxSetupStatus(projectDir) {
93
+ export async function readKtxSetupStatus(projectDir, options = {}) {
90
94
  const resolvedProjectDir = resolve(projectDir);
91
95
  if (!existsSync(join(resolvedProjectDir, 'ktx.yaml'))) {
92
96
  return {
@@ -95,6 +99,7 @@ export async function readKtxSetupStatus(projectDir) {
95
99
  embeddings: { ready: false },
96
100
  databases: [],
97
101
  sources: [],
102
+ runtime: { required: false, ready: true, features: [] },
98
103
  context: setupContextStatusFromState(await readKtxSetupContextState(resolvedProjectDir)),
99
104
  agents: [],
100
105
  };
@@ -130,6 +135,20 @@ export async function readKtxSetupStatus(projectDir) {
130
135
  });
131
136
  }
132
137
  const agents = [...agentMap.values()];
138
+ const runtimeRequirements = resolveProjectRuntimeRequirements(project.config, {
139
+ env: options.env ?? process.env,
140
+ });
141
+ let runtimeReady = runtimeRequirements.features.length === 0 || completedSteps.includes('runtime');
142
+ let runtimeDetail;
143
+ if (runtimeRequirements.features.length > 0 && options.cliVersion) {
144
+ const readRuntimeStatus = options.readRuntimeStatus ?? readManagedPythonRuntimeStatus;
145
+ const runtimeStatus = await readRuntimeStatus({ cliVersion: options.cliVersion, env: options.env ?? process.env });
146
+ runtimeDetail = runtimeStatus.detail;
147
+ runtimeReady =
148
+ runtimeStatus.kind === 'ready' &&
149
+ runtimeStatus.manifest !== undefined &&
150
+ runtimeRequirements.features.every((feature) => runtimeStatus.manifest?.features.includes(feature));
151
+ }
133
152
  return {
134
153
  project: { path: resolvedProjectDir, ready: true, name: basename(project.projectDir) || project.projectDir },
135
154
  llm,
@@ -142,6 +161,12 @@ export async function readKtxSetupStatus(projectDir) {
142
161
  ...source,
143
162
  ready: completedSteps.includes('sources'),
144
163
  })),
164
+ runtime: {
165
+ required: runtimeRequirements.features.length > 0,
166
+ ready: runtimeReady,
167
+ features: runtimeRequirements.features,
168
+ ...(runtimeDetail ? { detail: runtimeDetail } : {}),
169
+ },
145
170
  context: ingestContextStatus ?? setupContextStatus,
146
171
  agents,
147
172
  };
@@ -180,6 +205,11 @@ export function formatKtxSetupStatus(status) {
180
205
  `Embeddings ready: ${formatReady(status.embeddings.ready)}${status.embeddings.model ? ` (${status.embeddings.model})` : ''}`,
181
206
  `Databases configured: ${formatConnectionList(status.databases.map((database) => database.connectionId))}`,
182
207
  `Context sources configured: ${formatConnectionList(status.sources.map((source) => source.connectionId))}`,
208
+ ...(status.runtime.required
209
+ ? [
210
+ `Runtime ready: ${formatReady(status.runtime.ready)}${status.runtime.features.length > 0 ? ` (${status.runtime.features.join(', ')})` : ''}`,
211
+ ]
212
+ : []),
183
213
  `KTX context built: ${formatContextBuilt(status.context)}`,
184
214
  `Agent integration ready: ${formatReady(status.agents.some((agent) => agent.ready))}${status.agents.length > 0 ? ` (${status.agents.map((agent) => `${agent.target}:${agent.scope}`).join(', ')})` : ''}`,
185
215
  ];
@@ -188,6 +218,26 @@ export function formatKtxSetupStatus(status) {
188
218
  }
189
219
  return `${lines.join('\n')}\n`;
190
220
  }
221
+ export function formatKtxSetupCompletionSummary(status, options = {}) {
222
+ const readyAgents = status.agents.filter((agent) => agent.ready).map((agent) => targetDisplayName(agent.target));
223
+ const lines = [
224
+ 'Project',
225
+ ` ${status.project.path}`,
226
+ '',
227
+ 'Context',
228
+ ` ${status.context.ready ? 'built' : formatContextBuilt(status.context)}`,
229
+ '',
230
+ 'Agents configured',
231
+ ` ${readyAgents.length > 0 ? readyAgents.join(', ') : 'not installed'}`,
232
+ ];
233
+ const agentNextActions = options.agentNextActions?.trim();
234
+ if (agentNextActions) {
235
+ lines.push('', 'REQUIRED BEFORE USING AGENTS', '', ...agentNextActions.split('\n').map((line) => (line ? ` ${line}` : '')));
236
+ }
237
+ lines.push('', agentNextActions ? 'After that, try' : 'Try it');
238
+ lines.push(' Ask your agent: "Use KTX to show me the available tables."');
239
+ return lines.join('\n');
240
+ }
191
241
  function setupStatusReady(status) {
192
242
  if (!status.project.ready) {
193
243
  return false;
@@ -198,7 +248,8 @@ function setupStatusReady(status) {
198
248
  return (status.llm.ready &&
199
249
  embeddingsReady(status.embeddings) &&
200
250
  status.databases.every((database) => database.ready) &&
201
- status.sources.every((source) => source.ready));
251
+ status.sources.every((source) => source.ready) &&
252
+ status.runtime.ready);
202
253
  }
203
254
  function setupHasContextTargets(status) {
204
255
  return status.databases.length > 0 || status.sources.length > 0;
@@ -206,13 +257,14 @@ function setupHasContextTargets(status) {
206
257
  function setupContextReady(status) {
207
258
  return status.context.ready;
208
259
  }
209
- function writeContextNotReadyForAgents(projectDir, io) {
210
- io.stderr.write('KTX context is not ready for agents.\n\n');
211
- io.stderr.write(`Build context first:\n ktx setup --project-dir ${resolve(projectDir)}\n\n`);
212
- io.stderr.write(`Then install agent integration:\n ktx setup --agents --project-dir ${resolve(projectDir)}\n`);
260
+ function shouldPrintConciseReadySummary(status) {
261
+ return setupStatusReady(status) && setupContextReady(status) && status.agents.some((agent) => agent.ready);
213
262
  }
214
263
  function setupRuntimeInstallPolicy(args) {
215
- return args.inputMode === 'disabled' && !args.yes ? 'never' : 'auto';
264
+ if (args.yes) {
265
+ return 'auto';
266
+ }
267
+ return runtimeInstallPolicyFromFlags({ input: args.inputMode === 'disabled' ? false : true });
216
268
  }
217
269
  async function commitSetupConfigChanges(projectDir) {
218
270
  const project = await loadKtxProject({ projectDir });
@@ -234,6 +286,7 @@ async function runKtxSetupInner(args, io, deps = {}) {
234
286
  setupUi.intro('KTX setup', io);
235
287
  let entryAction;
236
288
  let projectResult;
289
+ let agentNextActions;
237
290
  const canShowEntryMenu = args.showEntryMenu === true &&
238
291
  args.inputMode !== 'disabled' &&
239
292
  !args.agents &&
@@ -241,7 +294,7 @@ async function runKtxSetupInner(args, io, deps = {}) {
241
294
  setupLoop: while (true) {
242
295
  entryAction = undefined;
243
296
  if (canShowEntryMenu) {
244
- const status = await readKtxSetupStatus(args.projectDir);
297
+ const status = await readKtxSetupStatus(args.projectDir, { cliVersion: args.cliVersion });
245
298
  entryAction = (await runKtxSetupEntryMenu(status, deps.entryMenuDeps)).action;
246
299
  if (entryAction === 'exit') {
247
300
  (deps.entryMenuDeps?.prompts ?? createEntryMenuPromptAdapter()).cancel('Setup cancelled.');
@@ -270,7 +323,7 @@ async function runKtxSetupInner(args, io, deps = {}) {
270
323
  return projectResult.status === 'cancelled' ? 0 : 1;
271
324
  }
272
325
  const agentsRequested = args.agents || entryAction === 'agents';
273
- const currentStatus = await readKtxSetupStatus(projectResult.projectDir);
326
+ const currentStatus = await readKtxSetupStatus(projectResult.projectDir, { cliVersion: args.cliVersion });
274
327
  let readyAction;
275
328
  if (args.inputMode !== 'disabled' && !agentsRequested) {
276
329
  if (isKtxSetupReady(currentStatus)) {
@@ -283,16 +336,18 @@ async function runKtxSetupInner(args, io, deps = {}) {
283
336
  }
284
337
  }
285
338
  const runOnly = readyAction;
339
+ const agentOnlySetup = agentsRequested || runOnly === 'agents';
286
340
  const shouldRunModels = !runOnly || runOnly === 'models';
287
341
  const shouldRunEmbeddings = !runOnly || runOnly === 'embeddings';
288
342
  const shouldRunDatabases = !runOnly || runOnly === 'databases';
289
343
  const shouldRunSources = !runOnly || runOnly === 'sources';
290
- const shouldRunContext = agentsRequested || !runOnly || runOnly === 'context';
344
+ const shouldRunRuntime = !agentOnlySetup && (!runOnly || runOnly === 'runtime' || runOnly === 'context');
345
+ const shouldRunContext = !agentOnlySetup && (!runOnly || runOnly === 'context');
291
346
  const shouldRunAgents = agentsRequested || !runOnly || runOnly === 'agents';
292
347
  const showPromptInstructions = projectResult.confirmedCreation !== true;
293
- const setupSteps = agentsRequested
294
- ? ['context']
295
- : ['models', 'embeddings', 'databases', 'sources', 'context'];
348
+ const setupSteps = agentOnlySetup
349
+ ? []
350
+ : ['models', 'embeddings', 'databases', 'sources', 'runtime', 'context'];
296
351
  if (shouldRunAgents && args.skipAgents !== true) {
297
352
  setupSteps.push('agents');
298
353
  }
@@ -306,6 +361,8 @@ async function runKtxSetupInner(args, io, deps = {}) {
306
361
  return !args.skipDatabases && shouldRunDatabases;
307
362
  if (step === 'sources')
308
363
  return args.skipSources !== true && shouldRunSources;
364
+ if (step === 'runtime')
365
+ return shouldRunRuntime;
309
366
  if (step === 'context')
310
367
  return shouldRunContext;
311
368
  return shouldRunAgents && args.skipAgents !== true;
@@ -410,6 +467,16 @@ async function runKtxSetupInner(args, io, deps = {}) {
410
467
  skipSources: args.skipSources === true || !shouldRunSources,
411
468
  }, io);
412
469
  }
470
+ else if (step === 'runtime') {
471
+ const runtimeRunner = deps.runtime ??
472
+ ((runtimeArgs, runtimeIo) => runKtxSetupRuntimeStep(runtimeArgs, runtimeIo, deps.runtimeDeps));
473
+ stepResult = await runtimeRunner({
474
+ projectDir: projectResult.projectDir,
475
+ inputMode: args.inputMode,
476
+ cliVersion: args.cliVersion,
477
+ runtimeInstallPolicy: setupRuntimeInstallPolicy(args),
478
+ }, io);
479
+ }
413
480
  else if (step === 'context') {
414
481
  const contextRunner = deps.context ??
415
482
  ((contextArgs, contextIo) => runKtxSetupContextStep(contextArgs, contextIo, deps.contextDeps));
@@ -424,7 +491,7 @@ async function runKtxSetupInner(args, io, deps = {}) {
424
491
  }
425
492
  else {
426
493
  const agentsRunner = deps.agents ?? ((agentArgs, agentIo) => runKtxSetupAgentsStep(agentArgs, agentIo, deps.agentsDeps));
427
- stepResult = await agentsRunner({
494
+ const agentResult = await agentsRunner({
428
495
  projectDir: projectResult.projectDir,
429
496
  inputMode: args.inputMode,
430
497
  yes: args.yes,
@@ -433,7 +500,12 @@ async function runKtxSetupInner(args, io, deps = {}) {
433
500
  scope: args.agentScope ?? 'project',
434
501
  mode: 'mcp',
435
502
  skipAgents: false,
503
+ showNextActions: agentsRequested,
436
504
  }, io);
505
+ stepResult = agentResult;
506
+ if (agentResult.status === 'ready') {
507
+ agentNextActions = agentResult.nextActions;
508
+ }
437
509
  }
438
510
  if (stepResult.status === 'failed' || stepResult.status === 'missing-input') {
439
511
  return 1;
@@ -455,10 +527,6 @@ async function runKtxSetupInner(args, io, deps = {}) {
455
527
  }
456
528
  if (step === 'context' && stepResult.status !== 'ready') {
457
529
  if (shouldRunAgents && args.skipAgents !== true) {
458
- if (agentsRequested) {
459
- writeContextNotReadyForAgents(projectResult.projectDir, io);
460
- return args.inputMode === 'disabled' ? 1 : 0;
461
- }
462
530
  return 0;
463
531
  }
464
532
  }
@@ -468,18 +536,25 @@ async function runKtxSetupInner(args, io, deps = {}) {
468
536
  break;
469
537
  }
470
538
  await commitSetupConfigChanges(projectResult.projectDir);
471
- const status = await readKtxSetupStatus(projectResult.projectDir);
539
+ const status = await readKtxSetupStatus(projectResult.projectDir, { cliVersion: args.cliVersion });
472
540
  const focusedOnAgents = args.agents || entryAction === 'agents';
473
541
  if (!focusedOnAgents) {
474
- setupUi.note(formatKtxSetupStatus(status).trimEnd(), 'Project status', io, {
475
- format: (line) => line,
476
- });
477
- setupUi.note(formatSetupNextStepLines({
478
- setupReady: setupStatusReady(status),
479
- hasContextTargets: setupHasContextTargets(status),
480
- contextReady: setupContextReady(status),
481
- agentIntegrationReady: status.agents.some((agent) => agent.ready),
482
- }).join('\n'), 'What you can do next', io);
542
+ if (shouldPrintConciseReadySummary(status)) {
543
+ setupUi.note(formatKtxSetupCompletionSummary(status, { agentNextActions }), agentNextActions ? 'Finish KTX agent setup' : 'KTX project ready', io, {
544
+ format: (line) => line,
545
+ });
546
+ }
547
+ else {
548
+ setupUi.note(formatKtxSetupStatus(status).trimEnd(), 'Project status', io, {
549
+ format: (line) => line,
550
+ });
551
+ setupUi.note(formatSetupNextStepLines({
552
+ setupReady: setupStatusReady(status),
553
+ hasContextTargets: setupHasContextTargets(status),
554
+ contextReady: setupContextReady(status),
555
+ agentIntegrationReady: status.agents.some((agent) => agent.ready),
556
+ }).join('\n'), 'What you can do next', io);
557
+ }
483
558
  }
484
559
  return 0;
485
560
  }