-33
stack/bushel/bin/bushel_main.ml
-33
stack/bushel/bin/bushel_main.ml
············
············
+32
-52
stack/bushel/bin/bushel_search.ml
+32
-52
stack/bushel/bin/bushel_search.ml
······-Printf.eprintf "Error: API key is required. Use --api-key, set TYPESENSE_API_KEY environment variable, or create .typesense-key file.\n";-let combined_response = Bushel.Typesense.combine_multisearch_results multisearch_resp ~limit ~offset () in-Printf.printf "Found %d results (%.2fms)\n\n" combined_response.total combined_response.query_time;-Printf.printf "%d. %s (score: %.2f)\n" (i + 1) (Bushel.Typesense.pp_search_result_oneline hit) hit.Bushel.Typesense.score
······+Printf.eprintf "Error: API key is required. Use TYPESENSE_API_KEY environment variable or create .typesense-key file.\n";+let combined_response = Bushel.Typesense.combine_multisearch_results multisearch_resp ~limit ~offset () in+Printf.printf "Found %d results (%.2fms)\n\n" combined_response.total combined_response.query_time;+Printf.printf "%d. %s (score: %.2f)\n" (i + 1) (Bushel.Typesense.pp_search_result_oneline hit) hit.Bushel.Typesense.score
+93
-153
stack/bushel/bin/bushel_typesense.ml
+93
-153
stack/bushel/bin/bushel_typesense.ml
···-Printf.eprintf "Error: API key is required. Use --api-key or set TYPESENSE_API_KEY environment variable.\n";-Printf.eprintf "Error: OpenAI API key is required for embeddings. Use --openai-key or set OPENAI_API_KEY environment variable.\n";-Printf.eprintf "Error: API key is required. Use --api-key or set TYPESENSE_API_KEY environment variable.\n";-Printf.eprintf "Error: API key is required. Use --api-key or set TYPESENSE_API_KEY environment variable.\n";-let doc = "Specific collection to search (contacts, papers, projects, news, videos, notes, ideas)" in···-`P "The API key can be provided via --api-key flag or TYPESENSE_API_KEY environment variable.";······-`P "Upload all bushel object types (contacts, papers, projects, news, videos, notes, ideas) to a Typesense search engine instance.";-`P "The API key can be provided via --api-key flag or TYPESENSE_API_KEY environment variable.";-`Pre " bushel-typesense upload --api-key xyz123 --openai-key sk-abc... --data-dir /path/to/data";-`Pre " bushel-typesense upload --endpoint https://search.example.com --api-key xyz123 --openai-key sk-abc...";···-let api_key = Arg.(value & opt string key & info ["api-key"; "k"] ~doc:"Typesense API key") in-| Some oa_key when oa_key <> "" -> Arg.(value & opt string oa_key & info ["openai-key"; "oa"] ~doc:"OpenAI API key")
···+Printf.eprintf "Error: API key is required. Use TYPESENSE_API_KEY environment variable or create .typesense-key file.\n";+Printf.eprintf "Error: OpenAI API key is required for embeddings. Use OPENAI_API_KEY environment variable or create .openrouter-api file.\n";+Printf.eprintf "Error: API key is required. Use TYPESENSE_API_KEY environment variable or create .typesense-key file.\n";+Printf.eprintf "Error: API key is required. Use TYPESENSE_API_KEY environment variable or create .typesense-key file.\n";+let doc = "Specific collection to search (contacts, papers, projects, notes, videos, ideas)" in···+`P "The API key can be read from .typesense-key file or TYPESENSE_API_KEY environment variable.";···+Cmd.v info Term.(const run $ query_text $ collection $ limit $ offset $ Bushel_common.setup_term)···+`P "Upload all bushel object types (contacts, papers, projects, notes, videos, ideas) to a Typesense search engine instance.";···
+3
-3
stack/bushel/bin/dune
+3
-3
stack/bushel/bin/dune
···-(modules bushel_main bushel_bibtex bushel_doi bushel_ideas bushel_info bushel_missing bushel_note_doi bushel_obsidian bushel_paper bushel_paper_classify bushel_paper_tex bushel_video bushel_video_thumbs bushel_thumbs bushel_faces bushel_links bushel_search)-(libraries bushel bushel_common cmdliner cohttp-lwt-unix lwt.unix yaml ezjsonm zotero-translation peertube fmt fmt.cli fmt.tty logs logs.cli logs.fmt cmarkit karakeep uri unix ptime.clock.os crockford))···
···+(modules bushel_main bushel_bibtex bushel_ideas bushel_info bushel_missing bushel_note_doi bushel_obsidian bushel_paper_classify bushel_paper_tex bushel_thumbs bushel_search)+(libraries bushel bushel_common cmdliner eio eio_main yaml ezjsonm zotero-translation fmt fmt.cli fmt.tty logs logs.cli logs.fmt cmarkit uri unix ptime.clock.os crockford))···
+9
-5
stack/bushel/bushel.opam
+9
-5
stack/bushel/bushel.opam
+10
-43
stack/bushel/dune-project
+10
-43
stack/bushel/dune-project
···
+3
-3
stack/bushel/lib/dune
+3
-3
stack/bushel/lib/dune
+30
-552
stack/bushel/lib/typesense.ml
+30
-552
stack/bushel/lib/typesense.ml
·································let search_collection ~sw ~env (config : config) collection_name query ?(limit=10) ?(offset=0) () =············let combine_multisearch_results (multisearch_resp : multisearch_response) ?(limit=10) ?(offset=0) () =···-let abstract = Md.markdown_to_plaintext entries (Paper.abstract paper) |> truncate_for_embedding in-let description = Md.markdown_to_plaintext entries (Project.body project) |> truncate_for_embedding in-let description = Md.markdown_to_plaintext entries (Video.body video) |> truncate_for_embedding in-let description = Md.markdown_to_plaintext entries (Idea.body idea) |> truncate_for_embedding in-("contacts", add_embedding_field_to_schema Contact.typesense_schema config ["name"; "names"], (List.map contact_to_document contacts : Ezjsonm.value list));-("papers", add_embedding_field_to_schema Paper.typesense_schema config ["title"; "abstract"; "authors"], (List.map (paper_to_document entries) papers : Ezjsonm.value list));-("videos", add_embedding_field_to_schema Video.typesense_schema config ["title"; "description"], (List.map (video_to_document entries) videos : Ezjsonm.value list));-("projects", add_embedding_field_to_schema Project.typesense_schema config ["title"; "description"; "tags"], (List.map (project_to_document entries) projects : Ezjsonm.value list));-("notes", add_embedding_field_to_schema Note.typesense_schema config ["title"; "content"; "tags"], (List.map (note_to_document entries) notes : Ezjsonm.value list));-("ideas", add_embedding_field_to_schema Idea.typesense_schema config ["title"; "description"; "tags"], (List.map (idea_to_document entries) ideas : Ezjsonm.value list));-let upload_collection ((name, schema, documents) : string * Ezjsonm.value * Ezjsonm.value list) =-let* () = Lwt_io.write Lwt_io.stdout (Fmt.str "Creating collection %s with %d documents\n" name (List.length documents)) in-if String.contains line ':' && Str.string_match (Str.regexp ".*success.*true.*") line 0 then acc + 1 else acc) 0 lines in-if String.contains line ':' && Str.string_match (Str.regexp ".*success.*false.*") line 0 then acc + 1 else acc) 0 lines in-let* () = Lwt_io.write Lwt_io.stdout (Fmt.str "Upload results for %s: %d successful, %d failed out of %d total\n"-let failed_lines = List.filter (fun line -> Str.string_match (Str.regexp ".*success.*false.*") line 0) lines in-let* result = Typesense_client.search_collection client_config collection_name query ~limit ~offset () in-| Error (Typesense_client.Http_error (code, msg)) -> Lwt.return_error (Http_error (code, msg))-let combined_response = Typesense_client.combine_multisearch_results multisearch_resp ~limit ~offset () in-| Error (Typesense_client.Http_error (code, msg)) -> Lwt.return_error (Http_error (code, msg))-| Error (Typesense_client.Http_error (code, msg)) -> Lwt.return_error (Http_error (code, msg))-| Error (Typesense_client.Http_error (code, msg)) -> Lwt.return_error (Http_error (code, msg))-let combine_multisearch_results (multisearch_resp : multisearch_response) ?(limit=10) ?(offset=0) () =
·································let search_collection ~sw ~env (config : config) collection_name query ?(limit=10) ?(offset=0) () =············let combine_multisearch_results (multisearch_resp : multisearch_response) ?(limit=10) ?(offset=0) () =···
+11
-129
stack/bushel/lib/typesense.mli
+11
-129
stack/bushel/lib/typesense.mli
·········env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->···env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->···env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->···env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->···env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->···env:< clock: float Eio.Time.clock_ty Eio.Resource.t; fs: Eio.Fs.dir_ty Eio.Path.t; net: [`Generic | `Unix] Eio.Net.ty Eio.Resource.t; .. > ->···env:< clock: float Eio.Time.clock_ty Eio.Resource.t; fs: Eio.Fs.dir_ty Eio.Path.t; net: [`Generic | `Unix] Eio.Net.ty Eio.Resource.t; .. > ->···env:< clock: float Eio.Time.clock_ty Eio.Resource.t; fs: Eio.Fs.dir_ty Eio.Path.t; net: [`Generic | `Unix] Eio.Net.ty Eio.Resource.t; .. > ->···val combine_multisearch_results : multisearch_response -> ?limit:int -> ?offset:int -> unit -> search_responseenv:< clock: float Eio.Time.clock_ty Eio.Resource.t; fs: Eio.Fs.dir_ty Eio.Path.t; net: [`Generic | `Unix] Eio.Net.ty Eio.Resource.t; .. > ->-val search_collection : config -> string -> string -> ?limit:int -> ?offset:int -> unit -> (search_response, error) result Lwt.t-val search_all : config -> string -> ?limit:int -> ?offset:int -> unit -> (search_response, error) result Lwt.t-val multisearch : config -> string -> ?limit:int -> unit -> (multisearch_response, error) result Lwt.t-val combine_multisearch_results : multisearch_response -> ?limit:int -> ?offset:int -> unit -> search_response
·········env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->···env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->···env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->···env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->···env:< clock: [> float Eio.Time.clock_ty ] Eio.Resource.t; net: [> [> `Generic ] Eio.Net.ty ] Eio.Resource.t; .. > ->···env:< clock: float Eio.Time.clock_ty Eio.Resource.t; fs: Eio.Fs.dir_ty Eio.Path.t; net: [`Generic | `Unix] Eio.Net.ty Eio.Resource.t; .. > ->···env:< clock: float Eio.Time.clock_ty Eio.Resource.t; fs: Eio.Fs.dir_ty Eio.Path.t; net: [`Generic | `Unix] Eio.Net.ty Eio.Resource.t; .. > ->···env:< clock: float Eio.Time.clock_ty Eio.Resource.t; fs: Eio.Fs.dir_ty Eio.Path.t; net: [`Generic | `Unix] Eio.Net.ty Eio.Resource.t; .. > ->···val combine_multisearch_results : multisearch_response -> ?limit:int -> ?offset:int -> unit -> search_responseenv:< clock: float Eio.Time.clock_ty Eio.Resource.t; fs: Eio.Fs.dir_ty Eio.Path.t; net: [`Generic | `Unix] Eio.Net.ty Eio.Resource.t; .. > ->