@tomtom-org/maps-sdk-plugin-agent-toolkit 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +513 -0
- package/README.md +520 -0
- package/dist/THIRD_PARTY.txt +1 -0
- package/dist/index.d.ts +4428 -0
- package/dist/index.es.js.js +2 -0
- package/dist/index.es.js.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
# TomTom Maps SDK - Agent Toolkit Plugin
|
|
2
|
+
|
|
3
|
+
A headless conversational agent that gives Large Language Models tool-based control over a [TomTom Map](https://developer.tomtom.com/) and TomTom location services, powered by [Vercel AI SDK v6](https://ai-sdk.dev/).
|
|
4
|
+
|
|
5
|
+
No UI is included — bring your own chat interface. No LLM provider is bundled — supply any AI SDK-compatible model.
|
|
6
|
+
|
|
7
|
+
> **Full documentation** — guides, architecture diagrams, and tutorials are available at [docs.tomtom.com](https://docs.tomtom.com/maps-sdk-js/guides/plugins/ai-agent).
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add @tomtom-org/maps-sdk @tomtom-org/maps-sdk-plugin-agent-toolkit ai zod maplibre-gl
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Install at least one AI SDK provider:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Pick one (or more)
|
|
19
|
+
pnpm add @ai-sdk/openai
|
|
20
|
+
pnpm add @ai-sdk/anthropic
|
|
21
|
+
pnpm add @ai-sdk/azure
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick start
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { TomTomMap } from '@tomtom-org/maps-sdk/map';
|
|
28
|
+
import { createMapAgent } from '@tomtom-org/maps-sdk-plugin-agent-toolkit';
|
|
29
|
+
import { openai } from '@ai-sdk/openai';
|
|
30
|
+
|
|
31
|
+
// 1. Create a TomTom map
|
|
32
|
+
const map = new TomTomMap({
|
|
33
|
+
mapLibre: { container: 'map', center: [4.9, 52.4], zoom: 10 },
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// 2. Create the agent
|
|
37
|
+
const agent = createMapAgent(map, {
|
|
38
|
+
model: openai('gpt-4o'),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// 3. Send a message
|
|
42
|
+
const result = await agent.generate({
|
|
43
|
+
messages: [{ role: 'user', content: 'Find coffee shops near Dam Square, Amsterdam' }],
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
console.log(result.text);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### With React (`useChat`)
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { DirectChatTransport } from 'ai/react';
|
|
53
|
+
import { useChat } from 'ai/react';
|
|
54
|
+
|
|
55
|
+
const agent = createMapAgent(map, { model: openai('gpt-4o') });
|
|
56
|
+
|
|
57
|
+
function ChatPanel() {
|
|
58
|
+
const { messages, sendMessage } = useChat({
|
|
59
|
+
transport: new DirectChatTransport({ agent }),
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<div>
|
|
64
|
+
{messages.map((m) => (
|
|
65
|
+
<div key={m.id}>{m.content}</div>
|
|
66
|
+
))}
|
|
67
|
+
<input onKeyDown={(e) => e.key === 'Enter' && sendMessage(e.target.value)} />
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
See [`examples/map-chat-agent`](../../examples/map-chat-agent) for a full working example.
|
|
74
|
+
|
|
75
|
+
## Tools reference
|
|
76
|
+
|
|
77
|
+
The plugin ships 53 tools organized into five categories. All tools are included by default and can be individually removed or replaced via the [`tools` option](#composing-tool-sets).
|
|
78
|
+
|
|
79
|
+
### Service tools — fetch data from TomTom APIs
|
|
80
|
+
|
|
81
|
+
| Tool | Description |
|
|
82
|
+
|---|---|
|
|
83
|
+
| `locatePlace` | Resolve a location string (landmark, city, address) to a place; optionally stage as a waypoint |
|
|
84
|
+
| `reverseGeocode` | Convert `[longitude, latitude]` coordinates to an address |
|
|
85
|
+
| `discoverPlaces` | Search for places by text query or POI category within an area |
|
|
86
|
+
| `setRouteLocations` | Set waypoints by resolving location queries and calculate a route |
|
|
87
|
+
| `setRouteParameters` | Configure route options (alternatives, avoidances, departure time) and recalculate |
|
|
88
|
+
| `addStopToRoute` | Insert a stop at the optimal position in the current route |
|
|
89
|
+
| `removeStopFromRoute` | Remove a stop by index from the current route |
|
|
90
|
+
| `getPOICategoryCodes` | Look up TomTom POI category codes from natural-language names |
|
|
91
|
+
| `getTrafficIncidents` | Fetch traffic incidents by bounding box or IDs |
|
|
92
|
+
| `getTrafficAreaAnalytics` | Fetch historical traffic analytics (speed, congestion, travel time) for an area |
|
|
93
|
+
| `queryTrafficAnalytics` | Query cached analytics data or check what is currently displayed |
|
|
94
|
+
| `searchAlongRoute` | Search for POIs along a calculated route, ranked by detour cost |
|
|
95
|
+
| `findReachableArea` | Calculate isochrone/isodistance polygons from a point |
|
|
96
|
+
|
|
97
|
+
### TomTom Map tools — render and inspect map state
|
|
98
|
+
|
|
99
|
+
| Tool | Description |
|
|
100
|
+
|---|---|
|
|
101
|
+
| `showPlaces` | Display the most recent place results as markers on the map |
|
|
102
|
+
| `showRoute` | Render the most recently calculated route and fit the camera |
|
|
103
|
+
| `showTrafficAreaAnalytics` | Visualize traffic analytics as hexgrid, heatmap, or tiles |
|
|
104
|
+
| `showWaypoints` | Display staged waypoint markers without the route line |
|
|
105
|
+
| `clearMap` | Remove displayed places, routes, or all features |
|
|
106
|
+
| `getShownPlaces` | List places currently displayed on the map |
|
|
107
|
+
| `getShownRoutes` | List routes currently rendered on the map |
|
|
108
|
+
| `getShownWaypoints` | List waypoint markers currently shown |
|
|
109
|
+
| `getShownRouteSections` | List sections (toll, country, motorway, etc.) of the shown route |
|
|
110
|
+
| `getShownRouteTrafficIncidents` | List traffic incidents overlaid on the shown route |
|
|
111
|
+
| `getShownIncidents` | List real-time incidents visible in the current viewport |
|
|
112
|
+
| `getStandardMapStyles` | List available standard map style presets |
|
|
113
|
+
| `setMapStandardStyle` | Switch map style (light, dark, satellite, driving, etc.) |
|
|
114
|
+
| `setRouteTheme` | Color the route line and waypoint icons |
|
|
115
|
+
| `setLanguage` | Change the language for map labels and API responses |
|
|
116
|
+
| `toggleBaseMapLayerGroups` | Show/hide named layer groups (buildings3D, roadLabels, water, etc.) |
|
|
117
|
+
| `togglePOIs` | Show/hide built-in map POI icons with optional category filtering |
|
|
118
|
+
| `toggleTrafficFlow` | Toggle real-time traffic flow overlay |
|
|
119
|
+
| `toggleTrafficIncidents` | Toggle real-time traffic incident markers |
|
|
120
|
+
| `fitRouteSection` | Fit the camera to a specific route section by type and ID |
|
|
121
|
+
|
|
122
|
+
### MapLibre tools — direct map engine access
|
|
123
|
+
|
|
124
|
+
| Tool | Description |
|
|
125
|
+
|---|---|
|
|
126
|
+
| `flyTo` | Move the camera to a position or bounding box |
|
|
127
|
+
| `getViewport` | Get current map center, zoom, and bounding box |
|
|
128
|
+
| `getMapStyleLayers` | List MapLibre layer IDs with their paint/layout properties |
|
|
129
|
+
| `setLayoutProperties` | Set MapLibre layout properties on named layers |
|
|
130
|
+
| `setPaintProperties` | Set MapLibre paint properties (colors, widths, opacity) on named layers |
|
|
131
|
+
| `setPitchBearing` | Tilt (pitch) and/or rotate (bearing) the camera |
|
|
132
|
+
| `zoomInOrOut` | Adjust the zoom level by a delta |
|
|
133
|
+
| `executeMaplibreCode` | Execute arbitrary MapLibre JS code for maximum flexibility |
|
|
134
|
+
|
|
135
|
+
### State tools — recall session history
|
|
136
|
+
|
|
137
|
+
| Tool | Description |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `recallPlaces` | Retrieve the history of place lookups from this session |
|
|
140
|
+
| `recallRoutes` | Retrieve previously calculated routes from this session |
|
|
141
|
+
| `recallRanges` | Retrieve stored reachable range results |
|
|
142
|
+
| `getCurrentWaypoints` | Get the staged waypoint slots (origin, stops, destination) |
|
|
143
|
+
|
|
144
|
+
### Utility tools — pure computation helpers
|
|
145
|
+
|
|
146
|
+
| Tool | Description |
|
|
147
|
+
|---|---|
|
|
148
|
+
| `calculateBBox` | Compute a bounding box from GeoJSON features or tool results |
|
|
149
|
+
| `formatDistance` | Format meters into a human-readable string (e.g. "2.5 km") |
|
|
150
|
+
| `formatDuration` | Format seconds into a human-readable string (e.g. "1 h 30 min") |
|
|
151
|
+
| `getCurrentLocation` | Get the user's physical GPS location from the browser |
|
|
152
|
+
| `getRouteProgress` | Get the position along the route at a given time or distance |
|
|
153
|
+
| `getSectionProgress` | Get the distance and travel time for route sections by type |
|
|
154
|
+
| `getSectionBBox` | Get the bounding box of a specific route section |
|
|
155
|
+
| `help` | List available capabilities in summary or searchable detail mode |
|
|
156
|
+
|
|
157
|
+
## Customization
|
|
158
|
+
|
|
159
|
+
### `createMapAgent` options
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
// Define custom state by extending ToolState
|
|
163
|
+
interface MyState extends ToolState {
|
|
164
|
+
fleet: FleetState;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const agent = createMapAgent<MyState>(map, {
|
|
168
|
+
// Required: AI SDK language model instance
|
|
169
|
+
model: openai('gpt-4o'),
|
|
170
|
+
|
|
171
|
+
// Include built-in defaults (default: true). Set false for custom-only.
|
|
172
|
+
includeDefaultTools: true,
|
|
173
|
+
|
|
174
|
+
// Add, replace, or remove tools (merged with defaults)
|
|
175
|
+
tools: { myCustomTool: weatherTool },
|
|
176
|
+
|
|
177
|
+
// Append to the built-in system prompt
|
|
178
|
+
systemPromptSuffix: 'Always respond in Spanish. Use metric units.',
|
|
179
|
+
|
|
180
|
+
// Or replace it entirely (systemPromptSuffix is ignored when this is set)
|
|
181
|
+
systemPrompt: 'You are a delivery route planner...',
|
|
182
|
+
|
|
183
|
+
// Custom state slices — only custom fields needed, built-in slices are created automatically
|
|
184
|
+
state: { fleet: new FleetState() },
|
|
185
|
+
|
|
186
|
+
// Intent classifier: omit for default LLM-based, false to disable
|
|
187
|
+
classifier: createDefaultClassifier({ model: openai('gpt-4o-mini') }),
|
|
188
|
+
|
|
189
|
+
// Observe classifier decisions
|
|
190
|
+
onClassify: (result) => console.log('Selected tools:', result?.activeToolNames),
|
|
191
|
+
|
|
192
|
+
// Custom prepareStep hook (composed with internal classification)
|
|
193
|
+
prepareStep: async (stepInfo) => ({ toolChoice: 'auto' }),
|
|
194
|
+
|
|
195
|
+
// Disable structured output schemas for providers that don't support them
|
|
196
|
+
outputSchemas: false,
|
|
197
|
+
|
|
198
|
+
// Max tool-loop iterations (default: 10)
|
|
199
|
+
maxSteps: 15,
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Composing tool sets
|
|
204
|
+
|
|
205
|
+
The `tools` option is merged with the built-in defaults. Use `false` to exclude a tool.
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
import { createMapAgent } from '@tomtom-org/maps-sdk-plugin-agent-toolkit';
|
|
209
|
+
|
|
210
|
+
// Add custom tools (defaults included automatically)
|
|
211
|
+
createMapAgent(map, { model, tools: { getWeather: myWeatherTool } });
|
|
212
|
+
|
|
213
|
+
// Remove specific defaults
|
|
214
|
+
createMapAgent(map, { model, tools: { setMapStandardStyle: false, setLanguage: false } });
|
|
215
|
+
|
|
216
|
+
// Replace a default tool (full ToolEntry required)
|
|
217
|
+
createMapAgent(map, { model, tools: { discoverPlaces: myCustomSearchTool } });
|
|
218
|
+
|
|
219
|
+
// Mix: add, remove, and replace in one call
|
|
220
|
+
createMapAgent(map, {
|
|
221
|
+
model,
|
|
222
|
+
tools: {
|
|
223
|
+
setLanguage: false,
|
|
224
|
+
discoverPlaces: myCustomSearchTool,
|
|
225
|
+
getWeather: myWeatherTool,
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// No defaults — only custom tools
|
|
230
|
+
createMapAgent(map, { model, includeDefaultTools: false, tools: { myTool } });
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Defining custom tools
|
|
234
|
+
|
|
235
|
+
Use `satisfies` for type-safe custom tool definitions:
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
import { type ToolEntry, createMapAgent } from '@tomtom-org/maps-sdk-plugin-agent-toolkit';
|
|
239
|
+
import { z } from 'zod';
|
|
240
|
+
|
|
241
|
+
const fleetTools = {
|
|
242
|
+
trackVehicle: {
|
|
243
|
+
description: 'Track a vehicle by ID on the map.',
|
|
244
|
+
inputSchema: z.object({ vehicleId: z.string() }),
|
|
245
|
+
execute: async ({ vehicleId }, state) => {
|
|
246
|
+
// state is the full ToolState — access state.places, state.routing, etc.
|
|
247
|
+
const position = await fetchVehiclePosition(vehicleId);
|
|
248
|
+
return { vehicleId, position };
|
|
249
|
+
},
|
|
250
|
+
tags: ['fleet'],
|
|
251
|
+
relatedTools: ['showPlaces'],
|
|
252
|
+
},
|
|
253
|
+
} satisfies Record<string, ToolEntry>;
|
|
254
|
+
|
|
255
|
+
// Pass directly — merged with defaults automatically
|
|
256
|
+
createMapAgent(map, { model, tools: fleetTools });
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Tool entry shape
|
|
260
|
+
|
|
261
|
+
Every tool (built-in or custom) follows the `ToolEntry` interface:
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
type ToolEntry<S extends ToolState = ToolState> = {
|
|
265
|
+
description: string; // Operational contract for the LLM
|
|
266
|
+
inputSchema: z.ZodType; // Zod schema for input validation
|
|
267
|
+
outputSchema?: z.ZodType; // Optional structured output schema
|
|
268
|
+
execute: (input, state: S) => Promise<any>;
|
|
269
|
+
|
|
270
|
+
// Classifier metadata (optional)
|
|
271
|
+
classificationPrompt?: string; // One-liner for the intent classifier
|
|
272
|
+
tags?: string[]; // Category tags (e.g. 'location', 'route')
|
|
273
|
+
examples?: string[]; // Code examples
|
|
274
|
+
examplePrompts?: string[]; // Natural language prompt examples
|
|
275
|
+
relatedTools?: string[]; // Tools often used together
|
|
276
|
+
dependsOn?: string[]; // Tools that must run before this one
|
|
277
|
+
};
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## State management
|
|
281
|
+
|
|
282
|
+
`ToolState` is organized by feature area. Each slice manages lazy-initialized map modules and an append-only history of results produced during the session. Built-in slices: `PlacesState`, `RoutingState`, `BaseMapState`, `TrafficState`, `RangeState`, `MapPOIsState`.
|
|
283
|
+
|
|
284
|
+
Create state manually for advanced scenarios:
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
import { createToolState, type ToolState } from '@tomtom-org/maps-sdk-plugin-agent-toolkit';
|
|
288
|
+
|
|
289
|
+
// Base state
|
|
290
|
+
const state = createToolState(map);
|
|
291
|
+
|
|
292
|
+
// With custom slices
|
|
293
|
+
const state = createToolState(map, {
|
|
294
|
+
fleet: new FleetState(),
|
|
295
|
+
weather: new WeatherCache(),
|
|
296
|
+
});
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Custom slices are merged alongside built-in state. When using `createMapAgent`, define an interface extending `ToolState` and pass the type parameter — only custom slices need to be provided:
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
interface MyState extends ToolState {
|
|
303
|
+
fleet: FleetState;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const agent = createMapAgent<MyState>(map, {
|
|
307
|
+
model,
|
|
308
|
+
state: { fleet: new FleetState() },
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
agent.state.fleet; // FleetState — custom slice
|
|
312
|
+
agent.state.places; // PlacesState — built-in slice
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Intent classifier
|
|
316
|
+
|
|
317
|
+
The intent classifier is an optional per-turn optimization that selects which tools the LLM sees, reducing noise and improving accuracy.
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
import { createMapAgent, createDefaultClassifier } from '@tomtom-org/maps-sdk-plugin-agent-toolkit';
|
|
321
|
+
|
|
322
|
+
// Default: uses the main model for classification
|
|
323
|
+
const agent = createMapAgent(map, { model: openai('gpt-4o') });
|
|
324
|
+
|
|
325
|
+
// Use a cheaper model for classification
|
|
326
|
+
const agent = createMapAgent(map, {
|
|
327
|
+
model: openai('gpt-4o'),
|
|
328
|
+
classifier: createDefaultClassifier({ model: openai('gpt-4o-mini') }),
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
// Disable classification entirely (all tools always visible)
|
|
332
|
+
const agent = createMapAgent(map, {
|
|
333
|
+
model: openai('gpt-4o'),
|
|
334
|
+
classifier: false,
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
The classifier prompt is built dynamically from each tool's `classificationPrompt` and `relatedTools` metadata, so it stays in sync automatically when tools are added or renamed.
|
|
339
|
+
|
|
340
|
+
## System prompt
|
|
341
|
+
|
|
342
|
+
The built-in `BASE_SYSTEM_PROMPT` teaches the LLM coordinate conventions, tool execution patterns, location reference rules, and response formatting. You can extend or replace it:
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
import { createMapAgent, BASE_SYSTEM_PROMPT } from '@tomtom-org/maps-sdk-plugin-agent-toolkit';
|
|
346
|
+
|
|
347
|
+
// Append additional instructions
|
|
348
|
+
const agent = createMapAgent(map, {
|
|
349
|
+
model,
|
|
350
|
+
systemPromptSuffix: 'Always use metric units. Respond in Dutch.',
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
// Full replacement
|
|
354
|
+
const agent = createMapAgent(map, {
|
|
355
|
+
model,
|
|
356
|
+
systemPrompt: BASE_SYSTEM_PROMPT + '\n\nYou are a delivery fleet dispatcher...',
|
|
357
|
+
});
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Advanced usage
|
|
361
|
+
|
|
362
|
+
### Manual agent setup
|
|
363
|
+
|
|
364
|
+
Bypass `createMapAgent` for maximum control:
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
import { ToolLoopAgent, stepCountIs, tool } from 'ai';
|
|
368
|
+
import { createToolState, DEFAULT_TOOLS, BASE_SYSTEM_PROMPT } from '@tomtom-org/maps-sdk-plugin-agent-toolkit';
|
|
369
|
+
|
|
370
|
+
const state = createToolState(map);
|
|
371
|
+
const { help, ...toolEntries } = DEFAULT_TOOLS; // customize as needed
|
|
372
|
+
|
|
373
|
+
// Convert ToolEntry records to AI SDK tools (bind state)
|
|
374
|
+
const tools = Object.fromEntries(
|
|
375
|
+
Object.entries(toolEntries).map(([name, entry]) => [
|
|
376
|
+
name,
|
|
377
|
+
tool({
|
|
378
|
+
description: entry.description,
|
|
379
|
+
inputSchema: entry.inputSchema,
|
|
380
|
+
outputSchema: entry.outputSchema,
|
|
381
|
+
execute: async (input) => entry.execute(input, state),
|
|
382
|
+
}),
|
|
383
|
+
]),
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
const agent = new ToolLoopAgent({
|
|
387
|
+
model: openai('gpt-4o'),
|
|
388
|
+
tools,
|
|
389
|
+
instructions: BASE_SYSTEM_PROMPT + '\n\nCustom instructions...',
|
|
390
|
+
stopWhen: stepCountIs(15),
|
|
391
|
+
});
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Wrapping default tools
|
|
395
|
+
|
|
396
|
+
Add logging, analytics, or custom behavior around existing tools:
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
import { DEFAULT_TOOLS, createMapAgent } from '@tomtom-org/maps-sdk-plugin-agent-toolkit';
|
|
400
|
+
|
|
401
|
+
const wrappedDiscover = {
|
|
402
|
+
...DEFAULT_TOOLS.discoverPlaces,
|
|
403
|
+
execute: async (input, state) => {
|
|
404
|
+
console.log('[Analytics] Search:', input.query);
|
|
405
|
+
const result = await DEFAULT_TOOLS.discoverPlaces.execute(input, state);
|
|
406
|
+
console.log('[Analytics] Found:', result.count, 'places');
|
|
407
|
+
return result;
|
|
408
|
+
},
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
createMapAgent(map, { model, tools: { discoverPlaces: wrappedDiscover } });
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### Common configuration patterns
|
|
415
|
+
|
|
416
|
+
**Search-only agent (no routing):**
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
const agent = createMapAgent(map, {
|
|
420
|
+
model,
|
|
421
|
+
tools: {
|
|
422
|
+
setRouteLocations: false,
|
|
423
|
+
setRouteParameters: false,
|
|
424
|
+
addStopToRoute: false,
|
|
425
|
+
removeStopFromRoute: false,
|
|
426
|
+
showRoute: false,
|
|
427
|
+
searchAlongRoute: false,
|
|
428
|
+
},
|
|
429
|
+
});
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
**Locked visual appearance:**
|
|
433
|
+
|
|
434
|
+
```typescript
|
|
435
|
+
const agent = createMapAgent(map, {
|
|
436
|
+
model,
|
|
437
|
+
tools: {
|
|
438
|
+
setMapStandardStyle: false,
|
|
439
|
+
setLanguage: false,
|
|
440
|
+
setLayoutProperties: false,
|
|
441
|
+
setPaintProperties: false,
|
|
442
|
+
toggleBaseMapLayerGroups: false,
|
|
443
|
+
},
|
|
444
|
+
});
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### The `MapAgentInstance`
|
|
448
|
+
|
|
449
|
+
`createMapAgent` returns a `ToolLoopAgent` (usable directly with `DirectChatTransport`) with two extra properties:
|
|
450
|
+
|
|
451
|
+
```typescript
|
|
452
|
+
const agent = createMapAgent(map, { model });
|
|
453
|
+
|
|
454
|
+
agent.state; // Live state — typed as CS when custom state is provided, ToolState otherwise
|
|
455
|
+
agent.destroy(); // Reset all state slices (call on unmount)
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
## Public API exports
|
|
459
|
+
|
|
460
|
+
```typescript
|
|
461
|
+
// Main factory
|
|
462
|
+
export { createMapAgent } from './create-map-agent';
|
|
463
|
+
|
|
464
|
+
// State
|
|
465
|
+
export { createToolState, type StateSlice } from './state';
|
|
466
|
+
|
|
467
|
+
// System prompt
|
|
468
|
+
export { BASE_SYSTEM_PROMPT, buildSystemPrompt } from './system-prompt';
|
|
469
|
+
|
|
470
|
+
// Tool registry
|
|
471
|
+
export { DEFAULT_TOOLS, TOOL_NAMES, type ToolName } from './tools';
|
|
472
|
+
|
|
473
|
+
// Tool composition
|
|
474
|
+
export { resolveTools } from './resolve-tools';
|
|
475
|
+
|
|
476
|
+
// Classifier
|
|
477
|
+
export {
|
|
478
|
+
type ClassificationResult,
|
|
479
|
+
classifyUserIntent,
|
|
480
|
+
createDefaultClassifier,
|
|
481
|
+
extractLastUserText,
|
|
482
|
+
} from './utils/intent-classifier';
|
|
483
|
+
|
|
484
|
+
// Types
|
|
485
|
+
export type {
|
|
486
|
+
Classifier,
|
|
487
|
+
ClassifierContext,
|
|
488
|
+
MapAgentInstance,
|
|
489
|
+
MapAgentOptions,
|
|
490
|
+
ToolEntry,
|
|
491
|
+
ToolMetadata,
|
|
492
|
+
ToolNameHint,
|
|
493
|
+
ToolState,
|
|
494
|
+
} from './types';
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
## Dependencies
|
|
498
|
+
|
|
499
|
+
| Type | Package | Purpose |
|
|
500
|
+
|---|---|---|
|
|
501
|
+
| Peer | `@tomtom-org/maps-sdk` | TomTom Maps SDK (types, services, map modules) |
|
|
502
|
+
| Peer | `ai@^6.0.0` | Vercel AI SDK (ToolLoopAgent, tool types) |
|
|
503
|
+
| Peer | `zod@^3.23.0` | Schema validation |
|
|
504
|
+
| Peer | `maplibre-gl@^5.0.0` | Map rendering engine |
|
|
505
|
+
|
|
506
|
+
## Design principles
|
|
507
|
+
|
|
508
|
+
1. **Client-side only** — uses AI SDK's `DirectChatTransport` + `ToolLoopAgent`. The consumer provides the model; no server infrastructure is required.
|
|
509
|
+
2. **No bundled LLM provider** — supply any AI SDK-compatible `LanguageModel`. Keeps the package provider-agnostic.
|
|
510
|
+
3. **Token-efficient** — all service responses are summarized before reaching the LLM. Full GeoJSON stays in `ToolState`.
|
|
511
|
+
4. **Lazy module initialization** — map modules are instantiated on first use and cached in state.
|
|
512
|
+
5. **Coordinate convention** — always `[longitude, latitude]` per GeoJSON standard, enforced throughout.
|
|
513
|
+
6. **Task-oriented tools** — tool boundaries follow user tasks, not SDK API surface. See [ENGINEERING-GUIDELINES.md](./ENGINEERING-GUIDELINES.md).
|
|
514
|
+
|
|
515
|
+
## References
|
|
516
|
+
|
|
517
|
+
- [AI SDK v6 documentation](https://ai-sdk.dev/)
|
|
518
|
+
- [TomTom Maps SDK documentation](https://developer.tomtom.com/)
|
|
519
|
+
- [Engineering guidelines](./ENGINEERING-GUIDELINES.md) — tool design standards, state management, system prompt structure
|
|
520
|
+
- [Example application](../../examples/map-chat-agent) — full chat interface implementation
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
No third parties dependencies
|