@cortexkit/aft-opencode 0.27.1 → 0.28.1

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.
@@ -262,6 +262,15 @@ const SidebarContent = (props: {
262
262
 
263
263
  const s = createMemo(() => status());
264
264
 
265
+ // Lazy-bridge: while AFT has no live bridge yet, the RPC server returns a
266
+ // synthetic snapshot with `cache_role === "not_initialized"`. In that state
267
+ // every metric is unknown by design — not "disabled" — so we hide the
268
+ // version line and the entire Search Index / Semantic Index / Compression
269
+ // grid until a first tool call warms the bridge. Users were reading the
270
+ // pre-init `vunknown` + `Status: unknown` rows as broken state instead of
271
+ // "AFT has not been used yet for this project".
272
+ const notInitialized = () => s()?.cache_role === "not_initialized";
273
+
265
274
  // Pre-compute display values so the JSX stays readable. createMemo for
266
275
  // each derived field would be overkill — these are cheap derivations.
267
276
  const searchStatus = () => statusDisplay(s()?.search_index?.status ?? "disabled");
@@ -324,7 +333,9 @@ const SidebarContent = (props: {
324
333
  </box>
325
334
  )}
326
335
  </box>
327
- <text fg={props.theme.textMuted}>v{s()?.version ?? props.pluginVersion}</text>
336
+ {!notInitialized() && (
337
+ <text fg={props.theme.textMuted}>v{s()?.version ?? props.pluginVersion}</text>
338
+ )}
328
339
  </box>
329
340
 
330
341
  {/* Degraded reason — explains why heavy tools (aft_search, aft_navigate)
@@ -343,90 +354,105 @@ const SidebarContent = (props: {
343
354
  until the first tool call routes through `callBridge()` and warms
344
355
  the bridge. Show the explanatory message instead of empty status
345
356
  rows so users understand why metrics are blank. */}
346
- {s()?.cache_role === "not_initialized" && (
357
+ {notInitialized() && (
347
358
  <box marginTop={1} width="100%">
348
359
  <text fg={props.theme.textMuted}>
349
- {s()!.message || "Waiting for first tool call to populate"}
360
+ {s()!.message ||
361
+ "AFT bridge is now spawned lazily, information here will be populated after first tool call."}
350
362
  </text>
351
363
  </box>
352
364
  )}
353
365
 
354
366
  {/* Search index */}
355
- <SectionHeader theme={props.theme} title="Search Index" />
356
- <StatRow
357
- theme={props.theme}
358
- label="Status"
359
- value={searchStatus().label}
360
- tone={searchStatus().tone}
361
- />
362
- {(s()?.search_index?.files ?? null) != null && (
363
- <StatRow
364
- theme={props.theme}
365
- label="Files"
366
- value={formatCount(s()!.search_index.files)}
367
- tone="muted"
368
- />
369
- )}
370
- <StatRow theme={props.theme} label="Disk" value={formatBytes(trigramBytes())} tone="muted" />
371
-
372
- {/* Semantic index */}
373
- <SectionHeader theme={props.theme} title="Semantic Index" />
374
- <StatRow
375
- theme={props.theme}
376
- label="Status"
377
- value={semanticStatus().label}
378
- tone={semanticStatus().tone}
379
- />
380
- {/* When loading, magic-context-style progress hint helps users see
367
+ {!notInitialized() && (
368
+ <>
369
+ <SectionHeader theme={props.theme} title="Search Index" />
370
+ <StatRow
371
+ theme={props.theme}
372
+ label="Status"
373
+ value={searchStatus().label}
374
+ tone={searchStatus().tone}
375
+ />
376
+ {(s()?.search_index?.files ?? null) != null && (
377
+ <StatRow
378
+ theme={props.theme}
379
+ label="Files"
380
+ value={formatCount(s()!.search_index.files)}
381
+ tone="muted"
382
+ />
383
+ )}
384
+ <StatRow
385
+ theme={props.theme}
386
+ label="Disk"
387
+ value={formatBytes(trigramBytes())}
388
+ tone="muted"
389
+ />
390
+
391
+ {/* Semantic index */}
392
+ <SectionHeader theme={props.theme} title="Semantic Index" />
393
+ <StatRow
394
+ theme={props.theme}
395
+ label="Status"
396
+ value={semanticStatus().label}
397
+ tone={semanticStatus().tone}
398
+ />
399
+ {/* When loading, magic-context-style progress hint helps users see
381
400
  background work is making progress instead of stuck. */}
382
- {s()?.semantic_index?.status === "loading" &&
383
- s()?.semantic_index?.entries_total != null &&
384
- s()!.semantic_index.entries_total! > 0 && (
401
+ {s()?.semantic_index?.status === "loading" &&
402
+ s()?.semantic_index?.entries_total != null &&
403
+ s()!.semantic_index.entries_total! > 0 && (
404
+ <StatRow
405
+ theme={props.theme}
406
+ label="Progress"
407
+ value={`${formatCount(s()!.semantic_index.entries_done)} / ${formatCount(
408
+ s()!.semantic_index.entries_total,
409
+ )}`}
410
+ tone="warn"
411
+ />
412
+ )}
413
+ {(s()?.semantic_index?.entries ?? null) != null && (
414
+ <StatRow
415
+ theme={props.theme}
416
+ label="Entries"
417
+ value={formatCount(s()!.semantic_index.entries)}
418
+ tone="muted"
419
+ />
420
+ )}
385
421
  <StatRow
386
422
  theme={props.theme}
387
- label="Progress"
388
- value={`${formatCount(s()!.semantic_index.entries_done)} / ${formatCount(
389
- s()!.semantic_index.entries_total,
390
- )}`}
391
- tone="warn"
423
+ label="Disk"
424
+ value={formatBytes(semanticBytes())}
425
+ tone="muted"
392
426
  />
393
- )}
394
- {(s()?.semantic_index?.entries ?? null) != null && (
395
- <StatRow
396
- theme={props.theme}
397
- label="Entries"
398
- value={formatCount(s()!.semantic_index.entries)}
399
- tone="muted"
400
- />
401
- )}
402
- <StatRow theme={props.theme} label="Disk" value={formatBytes(semanticBytes())} tone="muted" />
403
427
 
404
- {/* Compression aggregates. Tabular layout matching Search/Semantic
428
+ {/* Compression aggregates. Tabular layout matching Search/Semantic
405
429
  Index above: each scope ("Session", "Project") renders as a
406
430
  subheader followed by two StatRows (Tokens Saved, Compression
407
431
  Ratio). Keeps numbers right-aligned in the value column instead
408
432
  of jamming them after the label on the same line. */}
409
- {compressionRows().length > 0 && (
410
- <>
411
- <SectionHeader theme={props.theme} title="Compression" />
412
- {compressionRows().map((row) =>
413
- row.kind === "scope" ? (
414
- <box width="100%">
415
- <text fg={props.theme.text}>{row.label}</text>
416
- </box>
417
- ) : (
418
- <StatRow theme={props.theme} label={row.label} value={row.value} tone="muted" />
419
- ),
433
+ {compressionRows().length > 0 && (
434
+ <>
435
+ <SectionHeader theme={props.theme} title="Compression" />
436
+ {compressionRows().map((row) =>
437
+ row.kind === "scope" ? (
438
+ <box width="100%">
439
+ <text fg={props.theme.text}>{row.label}</text>
440
+ </box>
441
+ ) : (
442
+ <StatRow theme={props.theme} label={row.label} value={row.value} tone="muted" />
443
+ ),
444
+ )}
445
+ </>
420
446
  )}
421
- </>
422
- )}
423
447
 
424
- {/* Surface failures clearly so users know to act (install ONNX,
448
+ {/* Surface failures clearly so users know to act (install ONNX,
425
449
  fix config, etc.) rather than silently leaving the panel "off". */}
426
- {s()?.semantic_index?.status === "failed" && s()?.semantic_index?.error && (
427
- <box marginTop={1} width="100%">
428
- <text fg={props.theme.error}>⚠ {s()!.semantic_index.error}</text>
429
- </box>
450
+ {s()?.semantic_index?.status === "failed" && s()?.semantic_index?.error && (
451
+ <box marginTop={1} width="100%">
452
+ <text fg={props.theme.error}>⚠ {s()!.semantic_index.error}</text>
453
+ </box>
454
+ )}
455
+ </>
430
456
  )}
431
457
  </box>
432
458
  );