@cortexkit/aft-opencode 0.26.4 → 0.27.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.
@@ -19,7 +19,7 @@
19
19
  * installed, log a warning and keep the existing version.
20
20
  * Otherwise skip + warn.
21
21
  *
22
- * 3. Spawn `bun add <pkg>@<version> --cwd <cache_dir> --ignore-scripts`
22
+ * 3. Spawn `npm install --no-save <pkg>@<version> --ignore-scripts`
23
23
  * in the background. Drop a lockfile while running. Log progress.
24
24
  *
25
25
  * 4. The newly-installed binary will be picked up on the user's NEXT
@@ -1 +1 @@
1
- {"version":3,"file":"lsp-auto-install.d.ts","sourceRoot":"","sources":["../src/lsp-auto-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAwBH,+DAA+D;AAC/D,MAAM,WAAW,iBAAiB;IAChC,oCAAoC;IACpC,WAAW,EAAE,OAAO,CAAC;IACrB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,kGAAkG;IAClG,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED,qCAAqC;AACrC,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gDAAgD;IAChD,eAAe,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B;;;;;;;OAOG;IACH,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C;;;;;;;;;OASG;IACH,gBAAgB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAkDD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAM/D;AA0WD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,iBAAiB,EACzB,SAAS,GAAE,OAAO,KAAa,GAC9B,iBAAiB,CAwEnB"}
1
+ {"version":3,"file":"lsp-auto-install.d.ts","sourceRoot":"","sources":["../src/lsp-auto-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAwBH,+DAA+D;AAC/D,MAAM,WAAW,iBAAiB;IAChC,oCAAoC;IACpC,WAAW,EAAE,OAAO,CAAC;IACrB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,kGAAkG;IAClG,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED,qCAAqC;AACrC,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gDAAgD;IAChD,eAAe,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B;;;;;;;OAOG;IACH,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C;;;;;;;;;OASG;IACH,gBAAgB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAkDD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAM/D;AAqXD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,iBAAiB,EACzB,SAAS,GAAE,OAAO,KAAa,GAC9B,iBAAiB,CAwEnB"}
@@ -13,6 +13,7 @@
13
13
  * Messages are identified by markers and cleaned up on subsequent startups
14
14
  * when no longer relevant (Desktop only — TUI toasts are inherently transient).
15
15
  */
16
+ import type { BinaryBridge } from "@cortexkit/aft-bridge";
16
17
  type SdkMessage = {
17
18
  info?: {
18
19
  id?: string;
@@ -50,6 +51,7 @@ export interface ConfigureWarning {
50
51
  export interface ConfigureWarningOptions {
51
52
  client: unknown;
52
53
  sessionId: string;
54
+ bridge: Pick<BinaryBridge, "send">;
53
55
  storageDir: string;
54
56
  pluginVersion: string;
55
57
  projectRoot?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAyIH,KAAK,UAAU,GAAG;IAChB,IAAI,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACpE,CAAC;AAyBF,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,EAAE,CAAC,CAqBvB;AAqED,MAAM,WAAW,mBAAmB;IAClC,8BAA8B;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,yBAAyB,GAAG,uBAAuB,GAAG,oBAAoB,CAAC;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW3F;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C1F;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAAE,EAClB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAqCf;AA8FD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,uBAAuB,EAC7B,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C9E"}
1
+ {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAmI1D,KAAK,UAAU,GAAG;IAChB,IAAI,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACpE,CAAC;AAyBF,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,EAAE,CAAC,CAqBvB;AAqED,MAAM,WAAW,mBAAmB;IAClC,8BAA8B;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,yBAAyB,GAAG,uBAAuB,GAAG,oBAAoB,CAAC;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW3F;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C1F;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAAE,EAClB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CA2Cf;AA4ED,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,uBAAuB,EAC7B,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C9E"}
@@ -1,3 +1,13 @@
1
+ export interface StatusCompressionAggregate {
2
+ events: number;
3
+ original_tokens: number;
4
+ compressed_tokens: number;
5
+ savings_tokens: number;
6
+ }
7
+ export interface StatusCompression {
8
+ project: StatusCompressionAggregate;
9
+ session: StatusCompressionAggregate;
10
+ }
1
11
  export interface AftStatusSnapshot {
2
12
  version: string;
3
13
  project_root: string | null;
@@ -57,6 +67,8 @@ export interface AftStatusSnapshot {
57
67
  tracked_files: number;
58
68
  checkpoints: number;
59
69
  };
70
+ /** Compression aggregate passthrough; rendering is added separately. */
71
+ compression?: StatusCompression;
60
72
  /**
61
73
  * Human-readable explanation for a synthetic snapshot (e.g.
62
74
  * `cache_role === "not_initialized"`). When the plugin returns a placeholder
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/shared/status.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;OAOG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,+EAA+E;IAC/E,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE;QACR,cAAc,EAAE,OAAO,CAAC;QACxB,gBAAgB,EAAE,MAAM,CAAC;QACzB,wBAAwB,EAAE,OAAO,CAAC;QAClC,YAAY,EAAE,OAAO,CAAC;QACtB,eAAe,EAAE,OAAO,CAAC;KAC1B,CAAC;IACF,YAAY,EAAE;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,CAAC;IACF,cAAc,EAAE;QACd,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACvB,CAAC;IACF,IAAI,EAAE;QACJ,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,mBAAmB,EAAE,MAAM,CAAC;KAC7B,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE;QACZ,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iEAAiE;IACjE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,4DAA4D;IAC5D,OAAO,EAAE;QACP,EAAE,EAAE,MAAM,CAAC;QACX,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF;;;;;;OAMG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAkCD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAajD;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,iBAAiB,CAkEpF;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAuE3E;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CA0EtE"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/shared/status.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,0BAA0B,CAAC;IACpC,OAAO,EAAE,0BAA0B,CAAC;CACrC;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;;OAOG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,+EAA+E;IAC/E,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE;QACR,cAAc,EAAE,OAAO,CAAC;QACxB,gBAAgB,EAAE,MAAM,CAAC;QACzB,wBAAwB,EAAE,OAAO,CAAC;QAClC,YAAY,EAAE,OAAO,CAAC;QACtB,eAAe,EAAE,OAAO,CAAC;KAC1B,CAAC;IACF,YAAY,EAAE;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,CAAC;IACF,cAAc,EAAE;QACd,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACvB,CAAC;IACF,IAAI,EAAE;QACJ,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,mBAAmB,EAAE,MAAM,CAAC;KAC7B,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE;QACZ,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iEAAiE;IACjE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,4DAA4D;IAC5D,OAAO,EAAE;QACP,EAAE,EAAE,MAAM,CAAC;QACX,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,wEAAwE;IACxE,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC;;;;;;OAMG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAqDD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAajD;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,iBAAiB,CAmEpF;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAuE3E;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CA0EtE"}
@@ -1 +1 @@
1
- {"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAuEjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AAqRtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CA+JjE;AA8kCD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAwB/E;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAgGnF"}
1
+ {"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAuEjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AAqRtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CA+JjE;AAmmCD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAwB/E;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAgGnF"}
package/dist/tui.js CHANGED
@@ -4,7 +4,7 @@ import { createMemo as createMemo2, createSignal as createSignal2, onCleanup as
4
4
  // package.json
5
5
  var package_default = {
6
6
  name: "@cortexkit/aft-opencode",
7
- version: "0.26.4",
7
+ version: "0.27.1",
8
8
  type: "module",
9
9
  description: "OpenCode plugin for Agent File Tools (AFT) \u2014 tree-sitter and lsp powered code analysis",
10
10
  main: "dist/index.js",
@@ -28,11 +28,12 @@ var package_default = {
28
28
  test: "bun test",
29
29
  "test:e2e": "bun test src/__tests__/e2e/",
30
30
  lint: "biome check src",
31
+ schema: "bun scripts/build-schema.ts",
31
32
  prepublishOnly: "bun run build"
32
33
  },
33
34
  dependencies: {
34
35
  "@clack/prompts": "^1.2.0",
35
- "@cortexkit/aft-bridge": "0.26.4",
36
+ "@cortexkit/aft-bridge": "0.27.1",
36
37
  "@opencode-ai/plugin": "^1.15.5",
37
38
  "@opencode-ai/sdk": "^1.15.5",
38
39
  "comment-json": "^4.6.2",
@@ -40,11 +41,11 @@ var package_default = {
40
41
  zod: "^4.1.8"
41
42
  },
42
43
  optionalDependencies: {
43
- "@cortexkit/aft-darwin-arm64": "0.26.4",
44
- "@cortexkit/aft-darwin-x64": "0.26.4",
45
- "@cortexkit/aft-linux-arm64": "0.26.4",
46
- "@cortexkit/aft-linux-x64": "0.26.4",
47
- "@cortexkit/aft-win32-x64": "0.26.4"
44
+ "@cortexkit/aft-darwin-arm64": "0.27.1",
45
+ "@cortexkit/aft-darwin-x64": "0.27.1",
46
+ "@cortexkit/aft-linux-arm64": "0.27.1",
47
+ "@cortexkit/aft-linux-x64": "0.27.1",
48
+ "@cortexkit/aft-win32-x64": "0.27.1"
48
49
  },
49
50
  devDependencies: {
50
51
  "@types/node": "^22.0.0",
@@ -304,6 +305,24 @@ function readNumber(value, fallback = 0) {
304
305
  function readOptionalNumber(value) {
305
306
  return typeof value === "number" && Number.isFinite(value) ? value : null;
306
307
  }
308
+ function readCompressionAggregate(value) {
309
+ const aggregate = asRecord(value);
310
+ return {
311
+ events: readNumber(aggregate.events),
312
+ original_tokens: readNumber(aggregate.original_tokens),
313
+ compressed_tokens: readNumber(aggregate.compressed_tokens),
314
+ savings_tokens: readNumber(aggregate.savings_tokens)
315
+ };
316
+ }
317
+ function readCompression(value) {
318
+ if (typeof value !== "object" || value === null)
319
+ return;
320
+ const compression = asRecord(value);
321
+ return {
322
+ project: readCompressionAggregate(compression.project),
323
+ session: readCompressionAggregate(compression.session)
324
+ };
325
+ }
307
326
  function formatBytes(bytes) {
308
327
  if (!Number.isFinite(bytes) || bytes <= 0)
309
328
  return "0 B";
@@ -376,13 +395,14 @@ function coerceAftStatus(response) {
376
395
  tracked_files: readNumber(session.tracked_files),
377
396
  checkpoints: readNumber(session.checkpoints)
378
397
  },
398
+ compression: readCompression(response.compression),
379
399
  message: readString(response.message, "")
380
400
  };
381
401
  }
382
402
 
383
403
  // src/tui/sidebar.tsx
384
404
  import { createEffect, createMemo, createSignal, on, onCleanup } from "solid-js";
385
- import { jsxDEV } from "@opentui/solid/jsx-dev-runtime";
405
+ import { jsxDEV, Fragment } from "@opentui/solid/jsx-dev-runtime";
386
406
  var SINGLE_BORDER = { type: "single" };
387
407
  var REFRESH_DEBOUNCE_MS = 200;
388
408
  var POLL_INTERVAL_MS = 1500;
@@ -406,6 +426,23 @@ function formatCount(n) {
406
426
  return `${Math.round(n / 1000)}K`;
407
427
  return String(n);
408
428
  }
429
+ function appendScope(rows, label, scope) {
430
+ const savings = scope.savings_tokens;
431
+ const pct = scope.original_tokens > 0 ? Math.round(savings / scope.original_tokens * 100) : 0;
432
+ rows.push({ kind: "scope", label });
433
+ rows.push({ kind: "stat", label: "Tokens Saved", value: savings.toLocaleString("en-US") });
434
+ rows.push({ kind: "stat", label: "Compression Ratio", value: `${pct}%` });
435
+ }
436
+ function formatCompressionSidebarRows(compression) {
437
+ if (!compression || compression.project.events <= 0)
438
+ return [];
439
+ const rows = [];
440
+ if (compression.session.events > 0) {
441
+ appendScope(rows, "Session", compression.session);
442
+ }
443
+ appendScope(rows, "Project", compression.project);
444
+ return rows;
445
+ }
409
446
  function statusDisplay(status) {
410
447
  switch (status) {
411
448
  case "ready":
@@ -474,7 +511,7 @@ function getClient(directory) {
474
511
  return client;
475
512
  const home = process.env.HOME || process.env.USERPROFILE || "";
476
513
  const dataHome = process.env.XDG_DATA_HOME || `${home}/.local/share`;
477
- const storageDir = `${dataHome}/opencode/storage/plugin/aft`;
514
+ const storageDir = `${dataHome}/cortexkit/aft`;
478
515
  client = new AftRpcClient(storageDir, directory);
479
516
  sidebarClients.set(directory, client);
480
517
  return client;
@@ -562,6 +599,7 @@ var SidebarContent = (props) => {
562
599
  const semanticStatus = () => statusDisplay(s()?.semantic_index?.status ?? "disabled");
563
600
  const trigramBytes = () => s()?.disk?.trigram_disk_bytes ?? 0;
564
601
  const semanticBytes = () => s()?.disk?.semantic_disk_bytes ?? 0;
602
+ const compressionRows = () => formatCompressionSidebarRows(s()?.compression);
565
603
  const degradedReasonLabel = (reason) => {
566
604
  if (reason === "home_root") {
567
605
  return "project root is your home directory";
@@ -703,6 +741,26 @@ var SidebarContent = (props) => {
703
741
  value: formatBytes2(semanticBytes()),
704
742
  tone: "muted"
705
743
  }, undefined, false, undefined, this),
744
+ compressionRows().length > 0 && /* @__PURE__ */ jsxDEV(Fragment, {
745
+ children: [
746
+ /* @__PURE__ */ jsxDEV(SectionHeader, {
747
+ theme: props.theme,
748
+ title: "Compression"
749
+ }, undefined, false, undefined, this),
750
+ compressionRows().map((row) => row.kind === "scope" ? /* @__PURE__ */ jsxDEV("box", {
751
+ width: "100%",
752
+ children: /* @__PURE__ */ jsxDEV("text", {
753
+ fg: props.theme.text,
754
+ children: row.label
755
+ }, undefined, false, undefined, this)
756
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV(StatRow, {
757
+ theme: props.theme,
758
+ label: row.label,
759
+ value: row.value,
760
+ tone: "muted"
761
+ }, undefined, false, undefined, this))
762
+ ]
763
+ }, undefined, true, undefined, this),
706
764
  s()?.semantic_index?.status === "failed" && s()?.semantic_index?.error && /* @__PURE__ */ jsxDEV("box", {
707
765
  marginTop: 1,
708
766
  width: "100%",
@@ -744,7 +802,7 @@ function getRpcClient(directory) {
744
802
  return client;
745
803
  const home = process.env.HOME || process.env.USERPROFILE || "";
746
804
  const dataHome = process.env.XDG_DATA_HOME || `${home}/.local/share`;
747
- const storageDir = `${dataHome}/opencode/storage/plugin/aft`;
805
+ const storageDir = `${dataHome}/cortexkit/aft`;
748
806
  client = new AftRpcClient(storageDir, directory);
749
807
  rpcClients.set(directory, client);
750
808
  return client;
@@ -834,6 +892,7 @@ var StatusDialog = (props) => {
834
892
  }, POLL_INTERVAL_MS2);
835
893
  onCleanup2(() => clearInterval(timer));
836
894
  const cacheRoleTone = (role) => role === "main" ? "accent" : role === "worktree" ? "warn" : "muted";
895
+ const compressionAggregateRows = () => formatCompressionSidebarRows(status()?.compression);
837
896
  return /* @__PURE__ */ jsxDEV2("box", {
838
897
  flexDirection: "column",
839
898
  width: "100%",
@@ -1110,6 +1169,31 @@ var StatusDialog = (props) => {
1110
1169
  ]
1111
1170
  }, undefined, true, undefined, this)
1112
1171
  }, undefined, false, undefined, this) : null,
1172
+ compressionAggregateRows().length > 0 ? /* @__PURE__ */ jsxDEV2("box", {
1173
+ flexDirection: "column",
1174
+ width: "100%",
1175
+ marginTop: 1,
1176
+ children: [
1177
+ /* @__PURE__ */ jsxDEV2("text", {
1178
+ fg: t().text,
1179
+ children: /* @__PURE__ */ jsxDEV2("b", {
1180
+ children: "Compression"
1181
+ }, undefined, false, undefined, this)
1182
+ }, undefined, false, undefined, this),
1183
+ compressionAggregateRows().map((row) => row.kind === "scope" ? /* @__PURE__ */ jsxDEV2("box", {
1184
+ width: "100%",
1185
+ children: /* @__PURE__ */ jsxDEV2("text", {
1186
+ fg: t().text,
1187
+ children: row.label
1188
+ }, undefined, false, undefined, this)
1189
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV2(R, {
1190
+ theme: t(),
1191
+ label: row.label,
1192
+ value: row.value,
1193
+ tone: "muted"
1194
+ }, undefined, false, undefined, this))
1195
+ ]
1196
+ }, undefined, true, undefined, this) : null,
1113
1197
  /* @__PURE__ */ jsxDEV2("box", {
1114
1198
  marginTop: 1,
1115
1199
  justifyContent: "flex-end",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft-opencode",
3
- "version": "0.26.4",
3
+ "version": "0.27.1",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Agent File Tools (AFT) — tree-sitter and lsp powered code analysis",
6
6
  "main": "dist/index.js",
@@ -24,11 +24,12 @@
24
24
  "test": "bun test",
25
25
  "test:e2e": "bun test src/__tests__/e2e/",
26
26
  "lint": "biome check src",
27
+ "schema": "bun scripts/build-schema.ts",
27
28
  "prepublishOnly": "bun run build"
28
29
  },
29
30
  "dependencies": {
30
31
  "@clack/prompts": "^1.2.0",
31
- "@cortexkit/aft-bridge": "0.26.4",
32
+ "@cortexkit/aft-bridge": "0.27.1",
32
33
  "@opencode-ai/plugin": "^1.15.5",
33
34
  "@opencode-ai/sdk": "^1.15.5",
34
35
  "comment-json": "^4.6.2",
@@ -36,11 +37,11 @@
36
37
  "zod": "^4.1.8"
37
38
  },
38
39
  "optionalDependencies": {
39
- "@cortexkit/aft-darwin-arm64": "0.26.4",
40
- "@cortexkit/aft-darwin-x64": "0.26.4",
41
- "@cortexkit/aft-linux-arm64": "0.26.4",
42
- "@cortexkit/aft-linux-x64": "0.26.4",
43
- "@cortexkit/aft-win32-x64": "0.26.4"
40
+ "@cortexkit/aft-darwin-arm64": "0.27.1",
41
+ "@cortexkit/aft-darwin-x64": "0.27.1",
42
+ "@cortexkit/aft-linux-arm64": "0.27.1",
43
+ "@cortexkit/aft-linux-x64": "0.27.1",
44
+ "@cortexkit/aft-win32-x64": "0.27.1"
44
45
  },
45
46
  "devDependencies": {
46
47
  "@types/node": "^22.0.0",
@@ -1,3 +1,15 @@
1
+ export interface StatusCompressionAggregate {
2
+ events: number;
3
+ original_tokens: number;
4
+ compressed_tokens: number;
5
+ savings_tokens: number;
6
+ }
7
+
8
+ export interface StatusCompression {
9
+ project: StatusCompressionAggregate;
10
+ session: StatusCompressionAggregate;
11
+ }
12
+
1
13
  export interface AftStatusSnapshot {
2
14
  version: string;
3
15
  project_root: string | null;
@@ -57,6 +69,8 @@ export interface AftStatusSnapshot {
57
69
  tracked_files: number;
58
70
  checkpoints: number;
59
71
  };
72
+ /** Compression aggregate passthrough; rendering is added separately. */
73
+ compression?: StatusCompression;
60
74
  /**
61
75
  * Human-readable explanation for a synthetic snapshot (e.g.
62
76
  * `cache_role === "not_initialized"`). When the plugin returns a placeholder
@@ -91,6 +105,25 @@ function readOptionalNumber(value: unknown): number | null {
91
105
  return typeof value === "number" && Number.isFinite(value) ? value : null;
92
106
  }
93
107
 
108
+ function readCompressionAggregate(value: unknown): StatusCompressionAggregate {
109
+ const aggregate = asRecord(value);
110
+ return {
111
+ events: readNumber(aggregate.events),
112
+ original_tokens: readNumber(aggregate.original_tokens),
113
+ compressed_tokens: readNumber(aggregate.compressed_tokens),
114
+ savings_tokens: readNumber(aggregate.savings_tokens),
115
+ };
116
+ }
117
+
118
+ function readCompression(value: unknown): StatusCompression | undefined {
119
+ if (typeof value !== "object" || value === null) return undefined;
120
+ const compression = asRecord(value);
121
+ return {
122
+ project: readCompressionAggregate(compression.project),
123
+ session: readCompressionAggregate(compression.session),
124
+ };
125
+ }
126
+
94
127
  function formatFlag(enabled: boolean): string {
95
128
  return enabled ? "enabled" : "disabled";
96
129
  }
@@ -178,6 +211,7 @@ export function coerceAftStatus(response: Record<string, unknown>): AftStatusSna
178
211
  tracked_files: readNumber(session.tracked_files),
179
212
  checkpoints: readNumber(session.checkpoints),
180
213
  },
214
+ compression: readCompression(response.compression),
181
215
  message: readString(response.message, ""),
182
216
  };
183
217
  }
package/src/tui/index.tsx CHANGED
@@ -3,10 +3,11 @@
3
3
 
4
4
  import type { TuiPlugin, TuiPluginApi, TuiThemeCurrent } from "@opencode-ai/plugin/tui";
5
5
  import { createMemo, createSignal, onCleanup } from "solid-js";
6
+
6
7
  import packageJson from "../../package.json";
7
8
  import { AftRpcClient } from "../shared/rpc-client";
8
9
  import { type AftStatusSnapshot, coerceAftStatus, formatBytes } from "../shared/status";
9
- import { createAftSidebarSlot } from "./sidebar";
10
+ import { createAftSidebarSlot, formatCompressionSidebarRows } from "./sidebar";
10
11
 
11
12
  // The TUI talks to the server plugin via AftRpcClient. The client reads the
12
13
  // JSON port file written by AftRpcServer ({ port, token }) and includes that
@@ -22,9 +23,14 @@ function getRpcClient(directory: string): AftRpcClient {
22
23
  let client = rpcClients.get(directory);
23
24
  if (client) return client;
24
25
 
26
+ // v0.27 moved AFT storage to the CortexKit root. The TUI plugin must use
27
+ // the same path as the server plugin (`resolveCortexKitStorageRoot()`),
28
+ // otherwise it polls stale legacy port files written by older versions
29
+ // and never picks up the live RPC server, leaving the sidebar/dialog
30
+ // stuck on the "AFT is starting up" placeholder forever.
25
31
  const home = process.env.HOME || process.env.USERPROFILE || "";
26
32
  const dataHome = process.env.XDG_DATA_HOME || `${home}/.local/share`;
27
- const storageDir = `${dataHome}/opencode/storage/plugin/aft`;
33
+ const storageDir = `${dataHome}/cortexkit/aft`;
28
34
 
29
35
  client = new AftRpcClient(storageDir, directory);
30
36
  rpcClients.set(directory, client);
@@ -153,6 +159,11 @@ const StatusDialog = (props: StatusDialogProps) => {
153
159
  // not_initialized is muted. Matches the sidebar convention.
154
160
  const cacheRoleTone = (role: string): "accent" | "warn" | "muted" =>
155
161
  role === "main" ? "accent" : role === "worktree" ? "warn" : "muted";
162
+ // Reuse the sidebar's label/value formatter so the dialog and sidebar
163
+ // render identical text (e.g. "Session" / "-174,489 tokens, 59% reduction").
164
+ // The earlier `formatCompressionDialogRows` returned padded strings that
165
+ // looked offset against neighboring sections.
166
+ const compressionAggregateRows = () => formatCompressionSidebarRows(status()?.compression);
156
167
 
157
168
  return (
158
169
  <box
@@ -374,6 +385,28 @@ const StatusDialog = (props: StatusDialogProps) => {
374
385
  </box>
375
386
  ) : null}
376
387
 
388
+ {/* Compression aggregates — tabular layout matching Search/Semantic
389
+ Index. Each scope ("Session", "Project") renders as a subheader
390
+ followed by two <R> rows (Tokens Saved, Compression Ratio) so the
391
+ numbers stay right-aligned under the value column instead of
392
+ crowding the label. */}
393
+ {compressionAggregateRows().length > 0 ? (
394
+ <box flexDirection="column" width="100%" marginTop={1}>
395
+ <text fg={t().text}>
396
+ <b>Compression</b>
397
+ </text>
398
+ {compressionAggregateRows().map((row) =>
399
+ row.kind === "scope" ? (
400
+ <box width="100%">
401
+ <text fg={t().text}>{row.label}</text>
402
+ </box>
403
+ ) : (
404
+ <R theme={t()} label={row.label} value={row.value} tone="muted" />
405
+ ),
406
+ )}
407
+ </box>
408
+ ) : null}
409
+
377
410
  {/* Footer */}
378
411
  <box marginTop={1} justifyContent="flex-end" width="100%">
379
412
  <text fg={t().textMuted}>Enter or Esc to close</text>
@@ -11,7 +11,7 @@ import type { TuiPluginApi, TuiSlotPlugin, TuiThemeCurrent } from "@opencode-ai/
11
11
  import { createEffect, createMemo, createSignal, on, onCleanup } from "solid-js";
12
12
 
13
13
  import { AftRpcClient } from "../shared/rpc-client";
14
- import { type AftStatusSnapshot, coerceAftStatus } from "../shared/status";
14
+ import { type AftStatusSnapshot, coerceAftStatus, type StatusCompression } from "../shared/status";
15
15
 
16
16
  const SINGLE_BORDER = { type: "single" } as any;
17
17
  const REFRESH_DEBOUNCE_MS = 200;
@@ -35,6 +35,46 @@ function formatCount(n: number | null | undefined): string {
35
35
  return String(n);
36
36
  }
37
37
 
38
+ /** Tagged rows for the Compression section. Each scope (Session / Project)
39
+ * emits a "scope" header followed by two "stat" rows — Tokens Saved and
40
+ * Compression Ratio — so the renderer can use the same StatRow layout as
41
+ * Search Index / Semantic Index above. Pi's monospace overlay and the
42
+ * OpenCode TUI dialog/sidebar all consume this same shape. */
43
+ export type CompressionRow =
44
+ | { kind: "scope"; label: string }
45
+ | { kind: "stat"; label: string; value: string };
46
+
47
+ function appendScope(
48
+ rows: CompressionRow[],
49
+ label: string,
50
+ scope: {
51
+ events: number;
52
+ original_tokens: number;
53
+ compressed_tokens: number;
54
+ savings_tokens: number;
55
+ },
56
+ ): void {
57
+ const savings = scope.savings_tokens;
58
+ const pct = scope.original_tokens > 0 ? Math.round((savings / scope.original_tokens) * 100) : 0;
59
+ rows.push({ kind: "scope", label });
60
+ rows.push({ kind: "stat", label: "Tokens Saved", value: savings.toLocaleString("en-US") });
61
+ rows.push({ kind: "stat", label: "Compression Ratio", value: `${pct}%` });
62
+ }
63
+
64
+ export function formatCompressionSidebarRows(
65
+ compression: StatusCompression | undefined,
66
+ ): CompressionRow[] {
67
+ if (!compression || compression.project.events <= 0) return [];
68
+
69
+ const rows: CompressionRow[] = [];
70
+ if (compression.session.events > 0) {
71
+ appendScope(rows, "Session", compression.session);
72
+ }
73
+ appendScope(rows, "Project", compression.project);
74
+
75
+ return rows;
76
+ }
77
+
38
78
  // Map index status → (label, theme color name). The label is what we want
39
79
  // the user to see; the color encodes severity so the eye lands on warnings.
40
80
  function statusDisplay(status: string): { label: string; tone: "ok" | "warn" | "err" | "muted" } {
@@ -104,7 +144,10 @@ function getClient(directory: string): AftRpcClient {
104
144
  if (client) return client;
105
145
  const home = process.env.HOME || process.env.USERPROFILE || "";
106
146
  const dataHome = process.env.XDG_DATA_HOME || `${home}/.local/share`;
107
- const storageDir = `${dataHome}/opencode/storage/plugin/aft`;
147
+ // v0.27 moved AFT storage to the CortexKit root. Must match the server
148
+ // plugin's `resolveCortexKitStorageRoot()` or the sidebar will poll a
149
+ // stale legacy port file and never connect to the live RPC server.
150
+ const storageDir = `${dataHome}/cortexkit/aft`;
108
151
  client = new AftRpcClient(storageDir, directory);
109
152
  sidebarClients.set(directory, client);
110
153
  return client;
@@ -225,6 +268,7 @@ const SidebarContent = (props: {
225
268
  const semanticStatus = () => statusDisplay(s()?.semantic_index?.status ?? "disabled");
226
269
  const trigramBytes = () => s()?.disk?.trigram_disk_bytes ?? 0;
227
270
  const semanticBytes = () => s()?.disk?.semantic_disk_bytes ?? 0;
271
+ const compressionRows = () => formatCompressionSidebarRows(s()?.compression);
228
272
 
229
273
  // Degraded-mode reason → human-readable hint. Distinct strings per reason
230
274
  // because the UX direction is different: "home_root" tells the user to
@@ -357,6 +401,26 @@ const SidebarContent = (props: {
357
401
  )}
358
402
  <StatRow theme={props.theme} label="Disk" value={formatBytes(semanticBytes())} tone="muted" />
359
403
 
404
+ {/* Compression aggregates. Tabular layout matching Search/Semantic
405
+ Index above: each scope ("Session", "Project") renders as a
406
+ subheader followed by two StatRows (Tokens Saved, Compression
407
+ Ratio). Keeps numbers right-aligned in the value column instead
408
+ 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
+ ),
420
+ )}
421
+ </>
422
+ )}
423
+
360
424
  {/* Surface failures clearly so users know to act (install ONNX,
361
425
  fix config, etc.) rather than silently leaving the panel "off". */}
362
426
  {s()?.semantic_index?.status === "failed" && s()?.semantic_index?.error && (