@cortexkit/aft-opencode 0.12.1 → 0.13.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.
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAmCA,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qGAAqG;IACrG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iGAAiG;IACjG,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACzE;AAED;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAiB;IAEzD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,iBAAiB,CAA8B;IACvD,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,iBAAiB,CAAoE;IAC7F,OAAO,CAAC,iBAAiB,CAA8C;gBAGrE,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,aAAa,EACvB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAW3C,mEAAmE;IACnE,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,oDAAoD;IACpD,OAAO,IAAI,OAAO;IAIlB;;;OAGG;IACG,IAAI,CACR,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACnC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAwFnC,8DAA8D;IACxD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B/B,gGAAgG;YAClF,YAAY;IAoB1B,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,YAAY;IAwDpB,OAAO,CAAC,YAAY;IA4BpB,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,WAAW;IA8BnB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,sBAAsB;CAM/B"}
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AA0EA,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qGAAqG;IACrG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iGAAiG;IACjG,iBAAiB,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACzE;AAED;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAiB;IAEzD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,iBAAiB,CAA8B;IACvD,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,iBAAiB,CAAoE;IAC7F,OAAO,CAAC,iBAAiB,CAA8C;gBAGrE,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,aAAa,EACvB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAW3C,mEAAmE;IACnE,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,oDAAoD;IACpD,OAAO,IAAI,OAAO;IAIlB;;;OAGG;IACG,IAAI,CACR,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACnC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAwFnC,8DAA8D;IACxD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B/B,gGAAgG;YAClF,YAAY;IAoB1B,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,YAAY;IAuFpB,OAAO,CAAC,YAAY;IA4BpB,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,WAAW;IA8BnB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,sBAAsB;CAM/B"}
@@ -9,6 +9,6 @@ export declare function selectOne(message: string, options: {
9
9
  export declare function text(message: string, options?: {
10
10
  placeholder?: string;
11
11
  defaultValue?: string;
12
- validate?: (value: string) => string | undefined;
12
+ validate?: (value: string) => string | Error | undefined;
13
13
  }): Promise<string>;
14
14
  //# sourceMappingURL=prompts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/cli/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,EAEL,GAAG,EACH,IAAI,EACJ,KAAK,EAEL,OAAO,EACR,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAS5C,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,UAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAOlF;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,GACjE,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED,wBAAsB,IAAI,CACxB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC7C,GACL,OAAO,CAAC,MAAM,CAAC,CASjB"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/cli/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,EAEL,GAAG,EACH,IAAI,EACJ,KAAK,EAEL,OAAO,EACR,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAS5C,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,UAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAOlF;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,GACjE,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED,wBAAsB,IAAI,CACxB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;CACrD,GACL,OAAO,CAAC,MAAM,CAAC,CAcjB"}
package/dist/cli.js CHANGED
@@ -9745,12 +9745,15 @@ async function confirm(message, defaultYes = true) {
9745
9745
  return result;
9746
9746
  }
9747
9747
  async function text(message, options = {}) {
9748
- const result = await Ot({
9748
+ const promptOptions = {
9749
9749
  message,
9750
9750
  ...options.placeholder ? { placeholder: options.placeholder } : {},
9751
9751
  ...options.defaultValue !== undefined ? { defaultValue: options.defaultValue } : {},
9752
- ...options.validate ? { validate: options.validate } : {}
9753
- });
9752
+ ...options.validate ? {
9753
+ validate: (value) => options.validate?.(value ?? "")
9754
+ } : {}
9755
+ };
9756
+ const result = await Ot(promptOptions);
9754
9757
  handleCancel(result);
9755
9758
  return result;
9756
9759
  }
package/dist/config.d.ts CHANGED
@@ -36,6 +36,18 @@ export declare const AftConfigSchema: z.ZodObject<{
36
36
  restrict_to_project_root: z.ZodOptional<z.ZodBoolean>;
37
37
  experimental_search_index: z.ZodOptional<z.ZodBoolean>;
38
38
  experimental_semantic_search: z.ZodOptional<z.ZodBoolean>;
39
+ semantic: z.ZodOptional<z.ZodObject<{
40
+ backend: z.ZodOptional<z.ZodEnum<{
41
+ fastembed: "fastembed";
42
+ openai_compatible: "openai_compatible";
43
+ ollama: "ollama";
44
+ }>>;
45
+ model: z.ZodOptional<z.ZodString>;
46
+ base_url: z.ZodOptional<z.ZodString>;
47
+ api_key_env: z.ZodOptional<z.ZodString>;
48
+ timeout_ms: z.ZodOptional<z.ZodNumber>;
49
+ max_batch_size: z.ZodOptional<z.ZodNumber>;
50
+ }, z.core.$strip>>;
39
51
  }, z.core.$strip>;
40
52
  export type AftConfig = z.infer<typeof AftConfigSchema>;
41
53
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA8BxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwC1B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AA8HxD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAwBjE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA+CxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0C1B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AA2KxD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAiCjE"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA6FlD;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,MAAM,EAAE,MAiVb,CAAC;AAEF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA6FlD;;;;;;;;;;;;;;;;;;GAkBG;AACH,QAAA,MAAM,MAAM,EAAE,MA4Vb,CAAC;AAEF,eAAe,MAAM,CAAC"}
package/dist/index.js CHANGED
@@ -7805,12 +7805,13 @@ var require_src2 = __commonJS((exports, module) => {
7805
7805
  // src/index.ts
7806
7806
  import { existsSync as existsSync8, mkdirSync as mkdirSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
7807
7807
  import { createRequire as createRequire2 } from "module";
7808
- import { homedir as homedir6 } from "os";
7808
+ import { homedir as homedir7 } from "os";
7809
7809
  import { join as join13 } from "path";
7810
7810
 
7811
7811
  // src/config.ts
7812
7812
  var import_comment_json = __toESM(require_src2(), 1);
7813
7813
  import { existsSync, readFileSync } from "fs";
7814
+ import { homedir } from "os";
7814
7815
  import { join as join2 } from "path";
7815
7816
 
7816
7817
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
@@ -21433,6 +21434,15 @@ var CheckerEnum = exports_external.enum([
21433
21434
  "staticcheck",
21434
21435
  "none"
21435
21436
  ]);
21437
+ var SemanticBackendEnum = exports_external.enum(["fastembed", "openai_compatible", "ollama"]);
21438
+ var SemanticConfigSchema = exports_external.object({
21439
+ backend: SemanticBackendEnum.optional(),
21440
+ model: exports_external.string().trim().min(1).optional(),
21441
+ base_url: exports_external.string().trim().min(1).optional(),
21442
+ api_key_env: exports_external.string().trim().min(1).optional(),
21443
+ timeout_ms: exports_external.number().int().positive().optional(),
21444
+ max_batch_size: exports_external.number().int().positive().optional()
21445
+ });
21436
21446
  var AftConfigSchema = exports_external.object({
21437
21447
  format_on_edit: exports_external.boolean().optional(),
21438
21448
  validate_on_edit: exports_external.enum(["syntax", "full"]).optional(),
@@ -21443,7 +21453,8 @@ var AftConfigSchema = exports_external.object({
21443
21453
  disabled_tools: exports_external.array(exports_external.string()).optional(),
21444
21454
  restrict_to_project_root: exports_external.boolean().optional(),
21445
21455
  experimental_search_index: exports_external.boolean().optional(),
21446
- experimental_semantic_search: exports_external.boolean().optional()
21456
+ experimental_semantic_search: exports_external.boolean().optional(),
21457
+ semantic: SemanticConfigSchema.optional()
21447
21458
  });
21448
21459
  function detectConfigFile(basePath) {
21449
21460
  const jsoncPath = `${basePath}.jsonc`;
@@ -21503,18 +21514,46 @@ function loadConfigFromPath(configPath) {
21503
21514
  return null;
21504
21515
  }
21505
21516
  }
21517
+ function mergeSemanticConfig(baseSemantic, overrideSemantic) {
21518
+ const projectSemantic = {};
21519
+ if (overrideSemantic) {
21520
+ if (overrideSemantic.model !== undefined)
21521
+ projectSemantic.model = overrideSemantic.model;
21522
+ if (overrideSemantic.timeout_ms !== undefined)
21523
+ projectSemantic.timeout_ms = overrideSemantic.timeout_ms;
21524
+ if (overrideSemantic.max_batch_size !== undefined)
21525
+ projectSemantic.max_batch_size = overrideSemantic.max_batch_size;
21526
+ }
21527
+ const semantic = {
21528
+ ...baseSemantic,
21529
+ ...projectSemantic
21530
+ };
21531
+ if (Object.values(semantic).every((value) => value === undefined)) {
21532
+ return;
21533
+ }
21534
+ return Object.fromEntries(Object.entries(semantic).filter(([, value]) => value !== undefined));
21535
+ }
21506
21536
  function mergeConfigs(base, override) {
21507
21537
  const disabledTools = [...base.disabled_tools ?? [], ...override.disabled_tools ?? []];
21538
+ const formatter = { ...base.formatter, ...override.formatter };
21539
+ const checker = { ...base.checker, ...override.checker };
21540
+ const semantic = mergeSemanticConfig(base.semantic, override.semantic);
21541
+ const { semantic: _stripSemantic, ...safeOverride } = override;
21508
21542
  return {
21509
21543
  ...base,
21510
- ...override,
21511
- formatter: { ...base.formatter, ...override.formatter },
21512
- checker: { ...base.checker, ...override.checker },
21544
+ ...safeOverride,
21545
+ ...Object.keys(formatter).length > 0 ? { formatter } : {},
21546
+ ...Object.keys(checker).length > 0 ? { checker } : {},
21547
+ semantic,
21513
21548
  ...disabledTools.length > 0 ? { disabled_tools: [...new Set(disabledTools)] } : {}
21514
21549
  };
21515
21550
  }
21516
21551
  function getOpenCodeConfigDir() {
21517
- const xdgConfig = process.env.XDG_CONFIG_HOME || join2(process.env.HOME || "~", ".config");
21552
+ const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
21553
+ if (envDir) {
21554
+ return envDir;
21555
+ }
21556
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join2(homedir(), ".config");
21518
21557
  return join2(xdgConfig, "opencode");
21519
21558
  }
21520
21559
  function loadAftConfig(projectDirectory) {
@@ -21528,6 +21567,9 @@ function loadAftConfig(projectDirectory) {
21528
21567
  let config2 = loadConfigFromPath(userConfigPath) ?? {};
21529
21568
  const projectConfig = loadConfigFromPath(projectConfigPath);
21530
21569
  if (projectConfig) {
21570
+ if (projectConfig.semantic?.backend !== undefined || projectConfig.semantic?.base_url !== undefined || projectConfig.semantic?.api_key_env !== undefined) {
21571
+ warn("Ignoring semantic.backend/base_url/api_key_env from project config (security: use user config for external backends)");
21572
+ }
21531
21573
  config2 = mergeConfigs(config2, projectConfig);
21532
21574
  }
21533
21575
  return config2;
@@ -21535,7 +21577,7 @@ function loadAftConfig(projectDirectory) {
21535
21577
 
21536
21578
  // src/downloader.ts
21537
21579
  import { chmodSync, existsSync as existsSync2, mkdirSync, unlinkSync } from "fs";
21538
- import { homedir } from "os";
21580
+ import { homedir as homedir2 } from "os";
21539
21581
  import { join as join3 } from "path";
21540
21582
 
21541
21583
  // src/platform.ts
@@ -21557,10 +21599,10 @@ var REPO = "cortexkit/aft";
21557
21599
  function getCacheDir() {
21558
21600
  if (process.platform === "win32") {
21559
21601
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
21560
- const base2 = localAppData || join3(homedir(), "AppData", "Local");
21602
+ const base2 = localAppData || join3(homedir2(), "AppData", "Local");
21561
21603
  return join3(base2, "aft", "bin");
21562
21604
  }
21563
- const base = process.env.XDG_CACHE_HOME || join3(homedir(), ".cache");
21605
+ const base = process.env.XDG_CACHE_HOME || join3(homedir2(), ".cache");
21564
21606
  return join3(base, "aft", "bin");
21565
21607
  }
21566
21608
  function getBinaryName() {
@@ -21755,7 +21797,7 @@ function normalizeToolMap(tools) {
21755
21797
 
21756
21798
  // src/notifications.ts
21757
21799
  import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
21758
- import { homedir as homedir2, platform } from "os";
21800
+ import { homedir as homedir3, platform } from "os";
21759
21801
  import { join as join4 } from "path";
21760
21802
  function isTuiMode() {
21761
21803
  return process.env.OPENCODE_CLIENT === "cli";
@@ -21777,7 +21819,7 @@ var WARNING_MARKER = `${AFT_MARKER} \u26A0\uFE0F`;
21777
21819
  var STATUS_MARKER = `${AFT_MARKER} \u2705`;
21778
21820
  function getDesktopStatePath() {
21779
21821
  const os2 = platform();
21780
- const home = homedir2();
21822
+ const home = homedir3();
21781
21823
  if (os2 === "darwin") {
21782
21824
  return join4(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
21783
21825
  }
@@ -22059,8 +22101,7 @@ async function downloadOnnxRuntime(info, targetDir) {
22059
22101
  const { execSync } = await import("child_process");
22060
22102
  execSync(`tar xzf "${archivePath}" -C "${tmpDir}"`, { stdio: "pipe" });
22061
22103
  } else {
22062
- const { execSync } = await import("child_process");
22063
- execSync(`unzip -q "${archivePath}" -d "${tmpDir}"`, { stdio: "pipe" });
22104
+ await extractZipArchive(archivePath, tmpDir);
22064
22105
  }
22065
22106
  const extractedDir = join5(tmpDir, info.assetName, "lib");
22066
22107
  if (!existsSync4(extractedDir)) {
@@ -22118,11 +22159,45 @@ async function downloadOnnxRuntime(info, targetDir) {
22118
22159
  return null;
22119
22160
  }
22120
22161
  }
22162
+ async function extractZipArchive(archivePath, destinationDir) {
22163
+ const { execFileSync } = await import("child_process");
22164
+ if (process.platform === "win32") {
22165
+ let powershellError;
22166
+ try {
22167
+ execFileSync("powershell.exe", [
22168
+ "-NoProfile",
22169
+ "-NonInteractive",
22170
+ "-ExecutionPolicy",
22171
+ "Bypass",
22172
+ "-Command",
22173
+ "& { Expand-Archive -LiteralPath $args[0] -DestinationPath $args[1] -Force }",
22174
+ archivePath,
22175
+ destinationDir
22176
+ ], { stdio: "pipe", timeout: 120000 });
22177
+ return;
22178
+ } catch (err) {
22179
+ powershellError = err;
22180
+ warn(`PowerShell Expand-Archive failed, falling back to cmd/tar: ${String(err)}`);
22181
+ }
22182
+ try {
22183
+ execFileSync("cmd.exe", ["/d", "/s", "/c", `tar -xf "${archivePath}" -C "${destinationDir}"`], { stdio: "pipe", timeout: 120000 });
22184
+ return;
22185
+ } catch (cmdError) {
22186
+ throw new Error(`ZIP extraction failed via PowerShell and cmd/tar. PowerShell: ${String(powershellError)} | cmd/tar: ${String(cmdError)}`);
22187
+ }
22188
+ }
22189
+ execFileSync("unzip", ["-q", archivePath, "-d", destinationDir], {
22190
+ stdio: "pipe",
22191
+ timeout: 120000
22192
+ });
22193
+ }
22121
22194
 
22122
22195
  // src/bridge.ts
22123
22196
  import { spawn } from "child_process";
22124
- import { homedir as homedir3 } from "os";
22197
+ import { homedir as homedir4 } from "os";
22125
22198
  import { join as join6 } from "path";
22199
+ var DEFAULT_BRIDGE_TIMEOUT_MS = 30000;
22200
+ var SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS = 5000;
22126
22201
  function compareSemver(a, b) {
22127
22202
  const pa = a.split(".").map(Number);
22128
22203
  const pb = b.split(".").map(Number);
@@ -22133,6 +22208,28 @@ function compareSemver(a, b) {
22133
22208
  }
22134
22209
  return 0;
22135
22210
  }
22211
+ function clampSemanticTimeout(configOverrides, bridgeTimeoutMs) {
22212
+ const semantic = configOverrides.semantic;
22213
+ if (!semantic || typeof semantic !== "object" || Array.isArray(semantic)) {
22214
+ return configOverrides;
22215
+ }
22216
+ const timeoutMs = semantic.timeout_ms;
22217
+ if (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs)) {
22218
+ return configOverrides;
22219
+ }
22220
+ const maxSemanticTimeoutMs = bridgeTimeoutMs > SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS ? bridgeTimeoutMs - SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS : Math.max(1, bridgeTimeoutMs - 1);
22221
+ if (timeoutMs <= maxSemanticTimeoutMs) {
22222
+ return configOverrides;
22223
+ }
22224
+ warn(`semantic.timeout_ms=${timeoutMs} exceeds bridge timeout budget; clamping to ${maxSemanticTimeoutMs}ms (bridge timeout: ${bridgeTimeoutMs}ms)`);
22225
+ return {
22226
+ ...configOverrides,
22227
+ semantic: {
22228
+ ...semantic,
22229
+ timeout_ms: maxSemanticTimeoutMs
22230
+ }
22231
+ };
22232
+ }
22136
22233
 
22137
22234
  class BinaryBridge {
22138
22235
  static RESTART_RESET_MS = 5 * 60 * 1000;
@@ -22155,9 +22252,9 @@ class BinaryBridge {
22155
22252
  constructor(binaryPath, cwd, options, configOverrides) {
22156
22253
  this.binaryPath = binaryPath;
22157
22254
  this.cwd = cwd;
22158
- this.timeoutMs = options?.timeoutMs ?? 30000;
22255
+ this.timeoutMs = options?.timeoutMs ?? DEFAULT_BRIDGE_TIMEOUT_MS;
22159
22256
  this.maxRestarts = options?.maxRestarts ?? 3;
22160
- this.configOverrides = configOverrides ?? {};
22257
+ this.configOverrides = clampSemanticTimeout(configOverrides ?? {}, this.timeoutMs);
22161
22258
  this.minVersion = options?.minVersion;
22162
22259
  this.onVersionMismatch = options?.onVersionMismatch;
22163
22260
  }
@@ -22274,16 +22371,32 @@ class BinaryBridge {
22274
22371
  }
22275
22372
  spawnProcess() {
22276
22373
  log(`Spawning binary: ${this.binaryPath} (cwd: ${this.cwd})`);
22374
+ const semantic = this.configOverrides.semantic;
22375
+ const semanticBackend = (() => {
22376
+ if (semantic && typeof semantic === "object" && !Array.isArray(semantic)) {
22377
+ const candidate = semantic.backend;
22378
+ return typeof candidate === "string" ? candidate : undefined;
22379
+ }
22380
+ return;
22381
+ })();
22382
+ const useFastembedBackend = semanticBackend === undefined || semanticBackend === "fastembed" || semanticBackend === "";
22383
+ const ortDir = typeof this.configOverrides._ort_dylib_dir === "string" && useFastembedBackend ? this.configOverrides._ort_dylib_dir : null;
22384
+ const ortLibraryPath = ortDir == null ? null : join6(ortDir, process.platform === "win32" ? "onnxruntime.dll" : process.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
22385
+ const envPath = process.platform === "win32" && ortDir ? `${ortDir};${process.env.PATH ?? ""}` : process.env.PATH;
22386
+ const env = {
22387
+ ...process.env,
22388
+ ...envPath ? { PATH: envPath } : {}
22389
+ };
22390
+ if (useFastembedBackend) {
22391
+ env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ? join6(this.configOverrides.storage_dir, "semantic", "models") : join6(homedir4() || "", ".cache", "fastembed"));
22392
+ if (ortLibraryPath) {
22393
+ env.ORT_DYLIB_PATH = ortLibraryPath;
22394
+ }
22395
+ }
22277
22396
  const child = spawn(this.binaryPath, [], {
22278
22397
  cwd: this.cwd,
22279
22398
  stdio: ["pipe", "pipe", "pipe"],
22280
- env: {
22281
- ...process.env,
22282
- FASTEMBED_CACHE_DIR: process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ? join6(this.configOverrides.storage_dir, "semantic", "models") : join6(homedir3() || "", ".cache", "fastembed")),
22283
- ...typeof this.configOverrides._ort_dylib_dir === "string" && {
22284
- ORT_DYLIB_PATH: join6(this.configOverrides._ort_dylib_dir, process.platform === "win32" ? "onnxruntime.dll" : process.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so")
22285
- }
22286
- }
22399
+ env
22287
22400
  });
22288
22401
  child.stdout?.on("data", (chunk) => {
22289
22402
  this.onStdoutData(chunk.toString("utf-8"));
@@ -22493,7 +22606,7 @@ class BridgePool {
22493
22606
  import { execSync, spawnSync } from "child_process";
22494
22607
  import { chmodSync as chmodSync3, copyFileSync, existsSync as existsSync5, mkdirSync as mkdirSync4 } from "fs";
22495
22608
  import { createRequire } from "module";
22496
- import { homedir as homedir4 } from "os";
22609
+ import { homedir as homedir5 } from "os";
22497
22610
  import { join as join7 } from "path";
22498
22611
  function copyToVersionedCache(npmBinaryPath) {
22499
22612
  try {
@@ -22573,7 +22686,7 @@ function findBinarySync() {
22573
22686
  if (result)
22574
22687
  return result;
22575
22688
  } catch {}
22576
- const cargoPath = join7(homedir4(), ".cargo", "bin", `aft${ext}`);
22689
+ const cargoPath = join7(homedir5(), ".cargo", "bin", `aft${ext}`);
22577
22690
  if (existsSync5(cargoPath))
22578
22691
  return cargoPath;
22579
22692
  return null;
@@ -22783,6 +22896,10 @@ function coerceAftStatus(response) {
22783
22896
  const features = asRecord(response.features);
22784
22897
  const searchIndex = asRecord(response.search_index);
22785
22898
  const semanticIndex = asRecord(response.semantic_index);
22899
+ const semanticConfig = {
22900
+ ...asRecord(response.semantic),
22901
+ ...asRecord(response.semantic_config)
22902
+ };
22786
22903
  const disk = asRecord(response.disk);
22787
22904
  const symbolCache = asRecord(response.symbol_cache);
22788
22905
  return {
@@ -22802,8 +22919,15 @@ function coerceAftStatus(response) {
22802
22919
  },
22803
22920
  semantic_index: {
22804
22921
  status: readString(semanticIndex.status, "unknown"),
22922
+ backend: readNullableString(semanticIndex.backend ?? semanticConfig.backend),
22923
+ model: readNullableString(semanticIndex.model ?? semanticConfig.model),
22924
+ stage: readNullableString(semanticIndex.stage),
22925
+ files: readOptionalNumber(semanticIndex.files),
22926
+ entries_done: readOptionalNumber(semanticIndex.entries_done),
22927
+ entries_total: readOptionalNumber(semanticIndex.entries_total),
22805
22928
  entries: readOptionalNumber(semanticIndex.entries),
22806
- dimension: readOptionalNumber(semanticIndex.dimension)
22929
+ dimension: readOptionalNumber(semanticIndex.dimension),
22930
+ error: readNullableString(semanticIndex.error)
22807
22931
  },
22808
22932
  disk: {
22809
22933
  storage_dir: readNullableString(disk.storage_dir),
@@ -22839,9 +22963,27 @@ function formatStatusMarkdown(status) {
22839
22963
  `- **Status:** \`${status.semantic_index.status}\``,
22840
22964
  `- **Entries:** ${formatCount(status.semantic_index.entries)}`
22841
22965
  ];
22966
+ if (status.semantic_index.backend) {
22967
+ lines.push(`- **Backend:** ${status.semantic_index.backend}`);
22968
+ }
22969
+ if (status.semantic_index.model) {
22970
+ lines.push(`- **Model:** ${status.semantic_index.model}`);
22971
+ }
22842
22972
  if (status.semantic_index.dimension != null) {
22843
22973
  lines.push(`- **Dimension:** ${formatCount(status.semantic_index.dimension)}`);
22844
22974
  }
22975
+ if (status.semantic_index.stage) {
22976
+ lines.push(`- **Stage:** ${status.semantic_index.stage}`);
22977
+ }
22978
+ if (status.semantic_index.files != null) {
22979
+ lines.push(`- **Files:** ${formatCount(status.semantic_index.files)}`);
22980
+ }
22981
+ if (status.semantic_index.entries_done != null || status.semantic_index.entries_total != null) {
22982
+ lines.push(`- **Progress:** ${formatCount(status.semantic_index.entries_done ?? null)} / ${formatCount(status.semantic_index.entries_total ?? null)}`);
22983
+ }
22984
+ if (status.semantic_index.error) {
22985
+ lines.push(`- **Error:** ${status.semantic_index.error}`);
22986
+ }
22845
22987
  lines.push("", "### Disk usage", `- **Trigram index:** ${formatBytes(status.disk.trigram_disk_bytes)}`, `- **Semantic index:** ${formatBytes(status.disk.semantic_disk_bytes)}`, "", "### Runtime", `- **LSP servers:** ${formatCount(status.lsp_servers)}`, `- **Symbol cache:** ${formatCount(status.symbol_cache.local_entries)} local / ${formatCount(status.symbol_cache.warm_entries)} warm`);
22846
22988
  if (status.storage_dir ?? status.disk.storage_dir) {
22847
22989
  lines.push(`- **Storage dir:** \`${status.storage_dir ?? status.disk.storage_dir}\``);
@@ -22856,7 +22998,7 @@ import { existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as rea
22856
22998
  import { dirname as dirname2, join as join10 } from "path";
22857
22999
 
22858
23000
  // src/shared/opencode-config-dir.ts
22859
- import { homedir as homedir5 } from "os";
23001
+ import { homedir as homedir6 } from "os";
22860
23002
  import { join as join9, resolve } from "path";
22861
23003
  function getCliConfigDir() {
22862
23004
  const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
@@ -22864,9 +23006,9 @@ function getCliConfigDir() {
22864
23006
  return resolve(envConfigDir);
22865
23007
  }
22866
23008
  if (process.platform === "win32") {
22867
- return join9(homedir5(), ".config", "opencode");
23009
+ return join9(homedir6(), ".config", "opencode");
22868
23010
  }
22869
- return join9(process.env.XDG_CONFIG_HOME || join9(homedir5(), ".config"), "opencode");
23011
+ return join9(process.env.XDG_CONFIG_HOME || join9(homedir6(), ".config"), "opencode");
22870
23012
  }
22871
23013
  function getOpenCodeConfigDir2(_options) {
22872
23014
  return getCliConfigDir();
@@ -25234,9 +25376,12 @@ var plugin = async (input) => {
25234
25376
  configOverrides.experimental_search_index = aftConfig.experimental_search_index;
25235
25377
  if (aftConfig.experimental_semantic_search !== undefined)
25236
25378
  configOverrides.experimental_semantic_search = aftConfig.experimental_semantic_search;
25237
- const dataHome = process.env.XDG_DATA_HOME || join13(homedir6(), ".local", "share");
25379
+ if (aftConfig.semantic !== undefined)
25380
+ configOverrides.semantic = aftConfig.semantic;
25381
+ const isFastembedSemanticBackend = (aftConfig.semantic?.backend ?? "fastembed") === "fastembed";
25382
+ const dataHome = process.env.XDG_DATA_HOME || join13(homedir7(), ".local", "share");
25238
25383
  configOverrides.storage_dir = join13(dataHome, "opencode", "storage", "plugin", "aft");
25239
- if (aftConfig.experimental_semantic_search) {
25384
+ if (aftConfig.experimental_semantic_search && isFastembedSemanticBackend) {
25240
25385
  const storageDir2 = configOverrides.storage_dir;
25241
25386
  ensureOnnxRuntime(storageDir2).then((ortDir) => {
25242
25387
  if (ortDir) {
@@ -25314,7 +25459,7 @@ var plugin = async (input) => {
25314
25459
  });
25315
25460
  rpcServer.handle("get-warnings", async () => {
25316
25461
  const warnings = [];
25317
- if (aftConfig.experimental_semantic_search && !configOverrides._ort_dylib_dir) {
25462
+ if (aftConfig.experimental_semantic_search && isFastembedSemanticBackend && !configOverrides._ort_dylib_dir) {
25318
25463
  if (!isOrtAutoDownloadSupported()) {
25319
25464
  warnings.push(`Semantic search requires ONNX Runtime.
25320
25465
  Install: ${getManualInstallHint()}`);
@@ -25336,7 +25481,7 @@ Install: ${getManualInstallHint()}`);
25336
25481
  setTimeout(() => {
25337
25482
  sendFeatureAnnouncement(notifyOpts, PLUGIN_VERSION, featureList, storageDir).catch(() => {});
25338
25483
  }, 8000);
25339
- if (aftConfig.experimental_semantic_search && !configOverrides._ort_dylib_dir) {
25484
+ if (aftConfig.experimental_semantic_search && isFastembedSemanticBackend && !configOverrides._ort_dylib_dir) {
25340
25485
  setTimeout(() => {
25341
25486
  if (!configOverrides._ort_dylib_dir && !isOrtAutoDownloadSupported()) {
25342
25487
  sendWarning(notifyOpts, `Semantic search requires ONNX Runtime.
@@ -1 +1 @@
1
- {"version":3,"file":"onnx-runtime.d.ts","sourceRoot":"","sources":["../src/onnx-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA0DH,4DAA4D;AAC5D,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED,6EAA6E;AAC7E,wBAAgB,oBAAoB,IAAI,MAAM,CAQ7C;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4BlF;AAgJD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAU3D"}
1
+ {"version":3,"file":"onnx-runtime.d.ts","sourceRoot":"","sources":["../src/onnx-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA0DH,4DAA4D;AAC5D,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED,6EAA6E;AAC7E,wBAAgB,oBAAoB,IAAI,MAAM,CAQ7C;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4BlF;AA8LD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAU3D"}
@@ -15,8 +15,15 @@ export interface AftStatusSnapshot {
15
15
  };
16
16
  semantic_index: {
17
17
  status: string;
18
+ backend?: string | null;
19
+ model?: string | null;
20
+ stage?: string | null;
21
+ files?: number | null;
22
+ entries_done?: number | null;
23
+ entries_total?: number | null;
18
24
  entries: number | null;
19
25
  dimension: number | null;
26
+ error?: string | null;
20
27
  };
21
28
  disk: {
22
29
  storage_dir: string | null;
@@ -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,QAAQ,EAAE;QACR,cAAc,EAAE,OAAO,CAAC;QACxB,gBAAgB,EAAE,MAAM,CAAC;QACzB,wBAAwB,EAAE,OAAO,CAAC;QAClC,yBAAyB,EAAE,OAAO,CAAC;QACnC,4BAA4B,EAAE,OAAO,CAAC;KACvC,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,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,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;CAC5B;AAkCD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAajD;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,iBAAiB,CAuCpF;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAwC3E;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CA0CtE"}
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,QAAQ,EAAE;QACR,cAAc,EAAE,OAAO,CAAC;QACxB,gBAAgB,EAAE,MAAM,CAAC;QACzB,wBAAwB,EAAE,OAAO,CAAC;QAClC,yBAAyB,EAAE,OAAO,CAAC;QACnC,4BAA4B,EAAE,OAAO,CAAC;KACvC,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;CAC5B;AAkCD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAajD;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,iBAAiB,CAkDpF;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CA6D3E;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CA+DtE"}
package/dist/tui.js CHANGED
@@ -158,6 +158,10 @@ function coerceAftStatus(response) {
158
158
  const features = asRecord(response.features);
159
159
  const searchIndex = asRecord(response.search_index);
160
160
  const semanticIndex = asRecord(response.semantic_index);
161
+ const semanticConfig = {
162
+ ...asRecord(response.semantic),
163
+ ...asRecord(response.semantic_config)
164
+ };
161
165
  const disk = asRecord(response.disk);
162
166
  const symbolCache = asRecord(response.symbol_cache);
163
167
  return {
@@ -177,8 +181,15 @@ function coerceAftStatus(response) {
177
181
  },
178
182
  semantic_index: {
179
183
  status: readString(semanticIndex.status, "unknown"),
184
+ backend: readNullableString(semanticIndex.backend ?? semanticConfig.backend),
185
+ model: readNullableString(semanticIndex.model ?? semanticConfig.model),
186
+ stage: readNullableString(semanticIndex.stage),
187
+ files: readOptionalNumber(semanticIndex.files),
188
+ entries_done: readOptionalNumber(semanticIndex.entries_done),
189
+ entries_total: readOptionalNumber(semanticIndex.entries_total),
180
190
  entries: readOptionalNumber(semanticIndex.entries),
181
- dimension: readOptionalNumber(semanticIndex.dimension)
191
+ dimension: readOptionalNumber(semanticIndex.dimension),
192
+ error: readNullableString(semanticIndex.error)
182
193
  },
183
194
  disk: {
184
195
  storage_dir: readNullableString(disk.storage_dir),
@@ -212,6 +223,12 @@ function formatStatusDialogMessage(status) {
212
223
  `- status: ${status.semantic_index.status}`,
213
224
  `- entries: ${formatCount(status.semantic_index.entries)}`
214
225
  ];
226
+ if (status.semantic_index.backend) {
227
+ lines.push(`- backend: ${status.semantic_index.backend}`);
228
+ }
229
+ if (status.semantic_index.model) {
230
+ lines.push(`- model: ${status.semantic_index.model}`);
231
+ }
215
232
  if (status.semantic_index.dimension != null) {
216
233
  lines.push(`- dimension: ${formatCount(status.semantic_index.dimension)}`);
217
234
  }
@@ -219,6 +236,18 @@ function formatStatusDialogMessage(status) {
219
236
  if (status.storage_dir ?? status.disk.storage_dir) {
220
237
  lines.push(`- storage dir: ${status.storage_dir ?? status.disk.storage_dir}`);
221
238
  }
239
+ if (status.semantic_index.stage) {
240
+ lines.push("", "Semantic stage", status.semantic_index.stage);
241
+ }
242
+ if (status.semantic_index.files != null) {
243
+ lines.push(`- semantic files: ${formatCount(status.semantic_index.files)}`);
244
+ }
245
+ if (status.semantic_index.entries_done != null || status.semantic_index.entries_total != null) {
246
+ lines.push(`- semantic progress: ${formatCount(status.semantic_index.entries_done ?? null)} / ${formatCount(status.semantic_index.entries_total ?? null)}`);
247
+ }
248
+ if (status.semantic_index.error) {
249
+ lines.push("", "Semantic error", status.semantic_index.error);
250
+ }
222
251
  return lines.join(`
223
252
  `);
224
253
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft-opencode",
3
- "version": "0.12.1",
3
+ "version": "0.13.0",
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",
@@ -15,6 +15,8 @@
15
15
  },
16
16
  "files": [
17
17
  "dist",
18
+ "src/tui",
19
+ "src/shared",
18
20
  "README.md"
19
21
  ],
20
22
  "scripts": {
@@ -33,11 +35,11 @@
33
35
  "zod": "^4.1.8"
34
36
  },
35
37
  "optionalDependencies": {
36
- "@cortexkit/aft-darwin-arm64": "0.12.1",
37
- "@cortexkit/aft-darwin-x64": "0.12.1",
38
- "@cortexkit/aft-linux-arm64": "0.12.1",
39
- "@cortexkit/aft-linux-x64": "0.12.1",
40
- "@cortexkit/aft-win32-x64": "0.12.1"
38
+ "@cortexkit/aft-darwin-arm64": "0.13.0",
39
+ "@cortexkit/aft-darwin-x64": "0.13.0",
40
+ "@cortexkit/aft-linux-arm64": "0.13.0",
41
+ "@cortexkit/aft-linux-x64": "0.13.0",
42
+ "@cortexkit/aft-win32-x64": "0.13.0"
41
43
  },
42
44
  "devDependencies": {
43
45
  "@types/node": "^22.0.0",
@@ -50,7 +52,7 @@
50
52
  },
51
53
  "./tui": {
52
54
  "types": "./src/tui/index.tsx",
53
- "import": "./dist/tui.js"
55
+ "import": "./src/tui/index.tsx"
54
56
  }
55
57
  },
56
58
  "oc-plugin": [
@@ -0,0 +1,46 @@
1
+ import { homedir } from "node:os";
2
+ import { join, resolve } from "node:path";
3
+
4
+ export type OpenCodeBinaryType = "opencode" | "opencode-desktop";
5
+
6
+ export interface OpenCodeConfigDirOptions {
7
+ binary: OpenCodeBinaryType;
8
+ version?: string | null;
9
+ checkExisting?: boolean;
10
+ }
11
+
12
+ export interface OpenCodeConfigPaths {
13
+ configDir: string;
14
+ configJson: string;
15
+ configJsonc: string;
16
+ packageJson: string;
17
+ omoConfig: string;
18
+ }
19
+
20
+ function getCliConfigDir(): string {
21
+ const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
22
+ if (envConfigDir) {
23
+ return resolve(envConfigDir);
24
+ }
25
+
26
+ if (process.platform === "win32") {
27
+ return join(homedir(), ".config", "opencode");
28
+ }
29
+
30
+ return join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), "opencode");
31
+ }
32
+
33
+ export function getOpenCodeConfigDir(_options: OpenCodeConfigDirOptions): string {
34
+ return getCliConfigDir();
35
+ }
36
+
37
+ export function getOpenCodeConfigPaths(options: OpenCodeConfigDirOptions): OpenCodeConfigPaths {
38
+ const configDir = getOpenCodeConfigDir(options);
39
+ return {
40
+ configDir,
41
+ configJson: join(configDir, "opencode.json"),
42
+ configJsonc: join(configDir, "opencode.jsonc"),
43
+ packageJson: join(configDir, "package.json"),
44
+ omoConfig: join(configDir, "magic-context.jsonc"),
45
+ };
46
+ }