@arcgis/portal-components 5.2.0-next.11 → 5.2.0-next.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn/{ROCZLAYA.js → 2RGMWFHB.js} +1 -1
- package/dist/cdn/{2X4VWQ5E.js → 3KS5IDT2.js} +1 -1
- package/dist/cdn/{XLHPYPQY.js → 47NPIL2S.js} +1 -1
- package/dist/cdn/{YKHMRMUE.js → 5VHBNEN3.js} +1 -1
- package/dist/cdn/{DB6O5DIG.js → DBKSQGEI.js} +1 -1
- package/dist/cdn/{W3ZB6MHE.js → EETBNQU2.js} +1 -1
- package/dist/cdn/{VHSATYO4.js → EHRAFAEA.js} +1 -1
- package/dist/cdn/{GS6MPCDK.js → EKO6SVAF.js} +1 -1
- package/dist/cdn/{MLPVRTHY.js → FI45QCN2.js} +1 -1
- package/dist/cdn/{2CA7QHVV.js → FQ25WMSY.js} +1 -1
- package/dist/cdn/{JVKWYKZR.js → GEIZTD7F.js} +1 -1
- package/dist/cdn/{2V5S6KBL.js → HGSK6OFA.js} +1 -1
- package/dist/cdn/{4BGBBW4V.js → HIRM34QB.js} +1 -1
- package/dist/cdn/HMBSJR37.js +2 -0
- package/dist/cdn/KT7PE6UE.js +2 -0
- package/dist/cdn/{XFFD6YY5.js → KY7Q7DH3.js} +1 -1
- package/dist/cdn/{IKOAI6C7.js → KZWW4BWJ.js} +1 -1
- package/dist/cdn/{4VRIZNFA.js → MLTQECPL.js} +1 -1
- package/dist/cdn/{VQU2EEJR.js → OKRYML2G.js} +1 -1
- package/dist/cdn/PDL3DPMG.js +2 -0
- package/dist/cdn/{Z73H62GB.js → QJ2UHWPU.js} +1 -1
- package/dist/cdn/{KL4LVBFR.js → R4ZSXOQH.js} +142 -142
- package/dist/cdn/{QGFU75HM.js → VXCB2YBR.js} +1 -1
- package/dist/cdn/{BMUU2S5H.js → WJ2NMHDE.js} +1 -1
- package/dist/cdn/{QN3ZQLFB.js → YECI7XG3.js} +1 -1
- package/dist/cdn/{SB25M4FP.js → ZDLFZJBT.js} +1 -1
- package/dist/cdn/index.js +1 -1
- package/dist/chunks/{groups2.js → item2.js} +28 -28
- package/dist/components/arcgis-portal-ai-assistant/agents/types.d.ts +11 -2
- package/dist/components/arcgis-portal-ai-assistant/customElement.d.ts +4 -2
- package/dist/components/arcgis-portal-ai-assistant/customElement.js +436 -432
- package/dist/components/arcgis-portal-mentionable-text-area/customElement.js +1 -1
- package/dist/docs/api.json +1 -1
- package/dist/docs/docs.json +1 -1
- package/dist/docs/web-types.json +1 -1
- package/dist/loader.js +1 -1
- package/dist/types/lumina.d.ts +1 -1
- package/dist/types/preact.d.ts +1 -1
- package/dist/types/react.d.ts +1 -1
- package/dist/types/stencil.d.ts +1 -1
- package/package.json +4 -4
- package/dist/cdn/CTVWAEEO.js +0 -2
- package/dist/cdn/G3AK2CRM.js +0 -2
- package/dist/cdn/OMD65KRY.js +0 -2
|
@@ -1,229 +1,32 @@
|
|
|
1
1
|
/* COPYRIGHT Esri - https://js.arcgis.com/5.2/LICENSE.txt */
|
|
2
|
-
import { c as
|
|
3
|
-
import { LitElement as
|
|
4
|
-
import { css as
|
|
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";
|
|
5
5
|
import { createRef as M, ref as A } from "lit/directives/ref.js";
|
|
6
|
-
import { u as
|
|
7
|
-
import { a as T, t as
|
|
8
|
-
import { Annotation as
|
|
9
|
-
import { sendTraceMessage as g, invokeStructuredPrompt as b,
|
|
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";
|
|
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
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";
|
|
11
14
|
import { ChatPromptTemplate as z } from "@langchain/core/prompts";
|
|
12
15
|
import { createAgent as U } from "langchain";
|
|
13
16
|
import { tool as W } from "@langchain/core/tools";
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
import { Annotation as It } from "@langchain/langgraph";
|
|
18
|
-
import { c as xt, d as vt, i as St, b as Gt, g as Mt } from "../../chunks/groups.js";
|
|
19
|
-
const I = (e) => {
|
|
20
|
-
for (let t = e.length - 1; t >= 0; t -= 1) {
|
|
21
|
-
const s = e[t];
|
|
22
|
-
if (s.type !== "human")
|
|
23
|
-
continue;
|
|
24
|
-
const a = s.content;
|
|
25
|
-
if (typeof a == "string")
|
|
26
|
-
return a;
|
|
27
|
-
if (Array.isArray(a))
|
|
28
|
-
return a.map(
|
|
29
|
-
(r) => typeof r == "string" ? r : "text" in r && typeof r.text == "string" ? r.text : ""
|
|
30
|
-
).join(" ").trim();
|
|
31
|
-
}
|
|
32
|
-
return "";
|
|
33
|
-
}, At = () => ({ latestItemId: null, memory: {} }), R = (e) => {
|
|
34
|
-
const t = e?.agentExecutionContext.sharedState.portalItemAnalyticsSummaryMemory?.value;
|
|
35
|
-
return t ? { latestItemId: t.latestItemId, memory: t.memory } : At();
|
|
36
|
-
}, Tt = o.object({
|
|
37
|
-
intent: o.enum(["summarize", "followUp", "clarify"]),
|
|
38
|
-
itemId: o.string().default(""),
|
|
39
|
-
question: o.string().default("")
|
|
40
|
-
}), Ct = o.object({ summary: o.string(), followUpQuestions: o.array(o.string()).default([]) }), Pt = o.object({ answer: o.string(), isRelevant: o.boolean() }), Nt = async (e, t) => {
|
|
41
|
-
await g({ text: "Answering follow-up...", agentName: "analytics" }, t);
|
|
42
|
-
const s = R(e), a = e.analyticsItemId ?? s.latestItemId, r = a ? s.memory[a] : void 0, u = e.analyticsQuestion || I(e.agentExecutionContext.messages);
|
|
43
|
-
return r ? {
|
|
44
|
-
status: "success",
|
|
45
|
-
outputMessage: (await b({
|
|
46
|
-
promptText: $t,
|
|
47
|
-
schema: Pt,
|
|
48
|
-
modelTier: "default",
|
|
49
|
-
inputVariables: {
|
|
50
|
-
summary: r.summary,
|
|
51
|
-
question: u,
|
|
52
|
-
fullContext: JSON.stringify(r.fullContext)
|
|
53
|
-
}
|
|
54
|
-
})).answer
|
|
55
|
-
} : {
|
|
56
|
-
status: "success",
|
|
57
|
-
outputMessage: "I don't have enough information yet. Please ask me to summarize the item first using summarize item <item id>."
|
|
58
|
-
};
|
|
59
|
-
}, $t = `
|
|
60
|
-
You answer follow-up questions about an ArcGIS item.
|
|
61
|
-
|
|
62
|
-
Ground your answer in the provided item context.
|
|
63
|
-
If the answer is not available from the provided context, state that clearly and suggest what to check next.
|
|
64
|
-
|
|
65
|
-
Response rules:
|
|
66
|
-
- Reply in concise markdown.
|
|
67
|
-
- Keep the answer focused on the follow-up question.
|
|
68
|
-
- Do not include internal identifiers.
|
|
69
|
-
- Mark isRelevant=false when the question is not about this item or cannot be grounded in this item context.
|
|
70
|
-
|
|
71
|
-
Item summary:
|
|
72
|
-
{summary}
|
|
73
|
-
|
|
74
|
-
Item full context
|
|
75
|
-
{fullContext}
|
|
76
|
-
|
|
77
|
-
Question:
|
|
78
|
-
{question}
|
|
79
|
-
`;
|
|
80
|
-
function x(e) {
|
|
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";
|
|
19
|
+
const Y = (e) => {
|
|
81
20
|
const { portal: t, user: s } = e ?? {};
|
|
82
|
-
|
|
21
|
+
return !!e && !!t && !!s;
|
|
22
|
+
};
|
|
23
|
+
function I(e) {
|
|
24
|
+
if (!Y(e))
|
|
83
25
|
throw new Error("Invalid context: PortalAssistantContext with portal and user is required.");
|
|
84
26
|
}
|
|
85
|
-
const
|
|
86
|
-
async ({ itemTitle: e }, t) => {
|
|
87
|
-
const s = e.trim();
|
|
88
|
-
if (!s)
|
|
89
|
-
return null;
|
|
90
|
-
const a = t?.configurable?.context;
|
|
91
|
-
x(a);
|
|
92
|
-
const { result: r, error: u } = await gt(a.portal, s, { num: 1 });
|
|
93
|
-
return u && console.error("Error searching for portal item by title:", u), r?.results[0]?.id || null;
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
name: "resolvePortalItemIdByTitle",
|
|
97
|
-
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.',
|
|
98
|
-
schema: o.object({
|
|
99
|
-
itemTitle: o.string().describe("The portal item title to resolve to an item id.")
|
|
100
|
-
})
|
|
101
|
-
}
|
|
102
|
-
), qt = async (e, t) => {
|
|
103
|
-
await g({ text: "Analyzing intent...", agentName: "analytics" }, t);
|
|
104
|
-
const s = I(e.agentExecutionContext.messages), a = !!R(e).latestItemId, r = await z.fromTemplate(kt).format({
|
|
105
|
-
userMessage: s,
|
|
106
|
-
hasSummaryContext: String(a)
|
|
107
|
-
}), l = await U({
|
|
108
|
-
model: await E({ modelTier: "fast" }),
|
|
109
|
-
tools: [Y],
|
|
110
|
-
systemPrompt: r,
|
|
111
|
-
responseFormat: Tt,
|
|
112
|
-
checkpointer: !0
|
|
113
|
-
}).invoke({ messages: e.agentExecutionContext.messages }, t), { intent: i, itemId: n, question: c } = l.structuredResponse, m = i === "clarify" || i === "summarize" && !n || i === "followUp" && !c;
|
|
114
|
-
return {
|
|
115
|
-
agentExecutionContext: { ...e.agentExecutionContext },
|
|
116
|
-
analyticsIntent: m ? "clarify" : i,
|
|
117
|
-
analyticsItemId: n || null,
|
|
118
|
-
analyticsQuestion: c || "",
|
|
119
|
-
status: "success",
|
|
120
|
-
outputMessage: m ? 'Please clarify with summarize item <item id>, summarize item #<title>, or summarize item #"<title with spaces>".' : ""
|
|
121
|
-
};
|
|
122
|
-
}, kt = `
|
|
123
|
-
Classify the user analytics request.
|
|
124
|
-
|
|
125
|
-
Rules:
|
|
126
|
-
- intent="summarize" only when the user explicitly asks to summarize/overview/recap an item.
|
|
127
|
-
- intent="followUp" for analytical questions about item details, including schema/fields/attributes/layers.
|
|
128
|
-
- intent="clarify" when neither summarize nor follow-up intent is clear.
|
|
129
|
-
- itemId must be the final resolved item id.
|
|
130
|
-
- If request has explicit item id, set itemId directly.
|
|
131
|
-
- If request references item title (for example #title, #"title with spaces", or plain quoted title), call resolvePortalItemIdByTitle and set itemId to the returned value.
|
|
132
|
-
- Never return item titles in output fields.
|
|
133
|
-
- If intent is "followUp", set question to the user's full question/request text.
|
|
134
|
-
- If intent is "summarize", set question="".
|
|
135
|
-
- When user asks to show/list/explain fields, schema, attributes, columns, or layer details, classify as "followUp" unless they explicitly request a summary.
|
|
136
|
-
- If hasSummaryContext is true, prefer "followUp" for detail-oriented requests that do not explicitly ask to summarize.
|
|
137
|
-
|
|
138
|
-
Examples:
|
|
139
|
-
- "Summarize item 0123456789abcdef0123456789abcdef" => summarize, itemId="0123456789abcdef0123456789abcdef"
|
|
140
|
-
- "Summarize item #california" => summarize, call resolvePortalItemIdByTitle("california") and set itemId to tool result
|
|
141
|
-
- "Summarize item #"california farmland"" => summarize, call resolvePortalItemIdByTitle("california farmland") and set itemId to tool result
|
|
142
|
-
- "Show the layer's available fields" => followUp
|
|
143
|
-
- "List attributes and explain what status means" => followUp
|
|
144
|
-
- "What fields are available?" with hasSummaryContext=true => followUp
|
|
145
|
-
- "Give me an overview of item 0123456789abcdef0123456789abcdef" => summarize
|
|
146
|
-
|
|
147
|
-
hasSummaryContext:
|
|
148
|
-
{hasSummaryContext}
|
|
149
|
-
|
|
150
|
-
User message:
|
|
151
|
-
{userMessage}
|
|
152
|
-
`, Et = async (e, t) => {
|
|
153
|
-
const s = e.analyticsItemId;
|
|
154
|
-
if (!s)
|
|
155
|
-
return {
|
|
156
|
-
status: "success",
|
|
157
|
-
outputMessage: 'Please clarify with summarize item <item id>, summarize item #<title>, or summarize item #"<title with spaces>".'
|
|
158
|
-
};
|
|
159
|
-
await g({ text: `Summarizing item ${s}...`, agentName: "analytics" }, t);
|
|
160
|
-
const a = t?.configurable?.context;
|
|
161
|
-
x(a);
|
|
162
|
-
const { portal: r, user: u } = a, { result: l, error: i } = await ht(u, r, s);
|
|
163
|
-
if (i || !l)
|
|
164
|
-
return await g({ text: "Failed to get item context for summarization", agentName: "analytics" }, t), {
|
|
165
|
-
status: "success",
|
|
166
|
-
outputMessage: "Unable to retrieve item context for summarization."
|
|
167
|
-
};
|
|
168
|
-
const { context: n } = l, c = await b({
|
|
169
|
-
promptText: Dt,
|
|
170
|
-
schema: Ct,
|
|
171
|
-
modelTier: "default",
|
|
172
|
-
inputVariables: { context: JSON.stringify(n) }
|
|
173
|
-
}), { followUpQuestions: d, summary: p } = c, m = R(e), y = {
|
|
174
|
-
latestItemId: s,
|
|
175
|
-
memory: {
|
|
176
|
-
...m.memory,
|
|
177
|
-
[s]: { summary: p, followUpQuestions: d, fullContext: n }
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
return d.length && await D({ type: "suggested-prompts", data: { prompts: d } }, t), {
|
|
181
|
-
status: "success",
|
|
182
|
-
outputMessage: p,
|
|
183
|
-
sharedStatePatch: { portalItemAnalyticsSummaryMemory: { value: y } }
|
|
184
|
-
};
|
|
185
|
-
}, Dt = `
|
|
186
|
-
You are a item summary tool for ArcGIS. Your job is to summarize an item's info based on the provided context.
|
|
187
|
-
Summary rules:
|
|
188
|
-
- The summary should be concise markdown, make sure to format the output nicely so it's easy to read.
|
|
189
|
-
- Target length: 80-150 words.
|
|
190
|
-
- Provide one short descriptive paragraph.
|
|
191
|
-
- Also propose 3 concise follow-up questions grounded in the item summary.
|
|
192
|
-
- Keep follow-up questions specific and actionable.
|
|
193
|
-
Follow-up questions rules:
|
|
194
|
-
- These questions should be in the format of a prompt that the user can click on.
|
|
195
|
-
- Make sure the questions are relevant to the item summary and that you can answer based solely on the provided context.
|
|
196
|
-
Do not include internal identifiers.
|
|
197
|
-
If the user asks for a detailed summary, you may expand the response up to 300 words.
|
|
198
|
-
Item context:
|
|
199
|
-
{context}
|
|
200
|
-
`, q = (e, t) => t ?? e, _ = h.Root({
|
|
201
|
-
...N(),
|
|
202
|
-
// States shared only across nodes in the graph, not between invocations
|
|
203
|
-
analyticsIntent: h({
|
|
204
|
-
reducer: q,
|
|
205
|
-
default: () => "clarify"
|
|
206
|
-
}),
|
|
207
|
-
analyticsItemId: h({
|
|
208
|
-
reducer: q,
|
|
209
|
-
default: () => null
|
|
210
|
-
}),
|
|
211
|
-
analyticsQuestion: h({
|
|
212
|
-
reducer: q,
|
|
213
|
-
default: () => ""
|
|
214
|
-
})
|
|
215
|
-
}), zt = () => new C(_).addNode("detectAnalyticsIntent", qt).addNode("summarizePortalItem", Et).addNode("answerAnalyticsFollowUp", Nt).addEdge(P, "detectAnalyticsIntent").addConditionalEdges("detectAnalyticsIntent", (t) => t.analyticsIntent === "summarize" ? "summarizePortalItem" : t.analyticsIntent === "followUp" ? "answerAnalyticsFollowUp" : f).addEdge("summarizePortalItem", f).addEdge("answerAnalyticsFollowUp", f), Ut = String.raw`- **portal-item-analytics** - Portal item analytics assistant:
|
|
216
|
-
- summarizes ArcGIS portal items from item context
|
|
217
|
-
- suggests follow-up prompts grounded in the item
|
|
218
|
-
`, Rt = {
|
|
219
|
-
id: "portal-item-analytics",
|
|
220
|
-
name: "Portal Item Analytics",
|
|
221
|
-
description: Ut,
|
|
222
|
-
createGraph: zt,
|
|
223
|
-
workspace: _
|
|
224
|
-
}, Ft = (e) => e.map((t) => `"${t}"`).join(", "), jt = o.object({
|
|
27
|
+
const Tt = (e) => e.map((t) => `"${t}"`).join(", "), Ct = o.object({
|
|
225
28
|
successMessage: o.string().default("")
|
|
226
|
-
}), O = "portal-group-creation", V = "approveAddMembers",
|
|
29
|
+
}), O = "portal-group-creation", V = "approveAddMembers", Pt = async (e, t) => {
|
|
227
30
|
if (e.intentParams.intent !== "addMembers")
|
|
228
31
|
return {
|
|
229
32
|
status: "success",
|
|
@@ -235,31 +38,31 @@ Item context:
|
|
|
235
38
|
status: "success",
|
|
236
39
|
outputMessage: "Create a group first, then add members using @mention usernames."
|
|
237
40
|
};
|
|
238
|
-
const a = e.intentParams.memberInfo.memberIdentifiers.map((
|
|
41
|
+
const a = e.intentParams.memberInfo.memberIdentifiers.map((d) => d.trim()).filter(Boolean);
|
|
239
42
|
if (!a.length)
|
|
240
43
|
return {
|
|
241
44
|
status: "success",
|
|
242
45
|
outputMessage: "Use @mention usernames for the members you want to add."
|
|
243
46
|
};
|
|
244
|
-
const
|
|
47
|
+
const i = `The following member(s) will be added to the newly created group:
|
|
245
48
|
|
|
246
|
-
${a.map((
|
|
49
|
+
${a.map((d) => `- **@${d}**`).join(`
|
|
247
50
|
`)}
|
|
248
51
|
|
|
249
52
|
Do you want to continue?`, { hitlResponse: l } = t?.configurable ?? {};
|
|
250
53
|
if (l?.agentId !== O || l.id !== V) {
|
|
251
|
-
const
|
|
54
|
+
const d = {
|
|
252
55
|
agentId: O,
|
|
253
56
|
id: V,
|
|
254
57
|
kind: "booleanChoice",
|
|
255
|
-
message:
|
|
58
|
+
message: i,
|
|
256
59
|
metadata: {
|
|
257
60
|
action: "addMembers",
|
|
258
61
|
groupId: s,
|
|
259
62
|
members: [...a]
|
|
260
63
|
}
|
|
261
64
|
};
|
|
262
|
-
throw new K(
|
|
65
|
+
throw new K(d);
|
|
263
66
|
}
|
|
264
67
|
if (l.payload !== !0)
|
|
265
68
|
return {
|
|
@@ -267,25 +70,25 @@ Do you want to continue?`, { hitlResponse: l } = t?.configurable ?? {};
|
|
|
267
70
|
outputMessage: "Okay, I cancelled adding members to the group."
|
|
268
71
|
};
|
|
269
72
|
await g(
|
|
270
|
-
{ text: `Adding members ${
|
|
73
|
+
{ text: `Adding members ${Tt(a)}...`, agentName: "group-creation" },
|
|
271
74
|
t
|
|
272
75
|
);
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
const { result:
|
|
276
|
-
if (
|
|
76
|
+
const u = t?.configurable?.context;
|
|
77
|
+
I(u);
|
|
78
|
+
const { result: c, error: n } = await ft(u.portal, s, a);
|
|
79
|
+
if (n || !c)
|
|
277
80
|
return {
|
|
278
81
|
status: "success",
|
|
279
82
|
outputMessage: "I could not add members to that group. Please confirm group access and user accounts, then try again."
|
|
280
83
|
};
|
|
281
|
-
const { addedUsernames:
|
|
84
|
+
const { addedUsernames: m, notAddedUsers: p } = c;
|
|
282
85
|
try {
|
|
283
86
|
const y = (await b({
|
|
284
|
-
promptText:
|
|
285
|
-
schema:
|
|
87
|
+
promptText: Nt,
|
|
88
|
+
schema: Ct,
|
|
286
89
|
modelTier: "fast",
|
|
287
90
|
inputVariables: {
|
|
288
|
-
addedMembers:
|
|
91
|
+
addedMembers: m.join(", "),
|
|
289
92
|
notAddedMembers: JSON.stringify(
|
|
290
93
|
p.map((v) => ({ username: v.username, reason: v.error.message }))
|
|
291
94
|
)
|
|
@@ -293,11 +96,11 @@ Do you want to continue?`, { hitlResponse: l } = t?.configurable ?? {};
|
|
|
293
96
|
})).successMessage;
|
|
294
97
|
if (y)
|
|
295
98
|
return { status: "success", outputMessage: y };
|
|
296
|
-
} catch (
|
|
297
|
-
console.error("Error generating add-members success message:",
|
|
99
|
+
} catch (d) {
|
|
100
|
+
console.error("Error generating add-members success message:", d);
|
|
298
101
|
}
|
|
299
102
|
return {};
|
|
300
|
-
},
|
|
103
|
+
}, Nt = `
|
|
301
104
|
Write a concise, friendly success message for adding members to a group.
|
|
302
105
|
|
|
303
106
|
Rules:
|
|
@@ -312,11 +115,11 @@ Added members:
|
|
|
312
115
|
|
|
313
116
|
Not added members:
|
|
314
117
|
{notAddedMembers}
|
|
315
|
-
`, B = "portal-group-creation", Q = "approveCreateGroup",
|
|
118
|
+
`, B = "portal-group-creation", Q = "approveCreateGroup", qt = o.object({
|
|
316
119
|
successMessage: o.string().default("")
|
|
317
|
-
}),
|
|
120
|
+
}), $t = o.object({
|
|
318
121
|
failureMessage: o.string().default("")
|
|
319
|
-
}),
|
|
122
|
+
}), kt = async (e, t) => {
|
|
320
123
|
if (e.intentParams.intent !== "create")
|
|
321
124
|
return {
|
|
322
125
|
status: "success",
|
|
@@ -330,7 +133,7 @@ Not added members:
|
|
|
330
133
|
};
|
|
331
134
|
const a = `A group with the title **${s}** will be created. Do you want to continue?`, { hitlResponse: r } = t?.configurable;
|
|
332
135
|
if (r?.agentId !== B || r.id !== Q) {
|
|
333
|
-
const
|
|
136
|
+
const n = {
|
|
334
137
|
agentId: B,
|
|
335
138
|
id: Q,
|
|
336
139
|
kind: "booleanChoice",
|
|
@@ -341,7 +144,7 @@ Not added members:
|
|
|
341
144
|
access: "private"
|
|
342
145
|
}
|
|
343
146
|
};
|
|
344
|
-
throw new K(
|
|
147
|
+
throw new K(n);
|
|
345
148
|
}
|
|
346
149
|
if (r.payload !== !0)
|
|
347
150
|
return {
|
|
@@ -349,22 +152,22 @@ Not added members:
|
|
|
349
152
|
outputMessage: `Okay, I cancelled creating **${s}**.`
|
|
350
153
|
};
|
|
351
154
|
await g({ text: `Creating group "${s}"...`, agentName: "group-creation" }, t);
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
const { result: l, error:
|
|
155
|
+
const i = t?.configurable?.context;
|
|
156
|
+
I(i);
|
|
157
|
+
const { result: l, error: u } = await ht(i.portal, {
|
|
355
158
|
title: s,
|
|
356
159
|
access: "private"
|
|
357
160
|
});
|
|
358
|
-
if (
|
|
359
|
-
const
|
|
161
|
+
if (u || !l) {
|
|
162
|
+
const n = u?.message?.trim() || "No additional details were provided.";
|
|
360
163
|
try {
|
|
361
164
|
const p = (await b({
|
|
362
|
-
promptText:
|
|
363
|
-
schema:
|
|
165
|
+
promptText: Dt,
|
|
166
|
+
schema: $t,
|
|
364
167
|
modelTier: "fast",
|
|
365
168
|
inputVariables: {
|
|
366
169
|
groupTitle: s,
|
|
367
|
-
failureReason:
|
|
170
|
+
failureReason: n
|
|
368
171
|
}
|
|
369
172
|
})).failureMessage.trim();
|
|
370
173
|
if (p)
|
|
@@ -372,36 +175,36 @@ Not added members:
|
|
|
372
175
|
status: "success",
|
|
373
176
|
outputMessage: p
|
|
374
177
|
};
|
|
375
|
-
} catch (
|
|
376
|
-
console.error("Error generating create-group failure message:",
|
|
178
|
+
} catch (m) {
|
|
179
|
+
console.error("Error generating create-group failure message:", m);
|
|
377
180
|
}
|
|
378
181
|
return {
|
|
379
182
|
status: "success",
|
|
380
183
|
outputMessage: "I could not create that group. Please confirm your permissions and try again with the group title."
|
|
381
184
|
};
|
|
382
185
|
}
|
|
383
|
-
const
|
|
186
|
+
const c = l.id;
|
|
384
187
|
try {
|
|
385
|
-
const
|
|
386
|
-
promptText:
|
|
387
|
-
schema:
|
|
188
|
+
const m = (await b({
|
|
189
|
+
promptText: Et,
|
|
190
|
+
schema: qt,
|
|
388
191
|
modelTier: "fast",
|
|
389
192
|
inputVariables: {
|
|
390
193
|
groupTitle: s
|
|
391
194
|
}
|
|
392
195
|
})).successMessage.trim();
|
|
393
|
-
if (
|
|
196
|
+
if (m)
|
|
394
197
|
return {
|
|
395
198
|
status: "success",
|
|
396
|
-
outputMessage:
|
|
397
|
-
sharedStatePatch: { createdGroupId: { value:
|
|
398
|
-
createdGroupId:
|
|
199
|
+
outputMessage: m,
|
|
200
|
+
sharedStatePatch: { createdGroupId: { value: c } },
|
|
201
|
+
createdGroupId: c
|
|
399
202
|
};
|
|
400
|
-
} catch (
|
|
401
|
-
console.error("Error generating create-group success message:",
|
|
203
|
+
} catch (n) {
|
|
204
|
+
console.error("Error generating create-group success message:", n);
|
|
402
205
|
}
|
|
403
206
|
return {};
|
|
404
|
-
},
|
|
207
|
+
}, Et = `
|
|
405
208
|
Write a concise, friendly success message after creating a portal group.
|
|
406
209
|
|
|
407
210
|
Rules:
|
|
@@ -412,7 +215,7 @@ Rules:
|
|
|
412
215
|
|
|
413
216
|
Group title:
|
|
414
217
|
{groupTitle}
|
|
415
|
-
`,
|
|
218
|
+
`, Dt = `
|
|
416
219
|
Write a concise, friendly failure message after an attempt to create a portal group.
|
|
417
220
|
|
|
418
221
|
Rules:
|
|
@@ -427,25 +230,39 @@ Group title:
|
|
|
427
230
|
|
|
428
231
|
Failure reason:
|
|
429
232
|
{failureReason}
|
|
430
|
-
`,
|
|
233
|
+
`, x = (e) => {
|
|
234
|
+
for (let t = e.length - 1; t >= 0; t -= 1) {
|
|
235
|
+
const s = e[t];
|
|
236
|
+
if (s.type !== "human")
|
|
237
|
+
continue;
|
|
238
|
+
const a = s.content;
|
|
239
|
+
if (typeof a == "string")
|
|
240
|
+
return a;
|
|
241
|
+
if (Array.isArray(a))
|
|
242
|
+
return a.map(
|
|
243
|
+
(r) => typeof r == "string" ? r : "text" in r && typeof r.text == "string" ? r.text : ""
|
|
244
|
+
).join(" ").trim();
|
|
245
|
+
}
|
|
246
|
+
return "";
|
|
247
|
+
}, zt = o.object({
|
|
431
248
|
intent: o.enum(["clarify", "create", "addMembers"]).default("clarify"),
|
|
432
249
|
title: o.string().default(""),
|
|
433
250
|
memberIdentifiers: o.array(o.string()).default([]),
|
|
434
251
|
clarifyMessage: o.string().default("")
|
|
435
|
-
}),
|
|
252
|
+
}), Ut = async (e, t) => {
|
|
436
253
|
await g({ text: "Thinking about groups...", agentName: "group-creation" }, t);
|
|
437
|
-
const s =
|
|
438
|
-
promptText:
|
|
439
|
-
schema:
|
|
254
|
+
const s = x(e.agentExecutionContext.messages).trim(), a = await b({
|
|
255
|
+
promptText: Rt,
|
|
256
|
+
schema: zt,
|
|
440
257
|
modelTier: "default",
|
|
441
258
|
inputVariables: { userMessage: s }
|
|
442
|
-
}), r = a.title.trim(),
|
|
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;
|
|
443
260
|
return {
|
|
444
|
-
intentParams:
|
|
261
|
+
intentParams: u ? { intent: "create", title: r } : c ? { intent: "addMembers", memberInfo: { memberIdentifiers: i } } : { intent: "clarify" },
|
|
445
262
|
status: "success",
|
|
446
|
-
outputMessage: !
|
|
263
|
+
outputMessage: !u && !c ? l : ""
|
|
447
264
|
};
|
|
448
|
-
},
|
|
265
|
+
}, Rt = `
|
|
449
266
|
You classify whether a user is asking to create a new ArcGIS Portal group or add members to an existing group.
|
|
450
267
|
|
|
451
268
|
Rules:
|
|
@@ -471,7 +288,7 @@ Examples:
|
|
|
471
288
|
|
|
472
289
|
User message:
|
|
473
290
|
{userMessage}
|
|
474
|
-
`,
|
|
291
|
+
`, Ft = o.discriminatedUnion("destinationType", [
|
|
475
292
|
o.object({
|
|
476
293
|
destinationType: o.literal("portal-content")
|
|
477
294
|
}),
|
|
@@ -486,67 +303,63 @@ User message:
|
|
|
486
303
|
destinationType: o.literal("portal-group"),
|
|
487
304
|
groupId: o.string().trim().min(1)
|
|
488
305
|
})
|
|
489
|
-
])
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
}
|
|
494
|
-
const H = "portal-navigation", F = async (e, t) => {
|
|
495
|
-
await D({ type: H, data: { ...e } }, t);
|
|
496
|
-
}, Zt = async (e, t) => {
|
|
306
|
+
]), _ = "portal-navigation", R = async (e, t) => {
|
|
307
|
+
const s = t?.configurable?.context;
|
|
308
|
+
!Y(s) || !s.navigationTargetMap?.[e.destinationType] || await E({ type: _, data: { ...e } }, t);
|
|
309
|
+
}, jt = async (e, t) => {
|
|
497
310
|
const s = e.createdGroupId ?? e.agentExecutionContext.sharedState.createdGroupId?.value;
|
|
498
|
-
return s ? (await g({ text: "Preparing navigation...", agentName: "group-creation" }, t), await
|
|
499
|
-
}, L = (e, t) => t ?? e,
|
|
311
|
+
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({
|
|
500
313
|
...N(),
|
|
501
314
|
// * Shared state between nodes (but not persisted to the agent execution context)
|
|
502
315
|
/** Parameters related to the user's intent for group creation actions */
|
|
503
|
-
intentParams:
|
|
316
|
+
intentParams: f({ reducer: L, default: () => ({ intent: "clarify" }) }),
|
|
504
317
|
/** The ID of the group that was created
|
|
505
318
|
* even though we already have this in the shared state
|
|
506
319
|
* we still need it here to also share between nodes
|
|
507
320
|
*/
|
|
508
|
-
createdGroupId:
|
|
509
|
-
}),
|
|
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) => {
|
|
510
323
|
switch (t.intentParams.intent) {
|
|
511
324
|
case "create":
|
|
512
325
|
return "createPortalGroup";
|
|
513
326
|
case "addMembers":
|
|
514
327
|
return "addMembersToPortalGroup";
|
|
515
328
|
default:
|
|
516
|
-
return
|
|
329
|
+
return h;
|
|
517
330
|
}
|
|
518
|
-
}).addEdge("createPortalGroup", "suggestCreatedGroupNavigation").addEdge("addMembersToPortalGroup", "suggestCreatedGroupNavigation").addEdge("suggestCreatedGroupNavigation",
|
|
331
|
+
}).addEdge("createPortalGroup", "suggestCreatedGroupNavigation").addEdge("addMembersToPortalGroup", "suggestCreatedGroupNavigation").addEdge("suggestCreatedGroupNavigation", h), Vt = String.raw`- **portal-group-creation** - Portal group creation assistant:
|
|
519
332
|
- creates a new ArcGIS Portal group for the signed-in user
|
|
520
333
|
- adds users to the newly created group using @mention usernames
|
|
521
|
-
`,
|
|
334
|
+
`, Bt = {
|
|
522
335
|
id: "portal-group-creation",
|
|
523
336
|
name: "Portal Group Creation",
|
|
524
|
-
description:
|
|
525
|
-
createGraph:
|
|
526
|
-
workspace:
|
|
527
|
-
},
|
|
528
|
-
const t = e?.[
|
|
337
|
+
description: Vt,
|
|
338
|
+
createGraph: Ot,
|
|
339
|
+
workspace: H
|
|
340
|
+
}, X = "portalDocAssistantMemory", Qt = () => ({ conversationId: "" }), Lt = (e) => {
|
|
341
|
+
const t = e?.[X]?.value;
|
|
529
342
|
if (!t || typeof t != "object")
|
|
530
|
-
return
|
|
343
|
+
return Qt();
|
|
531
344
|
const s = t;
|
|
532
345
|
return {
|
|
533
346
|
conversationId: typeof s.conversationId == "string" ? s.conversationId : ""
|
|
534
347
|
};
|
|
535
|
-
},
|
|
536
|
-
[
|
|
348
|
+
}, Jt = (e) => ({
|
|
349
|
+
[X]: { value: e }
|
|
537
350
|
});
|
|
538
|
-
async function
|
|
351
|
+
async function Kt({
|
|
539
352
|
portal: e,
|
|
540
353
|
question: t,
|
|
541
354
|
persona: s,
|
|
542
355
|
previousConversationId: a,
|
|
543
356
|
signal: r,
|
|
544
|
-
skillId:
|
|
357
|
+
skillId: i
|
|
545
358
|
}) {
|
|
546
|
-
|
|
547
|
-
const
|
|
359
|
+
i ??= "doc_ai_assistant";
|
|
360
|
+
const u = await Wt({
|
|
548
361
|
portal: e,
|
|
549
|
-
skillId:
|
|
362
|
+
skillId: i,
|
|
550
363
|
message: t,
|
|
551
364
|
options: { context: {
|
|
552
365
|
kind: "DocAIAssistantRequest",
|
|
@@ -554,20 +367,20 @@ async function ne({
|
|
|
554
367
|
}, previousConversationId: a, signal: r }
|
|
555
368
|
});
|
|
556
369
|
return {
|
|
557
|
-
reply:
|
|
558
|
-
conversationId:
|
|
370
|
+
reply: Yt(u, i),
|
|
371
|
+
conversationId: u[0]?.conversationId ?? ""
|
|
559
372
|
};
|
|
560
373
|
}
|
|
561
|
-
async function
|
|
374
|
+
async function Wt({
|
|
562
375
|
portal: e,
|
|
563
376
|
skillId: t,
|
|
564
377
|
message: s,
|
|
565
378
|
options: a
|
|
566
379
|
}) {
|
|
567
|
-
const
|
|
380
|
+
const i = `${e.helperServices.aiAssistantServices.url}/skills/${t}/chat`, l = {
|
|
568
381
|
"Content-Type": "application/json",
|
|
569
|
-
token:
|
|
570
|
-
},
|
|
382
|
+
token: It.findCredential(e.url)?.token ?? ""
|
|
383
|
+
}, u = await j(i, {
|
|
571
384
|
method: "post",
|
|
572
385
|
body: JSON.stringify({
|
|
573
386
|
message: s,
|
|
@@ -577,17 +390,17 @@ async function ie({
|
|
|
577
390
|
headers: l,
|
|
578
391
|
signal: a.signal
|
|
579
392
|
});
|
|
580
|
-
if (
|
|
581
|
-
throw new Error(`Doc assistant chat failed (${
|
|
582
|
-
cause:
|
|
393
|
+
if (u.httpStatus !== 200)
|
|
394
|
+
throw new Error(`Doc assistant chat failed (${u.httpStatus})`, {
|
|
395
|
+
cause: u.data
|
|
583
396
|
});
|
|
584
|
-
const
|
|
397
|
+
const c = u.data, n = [c], { conversationId: m, inquiryId: p } = c, d = async (y, v) => {
|
|
585
398
|
if (!v)
|
|
586
399
|
return;
|
|
587
|
-
await
|
|
588
|
-
const w = await j(
|
|
400
|
+
await gt(1e3);
|
|
401
|
+
const w = await j(i, {
|
|
589
402
|
method: "post",
|
|
590
|
-
body: JSON.stringify({ conversationId:
|
|
403
|
+
body: JSON.stringify({ conversationId: m, inquiryId: p, ackSequenceNumber: y }),
|
|
591
404
|
headers: l,
|
|
592
405
|
signal: a.signal
|
|
593
406
|
});
|
|
@@ -596,11 +409,11 @@ async function ie({
|
|
|
596
409
|
cause: w.data
|
|
597
410
|
});
|
|
598
411
|
const S = w.data;
|
|
599
|
-
|
|
412
|
+
n.push(S), await d(S.sequenceNumber, S.hasMore);
|
|
600
413
|
};
|
|
601
|
-
return
|
|
414
|
+
return c.hasMore && await d(c.sequenceNumber, c.hasMore), n;
|
|
602
415
|
}
|
|
603
|
-
function
|
|
416
|
+
function Yt(e, t) {
|
|
604
417
|
switch (t) {
|
|
605
418
|
case "doc_chat":
|
|
606
419
|
return e.find((s) => s.message != null)?.message ?? "";
|
|
@@ -618,17 +431,17 @@ function ue(e, t) {
|
|
|
618
431
|
return T(t);
|
|
619
432
|
}
|
|
620
433
|
}
|
|
621
|
-
const
|
|
434
|
+
const _t = async (e, t) => {
|
|
622
435
|
await g({ text: "Asking documentation assistant...", agentName: "doc-assistant" }, t);
|
|
623
|
-
const s =
|
|
436
|
+
const s = x(e.agentExecutionContext.messages).trim();
|
|
624
437
|
if (!s)
|
|
625
438
|
return {
|
|
626
439
|
status: "success",
|
|
627
440
|
outputMessage: "Please share your question and I can help with ArcGIS and Portal documentation."
|
|
628
441
|
};
|
|
629
442
|
const a = t?.configurable?.context;
|
|
630
|
-
|
|
631
|
-
const r =
|
|
443
|
+
I(a);
|
|
444
|
+
const r = Lt(e.agentExecutionContext.sharedState), { reply: i, conversationId: l } = await Kt({
|
|
632
445
|
portal: a.portal,
|
|
633
446
|
question: s,
|
|
634
447
|
previousConversationId: r.conversationId || void 0,
|
|
@@ -637,20 +450,20 @@ const le = async (e, t) => {
|
|
|
637
450
|
});
|
|
638
451
|
return {
|
|
639
452
|
status: "success",
|
|
640
|
-
outputMessage:
|
|
641
|
-
sharedStatePatch:
|
|
453
|
+
outputMessage: i.trim() || "I could not retrieve a response from the documentation assistant.",
|
|
454
|
+
sharedStatePatch: Jt({
|
|
642
455
|
conversationId: l || r.conversationId
|
|
643
456
|
})
|
|
644
457
|
};
|
|
645
|
-
},
|
|
458
|
+
}, Z = W(
|
|
646
459
|
async ({ groupTitle: e }, t) => {
|
|
647
460
|
const s = e.trim();
|
|
648
461
|
if (!s)
|
|
649
462
|
return null;
|
|
650
463
|
const a = t?.configurable?.context;
|
|
651
|
-
|
|
464
|
+
I(a);
|
|
652
465
|
try {
|
|
653
|
-
return (await
|
|
466
|
+
return (await yt(a.portal, { query: `title:${s}`, num: 1 }))?.results[0]?.id || null;
|
|
654
467
|
} catch (r) {
|
|
655
468
|
return console.error("Error searching for portal group by title:", r), null;
|
|
656
469
|
}
|
|
@@ -662,32 +475,49 @@ const le = async (e, t) => {
|
|
|
662
475
|
groupTitle: o.string().describe("The portal group title to resolve to a group id.")
|
|
663
476
|
})
|
|
664
477
|
}
|
|
478
|
+
), tt = W(
|
|
479
|
+
async ({ itemTitle: e }, t) => {
|
|
480
|
+
const s = e.trim();
|
|
481
|
+
if (!s)
|
|
482
|
+
return null;
|
|
483
|
+
const a = t?.configurable?.context;
|
|
484
|
+
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;
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
name: "resolvePortalItemIdByTitle",
|
|
490
|
+
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.")
|
|
493
|
+
})
|
|
494
|
+
}
|
|
665
495
|
), J = o.object({
|
|
666
496
|
shouldSuggestNavigation: o.boolean().default(!1),
|
|
667
497
|
destinationType: o.enum(["none", "portal-content", "portal-item", "portal-groups", "portal-group"]).default("none"),
|
|
668
498
|
itemId: o.string().default(""),
|
|
669
499
|
groupId: o.string().default("")
|
|
670
|
-
}),
|
|
500
|
+
}), Ht = async (e, t) => {
|
|
671
501
|
await g({ text: "Extracting navigation intent...", agentName: "doc-assistant" }, t);
|
|
672
502
|
const s = e.outputMessage.trim();
|
|
673
503
|
if (!s)
|
|
674
504
|
return {};
|
|
675
|
-
const a =
|
|
505
|
+
const a = x(e.agentExecutionContext.messages).trim(), r = await z.fromTemplate(Zt).format({
|
|
676
506
|
question: a,
|
|
677
507
|
response: s
|
|
678
508
|
}), l = await U({
|
|
679
|
-
model: await
|
|
680
|
-
tools: [
|
|
509
|
+
model: await D({ modelTier: "default" }),
|
|
510
|
+
tools: [tt, Z],
|
|
681
511
|
systemPrompt: r,
|
|
682
512
|
responseFormat: J,
|
|
683
513
|
checkpointer: !0
|
|
684
|
-
}).invoke({ messages: e.agentExecutionContext.messages }, t),
|
|
685
|
-
if (!
|
|
514
|
+
}).invoke({ messages: e.agentExecutionContext.messages }, t), u = J.parse(l.structuredResponse ?? {});
|
|
515
|
+
if (!u.shouldSuggestNavigation || u.destinationType === "none")
|
|
686
516
|
return {};
|
|
687
|
-
const
|
|
688
|
-
return
|
|
517
|
+
const c = Xt(u);
|
|
518
|
+
return c ? (await R(c, t), {}) : {};
|
|
689
519
|
};
|
|
690
|
-
function
|
|
520
|
+
function Xt({
|
|
691
521
|
destinationType: e,
|
|
692
522
|
itemId: t,
|
|
693
523
|
groupId: s
|
|
@@ -707,7 +537,7 @@ function me({
|
|
|
707
537
|
return T(e);
|
|
708
538
|
}
|
|
709
539
|
}
|
|
710
|
-
const
|
|
540
|
+
const Zt = `
|
|
711
541
|
You decide whether the assistant response should include a navigation action to ArcGIS Portal.
|
|
712
542
|
|
|
713
543
|
Given the user question and assistant response:
|
|
@@ -731,16 +561,16 @@ User question:
|
|
|
731
561
|
|
|
732
562
|
Assistant response:
|
|
733
563
|
{response}
|
|
734
|
-
`, et =
|
|
564
|
+
`, et = xt.Root({
|
|
735
565
|
...N()
|
|
736
|
-
}),
|
|
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:
|
|
737
567
|
- answers general ArcGIS, Portal, Enterprise, and JavaScript SDK questions
|
|
738
568
|
- acts as a fallback when specialized agents are not applicable
|
|
739
|
-
`,
|
|
569
|
+
`, se = {
|
|
740
570
|
id: "portal-doc-assistant",
|
|
741
571
|
name: "Portal Doc Assistant",
|
|
742
|
-
description:
|
|
743
|
-
createGraph:
|
|
572
|
+
description: ee,
|
|
573
|
+
createGraph: te,
|
|
744
574
|
workspace: et
|
|
745
575
|
}, st = `
|
|
746
576
|
Shared markdown formatting rules:
|
|
@@ -749,21 +579,21 @@ Shared markdown formatting rules:
|
|
|
749
579
|
- Emphasize key metrics with bold labels (for example: **Recent items:** 4).
|
|
750
580
|
- Keep wording direct and analytical; avoid filler language but make sure the language is friendly.
|
|
751
581
|
- Do not include raw internal IDs unless explicitly requested.
|
|
752
|
-
`,
|
|
582
|
+
`, ae = () => ({ latestGroupId: null, memory: {} }), q = (e) => {
|
|
753
583
|
const t = e?.agentExecutionContext.sharedState.portalGroupSummaryMemory?.value;
|
|
754
|
-
return t ? { latestGroupId: t.latestGroupId, memory: t.memory } :
|
|
755
|
-
},
|
|
584
|
+
return t ? { latestGroupId: t.latestGroupId, memory: t.memory } : ae();
|
|
585
|
+
}, re = async (e, t) => {
|
|
756
586
|
await g({ text: "Answering group follow-up...", agentName: "group-analytics" }, t);
|
|
757
|
-
const s =
|
|
587
|
+
const s = q(e), a = e.groupSummaryGroupId ?? s.latestGroupId, r = a ? s.memory[a] : void 0, i = e.groupSummaryQuestion || x(e.agentExecutionContext.messages);
|
|
758
588
|
return r ? {
|
|
759
589
|
status: "success",
|
|
760
590
|
outputMessage: (await b({
|
|
761
|
-
promptText:
|
|
762
|
-
schema:
|
|
591
|
+
promptText: ne,
|
|
592
|
+
schema: oe,
|
|
763
593
|
modelTier: "default",
|
|
764
594
|
inputVariables: {
|
|
765
595
|
summary: r.summary,
|
|
766
|
-
question:
|
|
596
|
+
question: i,
|
|
767
597
|
fullContext: JSON.stringify(r.fullContext)
|
|
768
598
|
}
|
|
769
599
|
})).answer
|
|
@@ -771,10 +601,10 @@ Shared markdown formatting rules:
|
|
|
771
601
|
status: "success",
|
|
772
602
|
outputMessage: "I do not have group analytics context yet. Ask me to analyze a group first with analyze group <group id>."
|
|
773
603
|
};
|
|
774
|
-
},
|
|
604
|
+
}, oe = o.object({
|
|
775
605
|
answer: o.string(),
|
|
776
606
|
isRelevant: o.boolean()
|
|
777
|
-
}),
|
|
607
|
+
}), ne = `
|
|
778
608
|
You answer follow-up questions about ArcGIS group analytics.
|
|
779
609
|
|
|
780
610
|
${st}
|
|
@@ -799,30 +629,30 @@ Group full context:
|
|
|
799
629
|
|
|
800
630
|
Question:
|
|
801
631
|
{question}
|
|
802
|
-
`,
|
|
632
|
+
`, ie = async (e, t) => {
|
|
803
633
|
await g({ text: "Analyzing group-analytics intent...", agentName: "group-analytics" }, t);
|
|
804
|
-
const s =
|
|
634
|
+
const s = x(e.agentExecutionContext.messages), a = !!q(e).latestGroupId, r = await z.fromTemplate(le).format({
|
|
805
635
|
userMessage: s,
|
|
806
636
|
hasAnalyticsContext: String(a)
|
|
807
637
|
}), l = await U({
|
|
808
|
-
model: await
|
|
809
|
-
tools: [
|
|
638
|
+
model: await D({ modelTier: "fast" }),
|
|
639
|
+
tools: [Z],
|
|
810
640
|
systemPrompt: r,
|
|
811
|
-
responseFormat:
|
|
641
|
+
responseFormat: ue,
|
|
812
642
|
checkpointer: !0
|
|
813
|
-
}).invoke({ messages: e.agentExecutionContext.messages }, t), { intent:
|
|
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;
|
|
814
644
|
return {
|
|
815
|
-
groupSummaryIntent:
|
|
816
|
-
groupSummaryGroupId:
|
|
817
|
-
groupSummaryQuestion:
|
|
645
|
+
groupSummaryIntent: d ? "clarify" : u,
|
|
646
|
+
groupSummaryGroupId: c || null,
|
|
647
|
+
groupSummaryQuestion: n || "",
|
|
818
648
|
status: "success",
|
|
819
|
-
outputMessage:
|
|
649
|
+
outputMessage: d ? "Please clarify with a group id or title" : ""
|
|
820
650
|
};
|
|
821
|
-
},
|
|
651
|
+
}, ue = o.object({
|
|
822
652
|
intent: o.enum(["summarize", "followUp", "navigation", "clarify"]),
|
|
823
653
|
groupId: o.string().default(""),
|
|
824
654
|
question: o.string().default("")
|
|
825
|
-
}),
|
|
655
|
+
}), le = `
|
|
826
656
|
Classify the user's request for ArcGIS Portal group analytics.
|
|
827
657
|
|
|
828
658
|
Rules:
|
|
@@ -851,9 +681,9 @@ hasAnalyticsContext:
|
|
|
851
681
|
|
|
852
682
|
User message:
|
|
853
683
|
{userMessage}
|
|
854
|
-
`,
|
|
855
|
-
const s =
|
|
856
|
-
return await g({ text: "Preparing navigation...", agentName: "group-analytics" }, t), await
|
|
684
|
+
`, ce = async (e, t) => {
|
|
685
|
+
const s = q(e), a = e.groupSummaryGroupId ?? s.latestGroupId;
|
|
686
|
+
return await g({ text: "Preparing navigation...", agentName: "group-analytics" }, t), await R(
|
|
857
687
|
a ? { destinationType: "portal-group", groupId: a } : { destinationType: "portal-groups" },
|
|
858
688
|
t
|
|
859
689
|
), { status: "success" };
|
|
@@ -861,9 +691,9 @@ User message:
|
|
|
861
691
|
function at({ timestamp: e, now: t, windowMs: s }) {
|
|
862
692
|
return e ? t - e <= s : !1;
|
|
863
693
|
}
|
|
864
|
-
const
|
|
865
|
-
function
|
|
866
|
-
const t =
|
|
694
|
+
const me = 720 * 60 * 60 * 1e3;
|
|
695
|
+
function de(e) {
|
|
696
|
+
const t = vt(e);
|
|
867
697
|
return {
|
|
868
698
|
id: e.id ?? "",
|
|
869
699
|
title: e.title ?? "",
|
|
@@ -876,10 +706,10 @@ function Me(e) {
|
|
|
876
706
|
modified: e.modified?.getTime(),
|
|
877
707
|
isInvitationOnly: e.isInvitationOnly,
|
|
878
708
|
sourceSignals: {
|
|
879
|
-
capabilities:
|
|
880
|
-
membershipAccess:
|
|
881
|
-
isOpenData:
|
|
882
|
-
isDistributedCollaborationGroup:
|
|
709
|
+
capabilities: At(e),
|
|
710
|
+
membershipAccess: Mt(e),
|
|
711
|
+
isOpenData: Gt(e),
|
|
712
|
+
isDistributedCollaborationGroup: St(e),
|
|
883
713
|
orgId: t.orgId,
|
|
884
714
|
hiddenMembers: t.hiddenMembers,
|
|
885
715
|
isViewOnly: t.isViewOnly,
|
|
@@ -888,7 +718,7 @@ function Me(e) {
|
|
|
888
718
|
}
|
|
889
719
|
};
|
|
890
720
|
}
|
|
891
|
-
async function
|
|
721
|
+
async function pe(e) {
|
|
892
722
|
const t = { owner: e.owner ?? "", admins: [], users: [] };
|
|
893
723
|
try {
|
|
894
724
|
return await e.fetchMembers();
|
|
@@ -896,7 +726,7 @@ async function Ae(e) {
|
|
|
896
726
|
return console.warn("Unable to fetch group members for analytics context", s), t;
|
|
897
727
|
}
|
|
898
728
|
}
|
|
899
|
-
function
|
|
729
|
+
function ge(e) {
|
|
900
730
|
return e.map((t) => ({
|
|
901
731
|
id: t.id ?? "",
|
|
902
732
|
title: t.title ?? "Untitled",
|
|
@@ -906,40 +736,40 @@ function Te(e) {
|
|
|
906
736
|
modified: t.modified?.getTime()
|
|
907
737
|
}));
|
|
908
738
|
}
|
|
909
|
-
function
|
|
739
|
+
function fe(e, t) {
|
|
910
740
|
return e.filter(
|
|
911
|
-
(s) => s.modified ? at({ timestamp: s.modified, now: t, windowMs:
|
|
741
|
+
(s) => s.modified ? at({ timestamp: s.modified, now: t, windowMs: me }) : !1
|
|
912
742
|
);
|
|
913
743
|
}
|
|
914
|
-
function
|
|
744
|
+
function he(e) {
|
|
915
745
|
const t = /* @__PURE__ */ new Map();
|
|
916
746
|
for (const s of e)
|
|
917
747
|
t.set(s.type, (t.get(s.type) ?? 0) + 1);
|
|
918
748
|
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 }));
|
|
919
749
|
}
|
|
920
|
-
async function
|
|
921
|
-
const t = await e.queryItems({ num: 20, sortField: "modified", sortOrder: "desc" }), s =
|
|
750
|
+
async function ye(e) {
|
|
751
|
+
const t = await e.queryItems({ num: 20, sortField: "modified", sortOrder: "desc" }), s = ge(t.results), a = Date.now();
|
|
922
752
|
return {
|
|
923
753
|
total: t.total,
|
|
924
754
|
topItems: s,
|
|
925
|
-
recentlyModifiedItems:
|
|
926
|
-
topItemTypes:
|
|
755
|
+
recentlyModifiedItems: fe(s, a),
|
|
756
|
+
topItemTypes: he(s)
|
|
927
757
|
};
|
|
928
758
|
}
|
|
929
|
-
async function
|
|
759
|
+
async function we(e, t) {
|
|
930
760
|
if (!t)
|
|
931
761
|
return { error: { code: "missingGroupId", message: "Group id is required." } };
|
|
932
762
|
try {
|
|
933
763
|
const a = (await e.queryGroups({ query: `id:${t}`, num: 1 })).results[0];
|
|
934
764
|
if (!a)
|
|
935
765
|
return { error: { code: "groupNotFound", message: `No group found for id: ${t}` } };
|
|
936
|
-
const r =
|
|
937
|
-
return { result: { group: r, members:
|
|
766
|
+
const r = de(a), i = await pe(a), l = await ye(a);
|
|
767
|
+
return { result: { group: r, members: i, items: l } };
|
|
938
768
|
} catch (s) {
|
|
939
769
|
return console.error("Error fetching portal group analytics context:", s), { error: { code: "unhandledError" } };
|
|
940
770
|
}
|
|
941
771
|
}
|
|
942
|
-
const
|
|
772
|
+
const be = 2160 * 60 * 60 * 1e3, Ie = async (e, t) => {
|
|
943
773
|
const s = e.groupSummaryGroupId;
|
|
944
774
|
if (!s)
|
|
945
775
|
return {
|
|
@@ -948,42 +778,42 @@ const qe = 2160 * 60 * 60 * 1e3, ke = async (e, t) => {
|
|
|
948
778
|
};
|
|
949
779
|
await g({ text: `Analyzing group ${s}...`, agentName: "group-analytics" }, t);
|
|
950
780
|
const a = t?.configurable?.context;
|
|
951
|
-
|
|
952
|
-
const { result: r, error:
|
|
953
|
-
if (
|
|
781
|
+
I(a);
|
|
782
|
+
const { result: r, error: i } = await we(a.portal, s);
|
|
783
|
+
if (i || !r)
|
|
954
784
|
return await g({ text: "Failed to fetch group context", agentName: "group-analytics" }, t), {
|
|
955
785
|
status: "success",
|
|
956
786
|
outputMessage: "Unable to retrieve group context for analytics."
|
|
957
787
|
};
|
|
958
|
-
const { group: l, items:
|
|
959
|
-
promptText:
|
|
960
|
-
schema:
|
|
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,
|
|
961
791
|
modelTier: "default",
|
|
962
792
|
inputVariables: {
|
|
963
793
|
context: JSON.stringify(r),
|
|
964
794
|
deterministicSignals: JSON.stringify({
|
|
965
795
|
isGroupActive: y,
|
|
966
|
-
isGroupRecentlyModified:
|
|
967
|
-
hasRecentlyAddedOrUpdatedContent:
|
|
796
|
+
isGroupRecentlyModified: m,
|
|
797
|
+
hasRecentlyAddedOrUpdatedContent: d,
|
|
968
798
|
recentItemCount: p
|
|
969
799
|
})
|
|
970
800
|
}
|
|
971
|
-
}), { followUpQuestions: w, summary: S } = v,
|
|
801
|
+
}), { followUpQuestions: w, summary: S } = v, nt = q(e), it = {
|
|
972
802
|
latestGroupId: s,
|
|
973
803
|
memory: {
|
|
974
|
-
...
|
|
804
|
+
...nt.memory,
|
|
975
805
|
[s]: { summary: S, followUpQuestions: w, fullContext: r }
|
|
976
806
|
}
|
|
977
807
|
};
|
|
978
|
-
return w.length && await
|
|
808
|
+
return w.length && await E({ type: "suggested-prompts", data: { prompts: w } }, t), {
|
|
979
809
|
status: "success",
|
|
980
810
|
outputMessage: S,
|
|
981
|
-
sharedStatePatch: { portalGroupSummaryMemory: { value:
|
|
811
|
+
sharedStatePatch: { portalGroupSummaryMemory: { value: it } }
|
|
982
812
|
};
|
|
983
|
-
},
|
|
813
|
+
}, xe = o.object({
|
|
984
814
|
summary: o.string(),
|
|
985
815
|
followUpQuestions: o.array(o.string()).default([])
|
|
986
|
-
}),
|
|
816
|
+
}), ve = `
|
|
987
817
|
You summarize ArcGIS Portal groups based on structured context and deterministic activity signals.
|
|
988
818
|
|
|
989
819
|
${st}
|
|
@@ -1022,68 +852,242 @@ Group context:
|
|
|
1022
852
|
|
|
1023
853
|
Deterministic signals:
|
|
1024
854
|
{deterministicSignals}
|
|
1025
|
-
`,
|
|
855
|
+
`, $ = (e, t) => t ?? e, rt = f.Root({
|
|
1026
856
|
...N(),
|
|
1027
|
-
groupSummaryIntent:
|
|
1028
|
-
reducer:
|
|
857
|
+
groupSummaryIntent: f({
|
|
858
|
+
reducer: $,
|
|
1029
859
|
default: () => "clarify"
|
|
1030
860
|
}),
|
|
1031
|
-
groupSummaryGroupId:
|
|
1032
|
-
reducer:
|
|
861
|
+
groupSummaryGroupId: f({
|
|
862
|
+
reducer: $,
|
|
1033
863
|
default: () => null
|
|
1034
864
|
}),
|
|
1035
|
-
groupSummaryQuestion:
|
|
1036
|
-
reducer:
|
|
865
|
+
groupSummaryQuestion: f({
|
|
866
|
+
reducer: $,
|
|
1037
867
|
default: () => ""
|
|
1038
868
|
})
|
|
1039
|
-
}),
|
|
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:
|
|
1040
870
|
- summarizes ArcGIS portal groups from group context and sourceJSON details
|
|
1041
871
|
- answers follow-up questions grounded in the summarized group
|
|
1042
872
|
- suggests navigation to groups when relevant
|
|
1043
|
-
`,
|
|
873
|
+
`, Me = {
|
|
1044
874
|
id: "portal-group-analytics",
|
|
1045
875
|
name: "Portal Group Analytics",
|
|
876
|
+
description: Ge,
|
|
877
|
+
createGraph: Se,
|
|
878
|
+
workspace: rt
|
|
879
|
+
}, Ae = () => ({ latestItemId: null, memory: {} }), F = (e) => {
|
|
880
|
+
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) => {
|
|
887
|
+
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 ? {
|
|
890
|
+
status: "success",
|
|
891
|
+
outputMessage: (await b({
|
|
892
|
+
promptText: qe,
|
|
893
|
+
schema: Pe,
|
|
894
|
+
modelTier: "default",
|
|
895
|
+
inputVariables: {
|
|
896
|
+
summary: r.summary,
|
|
897
|
+
question: i,
|
|
898
|
+
fullContext: JSON.stringify(r.fullContext)
|
|
899
|
+
}
|
|
900
|
+
})).answer
|
|
901
|
+
} : {
|
|
902
|
+
status: "success",
|
|
903
|
+
outputMessage: "I don't have enough information yet. Please ask me to summarize the item first using summarize item <item id>."
|
|
904
|
+
};
|
|
905
|
+
}, qe = `
|
|
906
|
+
You answer follow-up questions about an ArcGIS item.
|
|
907
|
+
|
|
908
|
+
Ground your answer in the provided item context.
|
|
909
|
+
If the answer is not available from the provided context, state that clearly and suggest what to check next.
|
|
910
|
+
|
|
911
|
+
Response rules:
|
|
912
|
+
- Reply in concise markdown.
|
|
913
|
+
- Keep the answer focused on the follow-up question.
|
|
914
|
+
- Do not include internal identifiers.
|
|
915
|
+
- Mark isRelevant=false when the question is not about this item or cannot be grounded in this item context.
|
|
916
|
+
|
|
917
|
+
Item summary:
|
|
918
|
+
{summary}
|
|
919
|
+
|
|
920
|
+
Item full context
|
|
921
|
+
{fullContext}
|
|
922
|
+
|
|
923
|
+
Question:
|
|
924
|
+
{question}
|
|
925
|
+
`, $e = async (e, t) => {
|
|
926
|
+
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({
|
|
928
|
+
userMessage: s,
|
|
929
|
+
hasSummaryContext: String(a)
|
|
930
|
+
}), l = await U({
|
|
931
|
+
model: await D({ modelTier: "fast" }),
|
|
932
|
+
tools: [tt],
|
|
933
|
+
systemPrompt: r,
|
|
934
|
+
responseFormat: Te,
|
|
935
|
+
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;
|
|
937
|
+
return {
|
|
938
|
+
agentExecutionContext: { ...e.agentExecutionContext },
|
|
939
|
+
analyticsIntent: d ? "clarify" : u,
|
|
940
|
+
analyticsItemId: c || null,
|
|
941
|
+
analyticsQuestion: n || "",
|
|
942
|
+
status: "success",
|
|
943
|
+
outputMessage: d ? 'Please clarify with summarize item <item id>, summarize item #<title>, or summarize item #"<title with spaces>".' : ""
|
|
944
|
+
};
|
|
945
|
+
}, ke = `
|
|
946
|
+
Classify the user analytics request.
|
|
947
|
+
|
|
948
|
+
Rules:
|
|
949
|
+
- intent="summarize" only when the user explicitly asks to summarize/overview/recap an item.
|
|
950
|
+
- intent="followUp" for analytical questions about item details, including schema/fields/attributes/layers.
|
|
951
|
+
- intent="clarify" when neither summarize nor follow-up intent is clear.
|
|
952
|
+
- itemId must be the final resolved item id.
|
|
953
|
+
- If request has explicit item id, set itemId directly.
|
|
954
|
+
- If request references item title (for example #title, #"title with spaces", or plain quoted title), call resolvePortalItemIdByTitle and set itemId to the returned value.
|
|
955
|
+
- Never return item titles in output fields.
|
|
956
|
+
- If intent is "followUp", set question to the user's full question/request text.
|
|
957
|
+
- If intent is "summarize", set question="".
|
|
958
|
+
- When user asks to show/list/explain fields, schema, attributes, columns, or layer details, classify as "followUp" unless they explicitly request a summary.
|
|
959
|
+
- If hasSummaryContext is true, prefer "followUp" for detail-oriented requests that do not explicitly ask to summarize.
|
|
960
|
+
|
|
961
|
+
Examples:
|
|
962
|
+
- "Summarize item 0123456789abcdef0123456789abcdef" => summarize, itemId="0123456789abcdef0123456789abcdef"
|
|
963
|
+
- "Summarize item #california" => summarize, call resolvePortalItemIdByTitle("california") and set itemId to tool result
|
|
964
|
+
- "Summarize item #"california farmland"" => summarize, call resolvePortalItemIdByTitle("california farmland") and set itemId to tool result
|
|
965
|
+
- "Show the layer's available fields" => followUp
|
|
966
|
+
- "List attributes and explain what status means" => followUp
|
|
967
|
+
- "What fields are available?" with hasSummaryContext=true => followUp
|
|
968
|
+
- "Give me an overview of item 0123456789abcdef0123456789abcdef" => summarize
|
|
969
|
+
|
|
970
|
+
hasSummaryContext:
|
|
971
|
+
{hasSummaryContext}
|
|
972
|
+
|
|
973
|
+
User message:
|
|
974
|
+
{userMessage}
|
|
975
|
+
`, Ee = async (e, t) => {
|
|
976
|
+
const s = e.analyticsItemId;
|
|
977
|
+
if (!s)
|
|
978
|
+
return {
|
|
979
|
+
status: "success",
|
|
980
|
+
outputMessage: 'Please clarify with summarize item <item id>, summarize item #<title>, or summarize item #"<title with spaces>".'
|
|
981
|
+
};
|
|
982
|
+
await g({ text: `Summarizing item ${s}...`, agentName: "analytics" }, t);
|
|
983
|
+
const a = t?.configurable?.context;
|
|
984
|
+
I(a);
|
|
985
|
+
const { portal: r, user: i } = a, { result: l, error: u } = await bt(i, r, s);
|
|
986
|
+
if (u || !l)
|
|
987
|
+
return await g({ text: "Failed to get item context for summarization", agentName: "analytics" }, t), {
|
|
988
|
+
status: "success",
|
|
989
|
+
outputMessage: "Unable to retrieve item context for summarization."
|
|
990
|
+
};
|
|
991
|
+
const { context: c } = l, n = await b({
|
|
992
|
+
promptText: De,
|
|
993
|
+
schema: Ce,
|
|
994
|
+
modelTier: "default",
|
|
995
|
+
inputVariables: { context: JSON.stringify(c) }
|
|
996
|
+
}), { followUpQuestions: m, summary: p } = n, d = F(e), y = {
|
|
997
|
+
latestItemId: s,
|
|
998
|
+
memory: {
|
|
999
|
+
...d.memory,
|
|
1000
|
+
[s]: { summary: p, followUpQuestions: m, fullContext: c }
|
|
1001
|
+
}
|
|
1002
|
+
};
|
|
1003
|
+
return m.length && await E({ type: "suggested-prompts", data: { prompts: m } }, t), {
|
|
1004
|
+
status: "success",
|
|
1005
|
+
outputMessage: p,
|
|
1006
|
+
sharedStatePatch: { portalItemAnalyticsSummaryMemory: { value: y } }
|
|
1007
|
+
};
|
|
1008
|
+
}, De = `
|
|
1009
|
+
You are a item summary tool for ArcGIS. Your job is to summarize an item's info based on the provided context.
|
|
1010
|
+
Summary rules:
|
|
1011
|
+
- The summary should be concise markdown, make sure to format the output nicely so it's easy to read.
|
|
1012
|
+
- Target length: 80-150 words.
|
|
1013
|
+
- Provide one short descriptive paragraph.
|
|
1014
|
+
- Also propose 3 concise follow-up questions grounded in the item summary.
|
|
1015
|
+
- Keep follow-up questions specific and actionable.
|
|
1016
|
+
Follow-up questions rules:
|
|
1017
|
+
- These questions should be in the format of a prompt that the user can click on.
|
|
1018
|
+
- Make sure the questions are relevant to the item summary and that you can answer based solely on the provided context.
|
|
1019
|
+
Do not include internal identifiers.
|
|
1020
|
+
If the user asks for a detailed summary, you may expand the response up to 300 words.
|
|
1021
|
+
Item context:
|
|
1022
|
+
{context}
|
|
1023
|
+
`, k = (e, t) => t ?? e, ot = f.Root({
|
|
1024
|
+
...N(),
|
|
1025
|
+
// States shared only across nodes in the graph, not between invocations
|
|
1026
|
+
analyticsIntent: f({
|
|
1027
|
+
reducer: k,
|
|
1028
|
+
default: () => "clarify"
|
|
1029
|
+
}),
|
|
1030
|
+
analyticsItemId: f({
|
|
1031
|
+
reducer: k,
|
|
1032
|
+
default: () => null
|
|
1033
|
+
}),
|
|
1034
|
+
analyticsQuestion: f({
|
|
1035
|
+
reducer: k,
|
|
1036
|
+
default: () => ""
|
|
1037
|
+
})
|
|
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:
|
|
1039
|
+
- summarizes ArcGIS portal items from item context
|
|
1040
|
+
- suggests follow-up prompts grounded in the item
|
|
1041
|
+
`, Re = {
|
|
1042
|
+
id: "portal-item-analytics",
|
|
1043
|
+
name: "Portal Item Analytics",
|
|
1046
1044
|
description: Ue,
|
|
1047
1045
|
createGraph: ze,
|
|
1048
|
-
workspace:
|
|
1049
|
-
}, Fe =
|
|
1050
|
-
|
|
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) {
|
|
1049
|
+
if (!t)
|
|
1050
|
+
return;
|
|
1051
|
+
const { destinationType: s } = e;
|
|
1051
1052
|
switch (s) {
|
|
1052
1053
|
case "portal-content":
|
|
1053
|
-
return `${a}/content.html`;
|
|
1054
1054
|
case "portal-groups":
|
|
1055
|
-
return
|
|
1055
|
+
return t[s];
|
|
1056
1056
|
case "portal-item":
|
|
1057
|
-
return
|
|
1057
|
+
return t[s]?.(e.itemId);
|
|
1058
1058
|
case "portal-group":
|
|
1059
|
-
return
|
|
1059
|
+
return t[s]?.(e.groupId);
|
|
1060
1060
|
default:
|
|
1061
1061
|
return T(s);
|
|
1062
1062
|
}
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1063
|
+
}
|
|
1064
|
+
function Oe(e) {
|
|
1065
|
+
const t = Ft.safeParse(e);
|
|
1066
|
+
return t.success ? t.data : void 0;
|
|
1067
|
+
}
|
|
1068
|
+
class Ve extends lt {
|
|
1065
1069
|
constructor() {
|
|
1066
|
-
super(...arguments), this.t9n =
|
|
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) => {
|
|
1067
1071
|
const s = t.detail, a = s.data?.block;
|
|
1068
1072
|
if (!a)
|
|
1069
1073
|
return;
|
|
1070
1074
|
const r = this.getNavigationAction(a);
|
|
1071
1075
|
r && this.upsertNavigationSlotElement(s.slotName, r);
|
|
1072
|
-
}, this.inputText = "", this.showVoiceInput = !0, this.isListening = !1, this.isVoiceInputDisabled = !1, this.interrupt = null, this.autoDestroyDisabled = !1, this.defaultClosed = !1, this.arcgisPortalNavigationRequest =
|
|
1076
|
+
}, this.inputText = "", this.showVoiceInput = !0, this.isListening = !1, this.isVoiceInputDisabled = !1, this.interrupt = null, this.autoDestroyDisabled = !1, this.defaultClosed = !1, this.arcgisPortalNavigationRequest = ct();
|
|
1073
1077
|
}
|
|
1074
1078
|
static {
|
|
1075
|
-
this.properties = { inputText: 16, showVoiceInput: 16, isListening: 16, isVoiceInputDisabled: 16, interrupt: 16, autoDestroyDisabled: 5, portal: 0, user: 0, config: 0, defaultClosed: 5 };
|
|
1079
|
+
this.properties = { inputText: 16, showVoiceInput: 16, isListening: 16, isVoiceInputDisabled: 16, interrupt: 16, autoDestroyDisabled: 5, portal: 0, user: 0, config: 0, navigationTargetMap: 0, defaultClosed: 5 };
|
|
1076
1080
|
}
|
|
1077
1081
|
static {
|
|
1078
1082
|
this.styles = Fe;
|
|
1079
1083
|
}
|
|
1080
1084
|
getNavigationAction(t) {
|
|
1081
|
-
if (t?.type !==
|
|
1085
|
+
if (t?.type !== _)
|
|
1082
1086
|
return;
|
|
1083
|
-
const s =
|
|
1087
|
+
const s = Oe(t.data);
|
|
1084
1088
|
if (!s)
|
|
1085
1089
|
return;
|
|
1086
|
-
const a = je(s, this.
|
|
1090
|
+
const a = je(s, this.navigationTargetMap);
|
|
1087
1091
|
if (a)
|
|
1088
1092
|
return { href: a, targetDetail: s, label: this.getNavigationText(s.destinationType) };
|
|
1089
1093
|
}
|
|
@@ -1092,8 +1096,8 @@ class Oe extends ut {
|
|
|
1092
1096
|
if (!a)
|
|
1093
1097
|
return;
|
|
1094
1098
|
let r = this.navigationSlotElements.get(t);
|
|
1095
|
-
r || (r = document.createElement("div"), r.slot = t, this.navigationSlotElements.set(t, r), a.append(r)),
|
|
1096
|
-
|
|
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) => {
|
|
1100
|
+
i.preventDefault(), this.arcgisPortalNavigationRequest.emit({
|
|
1097
1101
|
href: s.href,
|
|
1098
1102
|
targetDetail: s.targetDetail
|
|
1099
1103
|
});
|
|
@@ -1115,7 +1119,7 @@ class Oe extends ut {
|
|
|
1115
1119
|
}
|
|
1116
1120
|
}
|
|
1117
1121
|
render() {
|
|
1118
|
-
const { t9n: t, inputText: s, portal: a, user: r, showVoiceInput:
|
|
1122
|
+
const { t9n: t, inputText: s, portal: a, user: r, navigationTargetMap: i, showVoiceInput: l, isListening: u, isVoiceInputDisabled: c } = this;
|
|
1119
1123
|
return G`<arcgis-assistant log-enabled keep-suggested-prompts .heading=${t.heading} .entryMessage=${t.entryMessage} @arcgisSlottableRequest=${this.handleSlottableRequest} @arcgisInterrupt=${({ detail: n }) => {
|
|
1120
1124
|
this.interrupt = n;
|
|
1121
1125
|
}} @arcgisInterruptCancel=${() => {
|
|
@@ -1128,8 +1132,8 @@ class Oe extends ut {
|
|
|
1128
1132
|
});
|
|
1129
1133
|
}} ${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) => {
|
|
1130
1134
|
n.preventDefault();
|
|
1131
|
-
const
|
|
1132
|
-
|
|
1135
|
+
const m = s.trim();
|
|
1136
|
+
m && (this.assistantEl.value?.submitMessage(m), this.inputText = "");
|
|
1133
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 }) => {
|
|
1134
1138
|
n.key === "Enter" && !n.shiftKey && (n.preventDefault(), this.formEl.value?.requestSubmit());
|
|
1135
1139
|
}} @arcgisUserMentionableTextAreaChange=${({ detail: n }) => {
|
|
@@ -1142,18 +1146,18 @@ class Oe extends ut {
|
|
|
1142
1146
|
n.detail.errorCode === "not-supported" && (this.showVoiceInput = !1);
|
|
1143
1147
|
}} @arcgisVoiceInputInterimTranscription=${(n) => {
|
|
1144
1148
|
this.inputText = n.detail.text;
|
|
1145
|
-
}} ${A(this.voiceInputEl)}></arcgis-portal-voice-input>${
|
|
1149
|
+
}} ${A(this.voiceInputEl)}></arcgis-portal-voice-input>${l && G`<calcite-button icon-start=microphone .label=${t.voiceInput} round .disabled=${c} .appearance=${u ? "solid" : "outline-fill"} @click=${async () => {
|
|
1146
1150
|
this.isVoiceInputDisabled = !0;
|
|
1147
1151
|
const n = this.voiceInputEl.value;
|
|
1148
|
-
|
|
1149
|
-
}}></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=${
|
|
1152
|
+
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 }) => {
|
|
1150
1154
|
this.assistantEl.value?.submitInterrupt(n);
|
|
1151
1155
|
}} @arcgisCancel=${() => {
|
|
1152
1156
|
this.assistantEl.value?.cancelInterrupt();
|
|
1153
1157
|
}}></arcgis-portal-ai-assistant-interrupt>` || ""}</arcgis-assistant>`;
|
|
1154
1158
|
}
|
|
1155
1159
|
}
|
|
1156
|
-
|
|
1160
|
+
ut("arcgis-portal-ai-assistant", Ve);
|
|
1157
1161
|
export {
|
|
1158
|
-
|
|
1162
|
+
Ve as ArcgisPortalAiAssistant
|
|
1159
1163
|
};
|