@kaelio/ktx 0.6.0 → 0.7.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.
@@ -28,6 +28,21 @@ const STRUCTURED_OUTPUT_TOOL_NAME = 'StructuredOutput';
28
28
  function isResult(message) {
29
29
  return message.type === 'result';
30
30
  }
31
+ // Skip emissions the SDK does not count toward `num_turns`: `pause_turn` continuations and
32
+ // errored partials (e.g. `max_output_tokens`) it retries internally. Without this, the
33
+ // runtime's step counter outruns `maxTurns` and the HUD renders e.g. `step 69/40`.
34
+ function countsAsAssistantTurn(message) {
35
+ if (message.type !== 'assistant' || message.parent_tool_use_id !== null) {
36
+ return false;
37
+ }
38
+ if (message.error !== undefined) {
39
+ return false;
40
+ }
41
+ if (message.message.stop_reason === 'pause_turn') {
42
+ return false;
43
+ }
44
+ return true;
45
+ }
31
46
  function resultError(result) {
32
47
  if (result.subtype === 'success') {
33
48
  return undefined;
@@ -124,7 +139,7 @@ async function collectResult(params) {
124
139
  let result;
125
140
  for await (const message of params.query({ prompt: params.prompt, options: params.options })) {
126
141
  assertInitIsolation(message, params.allowedToolIds, params.expectedMcpServerNames);
127
- if (message.type === 'assistant' && message.parent_tool_use_id === null) {
142
+ if (countsAsAssistantTurn(message)) {
128
143
  await params.onAssistantTurn?.();
129
144
  }
130
145
  if (isResult(message)) {
@@ -10,19 +10,11 @@ export interface KtxSetupProjectArgs {
10
10
  yes: boolean;
11
11
  allowBack?: boolean;
12
12
  }
13
- export type KtxSetupCreatedProjectCleanup = {
14
- kind: 'remove-project-dir';
15
- projectDir: string;
16
- } | {
17
- kind: 'remove-ktx-scaffold';
18
- projectDir: string;
19
- };
20
13
  export type KtxSetupProjectResult = {
21
14
  status: 'ready';
22
15
  projectDir: string;
23
16
  project: KtxLocalProject;
24
17
  confirmedCreation?: boolean;
25
- createdProjectCleanup?: KtxSetupCreatedProjectCleanup;
26
18
  } | {
27
19
  status: 'back';
28
20
  projectDir: string;
@@ -39,15 +39,6 @@ async function existingFolderState(projectDir) {
39
39
  throw error;
40
40
  }
41
41
  }
42
- function cleanupForFolderState(projectDir, state) {
43
- if (state === 'missing') {
44
- return { kind: 'remove-project-dir', projectDir };
45
- }
46
- if (state === 'empty-directory') {
47
- return { kind: 'remove-ktx-scaffold', projectDir };
48
- }
49
- return undefined;
50
- }
51
42
  async function confirmProjectDir(selectedDir, io, prompts) {
52
43
  const state = await existingFolderState(selectedDir);
53
44
  if (state === 'not-directory') {
@@ -86,7 +77,7 @@ async function confirmProjectDir(selectedDir, io, prompts) {
86
77
  return { status: 'back' };
87
78
  if (action !== 'create')
88
79
  return { status: 'cancelled' };
89
- return { status: 'confirmed', confirmedCreation: true, createdProjectCleanup: cleanupForFolderState(selectedDir, state) };
80
+ return { status: 'confirmed', confirmedCreation: true };
90
81
  }
91
82
  async function normalizeSetupGitignore(projectDir) {
92
83
  const gitignorePath = join(projectDir, '.ktx/.gitignore');
@@ -162,19 +153,9 @@ async function promptForNewProjectDir(projectDir, homeDir, io, prompts) {
162
153
  status: 'selected',
163
154
  projectDir: selectedDir,
164
155
  confirmedCreation: confirmed.confirmedCreation,
165
- ...(confirmed.createdProjectCleanup ? { createdProjectCleanup: confirmed.createdProjectCleanup } : {}),
166
156
  };
167
157
  }
168
158
  }
169
- async function createProjectWithCleanup(projectDir, deps) {
170
- const state = await existingFolderState(projectDir);
171
- const project = await createProject(projectDir, deps);
172
- const createdProjectCleanup = cleanupForFolderState(projectDir, state);
173
- return {
174
- project,
175
- ...(createdProjectCleanup ? { createdProjectCleanup } : {}),
176
- };
177
- }
178
159
  export async function runKtxSetupProjectStep(args, io, deps = {}) {
179
160
  const projectDir = resolve(args.projectDir);
180
161
  const homeDir = deps.homeDir ?? homedir();
@@ -203,7 +184,6 @@ export async function runKtxSetupProjectStep(args, io, deps = {}) {
203
184
  projectDir: selected.projectDir,
204
185
  project,
205
186
  confirmedCreation: selected.confirmedCreation,
206
- ...(selected.createdProjectCleanup ? { createdProjectCleanup: selected.createdProjectCleanup } : {}),
207
187
  };
208
188
  }
209
189
  if (exists) {
@@ -216,13 +196,12 @@ export async function runKtxSetupProjectStep(args, io, deps = {}) {
216
196
  io.stderr.write('Missing setup choice: pass --yes to create a project in non-interactive setup.\n');
217
197
  return { status: 'missing-input', projectDir };
218
198
  }
219
- const { project, createdProjectCleanup } = await createProjectWithCleanup(projectDir, deps);
199
+ const project = await createProject(projectDir, deps);
220
200
  printProjectSummary(io, projectDir);
221
201
  return {
222
202
  status: 'ready',
223
203
  projectDir,
224
204
  project,
225
- ...(createdProjectCleanup ? { createdProjectCleanup } : {}),
226
205
  };
227
206
  }
228
207
  if (!io.stdout.isTTY && !deps.prompts) {
@@ -255,13 +234,12 @@ export async function runKtxSetupProjectStep(args, io, deps = {}) {
255
234
  return { status: 'cancelled', projectDir };
256
235
  }
257
236
  if (choice === 'current') {
258
- const { project, createdProjectCleanup } = await createProjectWithCleanup(projectDir, deps);
237
+ const project = await createProject(projectDir, deps);
259
238
  printProjectSummary(io, projectDir);
260
239
  return {
261
240
  status: 'ready',
262
241
  projectDir,
263
242
  project,
264
- ...(createdProjectCleanup ? { createdProjectCleanup } : {}),
265
243
  };
266
244
  }
267
245
  if (choice === 'new-default') {
@@ -279,7 +257,6 @@ export async function runKtxSetupProjectStep(args, io, deps = {}) {
279
257
  projectDir: defaultProjectDir,
280
258
  project,
281
259
  confirmedCreation: confirmed.confirmedCreation,
282
- ...(confirmed.createdProjectCleanup ? { createdProjectCleanup: confirmed.createdProjectCleanup } : {}),
283
260
  };
284
261
  }
285
262
  if (choice === 'new-custom') {
@@ -309,7 +286,6 @@ export async function runKtxSetupProjectStep(args, io, deps = {}) {
309
286
  projectDir: customDir,
310
287
  project,
311
288
  confirmedCreation: confirmed.confirmedCreation,
312
- ...(confirmed.createdProjectCleanup ? { createdProjectCleanup: confirmed.createdProjectCleanup } : {}),
313
289
  };
314
290
  }
315
291
  prompts.cancel('Setup cancelled.');
package/dist/setup.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { existsSync } from 'node:fs';
2
- import { rm } from 'node:fs/promises';
3
2
  import { basename, join, resolve } from 'node:path';
4
3
  import { getLatestLocalIngestStatus } from './context/ingest/local-ingest.js';
5
4
  import { savedMemoryCountsForReport } from './context/ingest/reports.js';
@@ -16,7 +15,7 @@ import { readKtxAgentInstallManifest, runKtxSetupAgentsStep, targetDisplayName,
16
15
  import { runKtxSetupDatabasesStep, } from './setup-databases.js';
17
16
  import { runKtxSetupEmbeddingsStep } from './setup-embeddings.js';
18
17
  import { isKtxSetupLlmConfigReady, runKtxSetupAnthropicModelStep, } from './setup-models.js';
19
- import { runKtxSetupProjectStep, } from './setup-project.js';
18
+ import { runKtxSetupProjectStep } from './setup-project.js';
20
19
  import { isKtxPreAgentSetupReady, isKtxSetupReady, runKtxSetupReadyChangeMenu, } from './setup-ready-menu.js';
21
20
  import { runKtxSetupSourcesStep } from './setup-sources.js';
22
21
  import { runKtxSetupRuntimeStep, } from './setup-runtime.js';
@@ -306,17 +305,6 @@ async function commitSetupConfigChanges(projectDir) {
306
305
  const project = await loadKtxProject({ projectDir });
307
306
  await project.git.commitFile('ktx.yaml', 'setup: update KTX project config', 'ktx setup', 'setup@ktx.local');
308
307
  }
309
- const KTX_SETUP_SCAFFOLD_PATHS = ['ktx.yaml', '.ktx', 'wiki', 'semantic-layer', 'raw-sources', '.git'];
310
- async function cleanupCreatedProjectScaffold(cleanup) {
311
- if (!cleanup) {
312
- return;
313
- }
314
- if (cleanup.kind === 'remove-project-dir') {
315
- await rm(cleanup.projectDir, { recursive: true, force: true });
316
- return;
317
- }
318
- await Promise.all(KTX_SETUP_SCAFFOLD_PATHS.map((relativePath) => rm(join(cleanup.projectDir, relativePath), { recursive: true, force: true })));
319
- }
320
308
  export async function runKtxSetup(args, io, deps = {}) {
321
309
  try {
322
310
  return await runKtxSetupInner(args, io, deps);
@@ -579,7 +567,6 @@ async function runKtxSetupInner(args, io, deps = {}) {
579
567
  cliVersion: args.cliVersion,
580
568
  });
581
569
  if (stepResult.status === 'failed') {
582
- await cleanupCreatedProjectScaffold(projectResult.createdProjectCleanup);
583
570
  return 1;
584
571
  }
585
572
  if (stepResult.status === 'missing-input') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaelio/ktx",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Standalone ktx context layer for data agents",
5
5
  "type": "module",
6
6
  "engines": {