opencode-codebase-index 0.17.0 → 0.18.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.
@@ -655,467 +655,6 @@ var require_ignore = __commonJS({
655
655
  }
656
656
  });
657
657
 
658
- // node_modules/tiktoken/tiktoken_bg.cjs
659
- var require_tiktoken_bg = __commonJS({
660
- "node_modules/tiktoken/tiktoken_bg.cjs"(exports2, module3) {
661
- "use strict";
662
- var wasm;
663
- module3.exports.__wbg_set_wasm = function(val) {
664
- wasm = val;
665
- };
666
- var lTextDecoder = typeof TextDecoder === "undefined" ? (0, module3.require)("util").TextDecoder : TextDecoder;
667
- var cachedTextDecoder = new lTextDecoder("utf-8", { ignoreBOM: true, fatal: true });
668
- cachedTextDecoder.decode();
669
- var cachedUint8ArrayMemory0 = null;
670
- function getUint8ArrayMemory0() {
671
- if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
672
- cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
673
- }
674
- return cachedUint8ArrayMemory0;
675
- }
676
- function getStringFromWasm0(ptr, len) {
677
- ptr = ptr >>> 0;
678
- return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
679
- }
680
- var heap = new Array(128).fill(void 0);
681
- heap.push(void 0, null, true, false);
682
- var heap_next = heap.length;
683
- function addHeapObject(obj) {
684
- if (heap_next === heap.length) heap.push(heap.length + 1);
685
- const idx = heap_next;
686
- heap_next = heap[idx];
687
- heap[idx] = obj;
688
- return idx;
689
- }
690
- function handleError(f, args) {
691
- try {
692
- return f.apply(this, args);
693
- } catch (e) {
694
- wasm.__wbindgen_export_0(addHeapObject(e));
695
- }
696
- }
697
- function getObject(idx) {
698
- return heap[idx];
699
- }
700
- function dropObject(idx) {
701
- if (idx < 132) return;
702
- heap[idx] = heap_next;
703
- heap_next = idx;
704
- }
705
- function takeObject(idx) {
706
- const ret = getObject(idx);
707
- dropObject(idx);
708
- return ret;
709
- }
710
- var WASM_VECTOR_LEN = 0;
711
- var lTextEncoder = typeof TextEncoder === "undefined" ? (0, module3.require)("util").TextEncoder : TextEncoder;
712
- var cachedTextEncoder = new lTextEncoder("utf-8");
713
- var encodeString = typeof cachedTextEncoder.encodeInto === "function" ? function(arg, view) {
714
- return cachedTextEncoder.encodeInto(arg, view);
715
- } : function(arg, view) {
716
- const buf = cachedTextEncoder.encode(arg);
717
- view.set(buf);
718
- return {
719
- read: arg.length,
720
- written: buf.length
721
- };
722
- };
723
- function passStringToWasm0(arg, malloc, realloc) {
724
- if (realloc === void 0) {
725
- const buf = cachedTextEncoder.encode(arg);
726
- const ptr2 = malloc(buf.length, 1) >>> 0;
727
- getUint8ArrayMemory0().subarray(ptr2, ptr2 + buf.length).set(buf);
728
- WASM_VECTOR_LEN = buf.length;
729
- return ptr2;
730
- }
731
- let len = arg.length;
732
- let ptr = malloc(len, 1) >>> 0;
733
- const mem = getUint8ArrayMemory0();
734
- let offset = 0;
735
- for (; offset < len; offset++) {
736
- const code = arg.charCodeAt(offset);
737
- if (code > 127) break;
738
- mem[ptr + offset] = code;
739
- }
740
- if (offset !== len) {
741
- if (offset !== 0) {
742
- arg = arg.slice(offset);
743
- }
744
- ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
745
- const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
746
- const ret = encodeString(arg, view);
747
- offset += ret.written;
748
- ptr = realloc(ptr, len, offset, 1) >>> 0;
749
- }
750
- WASM_VECTOR_LEN = offset;
751
- return ptr;
752
- }
753
- function isLikeNone(x) {
754
- return x === void 0 || x === null;
755
- }
756
- var cachedDataViewMemory0 = null;
757
- function getDataViewMemory0() {
758
- if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || cachedDataViewMemory0.buffer.detached === void 0 && cachedDataViewMemory0.buffer !== wasm.memory.buffer) {
759
- cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
760
- }
761
- return cachedDataViewMemory0;
762
- }
763
- var cachedUint32ArrayMemory0 = null;
764
- function getUint32ArrayMemory0() {
765
- if (cachedUint32ArrayMemory0 === null || cachedUint32ArrayMemory0.byteLength === 0) {
766
- cachedUint32ArrayMemory0 = new Uint32Array(wasm.memory.buffer);
767
- }
768
- return cachedUint32ArrayMemory0;
769
- }
770
- function getArrayU32FromWasm0(ptr, len) {
771
- ptr = ptr >>> 0;
772
- return getUint32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
773
- }
774
- function passArray8ToWasm0(arg, malloc) {
775
- const ptr = malloc(arg.length * 1, 1) >>> 0;
776
- getUint8ArrayMemory0().set(arg, ptr / 1);
777
- WASM_VECTOR_LEN = arg.length;
778
- return ptr;
779
- }
780
- function passArray32ToWasm0(arg, malloc) {
781
- const ptr = malloc(arg.length * 4, 4) >>> 0;
782
- getUint32ArrayMemory0().set(arg, ptr / 4);
783
- WASM_VECTOR_LEN = arg.length;
784
- return ptr;
785
- }
786
- function getArrayU8FromWasm0(ptr, len) {
787
- ptr = ptr >>> 0;
788
- return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
789
- }
790
- module3.exports.get_encoding = function(encoding, extend_special_tokens) {
791
- if (wasm == null) throw new Error("tiktoken: WASM binary has not been propery initialized.");
792
- try {
793
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
794
- const ptr0 = passStringToWasm0(encoding, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
795
- const len0 = WASM_VECTOR_LEN;
796
- wasm.get_encoding(retptr, ptr0, len0, addHeapObject(extend_special_tokens));
797
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
798
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
799
- var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
800
- if (r2) {
801
- throw takeObject(r1);
802
- }
803
- return Tiktoken.__wrap(r0);
804
- } finally {
805
- wasm.__wbindgen_add_to_stack_pointer(16);
806
- }
807
- };
808
- module3.exports.encoding_for_model = function(model, extend_special_tokens) {
809
- if (wasm == null) throw new Error("tiktoken: WASM binary has not been propery initialized.");
810
- try {
811
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
812
- const ptr0 = passStringToWasm0(model, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
813
- const len0 = WASM_VECTOR_LEN;
814
- wasm.encoding_for_model(retptr, ptr0, len0, addHeapObject(extend_special_tokens));
815
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
816
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
817
- var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
818
- if (r2) {
819
- throw takeObject(r1);
820
- }
821
- return Tiktoken.__wrap(r0);
822
- } finally {
823
- wasm.__wbindgen_add_to_stack_pointer(16);
824
- }
825
- };
826
- module3.exports.get_encoding_name_for_model = function(model) {
827
- if (wasm == null) throw new Error("tiktoken: WASM binary has not been propery initialized.");
828
- let deferred3_0;
829
- let deferred3_1;
830
- try {
831
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
832
- const ptr0 = passStringToWasm0(model, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
833
- const len0 = WASM_VECTOR_LEN;
834
- wasm.get_encoding_name_for_model(retptr, ptr0, len0);
835
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
836
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
837
- var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
838
- var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
839
- var ptr2 = r0;
840
- var len2 = r1;
841
- if (r3) {
842
- ptr2 = 0;
843
- len2 = 0;
844
- throw takeObject(r2);
845
- }
846
- deferred3_0 = ptr2;
847
- deferred3_1 = len2;
848
- return getStringFromWasm0(ptr2, len2);
849
- } finally {
850
- wasm.__wbindgen_add_to_stack_pointer(16);
851
- wasm.__wbindgen_export_3(deferred3_0, deferred3_1, 1);
852
- }
853
- };
854
- var TiktokenFinalization = typeof FinalizationRegistry === "undefined" ? { register: () => {
855
- }, unregister: () => {
856
- } } : new FinalizationRegistry((ptr) => wasm.__wbg_tiktoken_free(ptr >>> 0, 1));
857
- var Tiktoken = class _Tiktoken {
858
- /**
859
- * @param {string} tiktoken_bfe
860
- * @param {any} special_tokens
861
- * @param {string} pat_str
862
- */
863
- constructor(tiktoken_bfe, special_tokens, pat_str) {
864
- if (wasm == null) throw new Error("tiktoken: WASM binary has not been propery initialized.");
865
- const ptr0 = passStringToWasm0(tiktoken_bfe, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
866
- const len0 = WASM_VECTOR_LEN;
867
- const ptr1 = passStringToWasm0(pat_str, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
868
- const len1 = WASM_VECTOR_LEN;
869
- const ret = wasm.tiktoken_new(ptr0, len0, addHeapObject(special_tokens), ptr1, len1);
870
- this.__wbg_ptr = ret >>> 0;
871
- TiktokenFinalization.register(this, this.__wbg_ptr, this);
872
- return this;
873
- }
874
- /** @returns {string | undefined} */
875
- get name() {
876
- try {
877
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
878
- wasm.tiktoken_name(retptr, this.__wbg_ptr);
879
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
880
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
881
- let v1;
882
- if (r0 !== 0) {
883
- v1 = getStringFromWasm0(r0, r1).slice();
884
- wasm.__wbindgen_export_3(r0, r1 * 1, 1);
885
- }
886
- return v1;
887
- } finally {
888
- wasm.__wbindgen_add_to_stack_pointer(16);
889
- }
890
- }
891
- static __wrap(ptr) {
892
- ptr = ptr >>> 0;
893
- const obj = Object.create(_Tiktoken.prototype);
894
- obj.__wbg_ptr = ptr;
895
- TiktokenFinalization.register(obj, obj.__wbg_ptr, obj);
896
- return obj;
897
- }
898
- __destroy_into_raw() {
899
- const ptr = this.__wbg_ptr;
900
- this.__wbg_ptr = 0;
901
- TiktokenFinalization.unregister(this);
902
- return ptr;
903
- }
904
- free() {
905
- if (wasm == null) throw new Error("tiktoken: WASM binary has not been propery initialized.");
906
- const ptr = this.__destroy_into_raw();
907
- wasm.__wbg_tiktoken_free(ptr, 0);
908
- }
909
- /**
910
- * @param {string} text
911
- * @param {any} allowed_special
912
- * @param {any} disallowed_special
913
- * @returns {Uint32Array}
914
- */
915
- encode(text3, allowed_special, disallowed_special) {
916
- if (wasm == null) throw new Error("tiktoken: WASM binary has not been propery initialized.");
917
- try {
918
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
919
- const ptr0 = passStringToWasm0(text3, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
920
- const len0 = WASM_VECTOR_LEN;
921
- wasm.tiktoken_encode(retptr, this.__wbg_ptr, ptr0, len0, addHeapObject(allowed_special), addHeapObject(disallowed_special));
922
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
923
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
924
- var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
925
- var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
926
- if (r3) {
927
- throw takeObject(r2);
928
- }
929
- var v2 = getArrayU32FromWasm0(r0, r1).slice();
930
- wasm.__wbindgen_export_3(r0, r1 * 4, 4);
931
- return v2;
932
- } finally {
933
- wasm.__wbindgen_add_to_stack_pointer(16);
934
- }
935
- }
936
- /**
937
- * @param {string} text
938
- * @returns {Uint32Array}
939
- */
940
- encode_ordinary(text3) {
941
- if (wasm == null) throw new Error("tiktoken: WASM binary has not been propery initialized.");
942
- try {
943
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
944
- const ptr0 = passStringToWasm0(text3, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
945
- const len0 = WASM_VECTOR_LEN;
946
- wasm.tiktoken_encode_ordinary(retptr, this.__wbg_ptr, ptr0, len0);
947
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
948
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
949
- var v2 = getArrayU32FromWasm0(r0, r1).slice();
950
- wasm.__wbindgen_export_3(r0, r1 * 4, 4);
951
- return v2;
952
- } finally {
953
- wasm.__wbindgen_add_to_stack_pointer(16);
954
- }
955
- }
956
- /**
957
- * @param {string} text
958
- * @param {any} allowed_special
959
- * @param {any} disallowed_special
960
- * @returns {any}
961
- */
962
- encode_with_unstable(text3, allowed_special, disallowed_special) {
963
- if (wasm == null) throw new Error("tiktoken: WASM binary has not been propery initialized.");
964
- try {
965
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
966
- const ptr0 = passStringToWasm0(text3, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
967
- const len0 = WASM_VECTOR_LEN;
968
- wasm.tiktoken_encode_with_unstable(retptr, this.__wbg_ptr, ptr0, len0, addHeapObject(allowed_special), addHeapObject(disallowed_special));
969
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
970
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
971
- var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
972
- if (r2) {
973
- throw takeObject(r1);
974
- }
975
- return takeObject(r0);
976
- } finally {
977
- wasm.__wbindgen_add_to_stack_pointer(16);
978
- }
979
- }
980
- /**
981
- * @param {Uint8Array} bytes
982
- * @returns {number}
983
- */
984
- encode_single_token(bytes) {
985
- if (wasm == null) throw new Error("tiktoken: WASM binary has not been propery initialized.");
986
- const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_export_1);
987
- const len0 = WASM_VECTOR_LEN;
988
- const ret = wasm.tiktoken_encode_single_token(this.__wbg_ptr, ptr0, len0);
989
- return ret >>> 0;
990
- }
991
- /**
992
- * @param {Uint32Array} tokens
993
- * @returns {Uint8Array}
994
- */
995
- decode(tokens) {
996
- if (wasm == null) throw new Error("tiktoken: WASM binary has not been propery initialized.");
997
- try {
998
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
999
- const ptr0 = passArray32ToWasm0(tokens, wasm.__wbindgen_export_1);
1000
- const len0 = WASM_VECTOR_LEN;
1001
- wasm.tiktoken_decode(retptr, this.__wbg_ptr, ptr0, len0);
1002
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
1003
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
1004
- var v2 = getArrayU8FromWasm0(r0, r1).slice();
1005
- wasm.__wbindgen_export_3(r0, r1 * 1, 1);
1006
- return v2;
1007
- } finally {
1008
- wasm.__wbindgen_add_to_stack_pointer(16);
1009
- }
1010
- }
1011
- /**
1012
- * @param {number} token
1013
- * @returns {Uint8Array}
1014
- */
1015
- decode_single_token_bytes(token) {
1016
- if (wasm == null) throw new Error("tiktoken: WASM binary has not been propery initialized.");
1017
- try {
1018
- const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
1019
- wasm.tiktoken_decode_single_token_bytes(retptr, this.__wbg_ptr, token);
1020
- var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
1021
- var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
1022
- var v1 = getArrayU8FromWasm0(r0, r1).slice();
1023
- wasm.__wbindgen_export_3(r0, r1 * 1, 1);
1024
- return v1;
1025
- } finally {
1026
- wasm.__wbindgen_add_to_stack_pointer(16);
1027
- }
1028
- }
1029
- /** @returns {any} */
1030
- token_byte_values() {
1031
- if (wasm == null) throw new Error("tiktoken: WASM binary has not been propery initialized.");
1032
- const ret = wasm.tiktoken_token_byte_values(this.__wbg_ptr);
1033
- return takeObject(ret);
1034
- }
1035
- };
1036
- module3.exports.Tiktoken = Tiktoken;
1037
- module3.exports.__wbg_parse_def2e24ef1252aff = function() {
1038
- return handleError(function(arg0, arg1) {
1039
- const ret = JSON.parse(getStringFromWasm0(arg0, arg1));
1040
- return addHeapObject(ret);
1041
- }, arguments);
1042
- };
1043
- module3.exports.__wbg_stringify_f7ed6987935b4a24 = function() {
1044
- return handleError(function(arg0) {
1045
- const ret = JSON.stringify(getObject(arg0));
1046
- return addHeapObject(ret);
1047
- }, arguments);
1048
- };
1049
- module3.exports.__wbindgen_error_new = function(arg0, arg1) {
1050
- const ret = new Error(getStringFromWasm0(arg0, arg1));
1051
- return addHeapObject(ret);
1052
- };
1053
- module3.exports.__wbindgen_is_undefined = function(arg0) {
1054
- const ret = getObject(arg0) === void 0;
1055
- return ret;
1056
- };
1057
- module3.exports.__wbindgen_object_drop_ref = function(arg0) {
1058
- takeObject(arg0);
1059
- };
1060
- module3.exports.__wbindgen_string_get = function(arg0, arg1) {
1061
- if (wasm == null) throw new Error("tiktoken: WASM binary has not been propery initialized.");
1062
- const obj = getObject(arg1);
1063
- const ret = typeof obj === "string" ? obj : void 0;
1064
- var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
1065
- var len1 = WASM_VECTOR_LEN;
1066
- getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
1067
- getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
1068
- };
1069
- module3.exports.__wbindgen_throw = function(arg0, arg1) {
1070
- throw new Error(getStringFromWasm0(arg0, arg1));
1071
- };
1072
- }
1073
- });
1074
-
1075
- // node_modules/tiktoken/tiktoken.cjs
1076
- var require_tiktoken = __commonJS({
1077
- "node_modules/tiktoken/tiktoken.cjs"(exports2) {
1078
- "use strict";
1079
- var wasm = require_tiktoken_bg();
1080
- var imports = {};
1081
- imports["./tiktoken_bg.js"] = wasm;
1082
- var path17 = require("path");
1083
- var fs = require("fs");
1084
- var candidates = __dirname.split(path17.sep).reduce((memo, _, index, array) => {
1085
- const prefix = array.slice(0, index + 1).join(path17.sep) + path17.sep;
1086
- if (!prefix.includes("node_modules" + path17.sep)) {
1087
- memo.unshift(
1088
- path17.join(
1089
- prefix,
1090
- "node_modules",
1091
- "tiktoken",
1092
- "",
1093
- "./tiktoken_bg.wasm"
1094
- )
1095
- );
1096
- }
1097
- return memo;
1098
- }, []);
1099
- candidates.unshift(path17.join(__dirname, "./tiktoken_bg.wasm"));
1100
- var bytes = null;
1101
- for (const candidate of candidates) {
1102
- try {
1103
- bytes = fs.readFileSync(candidate);
1104
- break;
1105
- } catch {
1106
- }
1107
- }
1108
- if (bytes == null) throw new Error("Missing tiktoken_bg.wasm");
1109
- var wasmModule = new WebAssembly.Module(bytes);
1110
- var wasmInstance = new WebAssembly.Instance(wasmModule, imports);
1111
- wasm.__wbg_set_wasm(wasmInstance.exports);
1112
- exports2["get_encoding"] = wasm["get_encoding"];
1113
- exports2["encoding_for_model"] = wasm["encoding_for_model"];
1114
- exports2["get_encoding_name_for_model"] = wasm["get_encoding_name_for_model"];
1115
- exports2["Tiktoken"] = wasm["Tiktoken"];
1116
- }
1117
- });
1118
-
1119
658
  // src/pi-extension.ts
1120
659
  var pi_extension_exports = {};
1121
660
  __export(pi_extension_exports, {
@@ -1139,7 +678,8 @@ var DEFAULT_INCLUDE = [
1139
678
  "**/*.{sh,bash,zsh}",
1140
679
  "**/*.{txt,html,htm}",
1141
680
  "**/*.zig",
1142
- "**/*.gd"
681
+ "**/*.gd",
682
+ "**/*.metal"
1143
683
  ];
1144
684
  var DEFAULT_EXCLUDE = [
1145
685
  "**/node_modules/**",
@@ -1330,6 +870,9 @@ function isValidProvider(value) {
1330
870
  return typeof value === "string" && Object.keys(EMBEDDING_MODELS).includes(value);
1331
871
  }
1332
872
  function isValidModel(value, provider) {
873
+ if (typeof value === "string" && provider === "ollama" && value.trim().length > 0) {
874
+ return true;
875
+ }
1333
876
  return typeof value === "string" && Object.keys(EMBEDDING_MODELS[provider]).includes(value);
1334
877
  }
1335
878
  function isValidScope(value) {
@@ -1529,6 +1072,9 @@ function loadOpenCodeAuth() {
1529
1072
  return {};
1530
1073
  }
1531
1074
  async function detectEmbeddingProvider(preferredProvider, model) {
1075
+ if (preferredProvider === "ollama") {
1076
+ return detectOllamaProvider(model);
1077
+ }
1532
1078
  const credentials = await getProviderCredentials(preferredProvider);
1533
1079
  if (credentials) {
1534
1080
  if (!model) {
@@ -1544,10 +1090,16 @@ async function detectEmbeddingProvider(preferredProvider, model) {
1544
1090
  );
1545
1091
  }
1546
1092
  const providerModels = EMBEDDING_MODELS[preferredProvider];
1093
+ const modelInfo = Object.values(providerModels).find((candidate) => candidate.model === model);
1094
+ if (!modelInfo) {
1095
+ throw new Error(
1096
+ `Model '${model}' is not supported by provider '${preferredProvider}'`
1097
+ );
1098
+ }
1547
1099
  return {
1548
1100
  provider: preferredProvider,
1549
1101
  credentials,
1550
- modelInfo: providerModels[model]
1102
+ modelInfo
1551
1103
  };
1552
1104
  }
1553
1105
  throw new Error(
@@ -1556,6 +1108,13 @@ async function detectEmbeddingProvider(preferredProvider, model) {
1556
1108
  }
1557
1109
  async function tryDetectProvider() {
1558
1110
  for (const provider of autoDetectProviders) {
1111
+ if (provider === "ollama") {
1112
+ const ollamaProvider = await tryDetectOllamaProvider();
1113
+ if (ollamaProvider) {
1114
+ return ollamaProvider;
1115
+ }
1116
+ continue;
1117
+ }
1559
1118
  const credentials = await getProviderCredentials(provider);
1560
1119
  if (credentials) {
1561
1120
  return {
@@ -1623,32 +1182,105 @@ function getGoogleCredentials() {
1623
1182
  }
1624
1183
  return null;
1625
1184
  }
1626
- async function getOllamaCredentials() {
1627
- const baseUrl = process.env.OLLAMA_HOST || "http://localhost:11434";
1185
+ async function fetchOllama(url, init) {
1186
+ const controller = new AbortController();
1187
+ const timeoutId = setTimeout(() => controller.abort(), 2e3);
1628
1188
  try {
1629
- const controller = new AbortController();
1630
- const timeoutId = setTimeout(() => controller.abort(), 2e3);
1631
- const response = await fetch(`${baseUrl}/api/tags`, {
1632
- signal: controller.signal
1633
- });
1189
+ return await fetch(url, { ...init, signal: controller.signal });
1190
+ } finally {
1634
1191
  clearTimeout(timeoutId);
1192
+ }
1193
+ }
1194
+ async function getOllamaCredentials() {
1195
+ const baseUrl = (process.env.OLLAMA_HOST || "http://localhost:11434").replace(/\/+$/, "");
1196
+ try {
1197
+ const response = await fetchOllama(`${baseUrl}/api/tags`);
1635
1198
  if (response.ok) {
1636
- const data = await response.json();
1637
- const hasEmbeddingModel = data.models?.some(
1638
- (m) => m.name.includes("nomic-embed") || m.name.includes("mxbai-embed") || m.name.includes("all-minilm")
1639
- );
1640
- if (hasEmbeddingModel) {
1641
- return {
1642
- provider: "ollama",
1643
- baseUrl
1644
- };
1645
- }
1199
+ return {
1200
+ provider: "ollama",
1201
+ baseUrl
1202
+ };
1646
1203
  }
1647
1204
  } catch {
1648
1205
  return null;
1649
1206
  }
1650
1207
  return null;
1651
1208
  }
1209
+ function findCatalogOllamaModel(model) {
1210
+ const stableName = model.endsWith(":latest") ? model.slice(0, -":latest".length) : model;
1211
+ return Object.values(EMBEDDING_MODELS.ollama).find((candidate) => candidate.model === stableName) ?? null;
1212
+ }
1213
+ function getPositiveIntegerMetadata(modelInfo, suffix) {
1214
+ const values = Object.entries(modelInfo).filter(([key]) => key.endsWith(suffix)).map(([, value]) => value).filter((value) => typeof value === "number" && Number.isInteger(value) && value > 0);
1215
+ return values.length === 1 ? values[0] : null;
1216
+ }
1217
+ async function fetchOllamaModelInfo(credentials, model) {
1218
+ const response = await fetchOllama(`${credentials.baseUrl}/api/show`, {
1219
+ method: "POST",
1220
+ headers: { "Content-Type": "application/json" },
1221
+ body: JSON.stringify({ model })
1222
+ });
1223
+ if (!response.ok) {
1224
+ return null;
1225
+ }
1226
+ const data = await response.json();
1227
+ if (!data.capabilities?.includes("embedding") || !data.model_info) {
1228
+ return null;
1229
+ }
1230
+ const dimensions = getPositiveIntegerMetadata(data.model_info, ".embedding_length");
1231
+ const maxTokens = getPositiveIntegerMetadata(data.model_info, ".context_length");
1232
+ if (!dimensions || !maxTokens) {
1233
+ return null;
1234
+ }
1235
+ return {
1236
+ provider: "ollama",
1237
+ model,
1238
+ dimensions,
1239
+ maxTokens,
1240
+ costPer1MTokens: 0
1241
+ };
1242
+ }
1243
+ async function listOllamaModels(credentials) {
1244
+ const response = await fetchOllama(`${credentials.baseUrl}/api/tags`);
1245
+ if (!response.ok) {
1246
+ return [];
1247
+ }
1248
+ const data = await response.json();
1249
+ return [...new Set((data.models ?? []).map((entry) => entry.name ?? entry.model).filter((name) => typeof name === "string" && name.trim().length > 0))];
1250
+ }
1251
+ async function detectOllamaProvider(model) {
1252
+ const credentials = await getOllamaCredentials();
1253
+ if (!credentials) {
1254
+ throw new Error("Preferred provider 'ollama' is not configured or authenticated");
1255
+ }
1256
+ const requestedModel = model?.trim();
1257
+ if (requestedModel) {
1258
+ const catalogModel = findCatalogOllamaModel(requestedModel);
1259
+ if (catalogModel) {
1260
+ return { provider: "ollama", credentials, modelInfo: catalogModel };
1261
+ }
1262
+ }
1263
+ const candidates = requestedModel ? [requestedModel] : await listOllamaModels(credentials);
1264
+ for (const candidate of candidates) {
1265
+ const modelInfo = await fetchOllamaModelInfo(credentials, candidate);
1266
+ if (modelInfo) {
1267
+ return {
1268
+ provider: "ollama",
1269
+ credentials,
1270
+ modelInfo: findCatalogOllamaModel(candidate) ?? modelInfo
1271
+ };
1272
+ }
1273
+ }
1274
+ const detail = model ? `Model '${model}' is not installed or is not embedding-capable` : "No installed embedding-capable Ollama model was found";
1275
+ throw new Error(detail);
1276
+ }
1277
+ async function tryDetectOllamaProvider() {
1278
+ try {
1279
+ return await detectOllamaProvider();
1280
+ } catch {
1281
+ return null;
1282
+ }
1283
+ }
1652
1284
  function getProviderDisplayName(provider) {
1653
1285
  switch (provider) {
1654
1286
  case "github-copilot":
@@ -1801,10 +1433,6 @@ function formatPrImpact(result) {
1801
1433
  var import_fs10 = require("fs");
1802
1434
  var path16 = __toESM(require("path"), 1);
1803
1435
 
1804
- // src/config/merger.ts
1805
- var import_fs5 = require("fs");
1806
- var path7 = __toESM(require("path"), 1);
1807
-
1808
1436
  // src/config/paths.ts
1809
1437
  var import_fs4 = require("fs");
1810
1438
  var os2 = __toESM(require("os"), 1);
@@ -1977,16 +1605,6 @@ function resolveWorktreeFallbackPath(projectRoot3, relativePath) {
1977
1605
  const fallbackPath = path4.join(mainRepoRoot, relativePath);
1978
1606
  return (0, import_fs4.existsSync)(fallbackPath) ? fallbackPath : null;
1979
1607
  }
1980
- function resolveWorktreeFallbackProjectIndexPath(projectRoot3, host) {
1981
- const inheritedHostPath = resolveWorktreeFallbackPath(projectRoot3, getProjectIndexRelativePath(host));
1982
- if (inheritedHostPath) {
1983
- return inheritedHostPath;
1984
- }
1985
- if (host !== "opencode") {
1986
- return resolveWorktreeFallbackPath(projectRoot3, OPENCODE_PROJECT_INDEX_RELATIVE_PATH);
1987
- }
1988
- return null;
1989
- }
1990
1608
  function getHostProjectConfigRelativePath(host) {
1991
1609
  return getProjectConfigRelativePath(host);
1992
1610
  }
@@ -2091,6 +1709,9 @@ function resolveProjectIndexPath(projectRoot3, scope, host = "opencode") {
2091
1709
  if (hasHostProjectConfig(projectRoot3, host)) {
2092
1710
  return localIndexPath;
2093
1711
  }
1712
+ if (resolveWorktreeMainRepoRoot(projectRoot3)) {
1713
+ return localIndexPath;
1714
+ }
2094
1715
  const hostFallback = resolveWorktreeFallbackPath(projectRoot3, getProjectIndexRelativePath(host));
2095
1716
  if (hostFallback) {
2096
1717
  return hostFallback;
@@ -2104,210 +1725,9 @@ function resolveProjectIndexPath(projectRoot3, scope, host = "opencode") {
2104
1725
  return localIndexPath;
2105
1726
  }
2106
1727
 
2107
- // src/config/rebase.ts
2108
- var path6 = __toESM(require("path"), 1);
2109
-
2110
- // src/utils/paths.ts
2111
- var path5 = __toESM(require("path"), 1);
2112
- function normalizePathSeparators(value) {
2113
- return value.replace(/\\/g, "/");
2114
- }
2115
- function isHiddenPathSegment(part) {
2116
- return part.startsWith(".") && part !== "." && part !== "..";
2117
- }
2118
- function isBuildPathSegment(part) {
2119
- return part.toLowerCase().includes("build");
2120
- }
2121
-
2122
- // src/config/rebase.ts
2123
- function isWithinRoot(rootDir, targetPath) {
2124
- const relativePath = path6.relative(rootDir, targetPath);
2125
- return relativePath === "" || !relativePath.startsWith("..") && !path6.isAbsolute(relativePath);
2126
- }
2127
- function resolveInheritedKnowledgeBaseEntries(values, sourceRoot, targetRoot) {
2128
- if (!Array.isArray(values)) {
2129
- return [];
2130
- }
2131
- return values.filter((value) => typeof value === "string").map((value) => {
2132
- const trimmed = value.trim();
2133
- if (!trimmed) {
2134
- return trimmed;
2135
- }
2136
- if (path6.isAbsolute(trimmed)) {
2137
- if (isWithinRoot(sourceRoot, trimmed)) {
2138
- return normalizePathSeparators(path6.normalize(path6.relative(sourceRoot, trimmed) || "."));
2139
- }
2140
- return path6.normalize(trimmed);
2141
- }
2142
- const resolvedFromSource = path6.resolve(sourceRoot, trimmed);
2143
- if (isWithinRoot(sourceRoot, resolvedFromSource)) {
2144
- return normalizePathSeparators(path6.normalize(trimmed));
2145
- }
2146
- return normalizePathSeparators(path6.normalize(path6.relative(targetRoot, resolvedFromSource)));
2147
- }).filter(Boolean);
2148
- }
2149
-
2150
- // src/config/merger.ts
2151
- var PROJECT_OVERRIDE_KEYS = [
2152
- "embeddingProvider",
2153
- "customProvider",
2154
- "embeddingModel",
2155
- "reranker",
2156
- "include",
2157
- "exclude",
2158
- "indexing",
2159
- "search",
2160
- "debug",
2161
- "scope"
2162
- ];
2163
- var MERGE_ARRAY_KEYS = ["knowledgeBases", "additionalInclude"];
2164
- function isRecord(value) {
2165
- return typeof value === "object" && value !== null && !Array.isArray(value);
2166
- }
2167
- function isStringArray2(value) {
2168
- return Array.isArray(value) && value.every((item) => typeof item === "string");
2169
- }
2170
- function applyProjectOverride(merged, normalizedProjectConfig, globalConfig, key) {
2171
- if (key in normalizedProjectConfig) {
2172
- merged[key] = normalizedProjectConfig[key];
2173
- return;
2174
- }
2175
- if (key in globalConfig) {
2176
- merged[key] = globalConfig[key];
2177
- }
2178
- }
2179
- function mergeUniqueStringArray(values) {
2180
- return [...new Set(values.map((value) => String(value).trim()))];
2181
- }
2182
- function normalizeKnowledgeBasePath(value) {
2183
- let normalized = path7.normalize(String(value).trim());
2184
- const root = path7.parse(normalized).root;
2185
- while (normalized.length > root.length && /[\\/]$/.test(normalized)) {
2186
- normalized = normalized.slice(0, -1);
2187
- }
2188
- return normalized;
2189
- }
2190
- function mergeKnowledgeBasePaths(values) {
2191
- return [...new Set(values.map((value) => normalizeKnowledgeBasePath(value)).filter((value) => value.length > 0))];
2192
- }
2193
- function validateConfigLayerShape(rawConfig, filePath) {
2194
- if (!isRecord(rawConfig)) {
2195
- throw new Error(`Config file ${filePath} must contain a JSON object at the root.`);
2196
- }
2197
- if (rawConfig.knowledgeBases !== void 0 && !isStringArray2(rawConfig.knowledgeBases)) {
2198
- throw new Error(`Config file ${filePath} field 'knowledgeBases' must be an array of strings.`);
2199
- }
2200
- if (rawConfig.additionalInclude !== void 0 && !isStringArray2(rawConfig.additionalInclude)) {
2201
- throw new Error(`Config file ${filePath} field 'additionalInclude' must be an array of strings.`);
2202
- }
2203
- if (rawConfig.include !== void 0 && !isStringArray2(rawConfig.include)) {
2204
- throw new Error(`Config file ${filePath} field 'include' must be an array of strings.`);
2205
- }
2206
- if (rawConfig.exclude !== void 0 && !isStringArray2(rawConfig.exclude)) {
2207
- throw new Error(`Config file ${filePath} field 'exclude' must be an array of strings.`);
2208
- }
2209
- for (const section of ["customProvider", "indexing", "search", "debug", "reranker"]) {
2210
- const value = rawConfig[section];
2211
- if (value !== void 0 && !isRecord(value)) {
2212
- throw new Error(`Config file ${filePath} field '${section}' must be an object.`);
2213
- }
2214
- }
2215
- return rawConfig;
2216
- }
2217
- function loadJsonFile(filePath) {
2218
- if (!(0, import_fs5.existsSync)(filePath)) {
2219
- return null;
2220
- }
2221
- try {
2222
- const content = (0, import_fs5.readFileSync)(filePath, "utf-8");
2223
- return validateConfigLayerShape(JSON.parse(content), filePath);
2224
- } catch (error) {
2225
- if (error instanceof Error && error.message.startsWith("Config file ")) {
2226
- throw error;
2227
- }
2228
- const message = error instanceof Error ? error.message : String(error);
2229
- throw new Error(`Failed to load config file ${filePath}: ${message}`);
2230
- }
2231
- }
2232
- function materializeLocalProjectConfig(projectRoot3, config, host = "opencode") {
2233
- const localConfigPath = resolveWritableProjectConfigPath(projectRoot3, host);
2234
- (0, import_fs5.mkdirSync)(path7.dirname(localConfigPath), { recursive: true });
2235
- (0, import_fs5.writeFileSync)(localConfigPath, JSON.stringify(config, null, 2), "utf-8");
2236
- return localConfigPath;
2237
- }
2238
- function loadProjectConfigLayer(projectRoot3, host = "opencode") {
2239
- const projectConfigPath = resolveProjectConfigPath(projectRoot3, host);
2240
- const projectConfig = loadJsonFile(projectConfigPath);
2241
- if (!projectConfig) {
2242
- return {};
2243
- }
2244
- const normalizedConfig = { ...projectConfig };
2245
- const projectConfigBaseDir = path7.dirname(path7.dirname(projectConfigPath));
2246
- if (Array.isArray(normalizedConfig.knowledgeBases)) {
2247
- normalizedConfig.knowledgeBases = resolveInheritedKnowledgeBaseEntries(
2248
- normalizedConfig.knowledgeBases,
2249
- projectConfigBaseDir,
2250
- projectRoot3
2251
- );
2252
- }
2253
- return normalizedConfig;
2254
- }
2255
- function loadMergedConfig(projectRoot3, host = "opencode") {
2256
- const globalConfigPath = resolveGlobalConfigPath(host);
2257
- const projectConfigPath = resolveProjectConfigPath(projectRoot3, host);
2258
- let globalConfig = null;
2259
- let globalConfigError = null;
2260
- try {
2261
- globalConfig = loadJsonFile(globalConfigPath);
2262
- } catch (error) {
2263
- globalConfigError = error instanceof Error ? error : new Error(String(error));
2264
- }
2265
- const projectConfig = loadJsonFile(projectConfigPath);
2266
- const normalizedProjectConfig = loadProjectConfigLayer(projectRoot3, host);
2267
- if (globalConfigError) {
2268
- if (!projectConfig) {
2269
- throw globalConfigError;
2270
- }
2271
- globalConfig = null;
2272
- }
2273
- if (!globalConfig && !projectConfig) {
2274
- return {};
2275
- }
2276
- if (!projectConfig && globalConfig) {
2277
- return globalConfig;
2278
- }
2279
- if (!globalConfig && projectConfig) {
2280
- return normalizedProjectConfig;
2281
- }
2282
- if (!globalConfig || !projectConfig) {
2283
- return globalConfig ?? normalizedProjectConfig;
2284
- }
2285
- const merged = { ...globalConfig };
2286
- for (const key of PROJECT_OVERRIDE_KEYS) {
2287
- applyProjectOverride(merged, normalizedProjectConfig, globalConfig, key);
2288
- }
2289
- if (projectConfig) {
2290
- for (const key of Object.keys(projectConfig)) {
2291
- if (PROJECT_OVERRIDE_KEYS.includes(key) || MERGE_ARRAY_KEYS.includes(key)) {
2292
- continue;
2293
- }
2294
- merged[key] = normalizedProjectConfig[key];
2295
- }
2296
- }
2297
- const globalKbs = globalConfig && Array.isArray(globalConfig.knowledgeBases) ? globalConfig.knowledgeBases : [];
2298
- const projectKbs = projectConfig ? Array.isArray(normalizedProjectConfig.knowledgeBases) ? normalizedProjectConfig.knowledgeBases : [] : [];
2299
- const allKbs = [...globalKbs, ...projectKbs];
2300
- merged.knowledgeBases = mergeKnowledgeBasePaths(allKbs);
2301
- const globalAdditional = globalConfig && Array.isArray(globalConfig.additionalInclude) ? globalConfig.additionalInclude : [];
2302
- const projectAdditional = projectConfig && Array.isArray(projectConfig.additionalInclude) ? projectConfig.additionalInclude : [];
2303
- const allAdditional = [...globalAdditional, ...projectAdditional];
2304
- merged.additionalInclude = mergeUniqueStringArray(allAdditional);
2305
- return merged;
2306
- }
2307
-
2308
1728
  // src/indexer/index.ts
2309
- var import_fs8 = require("fs");
2310
- var path13 = __toESM(require("path"), 1);
1729
+ var import_fs7 = require("fs");
1730
+ var path11 = __toESM(require("path"), 1);
2311
1731
  var import_perf_hooks = require("perf_hooks");
2312
1732
  var import_child_process3 = require("child_process");
2313
1733
  var import_util3 = require("util");
@@ -3658,6 +3078,7 @@ var GoogleEmbeddingProvider = class _GoogleEmbeddingProvider extends BaseEmbeddi
3658
3078
  // src/embeddings/providers/ollama.ts
3659
3079
  var OllamaEmbeddingProvider = class _OllamaEmbeddingProvider extends BaseEmbeddingProvider {
3660
3080
  static MIN_TRUNCATION_CHARS = 512;
3081
+ static REQUEST_TIMEOUT_MS = 12e4;
3661
3082
  constructor(credentials, modelInfo) {
3662
3083
  super(credentials, modelInfo);
3663
3084
  }
@@ -3732,22 +3153,45 @@ var OllamaEmbeddingProvider = class _OllamaEmbeddingProvider extends BaseEmbeddi
3732
3153
  }
3733
3154
  }
3734
3155
  async embedSingle(text3) {
3735
- const response = await fetch(`${this.credentials.baseUrl}/api/embeddings`, {
3736
- method: "POST",
3737
- headers: {
3738
- "Content-Type": "application/json"
3739
- },
3740
- body: JSON.stringify({
3741
- model: this.modelInfo.model,
3742
- prompt: text3,
3743
- truncate: false
3744
- })
3745
- });
3156
+ const controller = new AbortController();
3157
+ const timeout = setTimeout(
3158
+ () => controller.abort(),
3159
+ _OllamaEmbeddingProvider.REQUEST_TIMEOUT_MS
3160
+ );
3161
+ let response;
3162
+ try {
3163
+ response = await fetch(`${this.credentials.baseUrl}/api/embeddings`, {
3164
+ method: "POST",
3165
+ headers: {
3166
+ "Content-Type": "application/json"
3167
+ },
3168
+ body: JSON.stringify({
3169
+ model: this.modelInfo.model,
3170
+ prompt: text3,
3171
+ truncate: false
3172
+ }),
3173
+ signal: controller.signal
3174
+ });
3175
+ } catch (error) {
3176
+ if (error instanceof Error && error.name === "AbortError") {
3177
+ throw new Error(
3178
+ `Ollama embedding request timed out after ${_OllamaEmbeddingProvider.REQUEST_TIMEOUT_MS}ms`
3179
+ );
3180
+ }
3181
+ throw error;
3182
+ } finally {
3183
+ clearTimeout(timeout);
3184
+ }
3746
3185
  if (!response.ok) {
3747
3186
  const error = (await response.text()).slice(0, 500);
3748
3187
  throw new Error(`Ollama embedding API error: ${response.status} - ${error}`);
3749
3188
  }
3750
3189
  const data = await response.json();
3190
+ if (!Array.isArray(data.embedding) || data.embedding.length !== this.modelInfo.dimensions || data.embedding.some((value) => typeof value !== "number" || !Number.isFinite(value))) {
3191
+ throw new Error(
3192
+ `Ollama returned an invalid embedding; expected ${this.modelInfo.dimensions} finite dimensions`
3193
+ );
3194
+ }
3751
3195
  return {
3752
3196
  embedding: data.embedding,
3753
3197
  tokensUsed: this.estimateTokens(text3)
@@ -3894,9 +3338,23 @@ var SiliconFlowReranker = class {
3894
3338
  };
3895
3339
 
3896
3340
  // src/utils/files.ts
3897
- var import_ignore = __toESM(require_ignore(), 1);
3898
- var import_fs6 = require("fs");
3899
- var path8 = __toESM(require("path"), 1);
3341
+ var import_ignore = __toESM(require_ignore(), 1);
3342
+ var import_fs5 = require("fs");
3343
+ var path6 = __toESM(require("path"), 1);
3344
+
3345
+ // src/utils/paths.ts
3346
+ var path5 = __toESM(require("path"), 1);
3347
+ function normalizePathSeparators(value) {
3348
+ return value.replace(/\\/g, "/");
3349
+ }
3350
+ function isHiddenPathSegment(part) {
3351
+ return part.startsWith(".") && part !== "." && part !== "..";
3352
+ }
3353
+ function isBuildPathSegment(part) {
3354
+ return part.toLowerCase().includes("build");
3355
+ }
3356
+
3357
+ // src/utils/files.ts
3900
3358
  function createIgnoreFilter(projectRoot3) {
3901
3359
  const ig = (0, import_ignore.default)();
3902
3360
  const defaultIgnores = [
@@ -3918,9 +3376,9 @@ function createIgnoreFilter(projectRoot3) {
3918
3376
  "**/*build*/**"
3919
3377
  ];
3920
3378
  ig.add(defaultIgnores);
3921
- const gitignorePath = path8.join(projectRoot3, ".gitignore");
3922
- if ((0, import_fs6.existsSync)(gitignorePath)) {
3923
- const gitignoreContent = (0, import_fs6.readFileSync)(gitignorePath, "utf-8");
3379
+ const gitignorePath = path6.join(projectRoot3, ".gitignore");
3380
+ if ((0, import_fs5.existsSync)(gitignorePath)) {
3381
+ const gitignoreContent = (0, import_fs5.readFileSync)(gitignorePath, "utf-8");
3924
3382
  ig.add(gitignoreContent);
3925
3383
  }
3926
3384
  return ig;
@@ -3941,12 +3399,12 @@ function matchGlob(filePath, pattern) {
3941
3399
  return regex.test(filePath);
3942
3400
  }
3943
3401
  async function* walkDirectory(dir, projectRoot3, includePatterns, excludePatterns, ignoreFilter, maxFileSize, skipped, options, currentDepth = 0) {
3944
- const entries = await import_fs6.promises.readdir(dir, { withFileTypes: true });
3402
+ const entries = await import_fs5.promises.readdir(dir, { withFileTypes: true });
3945
3403
  const filesInDir = [];
3946
3404
  const subdirs = [];
3947
3405
  for (const entry of entries) {
3948
- const fullPath = path8.join(dir, entry.name);
3949
- const relativePath = path8.relative(projectRoot3, fullPath);
3406
+ const fullPath = path6.join(dir, entry.name);
3407
+ const relativePath = path6.relative(projectRoot3, fullPath);
3950
3408
  if (isHiddenPathSegment(entry.name)) {
3951
3409
  if (entry.isDirectory()) {
3952
3410
  skipped.push({ path: relativePath, reason: "excluded" });
@@ -3966,7 +3424,7 @@ async function* walkDirectory(dir, projectRoot3, includePatterns, excludePattern
3966
3424
  if (entry.isDirectory()) {
3967
3425
  subdirs.push({ fullPath, relativePath });
3968
3426
  } else if (entry.isFile()) {
3969
- const stat = await import_fs6.promises.stat(fullPath);
3427
+ const stat = await import_fs5.promises.stat(fullPath);
3970
3428
  if (stat.size > maxFileSize) {
3971
3429
  skipped.push({ path: relativePath, reason: "too_large" });
3972
3430
  continue;
@@ -3995,7 +3453,7 @@ async function* walkDirectory(dir, projectRoot3, includePatterns, excludePattern
3995
3453
  yield f;
3996
3454
  }
3997
3455
  for (let i = options.maxFilesPerDirectory; i < filesInDir.length; i++) {
3998
- skipped.push({ path: path8.relative(projectRoot3, filesInDir[i].path), reason: "excluded" });
3456
+ skipped.push({ path: path6.relative(projectRoot3, filesInDir[i].path), reason: "excluded" });
3999
3457
  }
4000
3458
  const canRecurse = options.maxDepth === -1 || currentDepth < options.maxDepth;
4001
3459
  if (canRecurse) {
@@ -4035,14 +3493,14 @@ async function collectFiles(projectRoot3, includePatterns, excludePatterns, maxF
4035
3493
  if (additionalRoots && additionalRoots.length > 0) {
4036
3494
  const normalizedRoots = /* @__PURE__ */ new Set();
4037
3495
  for (const kbRoot of additionalRoots) {
4038
- const resolved = path8.normalize(
4039
- path8.isAbsolute(kbRoot) ? kbRoot : path8.resolve(projectRoot3, kbRoot)
3496
+ const resolved = path6.normalize(
3497
+ path6.isAbsolute(kbRoot) ? kbRoot : path6.resolve(projectRoot3, kbRoot)
4040
3498
  );
4041
3499
  normalizedRoots.add(resolved);
4042
3500
  }
4043
3501
  for (const resolvedKbRoot of normalizedRoots) {
4044
3502
  try {
4045
- const stat = await import_fs6.promises.stat(resolvedKbRoot);
3503
+ const stat = await import_fs5.promises.stat(resolvedKbRoot);
4046
3504
  if (!stat.isDirectory()) {
4047
3505
  skipped.push({ path: resolvedKbRoot, reason: "excluded" });
4048
3506
  continue;
@@ -4383,7 +3841,7 @@ function initializeLogger(config) {
4383
3841
  }
4384
3842
 
4385
3843
  // src/native/index.ts
4386
- var path9 = __toESM(require("path"), 1);
3844
+ var path7 = __toESM(require("path"), 1);
4387
3845
  var os3 = __toESM(require("os"), 1);
4388
3846
  var module2 = __toESM(require("module"), 1);
4389
3847
  var import_url = require("url");
@@ -4408,19 +3866,19 @@ function getNativeBinding() {
4408
3866
  let currentDir;
4409
3867
  let requireTarget;
4410
3868
  if (typeof import_meta !== "undefined" && import_meta.url) {
4411
- currentDir = path9.dirname((0, import_url.fileURLToPath)(import_meta.url));
3869
+ currentDir = path7.dirname((0, import_url.fileURLToPath)(import_meta.url));
4412
3870
  requireTarget = import_meta.url;
4413
3871
  } else if (typeof __dirname !== "undefined") {
4414
3872
  currentDir = __dirname;
4415
3873
  requireTarget = __filename;
4416
3874
  } else {
4417
3875
  currentDir = process.cwd();
4418
- requireTarget = path9.join(currentDir, "index.js");
3876
+ requireTarget = path7.join(currentDir, "index.js");
4419
3877
  }
4420
3878
  const normalizedDir = currentDir.replace(/\\/g, "/");
4421
- const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(path9.join("src", "native"));
4422
- const packageRoot = isDevMode ? path9.resolve(currentDir, "../..") : path9.resolve(currentDir, "..");
4423
- const nativePath = path9.join(packageRoot, "native", bindingName);
3879
+ const isDevMode = normalizedDir.includes("/src/native") || currentDir.includes(path7.join("src", "native"));
3880
+ const packageRoot = isDevMode ? path7.resolve(currentDir, "../..") : path7.resolve(currentDir, "..");
3881
+ const nativePath = path7.join(packageRoot, "native", bindingName);
4424
3882
  const require2 = module2.createRequire(requireTarget);
4425
3883
  return require2(nativePath);
4426
3884
  }
@@ -4506,7 +3964,9 @@ function mapChunk(c) {
4506
3964
  return {
4507
3965
  content: c.content,
4508
3966
  startLine: c.startLine ?? c.start_line,
3967
+ startCol: c.startCol ?? c.start_col,
4509
3968
  endLine: c.endLine ?? c.end_line,
3969
+ endCol: c.endCol ?? c.end_col,
4510
3970
  chunkType: c.chunkType ?? c.chunk_type,
4511
3971
  name: c.name ?? void 0,
4512
3972
  language: c.language
@@ -4627,6 +4087,7 @@ function getEmbeddingHeaderParts(chunk, filePath) {
4627
4087
  javascript: "JavaScript",
4628
4088
  python: "Python",
4629
4089
  rust: "Rust",
4090
+ swift: "Swift",
4630
4091
  go: "Go",
4631
4092
  java: "Java"
4632
4093
  };
@@ -4635,7 +4096,16 @@ function getEmbeddingHeaderParts(chunk, filePath) {
4635
4096
  function: "function",
4636
4097
  arrow_function: "arrow function",
4637
4098
  method_definition: "method",
4099
+ method_declaration: "method",
4100
+ protocol_function_declaration: "protocol requirement",
4101
+ init_declaration: "initializer",
4102
+ deinit_declaration: "deinitializer",
4103
+ subscript_declaration: "subscript",
4638
4104
  class_declaration: "class",
4105
+ actor_declaration: "actor",
4106
+ extension_declaration: "extension",
4107
+ protocol_declaration: "protocol",
4108
+ struct_declaration: "struct",
4639
4109
  interface_declaration: "interface",
4640
4110
  type_alias_declaration: "type alias",
4641
4111
  enum_declaration: "enum",
@@ -5153,7 +4623,7 @@ var Database = class _Database {
5153
4623
  };
5154
4624
 
5155
4625
  // src/tools/changed-files.ts
5156
- var path10 = __toESM(require("path"), 1);
4626
+ var path8 = __toESM(require("path"), 1);
5157
4627
  var import_child_process = require("child_process");
5158
4628
  var import_util = require("util");
5159
4629
  var execFileAsync = (0, import_util.promisify)(import_child_process.execFile);
@@ -5241,8 +4711,8 @@ function normalizeFiles(rawFiles, projectRoot3) {
5241
4711
  for (const raw of rawFiles) {
5242
4712
  const trimmed = raw.trim();
5243
4713
  if (!trimmed) continue;
5244
- const absolute = path10.resolve(projectRoot3, trimmed);
5245
- const relative7 = path10.relative(projectRoot3, absolute);
4714
+ const absolute = path8.resolve(projectRoot3, trimmed);
4715
+ const relative7 = path8.relative(projectRoot3, absolute);
5246
4716
  const cleaned = relative7.startsWith("./") ? relative7.slice(2) : relative7;
5247
4717
  if (!seen.has(cleaned)) {
5248
4718
  seen.add(cleaned);
@@ -5254,7 +4724,7 @@ function normalizeFiles(rawFiles, projectRoot3) {
5254
4724
 
5255
4725
  // src/indexer/git-blame.ts
5256
4726
  var import_child_process2 = require("child_process");
5257
- var path11 = __toESM(require("path"), 1);
4727
+ var path9 = __toESM(require("path"), 1);
5258
4728
  var import_util2 = require("util");
5259
4729
  var execFileAsync2 = (0, import_util2.promisify)(import_child_process2.execFile);
5260
4730
  function parseGitBlamePorcelain(output) {
@@ -5292,7 +4762,7 @@ function parseGitBlamePorcelain(output) {
5292
4762
  return Array.from(commits.values()).filter((commit) => commit.lines > 0).sort((a, b) => b.lines - a.lines || b.committedAt - a.committedAt)[0];
5293
4763
  }
5294
4764
  async function getChunkGitBlame(projectRoot3, filePath, startLine, endLine) {
5295
- const relativePath = path11.relative(projectRoot3, filePath);
4765
+ const relativePath = path9.relative(projectRoot3, filePath);
5296
4766
  try {
5297
4767
  const { stdout } = await execFileAsync2(
5298
4768
  "git",
@@ -5307,9 +4777,9 @@ async function getChunkGitBlame(projectRoot3, filePath, startLine, endLine) {
5307
4777
 
5308
4778
  // src/indexer/index-lock.ts
5309
4779
  var import_crypto = require("crypto");
5310
- var import_fs7 = require("fs");
4780
+ var import_fs6 = require("fs");
5311
4781
  var os4 = __toESM(require("os"), 1);
5312
- var path12 = __toESM(require("path"), 1);
4782
+ var path10 = __toESM(require("path"), 1);
5313
4783
  var OWNER_FILE_NAME = "owner.json";
5314
4784
  var RECLAIM_DIRECTORY_NAME = "reclaiming";
5315
4785
  var RECOVERY_MARKER_PREFIX = "indexing.lock.recovery.";
@@ -5366,7 +4836,7 @@ function parseReclaimOwner(value) {
5366
4836
  }
5367
4837
  function readJsonDirectory(directoryPath, parser) {
5368
4838
  try {
5369
- return parser(JSON.parse((0, import_fs7.readFileSync)(path12.join(directoryPath, OWNER_FILE_NAME), "utf-8")));
4839
+ return parser(JSON.parse((0, import_fs6.readFileSync)(path10.join(directoryPath, OWNER_FILE_NAME), "utf-8")));
5370
4840
  } catch {
5371
4841
  return null;
5372
4842
  }
@@ -5382,7 +4852,7 @@ function readRecoveryOwner(markerPath) {
5382
4852
  }
5383
4853
  function readLegacyOwner(lockPath) {
5384
4854
  try {
5385
- const parsed = JSON.parse((0, import_fs7.readFileSync)(lockPath, "utf-8"));
4855
+ const parsed = JSON.parse((0, import_fs6.readFileSync)(lockPath, "utf-8"));
5386
4856
  if (!Number.isInteger(parsed.pid) || Number(parsed.pid) <= 0) return null;
5387
4857
  if (typeof parsed.startedAt !== "string" || Number.isNaN(Date.parse(parsed.startedAt))) return null;
5388
4858
  return {
@@ -5417,23 +4887,23 @@ function sameReclaimOwner(left, right) {
5417
4887
  function publishJsonDirectory(finalPath, value) {
5418
4888
  const candidatePath = `${finalPath}.candidate.${process.pid}.${(0, import_crypto.randomUUID)()}`;
5419
4889
  try {
5420
- (0, import_fs7.mkdirSync)(candidatePath, { mode: 448 });
4890
+ (0, import_fs6.mkdirSync)(candidatePath, { mode: 448 });
5421
4891
  } catch (error) {
5422
4892
  if (getErrorCode(error) === "ENOENT") return false;
5423
4893
  throw error;
5424
4894
  }
5425
4895
  try {
5426
- (0, import_fs7.writeFileSync)(path12.join(candidatePath, OWNER_FILE_NAME), JSON.stringify(value), {
4896
+ (0, import_fs6.writeFileSync)(path10.join(candidatePath, OWNER_FILE_NAME), JSON.stringify(value), {
5427
4897
  encoding: "utf-8",
5428
4898
  flag: "wx",
5429
4899
  mode: 384
5430
4900
  });
5431
- if ((0, import_fs7.existsSync)(finalPath)) return false;
4901
+ if ((0, import_fs6.existsSync)(finalPath)) return false;
5432
4902
  try {
5433
- (0, import_fs7.renameSync)(candidatePath, finalPath);
4903
+ (0, import_fs6.renameSync)(candidatePath, finalPath);
5434
4904
  return true;
5435
4905
  } catch (error) {
5436
- if ((0, import_fs7.existsSync)(finalPath)) return false;
4906
+ if ((0, import_fs6.existsSync)(finalPath)) return false;
5437
4907
  if (getErrorCode(error) === "ENOENT") return false;
5438
4908
  throw error;
5439
4909
  }
@@ -5441,7 +4911,7 @@ function publishJsonDirectory(finalPath, value) {
5441
4911
  if (getErrorCode(error) === "ENOENT") return false;
5442
4912
  throw error;
5443
4913
  } finally {
5444
- if ((0, import_fs7.existsSync)(candidatePath)) (0, import_fs7.rmSync)(candidatePath, { recursive: true, force: true });
4914
+ if ((0, import_fs6.existsSync)(candidatePath)) (0, import_fs6.rmSync)(candidatePath, { recursive: true, force: true });
5445
4915
  }
5446
4916
  }
5447
4917
  function createOwner(operation) {
@@ -5454,7 +4924,7 @@ function createOwner(operation) {
5454
4924
  };
5455
4925
  }
5456
4926
  function recoveryMarkerPath(indexPath, owner) {
5457
- return path12.join(indexPath, `${RECOVERY_MARKER_PREFIX}${owner.token}`);
4927
+ return path10.join(indexPath, `${RECOVERY_MARKER_PREFIX}${owner.token}`);
5458
4928
  }
5459
4929
  function publishRecoveryMarker(indexPath, owner) {
5460
4930
  const markerPath = recoveryMarkerPath(indexPath, owner);
@@ -5468,16 +4938,16 @@ function publishRecoveryMarker(indexPath, owner) {
5468
4938
  }
5469
4939
  function getPendingRecoveries(indexPath) {
5470
4940
  const recoveries = [];
5471
- const markerNames = (0, import_fs7.readdirSync)(indexPath).filter((name) => {
4941
+ const markerNames = (0, import_fs6.readdirSync)(indexPath).filter((name) => {
5472
4942
  if (!name.startsWith(RECOVERY_MARKER_PREFIX)) return false;
5473
4943
  return UUID_PATTERN.test(name.slice(RECOVERY_MARKER_PREFIX.length));
5474
4944
  }).sort();
5475
4945
  for (const markerName of markerNames) {
5476
- const markerPath = path12.join(indexPath, markerName);
4946
+ const markerPath = path10.join(indexPath, markerName);
5477
4947
  const markerToken = markerName.slice(RECOVERY_MARKER_PREFIX.length);
5478
4948
  let markerStats;
5479
4949
  try {
5480
- markerStats = (0, import_fs7.lstatSync)(markerPath);
4950
+ markerStats = (0, import_fs6.lstatSync)(markerPath);
5481
4951
  } catch (error) {
5482
4952
  if (getErrorCode(error) === "ENOENT") continue;
5483
4953
  throw error;
@@ -5499,17 +4969,17 @@ function getPendingRecoveries(indexPath) {
5499
4969
  }
5500
4970
  function cleanupDeadPublicationCandidates(indexPath) {
5501
4971
  const candidatePattern = /^indexing\.lock(?:\.recovery\.[0-9a-f-]{36})?\.candidate\.(\d+)\.[0-9a-f-]{36}$/i;
5502
- for (const entry of (0, import_fs7.readdirSync)(indexPath)) {
4972
+ for (const entry of (0, import_fs6.readdirSync)(indexPath)) {
5503
4973
  const match = candidatePattern.exec(entry);
5504
4974
  if (!match) continue;
5505
4975
  const pid = Number(match[1]);
5506
4976
  if (!Number.isInteger(pid) || pid <= 0) continue;
5507
4977
  if (getOwnerLiveness({ pid, hostname: os4.hostname() }) !== "dead") continue;
5508
- (0, import_fs7.rmSync)(path12.join(indexPath, entry), { recursive: true, force: true });
4978
+ (0, import_fs6.rmSync)(path10.join(indexPath, entry), { recursive: true, force: true });
5509
4979
  }
5510
4980
  }
5511
4981
  function removeDeadReclaimMarker(lockPath, expectedOwner) {
5512
- const markerPath = path12.join(lockPath, RECLAIM_DIRECTORY_NAME);
4982
+ const markerPath = path10.join(lockPath, RECLAIM_DIRECTORY_NAME);
5513
4983
  const marker = readReclaimOwner(markerPath);
5514
4984
  if (!marker || marker.expectedOwnerToken !== expectedOwner.token || getOwnerLiveness(marker) !== "dead") {
5515
4985
  return false;
@@ -5520,7 +4990,7 @@ function removeDeadReclaimMarker(lockPath, expectedOwner) {
5520
4990
  }
5521
4991
  const claimedMarkerPath = `${markerPath}.stale.${marker.pid}.${marker.token}.${(0, import_crypto.randomUUID)()}`;
5522
4992
  try {
5523
- (0, import_fs7.renameSync)(markerPath, claimedMarkerPath);
4993
+ (0, import_fs6.renameSync)(markerPath, claimedMarkerPath);
5524
4994
  } catch (error) {
5525
4995
  if (getErrorCode(error) === "ENOENT") return false;
5526
4996
  throw error;
@@ -5528,16 +4998,16 @@ function removeDeadReclaimMarker(lockPath, expectedOwner) {
5528
4998
  const claimedMarker = readReclaimOwner(claimedMarkerPath);
5529
4999
  const ownerAfterClaim = readDirectoryOwner(lockPath);
5530
5000
  if (!claimedMarker || !sameReclaimOwner(claimedMarker, marker) || !ownerAfterClaim || !sameOwner(ownerAfterClaim, expectedOwner) || getOwnerLiveness(ownerAfterClaim) !== "dead") {
5531
- if (!(0, import_fs7.existsSync)(markerPath) && (0, import_fs7.existsSync)(claimedMarkerPath)) {
5532
- (0, import_fs7.renameSync)(claimedMarkerPath, markerPath);
5001
+ if (!(0, import_fs6.existsSync)(markerPath) && (0, import_fs6.existsSync)(claimedMarkerPath)) {
5002
+ (0, import_fs6.renameSync)(claimedMarkerPath, markerPath);
5533
5003
  }
5534
5004
  return false;
5535
5005
  }
5536
- (0, import_fs7.rmSync)(claimedMarkerPath, { recursive: true, force: true });
5006
+ (0, import_fs6.rmSync)(claimedMarkerPath, { recursive: true, force: true });
5537
5007
  return true;
5538
5008
  }
5539
5009
  function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
5540
- const reclaimPath = path12.join(lockPath, RECLAIM_DIRECTORY_NAME);
5010
+ const reclaimPath = path10.join(lockPath, RECLAIM_DIRECTORY_NAME);
5541
5011
  const reclaimOwner = {
5542
5012
  pid: process.pid,
5543
5013
  hostname: os4.hostname(),
@@ -5563,8 +5033,8 @@ function reclaimDeadOwner(indexPath, lockPath, expectedOwner) {
5563
5033
  return false;
5564
5034
  }
5565
5035
  const quarantinePath = `${lockPath}.stale.${expectedOwner.token}.${reclaimOwner.token}`;
5566
- (0, import_fs7.renameSync)(lockPath, quarantinePath);
5567
- (0, import_fs7.rmSync)(quarantinePath, { recursive: true, force: true });
5036
+ (0, import_fs6.renameSync)(lockPath, quarantinePath);
5037
+ (0, import_fs6.rmSync)(quarantinePath, { recursive: true, force: true });
5568
5038
  return true;
5569
5039
  } catch (error) {
5570
5040
  if (getErrorCode(error) === "ENOENT") return false;
@@ -5589,9 +5059,9 @@ function isIndexLockContentionError(error) {
5589
5059
  return error instanceof IndexLockContentionError || typeof error === "object" && error !== null && "code" in error && error.code === "INDEX_BUSY";
5590
5060
  }
5591
5061
  function acquireIndexLock(indexPath, operation) {
5592
- (0, import_fs7.mkdirSync)(indexPath, { recursive: true });
5593
- const canonicalIndexPath = import_fs7.realpathSync.native(indexPath);
5594
- const lockPath = path12.join(canonicalIndexPath, "indexing.lock");
5062
+ (0, import_fs6.mkdirSync)(indexPath, { recursive: true });
5063
+ const canonicalIndexPath = import_fs6.realpathSync.native(indexPath);
5064
+ const lockPath = path10.join(canonicalIndexPath, "indexing.lock");
5595
5065
  cleanupDeadPublicationCandidates(canonicalIndexPath);
5596
5066
  for (let attempt = 0; attempt < 6; attempt += 1) {
5597
5067
  const owner = createOwner(operation);
@@ -5612,7 +5082,7 @@ function acquireIndexLock(indexPath, operation) {
5612
5082
  }
5613
5083
  let stats;
5614
5084
  try {
5615
- stats = (0, import_fs7.lstatSync)(lockPath);
5085
+ stats = (0, import_fs6.lstatSync)(lockPath);
5616
5086
  } catch (error) {
5617
5087
  if (getErrorCode(error) === "ENOENT") continue;
5618
5088
  throw error;
@@ -5640,78 +5110,44 @@ function releaseIndexLock(lease) {
5640
5110
  if (!currentOwner || !sameOwner(currentOwner, lease.owner)) return false;
5641
5111
  const releasePath = `${lease.lockPath}.release.${lease.owner.pid}.${lease.owner.token}`;
5642
5112
  try {
5643
- retryTransientFilesystemOperation(() => (0, import_fs7.renameSync)(lease.lockPath, releasePath));
5113
+ retryTransientFilesystemOperation(() => (0, import_fs6.renameSync)(lease.lockPath, releasePath));
5644
5114
  } catch (error) {
5645
5115
  if (getErrorCode(error) === "ENOENT") return false;
5646
5116
  throw error;
5647
5117
  }
5648
5118
  const claimedOwner = readDirectoryOwner(releasePath);
5649
5119
  if (!claimedOwner || !sameOwner(claimedOwner, lease.owner)) {
5650
- if (!(0, import_fs7.existsSync)(lease.lockPath) && (0, import_fs7.existsSync)(releasePath)) {
5651
- (0, import_fs7.renameSync)(releasePath, lease.lockPath);
5120
+ if (!(0, import_fs6.existsSync)(lease.lockPath) && (0, import_fs6.existsSync)(releasePath)) {
5121
+ (0, import_fs6.renameSync)(releasePath, lease.lockPath);
5652
5122
  }
5653
5123
  return false;
5654
5124
  }
5655
5125
  try {
5656
- retryTransientFilesystemOperation(() => (0, import_fs7.rmSync)(releasePath, { recursive: true, force: true }));
5126
+ retryTransientFilesystemOperation(() => (0, import_fs6.rmSync)(releasePath, { recursive: true, force: true }));
5657
5127
  } catch (error) {
5658
5128
  console.error(`[codebase-index] Lease released but tombstone cleanup failed: ${releasePath}`, error);
5659
5129
  }
5660
5130
  return true;
5661
5131
  }
5662
- async function withIndexLock(indexPath, operation, callback, options = {}) {
5663
- const lease = acquireIndexLock(indexPath, operation);
5664
- let result;
5665
- let callbackError;
5666
- let callbackFailed = false;
5667
- try {
5668
- result = await callback(lease);
5669
- } catch (error) {
5670
- callbackFailed = true;
5671
- callbackError = error;
5672
- }
5673
- if (!callbackFailed && options.completeRecoveries !== false) {
5674
- try {
5675
- completeLeaseRecovery(lease);
5676
- } catch (error) {
5677
- callbackFailed = true;
5678
- callbackError = error;
5679
- }
5680
- }
5681
- let releaseError;
5682
- try {
5683
- if (!releaseIndexLock(lease)) {
5684
- releaseError = new Error(`Lost ownership of index mutation lease ${lease.owner.token}`);
5685
- }
5686
- } catch (error) {
5687
- releaseError = error;
5688
- }
5689
- if (releaseError !== void 0) {
5690
- if (callbackFailed) throw new AggregateError([callbackError, releaseError], "Index mutation and lease release both failed");
5691
- throw releaseError;
5692
- }
5693
- if (callbackFailed) throw callbackError;
5694
- return result;
5695
- }
5696
5132
  function createLeaseTemporaryPath(targetPath, owner, kind = "tmp") {
5697
5133
  if (kind === "bak") return `${targetPath}.bak.${owner.pid}.${owner.token}`;
5698
5134
  temporaryCounter += 1;
5699
5135
  return `${targetPath}.tmp.${owner.pid}.${owner.token}.${temporaryCounter}`;
5700
5136
  }
5701
5137
  function removeLeaseTemporaryPath(temporaryPath) {
5702
- if ((0, import_fs7.existsSync)(temporaryPath)) (0, import_fs7.rmSync)(temporaryPath, { recursive: true, force: true });
5138
+ if ((0, import_fs6.existsSync)(temporaryPath)) (0, import_fs6.rmSync)(temporaryPath, { recursive: true, force: true });
5703
5139
  }
5704
5140
  function recoverLeaseArtifacts(indexPath, owner, backupTargets) {
5705
5141
  for (const targetPath of backupTargets) {
5706
5142
  const backupPath = createLeaseTemporaryPath(targetPath, owner, "bak");
5707
- if (!(0, import_fs7.existsSync)(backupPath)) continue;
5708
- if ((0, import_fs7.existsSync)(targetPath)) (0, import_fs7.rmSync)(targetPath, { recursive: true, force: true });
5709
- (0, import_fs7.renameSync)(backupPath, targetPath);
5143
+ if (!(0, import_fs6.existsSync)(backupPath)) continue;
5144
+ if ((0, import_fs6.existsSync)(targetPath)) (0, import_fs6.rmSync)(targetPath, { recursive: true, force: true });
5145
+ (0, import_fs6.renameSync)(backupPath, targetPath);
5710
5146
  }
5711
5147
  const temporaryOwnerMarker = `.tmp.${owner.pid}.${owner.token}.`;
5712
- for (const entry of (0, import_fs7.readdirSync)(indexPath)) {
5148
+ for (const entry of (0, import_fs6.readdirSync)(indexPath)) {
5713
5149
  if (!entry.includes(temporaryOwnerMarker)) continue;
5714
- (0, import_fs7.rmSync)(path12.join(indexPath, entry), { recursive: true, force: true });
5150
+ (0, import_fs6.rmSync)(path10.join(indexPath, entry), { recursive: true, force: true });
5715
5151
  }
5716
5152
  }
5717
5153
  function completeLeaseRecovery(lease) {
@@ -5722,13 +5158,23 @@ function completeLeaseRecovery(lease) {
5722
5158
  }
5723
5159
  }
5724
5160
  for (const recovery of lease.recoveries) {
5725
- (0, import_fs7.rmSync)(recovery.markerPath, { recursive: true, force: true });
5161
+ (0, import_fs6.rmSync)(recovery.markerPath, { recursive: true, force: true });
5726
5162
  }
5727
5163
  }
5728
5164
 
5729
5165
  // src/indexer/index.ts
5730
- var CALL_GRAPH_LANGUAGES = /* @__PURE__ */ new Set(["typescript", "tsx", "javascript", "jsx", "python", "go", "rust", "php", "apex", "zig", "gdscript", "matlab", "bash"]);
5731
- var CASE_INSENSITIVE_LANGUAGES = /* @__PURE__ */ new Set(["apex"]);
5166
+ var CALL_GRAPH_LANGUAGES = /* @__PURE__ */ new Set(["typescript", "tsx", "javascript", "jsx", "python", "go", "rust", "swift", "php", "apex", "zig", "gdscript", "matlab", "bash", "c", "cpp", "metal"]);
5167
+ var CASE_INSENSITIVE_LANGUAGES = /* @__PURE__ */ new Set(["apex", "php"]);
5168
+ var CALL_GRAPH_RESOLUTION_VERSION = "4";
5169
+ var PHP_FUNCTION_SYMBOL_CHUNK_TYPES = /* @__PURE__ */ new Set([
5170
+ "function_declaration",
5171
+ "function",
5172
+ "function_definition"
5173
+ ]);
5174
+ var PHP_CLASS_SYMBOL_CHUNK_TYPES = /* @__PURE__ */ new Set([
5175
+ "class_declaration",
5176
+ "class_definition"
5177
+ ]);
5732
5178
  var CALL_GRAPH_SYMBOL_CHUNK_TYPES = /* @__PURE__ */ new Set([
5733
5179
  "function_declaration",
5734
5180
  "function",
@@ -5741,6 +5187,9 @@ var CALL_GRAPH_SYMBOL_CHUNK_TYPES = /* @__PURE__ */ new Set([
5741
5187
  "enum_declaration",
5742
5188
  "function_definition",
5743
5189
  "class_definition",
5190
+ "class_specifier",
5191
+ "struct_specifier",
5192
+ "namespace_definition",
5744
5193
  "decorated_definition",
5745
5194
  "method_declaration",
5746
5195
  "type_declaration",
@@ -5756,6 +5205,14 @@ var CALL_GRAPH_SYMBOL_CHUNK_TYPES = /* @__PURE__ */ new Set([
5756
5205
  "test_declaration",
5757
5206
  "struct_declaration",
5758
5207
  "union_declaration",
5208
+ // Synthetic Swift declarations or declarations specific to tree-sitter-swift.
5209
+ "actor_declaration",
5210
+ "extension_declaration",
5211
+ "protocol_declaration",
5212
+ "protocol_function_declaration",
5213
+ "init_declaration",
5214
+ "deinit_declaration",
5215
+ "subscript_declaration",
5759
5216
  // GDScript declarations whose names participate in the call graph.
5760
5217
  // `function_definition` and `class_definition` are already in the set
5761
5218
  // above (shared with Python/C/Bash and Python, respectively).
@@ -5765,6 +5222,53 @@ var CALL_GRAPH_SYMBOL_CHUNK_TYPES = /* @__PURE__ */ new Set([
5765
5222
  "const_statement",
5766
5223
  "class_name_statement"
5767
5224
  ]);
5225
+ var C_FAMILY_TYPE_SYMBOL_CHUNK_TYPES = /* @__PURE__ */ new Set(["class_specifier", "struct_specifier"]);
5226
+ function isCompatibleCFamilyCallTarget(language, callType, symbolKind) {
5227
+ if (language !== "c" && language !== "cpp") return true;
5228
+ if (symbolKind === "namespace_definition") return callType === "Import";
5229
+ const isTypeSymbol = C_FAMILY_TYPE_SYMBOL_CHUNK_TYPES.has(symbolKind);
5230
+ if (callType === "Constructor" || callType === "Inherits" || callType === "Implements") {
5231
+ return isTypeSymbol;
5232
+ }
5233
+ return !isTypeSymbol;
5234
+ }
5235
+ var EXECUTABLE_SYMBOL_CHUNK_TYPES = /* @__PURE__ */ new Set([
5236
+ "function_declaration",
5237
+ "function",
5238
+ "arrow_function",
5239
+ "method_definition",
5240
+ "function_definition",
5241
+ "method_declaration",
5242
+ "function_item",
5243
+ "protocol_function_declaration",
5244
+ "init_declaration",
5245
+ "deinit_declaration",
5246
+ "subscript_declaration",
5247
+ "constructor_definition",
5248
+ "trigger_declaration",
5249
+ "test_declaration"
5250
+ ]);
5251
+ function findEnclosingSymbol(symbols, line, column) {
5252
+ let best;
5253
+ for (const symbol of symbols) {
5254
+ if (line < symbol.startLine || line > symbol.endLine) continue;
5255
+ if (column !== void 0 && (line === symbol.startLine && column < symbol.startCol || line === symbol.endLine && column >= symbol.endCol)) {
5256
+ continue;
5257
+ }
5258
+ if (!best) {
5259
+ best = symbol;
5260
+ continue;
5261
+ }
5262
+ const span = symbol.endLine - symbol.startLine;
5263
+ const bestSpan = best.endLine - best.startLine;
5264
+ const isNarrowerPositionRange = column !== void 0 && span === bestSpan && symbol.startLine === best.startLine && symbol.endLine === best.endLine && symbol.startCol >= best.startCol && symbol.endCol <= best.endCol && (symbol.startCol > best.startCol || symbol.endCol < best.endCol);
5265
+ const isMoreSpecificTie = span === bestSpan && symbol.startLine === best.startLine && EXECUTABLE_SYMBOL_CHUNK_TYPES.has(symbol.kind) && !EXECUTABLE_SYMBOL_CHUNK_TYPES.has(best.kind);
5266
+ if (span < bestSpan || span === bestSpan && symbol.startLine > best.startLine || isNarrowerPositionRange || isMoreSpecificTie) {
5267
+ best = symbol;
5268
+ }
5269
+ }
5270
+ return best;
5271
+ }
5768
5272
  function float32ArrayToBuffer(arr) {
5769
5273
  const float32 = new Float32Array(arr);
5770
5274
  return Buffer.from(float32.buffer);
@@ -5849,6 +5353,8 @@ function hasBlameMetadata(metadata) {
5849
5353
  }
5850
5354
  var INDEX_METADATA_VERSION = "1";
5851
5355
  var EMBEDDING_STRATEGY_VERSION = "2";
5356
+ var SWIFT_PARSER_VERSION = "1";
5357
+ var METAL_PARSER_VERSION = "1";
5852
5358
  var RANKING_TOKEN_CACHE_LIMIT = 4096;
5853
5359
  var RANK_HYBRID_CACHE_LIMIT = 256;
5854
5360
  function createPendingChunkStorageText(texts) {
@@ -6005,9 +5511,9 @@ function hasAllEmbeddingParts(parts, expectedPartCount) {
6005
5511
  return true;
6006
5512
  }
6007
5513
  function isPathWithinRoot(filePath, rootPath) {
6008
- const normalizedFilePath = path13.resolve(filePath);
6009
- const normalizedRoot = path13.resolve(rootPath);
6010
- return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${path13.sep}`);
5514
+ const normalizedFilePath = path11.resolve(filePath);
5515
+ const normalizedRoot = path11.resolve(rootPath);
5516
+ return normalizedFilePath === normalizedRoot || normalizedFilePath.startsWith(`${normalizedRoot}${path11.sep}`);
6011
5517
  }
6012
5518
  var rankingQueryTokenCache = /* @__PURE__ */ new Map();
6013
5519
  var rankingNameTokenCache = /* @__PURE__ */ new Map();
@@ -6171,15 +5677,25 @@ function chunkTypeBoost(chunkType) {
6171
5677
  case "function_declaration":
6172
5678
  case "method":
6173
5679
  case "method_definition":
5680
+ case "method_declaration":
5681
+ case "protocol_function_declaration":
5682
+ case "init_declaration":
5683
+ case "deinit_declaration":
5684
+ case "subscript_declaration":
6174
5685
  case "class":
6175
5686
  case "class_declaration":
5687
+ case "actor_declaration":
5688
+ case "extension_declaration":
6176
5689
  return 0.2;
6177
5690
  case "interface":
6178
5691
  case "type":
6179
5692
  case "enum":
5693
+ case "enum_declaration":
6180
5694
  case "struct":
5695
+ case "struct_declaration":
6181
5696
  case "impl":
6182
5697
  case "trait":
5698
+ case "protocol_declaration":
6183
5699
  case "module":
6184
5700
  return 0.1;
6185
5701
  default:
@@ -6286,11 +5802,21 @@ function isImplementationChunkType(chunkType) {
6286
5802
  "function_declaration",
6287
5803
  "method",
6288
5804
  "method_definition",
5805
+ "method_declaration",
5806
+ "protocol_function_declaration",
5807
+ "init_declaration",
5808
+ "deinit_declaration",
5809
+ "subscript_declaration",
6289
5810
  "class",
6290
5811
  "class_declaration",
5812
+ "actor_declaration",
5813
+ "extension_declaration",
6291
5814
  "interface",
5815
+ "protocol_declaration",
6292
5816
  "type",
6293
5817
  "enum",
5818
+ "enum_declaration",
5819
+ "struct_declaration",
6294
5820
  "module"
6295
5821
  ].includes(chunkType);
6296
5822
  }
@@ -7107,24 +6633,24 @@ var Indexer = class {
7107
6633
  this.config = config;
7108
6634
  this.host = host;
7109
6635
  this.indexPath = this.getIndexPath();
7110
- this.fileHashCachePath = path13.join(this.indexPath, "file-hashes.json");
7111
- this.failedBatchesPath = path13.join(this.indexPath, "failed-batches.json");
6636
+ this.fileHashCachePath = path11.join(this.indexPath, "file-hashes.json");
6637
+ this.failedBatchesPath = path11.join(this.indexPath, "failed-batches.json");
7112
6638
  this.logger = initializeLogger(config.debug);
7113
6639
  }
7114
6640
  getIndexPath() {
7115
6641
  return resolveProjectIndexPath(this.projectRoot, this.config.scope, this.host);
7116
6642
  }
7117
6643
  isLocalProjectIndexPath() {
7118
- const localProjectIndexPaths = [path13.join(this.projectRoot, getHostProjectIndexRelativePath(this.host))];
6644
+ const localProjectIndexPaths = [path11.join(this.projectRoot, getHostProjectIndexRelativePath(this.host))];
7119
6645
  if (this.host !== "opencode") {
7120
- localProjectIndexPaths.push(path13.join(this.projectRoot, getHostProjectIndexRelativePath("opencode")));
6646
+ localProjectIndexPaths.push(path11.join(this.projectRoot, getHostProjectIndexRelativePath("opencode")));
7121
6647
  }
7122
6648
  return localProjectIndexPaths.some((localPath) => {
7123
- if (!(0, import_fs8.existsSync)(localPath) || !(0, import_fs8.existsSync)(this.indexPath)) {
7124
- return path13.resolve(this.indexPath) === path13.resolve(localPath);
6649
+ if (!(0, import_fs7.existsSync)(localPath) || !(0, import_fs7.existsSync)(this.indexPath)) {
6650
+ return path11.resolve(this.indexPath) === path11.resolve(localPath);
7125
6651
  }
7126
- const indexStats = (0, import_fs8.statSync)(this.indexPath);
7127
- const localStats = (0, import_fs8.statSync)(localPath);
6652
+ const indexStats = (0, import_fs7.statSync)(this.indexPath);
6653
+ const localStats = (0, import_fs7.statSync)(localPath);
7128
6654
  return indexStats.dev === localStats.dev && indexStats.ino === localStats.ino;
7129
6655
  });
7130
6656
  }
@@ -7163,8 +6689,8 @@ var Indexer = class {
7163
6689
  async withIndexMutationLease(operation, callback) {
7164
6690
  const lease = acquireIndexLock(this.indexPath, operation);
7165
6691
  this.indexPath = lease.canonicalIndexPath;
7166
- this.fileHashCachePath = path13.join(this.indexPath, "file-hashes.json");
7167
- this.failedBatchesPath = path13.join(this.indexPath, "failed-batches.json");
6692
+ this.fileHashCachePath = path11.join(this.indexPath, "file-hashes.json");
6693
+ this.failedBatchesPath = path11.join(this.indexPath, "failed-batches.json");
7168
6694
  this.activeIndexLease = lease;
7169
6695
  let result;
7170
6696
  let callbackError;
@@ -7198,7 +6724,7 @@ var Indexer = class {
7198
6724
  } catch (error) {
7199
6725
  releaseError = error;
7200
6726
  this.writerArtifactFingerprint = null;
7201
- if (!(0, import_fs8.existsSync)(lease.lockPath) && this.activeIndexLease?.owner.token === lease.owner.token) {
6727
+ if (!(0, import_fs7.existsSync)(lease.lockPath) && this.activeIndexLease?.owner.token === lease.owner.token) {
7202
6728
  this.activeIndexLease = null;
7203
6729
  }
7204
6730
  }
@@ -7216,11 +6742,11 @@ var Indexer = class {
7216
6742
  return this.activeIndexLease;
7217
6743
  }
7218
6744
  loadFileHashCache() {
7219
- if (!(0, import_fs8.existsSync)(this.fileHashCachePath)) {
6745
+ if (!(0, import_fs7.existsSync)(this.fileHashCachePath)) {
7220
6746
  return;
7221
6747
  }
7222
6748
  try {
7223
- const data = (0, import_fs8.readFileSync)(this.fileHashCachePath, "utf-8");
6749
+ const data = (0, import_fs7.readFileSync)(this.fileHashCachePath, "utf-8");
7224
6750
  const parsed = JSON.parse(data);
7225
6751
  this.fileHashCache = new Map(Object.entries(parsed));
7226
6752
  } catch (error) {
@@ -7242,24 +6768,24 @@ var Indexer = class {
7242
6768
  atomicWriteSync(targetPath, data) {
7243
6769
  const lease = this.requireActiveLease();
7244
6770
  const tempPath = createLeaseTemporaryPath(targetPath, lease.owner, "tmp");
7245
- (0, import_fs8.mkdirSync)(path13.dirname(targetPath), { recursive: true });
6771
+ (0, import_fs7.mkdirSync)(path11.dirname(targetPath), { recursive: true });
7246
6772
  try {
7247
- (0, import_fs8.writeFileSync)(tempPath, data);
7248
- (0, import_fs8.renameSync)(tempPath, targetPath);
6773
+ (0, import_fs7.writeFileSync)(tempPath, data);
6774
+ (0, import_fs7.renameSync)(tempPath, targetPath);
7249
6775
  } finally {
7250
6776
  removeLeaseTemporaryPath(tempPath);
7251
6777
  }
7252
6778
  }
7253
6779
  saveInvertedIndex(invertedIndex) {
7254
6780
  this.atomicWriteSync(
7255
- path13.join(this.indexPath, "inverted-index.json"),
6781
+ path11.join(this.indexPath, "inverted-index.json"),
7256
6782
  invertedIndex.serialize()
7257
6783
  );
7258
6784
  }
7259
6785
  getScopedRoots() {
7260
- const roots = /* @__PURE__ */ new Set([path13.resolve(this.projectRoot)]);
6786
+ const roots = /* @__PURE__ */ new Set([path11.resolve(this.projectRoot)]);
7261
6787
  for (const kbRoot of this.config.knowledgeBases) {
7262
- roots.add(path13.resolve(this.projectRoot, kbRoot));
6788
+ roots.add(path11.resolve(this.projectRoot, kbRoot));
7263
6789
  }
7264
6790
  return Array.from(roots);
7265
6791
  }
@@ -7268,31 +6794,54 @@ var Indexer = class {
7268
6794
  if (this.config.scope !== "global") {
7269
6795
  return branchName;
7270
6796
  }
7271
- const projectHash = hashContent(path13.resolve(this.projectRoot)).slice(0, 16);
6797
+ const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
7272
6798
  return `${projectHash}:${branchName}`;
7273
6799
  }
7274
6800
  getBranchCatalogKeyFor(branchName) {
7275
6801
  if (this.config.scope !== "global") {
7276
6802
  return branchName;
7277
6803
  }
7278
- const projectHash = hashContent(path13.resolve(this.projectRoot)).slice(0, 16);
6804
+ const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
7279
6805
  return `${projectHash}:${branchName}`;
7280
6806
  }
7281
6807
  getLegacyBranchCatalogKey() {
7282
6808
  return this.currentBranch || "default";
7283
6809
  }
7284
6810
  getLegacyMigrationMetadataKey() {
7285
- const projectHash = hashContent(path13.resolve(this.projectRoot)).slice(0, 16);
6811
+ const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
7286
6812
  return `index.globalBranchMigration.${projectHash}`;
7287
6813
  }
7288
6814
  getProjectEmbeddingStrategyMetadataKey() {
7289
- const projectHash = hashContent(path13.resolve(this.projectRoot)).slice(0, 16);
6815
+ const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
7290
6816
  return `index.embeddingStrategyVersion.${projectHash}`;
7291
6817
  }
7292
6818
  getProjectForceReembedMetadataKey() {
7293
- const projectHash = hashContent(path13.resolve(this.projectRoot)).slice(0, 16);
6819
+ const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
7294
6820
  return `index.forceReembed.${projectHash}`;
7295
6821
  }
6822
+ getCallGraphResolutionMetadataKey() {
6823
+ if (this.config.scope !== "global") {
6824
+ return "index.callGraphResolutionVersion";
6825
+ }
6826
+ const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
6827
+ return `index.callGraphResolutionVersion.${projectHash}`;
6828
+ }
6829
+ getSwiftParserVersionMetadataKey() {
6830
+ const key = "index.parser.swiftVersion";
6831
+ if (this.config.scope !== "global") {
6832
+ return key;
6833
+ }
6834
+ const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
6835
+ return `${key}.${projectHash}`;
6836
+ }
6837
+ getMetalParserVersionMetadataKey() {
6838
+ const key = "index.parser.metalVersion";
6839
+ if (this.config.scope !== "global") {
6840
+ return key;
6841
+ }
6842
+ const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
6843
+ return `${key}.${projectHash}`;
6844
+ }
7296
6845
  hasProjectForceReembedPending() {
7297
6846
  return this.config.scope === "global" && this.database?.getMetadata(this.getProjectForceReembedMetadataKey()) === "true";
7298
6847
  }
@@ -7384,7 +6933,7 @@ var Indexer = class {
7384
6933
  if (!this.database) {
7385
6934
  return { chunkIds, symbolIds };
7386
6935
  }
7387
- const projectRootPath = path13.resolve(this.projectRoot);
6936
+ const projectRootPath = path11.resolve(this.projectRoot);
7388
6937
  const projectLocalFilePaths = /* @__PURE__ */ new Set([
7389
6938
  ...Array.from(this.fileHashCache.keys()).filter(
7390
6939
  (filePath) => this.isFileInCurrentScope(filePath, roots) && isPathWithinRoot(filePath, projectRootPath)
@@ -7407,7 +6956,7 @@ var Indexer = class {
7407
6956
  if (this.config.scope !== "global") {
7408
6957
  return this.getBranchCatalogCleanupKeys();
7409
6958
  }
7410
- const projectHash = hashContent(path13.resolve(this.projectRoot)).slice(0, 16);
6959
+ const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
7411
6960
  const keys = /* @__PURE__ */ new Set();
7412
6961
  const projectChunkIdSet = new Set(projectChunkIds);
7413
6962
  const projectSymbolIdSet = new Set(projectSymbolIds);
@@ -7491,7 +7040,7 @@ var Indexer = class {
7491
7040
  if (!this.database || this.config.scope !== "global") {
7492
7041
  return false;
7493
7042
  }
7494
- const projectHash = hashContent(path13.resolve(this.projectRoot)).slice(0, 16);
7043
+ const projectHash = hashContent(path11.resolve(this.projectRoot)).slice(0, 16);
7495
7044
  const roots = this.getScopedRoots();
7496
7045
  const { chunkIds: projectLocalChunkIds, symbolIds: projectLocalSymbolIds } = this.getProjectLocalScopedOwnershipIds(roots);
7497
7046
  return this.database.getAllBranches().some(
@@ -7525,7 +7074,7 @@ var Indexer = class {
7525
7074
  ...Array.from(this.fileHashCache.keys()).filter((filePath) => this.isFileInCurrentScope(filePath, roots)),
7526
7075
  ...scopedEntries.map(({ metadata }) => metadata.filePath)
7527
7076
  ]);
7528
- const projectRootPath = path13.resolve(this.projectRoot);
7077
+ const projectRootPath = path11.resolve(this.projectRoot);
7529
7078
  const projectLocalFilePaths = new Set(
7530
7079
  Array.from(filePaths).filter((filePath) => isPathWithinRoot(filePath, projectRootPath))
7531
7080
  );
@@ -7603,8 +7152,8 @@ var Indexer = class {
7603
7152
  });
7604
7153
  }
7605
7154
  if (this.config.scope === "global") {
7606
- if ((0, import_fs8.existsSync)(this.fileHashCachePath)) {
7607
- (0, import_fs8.unlinkSync)(this.fileHashCachePath);
7155
+ if ((0, import_fs7.existsSync)(this.fileHashCachePath)) {
7156
+ (0, import_fs7.unlinkSync)(this.fileHashCachePath);
7608
7157
  }
7609
7158
  await this.healthCheckUnlocked();
7610
7159
  }
@@ -7623,10 +7172,10 @@ var Indexer = class {
7623
7172
  }
7624
7173
  }
7625
7174
  loadSerializedFailedBatches() {
7626
- if (!(0, import_fs8.existsSync)(this.failedBatchesPath)) {
7175
+ if (!(0, import_fs7.existsSync)(this.failedBatchesPath)) {
7627
7176
  return [];
7628
7177
  }
7629
- const data = (0, import_fs8.readFileSync)(this.failedBatchesPath, "utf-8");
7178
+ const data = (0, import_fs7.readFileSync)(this.failedBatchesPath, "utf-8");
7630
7179
  const parsed = JSON.parse(data);
7631
7180
  return parsed.map((batch) => {
7632
7181
  const chunks = Array.isArray(batch.chunks) ? batch.chunks : [];
@@ -7643,9 +7192,9 @@ var Indexer = class {
7643
7192
  }
7644
7193
  saveFailedBatches(batches) {
7645
7194
  if (batches.length === 0) {
7646
- if ((0, import_fs8.existsSync)(this.failedBatchesPath)) {
7195
+ if ((0, import_fs7.existsSync)(this.failedBatchesPath)) {
7647
7196
  try {
7648
- (0, import_fs8.unlinkSync)(this.failedBatchesPath);
7197
+ (0, import_fs7.unlinkSync)(this.failedBatchesPath);
7649
7198
  } catch {
7650
7199
  }
7651
7200
  }
@@ -7831,7 +7380,7 @@ var Indexer = class {
7831
7380
  const intent = isLikelyImplementationPath(candidate.metadata.filePath) ? "implementation" : "doc_or_test";
7832
7381
  parts.push(`intent_hint: ${intent}`);
7833
7382
  try {
7834
- const fileContent = await import_fs8.promises.readFile(candidate.metadata.filePath, "utf-8");
7383
+ const fileContent = await import_fs7.promises.readFile(candidate.metadata.filePath, "utf-8");
7835
7384
  const lines = fileContent.split("\n");
7836
7385
  const snippetStartLine = Math.max(1, candidate.metadata.startLine - 2);
7837
7386
  const snippetEndLine = Math.min(lines.length, candidate.metadata.endLine + 2);
@@ -7925,7 +7474,7 @@ var Indexer = class {
7925
7474
  }
7926
7475
  getReaderFileFingerprint(filePath, identityOnly = false) {
7927
7476
  try {
7928
- const stats = (0, import_fs8.statSync)(filePath);
7477
+ const stats = (0, import_fs7.statSync)(filePath);
7929
7478
  if (identityOnly) {
7930
7479
  return `${stats.dev}:${stats.ino}`;
7931
7480
  }
@@ -7935,12 +7484,12 @@ var Indexer = class {
7935
7484
  }
7936
7485
  }
7937
7486
  captureReaderArtifactFingerprint() {
7938
- const storePath = path13.join(this.indexPath, "vectors");
7487
+ const storePath = path11.join(this.indexPath, "vectors");
7939
7488
  return {
7940
7489
  vectors: `${this.getReaderFileFingerprint(storePath)}|${this.getReaderFileFingerprint(`${storePath}.meta.json`)}`,
7941
- keyword: this.getReaderFileFingerprint(path13.join(this.indexPath, "inverted-index.json")),
7942
- database: this.getReaderFileFingerprint(path13.join(this.indexPath, "codebase.db")),
7943
- databaseIdentity: this.getReaderFileFingerprint(path13.join(this.indexPath, "codebase.db"), true)
7490
+ keyword: this.getReaderFileFingerprint(path11.join(this.indexPath, "inverted-index.json")),
7491
+ database: this.getReaderFileFingerprint(path11.join(this.indexPath, "codebase.db")),
7492
+ databaseIdentity: this.getReaderFileFingerprint(path11.join(this.indexPath, "codebase.db"), true)
7944
7493
  };
7945
7494
  }
7946
7495
  refreshReaderArtifacts() {
@@ -7965,13 +7514,13 @@ var Indexer = class {
7965
7514
  issues.set(component, this.createReadIssue(component, message));
7966
7515
  this.readerArtifactRetryAfter.set(component, Date.now() + READER_ARTIFACT_RETRY_INTERVAL_MS);
7967
7516
  };
7968
- const storePath = path13.join(this.indexPath, "vectors");
7517
+ const storePath = path11.join(this.indexPath, "vectors");
7969
7518
  const vectorMetadataPath = `${storePath}.meta.json`;
7970
- const invertedIndexPath = path13.join(this.indexPath, "inverted-index.json");
7971
- const dbPath = path13.join(this.indexPath, "codebase.db");
7519
+ const invertedIndexPath = path11.join(this.indexPath, "inverted-index.json");
7520
+ const dbPath = path11.join(this.indexPath, "codebase.db");
7972
7521
  if (vectorsChanged || retryDue("vectors")) {
7973
- const vectorStoreExists = (0, import_fs8.existsSync)(storePath);
7974
- const vectorMetadataExists = (0, import_fs8.existsSync)(vectorMetadataPath);
7522
+ const vectorStoreExists = (0, import_fs7.existsSync)(storePath);
7523
+ const vectorMetadataExists = (0, import_fs7.existsSync)(vectorMetadataPath);
7975
7524
  if (vectorStoreExists && vectorMetadataExists) {
7976
7525
  try {
7977
7526
  const store = new VectorStore(storePath, this.configuredProviderInfo.modelInfo.dimensions);
@@ -7986,8 +7535,8 @@ var Indexer = class {
7986
7535
  setIssue("vectors", this.getVectorReadIssueMessage());
7987
7536
  }
7988
7537
  }
7989
- if (keywordChanged || retryDue("keyword") || !(0, import_fs8.existsSync)(invertedIndexPath) && (this.store?.count() ?? 0) > 0) {
7990
- if ((0, import_fs8.existsSync)(invertedIndexPath)) {
7538
+ if (keywordChanged || retryDue("keyword") || !(0, import_fs7.existsSync)(invertedIndexPath) && (this.store?.count() ?? 0) > 0) {
7539
+ if ((0, import_fs7.existsSync)(invertedIndexPath)) {
7991
7540
  try {
7992
7541
  const invertedIndex = new InvertedIndex(invertedIndexPath);
7993
7542
  invertedIndex.load();
@@ -8002,7 +7551,7 @@ var Indexer = class {
8002
7551
  }
8003
7552
  }
8004
7553
  if (databaseReplaced || databaseChanged && issues.has("database") || retryDue("database")) {
8005
- if ((0, import_fs8.existsSync)(dbPath)) {
7554
+ if ((0, import_fs7.existsSync)(dbPath)) {
8006
7555
  try {
8007
7556
  const database = Database.openReadOnly(dbPath);
8008
7557
  if (this.database) {
@@ -8093,14 +7642,14 @@ var Indexer = class {
8093
7642
  }
8094
7643
  }
8095
7644
  const dimensions = this.configuredProviderInfo.modelInfo.dimensions;
8096
- const storePath = path13.join(this.indexPath, "vectors");
7645
+ const storePath = path11.join(this.indexPath, "vectors");
8097
7646
  const vectorMetadataPath = `${storePath}.meta.json`;
8098
- const invertedIndexPath = path13.join(this.indexPath, "inverted-index.json");
8099
- const dbPath = path13.join(this.indexPath, "codebase.db");
8100
- let dbIsNew = !(0, import_fs8.existsSync)(dbPath);
7647
+ const invertedIndexPath = path11.join(this.indexPath, "inverted-index.json");
7648
+ const dbPath = path11.join(this.indexPath, "codebase.db");
7649
+ let dbIsNew = !(0, import_fs7.existsSync)(dbPath);
8101
7650
  const readerArtifactFingerprint = mode === "reader" ? this.captureReaderArtifactFingerprint() : null;
8102
7651
  if (mode === "writer") {
8103
- await import_fs8.promises.mkdir(this.indexPath, { recursive: true });
7652
+ await import_fs7.promises.mkdir(this.indexPath, { recursive: true });
8104
7653
  if (recoveredOwners.length > 0 && this.config.scope === "project" && !this.isLocalProjectIndexPath()) {
8105
7654
  throw new Error(
8106
7655
  "Interrupted indexing recovery is unsafe while using an inherited worktree index. Run index_codebase with force=true to create a local project index boundary."
@@ -8116,15 +7665,15 @@ var Indexer = class {
8116
7665
  await this.resetLocalIndexArtifacts();
8117
7666
  }
8118
7667
  this.store = new VectorStore(storePath, dimensions);
8119
- if ((0, import_fs8.existsSync)(storePath) || (0, import_fs8.existsSync)(vectorMetadataPath)) {
7668
+ if ((0, import_fs7.existsSync)(storePath) || (0, import_fs7.existsSync)(vectorMetadataPath)) {
8120
7669
  this.store.load();
8121
7670
  }
8122
7671
  this.invertedIndex = new InvertedIndex(invertedIndexPath);
8123
7672
  try {
8124
7673
  this.invertedIndex.load();
8125
7674
  } catch {
8126
- if ((0, import_fs8.existsSync)(invertedIndexPath)) {
8127
- await import_fs8.promises.unlink(invertedIndexPath);
7675
+ if ((0, import_fs7.existsSync)(invertedIndexPath)) {
7676
+ await import_fs7.promises.unlink(invertedIndexPath);
8128
7677
  }
8129
7678
  this.invertedIndex = new InvertedIndex(invertedIndexPath);
8130
7679
  }
@@ -8141,8 +7690,8 @@ var Indexer = class {
8141
7690
  }
8142
7691
  } else {
8143
7692
  this.store = new VectorStore(storePath, dimensions);
8144
- const vectorStoreExists = (0, import_fs8.existsSync)(storePath);
8145
- const vectorMetadataExists = (0, import_fs8.existsSync)(vectorMetadataPath);
7693
+ const vectorStoreExists = (0, import_fs7.existsSync)(storePath);
7694
+ const vectorMetadataExists = (0, import_fs7.existsSync)(vectorMetadataPath);
8146
7695
  const vectorReadFailureMessage = this.getVectorReadIssueMessage();
8147
7696
  if (vectorStoreExists !== vectorMetadataExists) {
8148
7697
  this.recordReadIssue("vectors", vectorReadFailureMessage);
@@ -8155,7 +7704,7 @@ var Indexer = class {
8155
7704
  }
8156
7705
  }
8157
7706
  this.invertedIndex = new InvertedIndex(invertedIndexPath);
8158
- if ((0, import_fs8.existsSync)(invertedIndexPath)) {
7707
+ if ((0, import_fs7.existsSync)(invertedIndexPath)) {
8159
7708
  try {
8160
7709
  this.invertedIndex.load();
8161
7710
  } catch (error) {
@@ -8169,7 +7718,7 @@ var Indexer = class {
8169
7718
  } else if (this.store.count() > 0) {
8170
7719
  this.recordReadIssue("keyword", this.getKeywordReadIssueMessage());
8171
7720
  }
8172
- if ((0, import_fs8.existsSync)(dbPath)) {
7721
+ if ((0, import_fs7.existsSync)(dbPath)) {
8173
7722
  try {
8174
7723
  this.database = Database.openReadOnly(dbPath);
8175
7724
  } catch (error) {
@@ -8260,7 +7809,7 @@ var Indexer = class {
8260
7809
  if (await this.tryResetCorruptedIndex("running automatic orphan garbage collection", error)) {
8261
7810
  return {
8262
7811
  resetCorruptedIndex: true,
8263
- warning: this.getCorruptedIndexWarning(path13.join(this.indexPath, "codebase.db"))
7812
+ warning: this.getCorruptedIndexWarning(path11.join(this.indexPath, "codebase.db"))
8264
7813
  };
8265
7814
  }
8266
7815
  throw error;
@@ -8275,7 +7824,7 @@ var Indexer = class {
8275
7824
  return;
8276
7825
  }
8277
7826
  const retainedEntries = store.getAllMetadata().filter(({ key }) => !excludedSet.has(key));
8278
- const storeBasePath = path13.join(this.indexPath, "vectors");
7827
+ const storeBasePath = path11.join(this.indexPath, "vectors");
8279
7828
  const storeIndexPath = storeBasePath;
8280
7829
  const storeMetadataPath = `${storeBasePath}.meta.json`;
8281
7830
  const lease = this.requireActiveLease();
@@ -8285,19 +7834,19 @@ var Indexer = class {
8285
7834
  let backedUpMetadata = false;
8286
7835
  let rebuiltCount = 0;
8287
7836
  let skippedCount = 0;
8288
- if ((0, import_fs8.existsSync)(backupIndexPath)) {
8289
- (0, import_fs8.unlinkSync)(backupIndexPath);
7837
+ if ((0, import_fs7.existsSync)(backupIndexPath)) {
7838
+ (0, import_fs7.unlinkSync)(backupIndexPath);
8290
7839
  }
8291
- if ((0, import_fs8.existsSync)(backupMetadataPath)) {
8292
- (0, import_fs8.unlinkSync)(backupMetadataPath);
7840
+ if ((0, import_fs7.existsSync)(backupMetadataPath)) {
7841
+ (0, import_fs7.unlinkSync)(backupMetadataPath);
8293
7842
  }
8294
7843
  try {
8295
- if ((0, import_fs8.existsSync)(storeIndexPath)) {
8296
- (0, import_fs8.renameSync)(storeIndexPath, backupIndexPath);
7844
+ if ((0, import_fs7.existsSync)(storeIndexPath)) {
7845
+ (0, import_fs7.renameSync)(storeIndexPath, backupIndexPath);
8297
7846
  backedUpIndex = true;
8298
7847
  }
8299
- if ((0, import_fs8.existsSync)(storeMetadataPath)) {
8300
- (0, import_fs8.renameSync)(storeMetadataPath, backupMetadataPath);
7848
+ if ((0, import_fs7.existsSync)(storeMetadataPath)) {
7849
+ (0, import_fs7.renameSync)(storeMetadataPath, backupMetadataPath);
8301
7850
  backedUpMetadata = true;
8302
7851
  }
8303
7852
  store.clear();
@@ -8317,11 +7866,11 @@ var Indexer = class {
8317
7866
  rebuiltCount += 1;
8318
7867
  }
8319
7868
  store.save();
8320
- if (backedUpIndex && (0, import_fs8.existsSync)(backupIndexPath)) {
8321
- (0, import_fs8.unlinkSync)(backupIndexPath);
7869
+ if (backedUpIndex && (0, import_fs7.existsSync)(backupIndexPath)) {
7870
+ (0, import_fs7.unlinkSync)(backupIndexPath);
8322
7871
  }
8323
- if (backedUpMetadata && (0, import_fs8.existsSync)(backupMetadataPath)) {
8324
- (0, import_fs8.unlinkSync)(backupMetadataPath);
7872
+ if (backedUpMetadata && (0, import_fs7.existsSync)(backupMetadataPath)) {
7873
+ (0, import_fs7.unlinkSync)(backupMetadataPath);
8325
7874
  }
8326
7875
  this.logger.gc("info", "Rebuilt vector store to avoid native remove", {
8327
7876
  excludedChunks: excludedSet.size,
@@ -8333,17 +7882,17 @@ var Indexer = class {
8333
7882
  store.clear();
8334
7883
  } catch {
8335
7884
  }
8336
- if ((0, import_fs8.existsSync)(storeIndexPath)) {
8337
- (0, import_fs8.unlinkSync)(storeIndexPath);
7885
+ if ((0, import_fs7.existsSync)(storeIndexPath)) {
7886
+ (0, import_fs7.unlinkSync)(storeIndexPath);
8338
7887
  }
8339
- if ((0, import_fs8.existsSync)(storeMetadataPath)) {
8340
- (0, import_fs8.unlinkSync)(storeMetadataPath);
7888
+ if ((0, import_fs7.existsSync)(storeMetadataPath)) {
7889
+ (0, import_fs7.unlinkSync)(storeMetadataPath);
8341
7890
  }
8342
- if (backedUpIndex && (0, import_fs8.existsSync)(backupIndexPath)) {
8343
- (0, import_fs8.renameSync)(backupIndexPath, storeIndexPath);
7891
+ if (backedUpIndex && (0, import_fs7.existsSync)(backupIndexPath)) {
7892
+ (0, import_fs7.renameSync)(backupIndexPath, storeIndexPath);
8344
7893
  }
8345
- if (backedUpMetadata && (0, import_fs8.existsSync)(backupMetadataPath)) {
8346
- (0, import_fs8.renameSync)(backupMetadataPath, storeMetadataPath);
7894
+ if (backedUpMetadata && (0, import_fs7.existsSync)(backupMetadataPath)) {
7895
+ (0, import_fs7.renameSync)(backupMetadataPath, storeMetadataPath);
8347
7896
  }
8348
7897
  if (backedUpIndex || backedUpMetadata) {
8349
7898
  store.load();
@@ -8370,24 +7919,24 @@ var Indexer = class {
8370
7919
  this.readerArtifactRetryAfter.clear();
8371
7920
  this.fileHashCache.clear();
8372
7921
  const resetPaths = [
8373
- path13.join(this.indexPath, "codebase.db"),
8374
- path13.join(this.indexPath, "codebase.db-shm"),
8375
- path13.join(this.indexPath, "codebase.db-wal"),
8376
- path13.join(this.indexPath, "vectors"),
8377
- path13.join(this.indexPath, "vectors.usearch"),
8378
- path13.join(this.indexPath, "vectors.meta.json"),
8379
- path13.join(this.indexPath, "inverted-index.json"),
8380
- path13.join(this.indexPath, "file-hashes.json"),
8381
- path13.join(this.indexPath, "failed-batches.json")
7922
+ path11.join(this.indexPath, "codebase.db"),
7923
+ path11.join(this.indexPath, "codebase.db-shm"),
7924
+ path11.join(this.indexPath, "codebase.db-wal"),
7925
+ path11.join(this.indexPath, "vectors"),
7926
+ path11.join(this.indexPath, "vectors.usearch"),
7927
+ path11.join(this.indexPath, "vectors.meta.json"),
7928
+ path11.join(this.indexPath, "inverted-index.json"),
7929
+ path11.join(this.indexPath, "file-hashes.json"),
7930
+ path11.join(this.indexPath, "failed-batches.json")
8382
7931
  ];
8383
- await Promise.all(resetPaths.map((targetPath) => import_fs8.promises.rm(targetPath, { recursive: true, force: true })));
8384
- await import_fs8.promises.mkdir(this.indexPath, { recursive: true });
7932
+ await Promise.all(resetPaths.map((targetPath) => import_fs7.promises.rm(targetPath, { recursive: true, force: true })));
7933
+ await import_fs7.promises.mkdir(this.indexPath, { recursive: true });
8385
7934
  }
8386
7935
  async tryResetCorruptedIndex(stage, error) {
8387
7936
  if (!isSqliteCorruptionError(error)) {
8388
7937
  return false;
8389
7938
  }
8390
- const dbPath = path13.join(this.indexPath, "codebase.db");
7939
+ const dbPath = path11.join(this.indexPath, "codebase.db");
8391
7940
  const warning = this.getCorruptedIndexWarning(dbPath);
8392
7941
  const errorMessage = getErrorMessage2(error);
8393
7942
  if (this.config.scope === "global") {
@@ -8453,6 +8002,7 @@ var Indexer = class {
8453
8002
  this.database.setMetadata("index.embeddingProvider", provider.provider);
8454
8003
  this.database.setMetadata("index.embeddingModel", provider.modelInfo.model);
8455
8004
  this.database.setMetadata("index.embeddingDimensions", provider.modelInfo.dimensions.toString());
8005
+ this.database.setMetadata(this.getCallGraphResolutionMetadataKey(), CALL_GRAPH_RESOLUTION_VERSION);
8456
8006
  if (this.config.scope === "global") {
8457
8007
  if (completeProjectEmbeddingStrategyReset) {
8458
8008
  this.database.setMetadata(this.getProjectEmbeddingStrategyMetadataKey(), EMBEDDING_STRATEGY_VERSION);
@@ -8640,6 +8190,20 @@ var Indexer = class {
8640
8190
  totalChunks: 0
8641
8191
  });
8642
8192
  this.loadFileHashCache();
8193
+ const swiftParserMetadataKey = this.getSwiftParserVersionMetadataKey();
8194
+ const reparseCachedSwiftFiles = database.getMetadata(swiftParserMetadataKey) !== SWIFT_PARSER_VERSION;
8195
+ const metalParserMetadataKey = this.getMetalParserVersionMetadataKey();
8196
+ const reparseCachedMetalFiles = database.getMetadata(metalParserMetadataKey) !== METAL_PARSER_VERSION;
8197
+ if (reparseCachedSwiftFiles && Array.from(this.fileHashCache.keys()).some(
8198
+ (filePath) => path11.extname(filePath).toLowerCase() === ".swift"
8199
+ )) {
8200
+ this.logger.info("Reindexing cached Swift files for parser support");
8201
+ }
8202
+ if (reparseCachedMetalFiles && Array.from(this.fileHashCache.keys()).some(
8203
+ (filePath) => path11.extname(filePath).toLowerCase() === ".metal"
8204
+ )) {
8205
+ this.logger.info("Reindexing cached Metal files for parser support");
8206
+ }
8643
8207
  const includePatterns = [...this.config.include, ...this.config.additionalInclude];
8644
8208
  const { files, skipped } = await collectFiles(
8645
8209
  this.projectRoot,
@@ -8659,14 +8223,21 @@ var Indexer = class {
8659
8223
  const changedFiles = [];
8660
8224
  const unchangedFilePaths = /* @__PURE__ */ new Set();
8661
8225
  const currentFileHashes = /* @__PURE__ */ new Map();
8226
+ const needsCallGraphResolutionMigration = database.getMetadata(this.getCallGraphResolutionMetadataKey()) !== CALL_GRAPH_RESOLUTION_VERSION;
8662
8227
  for (const f of files) {
8663
8228
  const currentHash = hashFile(f.path);
8664
8229
  currentFileHashes.set(f.path, currentHash);
8665
- if (this.fileHashCache.get(f.path) === currentHash) {
8230
+ const cachedHashMatches = this.fileHashCache.get(f.path) === currentHash;
8231
+ const needsCallGraphRefresh = cachedHashMatches && needsCallGraphResolutionMigration && database.getChunksByFile(f.path).some(
8232
+ (chunk) => chunk.language === "php" || chunk.language === "c" || chunk.language === "cpp"
8233
+ );
8234
+ const requiresSwiftParserUpgrade = reparseCachedSwiftFiles && path11.extname(f.path).toLowerCase() === ".swift";
8235
+ const requiresMetalParserUpgrade = reparseCachedMetalFiles && path11.extname(f.path).toLowerCase() === ".metal";
8236
+ if (cachedHashMatches && !needsCallGraphRefresh && !requiresSwiftParserUpgrade && !requiresMetalParserUpgrade) {
8666
8237
  unchangedFilePaths.add(f.path);
8667
8238
  this.logger.recordCacheHit();
8668
8239
  } else {
8669
- const content = await import_fs8.promises.readFile(f.path, "utf-8");
8240
+ const content = await import_fs7.promises.readFile(f.path, "utf-8");
8670
8241
  changedFiles.push({ path: f.path, content, hash: currentHash });
8671
8242
  this.logger.recordCacheMiss();
8672
8243
  }
@@ -8764,7 +8335,7 @@ var Indexer = class {
8764
8335
  for (const parsed of parsedFiles) {
8765
8336
  currentFilePaths.add(parsed.path);
8766
8337
  if (parsed.chunks.length === 0) {
8767
- const relativePath = path13.relative(this.projectRoot, parsed.path);
8338
+ const relativePath = path11.relative(this.projectRoot, parsed.path);
8768
8339
  stats.parseFailures.push(relativePath);
8769
8340
  }
8770
8341
  let chunksToProcess = parsed.chunks;
@@ -8864,16 +8435,28 @@ var Indexer = class {
8864
8435
  const fileSymbols = [];
8865
8436
  for (const chunk of parsed.chunks) {
8866
8437
  if (!chunk.name || !CALL_GRAPH_SYMBOL_CHUNK_TYPES.has(chunk.chunkType)) continue;
8867
- const symbolId = `sym_${hashContent(parsed.path + ":" + chunk.name + ":" + chunk.chunkType + ":" + chunk.startLine).slice(0, 16)}`;
8438
+ const existingMetalSymbol = chunk.language === "metal" ? fileSymbols.find(
8439
+ (symbol2) => symbol2.name === chunk.name && symbol2.kind === chunk.chunkType && symbol2.startLine <= chunk.endLine && chunk.startLine <= symbol2.endLine
8440
+ ) : void 0;
8441
+ if (existingMetalSymbol) {
8442
+ existingMetalSymbol.startLine = Math.min(existingMetalSymbol.startLine, chunk.startLine);
8443
+ existingMetalSymbol.endLine = Math.max(existingMetalSymbol.endLine, chunk.endLine);
8444
+ existingMetalSymbol.startCol = Math.min(existingMetalSymbol.startCol, chunk.startCol ?? 0);
8445
+ existingMetalSymbol.endCol = Math.max(existingMetalSymbol.endCol, chunk.endCol ?? 0);
8446
+ continue;
8447
+ }
8448
+ const symbolId = `sym_${hashContent(
8449
+ parsed.path + ":" + chunk.name + ":" + chunk.chunkType + ":" + chunk.startLine + ":" + (chunk.startCol ?? 0)
8450
+ ).slice(0, 16)}`;
8868
8451
  const symbol = {
8869
8452
  id: symbolId,
8870
8453
  filePath: parsed.path,
8871
8454
  name: chunk.name,
8872
8455
  kind: chunk.chunkType,
8873
8456
  startLine: chunk.startLine,
8874
- startCol: 0,
8457
+ startCol: chunk.startCol ?? 0,
8875
8458
  endLine: chunk.endLine,
8876
- endCol: 0,
8459
+ endCol: chunk.endCol ?? 0,
8877
8460
  language: chunk.language
8878
8461
  };
8879
8462
  fileSymbols.push(symbol);
@@ -8898,8 +8481,10 @@ var Indexer = class {
8898
8481
  if (callSites.length === 0) continue;
8899
8482
  const edges = [];
8900
8483
  for (const site of callSites) {
8901
- const enclosingSymbol = fileSymbols.find(
8902
- (sym) => site.line >= sym.startLine && site.line <= sym.endLine
8484
+ const enclosingSymbol = findEnclosingSymbol(
8485
+ fileSymbols,
8486
+ site.line,
8487
+ site.column
8903
8488
  );
8904
8489
  if (!enclosingSymbol) continue;
8905
8490
  const edgeId = `edge_${hashContent(enclosingSymbol.id + ":" + site.calleeName + ":" + site.line + ":" + site.column).slice(0, 16)}`;
@@ -8918,7 +8503,21 @@ var Indexer = class {
8918
8503
  if (edges.length > 0) {
8919
8504
  database.upsertCallEdgesBatch(edges);
8920
8505
  for (const edge of edges) {
8921
- const candidates = symbolsByName.get(normalizeSymbolKey(edge.targetName));
8506
+ let candidates = symbolsByName.get(normalizeSymbolKey(edge.targetName));
8507
+ if (fileLanguage === "php" && candidates) {
8508
+ if (edge.callType === "Constructor") {
8509
+ candidates = candidates.filter(
8510
+ (candidate) => PHP_CLASS_SYMBOL_CHUNK_TYPES.has(candidate.kind)
8511
+ );
8512
+ } else if (edge.callType === "Call") {
8513
+ candidates = candidates.filter(
8514
+ (candidate) => PHP_FUNCTION_SYMBOL_CHUNK_TYPES.has(candidate.kind)
8515
+ );
8516
+ }
8517
+ }
8518
+ candidates = candidates?.filter(
8519
+ (symbol) => isCompatibleCFamilyCallTarget(fileLanguage, edge.callType, symbol.kind)
8520
+ );
8922
8521
  if (candidates && candidates.length === 1) {
8923
8522
  database.resolveCallEdge(edge.id, candidates[0].id);
8924
8523
  }
@@ -8960,8 +8559,8 @@ var Indexer = class {
8960
8559
  database.addChunksToBranchBatch(branchCatalogKey, Array.from(currentChunkIds));
8961
8560
  database.clearBranchSymbols(branchCatalogKey);
8962
8561
  database.addSymbolsToBranchBatch(branchCatalogKey, Array.from(allSymbolIds));
8963
- const vectorPath = path13.join(this.indexPath, "vectors");
8964
- const shouldFingerprintLegacyPair = !store.hasFingerprint() && (0, import_fs8.existsSync)(vectorPath) && (0, import_fs8.existsSync)(`${vectorPath}.meta.json`);
8562
+ const vectorPath = path11.join(this.indexPath, "vectors");
8563
+ const shouldFingerprintLegacyPair = !store.hasFingerprint() && (0, import_fs7.existsSync)(vectorPath) && (0, import_fs7.existsSync)(`${vectorPath}.meta.json`);
8965
8564
  if (backfilledBlameMetadata || shouldFingerprintLegacyPair) {
8966
8565
  store.save();
8967
8566
  }
@@ -8973,6 +8572,8 @@ var Indexer = class {
8973
8572
  this.saveFileHashCache();
8974
8573
  this.saveFailedBatches([]);
8975
8574
  }
8575
+ database.setMetadata(swiftParserMetadataKey, SWIFT_PARSER_VERSION);
8576
+ database.setMetadata(metalParserMetadataKey, METAL_PARSER_VERSION);
8976
8577
  this.saveIndexMetadata(configuredProviderInfo);
8977
8578
  this.indexCompatibility = { compatible: true };
8978
8579
  stats.durationMs = Date.now() - startTime;
@@ -9000,6 +8601,8 @@ var Indexer = class {
9000
8601
  this.saveFileHashCache();
9001
8602
  this.saveFailedBatches([]);
9002
8603
  }
8604
+ database.setMetadata(swiftParserMetadataKey, SWIFT_PARSER_VERSION);
8605
+ database.setMetadata(metalParserMetadataKey, METAL_PARSER_VERSION);
9003
8606
  this.saveIndexMetadata(configuredProviderInfo);
9004
8607
  this.indexCompatibility = { compatible: true };
9005
8608
  stats.durationMs = Date.now() - startTime;
@@ -9270,6 +8873,8 @@ var Indexer = class {
9270
8873
  if (forceScopedReembed && failedForcedChunkIds.size === 0) {
9271
8874
  database.deleteMetadata(this.getProjectForceReembedMetadataKey());
9272
8875
  }
8876
+ database.setMetadata(swiftParserMetadataKey, SWIFT_PARSER_VERSION);
8877
+ database.setMetadata(metalParserMetadataKey, METAL_PARSER_VERSION);
9273
8878
  this.saveIndexMetadata(configuredProviderInfo);
9274
8879
  this.indexCompatibility = { compatible: true };
9275
8880
  this.logger.recordIndexingEnd();
@@ -9516,7 +9121,7 @@ var Indexer = class {
9516
9121
  let contextEndLine = r.metadata.endLine;
9517
9122
  if (!metadataOnly && this.config.search.includeContext) {
9518
9123
  try {
9519
- const fileContent = await import_fs8.promises.readFile(
9124
+ const fileContent = await import_fs7.promises.readFile(
9520
9125
  r.metadata.filePath,
9521
9126
  "utf-8"
9522
9127
  );
@@ -9703,7 +9308,7 @@ var Indexer = class {
9703
9308
  const removedChunkKeys = [];
9704
9309
  const chunkKeysByRemovedFile = /* @__PURE__ */ new Map();
9705
9310
  for (const [filePath, chunkKeys] of filePathsToChunkKeys) {
9706
- if (!(0, import_fs8.existsSync)(filePath)) {
9311
+ if (!(0, import_fs7.existsSync)(filePath)) {
9707
9312
  chunkKeysByRemovedFile.set(filePath, chunkKeys);
9708
9313
  for (const key of chunkKeys) {
9709
9314
  removedChunkKeys.push(key);
@@ -9752,7 +9357,7 @@ var Indexer = class {
9752
9357
  gcOrphanSymbols: 0,
9753
9358
  gcOrphanCallEdges: 0,
9754
9359
  resetCorruptedIndex: true,
9755
- warning: this.getCorruptedIndexWarning(path13.join(this.indexPath, "codebase.db"))
9360
+ warning: this.getCorruptedIndexWarning(path11.join(this.indexPath, "codebase.db"))
9756
9361
  };
9757
9362
  }
9758
9363
  this.logger.recordGc(removedCount, gcOrphanChunks, gcOrphanEmbeddings);
@@ -10062,7 +9667,7 @@ var Indexer = class {
10062
9667
  let content = "";
10063
9668
  if (this.config.search.includeContext) {
10064
9669
  try {
10065
- const fileContent = await import_fs8.promises.readFile(
9670
+ const fileContent = await import_fs7.promises.readFile(
10066
9671
  r.metadata.filePath,
10067
9672
  "utf-8"
10068
9673
  );
@@ -10182,7 +9787,7 @@ var Indexer = class {
10182
9787
  "Run index_codebase first to build the call graph and symbol index for this branch."
10183
9788
  );
10184
9789
  }
10185
- const absoluteChangedFiles = changedFiles.map((f) => path13.resolve(this.projectRoot, f));
9790
+ const absoluteChangedFiles = changedFiles.map((f) => path11.resolve(this.projectRoot, f));
10186
9791
  const directSymbols = database.getSymbolsForFiles(absoluteChangedFiles, branchKey);
10187
9792
  const directIds = directSymbols.map((s) => s.id);
10188
9793
  const direction = opts.direction ?? "both";
@@ -10265,7 +9870,7 @@ var Indexer = class {
10265
9870
  projectRoot: this.projectRoot,
10266
9871
  baseBranch: this.baseBranch
10267
9872
  });
10268
- const otherAbsolute = otherChanged.files.map((f) => path13.resolve(this.projectRoot, f));
9873
+ const otherAbsolute = otherChanged.files.map((f) => path11.resolve(this.projectRoot, f));
10269
9874
  const otherBranchKey = this.getBranchCatalogKeyFor(openPr.headRefName);
10270
9875
  const otherSymbols = database.getSymbolsForFiles(otherAbsolute, otherBranchKey);
10271
9876
  const otherLabels = /* @__PURE__ */ new Set();
@@ -10329,12 +9934,12 @@ var Indexer = class {
10329
9934
  if (meta.filePath) filePaths.add(meta.filePath);
10330
9935
  }
10331
9936
  const directory = options?.directory?.replace(/\/$/, "");
10332
- const absoluteDirectoryFilter = directory ? path13.resolve(this.projectRoot, directory) : void 0;
9937
+ const absoluteDirectoryFilter = directory ? path11.resolve(this.projectRoot, directory) : void 0;
10333
9938
  for (const filePath of filePaths) {
10334
9939
  if (directory) {
10335
- const absoluteFilePath = path13.resolve(filePath);
9940
+ const absoluteFilePath = path11.resolve(filePath);
10336
9941
  const matchesRelative = filePath === directory || filePath.startsWith(directory + "/");
10337
- const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter + path13.sep));
9942
+ const matchesProjectRelative = absoluteDirectoryFilter !== void 0 && (absoluteFilePath === absoluteDirectoryFilter || absoluteFilePath.startsWith(absoluteDirectoryFilter + path11.sep));
10338
9943
  if (!matchesRelative && !matchesProjectRelative) {
10339
9944
  continue;
10340
9945
  }
@@ -10377,48 +9982,48 @@ var Indexer = class {
10377
9982
  };
10378
9983
 
10379
9984
  // src/tools/knowledge-base-paths.ts
10380
- var path14 = __toESM(require("path"), 1);
9985
+ var path12 = __toESM(require("path"), 1);
10381
9986
  function resolveConfigPathValue(value, baseDir) {
10382
9987
  const trimmed = value.trim();
10383
9988
  if (!trimmed) {
10384
9989
  return trimmed;
10385
9990
  }
10386
- const absolutePath = path14.isAbsolute(trimmed) ? trimmed : path14.resolve(baseDir, trimmed);
10387
- return path14.normalize(absolutePath);
9991
+ const absolutePath = path12.isAbsolute(trimmed) ? trimmed : path12.resolve(baseDir, trimmed);
9992
+ return path12.normalize(absolutePath);
10388
9993
  }
10389
9994
  function serializeConfigPathValue(value, baseDir) {
10390
9995
  const trimmed = value.trim();
10391
9996
  if (!trimmed) {
10392
9997
  return trimmed;
10393
9998
  }
10394
- if (!path14.isAbsolute(trimmed)) {
10395
- return normalizePathSeparators(path14.normalize(trimmed));
9999
+ if (!path12.isAbsolute(trimmed)) {
10000
+ return normalizePathSeparators(path12.normalize(trimmed));
10396
10001
  }
10397
- const relativePath = path14.relative(baseDir, trimmed);
10398
- if (!relativePath || !relativePath.startsWith("..") && !path14.isAbsolute(relativePath)) {
10399
- return normalizePathSeparators(path14.normalize(relativePath || "."));
10002
+ const relativePath = path12.relative(baseDir, trimmed);
10003
+ if (!relativePath || !relativePath.startsWith("..") && !path12.isAbsolute(relativePath)) {
10004
+ return normalizePathSeparators(path12.normalize(relativePath || "."));
10400
10005
  }
10401
- return path14.normalize(trimmed);
10006
+ return path12.normalize(trimmed);
10402
10007
  }
10403
10008
  function resolveKnowledgeBasePath(value, projectRoot3) {
10404
- return path14.isAbsolute(value) ? value : path14.resolve(projectRoot3, value);
10009
+ return path12.isAbsolute(value) ? value : path12.resolve(projectRoot3, value);
10405
10010
  }
10406
- function normalizeKnowledgeBasePath2(value, projectRoot3) {
10407
- return path14.normalize(resolveKnowledgeBasePath(value, projectRoot3));
10011
+ function normalizeKnowledgeBasePath(value, projectRoot3) {
10012
+ return path12.normalize(resolveKnowledgeBasePath(value, projectRoot3));
10408
10013
  }
10409
10014
  function hasMatchingKnowledgeBasePath(knowledgeBases, inputPath, projectRoot3) {
10410
- const normalizedInput = path14.normalize(inputPath);
10411
- return knowledgeBases.some((kb) => normalizeKnowledgeBasePath2(kb, projectRoot3) === normalizedInput);
10015
+ const normalizedInput = path12.normalize(inputPath);
10016
+ return knowledgeBases.some((kb) => normalizeKnowledgeBasePath(kb, projectRoot3) === normalizedInput);
10412
10017
  }
10413
10018
  function findKnowledgeBasePathIndex(knowledgeBases, inputPath, projectRoot3) {
10414
- const normalizedInput = path14.normalize(inputPath);
10019
+ const normalizedInput = path12.normalize(inputPath);
10415
10020
  return knowledgeBases.findIndex(
10416
- (kb) => path14.normalize(kb) === normalizedInput || normalizeKnowledgeBasePath2(kb, projectRoot3) === normalizedInput
10021
+ (kb) => path12.normalize(kb) === normalizedInput || normalizeKnowledgeBasePath(kb, projectRoot3) === normalizedInput
10417
10022
  );
10418
10023
  }
10419
10024
 
10420
10025
  // src/tools/utils.ts
10421
- var import_tiktoken = __toESM(require_tiktoken(), 1);
10026
+ var import_tiktoken = require("tiktoken");
10422
10027
  var MIN_CONTEXT_PACK_TOKEN_BUDGET = 128;
10423
10028
  var MAX_CONTEXT_PACK_TOKEN_BUDGET = 4e3;
10424
10029
  var DEFAULT_CONTEXT_PACK_TOKEN_BUDGET = 1200;
@@ -10815,6 +10420,193 @@ ${truncateContent(r.content)}
10815
10420
  // src/tools/config-state.ts
10816
10421
  var import_fs9 = require("fs");
10817
10422
  var path15 = __toESM(require("path"), 1);
10423
+
10424
+ // src/config/merger.ts
10425
+ var import_fs8 = require("fs");
10426
+ var path14 = __toESM(require("path"), 1);
10427
+
10428
+ // src/config/rebase.ts
10429
+ var path13 = __toESM(require("path"), 1);
10430
+ function isWithinRoot(rootDir, targetPath) {
10431
+ const relativePath = path13.relative(rootDir, targetPath);
10432
+ return relativePath === "" || !relativePath.startsWith("..") && !path13.isAbsolute(relativePath);
10433
+ }
10434
+ function resolveInheritedKnowledgeBaseEntries(values, sourceRoot, targetRoot) {
10435
+ if (!Array.isArray(values)) {
10436
+ return [];
10437
+ }
10438
+ return values.filter((value) => typeof value === "string").map((value) => {
10439
+ const trimmed = value.trim();
10440
+ if (!trimmed) {
10441
+ return trimmed;
10442
+ }
10443
+ if (path13.isAbsolute(trimmed)) {
10444
+ if (isWithinRoot(sourceRoot, trimmed)) {
10445
+ return normalizePathSeparators(path13.normalize(path13.relative(sourceRoot, trimmed) || "."));
10446
+ }
10447
+ return path13.normalize(trimmed);
10448
+ }
10449
+ const resolvedFromSource = path13.resolve(sourceRoot, trimmed);
10450
+ if (isWithinRoot(sourceRoot, resolvedFromSource)) {
10451
+ return normalizePathSeparators(path13.normalize(trimmed));
10452
+ }
10453
+ return normalizePathSeparators(path13.normalize(path13.relative(targetRoot, resolvedFromSource)));
10454
+ }).filter(Boolean);
10455
+ }
10456
+
10457
+ // src/config/merger.ts
10458
+ var PROJECT_OVERRIDE_KEYS = [
10459
+ "embeddingProvider",
10460
+ "customProvider",
10461
+ "embeddingModel",
10462
+ "reranker",
10463
+ "include",
10464
+ "exclude",
10465
+ "indexing",
10466
+ "search",
10467
+ "debug",
10468
+ "scope"
10469
+ ];
10470
+ var MERGE_ARRAY_KEYS = ["knowledgeBases", "additionalInclude"];
10471
+ function isRecord(value) {
10472
+ return typeof value === "object" && value !== null && !Array.isArray(value);
10473
+ }
10474
+ function isStringArray2(value) {
10475
+ return Array.isArray(value) && value.every((item) => typeof item === "string");
10476
+ }
10477
+ function applyProjectOverride(merged, normalizedProjectConfig, globalConfig, key) {
10478
+ if (key in normalizedProjectConfig) {
10479
+ merged[key] = normalizedProjectConfig[key];
10480
+ return;
10481
+ }
10482
+ if (key in globalConfig) {
10483
+ merged[key] = globalConfig[key];
10484
+ }
10485
+ }
10486
+ function mergeUniqueStringArray(values) {
10487
+ return [...new Set(values.map((value) => String(value).trim()))];
10488
+ }
10489
+ function normalizeKnowledgeBasePath2(value) {
10490
+ let normalized = path14.normalize(String(value).trim());
10491
+ const root = path14.parse(normalized).root;
10492
+ while (normalized.length > root.length && /[\\/]$/.test(normalized)) {
10493
+ normalized = normalized.slice(0, -1);
10494
+ }
10495
+ return normalized;
10496
+ }
10497
+ function mergeKnowledgeBasePaths(values) {
10498
+ return [...new Set(values.map((value) => normalizeKnowledgeBasePath2(value)).filter((value) => value.length > 0))];
10499
+ }
10500
+ function validateConfigLayerShape(rawConfig, filePath) {
10501
+ if (!isRecord(rawConfig)) {
10502
+ throw new Error(`Config file ${filePath} must contain a JSON object at the root.`);
10503
+ }
10504
+ if (rawConfig.knowledgeBases !== void 0 && !isStringArray2(rawConfig.knowledgeBases)) {
10505
+ throw new Error(`Config file ${filePath} field 'knowledgeBases' must be an array of strings.`);
10506
+ }
10507
+ if (rawConfig.additionalInclude !== void 0 && !isStringArray2(rawConfig.additionalInclude)) {
10508
+ throw new Error(`Config file ${filePath} field 'additionalInclude' must be an array of strings.`);
10509
+ }
10510
+ if (rawConfig.include !== void 0 && !isStringArray2(rawConfig.include)) {
10511
+ throw new Error(`Config file ${filePath} field 'include' must be an array of strings.`);
10512
+ }
10513
+ if (rawConfig.exclude !== void 0 && !isStringArray2(rawConfig.exclude)) {
10514
+ throw new Error(`Config file ${filePath} field 'exclude' must be an array of strings.`);
10515
+ }
10516
+ for (const section of ["customProvider", "indexing", "search", "debug", "reranker"]) {
10517
+ const value = rawConfig[section];
10518
+ if (value !== void 0 && !isRecord(value)) {
10519
+ throw new Error(`Config file ${filePath} field '${section}' must be an object.`);
10520
+ }
10521
+ }
10522
+ return rawConfig;
10523
+ }
10524
+ function loadJsonFile(filePath) {
10525
+ if (!(0, import_fs8.existsSync)(filePath)) {
10526
+ return null;
10527
+ }
10528
+ try {
10529
+ const content = (0, import_fs8.readFileSync)(filePath, "utf-8");
10530
+ return validateConfigLayerShape(JSON.parse(content), filePath);
10531
+ } catch (error) {
10532
+ if (error instanceof Error && error.message.startsWith("Config file ")) {
10533
+ throw error;
10534
+ }
10535
+ const message = error instanceof Error ? error.message : String(error);
10536
+ throw new Error(`Failed to load config file ${filePath}: ${message}`);
10537
+ }
10538
+ }
10539
+ function loadProjectConfigLayer(projectRoot3, host = "opencode") {
10540
+ const projectConfigPath = resolveProjectConfigPath(projectRoot3, host);
10541
+ const projectConfig = loadJsonFile(projectConfigPath);
10542
+ if (!projectConfig) {
10543
+ return {};
10544
+ }
10545
+ const normalizedConfig = { ...projectConfig };
10546
+ const projectConfigBaseDir = path14.dirname(path14.dirname(projectConfigPath));
10547
+ if (Array.isArray(normalizedConfig.knowledgeBases)) {
10548
+ normalizedConfig.knowledgeBases = resolveInheritedKnowledgeBaseEntries(
10549
+ normalizedConfig.knowledgeBases,
10550
+ projectConfigBaseDir,
10551
+ projectRoot3
10552
+ );
10553
+ }
10554
+ return normalizedConfig;
10555
+ }
10556
+ function loadMergedConfig(projectRoot3, host = "opencode") {
10557
+ const globalConfigPath = resolveGlobalConfigPath(host);
10558
+ const projectConfigPath = resolveProjectConfigPath(projectRoot3, host);
10559
+ let globalConfig = null;
10560
+ let globalConfigError = null;
10561
+ try {
10562
+ globalConfig = loadJsonFile(globalConfigPath);
10563
+ } catch (error) {
10564
+ globalConfigError = error instanceof Error ? error : new Error(String(error));
10565
+ }
10566
+ const projectConfig = loadJsonFile(projectConfigPath);
10567
+ const normalizedProjectConfig = loadProjectConfigLayer(projectRoot3, host);
10568
+ if (globalConfigError) {
10569
+ if (!projectConfig) {
10570
+ throw globalConfigError;
10571
+ }
10572
+ globalConfig = null;
10573
+ }
10574
+ if (!globalConfig && !projectConfig) {
10575
+ return {};
10576
+ }
10577
+ if (!projectConfig && globalConfig) {
10578
+ return globalConfig;
10579
+ }
10580
+ if (!globalConfig && projectConfig) {
10581
+ return normalizedProjectConfig;
10582
+ }
10583
+ if (!globalConfig || !projectConfig) {
10584
+ return globalConfig ?? normalizedProjectConfig;
10585
+ }
10586
+ const merged = { ...globalConfig };
10587
+ for (const key of PROJECT_OVERRIDE_KEYS) {
10588
+ applyProjectOverride(merged, normalizedProjectConfig, globalConfig, key);
10589
+ }
10590
+ if (projectConfig) {
10591
+ for (const key of Object.keys(projectConfig)) {
10592
+ if (PROJECT_OVERRIDE_KEYS.includes(key) || MERGE_ARRAY_KEYS.includes(key)) {
10593
+ continue;
10594
+ }
10595
+ merged[key] = normalizedProjectConfig[key];
10596
+ }
10597
+ }
10598
+ const globalKbs = globalConfig && Array.isArray(globalConfig.knowledgeBases) ? globalConfig.knowledgeBases : [];
10599
+ const projectKbs = projectConfig ? Array.isArray(normalizedProjectConfig.knowledgeBases) ? normalizedProjectConfig.knowledgeBases : [] : [];
10600
+ const allKbs = [...globalKbs, ...projectKbs];
10601
+ merged.knowledgeBases = mergeKnowledgeBasePaths(allKbs);
10602
+ const globalAdditional = globalConfig && Array.isArray(globalConfig.additionalInclude) ? globalConfig.additionalInclude : [];
10603
+ const projectAdditional = projectConfig && Array.isArray(projectConfig.additionalInclude) ? projectConfig.additionalInclude : [];
10604
+ const allAdditional = [...globalAdditional, ...projectAdditional];
10605
+ merged.additionalInclude = mergeUniqueStringArray(allAdditional);
10606
+ return merged;
10607
+ }
10608
+
10609
+ // src/tools/config-state.ts
10818
10610
  function normalizeKnowledgeBasePaths(config, projectRoot3) {
10819
10611
  const normalized = { ...config };
10820
10612
  if (Array.isArray(normalized.knowledgeBases)) {
@@ -10912,15 +10704,6 @@ function refreshIndexerForDirectory(projectRoot3, host = "opencode", config = pa
10912
10704
  indexerCache.set(key, indexer);
10913
10705
  configCache.set(key, config);
10914
10706
  }
10915
- function shouldForceLocalizeProjectIndex(projectRoot3, host = "opencode") {
10916
- const root = getProjectRoot(projectRoot3, host);
10917
- const localIndexPath = path16.join(root, getHostProjectIndexRelativePath(host));
10918
- if ((0, import_fs10.existsSync)(localIndexPath)) {
10919
- return false;
10920
- }
10921
- const inheritedIndexPath = resolveWorktreeFallbackProjectIndexPath(root, host);
10922
- return inheritedIndexPath !== null;
10923
- }
10924
10707
  async function searchCodebase(projectRoot3, host, query, options = {}) {
10925
10708
  const indexer = getIndexerForProject(projectRoot3, host);
10926
10709
  return indexer.search(query, options.limit, {
@@ -10970,9 +10753,7 @@ async function getCallGraphPath(projectRoot3, host, from, to, maxDepth) {
10970
10753
  }
10971
10754
  async function runIndexCodebase(projectRoot3, host, args, onProgress) {
10972
10755
  const root = getProjectRoot(projectRoot3, host);
10973
- const key = getIndexerCacheKey(root, host);
10974
- let indexer = getIndexerForProject(root, host);
10975
- const runtimeConfig = configCache.get(key);
10756
+ const indexer = getIndexerForProject(root, host);
10976
10757
  try {
10977
10758
  if (args.estimateOnly) {
10978
10759
  return { kind: "estimate", estimate: await indexer.estimateCost() };
@@ -10993,19 +10774,7 @@ async function runIndexCodebase(projectRoot3, host, args, onProgress) {
10993
10774
  return Promise.resolve();
10994
10775
  });
10995
10776
  };
10996
- let stats;
10997
- if (args.force && shouldForceLocalizeProjectIndex(root, host)) {
10998
- const inheritedIndexPath = resolveProjectIndexPath(root, runtimeConfig.scope, host);
10999
- stats = await withIndexLock(inheritedIndexPath, "force-index", async () => {
11000
- materializeLocalProjectConfig(root, loadProjectConfigLayer(root, host), host);
11001
- refreshIndexerForDirectory(root, host, runtimeConfig);
11002
- indexer = getIndexerForProject(root, host);
11003
- return runIndex(indexer);
11004
- }, { completeRecoveries: false });
11005
- } else {
11006
- stats = await runIndex(indexer);
11007
- }
11008
- return { kind: "stats", stats };
10777
+ return { kind: "stats", stats: await runIndex(indexer) };
11009
10778
  } catch (error) {
11010
10779
  const busyResult = getIndexBusyResult(error);
11011
10780
  if (!busyResult) throw error;