検索/RustのAIフレームワークに、新しいAIプロバイダーやベクトルストアを足す

RustのAIフレームワークに、新しいAIプロバイダーやベクトルストアを足す

多くのAIプロバイダーに対応するRustのフレームワークを広げる時に使う。今あるtraitとbuilderに合わせ、WebAssemblyで動く形を保ち、フックがストリーミングの有無で同じ動きをするようにし、記録したテスト用のカセットにAPIキーが入っていないか確かめる。

このAIルールを使うには
## 頼まれた範囲だけを変え、頼まれない限りコミットしない - コードを変える前に、既存実装、manifest、test、公開documentationを読む。 - すべての変更をユーザーが依頼した範囲内に保つ。 - 並行する抽象化を作らず、既存のtrait、builder、module、error typeを優先する。 - TODO、stub、placeholder behavior、投機的な公開APIを追加しない。 - ユーザーが明示的に依頼しない限り、commit、stage、push、branch作成、pull request作成を行わない。 - 無関係なユーザー変更を維持し、dirty treeを安全に避けて作業する。 - 近くの設計を改善できる場合でも、無関係なrefactorを避ける。 - contributor policyとrepository固有のengineering ruleを区別し、両方に従う。 - 必要なproduct intentまたは外部承認がない時は停止する。 ## crateの分け方とfeature flagを、ワークスペース全体でそろえる - 公開facade crate、core crate、companion integration、derive macro、example、testを既定の役割に保つ。 - facadeはcore APIをre-exportし、任意のcompanion crateをfeature flag経由で公開する。 - 公開feature、integration、module pathを変える前に、workspace manifestとfacade exportを確認する。 - 強いアーキテクチャ上の理由がない限り、providerとvector storeのintegrationはcompanion crateへ置く。 - workspace example、crate単位のexample、integration testを区別する。 - companion crateを追加する時は、必要に応じてroot dependency、feature、facade re-export、example、README、crate documentationを更新する。 - 利用不能なmoduleを露出せずにfeatureの各組み合わせがcompileできることを保証する。 - facadeと影響するcompanion crateの間で公開documentationを同期させる。 - codeとmanifestで確認するまで、module pathやfeatureを説明しない。 ## プロバイダー専用の物を作らず、共通のtraitの上に作る - frameworkの中核となるcompletion、embedding、vector index、呼び出し可能toolのtrait上にintegrationを構築する。 - 既存のprovider横断traitに対するprovider固有の代替を作らない。 - 設定可能な公開typeには確立済みのbuilder patternを使う。 - 構築過程をfluentかつ型安全に保ち、明示的なbuild stepの後にだけ完成させる。 - provider extensionと基盤HTTP transportを分離するgeneric client architectureを使う。 - 未対応behaviorがcompile時に失敗するよう、provider capabilityを明示的に宣言する。 - 存在しないcapabilityはruntimeの推測ではなく、意図的なmarker typeで表す。 - provider builderとパブリックclient aliasの間でAPI key typeの関係を維持する。 - provider固有のrequest typeとresponse typeをconversion boundaryの内側に置く。 ## 共有の非同期コードを、WebAssemblyでも動く形に保つ - 共有trait、future、error、integrationでWebAssembly対応を維持する。 - targetごとに要件が異なる場合は、生の`Send`と`Sync`境界ではなくframeworkのcompatibility abstractionを使う。 - 動的に返すfutureには、指定されたportable boxed-future typeを使う。 - native thread safetyの境界は、対応するtargetにだけ適用する。 - WebAssemblyのboxed errorから、未対応のnative専用境界を外す。 - 共有traitを変えた後は、nativeとWebAssembly向けのtype signatureを両方testする。 - 対応済みtargetを黙って対象外にするdependencyやAPIを追加しない。 - conditional compilationを狭い範囲に保ち、target間の違いを説明する。 - provider、vector store、hookのAPIで同じportability contractを使う。 ## はっきりしたエラーの型を使い、新しい公開APIには全部説明を書く - 新しいfallible APIのerror typeに`String`を使わない。 - 明示的なerror enumを定義し、frameworkのerror helperを通して有用なprovider responseの詳細を維持する。 - error contextを手作業で失う処理より、`?`と意味のあるconversionを優先する。 - 周囲のinvariantから不可能であることが明白な場合に限り、`unwrap()`または`expect()`を使う。 - 新しい公開type、function、trait、methodのすべてにitem documentationを追加する。 - 新しい公開moduleのすべてにmodule documentationを追加する。 - exampleを実在するAPI、model constant、module path、feature flagと一致させる。 - 外部credentialまたはserviceを必要とするexampleは非実行として印を付ける。 - 公開behaviorを変えた時はREADMEとcrate-level documentationを更新する。 ## 新しいAIプロバイダーは、一番近い既存のプロバイダーにならって足す - providerを実装または変更する前に、最も近い既存providerを調べる。 - provider extensionとbuilder type、provider実装、明示的なcapability declarationを追加する。 - frameworkが両方の経路を公開する場合は、environment valueとdirect valueからの構築を支援する。 - パブリックclientとbuilder aliasをprovider builderのAPI key typeと一致させる。 - 明示的なcredential markerまたはauthentication typeを使い、credentialを含むdebug表示を伏せる。 - framework requestをproviderの実際のwire formatへ変換し、responseをframework typeへ戻す。 - providerが実際に対応する場合にだけstreamingを追加し、標準helperを通してprovider errorを維持する。 - 確立済みのtelemetry conventionとextension traitに従う。 - providerの実際のAPIに存在しないrequest fieldやresponse fieldを作らない。 - 対応behaviorを証明する対象を絞ったtestまたはexampleを追加する。 ## 本当の絞り込みと、はっきりした検索結果を持つベクトルストアをつなぐ - core所有が正当化されない限り、vector store integrationをcompanion crateへ置く。 - resultを返すsearchとidentifierだけを返すsearchの両方を実装する。 - backendの実際のfiltering capabilityを反映するfilter typeを使う。 - 場当たり的なstring failureではなく、frameworkのvector store error variantを返す。 - core frameworkが使うものと同じportable async boundaryを適用する。 - score、document、identifier、metadataのconversionを明示する。 - ordering、limit、empty result、backend errorのbehaviorを定義する。 - filter、ranking order、result limit、missing record、conversion failureをtestする。 - secretを埋め込まず、必要なfeature、credential、index、external setupを文書化する。 ## フックのイベントごとに、できる操作を決める - hookをrun単位のlifecycle observerおよびsteererとしてmodel化する。 - run identity、turn、streaming mode、agent identity、共有scratch stateを含むrun contextをすべてのeventへ渡す。 - 未対応のaction組み合わせがcompile時に失敗するよう、eventごとに固有のaction typeを与える。 - completion call hookにはrequestのpatchまたは処理停止を返させる。 - tool call hookとtool result hookには後続hook向けのvalueを書き換えさせ、定義されたskipまたはstopをterminal actionとする。 - invalid tool callの処理を、明示的なfail、retry、repair、skip、stopの選択肢で表す。 - observe-only eventはcontinueまたはstopだけに制限する。 - stop actionがstackをshort-circuitする場合は、steering hookより前にobservation hookを登録する。 - dataを変換するaction、蓄積するaction、処理を終えるactionを文書化する。 ## 重ねたフックを、ストリーミングの有無で同じ動きにする - hookを入れ子またはstack化する時も、event固有のcomposition semanticsを維持する。 - completion request patchを登録順にmergeする。 - extra contextをappendし、additional parameterをshallow mergeし、active tool setの積集合を取る。 - 文書化されたscalar fieldとhistory fieldにだけ「最後の書き手を優先」を適用し、重要な上書きにはwarningを出す。 - 各request patchを1 turnだけに限定し、誤って持続させない。 - tool callとtool resultのrewriteを後続hookすべてへ渡す。 - terminal actionが要求した時はstackの評価を直ちに停止する。 - streaming surfaceとnon-streaming surfaceで同じlifecycle driverを共有する。 - streamingとnon-streamingの両entry pointで同一のhook behaviorをtestする。 - nested stack、merge conflict、rewrite chain、skip、stopのcomposition testを追加する。 ## 小さな回帰テストを選び、プロバイダーとのやり取りはカセットで試す - 信頼できる最小範囲でregression coverageを追加する。 - 独立したconversionまたはlogic defectには、実装の近くに置くunit testを優先する。 - behaviorがproviderのrequestとresponse trafficに依存する場合は、cassette-backed provider testを使う。 - deterministicなcassette replayでbehaviorを表せない場合に限り、ignored live testを使う。 - provider testを追加、更新、record、replayする前にrepositoryのtest guideを読む。 - 通常testがprovider credentialを要求しないよう、既定ではcassetteをreplayする。 - 変更するproviderとbehaviorにtest実行を絞る。 - 両surfaceが存在する場合は、streamingとnon-streamingのbehaviorをcoverする。 - regression assertionで元のfailure modeを維持する。 ## カセットは対象のテストだけ記録し、秘密の情報が入っていないか確かめる - record modeを、外部接続、credential使用、file上書きを伴うoperationとして扱う。 - record前に該当provider credentialを必須とし、表示へ決して露出しない。 - 無関係なfixture churnを最小化するため、対象provider testだけをrecordする。 - cassette diffを提示またはcommitする前に、すべて手作業で調べる。 - API key、bearer credential、cookie、account identifier、その他のsensitive valueを含むfixtureを拒否する。 - noisyなfixtureを受け入れず、無関係なrequestとresponseのchurnを取り除く。 - 自動scrubとsafety checkを有効に保つが、inspectionの代わりとして扱わない。 - secretと不安定なmetadataを伏せながら、deterministic replay dataを維持する。 - behavior changeを説明せず、失敗testをgreenにする目的だけでfixtureを絶対に上書きしない。 ## 狭いチェックから広げて回し、確かめられなかった所を報告する - 有用な最小checkから始め、影響範囲とriskに応じて広げる。 - workspaceをformatし、影響する全targetとfeatureにlintを実行する。 - 広いworkspace testより先にfocused testを実行する。 - 公開APIまたはdocumentを変えた場合は、dependencyを含めずdocumentationをbuildする。 - 共有boundaryまたはfutureを変えた場合は、nativeとWebAssemblyのcompatibilityを検証する。 - provider wire fieldが実際のAPIと一致し、cassette diffにsecretがないことを確認する。 - streamingとnon-streamingのsurfaceでhook semanticsが一致することを確認する。 - 必須checkが失敗している間は完了を主張しない。 - commandを実行できない場合は理由を説明し、未検証事項を正確に示す。 - 変更したsurface、実行したcheck、観測結果、残るrisk、意図的に除外した範囲を報告する。