@tomtom-org/maps-sdk-plugin-agent-toolkit 0.17.1 → 0.17.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/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { BaseMapModule, CustomGeoJSONLayerSpec, CustomGeoJSONModule, GeometriesModule, GeometryFillStyle, KnobEntry, KnobTarget, POIsModule, PlaceConnectionDisplay, PlacesModule, PlanningWaypoint, ReachableRangesModule, RoutingModule, StylingFoundationsModule, TerrainModule, TomTomMap, TrafficAreaAnalyticsModule, TrafficAreaAnalyticsModuleConfig, TrafficFlowModule, TrafficIncidentDetailsModule, TrafficIncidentsModule } from "@tomtom-org/maps-sdk/map";
2
2
  import { BBox, CommonPlaceProps, GeographyType, Place, Places, PolygonFeature, PolygonFeatures, ReachableRangeBudget, Route, Routes, TrafficAreaAnalytics, TrafficIncident, WaypointLike } from "@tomtom-org/maps-sdk/core";
3
3
  import { ChartConfiguration } from "chart.js";
4
- import { Map as Map$1 } from "maplibre-gl";
5
4
  import { z } from "zod";
5
+ import { Map as Map$1 } from "maplibre-gl";
6
6
  import { GeoBias, TrafficIncidentDetailsByBBoxParams } from "@tomtom-org/maps-sdk/services";
7
7
  import { LanguageModel, ModelMessage, PrepareStepFunction, ToolLoopAgent, ToolSet } from "ai";
8
8
  //#region src/engine/engine.d.ts
