@arcgis/portal-components 5.2.0-next.43 → 5.2.0-next.45

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,21 +1,21 @@
1
1
  /* COPYRIGHT Esri - https://js.arcgis.com/5.2/LICENSE.txt */
2
- import { c as ut } from "../../chunks/runtime.js";
3
- import { LitElement as lt, createEvent as ct } from "@arcgis/lumina";
4
- import { css as mt, render as dt, html as G } from "lit";
2
+ import { c as ct } from "../../chunks/runtime.js";
3
+ import { LitElement as dt, createEvent as mt } from "@arcgis/lumina";
4
+ import { css as pt, render as gt, html as G } from "lit";
5
5
  import { createRef as M, ref as A } from "lit/directives/ref.js";
6
- import { u as pt } from "../../chunks/useT9n.js";
7
- import { a as T, t as gt } from "../../chunks/functionalities.js";
8
- import { NodeInterrupt as K, Annotation as f, StateGraph as C, START as P, END as h } from "@langchain/langgraph/web";
6
+ import { u as ht } from "../../chunks/useT9n.js";
7
+ import { a as T, t as ft, b as yt } from "../../chunks/functionalities.js";
8
+ import { NodeInterrupt as J, Annotation as h, StateGraph as C, START as P, END as f } from "@langchain/langgraph/web";
9
9
  import { sendTraceMessage as g, invokeStructuredPrompt as b, sendUXSuggestion as E, createAgentRuntimeStateWithSharedState as N, createChatModel as D } from "@arcgis/ai-components/utils/index.js";
10
- import o from "zod";
11
- import { a as ft, c as ht, q as yt, s as wt, g as bt } from "../../chunks/item2.js";
12
- import It from "@arcgis/core/identity/IdentityManager.js";
13
- import j from "@arcgis/core/request.js";
10
+ import r from "zod";
11
+ import { a as wt, c as bt, q as It, s as xt, g as vt } from "../../chunks/item2.js";
12
+ import St from "@arcgis/core/identity/IdentityManager.js";
13
+ import O from "@arcgis/core/request.js";
14
14
  import { ChatPromptTemplate as z } from "@langchain/core/prompts";
15
15
  import { createAgent as U } from "langchain";
16
16
  import { tool as W } from "@langchain/core/tools";
17
- import { Annotation as xt } from "@langchain/langgraph";
18
- import { c as vt, d as St, i as Gt, b as Mt, g as At } from "../../chunks/groups.js";
17
+ import { Annotation as Gt } from "@langchain/langgraph";
18
+ import { c as Mt, d as At, i as Tt, b as Ct, g as Pt } from "../../chunks/groups.js";
19
19
  const Y = (e) => {
20
20
  const { portal: t, user: s } = e ?? {};
21
21
  return !!e && !!t && !!s;
@@ -24,9 +24,9 @@ function I(e) {
24
24
  if (!Y(e))
25
25
  throw new Error("Invalid context: PortalAssistantContext with portal and user is required.");
26
26
  }
27
- const Tt = (e) => e.map((t) => `"${t}"`).join(", "), Ct = o.object({
28
- successMessage: o.string().default("")
29
- }), O = "portal-group-creation", V = "approveAddMembers", Pt = async (e, t) => {
27
+ const Nt = (e) => e.map((t) => `"${t}"`).join(", "), qt = r.object({
28
+ successMessage: r.string().default("")
29
+ }), j = "portal-group-creation", V = "approveAddMembers", $t = async (e, t) => {
30
30
  if (e.intentParams.intent !== "addMembers")
31
31
  return {
32
32
  status: "success",
@@ -38,7 +38,7 @@ const Tt = (e) => e.map((t) => `"${t}"`).join(", "), Ct = o.object({
38
38
  status: "success",
39
39
  outputMessage: "Create a group first, then add members using @mention usernames."
40
40
  };
41
- const a = e.intentParams.memberInfo.memberIdentifiers.map((d) => d.trim()).filter(Boolean);
41
+ const a = e.intentParams.memberInfo.memberIdentifiers.map((m) => m.trim()).filter(Boolean);
42
42
  if (!a.length)
43
43
  return {
44
44
  status: "success",
@@ -46,13 +46,13 @@ const Tt = (e) => e.map((t) => `"${t}"`).join(", "), Ct = o.object({
46
46
  };
47
47
  const i = `The following member(s) will be added to the newly created group:
48
48
 
49
- ${a.map((d) => `- **@${d}**`).join(`
49
+ ${a.map((m) => `- **@${m}**`).join(`
50
50
  `)}
51
51
 
52
52
  Do you want to continue?`, { hitlResponse: l } = t?.configurable ?? {};
53
- if (l?.agentId !== O || l.id !== V) {
54
- const d = {
55
- agentId: O,
53
+ if (l?.agentId !== j || l.id !== V) {
54
+ const m = {
55
+ agentId: j,
56
56
  id: V,
57
57
  kind: "booleanChoice",
58
58
  message: i,
@@ -62,7 +62,7 @@ Do you want to continue?`, { hitlResponse: l } = t?.configurable ?? {};
62
62
  members: [...a]
63
63
  }
64
64
  };
65
- throw new K(d);
65
+ throw new J(m);
66
66
  }
67
67
  if (l.payload !== !0)
68
68
  return {
@@ -70,25 +70,25 @@ Do you want to continue?`, { hitlResponse: l } = t?.configurable ?? {};
70
70
  outputMessage: "Okay, I cancelled adding members to the group."
71
71
  };
72
72
  await g(
73
- { text: `Adding members ${Tt(a)}...`, agentName: "group-creation" },
73
+ { text: `Adding members ${Nt(a)}...`, agentName: "group-creation" },
74
74
  t
75
75
  );
76
76
  const u = t?.configurable?.context;
77
77
  I(u);
78
- const { result: c, error: n } = await ft(u.portal, s, a);
78
+ const { result: c, error: n } = await wt(u.portal, s, a);
79
79
  if (n || !c)
80
80
  return {
81
81
  status: "success",
82
82
  outputMessage: "I could not add members to that group. Please confirm group access and user accounts, then try again."
83
83
  };
84
- const { addedUsernames: m, notAddedUsers: p } = c;
84
+ const { addedUsernames: d, notAddedUsers: p } = c;
85
85
  try {
86
86
  const y = (await b({
87
- promptText: Nt,
88
- schema: Ct,
87
+ promptText: kt,
88
+ schema: qt,
89
89
  modelTier: "fast",
90
90
  inputVariables: {
91
- addedMembers: m.join(", "),
91
+ addedMembers: d.join(", "),
92
92
  notAddedMembers: JSON.stringify(
93
93
  p.map((v) => ({ username: v.username, reason: v.error.message }))
94
94
  )
@@ -96,11 +96,11 @@ Do you want to continue?`, { hitlResponse: l } = t?.configurable ?? {};
96
96
  })).successMessage;
97
97
  if (y)
98
98
  return { status: "success", outputMessage: y };
99
- } catch (d) {
100
- console.error("Error generating add-members success message:", d);
99
+ } catch (m) {
100
+ console.error("Error generating add-members success message:", m);
101
101
  }
102
102
  return {};
103
- }, Nt = `
103
+ }, kt = `
104
104
  Write a concise, friendly success message for adding members to a group.
105
105
 
106
106
  Rules:
@@ -115,11 +115,11 @@ Added members:
115
115
 
116
116
  Not added members:
117
117
  {notAddedMembers}
