@arcgis/ai-components 5.2.0-next.13 → 5.2.0-next.15

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.
@@ -1,11 +1,11 @@
1
1
  /* COPYRIGHT Esri - https://js.arcgis.com/5.2/LICENSE.txt */
2
2
  import { StateGraph as I, START as k, END as v } from "@langchain/langgraph/web";
3
- import { g as T, O as R, P as C, t as N, Q as V, f as h, R as D, r as z, S as b, T as P } from "./adapter.js";
3
+ import { g as T, O as R, P as C, t as N, Q as V, f, R as D, r as z, S as _, T as P } from "./adapter.js";
4
4
  import "@arcgis/core/identity/IdentityManager.js";
5
5
  import "@arcgis/core/portal/Portal.js";
6
6
  import "@arcgis/toolkit/string";
7
- import { h as _, e as Q } from "./generateLayerDescriptions.js";
8
- import { AIMessage as j } from "@langchain/core/messages";
7
+ import { h as $, e as Q } from "./generateLayerDescriptions.js";
8
+ import { AIMessage as O } from "@langchain/core/messages";
9
9
  import { s as n } from "./index.js";
10
10
  import "@langchain/openai";
11
11
  import "@arcgis/core/config.js";
@@ -13,8 +13,8 @@ import "@arcgis/core/core/reactiveUtils.js";
13
13
  import "@arcgis/core/layers/FeatureLayer.js";
14
14
  import "@arcgis/core/request.js";
15
15
  import "@langchain/core/prompts";
16
- import { h as $ } from "./toolCallResponse.js";
17
- import { ToolNode as O } from "@langchain/langgraph/prebuilt";
16
+ import { h as b } from "./toolCallResponse.js";
17
+ import { ToolNode as j } from "@langchain/langgraph/prebuilt";
18
18
  import G from "@arcgis/core/smartMapping/statistics/summaryStatistics.js";
19
19
  import U from "@arcgis/core/smartMapping/statistics/uniqueValues.js";