@@ -10,7 +10,7 @@ import { LanguageModel, ModelMessage, PrepareStepFunction, ToolLoopAgent, ToolSe
10
10
  type JobSpec = {
11
11
  /** Ids of every entry this job reads. The engine re-runs the job when any of them changes. */
12
12
  affectedEntryIds: readonly string[];
13
- /** The recipe, opaque to the engine and the single home of the code, compared on re-arm to detect change. */
13
+ /** The recipe, opaque to the engine and the single home of the code. */
14
14
  code: string;
15
15
  /** Whether the engine scans this job. A paused job (`false`) is retained but never run. */
16
16
  active: boolean;
@@ -23,7 +23,7 @@ type JobSpec = {
23
23
  interface Job {
24
24
  /** Ids of every entry this job reads (immutable, as a re-arm with different sources is a different job). */
25
25
  readonly affectedEntryIds: readonly string[];
26
- /** The recipe behind this job, which a re-arm compares to decide whether to drop stale history. */
26
+ /** The recipe behind this job. */
27
27
  readonly code: string;
28
28
  /** Whether the engine currently scans this job. */
29
29
  readonly active: boolean;
@@ -45,6 +45,7 @@ declare class JobEngine {
45
45
  private scanning;
46
46
  private scheduled;
47
47
  private pending;
48
+ private generation;
48
49
  /** Registers a job and returns its handle, which the owner stores as its reference to the recurrence. */
49
50
  register(spec: JobSpec): Job;
50
51
  /** @internal — called by {@link JobHandle.unregister}. */
@@ -78,6 +79,7 @@ declare class JobHandle implements Job {
78
79
  }
79
80
  //#endregion
80
81
  //#region src/tools/shared/sandbox-code.d.ts
82
+ /** @ignore */
81
83
  export type AnalysisOutputFormat = 'json' | 'chart';
82
84
  /**
83
85
  * Compact sandbox-code blurb shared by every code-generation tool, through
@@ -104,7 +106,11 @@ export declare const isChartConfiguration: (value: unknown) => value is ChartCon
104
106
  export declare const isPolygonFeature: <P = unknown>(value: unknown) => value is PolygonFeature<P>;
105
107
  /** @ignore */
106
108
  export declare const isPolygonFeatureArray: <P = unknown>(value: unknown) => value is PolygonFeature<P>[];
107
- /** Shared `describe()` text for the analyse-* `outputFormat` enum field. */
109
+ /**
110
+ * Shared `describe()` text for the analyse-* `outputFormat` enum field.
111
+ *
112
+ * @ignore
113
+ */
108
114
  export declare const ANALYSE_OUTPUT_FORMAT_DESCRIPTION: string;
109
115
  /**
110
116
  * Builds the shared "return value" blurb for the analyse-* tools' `code` field.
@@ -115,6 +121,8 @@ export declare const ANALYSE_OUTPUT_FORMAT_DESCRIPTION: string;
115
121
  * for the specific tool (e.g. "counts, groupings, hex bins, centroids").
116
122
  * @param chartLabelExample Optional inline code snippet illustrating a
117
123
  * multi-line `string[]` label using the tool's domain. Omitted when empty.
124
+ *
125
+ * @ignore
118
126
  */
119
127
  export declare const buildAnalyseReturnPrompt: (jsonExamples: string, chartLabelExample?: string) => string;
120
128
  /**
@@ -136,10 +144,9 @@ export declare const sandboxedGlobalShadows: readonly ["fetch", "XMLHttpRequest"
136
144
  /** @ignore */
137
145
  export declare const WORKER_PROVIDED_PARAMS: readonly ["turf", "h3", "routeUtils", "log", "cluster"];
138
146
  /**
139
- * Pluggable strategy for executing sandbox code. The default
140
- * {@link mainThreadExecutor} compiles and runs in the host realm. An alternative
141
- * executor, such as the iframe-worker one, can run the same code in a locked-down
142
- * realm off the main thread while honouring this exact contract.
147
+ * Pluggable strategy for executing sandbox code, chosen by environment: in a browser
148
+ * the default runs the code in a locked-down iframe worker, off the main thread, and
149
+ * without a DOM it runs in the host realm. Every executor honours this exact contract.
143
150
  *
144
151
  * `run` MUST resolve to `{ value }` or `{ error }` and never reject. Execution
145
152
  * failures are reported as `{ error }` via {@link formatSandboxExecutionError}.
@@ -199,8 +206,9 @@ export declare const stripInjectedRedeclarations: (code: string, identifiers: re
199
206
  * Appends a `Hint:` suffix when the error matches a common pattern so the
200
207
  * model can self-correct on retry. `verb` is the human-readable action used
201
208
  * in the prefix (e.g. `"Analysis"`, `"Process"`).
209
+ *
210
+ * @ignore
202
211
  */
203
- /** @ignore */
204
212
  export declare const formatSandboxExecutionError: (verb: string, error: unknown) => string;
205
213
  //#endregion
206
214
  //#region src/state/events.d.ts
@@ -210,7 +218,8 @@ export declare const formatSandboxExecutionError: (verb: string, error: unknown)
210
218
  * A tiny typed event emitter that every state slice (PlacesState, RoutingState, ...) uses to notify
211
219
  * subscribers when its internals change. Its shape mirrors the SDK's `ModuleEvents` API
212
220
  * (`on(type, handler) => unsubscribe`, `off(type)`), so consumers see one consistent pattern across
213
- * the SDK and the agent toolkit. It plugs straight into React's `useSyncExternalStore`.
221
+ * the SDK and the agent toolkit. To drive React's `useSyncExternalStore`, copy what an event reports into
222
+ * a new snapshot: a slice can still change its `entries` array, and the entries in it, in place.
214
223
  *
215
224
  * @group Agent Toolkit
216
225
  */
@@ -243,7 +252,7 @@ declare class StateEvents<EventMap extends Record<string, unknown>> {
243
252
  * @internal
244
253
  */
245
254
  emit<K extends keyof EventMap>(type: K, payload: EventMap[K]): void;
246
- /** Removes every handler for every type. A slice's `reset()` calls it to detach lingering listeners. */
255
+ /** Removes every handler for every type. */
247
256
  clear(): void;
248
257
  }
249
258
  //#endregion
@@ -257,7 +266,7 @@ declare class StateEvents<EventMap extends Record<string, unknown>> {
257
266
  * @ignore
258
267
  */
259
268
  type EntryAnalysis = {
260
- /** Unique name within the parent entry — used as the key (re-attaching the same name replaces). */
269
+ /** The analysis name. With its sorted source ids it forms the analysis id (see {@link makeAnalysisId}). */
261
270
  name: string;
262
271
  timestamp: number;
263
272
  /** Optional human-readable description of what the analysis computed. */
@@ -280,8 +289,11 @@ type EntryAnalysis = {
280
289
  type AnalysisRecord = {
281
290
  /** Stable handle minted by {@link makeAnalysisId} (name + sorted source ids). */
282
291
  analysisId: string;
292
+ /** The analysis name. With its sorted source ids it forms `analysisId`. */
283
293
  name: string;
294
+ /** Optional human-readable description of what the analysis computes. */
284
295
  description?: string;
296
+ /** How each result's `data` should be interpreted — plain JSON or a Chart.js configuration. */
285
297
  outputFormat: AnalysisOutputFormat;
286
298
  /** Ids of every entry this analysis is attached to. The per-entry lookup key. */
287
299
  affectedEntryIds: readonly string[];
@@ -296,14 +308,16 @@ type AnalysisRecord = {
296
308
  */
297
309
  type AnalysisRegistration = Omit<AnalysisRecord, 'history'>;
298
310
  /**
299
- * Events emitted by {@link Analyses}. One event for "an analysis result was attached or recomputed".
311
+ * Events emitted by {@link Analyses}. One event for "an analysis result was attached or recomputed, or the
312
+ * analysis was removed".
300
313
  *
301
314
  * @ignore
302
315
  */
303
316
  type AnalysesEvents = {
304
317
  /**
305
- * An analysis result landed (one-shot attach or a recompute). Carries the `analysisId` and the ids
306
- * of every entry it touches — a per-entry consumer filters with `affectedEntryIds.includes(id)`.
318
+ * An analysis result landed (one-shot attach or a recompute), or the analysis was removed. Carries the
319
+ * `analysisId` and the ids of every entry it touches — a per-entry consumer filters with
320
+ * `affectedEntryIds.includes(id)`.
307
321
  */
308
322
  'analysis-change': {
309
323
  analysisId: string;
@@ -311,15 +325,15 @@ type AnalysesEvents = {
311
325
  };
312
326
  };
313
327
  /**
314
- * The session-level registry of EVERY analysis, the single source of truth that replaces the per-entry
315
- * `_analyses` stores. It holds one {@link AnalysisRecord} per analysis (keyed by `analysisId`), each
316
- * with its own bounded result history. Entries carry no analysis state. Per-entry views call
328
+ * The session-level registry of EVERY analysis, the single source of truth for analysis state. It
329
+ * holds one {@link AnalysisRecord} per analysis (keyed by `analysisId`), each with its own bounded
330
+ * result history. Entries carry no analysis state. Per-entry views call
317
331
  * {@link getAnalysesForEntry}. `ToolState` holds it as `state.analyses`.
318
332
  *
319
333
  * It is a pure sink of metadata and result history. The recurrence lives on the {@link JobEngine}.
320
- * This registry keeps each monitored analysis's {@link Job} handle in `_jobs` (keyed by `analysisId`)
321
- * so it can pause or resume it ({@link job}) or compare its `code` on re-arm. A one-shot analysis keeps
322
- * a paused job for later promotion.
334
+ * This registry keeps each monitored analysis's {@link Job} handle in `_jobs` (keyed by `analysisId`),
335
+ * so the tools layer can pause or resume it ({@link job}), or keep or retire it on re-arm. A one-shot
336
+ * analysis keeps a paused job for later promotion.
323
337
  *
324
338
  * @group Agent Toolkit
325
339
  */
@@ -327,7 +341,7 @@ declare class Analyses {
327
341
  private readonly _records;
328
342
  /** analysisId → the {@link Job} backing it (one-shot = paused). The reference linking record to engine. */
329
343
  private readonly _jobs;
330
- /** The {@link AnalysesEvents} emitter, fired whenever a result is attached or recomputed. */
344
+ /** The {@link AnalysesEvents} emitter, fired whenever a result is attached or recomputed, or a record removed. */
331
345
  readonly events: StateEvents<AnalysesEvents>;
332
346
  /**
333
347
  * Inserts or replaces a record's metadata, NOT its result (use {@link attachResult}) or its recipe,
@@ -349,9 +363,8 @@ declare class Analyses {
349
363
  */
350
364
  attachResult(analysisId: string, result: EntryAnalysis): void;
351
365
  /**
352
- * Returns the latest result of every analysis attached to `entryId`, in registration order,
353
- * replacing the old per-entry `_analyses.results`. It scans records linearly, fine at session scale
354
- * (one record per distinct analyseData name+sources, plus one per clustered incidents entry).
366
+ * Returns the latest result of every analysis attached to `entryId`, in registration order. It scans
367
+ * records linearly, fine at session scale (one record per distinct analyseData name+sources).
355
368
  */
356
369
  getAnalysesForEntry(entryId: string): readonly EntryAnalysis[];
357
370
  /**
@@ -367,21 +380,24 @@ declare class Analyses {
367
380
  get(analysisId: string): AnalysisRecord | undefined;
368
381
  /** Whether the analysis is currently recomputed on source change (its job exists and is active). */
369
382
  isMonitored(analysisId: string): boolean;
370
- /** Removes an analysis, tearing down its job and dropping the record and handle. */
383
+ /** Removes an analysis, tearing down its job and dropping the record and handle. Emits `analysis-change`. */
371
384
  remove(analysisId: string): void;
372
385
  /**
373
- * Removes every record sharing a `name`, across all source entries, as the old per-entry
374
- * `unregister(name)` dropped a named analysis wherever it was attached.
386
+ * Removes every record sharing a `name`, across all source entries, so a named analysis is dropped
387
+ * wherever it is attached.
375
388
  */
376
389
  removeByName(name: string): void;
377
- /** Drops every record and job handle. `destroyState` calls it automatically (duck-typed `reset`). */
390
+ /**
391
+ * Drops every record and job handle, emitting `analysis-change` for each dropped record.
392
+ * `destroyState` calls it automatically (duck-typed `reset`).
393
+ */
378
394
  reset(): void;
379
395
  }
380
396
  //#endregion
381
397
  //#region src/state/byod/analysis.d.ts
382
398
  /**
383
399
  * A single analysis result attached to a BYOD entry. Alias of the shared {@link EntryAnalysis} —
384
- * every entry kind uses the same result shape; kept as a named export for back-compat.
400
+ * every entry kind uses the same result shape.
385
401
  *
386
402
  * @group Agent Toolkit
387
403
  *
@@ -696,169 +712,379 @@ type BYODEntry = BaseEntry<FeatureCollection$1> & {
696
712
  _shown?: boolean;
697
713
  };
698
714
  //#endregion
699
- //#region src/state/base-map/state.d.ts
715
+ //#region src/state/state.d.ts
700
716
  /**
701
- * State for base map display: style, language, viewport and layers.
702
- *
703
- * It exposes the TomTomMap and MapLibre instances directly, alongside
704
- * lazy-initialized BaseMapModule, StylingFoundationsModule and TerrainModule.
717
+ * The per-slice display policy. With `multiple` (default), several history entries can be on the
718
+ * map at once. With `single`, only the most recent one stays. Switching from `multiple` to
719
+ * `single` automatically drops every entry except the latest and clears their modules, so
720
+ * the map matches the new policy immediately.
705
721
  *
706
722
  * @group Agent Toolkit
707
723
  */
708
- declare class BaseMapState implements StateSlice {
709
- readonly ttMap: TomTomMap;
710
- private _baseMapModule?;
711
- private _stylingFoundationsModule?;
712
- private _terrainModule?;
713
- constructor(ttMap: TomTomMap);
714
- get mapLibreMap(): Map$1;
715
- getBaseMapModule(): Promise<BaseMapModule>;
716
- getStylingFoundationsModule(): Promise<StylingFoundationsModule>;
717
- getTerrainModule(): Promise<TerrainModule>;
718
- get terrainModule(): TerrainModule | undefined;
719
- reset(): void;
720
- }
721
- //#endregion
722
- //#region src/state/slice-knobs.d.ts
724
+ type EntryMode = 'single' | 'multiple';
723
725
  /**
724
- * The knobs set on every module of one kind a slice holds: the modules it holds now, and each one
725
- * it creates later through {@link SliceKnobs.applyTo}. `setMapStyling` sets the knobs of the
726
- * places, routes, geometries, ranges and traffic modules the agent drew through it.
726
+ * A state slice that owns a history of entries and can be set to `single` or `multiple`
727
+ * mode. Every {@link ToolState} slice with `setEntryMode` implements this shape, which lets
728
+ * callers (the `setEntryMode` tool, `createMapAgent`'s `dataEntries` option, …) handle the
729
+ * whole family uniformly without listing slice names.
727
730
  *
728
731
  * @group Agent Toolkit
729
732
  */
730
- declare class SliceKnobs {
731
- readonly catalogue: readonly KnobEntry<string>[];
732
- private readonly modules;
733
- private readonly _values;
734
- /**
735
- * @param catalogue - The catalogue of the module kind, e.g. `routingKnobCatalogue`.
736
- * @param modules - The modules of that kind the slice holds now.
737
- */
738
- constructor(catalogue: readonly KnobEntry<string>[], modules: () => Iterable<KnobTarget<unknown>>);
739
- /** Every knob set, by its id in the catalogue. */
740
- get values(): Readonly<Record<string, unknown>>;
741
- /** Sets the knob on every module, and remembers it for those created later. Throws on an invalid value. */
742
- set(id: string, value: unknown): void;
743
- /** Resets the knob on every module to its default, and forgets it. */
744
- reset(id: string): void;
745
- /** Resets every knob set. */
746
- resetAll(): void;
747
- /** Forgets every knob set without touching the modules, for a slice dropping them. */
748
- clear(): void;
749
- /** Sets every knob remembered on a module the slice just created, and returns it. */
750
- applyTo<MODULE extends KnobTarget<unknown>>(module: MODULE): MODULE;
751
- private _knob;
733
+ interface EntryModeSlice {
734
+ readonly entryMode: EntryMode;
735
+ readonly entries: readonly {
736
+ readonly id: string;
737
+ }[];
738
+ setEntryMode(mode: EntryMode): Promise<void>;
752
739
  }
753
- //#endregion
754
- //#region src/tools/shared/agent-headers.d.ts
755
740
  /**
756
- * @module agent-toolkit-tools
741
+ * The data-entry kind names that `dataEntries` on `createMapAgent` uses. They extend the
742
+ * analyse/process input kinds (`EntryDataKind`) with `ranges`, which has its own
743
+ * entry-mode-supporting slice but is not a top-level input kind for those tools.
744
+ *
745
+ * The kind names are LLM-facing (`routes`, `incidents`) instead of slice names (`routing`,
746
+ * `trafficIncidents`). The slice mapping is internal (see {@link DATA_ENTRY_KIND_TO_SLICE}).
747
+ *
748
+ * @group Agent Toolkit
757
749
  */
758
- export declare const AGENT_TOOLKIT_ID = "AgentToolkit";
750
+ type DataEntryKind = EntryDataKind | 'ranges';
759
751
  /**
760
- * The `tomtom-user-agent` value identifying agent-toolkit traffic. Shared by both paths that carry
761
- * it — {@link withAgentToolkitHeaders} on service calls, `createMapAgent` on the map — so the two
762
- * cannot drift into separate analytics rows.
752
+ * Per-kind configuration accepted by `createMapAgent`'s `dataEntries` option.
763
753
  *
764
- * @ignore
754
+ * @group Agent Toolkit
765
755
  */
766
- export declare const AGENT_TOOLKIT_USER_AGENT: string;
756
+ type DataEntryConfig = {
757
+ /**
758
+ * When `false`, the kind is removed from the agent's data tools:
759
+ * - The kind disappears from the `analyseData` and `processData` scope and input fields.
760
+ * - Its display and fetch tools are dropped from the registry (see {@link TOOLS_BY_DATA_ENTRY_KIND}).
761
+ * Tools spanning kinds, such as `recallState` and `setMapStyling`, stay.
762
+ *
763
+ * Defaults to `true`.
764
+ */
765
+ enabled?: boolean;
766
+ /**
767
+ * The initial entry-display policy for the underlying slice. `single` keeps only the latest
768
+ * entry on the map and hides the others. `multiple` (default) lets several coexist.
769
+ */
770
+ entryMode?: EntryMode;
771
+ };
767
772
  /**
768
- * Tags an SDK service call as coming from agent-toolkit, via the SDK's own supported per-call
769
- * `tomtom-user-agent` override (see `generateTomTomHeaders`, `core/src/util/headers.ts`) — reuses
770
- * an existing, already-allow-listed header rather than adding a new one.
773
+ * Maps each {@link DataEntryKind} (LLM-facing name) to the {@link ToolState} slice key that
774
+ * owns its entries. `createMapAgent` uses it to apply `entryMode` from
775
+ * `dataEntries[kind].entryMode` to the right slice.
771
776
  *
772
- * @ignore
777
+ * @group Agent Toolkit
773
778
  */
774
- export declare const withAgentToolkitHeaders: <P extends object>(params: P) => P;
775
- //#endregion
776
- //#region src/tools/shared/entry-kinds.d.ts
779
+ export declare const DATA_ENTRY_KIND_TO_SLICE: {
780
+ readonly places: "places";
781
+ readonly routes: "routing";
782
+ readonly incidents: "trafficIncidents";
783
+ readonly customGeometries: "customGeometries";
784
+ readonly trafficAreaAnalytics: "trafficAreaAnalytics";
785
+ readonly byod: "byod";
786
+ readonly ranges: "ranges";
787
+ };
777
788
  /**
778
- * Canonical ordering for {@link EntryDataKind}. Used wherever per-kind doc fragments or
779
- * field lists are concatenated — keeps the layout stable regardless of the order kinds
780
- * appear in a scope or enabled-kinds list.
789
+ * The compile-time union of {@link ToolState} keys whose slice supports {@link EntryMode}.
790
+ * Names match the {@link ToolState} keys exactly, such as `routing` (not `routes`) and
791
+ * `customGeometries` (not `geometries`), so the slice name in the tool API never drifts
792
+ * from the property on `state`.
781
793
  *
782
- * @ignore
794
+ * When a new slice implements `setEntryMode`, the union picks up its key, and the runtime
795
+ * list {@link ENTRY_MODE_SLICE_NAMES} fails to type-check until the key is added there too.
796
+ *
797
+ * @group Agent Toolkit
783
798
  */
784
- export declare const ALL_ENTRY_DATA_KINDS: readonly ["places", "routes", "incidents", "customGeometries", "trafficAreaAnalytics", "byod"];
799
+ type EntryModeSliceName = { [K in keyof ToolState]: ToolState[K] extends EntryModeSlice ? K : never; }[keyof ToolState];
785
800
  /**
786
- * Per-kind scope envelope. The classifier emits one of these in `toolScopes.<toolName>`
787
- * to narrow which kinds the tool's per-turn input schema and code-doc mention.
801
+ * The runtime list of slice names that support entry mode. Its `satisfies` clause makes
802
+ * drift a compile error. When a new {@link ToolState} slice gains `setEntryMode`, the
803
+ * package won't build until this constant is updated.
788
804
  *
789
- * @ignore
805
+ * @group Agent Toolkit
790
806
  */
791
- export type EntryKindScope = {
792
- kinds: readonly EntryDataKind[];
793
- };
807
+ export declare const ENTRY_MODE_SLICE_NAMES: readonly EntryModeSliceName[];
794
808
  /**
795
- * Build a zod scope schema that only accepts kinds within the supplied enabled set.
796
- * Mirrors the per-tool scope guard so a classifier picking a disabled kind fails-open
797
- * (the malformed scope is dropped, full surface stays in place).
809
+ * A state slice that owns a set of "entries", each of which can be hidden individually by id, and
810
+ * exposes the shown set. Helpers that hide previously-shown entries before rendering a new one
811
+ * consume it (see `hidePreviousShownEntries`).
798
812
  *
799
- * @ignore
813
+ * {@link PlacesState} doesn't implement it, because it uses a wider per-entry marker-type
814
+ * model (`removeShownEntries(ids)` instead of `hideEntry(id)`).
815
+ *
816
+ * @group Agent Toolkit
800
817
  */
801
- export declare const buildEntryKindScopeSchema: (enabled: readonly EntryDataKind[]) => z.ZodObject<{
802
- kinds: z.ZodArray<z.ZodEnum<{
803
- places: "places";
804
- routes: "routes";
805
- incidents: "incidents";
806
- customGeometries: "customGeometries";
807
- trafficAreaAnalytics: "trafficAreaAnalytics";
808
- byod: "byod";
809
- }>>;
810
- }, z.core.$strip>;
818
+ interface ShownEntriesSlice extends StateSlice {
819
+ readonly entryMode: EntryMode;
820
+ readonly shownEntryIds: ReadonlySet<string>;
821
+ hideEntry(entryId: string): Promise<void>;
822
+ }
823
+ //#endregion
824
+ //#region src/state/byod/state.d.ts
811
825
  /**
812
- * `extra` fragment supplied by the tool — appended to each generated input-field
813
- * description so callers see tool-specific hints alongside the shared metadata.
826
+ * Events fired by {@link BYODState}. Subscribe via `state.byod.events.on(type, handler)`.
814
827
  *
815
- * @ignore
828
+ * @group Agent Toolkit
816
829
  */
817
- type FieldBuildOptions = {
818
- verb: 'analyse' | 'process';
819
- requiredHint: string;
830
+ type BYODStateEvents = {
831
+ /**
832
+ * An entry was added or removed, its layers were replaced, entries were dropped by `single` mode, or
833
+ * `reset()` cleared the history. `entries` is the full snapshot after the change, and `changedIds`
834
+ * lists the ids of the entries this change added, changed in place, or removed.
835
+ */
836
+ 'entries-change': {
837
+ entries: readonly BYODEntry[];
838
+ changedIds: readonly string[];
839
+ };
840
+ /** The set of entries rendered on the map changed. */
841
+ 'shown-change': ReadonlySet<string>;
842
+ /** The display policy switched between `single` and `multiple`. */
843
+ 'mode-change': EntryMode;
820
844
  };
821
845
  /**
822
- * Per-kind metadata. One row per {@link EntryDataKind}. Owns:
823
- * - field name + label used in schemas and "at least one of" messages;
824
- * - the factory that produces the `*EntryIDs` zod field for a given tool verb;
825
- * - the one-line sandbox-doc fragment ("• `placesByEntry` — object keyed by entry id …");
826
- * - the deep schema-doc fragment (only included when scope commits to this kind);
827
- * - which recall tool the LLM should call to list available ids.
846
+ * Options accepted by {@link BYODState.addEntry}.
828
847
  *
829
- * @ignore
848
+ * @group Agent Toolkit
830
849
  */
831
- export type EntryKindMeta = {
832
- fieldName: string;
833
- fieldLabel: string;
834
- buildField: (options: FieldBuildOptions) => z.ZodTypeAny;
835
- sandboxDoc: string;
836
- schemaDoc: string;
837
- recallTool: string;
850
+ type AddBYODEntryOptions = {
851
+ /**
852
+ * Explicit MapLibre layer specs, never derived automatically. You pass them here,
853
+ * or the agent sets them via `setByodLayers`. Until then the entry renders nothing.
854
+ * Either way they are only stored, and {@link BYODState.showEntry} renders them.
855
+ */
856
+ layers?: CustomGeoJSONLayerSpec[];
857
+ /** Provenance for the data. Defaults to `{ kind: 'integrator' }`. */
858
+ source?: BYODSource;
859
+ /**
860
+ * Semantic entry id. Auto-suffixed (`-2`, `-3`, …) on collision. Defaults
861
+ * to `byod-N`.
862
+ */
863
+ explicitId?: string;
838
864
  };
839
865
  /**
840
- * Single source of truth for the per-kind input vocabulary. Both `analyseData` and
841
- * `processData` read this map to assemble their input schemas and doc fragments.
866
+ * The verdict a {@link ByodSourceUrlValidator} returns. `{ valid: true }` explicitly allows
867
+ * the fetch, and `{ valid: false, reason }` blocks it and surfaces the `reason` to the model
868
+ * as the tool error.
842
869
  *
843
- * @ignore
870
+ * @group Agent Toolkit
844
871
  */
845
- export declare const ENTRY_KIND_META: Record<EntryDataKind, EntryKindMeta>;
872
+ type ByodSourceUrlValidation = {
873
+ valid: true;
874
+ } | {
875
+ valid: false;
876
+ reason: string;
877
+ };
846
878
  /**
847
- * Resolve the set of kinds active for a single per-turn build: the intersection of
848
- * the agent's enabled kinds and the classifier's per-turn scope. `scope === undefined`
849
- * means "no per-turn narrowing — every enabled kind stays in scope".
879
+ * An app-supplied authorization hook for BYOD source URLs. `addByodSource` runs it on
880
+ * every `http:` or `https:` URL, before the network fetch. Return `{ valid: true }` to
881
+ * allow the fetch or `{ valid: false, reason }` to block it (see
882
+ * {@link ByodSourceUrlValidation}). It may be sync or async, such as an allowlist lookup.
850
883
  *
851
- * @ignore
852
- */
853
- export declare const resolveActiveKinds: (enabled: readonly EntryDataKind[], scope: EntryKindScope | undefined) => readonly EntryDataKind[];
854
- /**
855
- * Predicate form of {@link resolveActiveKinds} for a single kind. Used when generating
856
- * tool-specific fields (e.g. analyseData's `monitor`) that should only appear when
857
- * `incidents` is in the active set.
884
+ * It **replaces** the built-in policy, which allows only public `https:` URLs: no
885
+ * `http:`, no page origin, no `localhost`-style hostname and no loopback, private,
886
+ * link-local or other non-public IP address. The size cap, the timeout, the omitted
887
+ * credentials and the refused redirects apply either way. Set it via the
888
+ * `byod.validateSourceUrl` option on `createMapAgent`, or assign
889
+ * `state.byod.sourceUrlValidator` directly.
858
890
  *
859
- * @ignore
891
+ * @group Agent Toolkit
860
892
  */
861
- export declare const isKindActive: (enabled: readonly EntryDataKind[], scope: EntryKindScope | undefined, kind: EntryDataKind) => boolean;
893
+ type ByodSourceUrlValidator = (url: URL) => ByodSourceUrlValidation | Promise<ByodSourceUrlValidation>;
894
+ /**
895
+ * The state slice for BYOD (bring-your-own-data) GeoJSON layers, the customer-owned
896
+ * data that doesn't fit places, routes, ranges or custom geometries. Each entry
897
+ * wraps a {@link CustomGeoJSONModule} so the agent can render, query, and pipe it
898
+ * through analyseData or processData.
899
+ *
900
+ * As in {@link CustomGeometriesState}, every entry owns its own module, initialised
901
+ * lazily on first show.
902
+ *
903
+ * @group Agent Toolkit
904
+ */
905
+ declare class BYODState implements ShownEntriesSlice {
906
+ private readonly _ttMap;
907
+ private _entries;
908
+ private readonly _history;
909
+ private _entryMode;
910
+ private _addedCount;
911
+ private readonly _creatingModules;
912
+ /** The state change events, listed in {@link BYODStateEvents}. */
913
+ readonly events: StateEvents<BYODStateEvents>;
914
+ /**
915
+ * The optional authorization hook for `addByodSource` URL fetches (see
916
+ * {@link ByodSourceUrlValidator}). If unset, the built-in policy allows only
917
+ * public `https:` URLs.
918
+ */
919
+ sourceUrlValidator?: ByodSourceUrlValidator;
920
+ constructor(_ttMap: TomTomMap);
921
+ get entries(): readonly BYODEntry[];
922
+ get latestEntry(): BYODEntry | undefined;
923
+ /** Set of BYOD entry ids currently rendered on the map. */
924
+ get shownEntryIds(): ReadonlySet<string>;
925
+ get entryMode(): EntryMode;
926
+ setEntryMode(mode: EntryMode): Promise<void>;
927
+ findById(entryId: string): BYODEntry | undefined;
928
+ /**
929
+ * Appends a new BYOD entry and returns its assigned id. In `single` mode the new entry
930
+ * replaces every older one. It hides and drops them before pushing the new entry, so the
931
+ * caller never sees it rendered on top of a still-visible old one.
932
+ */
933
+ addEntry(data: FeatureCollection$1, label: string, options?: AddBYODEntryOptions): Promise<string>;
934
+ /**
935
+ * Replaces the MapLibre layer specs an entry renders under. If the entry already owns a
936
+ * module because it was shown at least once, the module's `applyConfig` runtime layer diff
937
+ * pushes the new specs live, without tear-down or flicker. Otherwise the specs are stored
938
+ * and the next {@link showEntry} picks them up. Throws on an unknown id, and keeps the previous
939
+ * specs when the module rejects the new ones.
940
+ */
941
+ setEntryLayers(entryId: string, layers: CustomGeoJSONLayerSpec[]): void;
942
+ /**
943
+ * Initialises the entry's CustomGeoJSONModule lazily. The module has a single
944
+ * source named `data`, configured with this entry's `layers`. To swap layers
945
+ * afterwards, call {@link setEntryLayers}, which pushes the new specs into this
946
+ * module via `applyConfig` instead of recreating it. Rejects for an entry with no layers yet, such as
947
+ * one `addByodSource` just added, since the module needs at least one.
948
+ */
949
+ getEntryModule(entryId: string): Promise<CustomGeoJSONModule>;
950
+ private _entryModule;
951
+ /** Renders the entry on the map. */
952
+ showEntry(entryId: string): Promise<void>;
953
+ private _hideOthersUnderSingleMode;
954
+ hideEntry(entryId: string): Promise<void>;
955
+ private _hideEntry;
956
+ /** Drops an entry from history and clears its module. Does nothing for an unknown id. */
957
+ removeEntry(entryId: string): Promise<void>;
958
+ private _requireEntry;
959
+ /**
960
+ * Hides every BYOD layer on the map but keeps the history. Implements
961
+ * {@link ClearableMapSlice}.
962
+ */
963
+ clearShown(): Promise<void>;
964
+ reset(): void;
965
+ }
966
+ //#endregion
967
+ //#region src/state/custom-geometries/analysis.d.ts
968
+ /**
969
+ * A single analysis result attached to a custom-geometries entry. Alias of the shared
970
+ * {@link EntryAnalysis} — every entry kind uses the same result shape.
971
+ *
972
+ * @group Agent Toolkit
973
+ *
974
+ * @ignore
975
+ */
976
+ type CustomGeometriesAnalysis = EntryAnalysis;
977
+ //#endregion
978
+ //#region src/tools/shared/agent-headers.d.ts
979
+ /**
980
+ * @module agent-toolkit-tools
981
+ */
982
+ /** @ignore */
983
+ export declare const AGENT_TOOLKIT_ID = "AgentToolkit";
984
+ /**
985
+ * The `tomtom-user-agent` value identifying agent-toolkit traffic. Shared by both paths that carry
986
+ * it — {@link withAgentToolkitHeaders} on service calls, `createMapAgent` on the map — so the two
987
+ * cannot drift into separate analytics rows.
988
+ *
989
+ * @ignore
990
+ */
991
+ export declare const AGENT_TOOLKIT_USER_AGENT: string;
992
+ /**
993
+ * Tags an SDK service call as coming from agent-toolkit, via the SDK's own supported per-call
994
+ * `tomtom-user-agent` override (see `generateTomTomHeaders`, `core/src/util/headers.ts`) — reuses
995
+ * an existing, already-allow-listed header rather than adding a new one.
996
+ *
997
+ * @ignore
998
+ */
999
+ export declare const withAgentToolkitHeaders: <P extends object>(parameters: P) => P;
1000
+ //#endregion
1001
+ //#region src/tools/shared/entry-kinds.d.ts
1002
+ /**
1003
+ * Canonical ordering for {@link EntryDataKind}. Used wherever per-kind doc fragments or
1004
+ * field lists are concatenated — keeps the layout stable regardless of the order kinds
1005
+ * appear in a scope or enabled-kinds list.
1006
+ *
1007
+ * @ignore
1008
+ */
1009
+ export declare const ALL_ENTRY_DATA_KINDS: readonly ["places", "routes", "incidents", "customGeometries", "trafficAreaAnalytics", "byod"];
1010
+ /**
1011
+ * Per-kind scope envelope. The classifier emits one of these in `toolScopes.<toolName>`
1012
+ * to narrow which kinds the tool's per-turn input schema and code-doc mention.
1013
+ *
1014
+ * @ignore
1015
+ */
1016
+ export type EntryKindScope = {
1017
+ kinds: readonly EntryDataKind[];
1018
+ };
1019
+ /**
1020
+ * Build a zod scope schema that only accepts kinds within the supplied enabled set.
1021
+ * Mirrors the per-tool scope guard so a classifier picking a disabled kind fails-open
1022
+ * (the malformed scope is dropped, full surface stays in place).
1023
+ *
1024
+ * @ignore
1025
+ */
1026
+ export declare const buildEntryKindScopeSchema: (enabled: readonly EntryDataKind[]) => z.ZodObject<{
1027
+ kinds: z.ZodArray<z.ZodEnum<{
1028
+ places: "places";
1029
+ routes: "routes";
1030
+ trafficAreaAnalytics: "trafficAreaAnalytics";
1031
+ customGeometries: "customGeometries";
1032
+ byod: "byod";
1033
+ incidents: "incidents";
1034
+ }>>;
1035
+ }, z.core.$strip>;
1036
+ /**
1037
+ * What the calling tool supplies to word each generated input-field description: its verb and
1038
+ * its "at least one of" hint.
1039
+ *
1040
+ * @ignore
1041
+ */
1042
+ type FieldBuildOptions = {
1043
+ verb: 'analyse' | 'process';
1044
+ requiredHint: string;
1045
+ };
1046
+ /**
1047
+ * Per-kind metadata. One row per {@link EntryDataKind}. Owns:
1048
+ * - field name + label used in schemas and "at least one of" messages;
1049
+ * - the factory that produces the `*EntryIDs` zod field for a given tool verb;
1050
+ * - the one-line sandbox-doc fragment ("• `placesByEntry` — object keyed by entry id …");
1051
+ * - the deep schema-doc fragment (only included when scope commits to this kind);
1052
+ * - which recall tool the LLM should call to list available ids, and the kind's name in a missing-id error.
1053
+ *
1054
+ * @ignore
1055
+ */
1056
+ export type EntryKindMeta = {
1057
+ fieldName: string;
1058
+ fieldLabel: string;
1059
+ buildField: (options: FieldBuildOptions) => z.ZodTypeAny;
1060
+ sandboxDoc: string;
1061
+ schemaDoc: string;
1062
+ recallTool: string;
1063
+ entryLabel: string;
1064
+ };
1065
+ /**
1066
+ * Single source of truth for the per-kind input vocabulary. Both `analyseData` and
1067
+ * `processData` read this map to assemble their input schemas and doc fragments.
1068
+ *
1069
+ * @ignore
1070
+ */
1071
+ export declare const ENTRY_KIND_META: Record<EntryDataKind, EntryKindMeta>;
1072
+ /**
1073
+ * Resolve the set of kinds active for a single per-turn build: the intersection of
1074
+ * the agent's enabled kinds and the classifier's per-turn scope. `scope === undefined`
1075
+ * means "no per-turn narrowing — every enabled kind stays in scope".
1076
+ *
1077
+ * @ignore
1078
+ */
1079
+ export declare const resolveActiveKinds: (enabled: readonly EntryDataKind[], scope: EntryKindScope | undefined) => readonly EntryDataKind[];
1080
+ /**
1081
+ * Predicate form of {@link resolveActiveKinds} for a single kind. Used when generating
1082
+ * tool-specific fields (e.g. analyseData's `monitor`) that should only appear when
1083
+ * `incidents` is in the active set.
1084
+ *
1085
+ * @ignore
1086
+ */
1087
+ export declare const isKindActive: (enabled: readonly EntryDataKind[], scope: EntryKindScope | undefined, kind: EntryDataKind) => boolean;
862
1088
  /**
863
1089
  * Slash-joined list of scoped `*EntryIDs` field labels — used in "At least one of `A` / `B`
864
1090
  * must be set." messages and in per-field hints. Order follows {@link ALL_ENTRY_DATA_KINDS}.
@@ -875,8 +1101,7 @@ export declare const buildEntryFieldList: (active: readonly EntryDataKind[]) =>
875
1101
  export declare const buildEntryKindSandboxDocs: (active: readonly EntryDataKind[]) => string;
876
1102
  /**
877
1103
  * Join the per-kind deep schema-doc fragments in canonical order for the supplied active
878
- * set. Empty when no active kind has a schema doc (only places / routes / customGeometries
879
- * carry one today).
1104
+ * set. Empty when no active kind has a schema doc (`byod` carries none).
880
1105
  *
881
1106
  * @ignore
882
1107
  */
@@ -895,8 +1120,7 @@ export declare const buildEntryIdFields: (active: readonly EntryDataKind[], opti
895
1120
  * "at least one of …" refine so both tools agree on what counts as "input present".
896
1121
  *
897
1122
  * `geometriesEntryIDs` carries `GeometriesId[]`; the rest carry `string[]`. We treat
898
- * either as "present" when the array has length, which is what the existing inline
899
- * refines did.
1123
+ * either as "present" when the array has length.
900
1124
  *
901
1125
  * @ignore
902
1126
  */
@@ -947,6 +1171,8 @@ export declare const applyFitOnMap: (state: ToolState, fit: FitOnMapInput) => z.
947
1171
  * from drowning the area. Without it, "De Pijp" and "Westminster" geocode to Streets at rank 0.
948
1172
  * Excludes `Country` (too coarse) and `PostalCodeArea` (homonym noise, such as "A10" matching a
949
1173
  * Kazakh postcode).
1174
+ *
1175
+ * @ignore
950
1176
  */
951
1177
  export declare const AREA_GEOGRAPHY_TYPES: GeographyType[];
952
1178
  /**
@@ -954,11 +1180,13 @@ export declare const AREA_GEOGRAPHY_TYPES: GeographyType[];
954
1180
  * `bias` (the map centre). Because `geographyTypes` filters to areas, every result carries a
955
1181
  * `boundingBox`. Callers choose among the candidates, for example the one nearest the current view.
956
1182
  * A centre bias is used rather than a hard viewport-bbox filter, so out-of-view areas still resolve.
1183
+ *
1184
+ * @ignore
957
1185
  */
958
- export declare const geocodeAreas: (query: string, opts?: {
1186
+ export declare const geocodeAreas: (query: string, options?: {
959
1187
  bias?: Position;
960
1188
  limit?: number;
961
- }, execOptions?: ToolExecuteOptions) => Promise<Place[]>;
1189
+ }, executeOptions?: ToolExecuteOptions) => Promise<Place[]>;
962
1190
  //#endregion
963
1191
  //#region src/tools/shared/geometries-id.d.ts
964
1192
  /**
@@ -966,7 +1194,7 @@ export declare const geocodeAreas: (query: string, opts?: {
966
1194
  *
967
1195
  * @group Agent Toolkit
968
1196
  */
969
- export type GeometriesIdKind = 'place' | 'places' | 'ranges' | 'customGeometries';
1197
+ export type GeometriesIdKind = GeometriesId['kind'];
970
1198
  /**
971
1199
  * Tagged geometries id. The Zod schema is exposed so tools can plug it
972
1200
  * straight into their input shape (`z.array(geometriesIdSchema).min(1)`),
@@ -1047,39 +1275,174 @@ export declare const GEOMETRIES_SOURCE_IDS_DESC = "Tagged input ids that contrib
1047
1275
  /** @ignore */
1048
1276
  export declare const GEOMETRIES_SCHEMA_DOC: string;
1049
1277
  //#endregion
1050
- //#region src/state/custom-geometries/analysis.d.ts
1278
+ //#region src/state/base-map/state.d.ts
1051
1279
  /**
1052
- * A single analysis result attached to a custom-geometries entry. Alias of the shared
1053
- * {@link EntryAnalysis} — every entry kind uses the same result shape; kept as a named export for
1054
- * back-compat.
1280
+ * State for the base map.
1281
+ *
1282
+ * It exposes the TomTomMap and MapLibre instances directly, alongside
1283
+ * lazy-initialized BaseMapModule, StylingFoundationsModule and TerrainModule.
1055
1284
  *
1056
1285
  * @group Agent Toolkit
1286
+ */
1287
+ declare class BaseMapState implements StateSlice {
1288
+ readonly ttMap: TomTomMap;
1289
+ private _terrainModule?;
1290
+ constructor(ttMap: TomTomMap);
1291
+ get mapLibreMap(): Map$1;
1292
+ getBaseMapModule(): Promise<BaseMapModule>;
1293
+ getStylingFoundationsModule(): Promise<StylingFoundationsModule>;
1294
+ getTerrainModule(): Promise<TerrainModule>;
1295
+ get terrainModule(): TerrainModule | undefined;
1296
+ reset(): void;
1297
+ }
1298
+ //#endregion
1299
+ //#region src/state/slice-knobs.d.ts
1300
+ /**
1301
+ * The knobs set on every module of one kind a slice holds: the modules it holds now, and each one
1302
+ * it creates later through {@link SliceKnobs.applyTo}. `setMapStyling` sets the knobs of the
1303
+ * places, routes, geometries, ranges and traffic modules the agent drew through it.
1057
1304
  *
1058
- * @ignore
1305
+ * @group Agent Toolkit
1059
1306
  */
1060
- type CustomGeometriesAnalysis = EntryAnalysis;
1307
+ declare class SliceKnobs {
1308
+ readonly catalogue: readonly KnobEntry<string>[];
1309
+ private readonly modules;
1310
+ private readonly _values;
1311
+ /**
1312
+ * @param catalogue - The catalogue of the module kind, e.g. `routingKnobCatalogue`.
1313
+ * @param modules - The modules of that kind the slice holds now.
1314
+ */
1315
+ constructor(catalogue: readonly KnobEntry<string>[], modules: () => Iterable<KnobTarget<unknown>>);
1316
+ /** Every knob set, by its id in the catalogue. */
1317
+ get values(): Readonly<Record<string, unknown>>;
1318
+ /** Sets the knob on every module, and remembers it for those created later. Throws on an invalid value. */
1319
+ set(id: string, value: unknown): void;
1320
+ /** Resets the knob on every module to its default, and forgets it. */
1321
+ reset(id: string): void;
1322
+ /** Resets every knob set. */
1323
+ resetAll(): void;
1324
+ /** Forgets every knob set without touching the modules, for a slice dropping them. */
1325
+ clear(): void;
1326
+ /** Sets every knob remembered on a module the slice just created, and returns it. */
1327
+ applyTo<MODULE extends KnobTarget<unknown>>(module: MODULE): MODULE;
1328
+ }
1061
1329
  //#endregion
1062
- //#region src/state/digest.d.ts
1330
+ //#region src/state/custom-geometries/state.d.ts
1063
1331
  /**
1064
- * A compact, diffable snapshot of the user-visible parts of `ToolState`. Every field serialises to
1065
- * JSON and stays stable for `===` comparison while the underlying state is unchanged.
1332
+ * Events fired by {@link CustomGeometriesState}. Subscribe via
1333
+ * `state.customGeometries.events.on(type, handler)`.
1066
1334
  *
1067
1335
  * @group Agent Toolkit
1068
1336
  */
1069
- type StateDigest = {
1070
- places: {
1071
- /** Entry ids currently rendered as individual pins, sorted ascending. */
1072
- shownAsPin: string[];
1073
- /** Entry ids currently rendered as base-map POIs, sorted ascending. */
1074
- shownAsBaseMap: string[];
1075
- /** The slice's display policy, `multiple` (default) or `single`. */
1076
- entryMode: EntryMode;
1337
+ type CustomGeometriesStateEvents = {
1338
+ /**
1339
+ * An entry was added or removed, entries were dropped by `single` mode, or `reset()` cleared the
1340
+ * history. `entries` is the full snapshot after the change, and `changedIds` lists the ids of the
1341
+ * entries this change added or removed.
1342
+ */
1343
+ 'entries-change': {
1344
+ entries: readonly CustomGeometriesEntry[];
1345
+ changedIds: readonly string[];
1077
1346
  };
1078
- routes: {
1079
- /** Routes-entry ids currently drawn on the map, sorted ascending. */
1080
- shown: string[];
1081
- /** The slice's display policy, `multiple` (default) or `single`. */
1082
- entryMode: EntryMode;
1347
+ /** The set of entries rendered on the map changed. */
1348
+ 'shown-change': ReadonlySet<string>;
1349
+ /** The display policy switched between `single` and `multiple`. */
1350
+ 'mode-change': EntryMode;
1351
+ };
1352
+ /**
1353
+ * The state for derived or custom geometries, the output of `processData` and any future
1354
+ * polygon-producing tool whose result doesn't belong to a place or a reachable-range entry.
1355
+ *
1356
+ * As in {@link RangeState}, each entry owns a dedicated GeometriesModule, initialised lazily
1357
+ * on first show. Provenance metadata captures the input sources (tagged ids) and the
1358
+ * operation that produced the polygons.
1359
+ *
1360
+ * @group Agent Toolkit
1361
+ */
1362
+ declare class CustomGeometriesState implements ShownEntriesSlice {
1363
+ private readonly _ttMap;
1364
+ private _entries;
1365
+ private readonly _history;
1366
+ private _entryMode;
1367
+ private _addedCount;
1368
+ private readonly _creatingModules;
1369
+ /** The state change events, listed in {@link CustomGeometriesStateEvents}. */
1370
+ readonly events: StateEvents<CustomGeometriesStateEvents>;
1371
+ /** The knobs set on every entry's GeometriesModule, such as `line.width`. Cleared on `reset`. */
1372
+ readonly knobs: SliceKnobs;
1373
+ constructor(_ttMap: TomTomMap);
1374
+ get entries(): readonly CustomGeometriesEntry[];
1375
+ get latestEntry(): CustomGeometriesEntry | undefined;
1376
+ /** Set of custom-geometries entry ids currently rendered on the map. */
1377
+ get shownEntryIds(): ReadonlySet<string>;
1378
+ /**
1379
+ * The display policy. `multiple` (default) lets several derived-geometry entries render
1380
+ * side by side. `single` allows at most one entry on the map, and switching to it hides
1381
+ * older entries.
1382
+ */
1383
+ get entryMode(): EntryMode;
1384
+ setEntryMode(mode: EntryMode): Promise<void>;
1385
+ findById(entryId: string): CustomGeometriesEntry | undefined;
1386
+ /**
1387
+ * Appends a new entry and returns its assigned id. If `explicitId` collides, the slice adds a
1388
+ * suffix (`-2`, `-3`, ...). In `single` mode the new entry replaces every older one.
1389
+ */
1390
+ addEntry(features: PolygonFeature<CommonPlaceProps>[], provenance: CustomGeometriesEntry['provenance'], label: string, explicitId?: string): Promise<string>;
1391
+ /**
1392
+ * Initialises the entry's GeometriesModule lazily, in `fillStyle` or as an outline. After that, a
1393
+ * passed `fillStyle` updates only the fill style, keeping the styling applied since.
1394
+ */
1395
+ getEntryGeometriesModule(entryId: string, fillStyle?: GeometryFillStyle): Promise<GeometriesModule>;
1396
+ private _geometriesModule;
1397
+ /**
1398
+ * Renders the entry's polygons. `mode` applies to this entry's own layer only:
1399
+ * - `'replace'` (default) shows exactly `entry.data` and clears whatever the
1400
+ * entry's module rendered before.
1401
+ * - `'add'` merges `entry.data` with the polygons shown on this entry's layer,
1402
+ * deduped by feature id. It matters mostly when re-showing the same entry.
1403
+ *
1404
+ * `fillStyle` restyles the entry's module; omit it to keep its current style, an outline at first.
1405
+ *
1406
+ * Other entries are handled separately. With `entryMode === 'single'`, other shown
1407
+ * entries are hidden first. Otherwise the caller uses `hideEntry` or the tools'
1408
+ * `hidePreviousEntries` option.
1409
+ */
1410
+ showEntry(entryId: string, fillStyle?: GeometryFillStyle, mode?: 'add' | 'replace'): Promise<void>;
1411
+ private _hideOthersUnderSingleMode;
1412
+ hideEntry(entryId: string): Promise<void>;
1413
+ private _hideEntry;
1414
+ /** Drops an entry from history and clears its module. Does nothing for an unknown id. */
1415
+ removeEntry(entryId: string): Promise<void>;
1416
+ private _requireEntry;
1417
+ /**
1418
+ * Hides every custom-geometries entry on the map but keeps the history. Implements
1419
+ * {@link ClearableMapSlice}.
1420
+ */
1421
+ clearShown(): Promise<void>;
1422
+ reset(): void;
1423
+ }
1424
+ //#endregion
1425
+ //#region src/state/digest.d.ts
1426
+ /**
1427
+ * A compact, diffable snapshot of the user-visible parts of `ToolState`. Every field serialises to
1428
+ * JSON. Each call builds new arrays, so compare two digests with {@link formatStateDigestDiff}, not `===`.
1429
+ *
1430
+ * @group Agent Toolkit
1431
+ */
1432
+ type StateDigest = {
1433
+ places: {
1434
+ /** Entry ids currently rendered as individual pins, sorted ascending. */
1435
+ shownAsPin: string[];
1436
+ /** Entry ids currently rendered as base-map POIs, sorted ascending. */
1437
+ shownAsBaseMap: string[];
1438
+ /** The slice's display policy, `multiple` (default) or `single`. */
1439
+ entryMode: EntryMode;
1440
+ };
1441
+ routes: {
1442
+ /** Routes-entry ids currently drawn on the map, sorted ascending. */
1443
+ shown: string[];
1444
+ /** The slice's display policy, `multiple` (default) or `single`. */
1445
+ entryMode: EntryMode;
1083
1446
  };
1084
1447
  ranges: {
1085
1448
  /** Range-entry ids currently drawn on the map, sorted ascending. */
@@ -1134,15 +1497,15 @@ export declare const getStateDigest: (state: ToolState) => StateDigest;
1134
1497
  *
1135
1498
  * @example
1136
1499
  * ```ts
1137
- * const prev = getStateDigest(state);
1500
+ * const previous = getStateDigest(state);
1138
1501
  * // ... user clicks around in the UI ...
1139
- * const diff = formatStateDigestDiff(prev, getStateDigest(state));
1140
- * // → '[map state changed since last response: places shown as pins: "amsterdam-cinemas"; route now "routes-2"]'
1502
+ * const diff = formatStateDigestDiff(previous, getStateDigest(state));
1503
+ * // → '[map state changed since last response: places shown as pins: "amsterdam-cinemas"; routes shown: "routes-2"]'
1141
1504
  * ```
1142
1505
  *
1143
1506
  * @group Agent Toolkit
1144
1507
  */
1145
- export declare const formatStateDigestDiff: (prev: StateDigest, next: StateDigest) => string | null;
1508
+ export declare const formatStateDigestDiff: (previous: StateDigest, next: StateDigest) => string | null;
1146
1509
  //#endregion
1147
1510
  //#region src/state/map-pois/state.d.ts
1148
1511
  /**
@@ -1165,7 +1528,7 @@ declare class MapPOIsState implements StateSlice {
1165
1528
  //#region src/state/places/analysis.d.ts
1166
1529
  /**
1167
1530
  * A single analysis result attached to a places entry. Alias of the shared {@link EntryAnalysis} —
1168
- * every entry kind uses the same result shape; kept as a named export for back-compat.
1531
+ * every entry kind uses the same result shape.
1169
1532
  *
1170
1533
  * @group Agent Toolkit
1171
1534
  *
@@ -1189,9 +1552,9 @@ type PlacesMarkerType = (typeof placesMarkerTypes)[number];
1189
1552
  */
1190
1553
  type PlacesStateEvents = {
1191
1554
  /**
1192
- * An entry was added or replaced, or `reset()` cleared the history. `entries` is the full
1193
- * snapshot after the change, and `changedIds` lists the ids of the entries this change added,
1194
- * replaced in place, or removed. The {@link JobEngine} matches these against each job's
1555
+ * An entry was added or removed, entries were dropped by `single` mode, or `reset()` cleared the
1556
+ * history. `entries` is the full snapshot after the change, and `changedIds` lists the ids of the
1557
+ * entries this change added or removed. The {@link JobEngine} matches these against each job's
1195
1558
  * `affectedEntryIds`.
1196
1559
  */
1197
1560
  'entries-change': {
@@ -1200,7 +1563,10 @@ type PlacesStateEvents = {
1200
1563
  };
1201
1564
  /** The set of entries rendered on the map, or a marker type, changed. */
1202
1565
  'shown-change': ReadonlySet<string>;
1203
- /** Boundary polygons were fetched and cached on an entry. */
1566
+ /**
1567
+ * Boundary polygons were fetched and cached on an entry, `count` being the cached total, or
1568
+ * its shown polygons were cleared, with `count: 0` while the cache stays.
1569
+ */
1204
1570
  'geometries-change': {
1205
1571
  entryId: string;
1206
1572
  count: number;
@@ -1222,7 +1588,11 @@ type PlacesStateEvents = {
1222
1588
  declare class PlacesState implements StateSlice {
1223
1589
  private readonly _ttMap;
1224
1590
  private _entries;
1591
+ private readonly _history;
1225
1592
  private _entryMode;
1593
+ private _addedCount;
1594
+ private readonly _creatingPlacesModules;
1595
+ private readonly _creatingGeometriesModules;
1226
1596
  /** The state change events, listed in {@link PlacesStateEvents}. */
1227
1597
  readonly events: StateEvents<PlacesStateEvents>;
1228
1598
  /** The knobs set on every entry's PlacesModule, such as `color` and `label.size`. Cleared on `reset`. */
@@ -1250,8 +1620,8 @@ declare class PlacesState implements StateSlice {
1250
1620
  getEntryPlacesModule(entryId: string, markerType: PlacesMarkerType): Promise<PlacesModule>;
1251
1621
  /**
1252
1622
  * Returns the entry's place-geometries module for POI footprints and municipality outlines,
1253
- * created on first call. Updates only the fill style when it changes, keeping the styling
1254
- * applied since. Throws on an unknown entry id.
1623
+ * created on first call in `fillStyle` or as an outline. After that, a passed `fillStyle` updates
1624
+ * only the fill style, keeping the styling applied since. Throws on an unknown entry id.
1255
1625
  */
1256
1626
  getEntryGeometriesModule(entryId: string, fillStyle?: GeometryFillStyle): Promise<GeometriesModule>;
1257
1627
  private _requireEntry;
@@ -1278,6 +1648,8 @@ declare class PlacesState implements StateSlice {
1278
1648
  * is unknown or has no geometry data source.
1279
1649
  */
1280
1650
  fetchPlaceGeometry(placeId: string, options?: ToolExecuteOptions): Promise<PolygonFeature | undefined>;
1651
+ private _storeGeometries;
1652
+ private _placesNeedingGeometry;
1281
1653
  /**
1282
1654
  * Batch-fetches boundary polygons for every place in an entry that has a geometry data source
1283
1655
  * but is not yet cached. Issues one Geometry Data request per chunk of {@link GEOMETRY_DATA_BATCH_SIZE}
@@ -1295,6 +1667,8 @@ declare class PlacesState implements StateSlice {
1295
1667
  * - `mode: 'add'` merges the new features with the polygons shown on this entry's layer,
1296
1668
  * deduped by `feature.id`, and re-renders the union. An empty array does nothing.
1297
1669
  *
1670
+ * `fillStyle` restyles the entry's module; omit it to keep its current style, an outline at first.
1671
+ *
1298
1672
  * `entryId` defaults to the latest entry that owns geometries, which suits callers that only
1299
1673
  * render the most recently produced footprints. Pass an explicit id to target an older one.
1300
1674
  */
@@ -1339,13 +1713,13 @@ declare class PlacesState implements StateSlice {
1339
1713
  clearShown(): Promise<void>;
1340
1714
  clearShownGeometries(ids?: readonly string[]): Promise<void>;
1341
1715
  /**
1342
- * Drops a single entry from history. It first hides the entry by clearing every module it
1343
- * owns, then removes it from `_entries`. Emits `entries-change`, plus `shown-change` if the
1344
- * entry was shown. Does nothing if the id is unknown.
1716
+ * Drops a single entry from history and clears every module it owns. Emits `entries-change`, plus
1717
+ * `shown-change` if the entry was shown. Does nothing if the id is unknown.
1345
1718
  */
1346
1719
  removeEntry(id: string): Promise<void>;
1347
1720
  private _showEntryAs;
1348
1721
  private _hideEntry;
1722
+ private _dropEntry;
1349
1723
  reset(): void;
1350
1724
  }
1351
1725
  //#endregion
@@ -1438,9 +1812,9 @@ type RangesEntry = BaseEntry<ReachableRange[]> & {
1438
1812
  */
1439
1813
  type RangeStateEvents = {
1440
1814
  /**
1441
- * An entry was added, or `reset()` cleared the range history. `entries` is the full snapshot
1442
- * after the change, and `changedIds` lists the ids of the entries this change added, replaced
1443
- * in place, or removed.
1815
+ * An entry was added or removed, entries were dropped by `single` mode, or `reset()` cleared the
1816
+ * range history. `entries` is the full snapshot after the change, and `changedIds` lists the ids
1817
+ * of the entries this change added or removed.
1444
1818
  */
1445
1819
  'entries-change': {
1446
1820
  entries: readonly RangesEntry[];
@@ -1463,7 +1837,14 @@ type RangeStateEvents = {
1463
1837
  declare class RangeState implements ShownEntriesSlice {
1464
1838
  private readonly _ttMap;
1465
1839
  private _entries;
1840
+ private readonly _history;
1466
1841
  private _entryMode;
1842
+ private _addedCount;
1843
+ private readonly _creatingRangesModules;
1844
+ private readonly _creatingGeometriesModules;
1845
+ private readonly _creatingPlacesModules;
1846
+ private readonly _drawing;
1847
+ private readonly _droppedWhileDrawn;
1467
1848
  /** The state change events, listed in {@link RangeStateEvents}. */
1468
1849
  readonly events: StateEvents<RangeStateEvents>;
1469
1850
  /** The knobs set on every entry's ReachableRangesModule, such as `fill.opacity`. Cleared on `reset`. */
@@ -1489,14 +1870,15 @@ declare class RangeState implements ShownEntriesSlice {
1489
1870
  setEntryMode(mode: EntryMode): Promise<void>;
1490
1871
  /**
1491
1872
  * Initialises the entry's ReachableRangesModule for the isochrone/isodistance polygons
1492
- * lazily and applies the requested fill style. Throws on unknown id.
1873
+ * lazily, in `fillStyle` or as an outline. After that, a passed `fillStyle` updates only the
1874
+ * fill style. Throws on unknown id.
1493
1875
  */
1494
1876
  getEntryRangesModule(entryId: string, fillStyle?: GeometryFillStyle): Promise<ReachableRangesModule>;
1495
1877
  /**
1496
1878
  * Initialises the entry's plain GeometriesModule lazily for drawing the entry's polygons in a
1497
- * style of your own (per-feature colours, border widths) instead of as reachable-range bands.
1498
- * Updates only the fill style when it changes, keeping the styling applied since. Throws on
1499
- * unknown id.
1879
+ * style of your own (per-feature colours, border widths) instead of as reachable-range bands,
1880
+ * in `fillStyle` or as an outline. After that, a passed `fillStyle` updates only the fill style,
1881
+ * keeping the styling applied since. Throws on unknown id.
1500
1882
  */
1501
1883
  getEntryGeometriesModule(entryId: string, fillStyle?: GeometryFillStyle): Promise<GeometriesModule>;
1502
1884
  /**
@@ -1510,18 +1892,22 @@ declare class RangeState implements ShownEntriesSlice {
1510
1892
  * flag in sync with what the user sees.
1511
1893
  *
1512
1894
  * With `entryMode === 'single'`, any other shown entry is hidden first so two range
1513
- * layers don't overlap.
1895
+ * layers don't overlap. An entry dropped since its modules were asked for has its modules
1896
+ * cleared instead.
1514
1897
  */
1515
1898
  markEntryShown(entryId: string): Promise<void>;
1516
- /** Clears every module on the entry. Does nothing if the entry is unknown. */
1899
+ /** Clears the entry's ranges, geometries and origin-pin modules. Does nothing if the entry is unknown or hidden. */
1517
1900
  hideEntry(entryId: string): Promise<void>;
1901
+ private _hideEntry;
1902
+ private _clearModules;
1903
+ private _dropEntry;
1518
1904
  /**
1519
- * Drops a single entry from history. It clears the entry's ranges and origin-pin modules to
1520
- * hide it, then removes it from `_entries`. Emits `entries-change`. Does nothing if the id is
1521
- * unknown.
1905
+ * Drops a single entry from history and hides it as {@link hideEntry} does. Emits `entries-change`.
1906
+ * Does nothing if the id is unknown.
1522
1907
  */
1523
1908
  removeEntry(entryId: string): Promise<void>;
1524
1909
  private _requireEntry;
1910
+ private _requireDrawnEntry;
1525
1911
  get entries(): readonly RangesEntry[];
1526
1912
  get latestEntry(): RangesEntry | undefined;
1527
1913
  addEntry(entry: Omit<RangesEntry, 'id' | 'timestamp'>): Promise<string>;
@@ -1536,7 +1922,7 @@ declare class RangeState implements ShownEntriesSlice {
1536
1922
  //#region src/state/routing/analysis.d.ts
1537
1923
  /**
1538
1924
  * A single analysis result attached to a routes entry. Alias of the shared {@link EntryAnalysis} —
1539
- * every entry kind uses the same result shape; kept as a named export for back-compat.
1925
+ * every entry kind uses the same result shape.
1540
1926
  *
1541
1927
  * @group Agent Toolkit
1542
1928
  *
@@ -1544,6 +1930,75 @@ declare class RangeState implements ShownEntriesSlice {
1544
1930
  */
1545
1931
  type RoutesAnalysis = EntryAnalysis;
1546
1932
  //#endregion
1933
+ //#region src/state/polling-monitor.d.ts
1934
+ /**
1935
+ * The lifecycle state of a per-entry route or incidents monitor. `stopped-error` means the last
1936
+ * poll failed and the timer was cleared. To retry, start the monitor again.
1937
+ *
1938
+ * @group Agent Toolkit
1939
+ */
1940
+ type PollingStatus = 'idle' | 'running' | 'stopped-error';
1941
+ /** The timers a polling monitor schedules on. */
1942
+ type PollingTimers = {
1943
+ /** Override for tests. Defaults to the global `setInterval`. */
1944
+ setInterval?: (fn: () => void, ms: number) => unknown;
1945
+ clearInterval?: (handle: unknown) => void;
1946
+ };
1947
+ /**
1948
+ * Events fired by a {@link PollingMonitor}. The owning slice subscribes once and re-emits translated
1949
+ * copies (`monitor-tick`, `monitor-error`) keyed by entry id.
1950
+ */
1951
+ type PollingMonitorEvents<SNAPSHOT> = {
1952
+ /** A poll succeeded. The payload is the fresh snapshot. */
1953
+ tick: SNAPSHOT;
1954
+ /** A poll failed, so the monitor cleared its timer and moved to `stopped-error`. */
1955
+ error: string;
1956
+ };
1957
+ /**
1958
+ * A one-shot polling loop. It owns its timer, status and error, and restarting it after `stop()`
1959
+ * resets all state. It never knows about the entry that owns it: the fetch it is started with
1960
+ * captures what to poll, and the caller decides what to do with each snapshot.
1961
+ *
1962
+ * Each snapshot is stamped with `takenAt` after its fetch resolves, so every consumer of one tick
1963
+ * (entry data, derived analyses, sandbox `now`) agrees on the same canonical moment.
1964
+ */
1965
+ declare abstract class PollingMonitor<VALUE, SNAPSHOT> {
1966
+ private readonly _subject;
1967
+ readonly events: StateEvents<PollingMonitorEvents<SNAPSHOT>>;
1968
+ private _status;
1969
+ private _error?;
1970
+ private _intervalHandle?;
1971
+ private _clearInterval?;
1972
+ private _fetch?;
1973
+ private _run;
1974
+ private _tickInFlightRun?;
1975
+ /** @param _subject The monitor as its console warnings name it, e.g. `a route monitor`. */
1976
+ protected constructor(_subject: string);
1977
+ get status(): PollingStatus;
1978
+ get error(): string | undefined;
1979
+ /**
1980
+ * Whether the monitor is *currently* polling. Unlike {@link isActive}, it excludes
1981
+ * `stopped-error`, a state where the timer is gone but the monitor still carries an
1982
+ * unacknowledged error. Use this to ask "is the entry being polled right now", and
1983
+ * `isActive` to ask "is there anything to clean up".
1984
+ */
1985
+ get isRunning(): boolean;
1986
+ /** Whether the monitor has any polling activity (running or stopped-error). */
1987
+ get isActive(): boolean;
1988
+ /** Stops polling and resets state. Does nothing when idle. */
1989
+ stop(): void;
1990
+ /** The snapshot one successful fetch makes. */
1991
+ protected abstract _snapshot(value: VALUE, takenAt: number): SNAPSHOT;
1992
+ /**
1993
+ * Starts polling `fetch`: fires the first tick immediately unless `skipInitialTick` is set, then
1994
+ * schedules an interval. Does nothing if already running.
1995
+ */
1996
+ protected _startPolling(fetch: () => Promise<VALUE>, timers: PollingTimers, intervalMs: number, skipInitialTick: boolean): void;
1997
+ private _tick;
1998
+ private _failed;
1999
+ private _releaseTimer;
2000
+ }
2001
+ //#endregion
1547
2002
  //#region src/state/routing/monitor/types.d.ts
1548
2003
  /**
1549
2004
  * A freshly recalculated route from a single monitor tick, with the moment it was sampled.
@@ -1555,13 +2010,6 @@ type RouteSnapshot = {
1555
2010
  takenAt: number;
1556
2011
  routes: Routes;
1557
2012
  };
1558
- /**
1559
- * The lifecycle state of a per-entry route monitor. `stopped-error` means the last recalculation
1560
- * failed and the timer was cleared. To retry, start the monitor again.
1561
- *
1562
- * @group Agent Toolkit
1563
- */
1564
- type RoutePollingStatus = 'idle' | 'running' | 'stopped-error';
1565
2013
  //#endregion
1566
2014
  //#region src/state/routing/monitor/monitor.d.ts
1567
2015
  /**
@@ -1574,45 +2022,17 @@ type RoutePollingStatus = 'idle' | 'running' | 'stopped-error';
1574
2022
  *
1575
2023
  * @group Agent Toolkit
1576
2024
  */
1577
- type RouteMonitorDeps = {
2025
+ type RouteMonitorDeps = PollingTimers & {
1578
2026
  recalculate: () => Promise<Routes>;
1579
- /** Override for tests. Defaults to the global `setInterval`. */
1580
- setInterval?: (fn: () => void, ms: number) => unknown;
1581
- clearInterval?: (handle: unknown) => void;
1582
- };
1583
- /**
1584
- * Events fired by {@link RouteMonitor}. The slice subscribes once and re-emits translated copies
1585
- * (`monitor-tick`, `monitor-error`) keyed by entry id.
1586
- */
1587
- type RouteMonitorEvents = {
1588
- /** A recalculation succeeded. The payload is the fresh snapshot. */
1589
- tick: RouteSnapshot;
1590
- /** A recalculation failed, so the monitor cleared its timer and moved to `stopped-error`. */
1591
- error: string;
1592
2027
  };
1593
2028
  /**
1594
- * A one-shot polling loop that recalculates a single route on an interval. It owns its timer, status,
1595
- * and error. Restarting it after `stop()` resets all state.
1596
- *
1597
- * The monitor never knows about the entry that owns it. The `recalculate` closure captures the
1598
- * waypoints and params, and the caller decides what to do with each fresh snapshot. It mirrors
1599
- * `IncidentMonitor`. Routes carry live traffic, so periodic recalculation keeps the entry fresh.
2029
+ * A one-shot polling loop that recalculates a single route on an interval. Routes carry live traffic,
2030
+ * so periodic recalculation keeps the entry fresh. It mirrors `IncidentMonitor`.
1600
2031
  *
1601
2032
  * @group Agent Toolkit
1602
2033
  */
1603
- declare class RouteMonitor {
1604
- readonly events: StateEvents<RouteMonitorEvents>;
1605
- private _status;
1606
- private _error?;
1607
- private _intervalHandle?;
1608
- private _clearInterval?;
1609
- private _recalculate?;
1610
- get status(): RoutePollingStatus;
1611
- get error(): string | undefined;
1612
- /** Whether the monitor is *currently* recalculating on its interval. */
1613
- get isRunning(): boolean;
1614
- /** Whether the monitor has any activity (running or stopped-error). */
1615
- get isActive(): boolean;
2034
+ declare class RouteMonitor extends PollingMonitor<Routes, RouteSnapshot> {
2035
+ constructor();
1616
2036
  /**
1617
2037
  * Starts polling. It captures `deps` for the lifetime of the run, fires the first recalculation
1618
2038
  * immediately unless `skipInitialTick` is set, then schedules an interval. Does nothing if
@@ -1622,11 +2042,7 @@ declare class RouteMonitor {
1622
2042
  * since an eager first tick would duplicate that recalculation.
1623
2043
  */
1624
2044
  start(deps: RouteMonitorDeps, intervalMs?: number, skipInitialTick?: boolean): void;
1625
- /** Stops polling and resets state. Does nothing when idle. */
1626
- stop(): void;
1627
- private _tick;
1628
- private _failed;
1629
- private _releaseTimer;
2045
+ protected _snapshot(routes: Routes, takenAt: number): RouteSnapshot;
1630
2046
  }
1631
2047
  //#endregion
1632
2048
  //#region src/state/routing/entry.d.ts
@@ -1681,9 +2097,9 @@ type RoutesEntry = BaseEntry<Routes> & {
1681
2097
  */
1682
2098
  _monitor?: RouteMonitor;
1683
2099
  /**
1684
- * Monotonic counter bumped on every {@link RoutingState.replaceRouteData}. Guards against an
1685
- * out-of-order render: a slow `showRoutes` from an earlier tick that resolves after a newer tick
1686
- * has already overwritten `data` bails before touching the map.
2100
+ * Monotonic counter bumped on every {@link RoutingState.replaceRouteData}. Guards the section
2101
+ * focus against an out-of-order render: a slow `showRoutes` from an earlier tick that resolves
2102
+ * after a newer tick has already overwritten `data` skips re-applying the focus.
1687
2103
  */
1688
2104
  _tick?: number;
1689
2105
  };
@@ -1696,9 +2112,10 @@ type RoutesEntry = BaseEntry<Routes> & {
1696
2112
  */
1697
2113
  type RoutingStateEvents = {
1698
2114
  /**
1699
- * A calculation was stored, an analysis attached, or `reset()` cleared the history.
1700
- * `entries` is the full snapshot after the change, and `changedIds` lists the ids of the
1701
- * entries this change added, replaced in place, or removed.
2115
+ * A calculation was stored, a monitor tick replaced an entry's routes, entries were removed or
2116
+ * dropped by `single` mode, or `reset()` cleared the history. `entries` is the full snapshot after
2117
+ * the change, and `changedIds` lists the ids of the entries this change added, replaced in place,
2118
+ * or removed.
1702
2119
  */
1703
2120
  'entries-change': {
1704
2121
  entries: readonly RoutesEntry[];
@@ -1748,9 +2165,12 @@ type RoutingStateEvents = {
1748
2165
  declare class RoutingState implements ShownEntriesSlice {
1749
2166
  private readonly _ttMap;
1750
2167
  private _entries;
2168
+ private readonly _history;
1751
2169
  private _planningSlots;
1752
2170
  private _params;
1753
2171
  private _entryMode;
2172
+ private _addedCount;
2173
+ private readonly _creatingModules;
1754
2174
  /** The knobs set on every entry's RoutingModule, `color` and `widthFactor` among them. Cleared on `reset`. */
1755
2175
  readonly knobs: SliceKnobs;
1756
2176
  /**
@@ -1793,7 +2213,7 @@ declare class RoutingState implements ShownEntriesSlice {
1793
2213
  * choice, and `showSummaryBubbles: false` to drop the per-route ETA bubbles (e.g. a monitored
1794
2214
  * corridor backdrop).
1795
2215
  */
1796
- showEntry(entryId: string, opts?: {
2216
+ showEntry(entryId: string, options?: {
1797
2217
  showWaypoints?: boolean;
1798
2218
  showSummaryBubbles?: boolean;
1799
2219
  }): Promise<void>;
@@ -1808,11 +2228,13 @@ declare class RoutingState implements ShownEntriesSlice {
1808
2228
  * Does nothing if the entry is unknown or already hidden.
1809
2229
  */
1810
2230
  hideEntry(entryId: string): Promise<void>;
2231
+ private _hideEntry;
1811
2232
  /**
1812
- * Drops a single entry from history. It clears the entry's routing module to hide it, then
1813
- * removes it from `_entries`. Emits `entries-change`. Does nothing if the id is unknown.
2233
+ * Drops a single entry from history, stops its monitor and clears its routing module. Emits
2234
+ * `entries-change`. Does nothing if the id is unknown.
1814
2235
  */
1815
2236
  removeEntry(entryId: string): Promise<void>;
2237
+ private _dropEntry;
1816
2238
  private _requireEntry;
1817
2239
  /**
1818
2240
  * The RoutingModule of the most recently shown entry, or undefined if no entry is shown.
@@ -1834,18 +2256,20 @@ declare class RoutingState implements ShownEntriesSlice {
1834
2256
  * false if the entry is unknown. Mirrors `TrafficIncidentsState.replaceEntryData`.
1835
2257
  */
1836
2258
  replaceRouteData(entryId: string, routes: Routes, sampledAt: number): Promise<boolean>;
2259
+ private _showRoutesKeepingSelection;
1837
2260
  private _createMonitorForEntry;
1838
2261
  /**
1839
2262
  * Arms background recalculation on an entry. Lazy-creates its monitor, then starts polling with
1840
2263
  * the caller-supplied `recalculate` closure. Emits `monitor-start` on the idle → running
1841
2264
  * transition. Throws on unknown id.
1842
2265
  */
1843
- startMonitoring(entryId: string, deps: RouteMonitorDeps, opts?: {
2266
+ startMonitoring(entryId: string, deps: RouteMonitorDeps, options?: {
1844
2267
  intervalMs?: number;
1845
2268
  skipInitialTick?: boolean;
1846
2269
  }): void;
1847
2270
  /** Stops recalculating an entry but keeps its last data. Emits `monitor-stop`. Does nothing if not running. */
1848
2271
  stopMonitoring(entryId: string): void;
2272
+ private _stopMonitor;
1849
2273
  /** Whether the entry is being recalculated on its interval. */
1850
2274
  isMonitored(entryId: string): boolean;
1851
2275
  /**
@@ -1858,8 +2282,8 @@ declare class RoutingState implements ShownEntriesSlice {
1858
2282
  //#endregion
1859
2283
  //#region src/types/state.d.ts
1860
2284
  /**
1861
- * Common interface for state slices. Implement `reset()` to participate
1862
- * in cleanup when `destroy()` is called on the agent.
2285
+ * Common interface for state slices. Implement `reset()` to participate in cleanup: `destroy()` on
2286
+ * the agent calls it, and so does the `resetState` tool when the user asks to start over.
1863
2287
  *
1864
2288
  * All built-in state classes implement this. Custom slices can optionally
1865
2289
  * implement it to get automatic cleanup.
@@ -1877,6 +2301,8 @@ export interface StateSlice {
1877
2301
  * logic (proximity, threshold, filter). The entry holds every feature, so without re-running the rule
1878
2302
  * that selection can't be recovered from `entryId` alone, and the verdict records exactly what matched.
1879
2303
  * These are the features the UI highlights and the `summary` cites.
2304
+ *
2305
+ * @group Agent Toolkit
1880
2306
  */
1881
2307
  type MemberRef = {
1882
2308
  entryId: string;
@@ -1887,17 +2313,31 @@ type MemberRef = {
1887
2313
  * and read back by the reducer. `members` groups matches by source entry, so a verdict can span
1888
2314
  * several entry kinds. For example, "an incident within 100m of a hospital" returns a hospitals group
1889
2315
  * and an incidents group. `summary` is a grounded headline the code produces deterministically.
2316
+ *
2317
+ * @group Agent Toolkit
1890
2318
  */
1891
2319
  type Verdict = {
1892
2320
  active: boolean;
1893
2321
  members: MemberRef[];
1894
2322
  summary: string;
1895
2323
  };
1896
- /** Toast-worthy (`alert`) or quietly-logged (`event`), discriminating events in one store. */
2324
+ /**
2325
+ * Toast-worthy (`alert`) or quietly-logged (`event`), discriminating events in one store.
2326
+ *
2327
+ * @group Agent Toolkit
2328
+ */
1897
2329
  type TrackerEventType = 'alert' | 'event';
1898
- /** Rising edge (`opened`) or falling edge (`resolved`), the only two statuses in the rising-edge model. */
2330
+ /**
2331
+ * Rising edge (`opened`) or falling edge (`resolved`), the only two statuses in the rising-edge model.
2332
+ *
2333
+ * @group Agent Toolkit
2334
+ */
1899
2335
  type TrackerEventStatus = 'opened' | 'resolved';
1900
- /** A tracker crossing an edge, kept as the durable record the feed and toasts render. */
2336
+ /**
2337
+ * A tracker crossing an edge, kept as the durable record the feed and toasts render.
2338
+ *
2339
+ * @group Agent Toolkit
2340
+ */
1901
2341
  type TrackerEvent = {
1902
2342
  id: string;
1903
2343
  /** Source-data sample time of the recompute that fired it, **not** wall-clock. */
@@ -1915,6 +2355,8 @@ type TrackerEvent = {
1915
2355
  * A tracker is one rule, a natural-language condition plus its rising-edge state. The compiled code
1916
2356
  * lives on the tracker's {@link Job}, not here. `affectedEntryIds` are the entries the rule watches,
1917
2357
  * and a verdict's `members` are the ones that matched.
2358
+ *
2359
+ * @group Agent Toolkit
1918
2360
  */
1919
2361
  type Tracker = {
1920
2362
  id: string;
@@ -1929,7 +2371,11 @@ type Tracker = {
1929
2371
  /** Rising-edge time of the current open episode, if active. */
1930
2372
  openedAt?: number;
1931
2373
  };
1932
- /** Events emitted by {@link EventsState}. */
2374
+ /**
2375
+ * Events emitted by {@link EventsState}.
2376
+ *
2377
+ * @group Agent Toolkit
2378
+ */
1933
2379
  type TrackerStateEvents = {
1934
2380
  /** The tracker set or a tracker's live state changed (create, clear, enable, edge crossed). */
1935
2381
  'trackers-change': readonly Tracker[];
@@ -1976,7 +2422,7 @@ declare class EventsState implements StateSlice {
1976
2422
  * The event log, newest last. Pass `sinceMs` to filter and `trackerId` to scope. Returns deep copies
1977
2423
  * so a caller can't mutate a logged event (or its `members`) and corrupt the store.
1978
2424
  */
1979
- log(opts?: {
2425
+ log(options?: {
1980
2426
  trackerId?: string;
1981
2427
  sinceMs?: number;
1982
2428
  }): readonly TrackerEvent[];
@@ -1997,8 +2443,7 @@ declare class EventsState implements StateSlice {
1997
2443
  //#region src/state/traffic-area-analytics/analysis.d.ts
1998
2444
  /**
1999
2445
  * A single analysis result attached to a traffic-area-analytics entry. Alias of the shared
2000
- * {@link EntryAnalysis} — every entry kind uses the same result shape; kept as a named export for
2001
- * back-compat.
2446
+ * {@link EntryAnalysis} — every entry kind uses the same result shape.
2002
2447
  *
2003
2448
  * @group Agent Toolkit
2004
2449
  *
@@ -2010,8 +2455,7 @@ type TrafficAreaAnalyticsAnalysis = EntryAnalysis;
2010
2455
  /**
2011
2456
  * Compact provenance metadata for a traffic-area-analytics entry — the request
2012
2457
  * parameters that produced the result. Kept opaque (`Record<string, unknown>`)
2013
- * because the SDK call accepts a wide param shape and we just want to surface
2014
- * enough context for `recall` / `digest` tools.
2458
+ * because the SDK call accepts a wide param shape.
2015
2459
  *
2016
2460
  * @group Agent Toolkit
2017
2461
  *
@@ -2038,7 +2482,7 @@ type TrafficAreaAnalyticsEntry = BaseEntry<TrafficAreaAnalytics> & {
2038
2482
  _module?: TrafficAreaAnalyticsModule;
2039
2483
  /** Latest viz config reflected from the module (mode / metric / scaleMode / …). */
2040
2484
  _config?: TrafficAreaAnalyticsModuleConfig;
2041
- /** Unsubscribe from this entry's module config-change wiring. Cleared on hide / remove. */
2485
+ /** Unsubscribe from this entry's module config-change wiring. Released when the entry is dropped or reset. */
2042
2486
  _configChangeUnsub?: () => void;
2043
2487
  /** True while `_module` is rendering on the map. */
2044
2488
  _shown?: boolean;
@@ -2053,9 +2497,9 @@ type TrafficAreaAnalyticsEntry = BaseEntry<TrafficAreaAnalytics> & {
2053
2497
  */
2054
2498
  type TrafficAreaAnalyticsStateEvents = {
2055
2499
  /**
2056
- * An entry was added or removed, or `reset()` cleared the history. `entries` is the full
2057
- * snapshot after the change, and `changedIds` lists the ids of the entries this change added,
2058
- * replaced in place, or removed.
2500
+ * An entry was added or removed, entries were dropped by `single` mode, or `reset()` cleared the
2501
+ * history. `entries` is the full snapshot after the change, and `changedIds` lists the ids of the
2502
+ * entries this change added or removed.
2059
2503
  */
2060
2504
  'entries-change': {
2061
2505
  entries: readonly TrafficAreaAnalyticsEntry[];
@@ -2080,10 +2524,13 @@ type TrafficAreaAnalyticsStateEvents = {
2080
2524
  *
2081
2525
  * @group Agent Toolkit
2082
2526
  */
2083
- declare class TrafficAreaAnalyticsState implements ShownEntriesSlice, StateSlice {
2527
+ declare class TrafficAreaAnalyticsState implements ShownEntriesSlice {
2084
2528
  private readonly _ttMap;
2085
2529
  private _entries;
2530
+ private readonly _history;
2086
2531
  private _entryMode;
2532
+ private _addedCount;
2533
+ private readonly _creatingModules;
2087
2534
  /** The state change events, listed in {@link TrafficAreaAnalyticsStateEvents}. */
2088
2535
  readonly events: StateEvents<TrafficAreaAnalyticsStateEvents>;
2089
2536
  /**
@@ -2113,8 +2560,10 @@ declare class TrafficAreaAnalyticsState implements ShownEntriesSlice, StateSlice
2113
2560
  showEntry(entryId: string): Promise<void>;
2114
2561
  /** Hides the entry's analytics on its module. Does nothing if unknown or already hidden. */
2115
2562
  hideEntry(entryId: string): Promise<void>;
2116
- /** Hides a single entry, then drops it from history and emits `entries-change`. Does nothing for an unknown id. */
2563
+ private _hideEntry;
2564
+ /** Drops a single entry from history, hides it and emits `entries-change`. Does nothing for an unknown id. */
2117
2565
  removeEntry(entryId: string): Promise<void>;
2566
+ private _dropEntry;
2118
2567
  private _requireEntry;
2119
2568
  /**
2120
2569
  * Hides every traffic-area-analytics entry on the map but keeps the history. Implements
@@ -2127,8 +2576,7 @@ declare class TrafficAreaAnalyticsState implements ShownEntriesSlice, StateSlice
2127
2576
  //#region src/state/traffic-incidents/analysis.d.ts
2128
2577
  /**
2129
2578
  * A single analysis result attached to a traffic-incidents entry. Alias of the shared
2130
- * {@link EntryAnalysis} — every entry kind uses the same result shape; kept as a named export for
2131
- * back-compat.
2579
+ * {@link EntryAnalysis} — every entry kind uses the same result shape.
2132
2580
  *
2133
2581
  * @group Agent Toolkit
2134
2582
  *
@@ -2137,9 +2585,18 @@ declare class TrafficAreaAnalyticsState implements ShownEntriesSlice, StateSlice
2137
2585
  type IncidentsAnalysis = EntryAnalysis;
2138
2586
  //#endregion
2139
2587
  //#region src/state/traffic-incidents/clustering.d.ts
2140
- /** Direction a cluster's total delay is trending across recent snapshots. */
2588
+ /**
2589
+ * Direction a cluster's total delay is trending across recent snapshots.
2590
+ *
2591
+ * @group Agent Toolkit
2592
+ */
2141
2593
  type ClusterTrend = 'growing' | 'fading' | 'steady' | 'new';
2142
- /** Tuneable parameters for {@link runClustering}, all optional with sensible defaults. */
2594
+ /**
2595
+ * Tuneable parameters for clustering traffic incidents, through the `clusterIncidents` tool or the sandbox's
2596
+ * `cluster(incidents, params)`, all optional with sensible defaults.
2597
+ *
2598
+ * @group Agent Toolkit
2599
+ */
2143
2600
  type ClusteringParams = {
2144
2601
  /** DBSCAN neighbourhood radius in km. Default: 0.5 */
2145
2602
  eps?: number;
@@ -2149,13 +2606,17 @@ type ClusteringParams = {
2149
2606
  maxClusters?: number;
2150
2607
  /** Pre-filter rules applied before clustering. */
2151
2608
  preFilter?: {
2152
- /** Categories to exclude entirely. Default: `['roadworks', 'road-closed']` */
2609
+ /** Categories whose incidents are dropped when below `minDelaySeconds`. Default: `['roadworks', 'road-closed']` */
2153
2610
  excludeCategories?: string[];
2154
2611
  /** Incidents in excludeCategories with `delayInSeconds` below this are excluded. Default: 1 (excludes 0-delay) */
2155
2612
  minDelaySeconds?: number;
2156
2613
  };
2157
2614
  };
2158
- /** A single cluster produced by {@link runClustering}. */
2615
+ /**
2616
+ * A single cluster of traffic incidents, as `clusterIncidents` and the sandbox's `cluster(...)` produce it.
2617
+ *
2618
+ * @group Agent Toolkit
2619
+ */
2159
2620
  type ClusterResult = {
2160
2621
  /** A stable identifier, reused across runs when member overlap >= 50%. */
2161
2622
  id: string;
@@ -2175,16 +2636,19 @@ type ClusterResult = {
2175
2636
  primaryRoads: string[];
2176
2637
  /** Most-frequent incident category across members (e.g. "jam"). */
2177
2638
  primaryCategory: string;
2178
- /** Trend across recent snapshots (see {@link classifyTrend}). */
2639
+ /** Trend across the last 3 snapshots: `new` on a first sighting, `steady` until there are 3. */
2179
2640
  trend: ClusterTrend;
2180
2641
  /**
2181
- * Rolling window of `totalDelaySeconds` across recent matched snapshots,
2182
- * bounded to {@link TREND_WINDOW}. Internal trend state threaded forward
2183
- * via the previous run, not display data.
2642
+ * Rolling window of `totalDelaySeconds` across the last 3 matched snapshots.
2643
+ * Internal trend state threaded forward via the previous run, not display data.
2184
2644
  */
2185
2645
  delaySamples: number[];
2186
2646
  };
2187
- /** Output of {@link runClustering}. */
2647
+ /**
2648
+ * Output of clustering traffic incidents: the clusters, ranked by total delay.
2649
+ *
2650
+ * @group Agent Toolkit
2651
+ */
2188
2652
  type ClusteringOutput = {
2189
2653
  groups: ClusterResult[];
2190
2654
  };
@@ -2201,7 +2665,7 @@ type SandboxClusteringOutput = ClusteringOutput & {
2201
2665
  //#endregion
2202
2666
  //#region src/state/traffic-incidents/monitor/types.d.ts
2203
2667
  /**
2204
- * The geographic area a {@link TrafficIncidentsEntry} monitor is polling, captured at
2668
+ * The geographic area a traffic incidents entry's monitor is polling, captured at
2205
2669
  * monitor-start time and replayed on every tick.
2206
2670
  *
2207
2671
  * @group Agent Toolkit
@@ -2212,8 +2676,8 @@ type MonitoredArea = {
2212
2676
  label?: string;
2213
2677
  };
2214
2678
  /**
2215
- * A fresh batch of incidents from a single monitor tick, with the moment it was sampled.
2216
- * Payload of {@link TrafficIncidentsStateEvents.monitor-tick}.
2679
+ * A fresh batch of incidents from a single monitor tick, with the moment it was sampled: the `snap`
2680
+ * field of the traffic incidents slice's `monitor-tick` event.
2217
2681
  *
2218
2682
  * @group Agent Toolkit
2219
2683
  */
@@ -2221,13 +2685,6 @@ type IncidentSnapshot = {
2221
2685
  takenAt: number;
2222
2686
  incidents: TrafficIncident[];
2223
2687
  };
2224
- /**
2225
- * The lifecycle state of a per-entry incidents monitor. `stopped-error` means the last
2226
- * poll failed and the timer was cleared. To retry, start the monitor again.
2227
- *
2228
- * @group Agent Toolkit
2229
- */
2230
- type PollingStatus = 'idle' | 'running' | 'stopped-error';
2231
2688
  //#endregion
2232
2689
  //#region src/state/traffic-incidents/monitor/monitor.d.ts
2233
2690
  /**
@@ -2241,53 +2698,20 @@ type PollingStatus = 'idle' | 'running' | 'stopped-error';
2241
2698
  *
2242
2699
  * @group Agent Toolkit
2243
2700
  */
2244
- type IncidentMonitorDeps = {
2701
+ type IncidentMonitorDeps = PollingTimers & {
2245
2702
  fetchIncidents: (bbox: BBox) => Promise<TrafficIncident[]>;
2246
- /** Override for tests. Defaults to the global `setInterval`. */
2247
- setInterval?: (fn: () => void, ms: number) => unknown;
2248
- clearInterval?: (handle: unknown) => void;
2249
2703
  };
2250
2704
  /**
2251
- * Events fired by {@link IncidentMonitor}. The slice subscribes once and re-emits
2252
- * translated copies (`monitor-tick`, `monitor-error`) keyed by entry id.
2253
- */
2254
- type IncidentMonitorEvents = {
2255
- /** A poll succeeded. Payload: the fresh snapshot. */
2256
- tick: IncidentSnapshot;
2257
- /** A poll failed, so the monitor cleared its timer and moved to `stopped-error`. */
2258
- error: string;
2259
- };
2260
- /**
2261
- * A one-shot polling loop scoped to a single bbox. It owns its timer, status, error,
2262
- * and captured area. Restarting it after `stop()` resets all state.
2263
- *
2264
- * The monitor never knows about the entry that owns it. It surfaces ticks and errors
2265
- * through `events`, and the caller decides what to do with the snapshot.
2705
+ * A one-shot polling loop scoped to a single bbox. Besides the polling state, it owns the area
2706
+ * captured at start.
2266
2707
  *
2267
2708
  * @group Agent Toolkit
2268
2709
  */
2269
- declare class IncidentMonitor {
2710
+ declare class IncidentMonitor extends PollingMonitor<TrafficIncident[], IncidentSnapshot> {
2270
2711
  private readonly _bbox;
2271
- readonly events: StateEvents<IncidentMonitorEvents>;
2272
- private _status;
2273
2712
  private _area?;
2274
- private _error?;
2275
- private _intervalHandle?;
2276
- private _clearInterval?;
2277
- private _fetchIncidents?;
2278
2713
  constructor(_bbox: BBox);
2279
- get status(): PollingStatus;
2280
2714
  get monitoredArea(): MonitoredArea | undefined;
2281
- get error(): string | undefined;
2282
- /**
2283
- * Whether the monitor is *currently* polling. Unlike {@link isActive}, it excludes
2284
- * `stopped-error`, a state where the timer is gone but the monitor still carries an
2285
- * unacknowledged error. Use this to ask "is the entry being polled right now", and
2286
- * `isActive` to ask "is there anything to clean up".
2287
- */
2288
- get isRunning(): boolean;
2289
- /** Whether the monitor has any polling activity (running or stopped-error). */
2290
- get isActive(): boolean;
2291
2715
  /**
2292
2716
  * Starts polling. It captures `deps` for the lifetime of the run, fires the first tick
2293
2717
  * immediately unless `skipInitialTick` is set, then schedules an interval. Does nothing if
@@ -2299,11 +2723,8 @@ declare class IncidentMonitor {
2299
2723
  * produces an initial snapshot without waiting a full interval.
2300
2724
  */
2301
2725
  start(area: MonitoredArea, deps: IncidentMonitorDeps, intervalMs?: number, skipInitialTick?: boolean): void;
2302
- /** Stops polling and resets state. Does nothing when idle. */
2303
2726
  stop(): void;
2304
- private _tick;
2305
- private _failed;
2306
- private _releaseTimer;
2727
+ protected _snapshot(incidents: TrafficIncident[], takenAt: number): IncidentSnapshot;
2307
2728
  }
2308
2729
  //#endregion
2309
2730
  //#region src/state/traffic-incidents/state.d.ts
@@ -2354,10 +2775,7 @@ type TrafficIncidentsEntry = BaseEntry<TrafficIncident[]> & {
2354
2775
  * Focused subset on this entry — the agent's `focusIds` write-side. Drives the dim/highlight
2355
2776
  * affordance on `_module` and feeds `focusedFeatures(entryId)` for stepping through.
2356
2777
  */
2357
- _focus?: {
2358
- ids: Set<string>;
2359
- reason?: string;
2360
- };
2778
+ _focus?: IncidentFocus;
2361
2779
  /**
2362
2780
  * Per-entry polling loop. Lazy-created on first {@link TrafficIncidentsState.startMonitoring}
2363
2781
  * call; reused across stop/start cycles. Owns timer, status, error, captured area.
@@ -2453,10 +2871,13 @@ type TrafficIncidentsStateEvents = {
2453
2871
  *
2454
2872
  * @group Agent Toolkit
2455
2873
  */
2456
- declare class TrafficIncidentsState implements StateSlice {
2874
+ declare class TrafficIncidentsState implements ShownEntriesSlice {
2457
2875
  private readonly _ttMap;
2458
2876
  private _entries;
2877
+ private readonly _history;
2459
2878
  private _entryMode;
2879
+ private _addedCount;
2880
+ private readonly _creatingModules;
2460
2881
  private readonly _clusters;
2461
2882
  /** The state change events, listed in {@link TrafficIncidentsStateEvents}. */
2462
2883
  readonly events: StateEvents<TrafficIncidentsStateEvents>;
@@ -2567,12 +2988,13 @@ declare class TrafficIncidentsState implements StateSlice {
2567
2988
  * once, then delegates to {@link IncidentMonitor.start}. Does nothing if polling is already
2568
2989
  * running. Throws on unknown entry id.
2569
2990
  */
2570
- startMonitoring(entryId: TrafficIncidentsEntry['id'], area: MonitoredArea, deps: IncidentMonitorDeps, opts?: {
2991
+ startMonitoring(entryId: TrafficIncidentsEntry['id'], area: MonitoredArea, deps: IncidentMonitorDeps, options?: {
2571
2992
  intervalMs?: number;
2572
2993
  skipInitialTick?: boolean;
2573
2994
  }): void;
2574
2995
  /** Stops polling. Does nothing if idle or unknown. */
2575
2996
  stopMonitoring(entryId: TrafficIncidentsEntry['id']): void;
2997
+ private _stopMonitor;
2576
2998
  /**
2577
2999
  * Whether the entry is *currently* being polled. A monitor stuck in
2578
3000
  * `stopped-error` returns false here, so the start tool can report a truthful
@@ -2634,17 +3056,19 @@ export type QueryAs = 'poi' | 'place';
2634
3056
  /**
2635
3057
  * Resolves a query string to up to `limit` Places, using POI search when `queryAs === 'poi'`,
2636
3058
  * otherwise geocoding. The optional `bias` narrows the search to a region.
3059
+ *
3060
+ * @ignore
2637
3061
  */
2638
3062
  export declare const locatePlaces: (query: string, queryAs: QueryAs, options: {
2639
3063
  limit: number;
2640
3064
  bias?: GeoBias;
2641
- }, execOptions?: ToolExecuteOptions) => Promise<Place[]>;
3065
+ }, executeOptions?: ToolExecuteOptions) => Promise<Place[]>;
2642
3066
  /**
2643
3067
  * Finds the best match for a query as the `locatePlace` tool does, for a custom tool that needs one place.
2644
3068
  * A failed or cancelled request rejects, so catch it in `execute`.
2645
3069
  *
2646
3070
  * @param bias - Favours results near a position, such as the map centre from {@link getViewportBias}.
2647
- * @param execOptions - The `execute` options, whose `signal` cancels the request with the turn.
3071
+ * @param executeOptions - The `execute` options, whose `signal` cancels the request with the turn.
2648
3072
  * @returns The first match, or `null` when nothing matches.
2649
3073
  *
2650
3074
  * @example
@@ -2658,7 +3082,7 @@ export declare const locatePlaces: (query: string, queryAs: QueryAs, options: {
2658
3082
  *
2659
3083
  * @group Agent Toolkit
2660
3084
  */
2661
- export declare const locatePlace: (query: string, queryAs: QueryAs, bias?: GeoBias, execOptions?: ToolExecuteOptions) => Promise<Place | null>;
3085
+ export declare const locatePlace: (query: string, queryAs: QueryAs, bias?: GeoBias, executeOptions?: ToolExecuteOptions) => Promise<Place | null>;
2662
3086
  //#endregion
2663
3087
  //#region src/tools/shared/location-input.d.ts
2664
3088
  /** @ignore */
@@ -2735,19 +3159,22 @@ export type CollectedGeometries = {
2735
3159
  * `PolygonFeature[]`. The id's `kind` tells the helper which slice to
2736
3160
  * consult: `place` and `places` go through the per-place fetch pipeline
2737
3161
  * (Geometry Data service for footprints, lazy cached on the places-entry);
2738
- * `ranges` flattens isochrone polygons already in memory; `custom` reads a
3162
+ * `ranges` flattens isochrone polygons already in memory; `customGeometries` reads a
2739
3163
  * derived entry produced by a previous `processData`.
2740
3164
  *
2741
3165
  * Validates the input precondition (at least one id) and the output
2742
3166
  * postcondition (at least one polygon collected). Returns `affectedEntries`
2743
3167
  * — the entries that should carry analyses computed from these geometries
2744
- * (places-entries from `place`/`places` inputs, custom-entries from
2745
- * `custom` inputs; ranges entries don't carry analyses, so they're not
3168
+ * (places-entries from `place`/`places` inputs, custom-geometries entries from
3169
+ * `customGeometries` inputs; ranges entries don't carry analyses, so they're not
2746
3170
  * included here).
2747
3171
  *
3172
+ * Pass the turn's `options` so cancelling it cancels the Geometry Data requests too; a monitor
3173
+ * re-run leaves them out.
3174
+ *
2748
3175
  * @ignore
2749
3176
  */
2750
- export declare const collectInputGeometries: (sources: readonly GeometriesId[], state: ToolState) => Promise<{
3177
+ export declare const collectInputGeometries: (inputSources: readonly GeometriesId[], state: ToolState, options?: ToolExecuteOptions) => Promise<{
2751
3178
  value: CollectedGeometries;
2752
3179
  } | {
2753
3180
  error: string;
@@ -2756,7 +3183,6 @@ export declare const collectInputGeometries: (sources: readonly GeometriesId[],
2756
3183
  * Resolves `placesEntryIDs` into a `Record<entryId, Places>` map for
2757
3184
  * sandbox cross-referencing. Returns `{ value: undefined }` when no IDs
2758
3185
  * are supplied so callers can pass the result straight into the sandbox.
2759
- * Mirrors the resolution used by analyse-routes and process-routes.
2760
3186
  *
2761
3187
  * @ignore
2762
3188
  */
@@ -2796,8 +3222,12 @@ export type ResolvedEntries = {
2796
3222
  trafficAreaAnalytics: TrafficAreaAnalyticsEntry[];
2797
3223
  byod: BYODEntry[];
2798
3224
  };
2799
- /** Newest `timestamp` across every resolved source entry, or undefined when none carry one, as
2800
- * the canonical `sampledAt` for a recurring sandbox run over these inputs. */
3225
+ /**
3226
+ * Newest `timestamp` across every resolved source entry, or undefined when none carry one, as
3227
+ * the canonical `sampledAt` for a recurring sandbox run over these inputs.
3228
+ *
3229
+ * @ignore
3230
+ */
2801
3231
  export declare const latestTimestamp: (resolved: ResolvedEntries) => number | undefined;
2802
3232
  /**
2803
3233
  * Sandbox-facing inputs. Each kind is exposed as a single `<kind>ByEntry` record keyed by the entry id
@@ -2863,11 +3293,12 @@ export type PreparedInputs = {
2863
3293
  /**
2864
3294
  * Resolve every requested input kind, build the sandbox views, and surface the resolved entries to the
2865
3295
  * caller. The caller (analyseData / processData) enforces "at least one input must be set" via the zod
2866
- * schema; this helper enforces it again as a safety net.
3296
+ * schema; this helper enforces it again as a safety net. Pass the turn's `options` from a tool call,
3297
+ * and none from a monitor re-run (see {@link collectInputGeometries}).
2867
3298
  *
2868
3299
  * @ignore
2869
3300
  */
2870
- export declare const prepareMultiInputs: (ids: MultiInputIds, state: ToolState) => Promise<{
3301
+ export declare const prepareMultiInputs: (ids: MultiInputIds, state: ToolState, options?: ToolExecuteOptions) => Promise<{
2871
3302
  value: PreparedInputs;
2872
3303
  } | {
2873
3304
  error: string;
@@ -2904,7 +3335,7 @@ export declare const buildSandboxToolsDoc: (active: readonly EntryDataKind[], sc
2904
3335
  * Pack `prepared.sandbox` into the positional argument array expected by
2905
3336
  * `runSandboxedFn`, in the same order as {@link MULTI_INPUT_SANDBOX_PARAMS}.
2906
3337
  *
2907
- * The merged / per-entry views are shallow — their feature objects are the SAME
3338
+ * The `<kind>ByEntry` records are shallow — their feature objects are the SAME
2908
3339
  * references held in the entry slices — so sandbox code must not mutate them in
2909
3340
  * place or it would corrupt live app state. We do NOT deep-copy here: the copy is
2910
3341
  * the executor's job, done exactly once and only where needed — the main-thread
@@ -2913,7 +3344,7 @@ export declare const buildSandboxToolsDoc: (active: readonly EntryDataKind[], sc
2913
3344
  * boundary. Cloning here too would be redundant double-work. Trailing `h3` / `turf` /
2914
3345
  * `routeUtils` / `cluster` are read-only function references, passed through untouched —
2915
3346
  * `routeUtils` is the shared {@link routeUtils} set and `cluster` is the
2916
- * {@link clusterIncidents} primitive; both are injected into both tools. (In the
3347
+ * {@link clusterIncidents} primitive; both reach every code-generation tool. (In the
2917
3348
  * iframe-worker path these positions are dropped and refilled from the worker's own
2918
3349
  * globals — see {@link WORKER_PROVIDED_PARAMS} — so they must stay function references here.)
2919
3350
  *
@@ -2926,26 +3357,23 @@ export declare const packSandboxArgs: (sandbox: SandboxInputs, libs: {
2926
3357
  //#endregion
2927
3358
  //#region src/tools/shared/places-schema-doc.d.ts
2928
3359
  /**
2929
- * Build the Place properties schema doc embedded in tool descriptions for
2930
- * sandboxed code. `Places` is a FeatureCollection of Point Features; only the
2931
- * `properties` shape (the TomTom-specific bit) is documented here.
2932
- *
2933
- * @remarks
2934
- * Takes {@link FeatureFlags} so a future flag can vary the doc; no flag
2935
- * currently does, so every caller gets the same text.
3360
+ * The Place properties schema doc embedded in tool descriptions for sandboxed code. `Places` is a
3361
+ * FeatureCollection of Point Features; only the `properties` shape (the TomTom-specific bit) is
3362
+ * documented here.
2936
3363
  *
2937
3364
  * @ignore
2938
3365
  */
2939
- export declare const buildPlacesSchemaDoc: (_flags: FeatureFlags) => string;
3366
+ export declare const PLACES_SCHEMA_DOC: string;
2940
3367
  /**
2941
- * Places schema doc — preserved as a named constant so non-flag-aware tools
2942
- * keep working.
3368
+ * The {@link PLACES_SCHEMA_DOC} for a set of {@link FeatureFlags}, which a future flag can vary; no flag
3369
+ * currently does, so every caller gets the same text.
2943
3370
  *
2944
3371
  * @ignore
2945
3372
  */
2946
- export declare const PLACES_SCHEMA_DOC: string;
3373
+ export declare const buildPlacesSchemaDoc: (_flags: FeatureFlags) => string;
2947
3374
  //#endregion
2948
3375
  //#region src/tools/shared/resolve-range.d.ts
3376
+ /** @ignore */
2949
3377
  export declare const getRangePolygons: (state: ToolState, rangeId: string) => {
2950
3378
  polygons: (Polygon | MultiPolygon)[];
2951
3379
  } | {
@@ -3074,9 +3502,8 @@ export declare const geometryDisplayConfigSchema: z.ZodObject<{
3074
3502
  }>>;
3075
3503
  }, z.core.$strip>;
3076
3504
  /**
3077
- * Shared marker-type enum. Used as a required field in `showPlacesSchema` (the
3078
- * nested `show` object for discover/filter/search tools) and as an optional
3079
- * top-level field in `showPlaces` itself.
3505
+ * Shared marker-type enum, a required field in `showPlacesSchema` (the nested `show` object of the
3506
+ * place-searching tools).
3080
3507
  *
3081
3508
  * @ignore
3082
3509
  */
@@ -3294,9 +3721,9 @@ export type ResolveAreasOptions = {
3294
3721
  };
3295
3722
  export type ResolveKind = 'within' | 'nearby' | 'global';
3296
3723
  export type AreaSource = 'viewport' | 'boundingBox' | 'query' | 'placeId' | 'geometries' | 'route';
3297
- export declare function resolveWhere(opts: ResolveAreasOptions, where?: AreaWhere, ctx?: WhereContext): Promise<ResolveError | ResolvedArea[]> | ResolvedBias | Promise<ResolvedBias>;
3298
- export declare const resolveWithin: (where: AreaWhere, ctx: WhereContext) => Promise<ResolvedArea[] | ResolveError>;
3299
- export declare const resolveNearby: (where: AreaWhere, ctx: WhereContext) => Promise<ResolvedBias>;
3724
+ export declare function resolveWhere(options: ResolveAreasOptions, where?: AreaWhere, context?: WhereContext): Promise<ResolveError | ResolvedArea[]> | ResolvedBias | Promise<ResolvedBias>;
3725
+ export declare const resolveWithin: (where: AreaWhere, context: WhereContext) => Promise<ResolvedArea[] | ResolveError>;
3726
+ export declare const resolveNearby: (where: AreaWhere, context: WhereContext) => Promise<ResolvedBias>;
3300
3727
  export declare const resolveGlobal: () => ResolvedBias;
3301
3728
  export type ResolvedArea = {
3302
3729
  bbox: BBox;
@@ -3322,7 +3749,7 @@ export type ResolvedAreaDisclosure = {
3322
3749
  query?: string;
3323
3750
  matched: string;
3324
3751
  };
3325
- export declare const isResolveError: (r: unknown) => r is ResolveError;
3752
+ export declare const isResolveError: (value: unknown) => value is ResolveError;
3326
3753
  //#endregion
3327
3754
  //#region src/tools/shared/route-utils.d.ts
3328
3755
  /**
@@ -3344,459 +3771,137 @@ export declare const routeUtils: {
3344
3771
  readonly compareRoutes: (route: import("@tomtom-org/maps-sdk/core").Route, reference: import("@tomtom-org/maps-sdk/core").Route, { types }?: import("@tomtom-org/maps-sdk/core").CompareRoutesOptions) => import("@tomtom-org/maps-sdk/core").RouteComparison;
3345
3772
  readonly getCoordinateAtRouteProgress: (route: import("@tomtom-org/maps-sdk/core").Route, query: import("@tomtom-org/maps-sdk/core").RouteProgressQuery) => import("@tomtom-org/maps-sdk/core").RouteCoordinateAtProgress | undefined;
3346
3773
  readonly getImportantRoads: (route: import("@tomtom-org/maps-sdk/core").Route, { within, minLengthInMeters }?: import("@tomtom-org/maps-sdk/core").ImportantRoadsOptions) => import("@tomtom-org/maps-sdk/core").ImportantRoad[];
3347
- readonly getProgressAtNearestRoutePoint: (route: import("@tomtom-org/maps-sdk/core").Route, point: import("@tomtom-org/maps-sdk/core").HasLngLat) => import("@tomtom-org/maps-sdk/core").RouteCoordinateAtProgress | undefined;
3348
- readonly getRouteProgressBetween: (route: import("@tomtom-org/maps-sdk/core").Route, startPathIndex: number, endPathIndex: number) => import("@tomtom-org/maps-sdk/core").RouteSegmentProgress | undefined;
3349
- readonly getRouteProgressForSection: (route: import("@tomtom-org/maps-sdk/core").Route, section: import("@tomtom-org/maps-sdk/core").RouteSpan) => import("@tomtom-org/maps-sdk/core").RouteSegmentProgress | undefined;
3350
- readonly getSectionBBox: (route: import("@tomtom-org/maps-sdk/core").Route, section: import("@tomtom-org/maps-sdk/core").RouteSpan) => import("@tomtom-org/maps-sdk/core").OptionalBBox;
3351
- readonly getSectionsWithin: (route: import("@tomtom-org/maps-sdk/core").Route, { within, types }?: import("@tomtom-org/maps-sdk/core").SectionsWithinOptions) => import("@tomtom-org/maps-sdk/core").SectionsWithin;
3352
- readonly isHairpin: (curve: Pick<import("@tomtom-org/maps-sdk/core").CurveSectionProps, "headingChangeInDegrees" | "radiusInMeters" | "maneuver">) => boolean;
3353
- };
3354
- //#endregion
3355
- //#region src/tools/shared/routes-schema-doc.d.ts
3356
- /**
3357
- * @module agent-toolkit-tools
3358
- *
3359
- * Compact schema documentation for the `Route` properties shape, reused by
3360
- * every tool whose LLM-authored code reads a Routes FeatureCollection
3361
- * (`analyseData`, `processData`), injected per entry as `routesByEntry[id]`.
3362
- * Only the non-GeoJSON-standard bits are spelled out, since `Route` is a LineString Feature.
3363
- */
3364
- /** @ignore */
3365
- export declare const ROUTES_SCHEMA_DOC: string;
3366
- //#endregion
3367
- //#region src/tools/shared/show-byod-on-map.d.ts
3368
- /**
3369
- * Render a BYOD entry on the map per the tool's `show` options: hide
3370
- * previously-shown entries (per `hidePreviousEntries`), show the new entry, then
3371
- * optionally fit the camera to every shown BYOD entry. Sequential by design —
3372
- * map mutations must not race (see ENGINEERING-GUIDELINES §6).
3373
- *
3374
- * @ignore
3375
- */
3376
- export declare const showByodOnMap: (state: ToolState, byodEntryId: string, show: z.infer<typeof showByodSchema>) => Promise<z.infer<typeof shownByodSchema>>;
3377
- //#endregion
3378
- //#region src/tools/shared/show-entry-geometries.d.ts
3379
- /** @ignore */
3380
- export type ShowEntryGeometriesResult = {
3381
- fetched: number;
3382
- shown: boolean;
3383
- };
3384
- /**
3385
- * Fetch boundary polygons for every place in an entry that has a geometry data source,
3386
- * cache them on the entry, and optionally render them via the entry's GeometriesModule.
3387
- *
3388
- * Shared by tools that produce a single places entry (discoverPlaces, locatePlace) — they
3389
- * differ only in how they shape the result into their output schemas.
3390
- *
3391
- * @ignore
3392
- */
3393
- export declare const showEntryGeometries: (state: ToolState, placesEntryId: string, config: NonNullable<z.infer<typeof showPlaceGeometriesSchema>>, options?: ToolExecuteOptions) => Promise<ShowEntryGeometriesResult>;
3394
- //#endregion
3395
- //#region src/tools/shared/show-places-on-map.d.ts
3396
- /** @ignore */
3397
- export declare const showResultsOnMap: (state: ToolState, placesEntryIds: readonly string[], show: z.infer<typeof showPlacesSchema>) => Promise<z.infer<typeof shownSchema>>;
3398
- //#endregion
3399
- //#region src/tools/shared/tool-state-where-context.d.ts
3400
- /** Adapts the live `ToolState` to the narrow `WhereContext` the resolver depends on. Keeping this
3401
- * mapping in one place lets resolveAreas stay testable without a ToolState. */
3402
- export declare const toolStateToWhereContext: (state: ToolState, options?: ToolExecuteOptions) => WhereContext;
3403
- //#endregion
3404
- //#region src/tools/shared/viewport-bias.d.ts
3405
- /**
3406
- * Lowest zoom at which {@link getViewportBias} returns the map centre.
3407
- *
3408
- * @group Agent Toolkit
3409
- */
3410
- export declare const MIN_VIEWPORT_BIAS_ZOOM = 6;
3411
- /**
3412
- * Returns the map centre, to favour search results in view. Pass it as `{ position }` to a service's `geoBias`
3413
- * or to {@link locatePlace}'s `bias`. Below `minZoom`, the view is too wide to say where the user means.
3414
- *
3415
- * @param map - The agent's base-map slice, `state.baseMap` in a tool's `execute`.
3416
- * @returns The centre as `[longitude, latitude]`, or `undefined` below `minZoom`.
3417
- *
3418
- * @group Agent Toolkit
3419
- */
3420
- export declare const getViewportBias: (map: BaseMapState, minZoom?: number) => Position | undefined;
3421
- /** @ignore */
3422
- export declare const getViewportBoundingBox: (map: BaseMapState) => BBox;
3423
- //#endregion
3424
- //#region src/state/custom-geometries/entry.d.ts
3425
- /**
3426
- * Provenance metadata for a custom-geometries entry — captures every input
3427
- * source that fed the polygon-producing operation. `sourceIds` holds tagged
3428
- * ids in the same form `geometriesEntryIDs` accepts: `{ kind: 'place' }` for
3429
- * a single place footprint, `{ kind: 'places' }` for every footprint in a
3430
- * places entry, `{ kind: 'ranges' }` for an isochrone entry,
3431
- * `{ kind: 'customGeometries' }` for a derived entry. `operation` is a short label for
3432
- * the kind of computation that produced the entry (e.g. `'union'`, `'buffer'`,
3433
- * `'h3-coverage'`).
3434
- *
3435
- * @group Agent Toolkit
3436
- *
3437
- * @ignore
3438
- */
3439
- type GeometryProvenance = {
3440
- /** Short label for the operation that produced this entry (free-form). */
3441
- operation?: string;
3442
- /** Tagged source ids that fed the producing operation. */
3443
- sourceIds: readonly GeometriesId[];
3444
- };
3445
- /**
3446
- * A single entry in the custom-geometries history — output of `processData`
3447
- * (and any future polygon-producing tool that doesn't naturally belong to
3448
- * places or ranges).
3449
- *
3450
- * @group Agent Toolkit
3451
- *
3452
- * @ignore
3453
- */
3454
- type CustomGeometriesEntry = BaseEntry<PolygonFeature[]> & {
3455
- /** Inputs and operation that produced this entry. */
3456
- provenance: GeometryProvenance;
3457
- /**
3458
- * Per-entry GeometriesModule. Each entry owns its own module so display state
3459
- * (fill style, current features) lives on the entry instead of a shared slice-level
3460
- * module. Lazy-initialised via CustomGeometriesState helpers.
3461
- */
3462
- _module?: GeometriesModule;
3463
- /** True while this entry's `_module` is rendering on the map. */
3464
- _shown?: boolean;
3465
- };
3466
- //#endregion
3467
- //#region src/state/custom-geometries/state.d.ts
3468
- /**
3469
- * Events fired by {@link CustomGeometriesState}. Subscribe via
3470
- * `state.customGeometries.events.on(type, handler)`.
3471
- *
3472
- * @group Agent Toolkit
3473
- */
3474
- type CustomGeometriesStateEvents = {
3475
- /**
3476
- * An entry was added, or `reset()` cleared the history. `entries` is the full snapshot after
3477
- * the change, and `changedIds` lists the ids of the entries this change added, replaced in
3478
- * place, or removed.
3479
- */
3480
- 'entries-change': {
3481
- entries: readonly CustomGeometriesEntry[];
3482
- changedIds: readonly string[];
3483
- };
3484
- /** The set of entries rendered on the map changed. */
3485
- 'shown-change': ReadonlySet<string>;
3486
- /** The display policy switched between `single` and `multiple`. */
3487
- 'mode-change': EntryMode;
3488
- };
3489
- /**
3490
- * The state for derived or custom geometries, the output of `processData` and any future
3491
- * polygon-producing tool whose result doesn't belong to a place or a reachable-range entry.
3492
- *
3493
- * As in {@link RangeState}, each entry owns a dedicated GeometriesModule, initialised lazily
3494
- * on first show. Provenance metadata captures the input sources (tagged ids) and the
3495
- * operation that produced the polygons.
3496
- *
3497
- * @group Agent Toolkit
3498
- */
3499
- declare class CustomGeometriesState implements ShownEntriesSlice, StateSlice {
3500
- private readonly _ttMap;
3501
- private _entries;
3502
- private _entryMode;
3503
- /** The state change events, listed in {@link CustomGeometriesStateEvents}. */
3504
- readonly events: StateEvents<CustomGeometriesStateEvents>;
3505
- /** The knobs set on every entry's GeometriesModule, such as `line.width`. Cleared on `reset`. */
3506
- readonly knobs: SliceKnobs;
3507
- constructor(_ttMap: TomTomMap);
3508
- get entries(): readonly CustomGeometriesEntry[];
3509
- get latestEntry(): CustomGeometriesEntry | undefined;
3510
- /** Set of custom-geometries entry ids currently rendered on the map. */
3511
- get shownEntryIds(): ReadonlySet<string>;
3512
- /**
3513
- * The display policy. `multiple` (default) lets several derived-geometry entries render
3514
- * side by side. `single` allows at most one entry on the map, and switching to it hides
3515
- * older entries.
3516
- */
3517
- get entryMode(): EntryMode;
3518
- setEntryMode(mode: EntryMode): Promise<void>;
3519
- findById(entryId: string): CustomGeometriesEntry | undefined;
3520
- /**
3521
- * Appends a new entry and returns its assigned id. If `explicitId` collides, the slice adds a
3522
- * suffix (`-2`, `-3`, ...). In `single` mode the new entry replaces every older one.
3523
- */
3524
- addEntry(features: PolygonFeature<CommonPlaceProps>[], provenance: CustomGeometriesEntry['provenance'], label: string, explicitId?: string): Promise<string>;
3525
- /**
3526
- * Initialises the entry's GeometriesModule lazily. Updates only the fill style when it changes,
3527
- * keeping the styling applied since.
3528
- */
3529
- getEntryGeometriesModule(entryId: string, fillStyle?: GeometryFillStyle): Promise<GeometriesModule>;
3530
- /**
3531
- * Renders the entry's polygons. `mode` applies to this entry's own layer only:
3532
- * - `'replace'` (default) shows exactly `entry.data` and clears whatever the
3533
- * entry's module rendered before.
3534
- * - `'add'` merges `entry.data` with the polygons shown on this entry's layer,
3535
- * deduped by feature id. It matters mostly when re-showing the same entry.
3536
- *
3537
- * Other entries are handled separately. With `entryMode === 'single'`, other shown
3538
- * entries are hidden first. Otherwise the caller uses `hideEntry` or the tools'
3539
- * `hidePreviousEntries` option.
3540
- */
3541
- showEntry(entryId: string, fillStyle?: GeometryFillStyle, mode?: 'add' | 'replace'): Promise<void>;
3542
- private _hideOthersUnderSingleMode;
3543
- hideEntry(entryId: string): Promise<void>;
3544
- /** Clears an entry's module, then drops the entry from history. Does nothing for an unknown id. */
3545
- removeEntry(entryId: string): Promise<void>;
3546
- private _requireEntry;
3547
- /**
3548
- * Hides every custom-geometries entry on the map but keeps the history. Implements
3549
- * {@link ClearableMapSlice}.
3550
- */
3551
- clearShown(): Promise<void>;
3552
- reset(): void;
3553
- }
3554
- //#endregion
3555
- //#region src/state/state.d.ts
3556
- /**
3557
- * The per-slice display policy. With `multiple` (default), several history entries can be on the
3558
- * map at once. With `single`, only the most recent one stays. Switching from `multiple` to
3559
- * `single` automatically drops every entry except the latest and clears their modules, so
3560
- * the map matches the new policy immediately.
3561
- *
3562
- * @group Agent Toolkit
3563
- */
3564
- type EntryMode = 'single' | 'multiple';
3565
- /**
3566
- * A state slice that owns a history of entries and can be set to `single` or `multiple`
3567
- * mode. Every {@link ToolState} slice with `setEntryMode` implements this shape, which lets
3568
- * callers (the `setEntryMode` tool, `createMapAgent`'s `dataEntries` option, …) handle the
3569
- * whole family uniformly without listing slice names.
3570
- *
3571
- * @group Agent Toolkit
3572
- */
3573
- interface EntryModeSlice {
3574
- readonly entryMode: EntryMode;
3575
- readonly entries: readonly {
3576
- readonly id: string;
3577
- }[];
3578
- setEntryMode(mode: EntryMode): Promise<void>;
3579
- }
3580
- /**
3581
- * The data-entry kind names that `dataEntries` on `createMapAgent` uses. They extend the
3582
- * analyse/process input kinds (`EntryDataKind`) with `ranges`, which has its own
3583
- * entry-mode-supporting slice but is not a top-level input kind for those tools.
3584
- *
3585
- * The kind names are LLM-facing (`routes`, `incidents`) instead of slice names (`routing`,
3586
- * `trafficIncidents`). The slice mapping is internal (see {@link DATA_ENTRY_KIND_TO_SLICE}).
3587
- *
3588
- * @group Agent Toolkit
3589
- */
3590
- type DataEntryKind = 'places' | 'routes' | 'incidents' | 'customGeometries' | 'trafficAreaAnalytics' | 'byod' | 'ranges';
3591
- /**
3592
- * Per-kind configuration accepted by `createMapAgent`'s `dataEntries` option.
3593
- *
3594
- * @group Agent Toolkit
3595
- */
3596
- type DataEntryConfig = {
3597
- /**
3598
- * When `false`, the kind is removed from the agent's tool surface entirely:
3599
- * - The kind disappears from the `analyseData` and `processData` scope and input fields.
3600
- * - Related recall, display and fetch tools are dropped from the registry
3601
- * (see {@link TOOLS_BY_DATA_ENTRY_KIND}).
3602
- *
3603
- * Defaults to `true`.
3604
- */
3605
- enabled?: boolean;
3606
- /**
3607
- * The initial entry-display policy for the underlying slice. `single` keeps only the latest
3608
- * entry on the map and hides the others. `multiple` (default) lets several coexist.
3609
- */
3610
- entryMode?: EntryMode;
3611
- };
3612
- /**
3613
- * Maps each {@link DataEntryKind} (LLM-facing name) to the {@link ToolState} slice key that
3614
- * owns its entries. `createMapAgent` uses it to apply `entryMode` from
3615
- * `dataEntries[kind].entryMode` to the right slice.
3616
- *
3617
- * @group Agent Toolkit
3618
- */
3619
- export declare const DATA_ENTRY_KIND_TO_SLICE: {
3620
- readonly places: "places";
3621
- readonly routes: "routing";
3622
- readonly incidents: "trafficIncidents";
3623
- readonly customGeometries: "customGeometries";
3624
- readonly trafficAreaAnalytics: "trafficAreaAnalytics";
3625
- readonly byod: "byod";
3626
- readonly ranges: "ranges";
3774
+ readonly getProgressAtNearestRoutePoint: (route: import("@tomtom-org/maps-sdk/core").Route, point: import("@tomtom-org/maps-sdk/core").HasLngLat) => import("@tomtom-org/maps-sdk/core").RouteCoordinateAtProgress | undefined;
3775
+ readonly getRouteProgressBetween: (route: import("@tomtom-org/maps-sdk/core").Route, startPathIndex: number, endPathIndex: number) => import("@tomtom-org/maps-sdk/core").RouteSegmentProgress | undefined;
3776
+ readonly getRouteProgressForSection: (route: import("@tomtom-org/maps-sdk/core").Route, section: import("@tomtom-org/maps-sdk/core").RouteSpan) => import("@tomtom-org/maps-sdk/core").RouteSegmentProgress | undefined;
3777
+ readonly getSectionBBox: (route: import("@tomtom-org/maps-sdk/core").Route, section: import("@tomtom-org/maps-sdk/core").RouteSpan) => import("@tomtom-org/maps-sdk/core").OptionalBBox;
3778
+ readonly getSectionsWithin: (route: import("@tomtom-org/maps-sdk/core").Route, { within, types }?: import("@tomtom-org/maps-sdk/core").SectionsWithinOptions) => import("@tomtom-org/maps-sdk/core").SectionsWithin;
3779
+ readonly isHairpin: (curve: Pick<import("@tomtom-org/maps-sdk/core").CurveSectionProps, "headingChangeInDegrees" | "radiusInMeters" | "maneuver">) => boolean;
3627
3780
  };
3781
+ //#endregion
3782
+ //#region src/tools/shared/routes-schema-doc.d.ts
3628
3783
  /**
3629
- * The compile-time union of {@link ToolState} keys whose slice supports {@link EntryMode}.
3630
- * Names match the {@link ToolState} keys exactly, such as `routing` (not `routes`) and
3631
- * `customGeometries` (not `geometries`), so the slice name in the tool API never drifts
3632
- * from the property on `state`.
3784
+ * @module agent-toolkit-tools
3633
3785
  *
3634
- * When a new slice implements `setEntryMode`, the union picks up its key, and the runtime
3635
- * list {@link ENTRY_MODE_SLICE_NAMES} fails to type-check until the key is added there too.
3786
+ * Compact schema documentation for the `Route` properties shape, reused by
3787
+ * every tool whose LLM-authored code reads a Routes FeatureCollection
3788
+ * (`analyseData`, `processData`), injected per entry as `routesByEntry[id]`.
3789
+ * Only the non-GeoJSON-standard bits are spelled out, since `Route` is a LineString Feature.
3790
+ */
3791
+ /** @ignore */
3792
+ export declare const ROUTES_SCHEMA_DOC: string;
3793
+ //#endregion
3794
+ //#region src/tools/shared/show-byod-on-map.d.ts
3795
+ /**
3796
+ * Render a BYOD entry on the map per the tool's `show` options: hide
3797
+ * previously-shown entries (per `hidePreviousEntries`), show the new entry, then
3798
+ * optionally fit the camera to every shown BYOD entry. Sequential by design —
3799
+ * map mutations must not race (see ENGINEERING-GUIDELINES §6).
3636
3800
  *
3637
- * @group Agent Toolkit
3801
+ * @ignore
3638
3802
  */
3639
- type EntryModeSliceName = { [K in keyof ToolState]: ToolState[K] extends EntryModeSlice ? K : never; }[keyof ToolState];
3803
+ export declare const showByodOnMap: (state: ToolState, byodEntryId: string, show: z.infer<typeof showByodSchema>) => Promise<z.infer<typeof shownByodSchema>>;
3804
+ //#endregion
3805
+ //#region src/tools/shared/show-entry-geometries.d.ts
3640
3806
  /**
3641
- * The runtime list of slice names that support entry mode. Its `satisfies` clause makes
3642
- * drift a compile error. When a new {@link ToolState} slice gains `setEntryMode`, the
3643
- * package won't build until this constant is updated.
3807
+ * `error` is set when a Geometry Data request failed, so a failed fetch doesn't read as a place
3808
+ * without a boundary.
3644
3809
  *
3645
- * @group Agent Toolkit
3810
+ * @ignore
3646
3811
  */
3647
- export declare const ENTRY_MODE_SLICE_NAMES: readonly EntryModeSliceName[];
3812
+ export type ShowEntryGeometriesResult = {
3813
+ fetched: number;
3814
+ shown: boolean;
3815
+ error?: string;
3816
+ };
3648
3817
  /**
3649
- * A state slice that owns a set of "entries" (routes, ranges), each of which can be hidden
3650
- * individually by id, and exposes the shown set. {@link RoutingState} and {@link RangeState}
3651
- * implement it. Helpers that hide previously-shown entries before rendering a new one
3652
- * consume it (see `hidePreviousShownEntries`).
3818
+ * Fetch boundary polygons for every place in an entry that has a geometry data source,
3819
+ * cache them on the entry, and optionally render them via the entry's GeometriesModule.
3653
3820
  *
3654
- * {@link PlacesState} doesn't implement it, because it uses a wider per-entry marker-type
3655
- * model (`removeShownEntries(ids)` instead of `hideEntry(id)`).
3821
+ * Shared by tools that produce a single places entry (discoverPlaces, locatePlace) — they
3822
+ * differ only in how they shape the result into their output schemas.
3656
3823
  *
3657
- * @group Agent Toolkit
3824
+ * @ignore
3658
3825
  */
3659
- interface ShownEntriesSlice extends StateSlice {
3660
- readonly entryMode: EntryMode;
3661
- readonly shownEntryIds: ReadonlySet<string>;
3662
- hideEntry(entryId: string): Promise<void>;
3663
- }
3826
+ export declare const showEntryGeometries: (state: ToolState, placesEntryId: string, config: NonNullable<z.infer<typeof showPlaceGeometriesSchema>>, options?: ToolExecuteOptions) => Promise<ShowEntryGeometriesResult>;
3664
3827
  //#endregion
3665
- //#region src/state/byod/state.d.ts
3828
+ //#region src/tools/shared/show-places-on-map.d.ts
3829
+ /** @ignore */
3830
+ export declare const showResultsOnMap: (state: ToolState, placesEntryIds: readonly string[], show: z.infer<typeof showPlacesSchema>) => Promise<z.infer<typeof shownSchema>>;
3831
+ //#endregion
3832
+ //#region src/tools/shared/tool-state-where-context.d.ts
3833
+ /** Adapts the live `ToolState` to the narrow `WhereContext` the resolver depends on. Keeping this
3834
+ * mapping in one place lets resolveWithin stay testable without a ToolState. */
3835
+ export declare const toolStateToWhereContext: (state: ToolState, options?: ToolExecuteOptions) => WhereContext;
3836
+ //#endregion
3837
+ //#region src/tools/shared/viewport-bias.d.ts
3666
3838
  /**
3667
- * Events fired by {@link BYODState}. Subscribe via `state.byod.events.on(type, handler)`.
3839
+ * Lowest zoom at which {@link getViewportBias} returns the map centre.
3668
3840
  *
3669
3841
  * @group Agent Toolkit
3670
3842
  */
3671
- type BYODStateEvents = {
3672
- /**
3673
- * An entry was added or removed, or `reset()` cleared the history. `entries` is the full
3674
- * snapshot after the change, and `changedIds` lists the ids of the entries this change added,
3675
- * replaced in place, or removed.
3676
- */
3677
- 'entries-change': {
3678
- entries: readonly BYODEntry[];
3679
- changedIds: readonly string[];
3680
- };
3681
- /** The set of entries rendered on the map changed. */
3682
- 'shown-change': ReadonlySet<string>;
3683
- /** The display policy switched between `single` and `multiple`. */
3684
- 'mode-change': EntryMode;
3685
- };
3843
+ export declare const MIN_VIEWPORT_BIAS_ZOOM = 6;
3686
3844
  /**
3687
- * Options accepted by {@link BYODState.addEntry}.
3845
+ * Returns the map centre, to favour search results in view. Pass it as `{ position }` to a service's `geoBias`
3846
+ * or to {@link locatePlace}'s `bias`. Below `minZoom`, the view is too wide to say where the user means.
3847
+ *
3848
+ * @param map - The agent's base-map slice, `state.baseMap` in a tool's `execute`.
3849
+ * @returns The centre as `[longitude, latitude]`, or `undefined` below `minZoom`.
3688
3850
  *
3689
3851
  * @group Agent Toolkit
3690
3852
  */
3691
- type AddBYODEntryOptions = {
3692
- /**
3693
- * Explicit MapLibre layer specs, never derived automatically. You pass them here,
3694
- * or the agent sets them via `setByodLayers`. Until then the entry renders nothing.
3695
- * Either way they are only stored, and {@link BYODState.showEntry} renders them.
3696
- */
3697
- layers?: CustomGeoJSONLayerSpec[];
3698
- /** Provenance for the data. Defaults to `{ kind: 'integrator' }`. */
3699
- source?: BYODSource;
3700
- /**
3701
- * Semantic entry id. Auto-suffixed (`-2`, `-3`, …) on collision. Defaults
3702
- * to `byod-N`.
3703
- */
3704
- explicitId?: string;
3705
- };
3853
+ export declare const getViewportBias: (map: BaseMapState, minZoom?: number) => Position | undefined;
3706
3854
  /**
3707
- * The verdict a {@link ByodSourceUrlValidator} returns. `{ valid: true }` explicitly allows
3708
- * the fetch, and `{ valid: false, reason }` blocks it and surfaces the `reason` to the model
3709
- * as the tool error.
3855
+ * MapLibre reports a view across the antimeridian with an edge past ±180, and a view wider than the
3856
+ * world with a span of 360 or more. The returned box wraps the edges, `west > east` across the
3857
+ * antimeridian, and spans the whole world once the view does.
3710
3858
  *
3711
- * @group Agent Toolkit
3859
+ * @ignore
3712
3860
  */
3713
- type ByodSourceUrlValidation = {
3714
- valid: true;
3715
- } | {
3716
- valid: false;
3717
- reason: string;
3718
- };
3861
+ export declare const getViewportBoundingBox: (map: BaseMapState) => BBox;
3862
+ //#endregion
3863
+ //#region src/state/custom-geometries/entry.d.ts
3719
3864
  /**
3720
- * An app-supplied authorization hook for BYOD source URLs. `addByodSource` runs it on
3721
- * every `http:` or `https:` URL, before the network fetch. Return `{ valid: true }` to
3722
- * allow the fetch or `{ valid: false, reason }` to block it (see
3723
- * {@link ByodSourceUrlValidation}). It may be sync or async, such as an allowlist lookup.
3724
- *
3725
- * It **replaces** the built-in policy, which allows only public `https:` URLs: no
3726
- * `http:`, no page origin, no `localhost`-style hostname and no loopback, private,
3727
- * link-local or other non-public IP address. The size cap, the timeout, the omitted
3728
- * credentials and the refused redirects apply either way. Set it via the
3729
- * `byod.validateSourceUrl` option on `createMapAgent`, or assign
3730
- * `state.byod.sourceUrlValidator` directly.
3865
+ * Provenance metadata for a custom-geometries entry — captures every input
3866
+ * source that fed the polygon-producing operation. `sourceIds` holds tagged
3867
+ * ids in the same form `geometriesEntryIDs` accepts: `{ kind: 'place' }` for
3868
+ * a single place footprint, `{ kind: 'places' }` for every footprint in a
3869
+ * places entry, `{ kind: 'ranges' }` for an isochrone entry,
3870
+ * `{ kind: 'customGeometries' }` for a derived entry. `operation` is a short label for
3871
+ * the kind of computation that produced the entry (e.g. `'union'`, `'buffer'`,
3872
+ * `'h3-coverage'`).
3731
3873
  *
3732
3874
  * @group Agent Toolkit
3875
+ *
3876
+ * @ignore
3733
3877
  */
3734
- type ByodSourceUrlValidator = (url: URL) => ByodSourceUrlValidation | Promise<ByodSourceUrlValidation>;
3878
+ type GeometryProvenance = {
3879
+ /** Short label for the operation that produced this entry (free-form). */
3880
+ operation?: string;
3881
+ /** Tagged source ids that fed the producing operation. */
3882
+ sourceIds: readonly GeometriesId[];
3883
+ };
3735
3884
  /**
3736
- * The state slice for BYOD (bring-your-own-data) GeoJSON layers, the customer-owned
3737
- * data that doesn't fit places, routes, ranges or custom geometries. Each entry
3738
- * wraps a {@link CustomGeoJSONModule} so the agent can render, query, and pipe it
3739
- * through analyseData or processData.
3740
- *
3741
- * As in {@link CustomGeometriesState}, every entry owns its own module, initialised
3742
- * lazily on first show.
3885
+ * A single entry in the custom-geometries history — output of `processData`
3886
+ * (and any future polygon-producing tool that doesn't naturally belong to
3887
+ * places or ranges).
3743
3888
  *
3744
3889
  * @group Agent Toolkit
3890
+ *
3891
+ * @ignore
3745
3892
  */
3746
- declare class BYODState implements ShownEntriesSlice, StateSlice {
3747
- private readonly _ttMap;
3748
- private _entries;
3749
- private _entryMode;
3750
- /** The state change events, listed in {@link BYODStateEvents}. */
3751
- readonly events: StateEvents<BYODStateEvents>;
3752
- /**
3753
- * The optional authorization hook for `addByodSource` URL fetches (see
3754
- * {@link ByodSourceUrlValidator}). If unset, the built-in policy allows only
3755
- * public `https:` URLs.
3756
- */
3757
- sourceUrlValidator?: ByodSourceUrlValidator;
3758
- constructor(_ttMap: TomTomMap);
3759
- get entries(): readonly BYODEntry[];
3760
- get latestEntry(): BYODEntry | undefined;
3761
- /** Set of BYOD entry ids currently rendered on the map. */
3762
- get shownEntryIds(): ReadonlySet<string>;
3763
- get entryMode(): EntryMode;
3764
- setEntryMode(mode: EntryMode): Promise<void>;
3765
- findById(entryId: string): BYODEntry | undefined;
3766
- /**
3767
- * Appends a new BYOD entry and returns its assigned id. In `single` mode the new entry
3768
- * replaces every older one. It hides and drops them before pushing the new entry, so the
3769
- * caller never sees it rendered on top of a still-visible old one.
3770
- */
3771
- addEntry(data: FeatureCollection$1, label: string, options?: AddBYODEntryOptions): Promise<string>;
3772
- /**
3773
- * Replaces the MapLibre layer specs an entry renders under. If the entry already owns a
3774
- * module because it was shown at least once, the module's `applyConfig` runtime layer diff
3775
- * pushes the new specs live, without tear-down or flicker. Otherwise the specs are stored
3776
- * and the next {@link showEntry} picks them up. Throws on an unknown id.
3777
- */
3778
- setEntryLayers(entryId: string, layers: CustomGeoJSONLayerSpec[]): void;
3779
- /**
3780
- * Initialises the entry's CustomGeoJSONModule lazily. The module has a single
3781
- * source named `data`, configured with this entry's `layers`. To swap layers
3782
- * afterwards, call {@link setEntryLayers}, which pushes the new specs into this
3783
- * module via `applyConfig` instead of recreating it.
3784
- */
3785
- getEntryModule(entryId: string): Promise<CustomGeoJSONModule>;
3786
- /** Renders the entry on the map. */
3787
- showEntry(entryId: string): Promise<void>;
3788
- private _hideOthersUnderSingleMode;
3789
- hideEntry(entryId: string): Promise<void>;
3790
- /** Clears an entry's module, then drops the entry from history. Does nothing for an unknown id. */
3791
- removeEntry(entryId: string): Promise<void>;
3792
- private _requireEntry;
3893
+ type CustomGeometriesEntry = BaseEntry<PolygonFeature[]> & {
3894
+ /** Inputs and operation that produced this entry. */
3895
+ provenance: GeometryProvenance;
3793
3896
  /**
3794
- * Hides every BYOD layer on the map but keeps the history. Implements
3795
- * {@link ClearableMapSlice}.
3897
+ * Per-entry GeometriesModule. Each entry owns its own module so display state
3898
+ * (fill style, current features) lives on the entry instead of a shared slice-level
3899
+ * module. Lazy-initialised via CustomGeometriesState helpers.
3796
3900
  */
3797
- clearShown(): Promise<void>;
3798
- reset(): void;
3799
- }
3901
+ _module?: GeometriesModule;
3902
+ /** True while this entry's `_module` is rendering on the map. */
3903
+ _shown?: boolean;
3904
+ };
3800
3905
  //#endregion
3801
3906
  //#region src/system-prompt.d.ts
3802
3907
  /**
@@ -3971,7 +4076,8 @@ export declare const buildSystemPrompt: ({ customPrompt, prefix, suffix }?: Buil
3971
4076
  * {@link ToolBuildOptions} (e.g. feature flags) at agent-creation time.
3972
4077
  *
3973
4078
  * createMapAgent includes it automatically unless includeDefaultTools is false.
3974
- * For manual composition outside createMapAgent, use resolveTools().
4079
+ * resolveTools() merges your additions, replacements and removals into it; createMapAgent then
4080
+ * builds the builder entries and binds `help`.
3975
4081
  * It leaves out executeMaplibreCode, which runs model-written code in your page.
3976
4082
  * createExecuteMaplibreCodeTool() adds it.
3977
4083
  *
@@ -4058,8 +4164,9 @@ export declare const TOOLS_BY_DATA_ENTRY_KIND: Record<DataEntryKind, readonly To
4058
4164
  * materialised with empty {@link ToolBuildOptions} so the prompts reflect the
4059
4165
  * tool's default (full-surface) shape. Tools without prompts map to `[]`.
4060
4166
  *
4061
- * Surface these in chat UIs to keep starter suggestions in sync with what the
4062
- * tools can actually do. The registry stays the single source of truth.
4167
+ * It covers the full default registry, whatever an agent's `dataEntries` or `tools`
4168
+ * options drop, so filter the result to the agent's resolved tools before surfacing
4169
+ * these as starter suggestions in a chat UI.
4063
4170
  *
4064
4171
  * @group Agent Toolkit
4065
4172
  */
@@ -4160,7 +4267,7 @@ export declare const extractLastUserText: (messages: ReadonlyArray<ModelMessage>
4160
4267
  * message with structured generation.
4161
4268
  *
4162
4269
  * @param options.model - Language model for classification (ideally fast/cheap like gpt-4o-mini)
4163
- * @param options.maxHistoryMessages - Max prior turns for context. Default: 8
4270
+ * @param options.maxHistoryMessages - Max prior messages, user and assistant alike, for context. Default: 8
4164
4271
  * @param options.maxHistoryMessageLength - Max chars per history message. Default: 300
4165
4272
  *
4166
4273
  * @group Agent Toolkit
@@ -4280,9 +4387,10 @@ export type CodeExecutionConfig = {
4280
4387
  timeoutMs?: number;
4281
4388
  /**
4282
4389
  * Optional override of the worker's library source. By default, the SDK loads its own
4283
- * inlined turf/h3 UMD (a separate lazy chunk), so this is rarely needed. Supply it only
4284
- * to pin a specific build or add libraries. Return UMD/IIFE JavaScript that defines
4285
- * `self.turf` and `self.h3` (string or Promise of one).
4390
+ * inlined turf/h3 UMD and worker utilities (a separate lazy chunk), so this is rarely needed.
4391
+ * Supply it only to pin a specific build. The returned source replaces the bundled one whole:
4392
+ * return UMD/IIFE JavaScript (string or Promise of one) that defines `self.turf` and `self.h3`,
4393
+ * plus `self.routeUtils` and `self.cluster` if generated code uses them.
4286
4394
  */
4287
4395
  loadWorkerLibrarySource?: () => string | Promise<string>;
4288
4396
  /**
@@ -4342,15 +4450,7 @@ export type ToolEntry<S extends ToolState = ToolState, Scope = unknown> = {
4342
4450
  inputSchema: z.ZodType;
4343
4451
  /** Optional Zod schema describing the tool's structured output. */
4344
4452
  outputSchema?: z.ZodType;
4345
- /**
4346
- * Function that executes the tool. It receives the parsed input and the agent's state.
4347
- *
4348
- * If this calls a `@tomtom-org/maps-sdk/services` function directly, wrap its params with
4349
- * `withAgentToolkitHeaders` (`tools/shared/agent-headers.ts`) before passing them in, for example
4350
- * `const requestParams = withAgentToolkitHeaders({ position }); await reverseGeocode(requestParams);`.
4351
- * This tags the request so TomTom's traffic analytics attribute it to agent-toolkit. The guard
4352
- * test in `tools/shared/tests/agent-headers.test.ts` picks up an untagged call.
4353
- */
4453
+ /** Function that executes the tool. It receives the parsed input and the agent's state. */
4354
4454
  execute: (input: any, state: S, options?: ToolExecuteOptions) => Promise<any>;
4355
4455
  /** Compact one-liner for the intent classifier prompt. */
4356
4456
  classificationPrompt?: string;
@@ -4368,7 +4468,8 @@ export type ToolEntry<S extends ToolState = ToolState, Scope = unknown> = {
4368
4468
  * Whether this tool stays active on every step regardless of the classifier's selection. Its name is
4369
4469
  * unioned into the per-turn `activeTools` set, so the model can always reach it. Use it sparingly,
4370
4470
  * for tools that may be needed to set up *any* request (e.g. asking the user to clarify intent).
4371
- * It has no effect on the fail-open path (when classification is skipped, every tool is active).
4471
+ * A host `prepareStep` can't narrow it away either. It has no effect on the fail-open path (when
4472
+ * classification is skipped, every tool is active).
4372
4473
  */
4373
4474
  alwaysActive?: boolean;
4374
4475
  /**
@@ -4404,7 +4505,7 @@ export type ToolEntry<S extends ToolState = ToolState, Scope = unknown> = {
4404
4505
  export type ToolMetadata = {
4405
4506
  /** Tool identifier, derived from the config key. */
4406
4507
  name: string;
4407
- /** Description of the tool's purpose, used by the SDK's system prompt. */
4508
+ /** Description of the tool's purpose, which the model reads and the help tool's detail mode shows. */
4408
4509
  description: string;
4409
4510
  /** Compact one-liner for the intent classifier prompt. */
4410
4511
  classificationPrompt?: string;
@@ -4516,7 +4617,7 @@ export type ToolEntryBuilder<S extends ToolState = ToolState, Scope = unknown> =
4516
4617
  *
4517
4618
  * @typeParam S - The ToolState shape this tool requires. Default: base `ToolState`.
4518
4619
  * @typeParam Scope - Optional per-tool scope shape (only relevant for builder
4519
- * form). Defaults to `never` for non-scopable tools.
4620
+ * form). Defaults to `any`, so builders with any scope type fit.
4520
4621
  *
4521
4622
  * @group Agent Toolkit
4522
4623
  */
@@ -4527,7 +4628,7 @@ export type ToolDefinition<S extends ToolState = ToolState, Scope = any> = ToolE
4527
4628
  * @group Agent Toolkit
4528
4629
  */
4529
4630
  export type ToolExecutionInfo = {
4530
- /** Registered tool name (the `defaultTools` key). */
4631
+ /** The name the tool is registered under: its `DEFAULT_TOOLS` or `MapAgentOptions.tools` key. */
4531
4632
  toolName: string;
4532
4633
  /** Wall-clock duration of `execute`, in milliseconds (includes any network/IO). */
4533
4634
  durationMs: number;
@@ -4599,7 +4700,7 @@ export type MapAgentOptions<CS extends ToolState = ToolState> = {
4599
4700
  * Tool overrides merged with default tools.
4600
4701
  * - {@link ToolDefinition} values (a `ToolEntry`, a builder, or a `DEFAULT_TOOLS` value) add a new
4601
4702
  * tool or replace a default.
4602
- * - `false` values exclude a default tool.
4703
+ * - `false` and `undefined` values exclude a default tool.
4603
4704
  *
4604
4705
  * When omitted, all default tools are used as-is.
4605
4706
  *
@@ -4628,13 +4729,13 @@ export type MapAgentOptions<CS extends ToolState = ToolState> = {
4628
4729
  /**
4629
4730
  * Per-kind data-entry configuration. Each {@link DataEntryKind} accepts
4630
4731
  * `{ enabled?, entryMode? }`. Setting `enabled: false` removes the kind from the
4631
- * agent's tool surface entirely. It disappears from `analyseData` / `processData`
4732
+ * agent's data tools. It disappears from `analyseData` / `processData`
4632
4733
  * scope and input fields, and its slice-specific display / fetch tools
4633
- * ({@link TOOLS_BY_DATA_ENTRY_KIND}) are dropped from the registry. `recallState` stays.
4734
+ * ({@link TOOLS_BY_DATA_ENTRY_KIND}) are dropped from the registry. `recallState` and `setMapStyling` stay.
4634
4735
  * `entryMode` is applied to the underlying slice right after the agent state is built, before any tool runs.
4635
4736
  *
4636
4737
  * Keys are LLM-facing kind names (`routes`, `incidents`), not slice names
4637
- * (`routing`, `trafficIncidents`). The slice mapping is internal.
4738
+ * (`routing`, `trafficIncidents`). {@link DATA_ENTRY_KIND_TO_SLICE} maps one to the other.
4638
4739
  *
4639
4740
  * @example
4640
4741
  * ```typescript
@@ -4705,7 +4806,8 @@ export type MapAgentOptions<CS extends ToolState = ToolState> = {
4705
4806
  onToolExecute?: OnToolExecute;
4706
4807
  /**
4707
4808
  * Custom prepareStep hook, composed with internal classification step.
4708
- * Your `activeTools` are intersected with the classifier's selection.
4809
+ * Your `activeTools` are intersected with the classifier's selection, and every `alwaysActive`
4810
+ * tool is added back.
4709
4811
  * An `instructions` or `messages` override carries over to the later steps of the turn: build
4710
4812
  * `instructions` from `initialInstructions`, and `messages` from
4711
4813
  * `[...initialMessages, ...responseMessages]`, so the earlier steps' tool calls and results stay in.
@@ -4777,7 +4879,10 @@ export type MapAgentInstance<CS extends ToolState = ToolState> = ToolLoopAgent &
4777
4879
  * `main-thread` (code runs unisolated) both mean the iframe sandbox couldn't start.
4778
4880
  */
4779
4881
  getCodeExecutionMode(): CodeExecutionMode;
4780
- /** Tears down by resetting all state slices that have a reset() method. */
4882
+ /**
4883
+ * Tears down by resetting all state slices that have a reset() method and destroying the code
4884
+ * sandbox. The map keeps the agent-toolkit request tag `createMapAgent` set on it.
4885
+ */
4781
4886
  destroy(): void;
4782
4887
  };
4783
4888
  //#endregion
@@ -4785,15 +4890,15 @@ export type MapAgentInstance<CS extends ToolState = ToolState> = ToolLoopAgent &
4785
4890
  /**
4786
4891
  * Creates a conversational agent toolkit that gives an LLM control over a TomTom map.
4787
4892
  *
4788
- * It returns a ToolLoopAgent instance (compatible with DirectChatTransport) with
4789
- * `state` and `destroy` attached. Classification runs transparently inside
4790
- * `prepareStep`, so you need no wrapper type.
4893
+ * It returns a ToolLoopAgent instance (compatible with DirectChatTransport) with `state`, `destroy`
4894
+ * and `getCodeExecutionMode` attached ({@link MapAgentInstance}). Classification runs transparently
4895
+ * inside `prepareStep`, so you need no wrapper type.
4791
4896
  *
4792
4897
  * @remarks
4793
4898
  * **[Public Preview](https://docs.tomtom.com/legal/public-preview)** until the plugin's 1.0.0 release.
4794
4899
  *
4795
4900
  * @param map - The map to control.
4796
- * @returns A ToolLoopAgent with state access and cleanup.
4901
+ * @returns A ToolLoopAgent with state access, cleanup and the code-execution mode.
4797
4902
  *
4798
4903
  * @example Basic usage
4799
4904
  * ```typescript
@@ -4829,7 +4934,7 @@ export declare const createMapAgent: <CS extends ToolState = ToolState>(map: Tom
4829
4934
  * Merges default tools with user overrides.
4830
4935
  *
4831
4936
  * - `ToolEntry` (or builder) values add or replace tools in `defaults`.
4832
- * - `false` values remove tools from `defaults`.
4937
+ * - `false` and `undefined` values remove tools from `defaults`.
4833
4938
  * - It returns a new object and never mutates `defaults`.
4834
4939
  *
4835
4940
  * Default entries may be {@link ToolEntryBuilder builders} that produce
@@ -4862,17 +4967,27 @@ export declare const resolveTools: <S extends ToolState>(defaults: Record<string
4862
4967
  export declare const createExecuteMaplibreCodeTool: () => ToolEntry;
4863
4968
  //#endregion
4864
4969
  //#region src/tools/utilities/clarify-user-intent.d.ts
4865
- /** A single clarification question shown to the user. Exported so a host can type its form state. */
4970
+ /**
4971
+ * A single clarification question shown to the user. Exported so a host can type its form state.
4972
+ *
4973
+ * @group Agent Toolkit
4974
+ */
4866
4975
  export declare const questionSchema: z.ZodObject<{
4867
4976
  id: z.ZodString;
4868
4977
  question: z.ZodString;
4869
4978
  options: z.ZodArray<z.ZodString>;
4870
4979
  multiSelect: z.ZodDefault<z.ZodBoolean>;
4871
4980
  }, z.core.$strip>;
4872
- /** One clarification question, the unit a host UI renders. */
4981
+ /**
4982
+ * One clarification question, the unit a host UI renders.
4983
+ *
4984
+ * @group Agent Toolkit
4985
+ */
4873
4986
  type ClarifyIntentQuestion = z.infer<typeof questionSchema>;
4874
4987
  /**
4875
- * Input schema for {@link executeClarifyIntent}.
4988
+ * Input schema for the clarifyIntent tool.
4989
+ *
4990
+ * @group Agent Toolkit
4876
4991
  */
4877
4992
  export declare const clarifyIntentSchema: z.ZodObject<{
4878
4993
  intro: z.ZodOptional<z.ZodString>;
@@ -4884,11 +4999,9 @@ export declare const clarifyIntentSchema: z.ZodObject<{
4884
4999
  }, z.core.$strip>>;
4885
5000
  }, z.core.$strip>;
4886
5001
  /**
4887
- * Output schema for {@link executeClarifyIntent}. The tool resolves immediately, echoing back the
4888
- * `intro` + `questions` (so a host can render the whole form) plus an `awaiting_user_response` status.
4889
- * No "stop and wait" directive is echoed, because the description-level usage contract already carries
4890
- * it. CLARIFY_FORM_PROMPT and CLARIFY_PROSE_PROMPT both tell the agent to STOP and wait, so repeating it
4891
- * in the result would be redundant.
5002
+ * Output schema for the clarifyIntent tool: the `intro` and `questions` echoed back, for a host to render.
5003
+ *
5004
+ * @group Agent Toolkit
4892
5005
  */
4893
5006
  export declare const clarifyIntentOutputSchema: z.ZodObject<{
4894
5007
  status: z.ZodLiteral<"awaiting_user_response">;
@@ -4900,11 +5013,23 @@ export declare const clarifyIntentOutputSchema: z.ZodObject<{
4900
5013
  multiSelect: z.ZodDefault<z.ZodBoolean>;
4901
5014
  }, z.core.$strip>>;
4902
5015
  }, z.core.$strip>;
4903
- /** Usage contract appended to the description when the host renders the form: silent turn, questions not restated in prose. */
5016
+ /**
5017
+ * Usage contract appended to the description when the host renders the form: silent turn, questions not restated in prose.
5018
+ *
5019
+ * @group Agent Toolkit
5020
+ */
4904
5021
  export declare const CLARIFY_FORM_PROMPT: string;
4905
- /** Usage contract appended to the description when there is no form. The model also writes the questions as prose so any UI shows them. */
5022
+ /**
5023
+ * Usage contract appended to the description when there is no form. The model also writes the questions as prose so any UI shows them.
5024
+ *
5025
+ * @group Agent Toolkit
5026
+ */
4906
5027
  export declare const CLARIFY_PROSE_PROMPT: string;
4907
- /** Per-call overrides accepted by {@link createClarifyIntentTool}. */
5028
+ /**
5029
+ * Per-call overrides accepted by {@link createClarifyIntentTool}.
5030
+ *
5031
+ * @group Agent Toolkit
5032
+ */
4908
5033
  type ClarifyIntentToolOptions = {
4909
5034
  /** Replace the default tool description (e.g. add domain-specific guidance). */
4910
5035
  description?: string;
@@ -4941,10 +5066,17 @@ type ClarifyIntentToolOptions = {
4941
5066
  * },
4942
5067
  * });
4943
5068
  * ```
5069
+ *
5070
+ * @group Agent Toolkit
4944
5071
  */
4945
5072
  export declare const createClarifyIntentTool: (options?: ClarifyIntentToolOptions) => ToolEntry;
4946
5073
  //#endregion
4947
5074
  //#region src/tools/utilities/get-current-location.d.ts
5075
+ /**
5076
+ * Options of {@link createGetCurrentLocationTool}.
5077
+ *
5078
+ * @group Agent Toolkit
5079
+ */
4948
5080
  type GetCurrentLocationToolOptions = {
4949
5081
  /**
4950
5082
  * Whether the model gets the exact position, the device's accuracy and the fix's timestamp, from a
@@ -4963,6 +5095,8 @@ type GetCurrentLocationToolOptions = {
4963
5095
  * tools: { getCurrentLocation: createGetCurrentLocationTool({ fullPrecision: true }) },
4964
5096
  * });
4965
5097
  * ```
5098
+ *
5099
+ * @group Agent Toolkit
4966
5100
  */
4967
5101
  export declare const createGetCurrentLocationTool: (options?: GetCurrentLocationToolOptions) => ToolEntry;
4968
5102
  //#endregion