118
- `, B = "portal-group-creation", Q = "approveCreateGroup", qt = o.object({
119
- successMessage: o.string().default("")
120
- }), $t = o.object({
121
- failureMessage: o.string().default("")
122
- }), kt = async (e, t) => {
118
+ `, B = "portal-group-creation", Q = "approveCreateGroup", Et = r.object({
119
+ successMessage: r.string().default("")
120
+ }), Dt = r.object({
121
+ failureMessage: r.string().default("")
122
+ }), zt = async (e, t) => {
123
123
  if (e.intentParams.intent !== "create")
124
124
  return {
125
125
  status: "success",
@@ -131,8 +131,8 @@ Not added members:
131
131
  status: "success",
132
132
  outputMessage: "What title would you like for the new group?"
133
133
  };
134
- const a = `A group with the title **${s}** will be created. Do you want to continue?`, { hitlResponse: r } = t?.configurable;
135
- if (r?.agentId !== B || r.id !== Q) {
134
+ const a = `A group with the title **${s}** will be created. Do you want to continue?`, { hitlResponse: o } = t?.configurable;
135
+ if (o?.agentId !== B || o.id !== Q) {
136
136
  const n = {
137
137
  agentId: B,
138
138
  id: Q,
@@ -144,9 +144,9 @@ Not added members:
144
144
  access: "private"
145
145
  }
146
146
  };
147
- throw new K(n);
147
+ throw new J(n);
148
148
  }
149
- if (r.payload !== !0)
149
+ if (o.payload !== !0)
150
150
  return {
151
151
  status: "success",
152
152
  outputMessage: `Okay, I cancelled creating **${s}**.`
@@ -154,7 +154,7 @@ Not added members:
154
154
  await g({ text: `Creating group "${s}"...`, agentName: "group-creation" }, t);
155
155
  const i = t?.configurable?.context;
156
156
  I(i);
157
- const { result: l, error: u } = await ht(i.portal, {
157
+ const { result: l, error: u } = await bt(i.portal, {
158
158
  title: s,
159
159
  access: "private"
160
160
  });
@@ -162,8 +162,8 @@ Not added members:
162
162
  const n = u?.message?.trim() || "No additional details were provided.";
163
163
  try {
164
164
  const p = (await b({
165
- promptText: Dt,
166
- schema: $t,
165
+ promptText: Rt,
166
+ schema: Dt,
167
167
  modelTier: "fast",
168
168
  inputVariables: {
169
169
  groupTitle: s,
@@ -175,8 +175,8 @@ Not added members:
175
175
  status: "success",
176
176
  outputMessage: p
177
177
  };
178
- } catch (m) {
179
- console.error("Error generating create-group failure message:", m);
178
+ } catch (d) {
179
+ console.error("Error generating create-group failure message:", d);
180
180
  }
181
181
  return {
182
182
  status: "success",
@@ -185,18 +185,18 @@ Not added members:
185
185
  }
186
186
  const c = l.id;
187
187
  try {
188
- const m = (await b({
189
- promptText: Et,
190
- schema: qt,
188
+ const d = (await b({
189
+ promptText: Ut,
190
+ schema: Et,
191
191
  modelTier: "fast",
192
192
  inputVariables: {
193
193
  groupTitle: s
194
194
  }
195
195
  })).successMessage.trim();
196
- if (m)
196
+ if (d)
197
197
  return {
198
198
  status: "success",
199
- outputMessage: m,
199
+ outputMessage: d,
200
200
  sharedStatePatch: { createdGroupId: { value: c } },
201
201
  createdGroupId: c
202
202
  };
@@ -204,7 +204,7 @@ Not added members:
204
204
  console.error("Error generating create-group success message:", n);
205
205
  }
206
206
  return {};
207
- }, Et = `
207
+ }, Ut = `
208
208
  Write a concise, friendly success message after creating a portal group.
209
209
 
210
210
  Rules:
@@ -215,7 +215,7 @@ Rules:
215
215
 
216
216
  Group title:
217
217
  {groupTitle}
218
- `, Dt = `
218
+ `, Rt = `
219
219
  Write a concise, friendly failure message after an attempt to create a portal group.
220
220
 
221
221
  Rules:
@@ -240,29 +240,29 @@ Failure reason:
240
240
  return a;
241
241
  if (Array.isArray(a))
242
242
  return a.map(
243
- (r) => typeof r == "string" ? r : "text" in r && typeof r.text == "string" ? r.text : ""
243
+ (o) => typeof o == "string" ? o : "text" in o && typeof o.text == "string" ? o.text : ""
244
244
  ).join(" ").trim();
245
245
  }
246
246
  return "";
247
- }, zt = o.object({
248
- intent: o.enum(["clarify", "create", "addMembers"]).default("clarify"),
249
- title: o.string().default(""),
250
- memberIdentifiers: o.array(o.string()).default([]),
251
- clarifyMessage: o.string().default("")
252
- }), Ut = async (e, t) => {
247
+ }, Ft = r.object({
248
+ intent: r.enum(["clarify", "create", "addMembers"]).default("clarify"),
249
+ title: r.string().default(""),
250
+ memberIdentifiers: r.array(r.string()).default([]),
251
+ clarifyMessage: r.string().default("")
252
+ }), Ot = async (e, t) => {
253
253
  await g({ text: "Thinking about groups...", agentName: "group-creation" }, t);
254
254
  const s = x(e.agentExecutionContext.messages).trim(), a = await b({
255
- promptText: Rt,
256
- schema: zt,
255
+ promptText: jt,
256
+ schema: Ft,
257
257
  modelTier: "default",
258
258
  inputVariables: { userMessage: s }
259
- }), r = a.title.trim(), i = a.memberIdentifiers.filter(Boolean), l = a.clarifyMessage.trim(), u = a.intent === "create" && !!r, c = a.intent === "addMembers" && i.length > 0;
259
+ }), o = a.title.trim(), i = a.memberIdentifiers.filter(Boolean), l = a.clarifyMessage.trim(), u = a.intent === "create" && !!o, c = a.intent === "addMembers" && i.length > 0;
260
260
  return {
261
- intentParams: u ? { intent: "create", title: r } : c ? { intent: "addMembers", memberInfo: { memberIdentifiers: i } } : { intent: "clarify" },
261
+ intentParams: u ? { intent: "create", title: o } : c ? { intent: "addMembers", memberInfo: { memberIdentifiers: i } } : { intent: "clarify" },
262
262
  status: "success",
263
263
  outputMessage: !u && !c ? l : ""
264
264
  };
265
- }, Rt = `
265
+ }, jt = `
266
266
  You classify whether a user is asking to create a new ArcGIS Portal group or add members to an existing group.
267
267
 
268
268
  Rules:
@@ -288,90 +288,93 @@ Examples:
288
288
 
289
289
  User message:
290
290
  {userMessage}
291
- `, Ft = o.discriminatedUnion("destinationType", [
292
- o.object({
293
- destinationType: o.literal("portal-content")
291
+ `, Vt = r.discriminatedUnion("destinationType", [
292
+ r.object({
293
+ destinationType: r.literal("portal-content")
294
+ }),
295
+ r.object({
296
+ destinationType: r.literal("portal-groups")
294
297
  }),
295
- o.object({
296
- destinationType: o.literal("portal-groups")
298
+ r.object({
299
+ destinationType: r.literal("portal-settings-security")
297
300
  }),
298
- o.object({
299
- destinationType: o.literal("portal-item"),
300
- itemId: o.string().trim().min(1)
301
+ r.object({
302
+ destinationType: r.literal("portal-item"),
303
+ itemId: r.string().trim().min(1)
301
304
  }),
302
- o.object({
303
- destinationType: o.literal("portal-group"),
304
- groupId: o.string().trim().min(1)
305
+ r.object({
306
+ destinationType: r.literal("portal-group"),
307
+ groupId: r.string().trim().min(1)
305
308
  })
306
309
  ]), _ = "portal-navigation", R = async (e, t) => {
307
310
  const s = t?.configurable?.context;
308
311
  !Y(s) || !s.navigationTargetMap?.[e.destinationType] || await E({ type: _, data: { ...e } }, t);
309
- }, jt = async (e, t) => {
312
+ }, Bt = async (e, t) => {
310
313
  const s = e.createdGroupId ?? e.agentExecutionContext.sharedState.createdGroupId?.value;
311
314
  return s ? (await g({ text: "Preparing navigation...", agentName: "group-creation" }, t), await R({ destinationType: "portal-group", groupId: s }, t), {}) : {};
312
- }, L = (e, t) => t ?? e, H = f.Root({
315
+ }, L = (e, t) => t ?? e, H = h.Root({
313
316
  ...N(),
314
317
  // * Shared state between nodes (but not persisted to the agent execution context)
315
318
  /** Parameters related to the user's intent for group creation actions */
316
- intentParams: f({ reducer: L, default: () => ({ intent: "clarify" }) }),
319
+ intentParams: h({ reducer: L, default: () => ({ intent: "clarify" }) }),
317
320
  /** The ID of the group that was created
318
321
  * even though we already have this in the shared state
319
322
  * we still need it here to also share between nodes
320
323
  */
321
- createdGroupId: f({ reducer: L, default: () => "" })
322
- }), Ot = () => new C(H).addNode("detectGroupCreationIntent", Ut).addNode("createPortalGroup", kt).addNode("addMembersToPortalGroup", Pt).addNode("suggestCreatedGroupNavigation", jt).addEdge(P, "detectGroupCreationIntent").addConditionalEdges("detectGroupCreationIntent", (t) => {
324
+ createdGroupId: h({ reducer: L, default: () => "" })
325
+ }), Qt = () => new C(H).addNode("detectGroupCreationIntent", Ot).addNode("createPortalGroup", zt).addNode("addMembersToPortalGroup", $t).addNode("suggestCreatedGroupNavigation", Bt).addEdge(P, "detectGroupCreationIntent").addConditionalEdges("detectGroupCreationIntent", (t) => {
323
326
  switch (t.intentParams.intent) {
324
327
  case "create":
325
328
  return "createPortalGroup";
326
329
  case "addMembers":
327
330
  return "addMembersToPortalGroup";
328
331
  default:
329
- return h;
332
+ return f;
330
333
  }
331
- }).addEdge("createPortalGroup", "suggestCreatedGroupNavigation").addEdge("addMembersToPortalGroup", "suggestCreatedGroupNavigation").addEdge("suggestCreatedGroupNavigation", h), Vt = String.raw`- **portal-group-creation** - Portal group creation assistant:
334
+ }).addEdge("createPortalGroup", "suggestCreatedGroupNavigation").addEdge("addMembersToPortalGroup", "suggestCreatedGroupNavigation").addEdge("suggestCreatedGroupNavigation", f), Lt = String.raw`- **portal-group-creation** - Portal group creation assistant:
332
335
  - creates a new ArcGIS Portal group for the signed-in user
333
336
  - adds users to the newly created group using @mention usernames
334
- `, Bt = {
337
+ `, Kt = {
335
338
  id: "portal-group-creation",
336
339
  name: "Portal Group Creation",
337
- description: Vt,
338
- createGraph: Ot,
340
+ description: Lt,
341
+ createGraph: Qt,
339
342
  workspace: H
340
- }, X = "portalDocAssistantMemory", Qt = () => ({ conversationId: "" }), Lt = (e) => {
343
+ }, X = "portalDocAssistantMemory", Jt = () => ({ conversationId: "" }), Wt = (e) => {
341
344
  const t = e?.[X]?.value;
342
345
  if (!t || typeof t != "object")
343
- return Qt();
346
+ return Jt();
344
347
  const s = t;
345
348
  return {
346
349
  conversationId: typeof s.conversationId == "string" ? s.conversationId : ""
347
350
  };
348
- }, Jt = (e) => ({
351
+ }, Yt = (e) => ({
349
352
  [X]: { value: e }
350
353
  });
351
- async function Kt({
354
+ async function _t({
352
355
  portal: e,
353
356
  question: t,
354
357
  persona: s,
355
358
  previousConversationId: a,
356
- signal: r,
359
+ signal: o,
357
360
  skillId: i
358
361
  }) {
359
362
  i ??= "doc_ai_assistant";
360
- const u = await Wt({
363
+ const u = await Ht({
361
364
  portal: e,
362
365
  skillId: i,
363
366
  message: t,
364
367
  options: { context: {
365
368
  kind: "DocAIAssistantRequest",
366
369
  filters: { persona: { persona: s } }
367
- }, previousConversationId: a, signal: r }
370
+ }, previousConversationId: a, signal: o }
368
371
  });
369
372
  return {
370
- reply: Yt(u, i),
373
+ reply: Xt(u, i),
371
374
  conversationId: u[0]?.conversationId ?? ""
372
375
  };
373
376
  }
374
- async function Wt({
377
+ async function Ht({
375
378
  portal: e,
376
379
  skillId: t,
377
380
  message: s,
@@ -379,8 +382,8 @@ async function Wt({
379
382
  }) {
380
383
  const i = `${e.helperServices.aiAssistantServices.url}/skills/${t}/chat`, l = {
381
384
  "Content-Type": "application/json",
382
- token: It.findCredential(e.url)?.token ?? ""
383
- }, u = await j(i, {
385
+ token: St.findCredential(e.url)?.token ?? ""
386
+ }, u = await O(i, {
384
387
  method: "post",
385
388
  body: JSON.stringify({
386
389
  message: s,
@@ -394,13 +397,13 @@ async function Wt({
394
397
  throw new Error(`Doc assistant chat failed (${u.httpStatus})`, {
395
398
  cause: u.data
396
399
  });
397
- const c = u.data, n = [c], { conversationId: m, inquiryId: p } = c, d = async (y, v) => {
400
+ const c = u.data, n = [c], { conversationId: d, inquiryId: p } = c, m = async (y, v) => {
398
401
  if (!v)
399
402
  return;
400
- await gt(1e3);
401
- const w = await j(i, {
403
+ await ft(1e3);
404
+ const w = await O(i, {
402
405
  method: "post",
403
- body: JSON.stringify({ conversationId: m, inquiryId: p, ackSequenceNumber: y }),
406
+ body: JSON.stringify({ conversationId: d, inquiryId: p, ackSequenceNumber: y }),
404
407
  headers: l,
405
408
  signal: a.signal
406
409
  });
@@ -409,11 +412,11 @@ async function Wt({
409
412
  cause: w.data
410
413
  });
411
414
  const S = w.data;
412
- n.push(S), await d(S.sequenceNumber, S.hasMore);
415
+ n.push(S), await m(S.sequenceNumber, S.hasMore);
413
416
  };
414
- return c.hasMore && await d(c.sequenceNumber, c.hasMore), n;
417
+ return c.hasMore && await m(c.sequenceNumber, c.hasMore), n;
415
418
  }
416
- function Yt(e, t) {
419
+ function Xt(e, t) {
417
420
  switch (t) {
418
421
  case "doc_chat":
419
422
  return e.find((s) => s.message != null)?.message ?? "";
@@ -421,9 +424,9 @@ function Yt(e, t) {
421
424
  for (let s = e.length - 1; s >= 0; s -= 1) {
422
425
  const a = e[s];
423
426
  if (a.context?.kind === "DocAIAssistantContext") {
424
- const r = a.context.results?.[0]?.reply;
425
- if (r)
426
- return r;
427
+ const o = a.context.results?.[0]?.reply;
428
+ if (o)
429
+ return o;
427
430
  }
428
431
  }
429
432
  return "";
@@ -431,7 +434,7 @@ function Yt(e, t) {
431
434
  return T(t);
432
435
  }
433
436
  }
434
- const _t = async (e, t) => {
437
+ const Zt = async (e, t) => {
435
438
  await g({ text: "Asking documentation assistant...", agentName: "doc-assistant" }, t);
436
439
  const s = x(e.agentExecutionContext.messages).trim();
437
440
  if (!s)
@@ -441,18 +444,18 @@ const _t = async (e, t) => {
441
444
  };
442
445
  const a = t?.configurable?.context;
443
446
  I(a);
444
- const r = Lt(e.agentExecutionContext.sharedState), { reply: i, conversationId: l } = await Kt({
447
+ const o = Wt(e.agentExecutionContext.sharedState), { reply: i, conversationId: l } = await _t({
445
448
  portal: a.portal,
446
449
  question: s,
447
- previousConversationId: r.conversationId || void 0,
450
+ previousConversationId: o.conversationId || void 0,
448
451
  skillId: "doc_ai_assistant",
449
452
  persona: "developers"
450
453
  });
451
454
  return {
452
455
  status: "success",
453
456
  outputMessage: i.trim() || "I could not retrieve a response from the documentation assistant.",
454
- sharedStatePatch: Jt({
455
- conversationId: l || r.conversationId
457
+ sharedStatePatch: Yt({
458
+ conversationId: l || o.conversationId
456
459
  })
457
460
  };
458
461
  }, Z = W(
@@ -463,16 +466,16 @@ const _t = async (e, t) => {
463
466
  const a = t?.configurable?.context;
464
467
  I(a);
465
468
  try {
466
- return (await yt(a.portal, { query: `title:${s}`, num: 1 }))?.results[0]?.id || null;
467
- } catch (r) {
468
- return console.error("Error searching for portal group by title:", r), null;
469
+ return (await It(a.portal, { query: `title:${s}`, num: 1 }))?.results[0]?.id || null;
470
+ } catch (o) {
471
+ return console.error("Error searching for portal group by title:", o), null;
469
472
  }
470
473
  },
471
474
  {
472
475
  name: "resolvePortalGroupIdByTitle",
473
476
  description: "Resolves an ArcGIS Portal group title to the best-match group id. Use this when a user references a group by title instead of an explicit group id.",
474
- schema: o.object({
475
- groupTitle: o.string().describe("The portal group title to resolve to a group id.")
477
+ schema: r.object({
478
+ groupTitle: r.string().describe("The portal group title to resolve to a group id.")
476
479
  })
477
480
  }
478
481
  ), tt = W(
@@ -482,42 +485,102 @@ const _t = async (e, t) => {
482
485
  return null;
483
486
  const a = t?.configurable?.context;
484
487
  I(a);
485
- const { result: r, error: i } = await wt(a.portal, s, { num: 1 });
486
- return i && console.error("Error searching for portal item by title:", i), r?.results[0]?.id || null;
488
+ const { result: o, error: i } = await xt(a.portal, s, { num: 1 });
489
+ return i && console.error("Error searching for portal item by title:", i), o?.results[0]?.id || null;
487
490
  },
488
491
  {
489
492
  name: "resolvePortalItemIdByTitle",
490
493
  description: 'Resolves an ArcGIS Portal item title to the best-match item id. Use this when a user references an item by title (including hash mentions like #title or #"title with spaces") instead of an explicit item id.',
491
- schema: o.object({
492
- itemTitle: o.string().describe("The portal item title to resolve to an item id.")
494
+ schema: r.object({
495
+ itemTitle: r.string().describe("The portal item title to resolve to an item id.")
493
496
  })
494
497
  }
495
- ), J = o.object({
496
- shouldSuggestNavigation: o.boolean().default(!1),
497
- destinationType: o.enum(["none", "portal-content", "portal-item", "portal-groups", "portal-group"]).default("none"),
498
- itemId: o.string().default(""),
499
- groupId: o.string().default("")
500
- }), Ht = async (e, t) => {
498
+ ), et = {
499
+ "portal-content": {
500
+ description: "The main content page of the portal.",
501
+ hints: ["My content", "Content"],
502
+ scope: "root"
503
+ },
504
+ "portal-group": {
505
+ description: "A specific group page in the portal.",
506
+ hints: ["Group", "group page"],
507
+ scope: "entity"
508
+ },
509
+ "portal-groups": {
510
+ description: "The groups listing page of the portal.",
511
+ hints: ["My groups", "Groups"],
512
+ scope: "collection"
513
+ },
514
+ "portal-item": {
515
+ description: "A specific item page in the portal.",
516
+ hints: ["Item", "item page"],
517
+ scope: "entity"
518
+ },
519
+ "portal-settings-security": {
520
+ description: "The Organization > Settings > Security page of the portal.",
521
+ hints: ["Organization settings", "Security", "Organization > Settings > Security"],
522
+ scope: "entity"
523
+ }
524
+ }, st = yt(et), te = st.map((e) => {
525
+ const { description: t, hints: s, scope: a } = et[e];
526
+ return ` - ${e}: ${t} (scope: ${a}; hints: ${s.join(", ")})`;
527
+ }).join(`
528
+ `), ee = `
529
+ You decide whether the assistant response should include a navigation action to ArcGIS Portal.
530
+
531
+ Given the user question and assistant response:
532
+ - Decide if a navigation action would help the user complete the task.
533
+ - If yes, choose one destination type:
534
+ ${te}
535
+
536
+ Rules:
537
+ - Only suggest navigation when you are highly confident the destination will help complete the user's task.
538
+ - If confidence is below 0.85, set shouldSuggestNavigation=false and destinationType=none.
539
+ - If there is no clear destination from the allowed types, set shouldSuggestNavigation=false and destinationType=none.
540
+ - If no navigation is useful, set shouldSuggestNavigation=false and destinationType=none.
541
+ - Prefer the most specific destination that is clearly supported by the question and response.
542
+ - Use entity-level destinations over collection/root destinations when both could apply and the entity target is explicit.
543
+ - Use collection/root destinations only for generic browsing intent with no specific entity target.
544
+ - If a chosen destination requires parameters, include all required parameters.
545
+ - If required parameters are missing or uncertain, set shouldSuggestNavigation=false and destinationType=none.
546
+ - Do not invent required parameters.
547
+ - Always include a confidence score from 0 to 1 in the output.
548
+ - Confidence means confidence that a navigation suggestion should be shown to the user.
549
+ - If shouldSuggestNavigation=false or destinationType=none, confidence must be <= 0.5.
550
+ - Use confidence >= 0.85 only when shouldSuggestNavigation=true and destinationType is not none.
551
+
552
+ User question:
553
+ {question}
554
+
555
+ Assistant response:
556
+ {response}
557
+ `, K = r.object({
558
+ shouldSuggestNavigation: r.boolean().default(!1),
559
+ destinationType: r.enum(["none", ...st]).default("none"),
560
+ itemId: r.string().default(""),
561
+ groupId: r.string().default(""),
562
+ confidence: r.number().min(0).max(1).default(0)
563
+ }), se = async (e, t) => {
501
564
  await g({ text: "Extracting navigation intent...", agentName: "doc-assistant" }, t);
502
565
  const s = e.outputMessage.trim();
503
566
  if (!s)
504
567
  return {};
505
- const a = x(e.agentExecutionContext.messages).trim(), r = await z.fromTemplate(Zt).format({
568
+ const a = x(e.agentExecutionContext.messages).trim(), o = await z.fromTemplate(ee).format({
506
569
  question: a,
507
570
  response: s
508
571
  }), l = await U({
509
572
  model: await D({ modelTier: "default" }),
510
573
  tools: [tt, Z],
511
- systemPrompt: r,
512
- responseFormat: J,
574
+ systemPrompt: o,
575
+ responseFormat: K,
513
576
  checkpointer: !0
514
- }).invoke({ messages: e.agentExecutionContext.messages }, t), u = J.parse(l.structuredResponse ?? {});
577
+ }).invoke({ messages: e.agentExecutionContext.messages }, t), u = K.parse(l.structuredResponse ?? {});
515
578
  if (!u.shouldSuggestNavigation || u.destinationType === "none")
516
579
  return {};
517
- const c = Xt(u);
580
+ const c = ae(u);
518
581
  return c ? (await R(c, t), {}) : {};
519
582
  };
520
- function Xt({
583
+ function ae({
521
584
  destinationType: e,
522
585
  itemId: t,
523
586
  groupId: s
@@ -527,6 +590,8 @@ function Xt({
527
590
  return { destinationType: "portal-content" };
528
591
  case "portal-groups":
529
592
  return { destinationType: "portal-groups" };
593
+ case "portal-settings-security":
594
+ return { destinationType: "portal-settings-security" };
530
595
  case "portal-item":
531
596
  return t ? { destinationType: "portal-item", itemId: t } : null;
532
597
  case "portal-group":
@@ -537,77 +602,53 @@ function Xt({
537
602
  return T(e);
538
603
  }
539
604
  }
540
- const Zt = `
541
- You decide whether the assistant response should include a navigation action to ArcGIS Portal.
542
-
543
- Given the user question and assistant response:
544
- - Decide if a navigation action would help the user complete the task.
545
- - If yes, choose one destination type:
546
- - portal-content: portal content page
547
- - portal-groups: groups listing page
548
- - portal-item: specific item page (requires itemId)
549
- - portal-group: specific group page (requires groupId)
550
-
551
- Rules:
552
- - If no navigation is useful, set shouldSuggestNavigation=false and destinationType=none.
553
- - If destinationType is portal-item and user references an item by title (for example #title, #"title with spaces", or plain quoted title), call resolvePortalItemIdByTitle and set itemId from the tool result.
554
- - If destinationType is portal-group and user references a group by title (for example $title, $"title with spaces", or plain quoted group title), call resolvePortalGroupIdByTitle and set groupId from the tool result.
555
- - Do not invent itemId.
556
- - Do not invent groupId.
557
- - Prefer destinationType=portal-content for generic "go to content" guidance.
558
-
559
- User question:
560
- {question}
561
-
562
- Assistant response:
563
- {response}
564
- `, et = xt.Root({
605
+ const at = Gt.Root({
565
606
  ...N()
566
- }), te = () => new C(et).addNode("answerDocQuestion", _t).addNode("extractNavigationIntent", Ht).addEdge(P, "answerDocQuestion").addEdge("answerDocQuestion", "extractNavigationIntent").addEdge("extractNavigationIntent", h), ee = String.raw`- **portal-doc-assistant** - General ArcGIS documentation and Portal help assistant:
607
+ }), oe = () => new C(at).addNode("answerDocQuestion", Zt).addNode("extractNavigationIntent", se).addEdge(P, "answerDocQuestion").addEdge("answerDocQuestion", "extractNavigationIntent").addEdge("extractNavigationIntent", f), re = String.raw`- **portal-doc-assistant** - General ArcGIS documentation and Portal help assistant:
567
608
  - answers general ArcGIS, Portal, Enterprise, and JavaScript SDK questions
568
609
  - acts as a fallback when specialized agents are not applicable
569
- `, se = {
610
+ `, ne = {
570
611
  id: "portal-doc-assistant",
571
612
  name: "Portal Doc Assistant",
572
- description: ee,
573
- createGraph: te,
574
- workspace: et
575
- }, st = `
613
+ description: re,
614
+ createGraph: oe,
615
+ workspace: at
616
+ }, ot = `
576
617
  Shared markdown formatting rules:
577
618
  - Use clear markdown headings (##) to separate sections.
578
619
  - Use concise bullet points for lists of facts, counts, or signals.
579
620
  - Emphasize key metrics with bold labels (for example: **Recent items:** 4).
580
621
  - Keep wording direct and analytical; avoid filler language but make sure the language is friendly.
581
622
  - Do not include raw internal IDs unless explicitly requested.
582
- `, ae = () => ({ latestGroupId: null, memory: {} }), q = (e) => {
623
+ `, ie = () => ({ latestGroupId: null, memory: {} }), q = (e) => {
583
624
  const t = e?.agentExecutionContext.sharedState.portalGroupSummaryMemory?.value;
584
- return t ? { latestGroupId: t.latestGroupId, memory: t.memory } : ae();
585
- }, re = async (e, t) => {
625
+ return t ? { latestGroupId: t.latestGroupId, memory: t.memory } : ie();
626
+ }, ue = async (e, t) => {
586
627
  await g({ text: "Answering group follow-up...", agentName: "group-analytics" }, t);
587
- const s = q(e), a = e.groupSummaryGroupId ?? s.latestGroupId, r = a ? s.memory[a] : void 0, i = e.groupSummaryQuestion || x(e.agentExecutionContext.messages);
588
- return r ? {
628
+ const s = q(e), a = e.groupSummaryGroupId ?? s.latestGroupId, o = a ? s.memory[a] : void 0, i = e.groupSummaryQuestion || x(e.agentExecutionContext.messages);
629
+ return o ? {
589
630
  status: "success",
590
631
  outputMessage: (await b({
591
- promptText: ne,
592
- schema: oe,
632
+ promptText: ce,
633
+ schema: le,
593
634
  modelTier: "default",
594
635
  inputVariables: {
595
- summary: r.summary,
636
+ summary: o.summary,
596
637
  question: i,
597
- fullContext: JSON.stringify(r.fullContext)
638
+ fullContext: JSON.stringify(o.fullContext)
598
639
  }
599
640
  })).answer
600
641
  } : {
601
642
  status: "success",
602
643
  outputMessage: "I do not have group analytics context yet. Ask me to analyze a group first with analyze group <group id>."
603
644
  };
604
- }, oe = o.object({
605
- answer: o.string(),
606
- isRelevant: o.boolean()
607
- }), ne = `
645
+ }, le = r.object({
646
+ answer: r.string(),
647
+ isRelevant: r.boolean()
648
+ }), ce = `
608
649
  You answer follow-up questions about ArcGIS group analytics.
609
650
 
610
- ${st}
651
+ ${ot}
611
652
 
612
653
  Ground your answer in the provided group analytics summary and context.
613
654
  If the answer is not available from the provided context, state that clearly and suggest what to check next.
@@ -629,30 +670,30 @@ Group full context:
629
670
 
630
671
  Question:
631
672
  {question}
632
- `, ie = async (e, t) => {
673
+ `, de = async (e, t) => {
633
674
  await g({ text: "Analyzing group-analytics intent...", agentName: "group-analytics" }, t);
634
- const s = x(e.agentExecutionContext.messages), a = !!q(e).latestGroupId, r = await z.fromTemplate(le).format({
675
+ const s = x(e.agentExecutionContext.messages), a = !!q(e).latestGroupId, o = await z.fromTemplate(pe).format({
635
676
  userMessage: s,
636
677
  hasAnalyticsContext: String(a)
637
678
  }), l = await U({
638
679
  model: await D({ modelTier: "fast" }),
639
680
  tools: [Z],
640
- systemPrompt: r,
641
- responseFormat: ue,
681
+ systemPrompt: o,
682
+ responseFormat: me,
642
683
  checkpointer: !0
643
- }).invoke({ messages: e.agentExecutionContext.messages }, t), { intent: u, groupId: c, question: n } = l.structuredResponse, m = u === "summarize" && !c, p = u === "followUp" && !(n ?? "").trim(), d = u === "clarify" || m || p;
684
+ }).invoke({ messages: e.agentExecutionContext.messages }, t), { intent: u, groupId: c, question: n } = l.structuredResponse, d = u === "summarize" && !c, p = u === "followUp" && !(n ?? "").trim(), m = u === "clarify" || d || p;
644
685
  return {
645
- groupSummaryIntent: d ? "clarify" : u,
686
+ groupSummaryIntent: m ? "clarify" : u,
646
687
  groupSummaryGroupId: c || null,
647
688
  groupSummaryQuestion: n || "",
648
689
  status: "success",
649
- outputMessage: d ? "Please clarify with a group id or title" : ""
690
+ outputMessage: m ? "Please clarify with a group id or title" : ""
650
691
  };
651
- }, ue = o.object({
652
- intent: o.enum(["summarize", "followUp", "navigation", "clarify"]),
653
- groupId: o.string().default(""),
654
- question: o.string().default("")
655
- }), le = `
692
+ }, me = r.object({
693
+ intent: r.enum(["summarize", "followUp", "navigation", "clarify"]),
694
+ groupId: r.string().default(""),
695
+ question: r.string().default("")
696
+ }), pe = `
656
697
  Classify the user's request for ArcGIS Portal group analytics.
657
698
 
658
699
  Rules:
@@ -681,19 +722,19 @@ hasAnalyticsContext:
681
722
 
682
723
  User message:
683
724
  {userMessage}
684
- `, ce = async (e, t) => {
725
+ `, ge = async (e, t) => {
685
726
  const s = q(e), a = e.groupSummaryGroupId ?? s.latestGroupId;
686
727
  return await g({ text: "Preparing navigation...", agentName: "group-analytics" }, t), await R(
687
728
  a ? { destinationType: "portal-group", groupId: a } : { destinationType: "portal-groups" },
688
729
  t
689
730
  ), { status: "success" };
690
731
  };
691
- function at({ timestamp: e, now: t, windowMs: s }) {
732
+ function rt({ timestamp: e, now: t, windowMs: s }) {
692
733
  return e ? t - e <= s : !1;
693
734
  }
694
- const me = 720 * 60 * 60 * 1e3;
695
- function de(e) {
696
- const t = vt(e);
735
+ const he = 720 * 60 * 60 * 1e3;
736
+ function fe(e) {
737
+ const t = Mt(e);
697
738
  return {
698
739
  id: e.id ?? "",
699
740
  title: e.title ?? "",
@@ -706,10 +747,10 @@ function de(e) {
706
747
  modified: e.modified?.getTime(),
707
748
  isInvitationOnly: e.isInvitationOnly,
708
749
  sourceSignals: {
709
- capabilities: At(e),
710
- membershipAccess: Mt(e),
711
- isOpenData: Gt(e),
712
- isDistributedCollaborationGroup: St(e),
750
+ capabilities: Pt(e),
751
+ membershipAccess: Ct(e),
752
+ isOpenData: Tt(e),
753
+ isDistributedCollaborationGroup: At(e),
713
754
  orgId: t.orgId,
714
755
  hiddenMembers: t.hiddenMembers,
715
756
  isViewOnly: t.isViewOnly,
@@ -718,7 +759,7 @@ function de(e) {
718
759
  }
719
760
  };
720
761
  }
721
- async function pe(e) {
762
+ async function ye(e) {
722
763
  const t = { owner: e.owner ?? "", admins: [], users: [] };
723
764
  try {
724
765
  return await e.fetchMembers();
@@ -726,7 +767,7 @@ async function pe(e) {
726
767
  return console.warn("Unable to fetch group members for analytics context", s), t;
727
768
  }
728
769
  }
729
- function ge(e) {
770
+ function we(e) {
730
771
  return e.map((t) => ({
731
772
  id: t.id ?? "",
732
773
  title: t.title ?? "Untitled",
@@ -736,40 +777,40 @@ function ge(e) {
736
777
  modified: t.modified?.getTime()
737
778
  }));
738
779
  }
739
- function fe(e, t) {
780
+ function be(e, t) {
740
781
  return e.filter(
741
- (s) => s.modified ? at({ timestamp: s.modified, now: t, windowMs: me }) : !1
782
+ (s) => s.modified ? rt({ timestamp: s.modified, now: t, windowMs: he }) : !1
742
783
  );
743
784
  }
744
- function he(e) {
785
+ function Ie(e) {
745
786
  const t = /* @__PURE__ */ new Map();
746
787
  for (const s of e)
747
788
  t.set(s.type, (t.get(s.type) ?? 0) + 1);
748
789
  return [...t.entries()].sort((s, a) => a[1] - s[1] || s[0].localeCompare(a[0])).slice(0, 6).map(([s, a]) => ({ type: s, count: a }));
749
790
  }
750
- async function ye(e) {
751
- const t = await e.queryItems({ num: 20, sortField: "modified", sortOrder: "desc" }), s = ge(t.results), a = Date.now();
791
+ async function xe(e) {
792
+ const t = await e.queryItems({ num: 20, sortField: "modified", sortOrder: "desc" }), s = we(t.results), a = Date.now();
752
793
  return {
753
794
  total: t.total,
754
795
  topItems: s,
755
- recentlyModifiedItems: fe(s, a),
756
- topItemTypes: he(s)
796
+ recentlyModifiedItems: be(s, a),
797
+ topItemTypes: Ie(s)
757
798
  };
758
799
  }
759
- async function we(e, t) {
800
+ async function ve(e, t) {
760
801
  if (!t)
761
802
  return { error: { code: "missingGroupId", message: "Group id is required." } };
762
803
  try {
763
804
  const a = (await e.queryGroups({ query: `id:${t}`, num: 1 })).results[0];
764
805
  if (!a)
765
806
  return { error: { code: "groupNotFound", message: `No group found for id: ${t}` } };
766
- const r = de(a), i = await pe(a), l = await ye(a);
767
- return { result: { group: r, members: i, items: l } };
807
+ const o = fe(a), i = await ye(a), l = await xe(a);
808
+ return { result: { group: o, members: i, items: l } };
768
809
  } catch (s) {
769
810
  return console.error("Error fetching portal group analytics context:", s), { error: { code: "unhandledError" } };
770
811
  }
771
812
  }
772
- const be = 2160 * 60 * 60 * 1e3, Ie = async (e, t) => {
813
+ const Se = 2160 * 60 * 60 * 1e3, Ge = async (e, t) => {
773
814
  const s = e.groupSummaryGroupId;
774
815
  if (!s)
775
816
  return {
@@ -779,44 +820,44 @@ const be = 2160 * 60 * 60 * 1e3, Ie = async (e, t) => {
779
820
  await g({ text: `Analyzing group ${s}...`, agentName: "group-analytics" }, t);
780
821
  const a = t?.configurable?.context;
781
822
  I(a);
782
- const { result: r, error: i } = await we(a.portal, s);
783
- if (i || !r)
823
+ const { result: o, error: i } = await ve(a.portal, s);
824
+ if (i || !o)
784
825
  return await g({ text: "Failed to fetch group context", agentName: "group-analytics" }, t), {
785
826
  status: "success",
786
827
  outputMessage: "Unable to retrieve group context for analytics."
787
828
  };
788
- const { group: l, items: u } = r, c = Date.now(), n = l.modified, m = n ? at({ timestamp: n, now: c, windowMs: be }) : !1, p = u.recentlyModifiedItems.length, d = p > 0, y = m || d, v = await b({
789
- promptText: ve,
790
- schema: xe,
829
+ const { group: l, items: u } = o, c = Date.now(), n = l.modified, d = n ? rt({ timestamp: n, now: c, windowMs: Se }) : !1, p = u.recentlyModifiedItems.length, m = p > 0, y = d || m, v = await b({
830
+ promptText: Ae,
831
+ schema: Me,
791
832
  modelTier: "default",
792
833
  inputVariables: {
793
- context: JSON.stringify(r),
834
+ context: JSON.stringify(o),
794
835
  deterministicSignals: JSON.stringify({
795
836
  isGroupActive: y,
796
- isGroupRecentlyModified: m,
797
- hasRecentlyAddedOrUpdatedContent: d,
837
+ isGroupRecentlyModified: d,
838
+ hasRecentlyAddedOrUpdatedContent: m,
798
839
  recentItemCount: p
799
840
  })
800
841
  }
801
- }), { followUpQuestions: w, summary: S } = v, nt = q(e), it = {
842
+ }), { followUpQuestions: w, summary: S } = v, ut = q(e), lt = {
802
843
  latestGroupId: s,
803
844
  memory: {
804
- ...nt.memory,
805
- [s]: { summary: S, followUpQuestions: w, fullContext: r }
845
+ ...ut.memory,
846
+ [s]: { summary: S, followUpQuestions: w, fullContext: o }
806
847
  }
807
848
  };
808
849
  return w.length && await E({ type: "suggested-prompts", data: { prompts: w } }, t), {
809
850
  status: "success",
810
851
  outputMessage: S,
811
- sharedStatePatch: { portalGroupSummaryMemory: { value: it } }
852
+ sharedStatePatch: { portalGroupSummaryMemory: { value: lt } }
812
853
  };
813
- }, xe = o.object({
814
- summary: o.string(),
815
- followUpQuestions: o.array(o.string()).default([])
816
- }), ve = `
854
+ }, Me = r.object({
855
+ summary: r.string(),
856
+ followUpQuestions: r.array(r.string()).default([])
857
+ }), Ae = `
817
858
  You summarize ArcGIS Portal groups based on structured context and deterministic activity signals.
818
859
 
819
- ${st}
860
+ ${ot}
820
861
 
821
862
  Output format requirements:
822
863
  - Return concise markdown with clear sections in this order:
@@ -852,57 +893,57 @@ Group context:
852
893
 
853
894
  Deterministic signals:
854
895
  {deterministicSignals}
855
- `, $ = (e, t) => t ?? e, rt = f.Root({
896
+ `, $ = (e, t) => t ?? e, nt = h.Root({
856
897
  ...N(),
857
- groupSummaryIntent: f({
898
+ groupSummaryIntent: h({
858
899
  reducer: $,
859
900
  default: () => "clarify"
860
901
  }),
861
- groupSummaryGroupId: f({
902
+ groupSummaryGroupId: h({
862
903
  reducer: $,
863
904
  default: () => null
864
905
  }),
865
- groupSummaryQuestion: f({
906
+ groupSummaryQuestion: h({
866
907
  reducer: $,
867
908
  default: () => ""
868
909
  })
869
- }), Se = () => new C(rt).addNode("detectGroupSummaryIntent", ie).addNode("summarizePortalGroup", Ie).addNode("answerGroupSummaryFollowUp", re).addNode("suggestGroupSummaryNavigation", ce).addEdge(P, "detectGroupSummaryIntent").addConditionalEdges("detectGroupSummaryIntent", (t) => t.groupSummaryIntent === "summarize" ? "summarizePortalGroup" : t.groupSummaryIntent === "followUp" ? "answerGroupSummaryFollowUp" : t.groupSummaryIntent === "navigation" ? "suggestGroupSummaryNavigation" : h).addEdge("summarizePortalGroup", h).addEdge("answerGroupSummaryFollowUp", h).addEdge("suggestGroupSummaryNavigation", h), Ge = String.raw`- **portal-group-analytics** - Portal group analytics assistant:
910
+ }), Te = () => new C(nt).addNode("detectGroupSummaryIntent", de).addNode("summarizePortalGroup", Ge).addNode("answerGroupSummaryFollowUp", ue).addNode("suggestGroupSummaryNavigation", ge).addEdge(P, "detectGroupSummaryIntent").addConditionalEdges("detectGroupSummaryIntent", (t) => t.groupSummaryIntent === "summarize" ? "summarizePortalGroup" : t.groupSummaryIntent === "followUp" ? "answerGroupSummaryFollowUp" : t.groupSummaryIntent === "navigation" ? "suggestGroupSummaryNavigation" : f).addEdge("summarizePortalGroup", f).addEdge("answerGroupSummaryFollowUp", f).addEdge("suggestGroupSummaryNavigation", f), Ce = String.raw`- **portal-group-analytics** - Portal group analytics assistant:
870
911
  - summarizes ArcGIS portal groups from group context and sourceJSON details
871
912
  - answers follow-up questions grounded in the summarized group
872
913
  - suggests navigation to groups when relevant
873
- `, Me = {
914
+ `, Pe = {
874
915
  id: "portal-group-analytics",
875
916
  name: "Portal Group Analytics",
876
- description: Ge,
877
- createGraph: Se,
878
- workspace: rt
879
- }, Ae = () => ({ latestItemId: null, memory: {} }), F = (e) => {
917
+ description: Ce,
918
+ createGraph: Te,
919
+ workspace: nt
920
+ }, Ne = () => ({ latestItemId: null, memory: {} }), F = (e) => {
880
921
  const t = e?.agentExecutionContext.sharedState.portalItemAnalyticsSummaryMemory?.value;
881
- return t ? { latestItemId: t.latestItemId, memory: t.memory } : Ae();
882
- }, Te = o.object({
883
- intent: o.enum(["summarize", "followUp", "clarify"]),
884
- itemId: o.string().default(""),
885
- question: o.string().default("")
886
- }), Ce = o.object({ summary: o.string(), followUpQuestions: o.array(o.string()).default([]) }), Pe = o.object({ answer: o.string(), isRelevant: o.boolean() }), Ne = async (e, t) => {
922
+ return t ? { latestItemId: t.latestItemId, memory: t.memory } : Ne();
923
+ }, qe = r.object({
924
+ intent: r.enum(["summarize", "followUp", "clarify"]),
925
+ itemId: r.string().default(""),
926
+ question: r.string().default("")
927
+ }), $e = r.object({ summary: r.string(), followUpQuestions: r.array(r.string()).default([]) }), ke = r.object({ answer: r.string(), isRelevant: r.boolean() }), Ee = async (e, t) => {
887
928
  await g({ text: "Answering follow-up...", agentName: "analytics" }, t);
888
- const s = F(e), a = e.analyticsItemId ?? s.latestItemId, r = a ? s.memory[a] : void 0, i = e.analyticsQuestion || x(e.agentExecutionContext.messages);
889
- return r ? {
929
+ const s = F(e), a = e.analyticsItemId ?? s.latestItemId, o = a ? s.memory[a] : void 0, i = e.analyticsQuestion || x(e.agentExecutionContext.messages);
930
+ return o ? {
890
931
  status: "success",
891
932
  outputMessage: (await b({
892
- promptText: qe,
893
- schema: Pe,
933
+ promptText: De,
934
+ schema: ke,
894
935
  modelTier: "default",
895
936
  inputVariables: {
896
- summary: r.summary,
937
+ summary: o.summary,
897
938
  question: i,
898
- fullContext: JSON.stringify(r.fullContext)
939
+ fullContext: JSON.stringify(o.fullContext)
899
940
  }
900
941
  })).answer
901
942
  } : {
902
943
  status: "success",
903
944
  outputMessage: "I don't have enough information yet. Please ask me to summarize the item first using summarize item <item id>."
904
945
  };
905
- }, qe = `
946
+ }, De = `
906
947
  You answer follow-up questions about an ArcGIS item.
907
948
 
908
949
  Ground your answer in the provided item context.
@@ -922,27 +963,27 @@ Item full context
922
963
 
923
964
  Question:
924
965
  {question}
925
- `, $e = async (e, t) => {
966
+ `, ze = async (e, t) => {
926
967
  await g({ text: "Analyzing intent...", agentName: "analytics" }, t);
927
- const s = x(e.agentExecutionContext.messages), a = !!F(e).latestItemId, r = await z.fromTemplate(ke).format({
968
+ const s = x(e.agentExecutionContext.messages), a = !!F(e).latestItemId, o = await z.fromTemplate(Ue).format({
928
969
  userMessage: s,
929
970
  hasSummaryContext: String(a)
930
971
  }), l = await U({
931
972
  model: await D({ modelTier: "fast" }),
932
973
  tools: [tt],
933
- systemPrompt: r,
934
- responseFormat: Te,
974
+ systemPrompt: o,
975
+ responseFormat: qe,
935
976
  checkpointer: !0
936
- }).invoke({ messages: e.agentExecutionContext.messages }, t), { intent: u, itemId: c, question: n } = l.structuredResponse, d = u === "clarify" || u === "summarize" && !c || u === "followUp" && !n;
977
+ }).invoke({ messages: e.agentExecutionContext.messages }, t), { intent: u, itemId: c, question: n } = l.structuredResponse, m = u === "clarify" || u === "summarize" && !c || u === "followUp" && !n;
937
978
  return {
938
979
  agentExecutionContext: { ...e.agentExecutionContext },
939
- analyticsIntent: d ? "clarify" : u,
980
+ analyticsIntent: m ? "clarify" : u,
940
981
  analyticsItemId: c || null,
941
982
  analyticsQuestion: n || "",
942
983
  status: "success",
943
- outputMessage: d ? 'Please clarify with summarize item <item id>, summarize item #<title>, or summarize item #"<title with spaces>".' : ""
984
+ outputMessage: m ? 'Please clarify with summarize item <item id>, summarize item #<title>, or summarize item #"<title with spaces>".' : ""
944
985
  };
945
- }, ke = `
986
+ }, Ue = `
946
987
  Classify the user analytics request.
947
988
 
948
989
  Rules:
@@ -972,7 +1013,7 @@ hasSummaryContext:
972
1013
 
973
1014
  User message:
974
1015
  {userMessage}
975
- `, Ee = async (e, t) => {
1016
+ `, Re = async (e, t) => {
976
1017
  const s = e.analyticsItemId;
977
1018
  if (!s)
978
1019
  return {
@@ -982,30 +1023,30 @@ User message:
982
1023
  await g({ text: `Summarizing item ${s}...`, agentName: "analytics" }, t);
983
1024
  const a = t?.configurable?.context;
984
1025
  I(a);
985
- const { portal: r, user: i } = a, { result: l, error: u } = await bt(i, r, s);
1026
+ const { portal: o, user: i } = a, { result: l, error: u } = await vt(i, o, s);
986
1027
  if (u || !l)
987
1028
  return await g({ text: "Failed to get item context for summarization", agentName: "analytics" }, t), {
988
1029
  status: "success",
989
1030
  outputMessage: "Unable to retrieve item context for summarization."
990
1031
  };
991
1032
  const { context: c } = l, n = await b({
992
- promptText: De,
993
- schema: Ce,
1033
+ promptText: Fe,
1034
+ schema: $e,
994
1035
  modelTier: "default",
995
1036
  inputVariables: { context: JSON.stringify(c) }
996
- }), { followUpQuestions: m, summary: p } = n, d = F(e), y = {
1037
+ }), { followUpQuestions: d, summary: p } = n, m = F(e), y = {
997
1038
  latestItemId: s,
998
1039
  memory: {
999
- ...d.memory,
1000
- [s]: { summary: p, followUpQuestions: m, fullContext: c }
1040
+ ...m.memory,
1041
+ [s]: { summary: p, followUpQuestions: d, fullContext: c }
1001
1042
  }
1002
1043
  };
1003
- return m.length && await E({ type: "suggested-prompts", data: { prompts: m } }, t), {
1044
+ return d.length && await E({ type: "suggested-prompts", data: { prompts: d } }, t), {
1004
1045
  status: "success",
1005
1046
  outputMessage: p,
1006
1047
  sharedStatePatch: { portalItemAnalyticsSummaryMemory: { value: y } }
1007
1048
  };
1008
- }, De = `
1049
+ }, Fe = `
1009
1050
  You are a item summary tool for ArcGIS. Your job is to summarize an item's info based on the provided context.
1010
1051
  Summary rules:
1011
1052
  - The summary should be concise markdown, make sure to format the output nicely so it's easy to read.
@@ -1020,38 +1061,39 @@ Do not include internal identifiers.
1020
1061
  If the user asks for a detailed summary, you may expand the response up to 300 words.
1021
1062
  Item context:
1022
1063
  {context}
1023
- `, k = (e, t) => t ?? e, ot = f.Root({
1064
+ `, k = (e, t) => t ?? e, it = h.Root({
1024
1065
  ...N(),
1025
1066
  // States shared only across nodes in the graph, not between invocations
1026
- analyticsIntent: f({
1067
+ analyticsIntent: h({
1027
1068
  reducer: k,
1028
1069
  default: () => "clarify"
1029
1070
  }),
1030
- analyticsItemId: f({
1071
+ analyticsItemId: h({
1031
1072
  reducer: k,
1032
1073
  default: () => null
1033
1074
  }),
1034
- analyticsQuestion: f({
1075
+ analyticsQuestion: h({
1035
1076
  reducer: k,
1036
1077
  default: () => ""
1037
1078
  })
1038
- }), ze = () => new C(ot).addNode("detectAnalyticsIntent", $e).addNode("summarizePortalItem", Ee).addNode("answerAnalyticsFollowUp", Ne).addEdge(P, "detectAnalyticsIntent").addConditionalEdges("detectAnalyticsIntent", (t) => t.analyticsIntent === "summarize" ? "summarizePortalItem" : t.analyticsIntent === "followUp" ? "answerAnalyticsFollowUp" : h).addEdge("summarizePortalItem", h).addEdge("answerAnalyticsFollowUp", h), Ue = String.raw`- **portal-item-analytics** - Portal item analytics assistant:
1079
+ }), Oe = () => new C(it).addNode("detectAnalyticsIntent", ze).addNode("summarizePortalItem", Re).addNode("answerAnalyticsFollowUp", Ee).addEdge(P, "detectAnalyticsIntent").addConditionalEdges("detectAnalyticsIntent", (t) => t.analyticsIntent === "summarize" ? "summarizePortalItem" : t.analyticsIntent === "followUp" ? "answerAnalyticsFollowUp" : f).addEdge("summarizePortalItem", f).addEdge("answerAnalyticsFollowUp", f), je = String.raw`- **portal-item-analytics** - Portal item analytics assistant:
1039
1080
  - summarizes ArcGIS portal items from item context
1040
1081
  - suggests follow-up prompts grounded in the item
1041
- `, Re = {
1082
+ `, Ve = {
1042
1083
  id: "portal-item-analytics",
1043
1084
  name: "Portal Item Analytics",
1044
- description: Ue,
1045
- createGraph: ze,
1046
- workspace: ot
1047
- }, Fe = mt`:host{height:100%;border-width:1px;border-style:solid;border-color:var(--calcite-color-border-3);display:block;width:100%;--tw-shadow: 0 1px 6px -1px rgba(0, 0, 0, .16), 0 1px 2px -1px rgba(0, 0, 0, .08);--tw-shadow-colored: 0 1px 6px -1px var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.chat-entry{display:flex;flex-direction:column;gap:.75rem;width:100%}.chat-actions{display:flex;justify-content:flex-end;gap:.5rem}.header-actions{display:flex;gap:.5rem;padding-inline-start:.75rem}.navigation-block{display:flex;flex-direction:column;align-items:stretch;gap:.35rem;margin-top:.5rem}.navigation-button{width:100%;margin-block:.25rem}.navigation-block-description{font-size:.75rem;color:var(--calcite-color-text-3)}`;
1048
- function je(e, t) {
1085
+ description: je,
1086
+ createGraph: Oe,
1087
+ workspace: it
1088
+ }, Be = pt`:host{height:100%;border-width:1px;border-style:solid;border-color:var(--calcite-color-border-3);display:block;width:100%;--tw-shadow: 0 1px 6px -1px rgba(0, 0, 0, .16), 0 1px 2px -1px rgba(0, 0, 0, .08);--tw-shadow-colored: 0 1px 6px -1px var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.chat-entry{display:flex;flex-direction:column;gap:.75rem;width:100%}.chat-actions{display:flex;justify-content:flex-end;gap:.5rem}.header-actions{display:flex;gap:.5rem;padding-inline-start:.75rem}.navigation-block{display:flex;flex-direction:column;align-items:stretch;gap:.35rem;margin-top:.5rem}.navigation-button{width:100%;margin-block:.25rem}.navigation-block-description{font-size:.75rem;color:var(--calcite-color-text-3)}`;
1089
+ function Qe(e, t) {
1049
1090
  if (!t)
1050
1091
  return;
1051
1092
  const { destinationType: s } = e;
1052
1093
  switch (s) {
1053
1094
  case "portal-content":
1054
1095
  case "portal-groups":
1096
+ case "portal-settings-security":
1055
1097
  return t[s];
1056
1098
  case "portal-item":
1057
1099
  return t[s]?.(e.itemId);
@@ -1061,33 +1103,33 @@ function je(e, t) {
1061
1103
  return T(s);
1062
1104
  }
1063
1105
  }
1064
- function Oe(e) {
1065
- const t = Ft.safeParse(e);
1106
+ function Le(e) {
1107
+ const t = Vt.safeParse(e);
1066
1108
  return t.success ? t.data : void 0;
1067
1109
  }
1068
- class Ve extends lt {
1110
+ class Ke extends dt {
1069
1111
  constructor() {
1070
- super(...arguments), this.t9n = pt({ blocking: !0 }), this.assistantEl = M(), this.formEl = M(), this.voiceInputEl = M(), this.inputEl = M(), this.navigationSlotElements = /* @__PURE__ */ new Map(), this.handleSlottableRequest = (t) => {
1112
+ super(...arguments), this.t9n = ht({ blocking: !0 }), this.assistantEl = M(), this.formEl = M(), this.voiceInputEl = M(), this.inputEl = M(), this.navigationSlotElements = /* @__PURE__ */ new Map(), this.handleSlottableRequest = (t) => {
1071
1113
  const s = t.detail, a = s.data?.block;
1072
1114
  if (!a)
1073
1115
  return;
1074
- const r = this.getNavigationAction(a);
1075
- r && this.upsertNavigationSlotElement(s.slotName, r);
1076
- }, this.inputText = "", this.showVoiceInput = !0, this.isListening = !1, this.isVoiceInputDisabled = !1, this.interrupt = null, this.autoDestroyDisabled = !1, this.defaultClosed = !1, this.arcgisPortalNavigationRequest = ct();
1116
+ const o = this.getNavigationAction(a);
1117
+ o && this.upsertNavigationSlotElement(s.slotName, o);
1118
+ }, this.inputText = "", this.showVoiceInput = !0, this.isListening = !1, this.isVoiceInputDisabled = !1, this.interrupt = null, this.autoDestroyDisabled = !1, this.defaultClosed = !1, this.arcgisPortalNavigationRequest = mt();
1077
1119
  }
1078
1120
  static {
1079
1121
  this.properties = { inputText: 16, showVoiceInput: 16, isListening: 16, isVoiceInputDisabled: 16, interrupt: 16, autoDestroyDisabled: 5, portal: 0, user: 0, config: 0, navigationTargetMap: 0, defaultClosed: 5 };
1080
1122
  }
1081
1123
  static {
1082
- this.styles = Fe;
1124
+ this.styles = Be;
1083
1125
  }
1084
1126
  getNavigationAction(t) {
1085
1127
  if (t?.type !== _)
1086
1128
  return;
1087
- const s = Oe(t.data);
1129
+ const s = Le(t.data);
1088
1130
  if (!s)
1089
1131
  return;
1090
- const a = je(s, this.navigationTargetMap);
1132
+ const a = Qe(s, this.navigationTargetMap);
1091
1133
  if (a)
1092
1134
  return { href: a, targetDetail: s, label: this.getNavigationText(s.destinationType) };
1093
1135
  }
@@ -1095,13 +1137,13 @@ class Ve extends lt {
1095
1137
  const a = this.assistantEl.value;
1096
1138
  if (!a)
1097
1139
  return;
1098
- let r = this.navigationSlotElements.get(t);
1099
- r || (r = document.createElement("div"), r.slot = t, this.navigationSlotElements.set(t, r), a.append(r)), dt(G`<div><calcite-button class="navigation-button" appearance=outline width=full .href=${s.href} icon-end=launch @click=${(i) => {
1140
+ let o = this.navigationSlotElements.get(t);
1141
+ o || (o = document.createElement("div"), o.slot = t, this.navigationSlotElements.set(t, o), a.append(o)), gt(G`<div><calcite-button class="navigation-button" appearance=outline width=full .href=${s.href} icon-end=launch @click=${(i) => {
1100
1142
  i.preventDefault(), this.arcgisPortalNavigationRequest.emit({
1101
1143
  href: s.href,
1102
1144
  targetDetail: s.targetDetail
1103
1145
  });
1104
- }}>${s.label}</calcite-button>${s.description ? G`<div class="navigation-block-description">${s.description}</div>` : null}</div>`, r);
1146
+ }}>${s.label}</calcite-button>${s.description ? G`<div class="navigation-block-description">${s.description}</div>` : null}</div>`, o);
1105
1147
  }
1106
1148
  getNavigationText(t) {
1107
1149
  const s = this.t9n.navigation;
@@ -1110,6 +1152,8 @@ class Ve extends lt {
1110
1152
  return s.openContent;
1111
1153
  case "portal-groups":
1112
1154
  return s.openGroups;
1155
+ case "portal-settings-security":
1156
+ return s.openOrganizationSettingsSecurity;
1113
1157
  case "portal-item":
1114
1158
  return s.openItem;
1115
1159
  case "portal-group":
@@ -1119,7 +1163,7 @@ class Ve extends lt {
1119
1163
  }
1120
1164
  }
1121
1165
  render() {
1122
- const { t9n: t, inputText: s, portal: a, user: r, navigationTargetMap: i, showVoiceInput: l, isListening: u, isVoiceInputDisabled: c } = this;
1166
+ const { t9n: t, inputText: s, portal: a, user: o, navigationTargetMap: i, showVoiceInput: l, isListening: u, isVoiceInputDisabled: c } = this;
1123
1167
  return G`<arcgis-assistant log-enabled keep-suggested-prompts .heading=${t.heading} .entryMessage=${t.entryMessage} @arcgisSlottableRequest=${this.handleSlottableRequest} @arcgisInterrupt=${({ detail: n }) => {
1124
1168
  this.interrupt = n;
1125
1169
  }} @arcgisInterruptCancel=${() => {
@@ -1132,9 +1176,9 @@ class Ve extends lt {
1132
1176
  });
1133
1177
  }} ${A(this.assistantEl)}><div slot=header-actions-start class="header-actions"><calcite-icon icon=effects></calcite-icon></div><form slot=chat-entry class="chat-entry" @submit=${(n) => {
1134
1178
  n.preventDefault();
1135
- const m = s.trim();
1136
- m && (this.assistantEl.value?.submitMessage(m), this.inputText = "");
1137
- }} ${A(this.formEl)}><arcgis-portal-mentionable-text-area .portal=${a} .user=${r} rows=3 .popoverListLabel=${t.mentionEntities} .placeholder=${t.placeholder} .value=${s} @arcgisUserMentionableTextAreaKeyDown=${({ detail: n }) => {
1179
+ const d = s.trim();
1180
+ d && (this.assistantEl.value?.submitMessage(d), this.inputText = "");
1181
+ }} ${A(this.formEl)}><arcgis-portal-mentionable-text-area .portal=${a} .user=${o} rows=3 .popoverListLabel=${t.mentionEntities} .placeholder=${t.placeholder} .value=${s} @arcgisUserMentionableTextAreaKeyDown=${({ detail: n }) => {
1138
1182
  n.key === "Enter" && !n.shiftKey && (n.preventDefault(), this.formEl.value?.requestSubmit());
1139
1183
  }} @arcgisUserMentionableTextAreaChange=${({ detail: n }) => {
1140
1184
  this.inputText = n ?? "";
@@ -1150,14 +1194,14 @@ class Ve extends lt {
1150
1194
  this.isVoiceInputDisabled = !0;
1151
1195
  const n = this.voiceInputEl.value;
1152
1196
  u ? await n?.stopListening() : await n?.startListening();
1153
- }}></calcite-button>` || ""}<calcite-button type=submit icon-start=send round .disabled=${!s.trim()} .label=${t.send}>${t.send}</calcite-button></div></form><arcgis-assistant-agent .agent=${Re} .context=${{ portal: a, user: r, navigationTargetMap: i }}></arcgis-assistant-agent><arcgis-assistant-agent .agent=${Bt} .context=${{ portal: a, user: r, navigationTargetMap: i }}></arcgis-assistant-agent><arcgis-assistant-agent .agent=${se} .context=${{ portal: a, user: r, navigationTargetMap: i }}></arcgis-assistant-agent><arcgis-assistant-agent .agent=${Me} .context=${{ portal: a, user: r, navigationTargetMap: i }}></arcgis-assistant-agent>${this.interrupt && G`<arcgis-portal-ai-assistant-interrupt slot=interrupt .type=${this.interrupt.type} .message=${this.interrupt.message} .options=${this.interrupt.options} @arcgisSubmit=${({ detail: n }) => {
1197
+ }}></calcite-button>` || ""}<calcite-button type=submit icon-start=send round .disabled=${!s.trim()} .label=${t.send}>${t.send}</calcite-button></div></form><arcgis-assistant-agent .agent=${Ve} .context=${{ portal: a, user: o, navigationTargetMap: i }}></arcgis-assistant-agent><arcgis-assistant-agent .agent=${Kt} .context=${{ portal: a, user: o, navigationTargetMap: i }}></arcgis-assistant-agent><arcgis-assistant-agent .agent=${ne} .context=${{ portal: a, user: o, navigationTargetMap: i }}></arcgis-assistant-agent><arcgis-assistant-agent .agent=${Pe} .context=${{ portal: a, user: o, navigationTargetMap: i }}></arcgis-assistant-agent>${this.interrupt && G`<arcgis-portal-ai-assistant-interrupt slot=interrupt .type=${this.interrupt.type} .message=${this.interrupt.message} .options=${this.interrupt.options} @arcgisSubmit=${({ detail: n }) => {
1154
1198
  this.assistantEl.value?.submitInterrupt(n);
1155
1199
  }} @arcgisCancel=${() => {
1156
1200
  this.assistantEl.value?.cancelInterrupt();
1157
1201
  }}></arcgis-portal-ai-assistant-interrupt>` || ""}</arcgis-assistant>`;
1158
1202
  }
1159
1203
  }
1160
- ut("arcgis-portal-ai-assistant", Ve);
1204
+ ct("arcgis-portal-ai-assistant", Ke);
1161
1205
  export {
1162
- Ve as ArcgisPortalAiAssistant
1206
+ Ke as ArcgisPortalAiAssistant
1163
1207
  };