feat(assistant): expenses, shares, wind, journey tracks and Dawarich checks as MCP tools

- list_budget_items lists a trip's expenses with their ids, payers and
  splits, page by page so no page is cut down on its way to a model;
  get_budget_per_person answers who paid and owes what. Both in a new
  budget-items.mcp.ts, checked like their REST twins.
- get_wind_forecast reads the hourly wind, gusts and direction of a day.
- get_journey_tracks lists a journey's GPX tracks; the line for drawing
  rides under a key the provider never receives.
- The Dawarich wishlist scan and the countries the recordings suggest
  become tools, with their confirming writes, in DawarichAtlasMcp in the
  Atlas group; the shared time window check refuses alike on REST and
  MCP, and the model never sees when the user was last seen in a city.
- The journal's map, tracks and recorded days load with the journey
  group instead of riding in the core of every step.
- The prompt points at list_budget_items for expense ids (the trip
  summary never carried them) and names the shares and the wind tools;
  each new read has its own live step.
This commit is contained in:
Maurice
2026-10-22 00:03:19 +00:00
parent 3c0f324266
commit 6d6efddc4e
63 changed files with 2418 additions and 51 deletions
@@ -130,6 +130,26 @@ describe('toolStepKey', () => {
expect(toolStepKey('constructor')).toBe('assistant.step.working');
});
it('FE-AI-MODEL-011: names the expense, share, wind, track and Dawarich reads by what they look at', () => {
expect(
[
'list_budget_items',
'get_budget_per_person',
'get_wind_forecast',
'get_journey_tracks',
'scan_bucket_list_visits',
'suggest_atlas_countries',
].map(toolStepKey)
).toEqual([
'assistant.step.expenses',
'assistant.step.shares',
'assistant.step.wind',
'assistant.step.tracks',
'assistant.step.bucketScan',
'assistant.step.atlasCountries',
]);
});
it('FE-AI-MODEL-010: a running step that names a place or a query says it, and falls back to its name', () => {
expect(liveStepText('search_nearby_places', 'Trastevere')).toEqual({
key: 'assistant.step.nearbyAt',
@@ -167,6 +167,12 @@ const STEPS: Partial<Record<string, StepLook>> = {
get_weather: { stepKey: 'assistant.step.weather', live: { liveKey: 'assistant.step.weatherAt', param: 'place' } },
list_todos: { stepKey: 'assistant.step.todos' },
get_settlement_summary: { stepKey: 'assistant.step.costs' },
list_budget_items: { stepKey: 'assistant.step.expenses' },
get_budget_per_person: { stepKey: 'assistant.step.shares' },
get_wind_forecast: { stepKey: 'assistant.step.wind' },
get_journey_tracks: { stepKey: 'assistant.step.tracks' },
scan_bucket_list_visits: { stepKey: 'assistant.step.bucketScan' },
suggest_atlas_countries: { stepKey: 'assistant.step.atlasCountries' },
propose_hike: {
stepKey: 'assistant.step.planningHike',
live: { liveKey: 'assistant.step.planningHikeTo', param: 'place' },