@arcgis/portal-components 5.2.0-next.55 → 5.2.0-next.57
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.
|
@@ -5,14 +5,14 @@ import { css as gt, render as ht, html as M } from "lit";
|
|
|
5
5
|
import { createRef as T, ref as A } from "lit/directives/ref.js";
|
|
6
6
|
import { u as ft } from "../../chunks/useT9n.js";
|
|
7
7
|
import { a as C, t as yt, b as wt } from "../../chunks/functionalities.js";
|
|
8
|
-
import { NodeInterrupt as
|
|
8
|
+
import { NodeInterrupt as W, Annotation as y, StateGraph as N, START as P, END as w } from "@langchain/langgraph/web";
|
|
9
9
|
import { sendTraceMessage as g, invokeStructuredPrompt as v, sendUXSuggestion as E, createAgentRuntimeStateWithSharedState as k, createChatModel as D } from "@arcgis/ai-components/utils/index.js";
|
|
10
10
|
import n from "zod";
|
|
11
11
|
import { a as bt, c as vt, q as It } from "../../chunks/groups2.js";
|
|
12
12
|
import xt from "@arcgis/core/identity/IdentityManager.js";
|
|
13
13
|
import F from "@arcgis/core/request.js";
|
|
14
14
|
import { ChatPromptTemplate as U } from "@langchain/core/prompts";
|
|
15
|
-
import { tool as
|
|
15
|
+
import { tool as Y } from "@langchain/core/tools";
|
|
16
16
|
import { s as St, a as Mt } from "../../chunks/item.js";
|
|
17
17
|
import { c as Gt, d as Tt, i as At, b as Ct, g as Nt } from "../../chunks/groups.js";
|
|
18
18
|
const H = (a) => {
|
|
@@ -38,9 +38,9 @@ Added members:
|
|
|
38
38
|
|
|
39
39
|
Not added members:
|
|
40
40
|
{notAddedMembers}
|
|
41
|
-
`, kt = (a) => a.map((t) => `"${t}"`).join(", "),
|
|
41
|
+
`, kt = (a) => a.map((t) => `"${t}"`).join(", "), qt = n.object({
|
|
42
42
|
successMessage: n.string().default("")
|
|
43
|
-
}), V = "portal-group-creation", j = "approveAddMembers",
|
|
43
|
+
}), V = "portal-group-creation", j = "approveAddMembers", zt = async (a, t) => {
|
|
44
44
|
if (a.intentParams.intent !== "addMembers")
|
|
45
45
|
return {
|
|
46
46
|
status: "success",
|
|
@@ -76,7 +76,7 @@ Do you want to continue?`, { hitlResponse: c } = t?.configurable ?? {};
|
|
|
76
76
|
members: [...s]
|
|
77
77
|
}
|
|
78
78
|
};
|
|
79
|
-
throw new
|
|
79
|
+
throw new W(d);
|
|
80
80
|
}
|
|
81
81
|
if (c.payload !== !0)
|
|
82
82
|
return {
|
|
@@ -99,7 +99,7 @@ Do you want to continue?`, { hitlResponse: c } = t?.configurable ?? {};
|
|
|
99
99
|
try {
|
|
100
100
|
const h = (await v({
|
|
101
101
|
promptText: Pt,
|
|
102
|
-
schema:
|
|
102
|
+
schema: qt,
|
|
103
103
|
modelTier: "fast",
|
|
104
104
|
inputVariables: {
|
|
105
105
|
addedMembers: p.join(", "),
|
|
@@ -140,7 +140,7 @@ Group title:
|
|
|
140
140
|
|
|
141
141
|
Failure reason:
|
|
142
142
|
{failureReason}
|
|
143
|
-
`,
|
|
143
|
+
`, _ = "portal-group-creation", L = "approveCreateGroup", Dt = n.object({
|
|
144
144
|
successMessage: n.string().default("")
|
|
145
145
|
}), Ut = n.object({
|
|
146
146
|
failureMessage: n.string().default("")
|
|
@@ -157,10 +157,10 @@ Failure reason:
|
|
|
157
157
|
outputMessage: "What title would you like for the new group?"
|
|
158
158
|
};
|
|
159
159
|
const s = `A group with the title **${e}** will be created. Do you want to continue?`, { hitlResponse: o } = t?.configurable;
|
|
160
|
-
if (o?.agentId !==
|
|
160
|
+
if (o?.agentId !== _ || o.id !== L) {
|
|
161
161
|
const r = {
|
|
162
|
-
agentId:
|
|
163
|
-
id:
|
|
162
|
+
agentId: _,
|
|
163
|
+
id: L,
|
|
164
164
|
kind: "booleanChoice",
|
|
165
165
|
message: s,
|
|
166
166
|
metadata: {
|
|
@@ -169,7 +169,7 @@ Failure reason:
|
|
|
169
169
|
access: "private"
|
|
170
170
|
}
|
|
171
171
|
};
|
|
172
|
-
throw new
|
|
172
|
+
throw new W(r);
|
|
173
173
|
}
|
|
174
174
|
if (o.payload !== !0)
|
|
175
175
|
return {
|
|
@@ -302,10 +302,10 @@ User message:
|
|
|
302
302
|
"portal-notebooks",
|
|
303
303
|
"portal-scene-viewer",
|
|
304
304
|
"portal-settings-security"
|
|
305
|
-
]),
|
|
305
|
+
]), _t = n.object({
|
|
306
306
|
destinationType: jt
|
|
307
|
-
}),
|
|
308
|
-
|
|
307
|
+
}), Lt = n.union([
|
|
308
|
+
_t,
|
|
309
309
|
n.object({
|
|
310
310
|
destinationType: n.literal("portal-item"),
|
|
311
311
|
itemId: n.string().trim().min(1)
|
|
@@ -317,20 +317,20 @@ User message:
|
|
|
317
317
|
]), X = "portal-navigation", R = async (a, t) => {
|
|
318
318
|
const e = t?.configurable?.context;
|
|
319
319
|
!H(e) || !e.navigationTargetMap?.[a.destinationType] || await E({ type: X, data: { ...a } }, t);
|
|
320
|
-
},
|
|
320
|
+
}, Bt = async (a, t) => {
|
|
321
321
|
const e = a.createdGroupId ?? a.agentExecutionContext.sharedState.createdGroupId?.value;
|
|
322
322
|
return e ? (await g({ text: "Preparing navigation...", agentName: "group-creation" }, t), await R({ destinationType: "portal-group", groupId: e }, t), {}) : {};
|
|
323
|
-
},
|
|
323
|
+
}, B = (a, t) => t ?? a, Z = y.Root({
|
|
324
324
|
...k(),
|
|
325
325
|
// * Shared state between nodes (but not persisted to the agent execution context)
|
|
326
326
|
/** Parameters related to the user's intent for group creation actions */
|
|
327
|
-
intentParams: y({ reducer:
|
|
327
|
+
intentParams: y({ reducer: B, default: () => ({ intent: "clarify" }) }),
|
|
328
328
|
/** The ID of the group that was created
|
|
329
329
|
* even though we already have this in the shared state
|
|
330
330
|
* we still need it here to also share between nodes
|
|
331
331
|
*/
|
|
332
|
-
createdGroupId: y({ reducer:
|
|
333
|
-
}),
|
|
332
|
+
createdGroupId: y({ reducer: B, default: () => "" })
|
|
333
|
+
}), Qt = () => new N(Z).addNode("detectGroupCreationIntent", Vt).addNode("createPortalGroup", Rt).addNode("addMembersToPortalGroup", zt).addNode("suggestCreatedGroupNavigation", Bt).addEdge(P, "detectGroupCreationIntent").addConditionalEdges("detectGroupCreationIntent", (t) => {
|
|
334
334
|
switch (t.intentParams.intent) {
|
|
335
335
|
case "create":
|
|
336
336
|
return "createPortalGroup";
|
|
@@ -339,27 +339,53 @@ User message:
|
|
|
339
339
|
default:
|
|
340
340
|
return w;
|
|
341
341
|
}
|
|
342
|
-
}).addEdge("createPortalGroup", "suggestCreatedGroupNavigation").addEdge("addMembersToPortalGroup", "suggestCreatedGroupNavigation").addEdge("suggestCreatedGroupNavigation", w),
|
|
342
|
+
}).addEdge("createPortalGroup", "suggestCreatedGroupNavigation").addEdge("addMembersToPortalGroup", "suggestCreatedGroupNavigation").addEdge("suggestCreatedGroupNavigation", w), Kt = String.raw`- **portal-group-creation** - Portal group creation assistant:
|
|
343
343
|
- creates a new ArcGIS Portal group for the signed-in user
|
|
344
344
|
- adds users to the newly created group using @mention usernames
|
|
345
|
-
`,
|
|
345
|
+
`, Jt = {
|
|
346
346
|
id: "portal-group-creation",
|
|
347
347
|
name: "Portal Group Creation",
|
|
348
|
-
description:
|
|
349
|
-
createGraph:
|
|
348
|
+
description: Kt,
|
|
349
|
+
createGraph: Qt,
|
|
350
350
|
workspace: Z
|
|
351
|
-
}, tt = "portalDocAssistantMemory",
|
|
351
|
+
}, tt = "portalDocAssistantMemory", Wt = () => ({ conversationId: "" }), Yt = (a) => {
|
|
352
352
|
const t = a?.[tt]?.value;
|
|
353
353
|
if (!t || typeof t != "object")
|
|
354
|
-
return
|
|
354
|
+
return Wt();
|
|
355
355
|
const e = t;
|
|
356
356
|
return {
|
|
357
357
|
conversationId: typeof e.conversationId == "string" ? e.conversationId : ""
|
|
358
358
|
};
|
|
359
359
|
}, Ht = (a) => ({
|
|
360
360
|
[tt]: { value: a }
|
|
361
|
-
})
|
|
362
|
-
|
|
361
|
+
}), Xt = {
|
|
362
|
+
rag: {
|
|
363
|
+
top_k: 20,
|
|
364
|
+
certainty_threshold: 0.7,
|
|
365
|
+
radius_of_surrounding_chunks: 2,
|
|
366
|
+
top_k_surrounding_chunks: 120,
|
|
367
|
+
extract_key_terms: !0
|
|
368
|
+
},
|
|
369
|
+
pipeline: {
|
|
370
|
+
conversation_history: {
|
|
371
|
+
allow: !0,
|
|
372
|
+
number_of_interactions_to_include: 4
|
|
373
|
+
},
|
|
374
|
+
conversation_title: { allow: !1 },
|
|
375
|
+
follow_up: { allow: !1 },
|
|
376
|
+
retrieved_chunks_in_response: { allow: !1 }
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
function Zt(a) {
|
|
380
|
+
return {
|
|
381
|
+
kind: "DocAIAssistantRequest",
|
|
382
|
+
filters: {
|
|
383
|
+
...Xt,
|
|
384
|
+
persona: { persona: a }
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
async function te({
|
|
363
389
|
portal: a,
|
|
364
390
|
question: t,
|
|
365
391
|
persona: e,
|
|
@@ -368,21 +394,18 @@ async function Xt({
|
|
|
368
394
|
skillId: l
|
|
369
395
|
}) {
|
|
370
396
|
l ??= "doc_ai_assistant";
|
|
371
|
-
const i = await
|
|
397
|
+
const c = Zt(e), i = await ee({
|
|
372
398
|
portal: a,
|
|
373
399
|
skillId: l,
|
|
374
400
|
message: t,
|
|
375
|
-
options: { context:
|
|
376
|
-
kind: "DocAIAssistantRequest",
|
|
377
|
-
filters: { persona: { persona: e } }
|
|
378
|
-
}, previousConversationId: s, signal: o }
|
|
401
|
+
options: { context: c, previousConversationId: s, signal: o }
|
|
379
402
|
});
|
|
380
403
|
return {
|
|
381
|
-
reply:
|
|
404
|
+
reply: ae(i, l),
|
|
382
405
|
conversationId: i[0]?.conversationId ?? ""
|
|
383
406
|
};
|
|
384
407
|
}
|
|
385
|
-
async function
|
|
408
|
+
async function ee({
|
|
386
409
|
portal: a,
|
|
387
410
|
skillId: t,
|
|
388
411
|
message: e,
|
|
@@ -408,7 +431,7 @@ async function Zt({
|
|
|
408
431
|
const u = i.data, r = [u], { conversationId: p, inquiryId: m } = u, d = async (h, f) => {
|
|
409
432
|
if (!f)
|
|
410
433
|
return;
|
|
411
|
-
await yt(
|
|
434
|
+
await yt(500);
|
|
412
435
|
const b = await F(l, {
|
|
413
436
|
method: "post",
|
|
414
437
|
body: JSON.stringify({ conversationId: p, inquiryId: m, ackSequenceNumber: h }),
|
|
@@ -424,7 +447,7 @@ async function Zt({
|
|
|
424
447
|
};
|
|
425
448
|
return u.hasMore && await d(u.sequenceNumber, u.hasMore), r;
|
|
426
449
|
}
|
|
427
|
-
function
|
|
450
|
+
function ae(a, t) {
|
|
428
451
|
switch (t) {
|
|
429
452
|
case "doc_chat":
|
|
430
453
|
return a.find((e) => e.message != null)?.message ?? "";
|
|
@@ -442,7 +465,7 @@ function te(a, t) {
|
|
|
442
465
|
return C(t);
|
|
443
466
|
}
|
|
444
467
|
}
|
|
445
|
-
const
|
|
468
|
+
const se = async (a, t) => {
|
|
446
469
|
await g({ text: "Asking documentation assistant...", agentName: "doc-assistant" }, t);
|
|
447
470
|
const e = x(a.agentExecutionContext.messages).trim();
|
|
448
471
|
if (!e)
|
|
@@ -452,12 +475,12 @@ const ee = async (a, t) => {
|
|
|
452
475
|
};
|
|
453
476
|
const s = t?.configurable?.context;
|
|
454
477
|
I(s);
|
|
455
|
-
const o =
|
|
478
|
+
const o = Yt(a.agentExecutionContext.sharedState), { reply: l, conversationId: c } = await te({
|
|
456
479
|
portal: s.portal,
|
|
457
480
|
question: e,
|
|
458
481
|
previousConversationId: o.conversationId || void 0,
|
|
459
482
|
skillId: "doc_ai_assistant",
|
|
460
|
-
persona: "
|
|
483
|
+
persona: "doc-online"
|
|
461
484
|
});
|
|
462
485
|
return {
|
|
463
486
|
status: "success",
|
|
@@ -466,7 +489,7 @@ const ee = async (a, t) => {
|
|
|
466
489
|
conversationId: c || o.conversationId
|
|
467
490
|
})
|
|
468
491
|
};
|
|
469
|
-
}, et =
|
|
492
|
+
}, et = Y(
|
|
470
493
|
async ({ groupTitle: a }, t) => {
|
|
471
494
|
const e = a.trim();
|
|
472
495
|
if (!e)
|
|
@@ -486,7 +509,7 @@ const ee = async (a, t) => {
|
|
|
486
509
|
groupTitle: n.string().describe("The portal group title to resolve to a group id.")
|
|
487
510
|
})
|
|
488
511
|
}
|
|
489
|
-
), at =
|
|
512
|
+
), at = Y(
|
|
490
513
|
async ({ itemTitle: a }, t) => {
|
|
491
514
|
const e = a.trim();
|
|
492
515
|
if (!e)
|
|
@@ -592,16 +615,16 @@ const st = {
|
|
|
592
615
|
hints: ["Organization settings", "Security", "Organization > Settings > Security"],
|
|
593
616
|
scope: "entity"
|
|
594
617
|
}
|
|
595
|
-
},
|
|
618
|
+
}, oe = wt(st), re = Object.entries(st).map(
|
|
596
619
|
([a, { description: t, hints: e, scope: s }]) => ` - ${a}: ${t} (scope: ${s}; hints: ${e.join(", ")})`
|
|
597
620
|
).join(`
|
|
598
|
-
`),
|
|
621
|
+
`), ne = `
|
|
599
622
|
You decide whether the assistant response should include a navigation action to ArcGIS Portal.
|
|
600
623
|
|
|
601
624
|
Given the user question and assistant response:
|
|
602
625
|
- Decide if a navigation action would help the user complete the task.
|
|
603
626
|
- If yes, choose one destination type:
|
|
604
|
-
${
|
|
627
|
+
${re}
|
|
605
628
|
|
|
606
629
|
Rules:
|
|
607
630
|
- Only suggest navigation when you are highly confident the destination will help complete the user's task.
|
|
@@ -624,21 +647,21 @@ User question:
|
|
|
624
647
|
|
|
625
648
|
Assistant response:
|
|
626
649
|
{response}
|
|
627
|
-
`,
|
|
650
|
+
`, Q = n.object({
|
|
628
651
|
shouldSuggestNavigation: n.boolean().default(!1),
|
|
629
|
-
destinationType: n.enum(["none", ...
|
|
652
|
+
destinationType: n.enum(["none", ...oe]).default("none"),
|
|
630
653
|
itemId: n.string().default(""),
|
|
631
654
|
groupId: n.string().default(""),
|
|
632
655
|
confidence: n.number().min(0).max(1).default(0)
|
|
633
|
-
}),
|
|
656
|
+
}), ie = async (a, t) => {
|
|
634
657
|
await g({ text: "Extracting navigation intent...", agentName: "doc-assistant" }, t);
|
|
635
658
|
const e = a.outputMessage.trim();
|
|
636
659
|
if (!e)
|
|
637
660
|
return {};
|
|
638
|
-
const s = x(a.agentExecutionContext.messages).trim(), o = await U.fromTemplate(
|
|
661
|
+
const s = x(a.agentExecutionContext.messages).trim(), o = await U.fromTemplate(ne).format({
|
|
639
662
|
question: s,
|
|
640
663
|
response: e
|
|
641
|
-
}), c = (await D({ modelTier: "fast" })).withStructuredOutput(
|
|
664
|
+
}), c = (await D({ modelTier: "fast" })).withStructuredOutput(Q), i = Q.parse(await c.invoke(o));
|
|
642
665
|
if (!i.shouldSuggestNavigation || i.destinationType === "none")
|
|
643
666
|
return {};
|
|
644
667
|
if (i.destinationType === "portal-item" && !i.itemId) {
|
|
@@ -649,10 +672,10 @@ Assistant response:
|
|
|
649
672
|
const r = G(s, "$") ?? G(s, "#");
|
|
650
673
|
r && (i.groupId = await et.invoke({ groupTitle: r }, t) ?? "");
|
|
651
674
|
}
|
|
652
|
-
const u =
|
|
675
|
+
const u = le(i);
|
|
653
676
|
return u ? (await R(u, t), {}) : {};
|
|
654
677
|
};
|
|
655
|
-
function
|
|
678
|
+
function le({
|
|
656
679
|
destinationType: a,
|
|
657
680
|
itemId: t,
|
|
658
681
|
groupId: e
|
|
@@ -685,18 +708,18 @@ function ne({
|
|
|
685
708
|
}
|
|
686
709
|
const ot = y.Root({
|
|
687
710
|
...k()
|
|
688
|
-
}),
|
|
711
|
+
}), ue = () => new N(ot).addNode("answerDocQuestion", se).addNode("extractNavigationIntent", ie).addEdge(P, "answerDocQuestion").addEdge("answerDocQuestion", "extractNavigationIntent").addEdge("extractNavigationIntent", w), ce = String.raw`- **portal-doc-assistant** - General ArcGIS documentation and Portal help assistant:
|
|
689
712
|
- answers general ArcGIS, Portal, Enterprise, and JavaScript SDK questions
|
|
690
713
|
- acts as a fallback when specialized agents are not applicable
|
|
691
|
-
`,
|
|
714
|
+
`, pe = {
|
|
692
715
|
id: "portal-doc-assistant",
|
|
693
716
|
name: "Portal Doc Assistant",
|
|
694
|
-
description:
|
|
695
|
-
createGraph:
|
|
717
|
+
description: ce,
|
|
718
|
+
createGraph: ue,
|
|
696
719
|
workspace: ot
|
|
697
|
-
},
|
|
720
|
+
}, de = () => ({ latestGroupId: null, memory: {} }), q = (a) => {
|
|
698
721
|
const t = a?.agentExecutionContext.sharedState.portalGroupSummaryMemory?.value;
|
|
699
|
-
return t ? { latestGroupId: t.latestGroupId, memory: t.memory } :
|
|
722
|
+
return t ? { latestGroupId: t.latestGroupId, memory: t.memory } : de();
|
|
700
723
|
}, rt = `
|
|
701
724
|
Shared markdown formatting rules:
|
|
702
725
|
- Use clear markdown headings (##) to separate sections.
|
|
@@ -704,7 +727,7 @@ Shared markdown formatting rules:
|
|
|
704
727
|
- Emphasize key metrics with bold labels (for example: **Recent items:** 4).
|
|
705
728
|
- Keep wording direct and analytical; avoid filler language but make sure the language is friendly.
|
|
706
729
|
- Do not include raw internal IDs unless explicitly requested.
|
|
707
|
-
`,
|
|
730
|
+
`, me = `
|
|
708
731
|
You answer follow-up questions about ArcGIS group analytics.
|
|
709
732
|
|
|
710
733
|
${rt}
|
|
@@ -729,14 +752,14 @@ Group full context:
|
|
|
729
752
|
|
|
730
753
|
Question:
|
|
731
754
|
{question}
|
|
732
|
-
`,
|
|
755
|
+
`, ge = async (a, t) => {
|
|
733
756
|
await g({ text: "Answering group follow-up...", agentName: "group-analytics" }, t);
|
|
734
|
-
const e =
|
|
757
|
+
const e = q(a), s = a.groupSummaryGroupId ?? e.latestGroupId, o = s ? e.memory[s] : void 0, l = a.groupSummaryQuestion || x(a.agentExecutionContext.messages);
|
|
735
758
|
return o ? {
|
|
736
759
|
status: "success",
|
|
737
760
|
outputMessage: (await v({
|
|
738
|
-
promptText:
|
|
739
|
-
schema:
|
|
761
|
+
promptText: me,
|
|
762
|
+
schema: he,
|
|
740
763
|
modelTier: "default",
|
|
741
764
|
inputVariables: {
|
|
742
765
|
summary: o.summary,
|
|
@@ -748,10 +771,10 @@ Question:
|
|
|
748
771
|
status: "success",
|
|
749
772
|
outputMessage: "I do not have group analytics context yet. Ask me to analyze a group first with analyze group <group id>."
|
|
750
773
|
};
|
|
751
|
-
},
|
|
774
|
+
}, he = n.object({
|
|
752
775
|
answer: n.string(),
|
|
753
776
|
isRelevant: n.boolean()
|
|
754
|
-
}),
|
|
777
|
+
}), fe = `
|
|
755
778
|
Classify the user's request for ArcGIS Portal group analytics.
|
|
756
779
|
|
|
757
780
|
Rules:
|
|
@@ -780,12 +803,12 @@ hasAnalyticsContext:
|
|
|
780
803
|
|
|
781
804
|
User message:
|
|
782
805
|
{userMessage}
|
|
783
|
-
`,
|
|
806
|
+
`, ye = async (a, t) => {
|
|
784
807
|
await g({ text: "Analyzing group-analytics intent...", agentName: "group-analytics" }, t);
|
|
785
|
-
const e = x(a.agentExecutionContext.messages), s = !!
|
|
808
|
+
const e = x(a.agentExecutionContext.messages), s = !!q(a).latestGroupId, o = await U.fromTemplate(fe).format({
|
|
786
809
|
userMessage: e,
|
|
787
810
|
hasAnalyticsContext: String(s)
|
|
788
|
-
}), c = (await D({ modelTier: "fast" })).withStructuredOutput(
|
|
811
|
+
}), c = (await D({ modelTier: "fast" })).withStructuredOutput(K), i = K.parse(await c.invoke(o));
|
|
789
812
|
let u = i.groupId;
|
|
790
813
|
if ((i.intent === "summarize" || i.intent === "navigation") && !u) {
|
|
791
814
|
const f = G(e, "$");
|
|
@@ -799,12 +822,12 @@ User message:
|
|
|
799
822
|
status: "success",
|
|
800
823
|
outputMessage: h ? "Please clarify with a group id or title" : ""
|
|
801
824
|
};
|
|
802
|
-
},
|
|
825
|
+
}, K = n.object({
|
|
803
826
|
intent: n.enum(["summarize", "followUp", "navigation", "clarify"]),
|
|
804
827
|
groupId: n.string().default(""),
|
|
805
828
|
question: n.string().default("")
|
|
806
|
-
}),
|
|
807
|
-
const e =
|
|
829
|
+
}), we = async (a, t) => {
|
|
830
|
+
const e = q(a), s = a.groupSummaryGroupId ?? e.latestGroupId;
|
|
808
831
|
return await g({ text: "Preparing navigation...", agentName: "group-analytics" }, t), await R(
|
|
809
832
|
s ? { destinationType: "portal-group", groupId: s } : { destinationType: "portal-groups" },
|
|
810
833
|
t
|
|
@@ -813,8 +836,8 @@ User message:
|
|
|
813
836
|
function nt({ timestamp: a, now: t, windowMs: e }) {
|
|
814
837
|
return a ? t - a <= e : !1;
|
|
815
838
|
}
|
|
816
|
-
const
|
|
817
|
-
function
|
|
839
|
+
const be = 720 * 60 * 60 * 1e3;
|
|
840
|
+
function ve(a) {
|
|
818
841
|
const t = Gt(a);
|
|
819
842
|
return {
|
|
820
843
|
id: a.id ?? "",
|
|
@@ -840,7 +863,7 @@ function we(a) {
|
|
|
840
863
|
}
|
|
841
864
|
};
|
|
842
865
|
}
|
|
843
|
-
async function
|
|
866
|
+
async function Ie(a) {
|
|
844
867
|
const t = { owner: a.owner ?? "", admins: [], users: [] };
|
|
845
868
|
try {
|
|
846
869
|
return await a.fetchMembers();
|
|
@@ -848,7 +871,7 @@ async function be(a) {
|
|
|
848
871
|
return console.warn("Unable to fetch group members for analytics context", e), t;
|
|
849
872
|
}
|
|
850
873
|
}
|
|
851
|
-
function
|
|
874
|
+
function xe(a) {
|
|
852
875
|
return a.map((t) => ({
|
|
853
876
|
id: t.id ?? "",
|
|
854
877
|
title: t.title ?? "Untitled",
|
|
@@ -858,40 +881,40 @@ function ve(a) {
|
|
|
858
881
|
modified: t.modified?.getTime()
|
|
859
882
|
}));
|
|
860
883
|
}
|
|
861
|
-
function
|
|
884
|
+
function Se(a, t) {
|
|
862
885
|
return a.filter(
|
|
863
|
-
(e) => e.modified ? nt({ timestamp: e.modified, now: t, windowMs:
|
|
886
|
+
(e) => e.modified ? nt({ timestamp: e.modified, now: t, windowMs: be }) : !1
|
|
864
887
|
);
|
|
865
888
|
}
|
|
866
|
-
function
|
|
889
|
+
function Me(a) {
|
|
867
890
|
const t = /* @__PURE__ */ new Map();
|
|
868
891
|
for (const e of a)
|
|
869
892
|
t.set(e.type, (t.get(e.type) ?? 0) + 1);
|
|
870
893
|
return [...t.entries()].sort((e, s) => s[1] - e[1] || e[0].localeCompare(s[0])).slice(0, 6).map(([e, s]) => ({ type: e, count: s }));
|
|
871
894
|
}
|
|
872
|
-
async function
|
|
873
|
-
const t = await a.queryItems({ num: 20, sortField: "modified", sortOrder: "desc" }), e =
|
|
895
|
+
async function Ge(a) {
|
|
896
|
+
const t = await a.queryItems({ num: 20, sortField: "modified", sortOrder: "desc" }), e = xe(t.results), s = Date.now();
|
|
874
897
|
return {
|
|
875
898
|
total: t.total,
|
|
876
899
|
topItems: e,
|
|
877
|
-
recentlyModifiedItems:
|
|
878
|
-
topItemTypes:
|
|
900
|
+
recentlyModifiedItems: Se(e, s),
|
|
901
|
+
topItemTypes: Me(e)
|
|
879
902
|
};
|
|
880
903
|
}
|
|
881
|
-
async function
|
|
904
|
+
async function Te(a, t) {
|
|
882
905
|
if (!t)
|
|
883
906
|
return { error: { code: "missingGroupId", message: "Group id is required." } };
|
|
884
907
|
try {
|
|
885
908
|
const s = (await a.queryGroups({ query: `id:${t}`, num: 1 })).results[0];
|
|
886
909
|
if (!s)
|
|
887
910
|
return { error: { code: "groupNotFound", message: `No group found for id: ${t}` } };
|
|
888
|
-
const o =
|
|
911
|
+
const o = ve(s), l = await Ie(s), c = await Ge(s);
|
|
889
912
|
return { result: { group: o, members: l, items: c } };
|
|
890
913
|
} catch (e) {
|
|
891
914
|
return console.error("Error fetching portal group analytics context:", e), { error: { code: "unhandledError" } };
|
|
892
915
|
}
|
|
893
916
|
}
|
|
894
|
-
const
|
|
917
|
+
const Ae = `
|
|
895
918
|
You summarize ArcGIS Portal groups based on structured context and deterministic activity signals.
|
|
896
919
|
|
|
897
920
|
${rt}
|
|
@@ -930,7 +953,7 @@ Group context:
|
|
|
930
953
|
|
|
931
954
|
Deterministic signals:
|
|
932
955
|
{deterministicSignals}
|
|
933
|
-
`,
|
|
956
|
+
`, Ce = 2160 * 60 * 60 * 1e3, Ne = async (a, t) => {
|
|
934
957
|
const e = a.groupSummaryGroupId;
|
|
935
958
|
if (!e)
|
|
936
959
|
return {
|
|
@@ -940,15 +963,15 @@ Deterministic signals:
|
|
|
940
963
|
await g({ text: `Analyzing group ${e}...`, agentName: "group-analytics" }, t);
|
|
941
964
|
const s = t?.configurable?.context;
|
|
942
965
|
I(s);
|
|
943
|
-
const { result: o, error: l } = await
|
|
966
|
+
const { result: o, error: l } = await Te(s.portal, e);
|
|
944
967
|
if (l || !o)
|
|
945
968
|
return await g({ text: "Failed to fetch group context", agentName: "group-analytics" }, t), {
|
|
946
969
|
status: "success",
|
|
947
970
|
outputMessage: "Unable to retrieve group context for analytics."
|
|
948
971
|
};
|
|
949
|
-
const { group: c, items: i } = o, u = Date.now(), r = c.modified, p = r ? nt({ timestamp: r, now: u, windowMs:
|
|
950
|
-
promptText:
|
|
951
|
-
schema:
|
|
972
|
+
const { group: c, items: i } = o, u = Date.now(), r = c.modified, p = r ? nt({ timestamp: r, now: u, windowMs: Ce }) : !1, m = i.recentlyModifiedItems.length, d = m > 0, h = p || d, f = await v({
|
|
973
|
+
promptText: Ae,
|
|
974
|
+
schema: Pe,
|
|
952
975
|
modelTier: "default",
|
|
953
976
|
inputVariables: {
|
|
954
977
|
context: JSON.stringify(o),
|
|
@@ -959,7 +982,7 @@ Deterministic signals:
|
|
|
959
982
|
recentItemCount: m
|
|
960
983
|
})
|
|
961
984
|
}
|
|
962
|
-
}), { followUpQuestions: b, summary: S } = f, ut =
|
|
985
|
+
}), { followUpQuestions: b, summary: S } = f, ut = q(a), ct = {
|
|
963
986
|
latestGroupId: e,
|
|
964
987
|
memory: {
|
|
965
988
|
...ut.memory,
|
|
@@ -971,41 +994,41 @@ Deterministic signals:
|
|
|
971
994
|
outputMessage: S,
|
|
972
995
|
sharedStatePatch: { portalGroupSummaryMemory: { value: ct } }
|
|
973
996
|
};
|
|
974
|
-
},
|
|
997
|
+
}, Pe = n.object({
|
|
975
998
|
summary: n.string(),
|
|
976
999
|
followUpQuestions: n.array(n.string()).default([])
|
|
977
|
-
}),
|
|
1000
|
+
}), z = (a, t) => t ?? a, it = y.Root({
|
|
978
1001
|
...k(),
|
|
979
1002
|
groupSummaryIntent: y({
|
|
980
|
-
reducer:
|
|
1003
|
+
reducer: z,
|
|
981
1004
|
default: () => "clarify"
|
|
982
1005
|
}),
|
|
983
1006
|
groupSummaryGroupId: y({
|
|
984
|
-
reducer:
|
|
1007
|
+
reducer: z,
|
|
985
1008
|
default: () => null
|
|
986
1009
|
}),
|
|
987
1010
|
groupSummaryQuestion: y({
|
|
988
|
-
reducer:
|
|
1011
|
+
reducer: z,
|
|
989
1012
|
default: () => ""
|
|
990
1013
|
})
|
|
991
|
-
}),
|
|
1014
|
+
}), ke = () => new N(it).addNode("detectGroupSummaryIntent", ye).addNode("summarizePortalGroup", Ne).addNode("answerGroupSummaryFollowUp", ge).addNode("suggestGroupSummaryNavigation", we).addEdge(P, "detectGroupSummaryIntent").addConditionalEdges("detectGroupSummaryIntent", (t) => t.groupSummaryIntent === "summarize" ? "summarizePortalGroup" : t.groupSummaryIntent === "followUp" ? "answerGroupSummaryFollowUp" : t.groupSummaryIntent === "navigation" ? "suggestGroupSummaryNavigation" : w).addEdge("summarizePortalGroup", w).addEdge("answerGroupSummaryFollowUp", w).addEdge("suggestGroupSummaryNavigation", w), qe = String.raw`- **portal-group-analytics** - Portal group analytics assistant:
|
|
992
1015
|
- summarizes ArcGIS portal groups from group context and sourceJSON details
|
|
993
1016
|
- answers follow-up questions grounded in the summarized group
|
|
994
1017
|
- suggests navigation to groups when relevant
|
|
995
|
-
`,
|
|
1018
|
+
`, ze = {
|
|
996
1019
|
id: "portal-group-analytics",
|
|
997
1020
|
name: "Portal Group Analytics",
|
|
998
|
-
description:
|
|
999
|
-
createGraph:
|
|
1021
|
+
description: qe,
|
|
1022
|
+
createGraph: ke,
|
|
1000
1023
|
workspace: it
|
|
1001
|
-
},
|
|
1024
|
+
}, $e = () => ({ latestItemId: null, memory: {} }), O = (a) => {
|
|
1002
1025
|
const t = a?.agentExecutionContext.sharedState.portalItemAnalyticsSummaryMemory?.value;
|
|
1003
|
-
return t ? { latestItemId: t.latestItemId, memory: t.memory } :
|
|
1004
|
-
},
|
|
1026
|
+
return t ? { latestItemId: t.latestItemId, memory: t.memory } : $e();
|
|
1027
|
+
}, J = n.object({
|
|
1005
1028
|
intent: n.enum(["summarize", "followUp", "clarify"]),
|
|
1006
1029
|
itemId: n.string().default(""),
|
|
1007
1030
|
question: n.string().default("")
|
|
1008
|
-
}),
|
|
1031
|
+
}), Ee = n.object({ summary: n.string(), followUpQuestions: n.array(n.string()).default([]) }), De = n.object({ answer: n.string(), isRelevant: n.boolean() }), Ue = `
|
|
1009
1032
|
You answer follow-up questions about an ArcGIS item.
|
|
1010
1033
|
|
|
1011
1034
|
Ground your answer in the provided item context.
|
|
@@ -1025,14 +1048,14 @@ Item full context
|
|
|
1025
1048
|
|
|
1026
1049
|
Question:
|
|
1027
1050
|
{question}
|
|
1028
|
-
`,
|
|
1051
|
+
`, Re = async (a, t) => {
|
|
1029
1052
|
await g({ text: "Answering follow-up...", agentName: "analytics" }, t);
|
|
1030
1053
|
const e = O(a), s = a.analyticsItemId ?? e.latestItemId, o = s ? e.memory[s] : void 0, l = a.analyticsQuestion || x(a.agentExecutionContext.messages);
|
|
1031
1054
|
return o ? {
|
|
1032
1055
|
status: "success",
|
|
1033
1056
|
outputMessage: (await v({
|
|
1034
|
-
promptText:
|
|
1035
|
-
schema:
|
|
1057
|
+
promptText: Ue,
|
|
1058
|
+
schema: De,
|
|
1036
1059
|
modelTier: "default",
|
|
1037
1060
|
inputVariables: {
|
|
1038
1061
|
summary: o.summary,
|
|
@@ -1044,7 +1067,7 @@ Question:
|
|
|
1044
1067
|
status: "success",
|
|
1045
1068
|
outputMessage: "I don't have enough information yet. Please ask me to summarize the item first using summarize item <item id>."
|
|
1046
1069
|
};
|
|
1047
|
-
},
|
|
1070
|
+
}, Oe = `
|
|
1048
1071
|
Classify the user analytics request.
|
|
1049
1072
|
|
|
1050
1073
|
Rules:
|
|
@@ -1074,12 +1097,12 @@ hasSummaryContext:
|
|
|
1074
1097
|
|
|
1075
1098
|
User message:
|
|
1076
1099
|
{userMessage}
|
|
1077
|
-
`,
|
|
1100
|
+
`, Fe = async (a, t) => {
|
|
1078
1101
|
await g({ text: "Analyzing intent...", agentName: "analytics" }, t);
|
|
1079
|
-
const e = x(a.agentExecutionContext.messages), s = !!O(a).latestItemId, o = await U.fromTemplate(
|
|
1102
|
+
const e = x(a.agentExecutionContext.messages), s = !!O(a).latestItemId, o = await U.fromTemplate(Oe).format({
|
|
1080
1103
|
userMessage: e,
|
|
1081
1104
|
hasSummaryContext: String(s)
|
|
1082
|
-
}), c = (await D({ modelTier: "fast" })).withStructuredOutput(
|
|
1105
|
+
}), c = (await D({ modelTier: "fast" })).withStructuredOutput(J), i = J.parse(await c.invoke(o));
|
|
1083
1106
|
let u = i.itemId;
|
|
1084
1107
|
if (i.intent === "summarize" && !u) {
|
|
1085
1108
|
const f = G(e, "#");
|
|
@@ -1094,7 +1117,7 @@ User message:
|
|
|
1094
1117
|
status: "success",
|
|
1095
1118
|
outputMessage: h ? 'Please clarify with summarize item <item id>, summarize item #<title>, or summarize item #"<title with spaces>".' : ""
|
|
1096
1119
|
};
|
|
1097
|
-
},
|
|
1120
|
+
}, Ve = `
|
|
1098
1121
|
You are a item summary tool for ArcGIS. Your job is to summarize an item's info based on the provided context.
|
|
1099
1122
|
Summary rules:
|
|
1100
1123
|
- The summary should be concise markdown, make sure to format the output nicely so it's easy to read.
|
|
@@ -1109,7 +1132,7 @@ Do not include internal identifiers.
|
|
|
1109
1132
|
If the user asks for a detailed summary, you may expand the response up to 300 words.
|
|
1110
1133
|
Item context:
|
|
1111
1134
|
{context}
|
|
1112
|
-
`,
|
|
1135
|
+
`, je = async (a, t) => {
|
|
1113
1136
|
const e = a.analyticsItemId;
|
|
1114
1137
|
if (!e)
|
|
1115
1138
|
return {
|
|
@@ -1126,8 +1149,8 @@ Item context:
|
|
|
1126
1149
|
outputMessage: "Unable to retrieve item context for summarization."
|
|
1127
1150
|
};
|
|
1128
1151
|
const { context: u } = c, r = await v({
|
|
1129
|
-
promptText:
|
|
1130
|
-
schema:
|
|
1152
|
+
promptText: Ve,
|
|
1153
|
+
schema: Ee,
|
|
1131
1154
|
modelTier: "default",
|
|
1132
1155
|
inputVariables: { context: JSON.stringify(u) }
|
|
1133
1156
|
}), { followUpQuestions: p, summary: m } = r, d = O(a), h = {
|
|
@@ -1157,19 +1180,19 @@ Item context:
|
|
|
1157
1180
|
reducer: $,
|
|
1158
1181
|
default: () => ""
|
|
1159
1182
|
})
|
|
1160
|
-
}),
|
|
1183
|
+
}), _e = () => new N(lt).addNode("detectAnalyticsIntent", Fe).addNode("summarizePortalItem", je).addNode("answerAnalyticsFollowUp", Re).addEdge(P, "detectAnalyticsIntent").addConditionalEdges("detectAnalyticsIntent", (t) => t.analyticsIntent === "summarize" ? "summarizePortalItem" : t.analyticsIntent === "followUp" ? "answerAnalyticsFollowUp" : w).addEdge("summarizePortalItem", w).addEdge("answerAnalyticsFollowUp", w), Le = String.raw`- **portal-item-analytics** - Portal item analytics assistant:
|
|
1161
1184
|
- answers questions about one specific ArcGIS portal item when item context is present
|
|
1162
1185
|
- summarizes item details, metadata, and context grounded in that item
|
|
1163
1186
|
- suggests follow-up prompts grounded in the same item
|
|
1164
1187
|
- use for item-specific requests, not for gallery browsing, featured content, or opening Map Viewer
|
|
1165
|
-
`,
|
|
1188
|
+
`, Be = {
|
|
1166
1189
|
id: "portal-item-analytics",
|
|
1167
1190
|
name: "Portal Item Analytics",
|
|
1168
|
-
description:
|
|
1169
|
-
createGraph:
|
|
1191
|
+
description: Le,
|
|
1192
|
+
createGraph: _e,
|
|
1170
1193
|
workspace: lt
|
|
1171
|
-
},
|
|
1172
|
-
function
|
|
1194
|
+
}, Qe = gt`: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)}`;
|
|
1195
|
+
function Ke(a, t) {
|
|
1173
1196
|
if (!t)
|
|
1174
1197
|
return;
|
|
1175
1198
|
const { destinationType: e } = a;
|
|
@@ -1197,11 +1220,11 @@ function Qe(a, t) {
|
|
|
1197
1220
|
return C(e);
|
|
1198
1221
|
}
|
|
1199
1222
|
}
|
|
1200
|
-
function
|
|
1201
|
-
const t =
|
|
1223
|
+
function Je(a) {
|
|
1224
|
+
const t = Lt.safeParse(a);
|
|
1202
1225
|
return t.success ? t.data : void 0;
|
|
1203
1226
|
}
|
|
1204
|
-
class
|
|
1227
|
+
class We extends dt {
|
|
1205
1228
|
constructor() {
|
|
1206
1229
|
super(...arguments), this.t9n = ft({ blocking: !0 }), this.assistantEl = T(), this.formEl = T(), this.voiceInputEl = T(), this.inputEl = T(), this.navigationSlotElements = /* @__PURE__ */ new Map(), this.handleSlottableRequest = (t) => {
|
|
1207
1230
|
const e = t.detail, s = e.data?.block;
|
|
@@ -1215,15 +1238,15 @@ class Je extends dt {
|
|
|
1215
1238
|
this.properties = { inputText: 16, showVoiceInput: 16, isListening: 16, isVoiceInputDisabled: 16, interrupt: 16, autoDestroyDisabled: 5, portal: 0, user: 0, config: 0, navigationTargetMap: 0, defaultClosed: 5 };
|
|
1216
1239
|
}
|
|
1217
1240
|
static {
|
|
1218
|
-
this.styles =
|
|
1241
|
+
this.styles = Qe;
|
|
1219
1242
|
}
|
|
1220
1243
|
getNavigationAction(t) {
|
|
1221
1244
|
if (t?.type !== X)
|
|
1222
1245
|
return;
|
|
1223
|
-
const e =
|
|
1246
|
+
const e = Je(t.data);
|
|
1224
1247
|
if (!e)
|
|
1225
1248
|
return;
|
|
1226
|
-
const s =
|
|
1249
|
+
const s = Ke(e, this.navigationTargetMap);
|
|
1227
1250
|
if (s)
|
|
1228
1251
|
return { href: s, targetDetail: e, label: this.getNavigationText(e.destinationType) };
|
|
1229
1252
|
}
|
|
@@ -1310,14 +1333,14 @@ class Je extends dt {
|
|
|
1310
1333
|
this.isVoiceInputDisabled = !0;
|
|
1311
1334
|
const r = this.voiceInputEl.value;
|
|
1312
1335
|
i ? await r?.stopListening() : await r?.startListening();
|
|
1313
|
-
}}></calcite-button>` || ""}<calcite-button type=submit icon-start=send round .disabled=${!e.trim()} .label=${t.send}>${t.send}</calcite-button></div></form><arcgis-assistant-agent .agent=${
|
|
1336
|
+
}}></calcite-button>` || ""}<calcite-button type=submit icon-start=send round .disabled=${!e.trim()} .label=${t.send}>${t.send}</calcite-button></div></form><arcgis-assistant-agent .agent=${Be} .context=${{ portal: s, user: o, navigationTargetMap: l }}></arcgis-assistant-agent><arcgis-assistant-agent .agent=${Jt} .context=${{ portal: s, user: o, navigationTargetMap: l }}></arcgis-assistant-agent><arcgis-assistant-agent .agent=${pe} .context=${{ portal: s, user: o, navigationTargetMap: l }}></arcgis-assistant-agent><arcgis-assistant-agent .agent=${ze} .context=${{ portal: s, user: o, navigationTargetMap: l }}></arcgis-assistant-agent>${this.interrupt && M`<arcgis-portal-ai-assistant-interrupt slot=interrupt .type=${this.interrupt.type} .message=${this.interrupt.message} .options=${this.interrupt.options} @arcgisSubmit=${({ detail: r }) => {
|
|
1314
1337
|
this.assistantEl.value?.submitInterrupt(r);
|
|
1315
1338
|
}} @arcgisCancel=${() => {
|
|
1316
1339
|
this.assistantEl.value?.cancelInterrupt();
|
|
1317
1340
|
}}></arcgis-portal-ai-assistant-interrupt>` || ""}</arcgis-assistant>`;
|
|
1318
1341
|
}
|
|
1319
1342
|
}
|
|
1320
|
-
pt("arcgis-portal-ai-assistant",
|
|
1343
|
+
pt("arcgis-portal-ai-assistant", We);
|
|
1321
1344
|
export {
|
|
1322
|
-
|
|
1345
|
+
We as ArcgisPortalAiAssistant
|
|
1323
1346
|
};
|