Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/agent/tools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,22 @@ describe('searchStationsByName', () => {
});
});

it('STATION_API があれば優先し、サブドメイン直下へ POST する', async () => {
const stationApiFetch = jest
.fn()
.mockResolvedValue(gqlResponse([gqlStation(1)]));
const bffFetch = jest.fn();
const env = {
STATION_API: { fetch: stationApiFetch },
SAPI_BFF: { fetch: bffFetch },
} as unknown as Env;
const result = await searchStationsByName(env, '鎌倉', undefined);
expect(result[0].stationId).toBe(1);
expect(bffFetch).not.toHaveBeenCalled();
expect(stationApiFetch.mock.calls[0][0]).toBe('https://stationapi/');
expect(stationApiFetch.mock.calls[0][1].method).toBe('POST');
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.

it('失敗時に 1 回だけ再試行する', async () => {
const fetchMock = jest
.fn()
Expand Down
21 changes: 14 additions & 7 deletions src/agent/tools.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* 駅検索ツール — sapi-bff(BFF ルートワーカー)の GraphQL stationsByName で
* 駅名の実在確認を行う。Service Binding(SAPI_BFF)を優先し、
* 未設定なら SAPI_BFF_GRAPHQL_URL への fetch にフォールバックする。
* 駅検索ツール — stationapi の GraphQL stationsByName で
* 駅名の実在確認を行う。Service Binding(STATION_API、未移行の環境は SAPI_BFF)
* 優先し、未設定なら SAPI_BFF_GRAPHQL_URL への fetch にフォールバックする。
* 検索結果は verified マップへ蓄積し、最終応答のサーバ側検証
* (validate.ts の sanitizeSuggestions)の突合元になる。
*/
Expand All @@ -15,12 +15,12 @@ import {

/** stationsByName へ渡す件数(設計値。全量を返すとツール結果でトークンを浪費する) */
const STATION_SEARCH_LIMIT = 10;
/** sapi-bff 呼び出しの 1 試行あたり期限 */
/** 駅検索 API 呼び出しの 1 試行あたり期限 */
const TOOL_TIMEOUT_MS = 5_000;
/** 1 ターン合計のツール呼び出し上限 */
export const MAX_TOOL_CALLS_PER_TURN = 5;
/**
* ツール 1 回あたりの sapi-bff 呼び出し上限(表記ゆれ候補 + 一過性エラーの再試行の合計)。
* ツール 1 回あたりの駅検索 API 呼び出し上限(表記ゆれ候補 + 一過性エラーの再試行の合計)。
* 1 試行 5 秒のため、全体 25 秒の予算内に収まる値にする。
*/
const MAX_SEARCH_ATTEMPTS = 3;
Expand Down Expand Up @@ -102,14 +102,21 @@ const postGraphQL = async (
body,
signal,
};
if (env.STATION_API) {
// Service Binding はホスト名を解決しないため URL はダミーでよい。
// stationapi は GraphQL をサブドメイン直下(POST /)で受ける
return env.STATION_API.fetch('https://stationapi/', init);
}
if (env.SAPI_BFF) {
// Service Binding はホスト名を解決しないため URL はダミーでよい
return env.SAPI_BFF.fetch('https://sapi-bff/graphql', init);
}
if (env.SAPI_BFF_GRAPHQL_URL) {
return fetch(env.SAPI_BFF_GRAPHQL_URL, init);
}
throw new Error('SAPI_BFF binding or SAPI_BFF_GRAPHQL_URL is required');
throw new Error(
'STATION_API / SAPI_BFF binding or SAPI_BFF_GRAPHQL_URL is required'
);
};

const queryStationsOnce = async (
Expand Down Expand Up @@ -341,7 +348,7 @@ export interface StationSearchToolResult {
}

export interface StationSearchToolOptions {
/** 駅名 → 実在駅リスト(sapi-bff 呼び出し。テストでは差し替え可能) */
/** 駅名 → 実在駅リスト(駅検索 API 呼び出し。テストでは差し替え可能) */
search: (name: string) => Promise<StationSuggestion[]>;
/** このターンで実在確認済みの駅(stationId → 駅)。突合検証の元データ */
verified: Map<number, StationSuggestion>;
Expand Down
4 changes: 3 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ export interface Env {
TTS_BUCKET: R2Bucket;
UPLOAD_BUCKET: R2Bucket;
FEEDBACK_QUEUE: Queue<FeedbackQueueMessage>;
/** sapi-bff(BFF ルートワーカー)への Service Binding。エージェントの駅検索に使う */
/** stationapi(GraphQL ワーカー)への Service Binding。エージェントの駅検索に使う */
STATION_API?: Fetcher;
/** sapi-bff(BFF ルートワーカー)への Service Binding。stationapi 未移行の環境用 */
SAPI_BFF?: Fetcher;

// --- Vars(非機密。wrangler.jsonc の vars) ---
Expand Down
5 changes: 3 additions & 2 deletions wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@
]
},

// エージェントの駅検索(stationsByName)は同一アカウントの sapi-bff を Service Binding で呼ぶ
"services": [{ "binding": "SAPI_BFF", "service": "sapi-bff-stg" }],
// エージェントの駅検索(stationsByName)は同一アカウントの stationapi を Service Binding で呼ぶ。
// staging は BFF 廃止に伴い stationapi-stg へ移行済み(本番は sapi-bff のまま)
"services": [{ "binding": "STATION_API", "service": "stationapi-stg" }],

"vars": {
"GOOGLE_PLAY_PACKAGE_NAME": "me.tinykitten.trainlcd",
Expand Down