Commit Graph

10 Commits

Author SHA1 Message Date
88dc0c5323 mock: drop a real flight booking → LLM re-anchors the trip
The user drags a flight ticket (PDF/text/ics/html) onto the chat panel,
or uses the new 📎 button. The doc is text-extracted server-side
(pdftotext for PDFs; images rejected with a clear "no OCR" message),
then the LLM reads it, extracts the confirmed arrival + departure
(date, local time, airport, city) and calls a new deterministic tool,
apply_flight_anchors, which reconfigures the trip:

- re-dates the day window across the booked [arrival, departure] span
  (contiguous when the day counts match, evenly spread when they don't)
- records the flights as hard-anchor bookings, replacing placeholders
- shortens the arrival day (start after landing + a real airport→hotel
  taxi time) and the departure day (ends exactly at the booked time)
- trims stops that no longer fit and updates the trip title's range

Undo/redo and reload persistence now version the trip's bookings + title
alongside days/stays, so a re-configuration reverts and reloads cleanly.
Server gains POST /parse-doc. Verified E2E (LLM extraction + reconfigure),
idempotency, drag-and-drop, and undo; non-flight agent unaffected.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-09 13:20:47 -04:00
c7b5ecb8da mock: give the chat assistant a tool-calling agent loop
The LLM now orchestrates the plan instead of only answering from a
static snapshot. It reads the live plan, calls deterministic client-side
tools, and proposes small fix-ops; the tools validate, compute and
commit, so every edit is undo-able (LLM proposes, tools decide).

This llama.cpp build ignores the native OpenAI `tools` field, so tool
calls use a text protocol: the model emits <tool>{"name","args"}</tool>,
the app executes it and feeds the JSON result back as the next turn; the
loop ends when the model stops calling (capped at 10 turns).

Tools: itinerary_summary, search_places, place_facts, route_between
(real OSRM walk, straight-line fallback), review_plan (day overrun /
meal-hour / duplicate checks), and fix-ops add_stop, remove_stop,
move_stop, set_duration, set_start. Places and stops resolve by id or
name; dayIds are surfaced in the plan snapshot ([D1 · date]) so the model
doesn't guess. A subtle ⚙ activity line shows each tool call in the chat.

Verified end-to-end in headless Chrome: factual routing (route_between),
search+swap (search_places→add_stop, incumbent demoted to backup), and
diagnose+fix (review_plan→move_stop→set_start→re-review), with clean
undo-able commits each time.
2026-09-09 11:48:00 -04:00
af63297297 mock: wire the local LLM backend (llama.cpp Qwen3.8-27B-UD3-Q5-dual)
server.js: /llm-status probe + /llm-chat proxy to the local llama.cpp
OpenAI-compatible server (192.168.3.7:1234, model ctx 131072, 2 parallel
sessions). Model name, base URL and token budget pinned server-side
(LLM_BASE/LLM_MODEL/LLM_MAX_TOKENS env to override); non-streaming, since
the hidden thinking text shares max_tokens with the visible answer.

app.js: checkLLM() alongside checkRouter(); free-form chat now goes to the
model with a compact live plan snapshot (bookings, stays, per-day stops
with times) as system context. Deterministic UI intents (discovery
drawer, time nudges, swaps) stay local — the LLM proposes, the UI
commits. Canned-reply fallback when the server is down or the model is
not loaded; status badge now reads e.g. 'online · router · llm'.
2026-09-09 10:19:39 -04:00
33ed5d9fe6 multi-trip mock + Colombia trip with a real walking router
The mock can now work several trips at once: a trip picker in the
topbar, per-trip state in localStorage (edits + version history survive
switching), and a per-trip router key so each trip routes on its own
OSRM extract.

Colombia (Cartagena -> Santa Marta, 8 days) becomes the default working
trip, inside a new walking-profile OSRM instance:
- scripts/crop_pbf.py: streaming 3-pass PBF cropper (no PBF library;
  the country file is too big for osmium extract -s complete_ways on
  this box). Framing validated against osmium test fixtures and
  osrm-extract. Drops relations (foot profile ignores restrictions).
- scripts/setup-osrm-colombia.sh: download -> crop (~4.6 MB) ->
  extract/partition/customize with the official foot.lua -> serve
  :5003. Verified: Getsemaní -> Castillo San Felipe 7.98 km / 96 min.
- server.js: ROUTERS map, ?router=colombia|northeast on /route,
  /table, /router-status (per-router probe points).
- app.js: legs touching a transit stop are fixed (flight/taxi/bus via
  M.multimodal), never re-routed; distance-0 router answers (both
  points on one node) read as adjacent stops, not out-of-coverage.
- multi-hotel fix: day-scope map fit uses the stays covering THAT day,
  so a two-city trip no longer fits the whole country per day.

Also: pre-cache-tiles.sh (Cartagena+Santa Marta z14-16, 2560 tiles),
tile cache write fix (Node rejects flags:'x'; buffer-then-write),
favicon, renderHotelMks load-order guard, tests updated for the new
default trip (all four puppeteer suites green, zero console errors).
2026-09-09 09:44:29 -04:00
30f3dd9cbf mock: wire to the real local OSRM router + L0 trip view, version history, offline cues
- server.js: proxy /route, /table, /router-status to the local OSRM on :5000
- app.js: routeClient (polyline-5 decode, ordered route fetch); legs start as
  straight-line estimates (conf 1) and are upgraded in the background to real
  road geometry + duration (conf 3); out-of-coverage trips (Florence) fall
  back gracefully with a 'estimate — outside router coverage' source
- L3 leg editor: dragging a waypoint now genuinely re-routes through the
  router (was silently no-op — #app covered the map with pointer-events:auto,
  so no map drag ever landed; #app is now pointer-events:none, children opt in)
- data.js: second demo city (Boston 14–16 Sep, inside the router's NE-US
  extract) via ?city=boston; nudges + multimodal legs are now dataset-driven
- L0: Day/Trip scope toggle — per-day summary cards (pacing bar, stops,
  end time, price, base) with click-to-jump; map fits the whole trip
- version history: commit() snapshots days+stays on every mutation; topbar
  vN pill with undo/redo + dropdown timeline showing a diff label per version;
  Ctrl+Z / Ctrl+Shift+Z / Ctrl+Y; restore() re-enriches legs (snapshots may
  predate route enrichment)
- offline: staged 'prepare for offline' card in the trip rail (itinerary →
  POI details → vector tiles) that flips the topbar badge to '📦 offline ready'
- chat/scripts/nudges: Florence-specific strings generalized (stay name/dates,
  vibes, pacing summary) so both demo cities read naturally
2026-09-09 00:47:50 -04:00
146c7e168c mock: redesign around the planning workflow
- one unified canvas: discovery is a drawer over the map (chips: lunch /
  dinner / afternoon / hotel), the plan rail stays visible — no more
  modal focus-mode / dimmed rail
- smoother discovery: 'you might like' suggestion block in the rail
  (unfilled slots / more-like-this-day), region placeholders open the
  drawer, chat still filters an open drawer
- frictionless replacement: every planned stop card expands to inline
  alternatives with one-click swap (incumbent demotes to backup, new
  stop takes its sequence position); candidate cards are draggable and
  drop onto a same-slot stop (swap) or the plan (hold as idea)
- multi-scale comparison: persistent bottom dock lines up 2-4
  candidates/stops side by side (walk from anchor, walk to hotel,
  duration, price, tags) at both hotel and stop scale, with choose /
  idea actions
- gentler load: states read as in plan / idea / backup, issues panel
  becomes 'nudges' (one-tap fixes, 'this day looks good' when clear),
  budget phrasing ('comfortably paced' / 'running a bit full')
- new day strip: horizontal L1 overview of the whole day (stops, legs,
  buffer, return-to-hotel) with hour axis; click a block to fly
- mobile: drawer becomes a bottom sheet, dock sits above the tab bar
2026-09-08 22:54:33 -04:00
fc9cf44052 traffic: live-traffic pipeline (511NY → Overpass match → OSRM segment speeds)
Verified end-to-end on the local OSRM stack:
- internal/traffic: 511NY OData client (lenient decode, raw archive),
  Overpass way matcher (class-window selection: highest-class road within
  150m beats a closer service road), incident policy map, CSV builder
- cmd/traffic: fetch | match | apply; apply copies the dataset (CoW) and
  re-customizes the traffic layer in ~15s (v26 customize has no
  --output-prefix; it writes contract files in place)
- Proof: synthetic I-90 closure → 38s (static :5000) vs 142s (traffic
  :5002) on the same 0.87 km stretch
- Policy speeds are 'assumed' provenance; R4: traffic routes must carry
  computed(traffic, as_of, policy=assumed)
2026-09-06 21:22:36 -04:00
916f9eb503 destination: 39-84 46th St, Sunnyside (OSM way 241831843); durable data location; profile-sensitivity experiment
- destination changed from generic 'Queens NY' to the real address,
  geocoded offline from the NY PBF (addr:street=46th Street,
  addr:housenumber=39-84, postcode 11104 -> 40.74707,-73.9181)
- OSRM tree moved /tmp/osm-build -> /home/gmp/osm-build (durable);
  scripts default W to $HOME/osm-build; LD_LIBRARY_PATH export for
  the baked-in RPATH; cmake stub paths re-pointed
- profile experiment: profiles/car-us.lua (US-tuned speed table on
  stock car.lua) -> Lincoln->Sunnyside 406 -> 377 min vs Valhalla 327;
  README documents the mechanism (motorway=90 x speed_reduction 0.8
  = 72 km/h effective on untagged US interstates)
- bench goldens re-recorded for both backends with new destination;
  both 26/26 PASS, integration tests pass on both routers
2026-09-06 16:48:51 -04:00
0c4a1f9f60 router: working local OSRM backend + per-backend bench goldens
- fix encoded-polyline decoder (zigzag: (n>>1) ^ -(n&1)) — caught by
  the OSRM integration tests (Boston clearance 5681km -> 38km)
- OSRM client: routes[] JSON shape, overview=full for geometry,
  polyline+geojson support
- local OSRM 26.4.1 built from source (no sudo): deps.sh (bzip2, lua
  5.2 with readline stub, oneTBB, boost 1.84 via b2 + hand-rolled
  CMake config files, osmium-tool), setup-osrm.sh (merge PBFs ->
  extract -> partition -> customize -> serve :5000); v26 flag fixes
- bench: tasks.osrm.json goldens; both backends 26/26 PASS and agree
  on all 5 optimized orders (Ladd->Cascade etc.)
- README: profile deltas (Valhalla 332min vs OSRM 410min, same route
  shape), per-backend goldens, verified self-host status
2026-09-06 01:19:37 -04:00
efde2cc71b maps project: design, survey, mock app, and route-aware planning backend
- DESIGN.md: full design incl. driving-trip requirements (R1-R4),
  stays model, focus mode, mobile, provenance rules
- SURVEY.md: open-source landscape
- mock/: interaction mock (Florence itinerary, focus mode, stays,
  region stops, mobile layout)
- router/: Go module (stdlib-only) with Router interface
  (Valhalla + OSRM backends), stop_cost, optimize_stops, corridor,
  routectl CLI, bench (5 real NE-corridor tasks, 26 checks passing),
  integration tests, and setup-osrm.sh for the self-hosted router
- osm/: NH+MA+CT+NY PBFs (gitignored) + setup artifacts
2026-09-06 00:05:17 -04:00