20
20
  const W = async (t, e) => (await n({ text: "Exiting Data Exploration agent" }, e), t), B = async (t, e) => {
@@ -22,7 +22,7 @@ const W = async (t, e) => (await n({ text: "Exiting Data Exploration agent" }, e
22
22
  const d = await T("data_explore_filter_prompt");
23
23
  if (!e?.configurable)
24
24
  throw new Error("config.configurable is required for layer filter tools");
25
- const { userTimezone: l, userTimezoneOffset: s } = R(), o = {
25
+ const { userTimezone: l, userTimezoneOffset: s } = R(), r = {
26
26
  layerFieldInfo: t.layerFieldInfo,
27
27
  userTimezone: l,
28
28
  userTimezoneOffset: s,
@@ -30,59 +30,70 @@ const W = async (t, e) => (await n({ text: "Exiting Data Exploration agent" }, e
30
30
  assignedTask: t.agentExecutionContext.assignedTask,
31
31
  userRequest: t.agentExecutionContext.userRequest,
32
32
  priorSteps: t.agentExecutionContext.priorSteps
33
- }, r = await _({
33
+ }, o = await $({
34
34
  promptText: d,
35
35
  modelTier: "advanced",
36
36
  config: e,
37
37
  messages: t.dataExplorationMessages,
38
- inputVariables: o,
38
+ inputVariables: r,
39
39
  tools: C
40
- }), i = [...t.dataExplorationMessages, r];
41
- if (!((r.tool_calls?.length ?? 0) > 0))
40
+ }), i = [...t.dataExplorationMessages, o];
41
+ if (!((o.tool_calls?.length ?? 0) > 0))
42
42
  return await n({ text: "LLM determined no filter changes needed" }, e), {
43
43
  ...t,
44
44
  dataExplorationMessages: i
45
45
  // Don't overwrite outputMessage if query already set it
46
46
  };
47
- const m = i, p = r.content.toString();
48
- return await $(r, e), { ...t, dataExplorationMessages: m, outputMessage: p };
47
+ const m = i, g = o.content.toString();
48
+ return await b(o, e), { ...t, dataExplorationMessages: m, outputMessage: g };
49
49
  }, H = async (t, e) => {
50
50
  await n({ text: "Requesting LLM for layer query results" }, e);
51
51
  const d = await T("data_explore_query_prompt");
52
52
  if (!e?.configurable)
53
53
  throw new Error("config.configurable is required for layer query tools");
54
- const { userTimezone: l, userTimezoneOffset: s } = R(), r = t.agentExecutionContext.sharedState.lastNavigatedFeatures, i = r && typeof r == "object" && "value" in r ? r.value : r;
54
+ const { userTimezone: l, userTimezoneOffset: s } = R(), r = t.agentExecutionContext.sharedState, o = r.lastNavigatedFeatures?.value, i = r.lastResolvedLocation?.value;
55
55
  let c = "none";
56
- if (i != null)
56
+ if (o != null)
57
57
  try {
58
- c = JSON.stringify(i);
58
+ c = JSON.stringify(o);
59
59
  } catch {
60
60
  c = "none";
61
61
  }
62
- const m = {
62
+ let m = "none";
63
+ if (i != null)
64
+ try {
65
+ m = JSON.stringify({
66
+ address: i.address,
67
+ location: i.location
68
+ });
69
+ } catch {
70
+ m = "none";
71
+ }
72
+ const g = {
63
73
  layerFieldInfo: t.layerFieldInfo,
64
74
  userTimezone: l,
65
75
  userTimezoneOffset: s,
66
76
  assignedTask: t.agentExecutionContext.assignedTask,
67
77
  userRequest: t.agentExecutionContext.userRequest,
68
78
  priorSteps: t.agentExecutionContext.priorSteps,
69
- lastNavigatedFeatures: c
70
- }, p = await _({
79
+ lastNavigatedFeatures: c,
80
+ lastResolvedLocation: m
81
+ }, y = await $({
71
82
  promptText: d,
72
83
  modelTier: "advanced",
73
84
  config: e,
74
85
  messages: t.dataExplorationMessages,
75
- inputVariables: m,
86
+ inputVariables: g,
76
87
  tools: V
77
- }), f = (p.tool_calls?.length ?? 0) > 0, g = p.content.toString();
78
- return await $(p, e), {
88
+ }), h = (y.tool_calls?.length ?? 0) > 0, p = y.content.toString();
89
+ return await b(y, e), {
79
90
  ...t,
80
- dataExplorationMessages: [...t.dataExplorationMessages, p],
91
+ dataExplorationMessages: [...t.dataExplorationMessages, y],
81
92
  // Only emit output here when no tools are being called.
82
93
  // For tool-calling flows, downstream summarizer nodes provide the final user-facing message.
83
- ...f ? {} : { outputMessage: g },
94
+ ...h ? {} : { outputMessage: p },
84
95
  status: "success",
85
- summary: g && !f ? N(g) : "Query planning completed."
96
+ summary: p && !h ? N(p) : "Query planning completed."
86
97
  };
87
98
  }, J = async (t, e) => {
88
99
  try {
@@ -98,15 +109,15 @@ const W = async (t, e) => (await n({ text: "Exiting Data Exploration agent" }, e
98
109
  config: e,
99
110
  messages: t.dataExplorationMessages,
100
111
  inputVariables: l
101
- }), o = typeof s == "string" ? s : s.content, r = new j(o);
102
- await n({ text: `Received response from LLM: ${o}` }, e);
103
- const i = o;
112
+ }), r = typeof s == "string" ? s : s.content, o = new O(r);
113
+ await n({ text: `Received response from LLM: ${r}` }, e);
114
+ const i = r;
104
115
  return {
105
116
  ...t,
106
117
  outputMessage: i,
107
118
  status: "success",
108
119
  summary: i ? N(i) : "Summary generated.",
109
- dataExplorationMessages: [...t.dataExplorationMessages, r]
120
+ dataExplorationMessages: [...t.dataExplorationMessages, o]
110
121
  };
111
122
  } catch (a) {
112
123
  throw await n({ text: "Error during filter LLM request" }, e), new Error(`Error during filter LLM request: ${a instanceof Error ? a.message : String(a)}`);
@@ -114,11 +125,11 @@ const W = async (t, e) => (await n({ text: "Exiting Data Exploration agent" }, e
114
125
  };
115
126
  async function K(t, e) {
116
127
  if ((t.queryResponse ?? []).some((s) => {
117
- const o = s.details;
118
- return typeof o == "object" && o !== null && "error" in o;
128
+ const r = s.details;
129
+ return typeof r == "object" && r !== null && "error" in r;
119
130
  }))
120
131
  return await n({ text: "Skipping layer filter tool because query response contains an error." }, e), { ...t };
121
- const l = await new O(C, { handleToolErrors: !1 }).invoke(
132
+ const l = await new j(C, { handleToolErrors: !1 }).invoke(
122
133
  {
123
134
  messages: t.dataExplorationMessages
124
135
  },
@@ -134,14 +145,14 @@ const X = 10, Y = ["string", "small-integer", "integer"], Z = async (t, e, { inc
134
145
  try {
135
146
  if (e.type !== "geometry" && e.type !== "oid" && e.type !== "global-id") {
136
147
  a && (l = await G({ layer: t, field: e.name }));
137
- const o = e.domain?.type === "coded-value" ? e.domain : null;
138
- d && (Y.includes(e.type) || o) && (s = (await U({ layer: t, field: e.name })).uniqueValueInfos.sort((r, i) => i.count - r.count).slice(0, X), o && (s = s.map((r) => ({
139
- ...r,
140
- value: o.getName(r.value) ?? r.value
148
+ const r = e.domain?.type === "coded-value" ? e.domain : null;
149
+ d && (Y.includes(e.type) || r) && (s = (await U({ layer: t, field: e.name })).uniqueValueInfos.sort((o, i) => i.count - o.count).slice(0, X), r && (s = s.map((o) => ({
150
+ ...o,
151
+ value: r.getName(o.value) ?? o.value
141
152
  }))));
142
153
  }
143
- } catch (o) {
144
- console.error(`Error fetching statistics for field ${e.name}:`, o);
154
+ } catch (r) {
155
+ console.error(`Error fetching statistics for field ${e.name}:`, r);
145
156
  }
146
157
  return {
147
158
  summaryStatistics: l,
@@ -152,36 +163,36 @@ function ee(t, e) {
152
163
  return ["string", "small-integer", "integer"].includes(t) || e === "coded-value";
153
164
  }
154
165
  async function te(t, e, a, d = !0) {
155
- const l = [], s = [], o = [];
156
- for (const r of t) {
157
- let i = function(y) {
158
- const u = e.get(y)?.layerItem;
166
+ const l = [], s = [], r = [];
167
+ for (const o of t) {
168
+ let i = function(p) {
169
+ const u = e.get(p)?.layerItem;
159
170
  return u ? [
160
171
  u.name && `Name: ${u.name}`,
161
172
  u.title && `Title: ${u.title}`,
162
173
  u.description && `Description: ${u.description}`
163
- ].filter(Boolean).join(" | ") : y;
174
+ ].filter(Boolean).join(" | ") : p;
164
175
  };
165
- const { layerId: c, results: m } = r, p = a.map?.allLayers.find((y) => y.id === c), f = e.get(c)?.fieldRegistry;
166
- if (!f)
176
+ const { layerId: c, results: m } = o, g = a.map?.allLayers.find((p) => p.id === c), y = e.get(c)?.fieldRegistry;
177
+ if (!y)
167
178
  continue;
168
- let g = l.find((y) => y.layerId === c);
169
- g || (g = {
179
+ let h = l.find((p) => p.layerId === c);
180
+ h || (h = {
170
181
  layerId: c,
171
182
  layerSummary: i(c),
172
183
  fieldInfos: []
173
- }, l.push(g));
174
- for (const y of m) {
175
- const u = f.get(y.name);
184
+ }, l.push(h));
185
+ for (const p of m) {
186
+ const u = y.get(p.name);
176
187
  if (!u)
177
188
  continue;
178
189
  const x = u.statistics, E = d && !x?.summaryStatistics, w = ee(u.type, u.domain?.type) && !x?.uniqueValues, q = E || w;
179
- if (o.push({
190
+ if (r.push({
180
191
  layerId: c,
181
192
  fieldName: u.name,
182
193
  didFetchStatistics: q
183
194
  }), q) {
184
- const A = Z(p, u, {
195
+ const A = Z(g, u, {
185
196
  includeSummaryStatistics: E,
186
197
  includeUniqueValues: w
187
198
  }).then((F) => {
@@ -189,31 +200,31 @@ async function te(t, e, a, d = !0) {
189
200
  summaryStatistics: x?.summaryStatistics ?? null,
190
201
  uniqueValues: x?.uniqueValues ?? null
191
202
  };
192
- E && (S.summaryStatistics = F.summaryStatistics), w && (S.uniqueValues = F.uniqueValues), f.set(u.name, { ...u, statistics: S }), u.statistics = S;
203
+ E && (S.summaryStatistics = F.summaryStatistics), w && (S.uniqueValues = F.uniqueValues), y.set(u.name, { ...u, statistics: S }), u.statistics = S;
193
204
  });
194
205
  s.push(A);
195
206
  }
196
- g.fieldInfos.push(u);
207
+ h.fieldInfos.push(u);
197
208
  }
198
209
  }
199
210
  return await Promise.all(s), {
200
211
  layerFieldInfo: l,
201
212
  didFetchStatistics: s.length > 0,
202
- fieldStatisticsFetchStatus: o
213
+ fieldStatisticsFetchStatus: r
203
214
  };
204
215
  }
205
- const M = /\b(average|avg|mean|median|max(?:imum)?|min(?:imum)?|sum|total|count|std(?:dev|\s*deviation)|variance|null\s*count|missing\s*values?|range)\b/iu;
216
+ const L = /\b(average|avg|mean|median|max(?:imum)?|min(?:imum)?|sum|total|count|std(?:dev|\s*deviation)|variance|null\s*count|missing\s*values?|range)\b/iu;
206
217
  function ae(t, e) {
207
- return M.test(t) || M.test(e);
218
+ return L.test(t) || L.test(e);
208
219
  }
209
220
  const se = async (t, e) => {
210
221
  try {
211
222
  await n({ text: "Preparing field information for vector search results" }, e);
212
- const a = h(e, "layersAndFieldsRegistry"), { mapView: d } = D(e), { assignedTask: l, userRequest: s } = t.agentExecutionContext, o = ae(l, s), { layerFieldInfo: r, didFetchStatistics: i, fieldStatisticsFetchStatus: c } = await te(
223
+ const a = f(e, "layersAndFieldsRegistry"), { mapView: d } = D(e), { assignedTask: l, userRequest: s } = t.agentExecutionContext, r = ae(l, s), { layerFieldInfo: o, didFetchStatistics: i, fieldStatisticsFetchStatus: c } = await te(
213
224
  t.vectorSearchFieldResults,
214
225
  a,
215
226
  d,
216
- o
227
+ r
217
228
  );
218
229
  i ? await n({ text: "Statistics fetched" }, e) : await n({ text: "Statistics skipped" }, e);
219
230
  for (const m of c)
@@ -223,29 +234,29 @@ const se = async (t, e) => {
223
234
  },
224
235
  e
225
236
  );
226
- return await n({ text: "Field information prepared" }, e), { ...t, layerFieldInfo: r };
237
+ return await n({ text: "Field information prepared" }, e), { ...t, layerFieldInfo: o };
227
238
  } catch (a) {
228
239
  throw await n({ text: "Error during fetching statistics" }, e), new Error(`Error during fetching statistics: ${a instanceof Error ? a.message : String(a)}`);
229
240
  }
230
- }, L = 0.7, re = 10, oe = async (t, e) => {
241
+ }, M = 0.7, re = 10, oe = async (t, e) => {
231
242
  try {
232
243
  await n({ text: "Similarity search to find fields" }, e);
233
- const a = h(e, "fieldSearch"), d = h(e, "layersAndFieldsRegistry"), l = h(e, "embeddingCache"), s = await a.searchFields({
244
+ const a = f(e, "fieldSearch"), d = f(e, "layersAndFieldsRegistry"), l = f(e, "embeddingCache"), s = await a.searchFields({
234
245
  text: t.agentExecutionContext.assignedTask,
235
246
  layerIds: t.vectorSearchLayerIds,
236
- minScore: L,
247
+ minScore: M,
237
248
  topResults: re,
238
249
  embeddingCache: l
239
- }), o = s.map(({ layerId: i, results: c }) => {
240
- const m = c.map((p) => ` - ${p.name} (${p.score.toFixed(2)})`).join(`
250
+ }), r = s.map(({ layerId: i, results: c }) => {
251
+ const m = c.map((g) => ` - ${g.name} (${g.score.toFixed(2)})`).join(`
241
252
  `);
242
253
  return `${d.get(i)?.layerItem.name ?? i}:
243
254
  ${m}`;
244
255
  }).join(`
245
256
  `);
246
- let r;
247
- return s.length > 0 ? r = `Vector search completed. Matching layers and fields with scores:
248
- ${o}` : r = `No vector search results found for score over ${L}.`, await n({ text: r }, e), {
257
+ let o;
258
+ return s.length > 0 ? o = `Vector search completed. Matching layers and fields with scores:
259
+ ${r}` : o = `No vector search results found for score over ${M}.`, await n({ text: o }, e), {
249
260
  ...t,
250
261
  vectorSearchFieldResults: s
251
262
  };
@@ -261,17 +272,17 @@ ${o}` : r = `No vector search results found for score over ${L}.`, await n({ tex
261
272
  { text: `Similarity search to find layers: ${t.agentExecutionContext.assignedTask}` },
262
273
  e
263
274
  );
264
- const a = h(e, "layerSearch"), d = h(e, "layersAndFieldsRegistry"), l = h(e, "embeddingCache"), s = await a.searchLayers({
275
+ const a = f(e, "layerSearch"), d = f(e, "layersAndFieldsRegistry"), l = f(e, "embeddingCache"), s = await a.searchLayers({
265
276
  text: t.agentExecutionContext.assignedTask,
266
277
  minScore: ie,
267
278
  embeddingCache: l
268
- }), o = s.map((c) => c.id), r = s.map(({ id: c, score: m }) => `${d.get(c)?.layerItem.name ?? c} (${m.toFixed(2)})`).join(`
279
+ }), r = s.map((c) => c.id), o = s.map(({ id: c, score: m }) => `${d.get(c)?.layerItem.name ?? c} (${m.toFixed(2)})`).join(`
269
280
  `);
270
281
  let i;
271
- return o.length > 0 ? i = `Vector search completed. Matching layers with scores:
272
- ${r}` : i = "Vector search completed. No matching layers found.", await n({ text: i }, e), {
282
+ return r.length > 0 ? i = `Vector search completed. Matching layers with scores:
283
+ ${o}` : i = "Vector search completed. No matching layers found.", await n({ text: i }, e), {
273
284
  ...t,
274
- vectorSearchLayerIds: o
285
+ vectorSearchLayerIds: r
275
286
  };
276
287
  } catch (a) {
277
288
  throw await n(
@@ -282,7 +293,7 @@ ${r}` : i = "Vector search completed. No matching layers found.", await n({ text
282
293
  }, le = (t, e) => z(["layerSearch", "fieldSearch", "layersAndFieldsRegistry"], "Data Exploration Agent")(
283
294
  t,
284
295
  e
285
- ), ce = () => new I(b).addNode("requireDataExplorationServices", le).addNode("vectorSearchLayers", ne).addNode("vectorSearchFields", oe).addNode("fieldStatistics", se).addNode("queryAgent", H).addNode("queryTools", P).addNode("summarizeQueryResponseLLM", J).addNode("filterAgent", B).addNode("filterTools", K).addNode("earlyExit", W).addEdge(k, "requireDataExplorationServices").addEdge("requireDataExplorationServices", "vectorSearchLayers").addConditionalEdges(
296
+ ), ce = () => new I(_).addNode("requireDataExplorationServices", le).addNode("vectorSearchLayers", ne).addNode("vectorSearchFields", oe).addNode("fieldStatistics", se).addNode("queryAgent", H).addNode("queryTools", P).addNode("summarizeQueryResponseLLM", J).addNode("filterAgent", B).addNode("filterTools", K).addNode("earlyExit", W).addEdge(k, "requireDataExplorationServices").addEdge("requireDataExplorationServices", "vectorSearchLayers").addConditionalEdges(
286
297
  "vectorSearchLayers",
287
298
  (e) => e.vectorSearchLayerIds.length ? "vectorSearchFields" : "earlyExit"
288
299
  ).addConditionalEdges(
@@ -304,7 +315,7 @@ ${r}` : i = "Vector search completed. No matching layers found.", await n({ text
304
315
  name: "Data Exploration Agent",
305
316
  description: de,
306
317
  createGraph: ce,
307
- workspace: b
318
+ workspace: _
308
319
  };
309
320
  export {
310
321
  Ce as D
@@ -39,10 +39,13 @@ Prior steps:
39
39
  Last navigated features from shared state (if available):
40
40
  {lastNavigatedFeatures}
41
41
 
42
+ Last resolved location from shared state (if available):
43
+ {lastResolvedLocation}
44
+
42
45
  Use the assigned task as the primary instruction for the current query.
43
46
  Use the latest user request as supporting context when needed.
44
47
  Use prior steps only when the assigned task or user request clearly depends on earlier results.
45
- Use lastNavigatedFeatures as authoritative context for map-navigation references when present.
48
+ Use shared-state context (\`lastResolvedLocation\`, \`lastNavigatedFeatures\`) for referential follow-ups when relevant.
46
49
  Use chat history only when necessary to understand conversational references, and do not override the assigned task.
47
50
 
48
51
  ### Anchor selection rule (strict, single source of truth)
@@ -50,8 +53,9 @@ Use chat history only when necessary to understand conversational references, an
50
53
  When the request is referential (for example: "this", "it", "that", "those", "them", "of those", "the same one(s)"), choose exactly one anchor using this priority order:
51
54
 
52
55
  1. Explicit entity named in the current request (if present)
53
- 2. \`lastNavigatedFeatures\` (if present)
54
- 3. The immediately previous successful relevant step from \`priorSteps\`
56
+ 2. \`lastResolvedLocation\` (if present and the request refers to a place/location)
57
+ 3. \`lastNavigatedFeatures\` (if present)
58
+ 4. The immediately previous successful relevant step from \`priorSteps\`
55
59
 
56
60
  After selecting the anchor, keep that anchor for this query and do not switch to an older entity.
57
61
  If \`lastNavigatedFeatures\` is used as the anchor, reuse its \`layerId\` and \`where\` for query scope unless the current request explicitly overrides it.
@@ -78,7 +82,8 @@ Start with a fresh WHERE clause for each new question. Do not inherit filters fr
78
82
 
79
83
  This is an exception to the "fresh WHERE clause" rule above.
80
84
 
81
- - If the anchored context indicates \`useCurrentExtent: true\`, use \`useCurrentExtent: true\` with \`where: "1=1"\`.
85
+ - If the anchored context is \`lastResolvedLocation\` with a point, prefer \`geometryFilter.point\` and use \`where: "1=1"\` unless the user asked for additional attribute filters.
86
+ - Only use \`useCurrentExtent: true\` when the user explicitly asks about the current view/map extent (for example: "in my view", "on my map", "visible now").
82
87
  - If the anchored context includes specific feature IDs/objectIds, scope to those IDs.
83
88
  - Otherwise, use the anchored \`layerId\` + \`where\` combination.
84
89