@arcgis/portal-components 5.2.0-next.2 → 5.2.0-next.21
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/25UUUQAQ.js +71 -0
- package/dist/cdn/{OQDPULPD.js → 2RGMWFHB.js} +1 -1
- package/dist/cdn/3KS5IDT2.js +2 -0
- package/dist/cdn/{AQWTJKUH.js → 3MQIRMUM.js} +9 -7
- package/dist/cdn/{JNRN6DTV.js → 47NPIL2S.js} +1 -1
- package/dist/cdn/{LQ3DMZ3K.js → 5VHBNEN3.js} +1 -1
- package/dist/cdn/6AGZRMJC.js +2 -0
- package/dist/cdn/6W2IHKCA.js +2 -0
- package/dist/cdn/{WOZDQW3S.js → DBKSQGEI.js} +1 -1
- package/dist/cdn/DFTUMKSN.js +3 -0
- package/dist/cdn/{YMPTDKT6.js → EETBNQU2.js} +1 -1
- package/dist/cdn/EHRAFAEA.js +65 -0
- package/dist/cdn/EKO6SVAF.js +2 -0
- package/dist/cdn/{GHQ3ZW4U.js → FI45QCN2.js} +1 -1
- package/dist/cdn/GEIZTD7F.js +2 -0
- package/dist/cdn/{ZTHTFEYA.js → HGSK6OFA.js} +1 -1
- package/dist/cdn/{LAFNDBTQ.js → HIRM34QB.js} +1 -1
- package/dist/cdn/HMBSJR37.js +2 -0
- package/dist/cdn/KT7PE6UE.js +2 -0
- package/dist/cdn/{BEHLBKKM.js → KY7Q7DH3.js} +1 -1
- package/dist/cdn/{5DPWJ7DI.js → KZWW4BWJ.js} +1 -1
- package/dist/cdn/{N6G6Z7BF.js → MH7KZ5G3.js} +256 -154
- package/dist/cdn/MLTQECPL.js +2 -0
- package/dist/cdn/{G47ZZQYL.js → OKRYML2G.js} +1 -1
- package/dist/cdn/PDL3DPMG.js +2 -0
- package/dist/cdn/{QNUYUNEY.js → QJ2UHWPU.js} +1 -1
- package/dist/cdn/{GT26WGJS.js → SXZRHHXC.js} +1 -1
- package/dist/cdn/TSLW4FSA.js +2 -0
- package/dist/cdn/{72N3KAXN.js → TW4LFQA5.js} +1 -1
- package/dist/cdn/{7WZHZP6U.js → UR7W4CEV.js} +8 -2
- package/dist/cdn/{W6PSG4GX.js → VRXKORTR.js} +9 -4
- package/dist/cdn/VXCB2YBR.js +3 -0
- package/dist/cdn/{DHHSKOUY.js → WJ2NMHDE.js} +1 -1
- package/dist/cdn/{2UUZHENH.js → WSNLUGEP.js} +1 -1
- package/dist/cdn/{53MSUMA3.js → XCZSPNKS.js} +16 -0
- package/dist/cdn/{K3HS2LQ7.js → YECI7XG3.js} +1 -1
- package/dist/cdn/ZDLFZJBT.js +2 -0
- package/dist/cdn/assets/portal-group-badges/t9n/messages.en.json +1 -0
- package/dist/cdn/assets/portal-group-card/t9n/messages.en.json +1 -0
- package/dist/cdn/assets/portal-item-type/icons/parquetfeaturelayer16.svg +1 -0
- package/dist/cdn/assets/portal-item-type/icons/parquetfeaturelayer32.svg +1 -0
- package/dist/cdn/assets/portal-item-type/icons/storymapframe16.svg +1 -0
- package/dist/cdn/assets/portal-item-type/icons/storymapframe32.svg +1 -0
- package/dist/cdn/assets/portal-item-type/t9n/messages.en.json +1 -1
- package/dist/cdn/assets/portal-user-popup/t9n/messages.en.json +1 -0
- package/dist/cdn/index.js +1 -1
- package/dist/cdn/main.css +1 -1
- package/dist/chunks/groups.js +7 -83
- package/dist/chunks/item2.js +86 -0
- package/dist/chunks/portal.js +48 -8
- package/dist/chunks/user2.js +26 -25
- 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 +797 -488
- package/dist/components/arcgis-portal-ai-assistant-interrupt/customElement.js +10 -10
- package/dist/components/arcgis-portal-group-badges/customElement.d.ts +102 -0
- package/dist/components/arcgis-portal-group-badges/customElement.js +50 -0
- package/dist/components/arcgis-portal-group-badges/index.d.ts +1 -0
- package/dist/components/arcgis-portal-group-badges/index.js +3 -0
- package/dist/components/arcgis-portal-group-badges/types.d.ts +3 -0
- package/dist/components/arcgis-portal-group-card/customElement.d.ts +167 -0
- package/dist/components/arcgis-portal-group-card/customElement.js +187 -0
- package/dist/components/arcgis-portal-group-card/index.d.ts +1 -0
- package/dist/components/arcgis-portal-group-card/index.js +8 -0
- package/dist/components/arcgis-portal-group-thumbnail/customElement.d.ts +32 -0
- package/dist/components/arcgis-portal-group-thumbnail/customElement.js +153 -0
- package/dist/components/arcgis-portal-group-thumbnail/index.d.ts +1 -0
- package/dist/components/arcgis-portal-group-thumbnail/index.js +3 -0
- package/dist/components/arcgis-portal-item-type/customElement.d.ts +2 -0
- package/dist/components/arcgis-portal-item-type/customElement.js +45 -37
- package/dist/components/arcgis-portal-mentionable-text-area/customElement.js +1 -1
- package/dist/components/arcgis-portal-replacement-item-redirect/customElement.js +53 -42
- package/dist/components/arcgis-portal-user-popup/customElement.d.ts +111 -0
- package/dist/components/arcgis-portal-user-popup/customElement.js +231 -0
- package/dist/components/arcgis-portal-user-popup/index.d.ts +1 -0
- package/dist/components/arcgis-portal-user-popup/index.js +5 -0
- package/dist/components/arcgis-portal-voice-input/customElement.d.ts +1 -1
- package/dist/docs/api.json +1 -1
- package/dist/docs/docs.json +1 -1
- package/dist/docs/vscode.html-custom-data.json +1 -1
- package/dist/docs/web-types.json +1 -1
- package/dist/index.d.ts +30 -2
- package/dist/loader.js +8 -4
- package/dist/types/lumina.d.ts +26 -1
- package/dist/types/preact.d.ts +30 -1
- package/dist/types/react.d.ts +34 -1
- package/dist/types/stencil.d.ts +26 -1
- package/dist/types/tracking.d.ts +10 -0
- package/dist/types/user.d.ts +2 -2
- package/package.json +7 -7
- package/dist/cdn/5VSDGPHH.js +0 -2
- package/dist/cdn/CI5ENGVT.js +0 -2
- package/dist/cdn/EVDOPN3G.js +0 -54
- package/dist/cdn/GNOZCQ34.js +0 -2
- package/dist/cdn/KEKBRUUC.js +0 -2
- package/dist/cdn/RNLVNDGG.js +0 -2
- package/dist/cdn/SM4GWLRA.js +0 -66
- package/dist/cdn/TMYTUOSS.js +0 -2
- package/dist/cdn/YG5YYL6X.js +0 -2
- /package/dist/cdn/{B7633S2A.js → 5NIJVBS7.js} +0 -0
|
@@ -1,302 +1,106 @@
|
|
|
1
1
|
/* COPYRIGHT Esri - https://js.arcgis.com/5.2/LICENSE.txt */
|
|
2
|
-
import { c as
|
|
3
|
-
import { LitElement as
|
|
4
|
-
import { css as
|
|
5
|
-
import { createRef as M, ref as
|
|
6
|
-
import { u as
|
|
7
|
-
import { a as
|
|
8
|
-
import {
|
|
9
|
-
import { sendTraceMessage as g, invokeStructuredPrompt as b,
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
import { Annotation as
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return a;
|
|
26
|
-
if (Array.isArray(a))
|
|
27
|
-
return a.map(
|
|
28
|
-
(r) => typeof r == "string" ? r : "text" in r && typeof r.text == "string" ? r.text : ""
|
|
29
|
-
).join(" ").trim();
|
|
30
|
-
}
|
|
31
|
-
return "";
|
|
32
|
-
}, pt = () => ({ latestItemId: null, memory: {} }), N = (s) => {
|
|
33
|
-
const t = s?.agentExecutionContext.sharedState.portalItemAnalyticsSummaryMemory?.value;
|
|
34
|
-
return t ? { latestItemId: t.latestItemId, memory: t.memory } : pt();
|
|
35
|
-
}, gt = n.object({
|
|
36
|
-
intent: n.enum(["summarize", "followUp", "clarify"]),
|
|
37
|
-
itemId: n.string().default(""),
|
|
38
|
-
question: n.string().default("")
|
|
39
|
-
}), ht = n.object({ summary: n.string(), followUpQuestions: n.array(n.string()).default([]) }), ft = n.object({ answer: n.string(), isRelevant: n.boolean() }), yt = async (s, t) => {
|
|
40
|
-
await g({ text: "Answering follow-up...", agentName: "analytics" }, t);
|
|
41
|
-
const e = N(s), a = s.analyticsItemId ?? e.latestItemId, r = a ? e.memory[a] : void 0, l = s.analyticsQuestion || x(s.agentExecutionContext.messages);
|
|
42
|
-
return r ? {
|
|
43
|
-
status: "success",
|
|
44
|
-
outputMessage: (await b({
|
|
45
|
-
promptText: bt,
|
|
46
|
-
schema: ft,
|
|
47
|
-
modelTier: "default",
|
|
48
|
-
inputVariables: {
|
|
49
|
-
summary: r.summary,
|
|
50
|
-
question: l,
|
|
51
|
-
fullContext: JSON.stringify(r.fullContext)
|
|
52
|
-
}
|
|
53
|
-
})).answer
|
|
54
|
-
} : {
|
|
55
|
-
status: "success",
|
|
56
|
-
outputMessage: "I don't have enough information yet. Please ask me to summarize the item first using summarize item <item id>."
|
|
57
|
-
};
|
|
58
|
-
}, bt = `
|
|
59
|
-
You answer follow-up questions about an ArcGIS item.
|
|
60
|
-
|
|
61
|
-
Ground your answer in the provided item context.
|
|
62
|
-
If the answer is not available from the provided context, state that clearly and suggest what to check next.
|
|
63
|
-
|
|
64
|
-
Response rules:
|
|
65
|
-
- Reply in concise markdown.
|
|
66
|
-
- Keep the answer focused on the follow-up question.
|
|
67
|
-
- Do not include internal identifiers.
|
|
68
|
-
- Mark isRelevant=false when the question is not about this item or cannot be grounded in this item context.
|
|
69
|
-
|
|
70
|
-
Item summary:
|
|
71
|
-
{summary}
|
|
72
|
-
|
|
73
|
-
Item full context
|
|
74
|
-
{fullContext}
|
|
75
|
-
|
|
76
|
-
Question:
|
|
77
|
-
{question}
|
|
78
|
-
`;
|
|
79
|
-
function I(s) {
|
|
80
|
-
const { portal: t, user: e } = s ?? {};
|
|
81
|
-
if (!s || !t || !e)
|
|
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
|
+
import { createRef as M, ref as A } from "lit/directives/ref.js";
|
|
6
|
+
import { u as pt } from "../../chunks/useT9n.js";
|
|
7
|
+
import { a as T, t as gt } from "../../chunks/functionalities.js";
|
|
8
|
+
import { NodeInterrupt as K, Annotation as f, StateGraph as C, START as P, END as h } from "@langchain/langgraph/web";
|
|
9
|
+
import { sendTraceMessage as g, invokeStructuredPrompt as b, sendUXSuggestion as E, createAgentRuntimeStateWithSharedState as N, createChatModel as D } from "@arcgis/ai-components/utils/index.js";
|
|
10
|
+
import o from "zod";
|
|
11
|
+
import { a as ft, c as ht, q as yt, s as wt, g as bt } from "../../chunks/item2.js";
|
|
12
|
+
import It from "@arcgis/core/identity/IdentityManager.js";
|
|
13
|
+
import j from "@arcgis/core/request.js";
|
|
14
|
+
import { ChatPromptTemplate as z } from "@langchain/core/prompts";
|
|
15
|
+
import { createAgent as U } from "langchain";
|
|
16
|
+
import { tool as W } from "@langchain/core/tools";
|
|
17
|
+
import { Annotation as xt } from "@langchain/langgraph";
|
|
18
|
+
import { c as vt, d as St, i as Gt, b as Mt, g as At } from "../../chunks/groups.js";
|
|
19
|
+
const Y = (e) => {
|
|
20
|
+
const { portal: t, user: s } = e ?? {};
|
|
21
|
+
return !!e && !!t && !!s;
|
|
22
|
+
};
|
|
23
|
+
function I(e) {
|
|
24
|
+
if (!Y(e))
|
|
82
25
|
throw new Error("Invalid context: PortalAssistantContext with portal and user is required.");
|
|
83
26
|
}
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return null;
|
|
89
|
-
const a = t?.configurable?.context;
|
|
90
|
-
I(a);
|
|
91
|
-
const { result: r, error: l } = await nt(a.portal, e, { num: 1 });
|
|
92
|
-
return l && console.error("Error searching for portal item by title:", l), r?.results[0]?.id || null;
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
name: "resolvePortalItemIdByTitle",
|
|
96
|
-
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.',
|
|
97
|
-
schema: n.object({
|
|
98
|
-
itemTitle: n.string().describe("The portal item title to resolve to an item id.")
|
|
99
|
-
})
|
|
100
|
-
}
|
|
101
|
-
), It = async (s, t) => {
|
|
102
|
-
await g({ text: "Analyzing intent...", agentName: "analytics" }, t);
|
|
103
|
-
const e = x(s.agentExecutionContext.messages), a = !!N(s).latestItemId, r = await L.fromTemplate(wt).format({
|
|
104
|
-
userMessage: e,
|
|
105
|
-
hasSummaryContext: String(a)
|
|
106
|
-
}), c = await Q({
|
|
107
|
-
model: await F("fast"),
|
|
108
|
-
tools: [W],
|
|
109
|
-
systemPrompt: r,
|
|
110
|
-
responseFormat: gt,
|
|
111
|
-
checkpointer: !0
|
|
112
|
-
}).invoke({ messages: s.agentExecutionContext.messages }, t), { intent: i, itemId: o, question: u } = c.structuredResponse, m = i === "clarify" || i === "summarize" && !o || i === "followUp" && !u;
|
|
113
|
-
return {
|
|
114
|
-
agentExecutionContext: { ...s.agentExecutionContext },
|
|
115
|
-
analyticsIntent: m ? "clarify" : i,
|
|
116
|
-
analyticsItemId: o || null,
|
|
117
|
-
analyticsQuestion: u || "",
|
|
118
|
-
status: "success",
|
|
119
|
-
outputMessage: m ? 'Please clarify with summarize item <item id>, summarize item #<title>, or summarize item #"<title with spaces>".' : ""
|
|
120
|
-
};
|
|
121
|
-
}, wt = `
|
|
122
|
-
Classify the user analytics request.
|
|
123
|
-
|
|
124
|
-
Rules:
|
|
125
|
-
- intent="summarize" only when the user explicitly asks to summarize/overview/recap an item.
|
|
126
|
-
- intent="followUp" for analytical questions about item details, including schema/fields/attributes/layers.
|
|
127
|
-
- intent="clarify" when neither summarize nor follow-up intent is clear.
|
|
128
|
-
- itemId must be the final resolved item id.
|
|
129
|
-
- If request has explicit item id, set itemId directly.
|
|
130
|
-
- If request references item title (for example #title, #"title with spaces", or plain quoted title), call resolvePortalItemIdByTitle and set itemId to the returned value.
|
|
131
|
-
- Never return item titles in output fields.
|
|
132
|
-
- If intent is "followUp", set question to the user's full question/request text.
|
|
133
|
-
- If intent is "summarize", set question="".
|
|
134
|
-
- When user asks to show/list/explain fields, schema, attributes, columns, or layer details, classify as "followUp" unless they explicitly request a summary.
|
|
135
|
-
- If hasSummaryContext is true, prefer "followUp" for detail-oriented requests that do not explicitly ask to summarize.
|
|
136
|
-
|
|
137
|
-
Examples:
|
|
138
|
-
- "Summarize item 0123456789abcdef0123456789abcdef" => summarize, itemId="0123456789abcdef0123456789abcdef"
|
|
139
|
-
- "Summarize item #california" => summarize, call resolvePortalItemIdByTitle("california") and set itemId to tool result
|
|
140
|
-
- "Summarize item #"california farmland"" => summarize, call resolvePortalItemIdByTitle("california farmland") and set itemId to tool result
|
|
141
|
-
- "Show the layer's available fields" => followUp
|
|
142
|
-
- "List attributes and explain what status means" => followUp
|
|
143
|
-
- "What fields are available?" with hasSummaryContext=true => followUp
|
|
144
|
-
- "Give me an overview of item 0123456789abcdef0123456789abcdef" => summarize
|
|
145
|
-
|
|
146
|
-
hasSummaryContext:
|
|
147
|
-
{hasSummaryContext}
|
|
148
|
-
|
|
149
|
-
User message:
|
|
150
|
-
{userMessage}
|
|
151
|
-
`, xt = async (s, t) => {
|
|
152
|
-
const e = s.analyticsItemId;
|
|
153
|
-
if (!e)
|
|
154
|
-
return {
|
|
155
|
-
status: "success",
|
|
156
|
-
outputMessage: 'Please clarify with summarize item <item id>, summarize item #<title>, or summarize item #"<title with spaces>".'
|
|
157
|
-
};
|
|
158
|
-
await g({ text: `Summarizing item ${e}...`, agentName: "analytics" }, t);
|
|
159
|
-
const a = t?.configurable?.context;
|
|
160
|
-
I(a);
|
|
161
|
-
const { portal: r, user: l } = a, { result: c, error: i } = await it(l, r, e);
|
|
162
|
-
if (i || !c)
|
|
163
|
-
return await g({ text: "Failed to get item context for summarization", agentName: "analytics" }, t), {
|
|
164
|
-
status: "success",
|
|
165
|
-
outputMessage: "Unable to retrieve item context for summarization."
|
|
166
|
-
};
|
|
167
|
-
const { context: o } = c, u = await b({
|
|
168
|
-
promptText: vt,
|
|
169
|
-
schema: ht,
|
|
170
|
-
modelTier: "default",
|
|
171
|
-
inputVariables: { context: JSON.stringify(o) }
|
|
172
|
-
}), { followUpQuestions: d, summary: p } = u, m = N(s), f = {
|
|
173
|
-
latestItemId: e,
|
|
174
|
-
memory: {
|
|
175
|
-
...m.memory,
|
|
176
|
-
[e]: { summary: p, followUpQuestions: d, fullContext: o }
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
return d.length && await B({ type: "suggested-prompts", data: { prompts: d } }, t), {
|
|
180
|
-
status: "success",
|
|
181
|
-
outputMessage: p,
|
|
182
|
-
sharedStatePatch: { portalItemAnalyticsSummaryMemory: { value: f } }
|
|
183
|
-
};
|
|
184
|
-
}, vt = `
|
|
185
|
-
You are a item summary tool for ArcGIS. Your job is to summarize an item's info based on the provided context.
|
|
186
|
-
Summary rules:
|
|
187
|
-
- The summary should be concise markdown, make sure to format the output nicely so it's easy to read.
|
|
188
|
-
- Target length: 80-150 words.
|
|
189
|
-
- Provide one short descriptive paragraph.
|
|
190
|
-
- Also propose 3 concise follow-up questions grounded in the item summary.
|
|
191
|
-
- Keep follow-up questions specific and actionable.
|
|
192
|
-
Follow-up questions rules:
|
|
193
|
-
- These questions should be in the format of a prompt that the user can click on.
|
|
194
|
-
- Make sure the questions are relevant to the item summary and that you can answer based solely on the provided context.
|
|
195
|
-
Do not include internal identifiers.
|
|
196
|
-
If the user asks for a detailed summary, you may expand the response up to 300 words.
|
|
197
|
-
Item context:
|
|
198
|
-
{context}
|
|
199
|
-
`, C = (s, t) => t ?? s, O = h.Root({
|
|
200
|
-
...E(),
|
|
201
|
-
// States shared only across nodes in the graph, not between invocations
|
|
202
|
-
analyticsIntent: h({
|
|
203
|
-
reducer: C,
|
|
204
|
-
default: () => "clarify"
|
|
205
|
-
}),
|
|
206
|
-
analyticsItemId: h({
|
|
207
|
-
reducer: C,
|
|
208
|
-
default: () => null
|
|
209
|
-
}),
|
|
210
|
-
analyticsQuestion: h({
|
|
211
|
-
reducer: C,
|
|
212
|
-
default: () => ""
|
|
213
|
-
})
|
|
214
|
-
}), St = () => new $(O).addNode("detectAnalyticsIntent", It).addNode("summarizePortalItem", xt).addNode("answerAnalyticsFollowUp", yt).addEdge(G, "detectAnalyticsIntent").addConditionalEdges("detectAnalyticsIntent", (t) => t.analyticsIntent === "summarize" ? "summarizePortalItem" : t.analyticsIntent === "followUp" ? "answerAnalyticsFollowUp" : y).addEdge("summarizePortalItem", y).addEdge("answerAnalyticsFollowUp", y), Mt = String.raw`- **portal-item-analytics** - Portal item analytics assistant:
|
|
215
|
-
- summarizes ArcGIS portal items from item context
|
|
216
|
-
- suggests follow-up prompts grounded in the item
|
|
217
|
-
`, Tt = {
|
|
218
|
-
id: "portal-item-analytics",
|
|
219
|
-
name: "Portal Item Analytics",
|
|
220
|
-
description: Mt,
|
|
221
|
-
createGraph: St,
|
|
222
|
-
workspace: O
|
|
223
|
-
}, Pt = (s) => s.map((t) => `"${t}"`).join(", "), At = n.object({
|
|
224
|
-
successMessage: n.string().default("")
|
|
225
|
-
}), q = "portal-group-creation", D = "approveAddMembers", Ct = async (s, t) => {
|
|
226
|
-
if (s.intentParams.intent !== "addMembers")
|
|
27
|
+
const Tt = (e) => e.map((t) => `"${t}"`).join(", "), Ct = o.object({
|
|
28
|
+
successMessage: o.string().default("")
|
|
29
|
+
}), O = "portal-group-creation", V = "approveAddMembers", Pt = async (e, t) => {
|
|
30
|
+
if (e.intentParams.intent !== "addMembers")
|
|
227
31
|
return {
|
|
228
32
|
status: "success",
|
|
229
33
|
outputMessage: "Use @mention usernames for the members you want to add."
|
|
230
34
|
};
|
|
231
|
-
const
|
|
232
|
-
if (!
|
|
35
|
+
const s = e.agentExecutionContext.sharedState.createdGroupId?.value;
|
|
36
|
+
if (!s)
|
|
233
37
|
return {
|
|
234
38
|
status: "success",
|
|
235
39
|
outputMessage: "Create a group first, then add members using @mention usernames."
|
|
236
40
|
};
|
|
237
|
-
const a =
|
|
41
|
+
const a = e.intentParams.memberInfo.memberIdentifiers.map((d) => d.trim()).filter(Boolean);
|
|
238
42
|
if (!a.length)
|
|
239
43
|
return {
|
|
240
44
|
status: "success",
|
|
241
45
|
outputMessage: "Use @mention usernames for the members you want to add."
|
|
242
46
|
};
|
|
243
|
-
const
|
|
47
|
+
const i = `The following member(s) will be added to the newly created group:
|
|
244
48
|
|
|
245
|
-
${a.map((
|
|
49
|
+
${a.map((d) => `- **@${d}**`).join(`
|
|
246
50
|
`)}
|
|
247
51
|
|
|
248
|
-
Do you want to continue?`, { hitlResponse:
|
|
249
|
-
if (
|
|
250
|
-
const
|
|
251
|
-
agentId:
|
|
252
|
-
id:
|
|
52
|
+
Do you want to continue?`, { hitlResponse: l } = t?.configurable ?? {};
|
|
53
|
+
if (l?.agentId !== O || l.id !== V) {
|
|
54
|
+
const d = {
|
|
55
|
+
agentId: O,
|
|
56
|
+
id: V,
|
|
253
57
|
kind: "booleanChoice",
|
|
254
|
-
message:
|
|
58
|
+
message: i,
|
|
255
59
|
metadata: {
|
|
256
60
|
action: "addMembers",
|
|
257
|
-
groupId:
|
|
61
|
+
groupId: s,
|
|
258
62
|
members: [...a]
|
|
259
63
|
}
|
|
260
64
|
};
|
|
261
|
-
throw new
|
|
65
|
+
throw new K(d);
|
|
262
66
|
}
|
|
263
|
-
if (
|
|
67
|
+
if (l.payload !== !0)
|
|
264
68
|
return {
|
|
265
69
|
status: "success",
|
|
266
70
|
outputMessage: "Okay, I cancelled adding members to the group."
|
|
267
71
|
};
|
|
268
72
|
await g(
|
|
269
|
-
{ text: `Adding members ${
|
|
73
|
+
{ text: `Adding members ${Tt(a)}...`, agentName: "group-creation" },
|
|
270
74
|
t
|
|
271
75
|
);
|
|
272
|
-
const
|
|
273
|
-
I(
|
|
274
|
-
const { result:
|
|
275
|
-
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)
|
|
276
80
|
return {
|
|
277
81
|
status: "success",
|
|
278
82
|
outputMessage: "I could not add members to that group. Please confirm group access and user accounts, then try again."
|
|
279
83
|
};
|
|
280
|
-
const { addedUsernames:
|
|
84
|
+
const { addedUsernames: m, notAddedUsers: p } = c;
|
|
281
85
|
try {
|
|
282
|
-
const
|
|
283
|
-
promptText:
|
|
284
|
-
schema:
|
|
86
|
+
const y = (await b({
|
|
87
|
+
promptText: Nt,
|
|
88
|
+
schema: Ct,
|
|
285
89
|
modelTier: "fast",
|
|
286
90
|
inputVariables: {
|
|
287
|
-
addedMembers:
|
|
91
|
+
addedMembers: m.join(", "),
|
|
288
92
|
notAddedMembers: JSON.stringify(
|
|
289
93
|
p.map((v) => ({ username: v.username, reason: v.error.message }))
|
|
290
94
|
)
|
|
291
95
|
}
|
|
292
96
|
})).successMessage;
|
|
293
|
-
if (
|
|
294
|
-
return { status: "success", outputMessage:
|
|
295
|
-
} catch (
|
|
296
|
-
console.error("Error generating add-members success message:",
|
|
97
|
+
if (y)
|
|
98
|
+
return { status: "success", outputMessage: y };
|
|
99
|
+
} catch (d) {
|
|
100
|
+
console.error("Error generating add-members success message:", d);
|
|
297
101
|
}
|
|
298
102
|
return {};
|
|
299
|
-
},
|
|
103
|
+
}, Nt = `
|
|
300
104
|
Write a concise, friendly success message for adding members to a group.
|
|
301
105
|
|
|
302
106
|
Rules:
|
|
@@ -311,59 +115,59 @@ Added members:
|
|
|
311
115
|
|
|
312
116
|
Not added members:
|
|
313
117
|
{notAddedMembers}
|
|
314
|
-
`,
|
|
315
|
-
successMessage:
|
|
316
|
-
}),
|
|
317
|
-
failureMessage:
|
|
318
|
-
}),
|
|
319
|
-
if (
|
|
118
|
+
`, B = "portal-group-creation", Q = "approveCreateGroup", qt = o.object({
|
|
119
|
+
successMessage: o.string().default("")
|
|
120
|
+
}), $t = o.object({
|
|
121
|
+
failureMessage: o.string().default("")
|
|
122
|
+
}), kt = async (e, t) => {
|
|
123
|
+
if (e.intentParams.intent !== "create")
|
|
320
124
|
return {
|
|
321
125
|
status: "success",
|
|
322
126
|
outputMessage: "Tell me the group title you want to use."
|
|
323
127
|
};
|
|
324
|
-
const
|
|
325
|
-
if (!
|
|
128
|
+
const s = e.intentParams.title.trim();
|
|
129
|
+
if (!s)
|
|
326
130
|
return {
|
|
327
131
|
status: "success",
|
|
328
132
|
outputMessage: "What title would you like for the new group?"
|
|
329
133
|
};
|
|
330
|
-
const a = `A group with the title **${
|
|
331
|
-
if (r?.agentId !==
|
|
332
|
-
const
|
|
333
|
-
agentId:
|
|
334
|
-
id:
|
|
134
|
+
const a = `A group with the title **${s}** will be created. Do you want to continue?`, { hitlResponse: r } = t?.configurable;
|
|
135
|
+
if (r?.agentId !== B || r.id !== Q) {
|
|
136
|
+
const n = {
|
|
137
|
+
agentId: B,
|
|
138
|
+
id: Q,
|
|
335
139
|
kind: "booleanChoice",
|
|
336
140
|
message: a,
|
|
337
141
|
metadata: {
|
|
338
142
|
action: "createGroup",
|
|
339
|
-
title:
|
|
143
|
+
title: s,
|
|
340
144
|
access: "private"
|
|
341
145
|
}
|
|
342
146
|
};
|
|
343
|
-
throw new
|
|
147
|
+
throw new K(n);
|
|
344
148
|
}
|
|
345
149
|
if (r.payload !== !0)
|
|
346
150
|
return {
|
|
347
151
|
status: "success",
|
|
348
|
-
outputMessage: `Okay, I cancelled creating **${
|
|
152
|
+
outputMessage: `Okay, I cancelled creating **${s}**.`
|
|
349
153
|
};
|
|
350
|
-
await g({ text: `Creating group "${
|
|
351
|
-
const
|
|
352
|
-
I(
|
|
353
|
-
const { result:
|
|
354
|
-
title:
|
|
154
|
+
await g({ text: `Creating group "${s}"...`, agentName: "group-creation" }, t);
|
|
155
|
+
const i = t?.configurable?.context;
|
|
156
|
+
I(i);
|
|
157
|
+
const { result: l, error: u } = await ht(i.portal, {
|
|
158
|
+
title: s,
|
|
355
159
|
access: "private"
|
|
356
160
|
});
|
|
357
|
-
if (
|
|
358
|
-
const
|
|
161
|
+
if (u || !l) {
|
|
162
|
+
const n = u?.message?.trim() || "No additional details were provided.";
|
|
359
163
|
try {
|
|
360
164
|
const p = (await b({
|
|
361
|
-
promptText:
|
|
362
|
-
schema:
|
|
165
|
+
promptText: Dt,
|
|
166
|
+
schema: $t,
|
|
363
167
|
modelTier: "fast",
|
|
364
168
|
inputVariables: {
|
|
365
|
-
groupTitle:
|
|
366
|
-
failureReason:
|
|
169
|
+
groupTitle: s,
|
|
170
|
+
failureReason: n
|
|
367
171
|
}
|
|
368
172
|
})).failureMessage.trim();
|
|
369
173
|
if (p)
|
|
@@ -371,36 +175,36 @@ Not added members:
|
|
|
371
175
|
status: "success",
|
|
372
176
|
outputMessage: p
|
|
373
177
|
};
|
|
374
|
-
} catch (
|
|
375
|
-
console.error("Error generating create-group failure message:",
|
|
178
|
+
} catch (m) {
|
|
179
|
+
console.error("Error generating create-group failure message:", m);
|
|
376
180
|
}
|
|
377
181
|
return {
|
|
378
182
|
status: "success",
|
|
379
183
|
outputMessage: "I could not create that group. Please confirm your permissions and try again with the group title."
|
|
380
184
|
};
|
|
381
185
|
}
|
|
382
|
-
const
|
|
186
|
+
const c = l.id;
|
|
383
187
|
try {
|
|
384
|
-
const
|
|
385
|
-
promptText:
|
|
386
|
-
schema:
|
|
188
|
+
const m = (await b({
|
|
189
|
+
promptText: Et,
|
|
190
|
+
schema: qt,
|
|
387
191
|
modelTier: "fast",
|
|
388
192
|
inputVariables: {
|
|
389
|
-
groupTitle:
|
|
193
|
+
groupTitle: s
|
|
390
194
|
}
|
|
391
195
|
})).successMessage.trim();
|
|
392
|
-
if (
|
|
196
|
+
if (m)
|
|
393
197
|
return {
|
|
394
198
|
status: "success",
|
|
395
|
-
outputMessage:
|
|
396
|
-
sharedStatePatch: { createdGroupId: { value:
|
|
397
|
-
createdGroupId:
|
|
199
|
+
outputMessage: m,
|
|
200
|
+
sharedStatePatch: { createdGroupId: { value: c } },
|
|
201
|
+
createdGroupId: c
|
|
398
202
|
};
|
|
399
|
-
} catch (
|
|
400
|
-
console.error("Error generating create-group success message:",
|
|
203
|
+
} catch (n) {
|
|
204
|
+
console.error("Error generating create-group success message:", n);
|
|
401
205
|
}
|
|
402
206
|
return {};
|
|
403
|
-
},
|
|
207
|
+
}, Et = `
|
|
404
208
|
Write a concise, friendly success message after creating a portal group.
|
|
405
209
|
|
|
406
210
|
Rules:
|
|
@@ -411,7 +215,7 @@ Rules:
|
|
|
411
215
|
|
|
412
216
|
Group title:
|
|
413
217
|
{groupTitle}
|
|
414
|
-
`,
|
|
218
|
+
`, Dt = `
|
|
415
219
|
Write a concise, friendly failure message after an attempt to create a portal group.
|
|
416
220
|
|
|
417
221
|
Rules:
|
|
@@ -426,25 +230,39 @@ Group title:
|
|
|
426
230
|
|
|
427
231
|
Failure reason:
|
|
428
232
|
{failureReason}
|
|
429
|
-
`,
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
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({
|
|
248
|
+
intent: o.enum(["clarify", "create", "addMembers"]).default("clarify"),
|
|
249
|
+
title: o.string().default(""),
|
|
250
|
+
memberIdentifiers: o.array(o.string()).default([]),
|
|
251
|
+
clarifyMessage: o.string().default("")
|
|
252
|
+
}), Ut = async (e, t) => {
|
|
435
253
|
await g({ text: "Thinking about groups...", agentName: "group-creation" }, t);
|
|
436
|
-
const
|
|
437
|
-
promptText:
|
|
438
|
-
schema:
|
|
254
|
+
const s = x(e.agentExecutionContext.messages).trim(), a = await b({
|
|
255
|
+
promptText: Rt,
|
|
256
|
+
schema: zt,
|
|
439
257
|
modelTier: "default",
|
|
440
|
-
inputVariables: { userMessage:
|
|
441
|
-
}), r = a.title.trim(),
|
|
258
|
+
inputVariables: { userMessage: s }
|
|
259
|
+
}), r = a.title.trim(), i = a.memberIdentifiers.filter(Boolean), l = a.clarifyMessage.trim(), u = a.intent === "create" && !!r, c = a.intent === "addMembers" && i.length > 0;
|
|
442
260
|
return {
|
|
443
|
-
intentParams:
|
|
261
|
+
intentParams: u ? { intent: "create", title: r } : c ? { intent: "addMembers", memberInfo: { memberIdentifiers: i } } : { intent: "clarify" },
|
|
444
262
|
status: "success",
|
|
445
|
-
outputMessage: !
|
|
263
|
+
outputMessage: !u && !c ? l : ""
|
|
446
264
|
};
|
|
447
|
-
},
|
|
265
|
+
}, Rt = `
|
|
448
266
|
You classify whether a user is asking to create a new ArcGIS Portal group or add members to an existing group.
|
|
449
267
|
|
|
450
268
|
Rules:
|
|
@@ -470,142 +288,138 @@ Examples:
|
|
|
470
288
|
|
|
471
289
|
User message:
|
|
472
290
|
{userMessage}
|
|
473
|
-
`,
|
|
474
|
-
|
|
475
|
-
destinationType:
|
|
291
|
+
`, Ft = o.discriminatedUnion("destinationType", [
|
|
292
|
+
o.object({
|
|
293
|
+
destinationType: o.literal("portal-content")
|
|
476
294
|
}),
|
|
477
|
-
|
|
478
|
-
destinationType:
|
|
295
|
+
o.object({
|
|
296
|
+
destinationType: o.literal("portal-groups")
|
|
479
297
|
}),
|
|
480
|
-
|
|
481
|
-
destinationType:
|
|
482
|
-
itemId:
|
|
298
|
+
o.object({
|
|
299
|
+
destinationType: o.literal("portal-item"),
|
|
300
|
+
itemId: o.string().trim().min(1)
|
|
483
301
|
}),
|
|
484
|
-
|
|
485
|
-
destinationType:
|
|
486
|
-
groupId:
|
|
302
|
+
o.object({
|
|
303
|
+
destinationType: o.literal("portal-group"),
|
|
304
|
+
groupId: o.string().trim().min(1)
|
|
487
305
|
})
|
|
488
|
-
])
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
const e = s.createdGroupId ?? s.agentExecutionContext.sharedState.createdGroupId?.value;
|
|
497
|
-
return e ? (await g({ text: "Preparing navigation...", agentName: "group-creation" }, t), await J({ destinationType: "portal-group", groupId: e }, t), {}) : {};
|
|
498
|
-
}, z = (s, t) => t ?? s, Y = h.Root({
|
|
499
|
-
...E(),
|
|
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) => {
|
|
310
|
+
const s = e.createdGroupId ?? e.agentExecutionContext.sharedState.createdGroupId?.value;
|
|
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({
|
|
313
|
+
...N(),
|
|
500
314
|
// * Shared state between nodes (but not persisted to the agent execution context)
|
|
501
315
|
/** Parameters related to the user's intent for group creation actions */
|
|
502
|
-
intentParams:
|
|
316
|
+
intentParams: f({ reducer: L, default: () => ({ intent: "clarify" }) }),
|
|
503
317
|
/** The ID of the group that was created
|
|
504
318
|
* even though we already have this in the shared state
|
|
505
319
|
* we still need it here to also share between nodes
|
|
506
320
|
*/
|
|
507
|
-
createdGroupId:
|
|
508
|
-
}),
|
|
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) => {
|
|
509
323
|
switch (t.intentParams.intent) {
|
|
510
324
|
case "create":
|
|
511
325
|
return "createPortalGroup";
|
|
512
326
|
case "addMembers":
|
|
513
327
|
return "addMembersToPortalGroup";
|
|
514
328
|
default:
|
|
515
|
-
return
|
|
329
|
+
return h;
|
|
516
330
|
}
|
|
517
|
-
}).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:
|
|
518
332
|
- creates a new ArcGIS Portal group for the signed-in user
|
|
519
333
|
- adds users to the newly created group using @mention usernames
|
|
520
|
-
`,
|
|
334
|
+
`, Bt = {
|
|
521
335
|
id: "portal-group-creation",
|
|
522
336
|
name: "Portal Group Creation",
|
|
523
|
-
description:
|
|
524
|
-
createGraph:
|
|
525
|
-
workspace:
|
|
526
|
-
},
|
|
527
|
-
const t =
|
|
337
|
+
description: Vt,
|
|
338
|
+
createGraph: Ot,
|
|
339
|
+
workspace: H
|
|
340
|
+
}, X = "portalDocAssistantMemory", Qt = () => ({ conversationId: "" }), Lt = (e) => {
|
|
341
|
+
const t = e?.[X]?.value;
|
|
528
342
|
if (!t || typeof t != "object")
|
|
529
343
|
return Qt();
|
|
530
|
-
const
|
|
344
|
+
const s = t;
|
|
531
345
|
return {
|
|
532
|
-
conversationId: typeof
|
|
346
|
+
conversationId: typeof s.conversationId == "string" ? s.conversationId : ""
|
|
533
347
|
};
|
|
534
|
-
},
|
|
535
|
-
[
|
|
348
|
+
}, Jt = (e) => ({
|
|
349
|
+
[X]: { value: e }
|
|
536
350
|
});
|
|
537
|
-
async function
|
|
538
|
-
portal:
|
|
351
|
+
async function Kt({
|
|
352
|
+
portal: e,
|
|
539
353
|
question: t,
|
|
540
|
-
persona:
|
|
354
|
+
persona: s,
|
|
541
355
|
previousConversationId: a,
|
|
542
356
|
signal: r,
|
|
543
|
-
skillId:
|
|
357
|
+
skillId: i
|
|
544
358
|
}) {
|
|
545
|
-
|
|
546
|
-
const
|
|
547
|
-
portal:
|
|
548
|
-
skillId:
|
|
359
|
+
i ??= "doc_ai_assistant";
|
|
360
|
+
const u = await Wt({
|
|
361
|
+
portal: e,
|
|
362
|
+
skillId: i,
|
|
549
363
|
message: t,
|
|
550
364
|
options: { context: {
|
|
551
365
|
kind: "DocAIAssistantRequest",
|
|
552
|
-
filters: { persona: { persona:
|
|
366
|
+
filters: { persona: { persona: s } }
|
|
553
367
|
}, previousConversationId: a, signal: r }
|
|
554
368
|
});
|
|
555
369
|
return {
|
|
556
|
-
reply:
|
|
557
|
-
conversationId:
|
|
370
|
+
reply: Yt(u, i),
|
|
371
|
+
conversationId: u[0]?.conversationId ?? ""
|
|
558
372
|
};
|
|
559
373
|
}
|
|
560
|
-
async function
|
|
561
|
-
portal:
|
|
374
|
+
async function Wt({
|
|
375
|
+
portal: e,
|
|
562
376
|
skillId: t,
|
|
563
|
-
message:
|
|
377
|
+
message: s,
|
|
564
378
|
options: a
|
|
565
379
|
}) {
|
|
566
|
-
const
|
|
380
|
+
const i = `${e.helperServices.aiAssistantServices.url}/skills/${t}/chat`, l = {
|
|
567
381
|
"Content-Type": "application/json",
|
|
568
|
-
token:
|
|
569
|
-
},
|
|
382
|
+
token: It.findCredential(e.url)?.token ?? ""
|
|
383
|
+
}, u = await j(i, {
|
|
570
384
|
method: "post",
|
|
571
385
|
body: JSON.stringify({
|
|
572
|
-
message:
|
|
386
|
+
message: s,
|
|
573
387
|
context: a.context,
|
|
574
388
|
conversationId: a.previousConversationId
|
|
575
389
|
}),
|
|
576
|
-
headers:
|
|
390
|
+
headers: l,
|
|
577
391
|
signal: a.signal
|
|
578
392
|
});
|
|
579
|
-
if (
|
|
580
|
-
throw new Error(`Doc assistant chat failed (${
|
|
581
|
-
cause:
|
|
393
|
+
if (u.httpStatus !== 200)
|
|
394
|
+
throw new Error(`Doc assistant chat failed (${u.httpStatus})`, {
|
|
395
|
+
cause: u.data
|
|
582
396
|
});
|
|
583
|
-
const
|
|
397
|
+
const c = u.data, n = [c], { conversationId: m, inquiryId: p } = c, d = async (y, v) => {
|
|
584
398
|
if (!v)
|
|
585
399
|
return;
|
|
586
|
-
await
|
|
587
|
-
const
|
|
400
|
+
await gt(1e3);
|
|
401
|
+
const w = await j(i, {
|
|
588
402
|
method: "post",
|
|
589
|
-
body: JSON.stringify({ conversationId:
|
|
590
|
-
headers:
|
|
403
|
+
body: JSON.stringify({ conversationId: m, inquiryId: p, ackSequenceNumber: y }),
|
|
404
|
+
headers: l,
|
|
591
405
|
signal: a.signal
|
|
592
406
|
});
|
|
593
|
-
if (
|
|
594
|
-
throw new Error(`Doc assistant poll failed (${
|
|
595
|
-
cause:
|
|
407
|
+
if (w.httpStatus !== 200)
|
|
408
|
+
throw new Error(`Doc assistant poll failed (${w.httpStatus})`, {
|
|
409
|
+
cause: w.data
|
|
596
410
|
});
|
|
597
|
-
const
|
|
598
|
-
|
|
411
|
+
const S = w.data;
|
|
412
|
+
n.push(S), await d(S.sequenceNumber, S.hasMore);
|
|
599
413
|
};
|
|
600
|
-
return
|
|
414
|
+
return c.hasMore && await d(c.sequenceNumber, c.hasMore), n;
|
|
601
415
|
}
|
|
602
|
-
function
|
|
416
|
+
function Yt(e, t) {
|
|
603
417
|
switch (t) {
|
|
604
418
|
case "doc_chat":
|
|
605
|
-
return
|
|
419
|
+
return e.find((s) => s.message != null)?.message ?? "";
|
|
606
420
|
case "doc_ai_assistant":
|
|
607
|
-
for (let
|
|
608
|
-
const a = s
|
|
421
|
+
for (let s = e.length - 1; s >= 0; s -= 1) {
|
|
422
|
+
const a = e[s];
|
|
609
423
|
if (a.context?.kind === "DocAIAssistantContext") {
|
|
610
424
|
const r = a.context.results?.[0]?.reply;
|
|
611
425
|
if (r)
|
|
@@ -614,42 +428,42 @@ function Jt(s, t) {
|
|
|
614
428
|
}
|
|
615
429
|
return "";
|
|
616
430
|
default:
|
|
617
|
-
return
|
|
431
|
+
return T(t);
|
|
618
432
|
}
|
|
619
433
|
}
|
|
620
|
-
const
|
|
434
|
+
const _t = async (e, t) => {
|
|
621
435
|
await g({ text: "Asking documentation assistant...", agentName: "doc-assistant" }, t);
|
|
622
|
-
const
|
|
623
|
-
if (!
|
|
436
|
+
const s = x(e.agentExecutionContext.messages).trim();
|
|
437
|
+
if (!s)
|
|
624
438
|
return {
|
|
625
439
|
status: "success",
|
|
626
440
|
outputMessage: "Please share your question and I can help with ArcGIS and Portal documentation."
|
|
627
441
|
};
|
|
628
442
|
const a = t?.configurable?.context;
|
|
629
443
|
I(a);
|
|
630
|
-
const r =
|
|
444
|
+
const r = Lt(e.agentExecutionContext.sharedState), { reply: i, conversationId: l } = await Kt({
|
|
631
445
|
portal: a.portal,
|
|
632
|
-
question:
|
|
446
|
+
question: s,
|
|
633
447
|
previousConversationId: r.conversationId || void 0,
|
|
634
448
|
skillId: "doc_ai_assistant",
|
|
635
449
|
persona: "developers"
|
|
636
450
|
});
|
|
637
451
|
return {
|
|
638
452
|
status: "success",
|
|
639
|
-
outputMessage:
|
|
640
|
-
sharedStatePatch:
|
|
641
|
-
conversationId:
|
|
453
|
+
outputMessage: i.trim() || "I could not retrieve a response from the documentation assistant.",
|
|
454
|
+
sharedStatePatch: Jt({
|
|
455
|
+
conversationId: l || r.conversationId
|
|
642
456
|
})
|
|
643
457
|
};
|
|
644
|
-
},
|
|
645
|
-
async ({ groupTitle:
|
|
646
|
-
const
|
|
647
|
-
if (!
|
|
458
|
+
}, Z = W(
|
|
459
|
+
async ({ groupTitle: e }, t) => {
|
|
460
|
+
const s = e.trim();
|
|
461
|
+
if (!s)
|
|
648
462
|
return null;
|
|
649
463
|
const a = t?.configurable?.context;
|
|
650
464
|
I(a);
|
|
651
465
|
try {
|
|
652
|
-
return (await
|
|
466
|
+
return (await yt(a.portal, { query: `title:${s}`, num: 1 }))?.results[0]?.id || null;
|
|
653
467
|
} catch (r) {
|
|
654
468
|
return console.error("Error searching for portal group by title:", r), null;
|
|
655
469
|
}
|
|
@@ -657,41 +471,58 @@ const Yt = async (s, t) => {
|
|
|
657
471
|
{
|
|
658
472
|
name: "resolvePortalGroupIdByTitle",
|
|
659
473
|
description: "Resolves an ArcGIS Portal group title to the best-match group id. Use this when a user references a group by title instead of an explicit group id.",
|
|
660
|
-
schema:
|
|
661
|
-
groupTitle:
|
|
474
|
+
schema: o.object({
|
|
475
|
+
groupTitle: o.string().describe("The portal group title to resolve to a group id.")
|
|
662
476
|
})
|
|
663
477
|
}
|
|
664
|
-
),
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
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
|
+
}
|
|
495
|
+
), J = o.object({
|
|
496
|
+
shouldSuggestNavigation: o.boolean().default(!1),
|
|
497
|
+
destinationType: o.enum(["none", "portal-content", "portal-item", "portal-groups", "portal-group"]).default("none"),
|
|
498
|
+
itemId: o.string().default(""),
|
|
499
|
+
groupId: o.string().default("")
|
|
500
|
+
}), Ht = async (e, t) => {
|
|
670
501
|
await g({ text: "Extracting navigation intent...", agentName: "doc-assistant" }, t);
|
|
671
|
-
const
|
|
672
|
-
if (!
|
|
502
|
+
const s = e.outputMessage.trim();
|
|
503
|
+
if (!s)
|
|
673
504
|
return {};
|
|
674
|
-
const a = x(
|
|
505
|
+
const a = x(e.agentExecutionContext.messages).trim(), r = await z.fromTemplate(Zt).format({
|
|
675
506
|
question: a,
|
|
676
|
-
response:
|
|
677
|
-
}),
|
|
678
|
-
model: await
|
|
679
|
-
tools: [
|
|
507
|
+
response: s
|
|
508
|
+
}), l = await U({
|
|
509
|
+
model: await D({ modelTier: "default" }),
|
|
510
|
+
tools: [tt, Z],
|
|
680
511
|
systemPrompt: r,
|
|
681
|
-
responseFormat:
|
|
512
|
+
responseFormat: J,
|
|
682
513
|
checkpointer: !0
|
|
683
|
-
}).invoke({ messages:
|
|
684
|
-
if (!
|
|
514
|
+
}).invoke({ messages: e.agentExecutionContext.messages }, t), u = J.parse(l.structuredResponse ?? {});
|
|
515
|
+
if (!u.shouldSuggestNavigation || u.destinationType === "none")
|
|
685
516
|
return {};
|
|
686
|
-
const
|
|
687
|
-
return
|
|
517
|
+
const c = Xt(u);
|
|
518
|
+
return c ? (await R(c, t), {}) : {};
|
|
688
519
|
};
|
|
689
|
-
function
|
|
690
|
-
destinationType:
|
|
520
|
+
function Xt({
|
|
521
|
+
destinationType: e,
|
|
691
522
|
itemId: t,
|
|
692
|
-
groupId:
|
|
523
|
+
groupId: s
|
|
693
524
|
}) {
|
|
694
|
-
switch (
|
|
525
|
+
switch (e) {
|
|
695
526
|
case "portal-content":
|
|
696
527
|
return { destinationType: "portal-content" };
|
|
697
528
|
case "portal-groups":
|
|
@@ -699,14 +530,14 @@ function Zt({
|
|
|
699
530
|
case "portal-item":
|
|
700
531
|
return t ? { destinationType: "portal-item", itemId: t } : null;
|
|
701
532
|
case "portal-group":
|
|
702
|
-
return
|
|
533
|
+
return s ? { destinationType: "portal-group", groupId: s } : null;
|
|
703
534
|
case "none":
|
|
704
535
|
return null;
|
|
705
536
|
default:
|
|
706
|
-
return
|
|
537
|
+
return T(e);
|
|
707
538
|
}
|
|
708
539
|
}
|
|
709
|
-
const
|
|
540
|
+
const Zt = `
|
|
710
541
|
You decide whether the assistant response should include a navigation action to ArcGIS Portal.
|
|
711
542
|
|
|
712
543
|
Given the user question and assistant response:
|
|
@@ -730,125 +561,603 @@ User question:
|
|
|
730
561
|
|
|
731
562
|
Assistant response:
|
|
732
563
|
{response}
|
|
733
|
-
`,
|
|
734
|
-
...
|
|
735
|
-
}),
|
|
564
|
+
`, et = xt.Root({
|
|
565
|
+
...N()
|
|
566
|
+
}), te = () => new C(et).addNode("answerDocQuestion", _t).addNode("extractNavigationIntent", Ht).addEdge(P, "answerDocQuestion").addEdge("answerDocQuestion", "extractNavigationIntent").addEdge("extractNavigationIntent", h), ee = String.raw`- **portal-doc-assistant** - General ArcGIS documentation and Portal help assistant:
|
|
736
567
|
- answers general ArcGIS, Portal, Enterprise, and JavaScript SDK questions
|
|
737
568
|
- acts as a fallback when specialized agents are not applicable
|
|
738
|
-
`,
|
|
569
|
+
`, se = {
|
|
739
570
|
id: "portal-doc-assistant",
|
|
740
571
|
name: "Portal Doc Assistant",
|
|
741
|
-
description:
|
|
742
|
-
createGraph:
|
|
743
|
-
workspace:
|
|
744
|
-
},
|
|
745
|
-
|
|
746
|
-
|
|
572
|
+
description: ee,
|
|
573
|
+
createGraph: te,
|
|
574
|
+
workspace: et
|
|
575
|
+
}, st = `
|
|
576
|
+
Shared markdown formatting rules:
|
|
577
|
+
- Use clear markdown headings (##) to separate sections.
|
|
578
|
+
- Use concise bullet points for lists of facts, counts, or signals.
|
|
579
|
+
- Emphasize key metrics with bold labels (for example: **Recent items:** 4).
|
|
580
|
+
- Keep wording direct and analytical; avoid filler language but make sure the language is friendly.
|
|
581
|
+
- Do not include raw internal IDs unless explicitly requested.
|
|
582
|
+
`, ae = () => ({ latestGroupId: null, memory: {} }), q = (e) => {
|
|
583
|
+
const t = e?.agentExecutionContext.sharedState.portalGroupSummaryMemory?.value;
|
|
584
|
+
return t ? { latestGroupId: t.latestGroupId, memory: t.memory } : ae();
|
|
585
|
+
}, re = async (e, t) => {
|
|
586
|
+
await g({ text: "Answering group follow-up...", agentName: "group-analytics" }, t);
|
|
587
|
+
const s = q(e), a = e.groupSummaryGroupId ?? s.latestGroupId, r = a ? s.memory[a] : void 0, i = e.groupSummaryQuestion || x(e.agentExecutionContext.messages);
|
|
588
|
+
return r ? {
|
|
589
|
+
status: "success",
|
|
590
|
+
outputMessage: (await b({
|
|
591
|
+
promptText: ne,
|
|
592
|
+
schema: oe,
|
|
593
|
+
modelTier: "default",
|
|
594
|
+
inputVariables: {
|
|
595
|
+
summary: r.summary,
|
|
596
|
+
question: i,
|
|
597
|
+
fullContext: JSON.stringify(r.fullContext)
|
|
598
|
+
}
|
|
599
|
+
})).answer
|
|
600
|
+
} : {
|
|
601
|
+
status: "success",
|
|
602
|
+
outputMessage: "I do not have group analytics context yet. Ask me to analyze a group first with analyze group <group id>."
|
|
603
|
+
};
|
|
604
|
+
}, oe = o.object({
|
|
605
|
+
answer: o.string(),
|
|
606
|
+
isRelevant: o.boolean()
|
|
607
|
+
}), ne = `
|
|
608
|
+
You answer follow-up questions about ArcGIS group analytics.
|
|
609
|
+
|
|
610
|
+
${st}
|
|
611
|
+
|
|
612
|
+
Ground your answer in the provided group analytics summary and context.
|
|
613
|
+
If the answer is not available from the provided context, state that clearly and suggest what to check next.
|
|
614
|
+
|
|
615
|
+
Response rules:
|
|
616
|
+
- Reply in concise markdown with this section structure:
|
|
617
|
+
1) ## Answer
|
|
618
|
+
2) ## Evidence
|
|
619
|
+
3) ## Gaps (only when data is missing)
|
|
620
|
+
- Keep the answer focused on the follow-up question.
|
|
621
|
+
- Do not include internal identifiers.
|
|
622
|
+
- Mark isRelevant=false when the question is not about this group or cannot be grounded in this group context.
|
|
623
|
+
|
|
624
|
+
Group analytics summary:
|
|
625
|
+
{summary}
|
|
626
|
+
|
|
627
|
+
Group full context:
|
|
628
|
+
{fullContext}
|
|
629
|
+
|
|
630
|
+
Question:
|
|
631
|
+
{question}
|
|
632
|
+
`, ie = async (e, t) => {
|
|
633
|
+
await g({ text: "Analyzing group-analytics intent...", agentName: "group-analytics" }, t);
|
|
634
|
+
const s = x(e.agentExecutionContext.messages), a = !!q(e).latestGroupId, r = await z.fromTemplate(le).format({
|
|
635
|
+
userMessage: s,
|
|
636
|
+
hasAnalyticsContext: String(a)
|
|
637
|
+
}), l = await U({
|
|
638
|
+
model: await D({ modelTier: "fast" }),
|
|
639
|
+
tools: [Z],
|
|
640
|
+
systemPrompt: r,
|
|
641
|
+
responseFormat: ue,
|
|
642
|
+
checkpointer: !0
|
|
643
|
+
}).invoke({ messages: e.agentExecutionContext.messages }, t), { intent: u, groupId: c, question: n } = l.structuredResponse, m = u === "summarize" && !c, p = u === "followUp" && !(n ?? "").trim(), d = u === "clarify" || m || p;
|
|
644
|
+
return {
|
|
645
|
+
groupSummaryIntent: d ? "clarify" : u,
|
|
646
|
+
groupSummaryGroupId: c || null,
|
|
647
|
+
groupSummaryQuestion: n || "",
|
|
648
|
+
status: "success",
|
|
649
|
+
outputMessage: d ? "Please clarify with a group id or title" : ""
|
|
650
|
+
};
|
|
651
|
+
}, ue = o.object({
|
|
652
|
+
intent: o.enum(["summarize", "followUp", "navigation", "clarify"]),
|
|
653
|
+
groupId: o.string().default(""),
|
|
654
|
+
question: o.string().default("")
|
|
655
|
+
}), le = `
|
|
656
|
+
Classify the user's request for ArcGIS Portal group analytics.
|
|
657
|
+
|
|
658
|
+
Rules:
|
|
659
|
+
- intent="summarize" only when the user explicitly asks to summarize, analyze, overview, or recap a group.
|
|
660
|
+
- intent="followUp" for follow-up questions about a previously analyzed group.
|
|
661
|
+
- intent="navigation" when the user asks to open, go to, navigate to, or view the group page.
|
|
662
|
+
- intent="clarify" when intent or required group target is missing.
|
|
663
|
+
- groupId must be the final resolved group id.
|
|
664
|
+
- If request has explicit group id, set groupId directly.
|
|
665
|
+
- If request references group title (for example $title, $"title with spaces", or plain quoted group title), call resolvePortalGroupIdByTitle and set groupId to the tool result.
|
|
666
|
+
- Never return group titles in output fields.
|
|
667
|
+
- If intent is "followUp", set question to the user's full question/request text.
|
|
668
|
+
- If intent is "navigation", set question="".
|
|
669
|
+
- If intent is "summarize", set question="".
|
|
670
|
+
- If intent is "navigation" and no group is specified, leave groupId empty so the system can navigate to the groups listing page.
|
|
671
|
+
- If hasAnalyticsContext is true and the user asks about the same group context without an explicit summarize/analyze command, prefer "followUp".
|
|
672
|
+
|
|
673
|
+
Examples:
|
|
674
|
+
- "Analyze group 0123456789abcdef0123456789abcdef" => summarize, groupId="0123456789abcdef0123456789abcdef"
|
|
675
|
+
- "Analyze group $living atlas" => summarize, call resolvePortalGroupIdByTitle("living atlas") and set groupId to tool result
|
|
676
|
+
- "Analyze group $"living atlas basemaps"" => summarize, call resolvePortalGroupIdByTitle("living atlas basemaps") and set groupId to tool result
|
|
677
|
+
- "Is this group active?" with hasAnalyticsContext=true => followUp
|
|
678
|
+
|
|
679
|
+
hasAnalyticsContext:
|
|
680
|
+
{hasAnalyticsContext}
|
|
681
|
+
|
|
682
|
+
User message:
|
|
683
|
+
{userMessage}
|
|
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(
|
|
687
|
+
a ? { destinationType: "portal-group", groupId: a } : { destinationType: "portal-groups" },
|
|
688
|
+
t
|
|
689
|
+
), { status: "success" };
|
|
690
|
+
};
|
|
691
|
+
function at({ timestamp: e, now: t, windowMs: s }) {
|
|
692
|
+
return e ? t - e <= s : !1;
|
|
693
|
+
}
|
|
694
|
+
const me = 720 * 60 * 60 * 1e3;
|
|
695
|
+
function de(e) {
|
|
696
|
+
const t = vt(e);
|
|
697
|
+
return {
|
|
698
|
+
id: e.id ?? "",
|
|
699
|
+
title: e.title ?? "",
|
|
700
|
+
description: e.description ?? "",
|
|
701
|
+
snippet: e.snippet ?? "",
|
|
702
|
+
access: e.access ?? null,
|
|
703
|
+
owner: e.owner ?? "",
|
|
704
|
+
tags: e.tags ?? [],
|
|
705
|
+
created: e.created?.getTime(),
|
|
706
|
+
modified: e.modified?.getTime(),
|
|
707
|
+
isInvitationOnly: e.isInvitationOnly,
|
|
708
|
+
sourceSignals: {
|
|
709
|
+
capabilities: At(e),
|
|
710
|
+
membershipAccess: Mt(e),
|
|
711
|
+
isOpenData: Gt(e),
|
|
712
|
+
isDistributedCollaborationGroup: St(e),
|
|
713
|
+
orgId: t.orgId,
|
|
714
|
+
hiddenMembers: t.hiddenMembers,
|
|
715
|
+
isViewOnly: t.isViewOnly,
|
|
716
|
+
isReadOnly: t.isReadOnly,
|
|
717
|
+
leavingDisallowed: t.leavingDisallowed
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
async function pe(e) {
|
|
722
|
+
const t = { owner: e.owner ?? "", admins: [], users: [] };
|
|
723
|
+
try {
|
|
724
|
+
return await e.fetchMembers();
|
|
725
|
+
} catch (s) {
|
|
726
|
+
return console.warn("Unable to fetch group members for analytics context", s), t;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
function ge(e) {
|
|
730
|
+
return e.map((t) => ({
|
|
731
|
+
id: t.id ?? "",
|
|
732
|
+
title: t.title ?? "Untitled",
|
|
733
|
+
type: t.type ?? "Unknown",
|
|
734
|
+
owner: t.owner ?? "",
|
|
735
|
+
created: t.created?.getTime(),
|
|
736
|
+
modified: t.modified?.getTime()
|
|
737
|
+
}));
|
|
738
|
+
}
|
|
739
|
+
function fe(e, t) {
|
|
740
|
+
return e.filter(
|
|
741
|
+
(s) => s.modified ? at({ timestamp: s.modified, now: t, windowMs: me }) : !1
|
|
742
|
+
);
|
|
743
|
+
}
|
|
744
|
+
function he(e) {
|
|
745
|
+
const t = /* @__PURE__ */ new Map();
|
|
746
|
+
for (const s of e)
|
|
747
|
+
t.set(s.type, (t.get(s.type) ?? 0) + 1);
|
|
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 }));
|
|
749
|
+
}
|
|
750
|
+
async function ye(e) {
|
|
751
|
+
const t = await e.queryItems({ num: 20, sortField: "modified", sortOrder: "desc" }), s = ge(t.results), a = Date.now();
|
|
752
|
+
return {
|
|
753
|
+
total: t.total,
|
|
754
|
+
topItems: s,
|
|
755
|
+
recentlyModifiedItems: fe(s, a),
|
|
756
|
+
topItemTypes: he(s)
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
async function we(e, t) {
|
|
760
|
+
if (!t)
|
|
761
|
+
return { error: { code: "missingGroupId", message: "Group id is required." } };
|
|
762
|
+
try {
|
|
763
|
+
const a = (await e.queryGroups({ query: `id:${t}`, num: 1 })).results[0];
|
|
764
|
+
if (!a)
|
|
765
|
+
return { error: { code: "groupNotFound", message: `No group found for id: ${t}` } };
|
|
766
|
+
const r = de(a), i = await pe(a), l = await ye(a);
|
|
767
|
+
return { result: { group: r, members: i, items: l } };
|
|
768
|
+
} catch (s) {
|
|
769
|
+
return console.error("Error fetching portal group analytics context:", s), { error: { code: "unhandledError" } };
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
const be = 2160 * 60 * 60 * 1e3, Ie = async (e, t) => {
|
|
773
|
+
const s = e.groupSummaryGroupId;
|
|
774
|
+
if (!s)
|
|
775
|
+
return {
|
|
776
|
+
status: "success",
|
|
777
|
+
outputMessage: 'Please clarify with analyze group <group id>, analyze group $<title>, or analyze group $"<title with spaces>".'
|
|
778
|
+
};
|
|
779
|
+
await g({ text: `Analyzing group ${s}...`, agentName: "group-analytics" }, t);
|
|
780
|
+
const a = t?.configurable?.context;
|
|
781
|
+
I(a);
|
|
782
|
+
const { result: r, error: i } = await we(a.portal, s);
|
|
783
|
+
if (i || !r)
|
|
784
|
+
return await g({ text: "Failed to fetch group context", agentName: "group-analytics" }, t), {
|
|
785
|
+
status: "success",
|
|
786
|
+
outputMessage: "Unable to retrieve group context for analytics."
|
|
787
|
+
};
|
|
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,
|
|
791
|
+
modelTier: "default",
|
|
792
|
+
inputVariables: {
|
|
793
|
+
context: JSON.stringify(r),
|
|
794
|
+
deterministicSignals: JSON.stringify({
|
|
795
|
+
isGroupActive: y,
|
|
796
|
+
isGroupRecentlyModified: m,
|
|
797
|
+
hasRecentlyAddedOrUpdatedContent: d,
|
|
798
|
+
recentItemCount: p
|
|
799
|
+
})
|
|
800
|
+
}
|
|
801
|
+
}), { followUpQuestions: w, summary: S } = v, nt = q(e), it = {
|
|
802
|
+
latestGroupId: s,
|
|
803
|
+
memory: {
|
|
804
|
+
...nt.memory,
|
|
805
|
+
[s]: { summary: S, followUpQuestions: w, fullContext: r }
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
return w.length && await E({ type: "suggested-prompts", data: { prompts: w } }, t), {
|
|
809
|
+
status: "success",
|
|
810
|
+
outputMessage: S,
|
|
811
|
+
sharedStatePatch: { portalGroupSummaryMemory: { value: it } }
|
|
812
|
+
};
|
|
813
|
+
}, xe = o.object({
|
|
814
|
+
summary: o.string(),
|
|
815
|
+
followUpQuestions: o.array(o.string()).default([])
|
|
816
|
+
}), ve = `
|
|
817
|
+
You summarize ArcGIS Portal groups based on structured context and deterministic activity signals.
|
|
818
|
+
|
|
819
|
+
${st}
|
|
820
|
+
|
|
821
|
+
Output format requirements:
|
|
822
|
+
- Return concise markdown with clear sections in this order:
|
|
823
|
+
1) Overview
|
|
824
|
+
2) Activity
|
|
825
|
+
3) Members
|
|
826
|
+
4) Content Theme
|
|
827
|
+
5) Contribution Model
|
|
828
|
+
6) Unknowns / Data Gaps
|
|
829
|
+
- Keep total response about 180-280 words unless the user asked for extra detail.
|
|
830
|
+
- Avoid internal-only implementation details and do not expose raw IDs unless user explicitly asks.
|
|
831
|
+
|
|
832
|
+
Reasoning rules:
|
|
833
|
+
- Use deterministicSignals as the source of truth for active/recent status.
|
|
834
|
+
- If group description/snippet are empty, infer purpose from tags, item title patterns, and item type distribution.
|
|
835
|
+
- For members, report owner/admin/user counts when available; if unavailable due to permission scope, explicitly say so.
|
|
836
|
+
- For contribution model, use membershipAccess, capabilities, and sourceJSON flags to characterize collaboration vs distribution behavior.
|
|
837
|
+
- Be explicit when signals are heuristic or unavailable.
|
|
838
|
+
|
|
839
|
+
Follow-up prompt rules:
|
|
840
|
+
- Generate exactly 3 follow-up prompts.
|
|
841
|
+
- Write them as direct first-person user chat prompts that can be clicked and sent as-is.
|
|
842
|
+
- Do not write meta-questions such as "Would you like..." or "Do you want me to...".
|
|
843
|
+
- Keep each prompt short, specific, and actionable.
|
|
844
|
+
- Every prompt must be answerable using only the provided group context and deterministic signals.
|
|
845
|
+
- Do not require external data, navigation, or additional fetches.
|
|
846
|
+
- Tailor each prompt to this specific group's available signals (content mix, activity, members, and contribution model).
|
|
847
|
+
- Avoid repeating phrasing from prior prompts or using generic template wording.
|
|
848
|
+
- If a signal is unavailable (for example members), do not ask follow-ups that depend on that missing signal.
|
|
849
|
+
|
|
850
|
+
Group context:
|
|
851
|
+
{context}
|
|
852
|
+
|
|
853
|
+
Deterministic signals:
|
|
854
|
+
{deterministicSignals}
|
|
855
|
+
`, $ = (e, t) => t ?? e, rt = f.Root({
|
|
856
|
+
...N(),
|
|
857
|
+
groupSummaryIntent: f({
|
|
858
|
+
reducer: $,
|
|
859
|
+
default: () => "clarify"
|
|
860
|
+
}),
|
|
861
|
+
groupSummaryGroupId: f({
|
|
862
|
+
reducer: $,
|
|
863
|
+
default: () => null
|
|
864
|
+
}),
|
|
865
|
+
groupSummaryQuestion: f({
|
|
866
|
+
reducer: $,
|
|
867
|
+
default: () => ""
|
|
868
|
+
})
|
|
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:
|
|
870
|
+
- summarizes ArcGIS portal groups from group context and sourceJSON details
|
|
871
|
+
- answers follow-up questions grounded in the summarized group
|
|
872
|
+
- suggests navigation to groups when relevant
|
|
873
|
+
`, Me = {
|
|
874
|
+
id: "portal-group-analytics",
|
|
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",
|
|
1044
|
+
description: Ue,
|
|
1045
|
+
createGraph: ze,
|
|
1046
|
+
workspace: ot
|
|
1047
|
+
}, Fe = mt`:host{height:100%;border-width:1px;border-style:solid;border-color:var(--calcite-color-border-3);display:block;width:100%;--tw-shadow: 0 1px 6px -1px rgba(0, 0, 0, .16), 0 1px 2px -1px rgba(0, 0, 0, .08);--tw-shadow-colored: 0 1px 6px -1px var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.chat-entry{display:flex;flex-direction:column;gap:.75rem;width:100%}.chat-actions{display:flex;justify-content:flex-end;gap:.5rem}.header-actions{display:flex;gap:.5rem;padding-inline-start:.75rem}.navigation-block{display:flex;flex-direction:column;align-items:stretch;gap:.35rem;margin-top:.5rem}.navigation-button{width:100%;margin-block:.25rem}.navigation-block-description{font-size:.75rem;color:var(--calcite-color-text-3)}`;
|
|
1048
|
+
function je(e, t) {
|
|
1049
|
+
if (!t)
|
|
1050
|
+
return;
|
|
1051
|
+
const { destinationType: s } = e;
|
|
1052
|
+
switch (s) {
|
|
747
1053
|
case "portal-content":
|
|
748
|
-
return `${a}/content.html`;
|
|
749
1054
|
case "portal-groups":
|
|
750
|
-
return
|
|
1055
|
+
return t[s];
|
|
751
1056
|
case "portal-item":
|
|
752
|
-
return
|
|
1057
|
+
return t[s]?.(e.itemId);
|
|
753
1058
|
case "portal-group":
|
|
754
|
-
return
|
|
1059
|
+
return t[s]?.(e.groupId);
|
|
755
1060
|
default:
|
|
756
|
-
return
|
|
1061
|
+
return T(s);
|
|
757
1062
|
}
|
|
758
|
-
}
|
|
759
|
-
|
|
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 {
|
|
760
1069
|
constructor() {
|
|
761
|
-
super(...arguments), this.t9n =
|
|
762
|
-
const
|
|
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) => {
|
|
1071
|
+
const s = t.detail, a = s.data?.block;
|
|
763
1072
|
if (!a)
|
|
764
1073
|
return;
|
|
765
1074
|
const r = this.getNavigationAction(a);
|
|
766
|
-
r && this.upsertNavigationSlotElement(
|
|
767
|
-
}, this.inputText = "", this.showVoiceInput = !0, this.isListening = !1, this.isVoiceInputDisabled = !1, this.interrupt = null, this.autoDestroyDisabled = !1, this.defaultClosed = !1, this.arcgisPortalNavigationRequest =
|
|
1075
|
+
r && this.upsertNavigationSlotElement(s.slotName, r);
|
|
1076
|
+
}, this.inputText = "", this.showVoiceInput = !0, this.isListening = !1, this.isVoiceInputDisabled = !1, this.interrupt = null, this.autoDestroyDisabled = !1, this.defaultClosed = !1, this.arcgisPortalNavigationRequest = ct();
|
|
768
1077
|
}
|
|
769
1078
|
static {
|
|
770
|
-
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 };
|
|
771
1080
|
}
|
|
772
1081
|
static {
|
|
773
|
-
this.styles =
|
|
1082
|
+
this.styles = Fe;
|
|
774
1083
|
}
|
|
775
1084
|
getNavigationAction(t) {
|
|
776
1085
|
if (t?.type !== _)
|
|
777
1086
|
return;
|
|
778
|
-
const
|
|
779
|
-
if (!
|
|
1087
|
+
const s = Oe(t.data);
|
|
1088
|
+
if (!s)
|
|
780
1089
|
return;
|
|
781
|
-
const a =
|
|
1090
|
+
const a = je(s, this.navigationTargetMap);
|
|
782
1091
|
if (a)
|
|
783
|
-
return { href: a, targetDetail:
|
|
1092
|
+
return { href: a, targetDetail: s, label: this.getNavigationText(s.destinationType) };
|
|
784
1093
|
}
|
|
785
|
-
upsertNavigationSlotElement(t,
|
|
1094
|
+
upsertNavigationSlotElement(t, s) {
|
|
786
1095
|
const a = this.assistantEl.value;
|
|
787
1096
|
if (!a)
|
|
788
1097
|
return;
|
|
789
1098
|
let r = this.navigationSlotElements.get(t);
|
|
790
|
-
r || (r = document.createElement("div"), r.slot = t, this.navigationSlotElements.set(t, r), a.append(r)),
|
|
791
|
-
|
|
792
|
-
href:
|
|
793
|
-
targetDetail:
|
|
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({
|
|
1101
|
+
href: s.href,
|
|
1102
|
+
targetDetail: s.targetDetail
|
|
794
1103
|
});
|
|
795
|
-
}}>${
|
|
1104
|
+
}}>${s.label}</calcite-button>${s.description ? G`<div class="navigation-block-description">${s.description}</div>` : null}</div>`, r);
|
|
796
1105
|
}
|
|
797
1106
|
getNavigationText(t) {
|
|
798
|
-
const
|
|
1107
|
+
const s = this.t9n.navigation;
|
|
799
1108
|
switch (t) {
|
|
800
1109
|
case "portal-content":
|
|
801
|
-
return
|
|
1110
|
+
return s.openContent;
|
|
802
1111
|
case "portal-groups":
|
|
803
|
-
return
|
|
1112
|
+
return s.openGroups;
|
|
804
1113
|
case "portal-item":
|
|
805
|
-
return
|
|
1114
|
+
return s.openItem;
|
|
806
1115
|
case "portal-group":
|
|
807
|
-
return
|
|
1116
|
+
return s.openGroup;
|
|
808
1117
|
default:
|
|
809
|
-
return
|
|
1118
|
+
return T(t);
|
|
810
1119
|
}
|
|
811
1120
|
}
|
|
812
1121
|
render() {
|
|
813
|
-
const { t9n: t, inputText:
|
|
814
|
-
return
|
|
815
|
-
this.interrupt =
|
|
1122
|
+
const { t9n: t, inputText: s, portal: a, user: r, navigationTargetMap: i, showVoiceInput: l, isListening: u, isVoiceInputDisabled: c } = this;
|
|
1123
|
+
return G`<arcgis-assistant log-enabled keep-suggested-prompts .heading=${t.heading} .entryMessage=${t.entryMessage} @arcgisSlottableRequest=${this.handleSlottableRequest} @arcgisInterrupt=${({ detail: n }) => {
|
|
1124
|
+
this.interrupt = n;
|
|
816
1125
|
}} @arcgisInterruptCancel=${() => {
|
|
817
1126
|
this.interrupt = null;
|
|
818
1127
|
}} @arcgisInterruptSubmit=${() => {
|
|
819
1128
|
this.interrupt = null;
|
|
820
|
-
}} @arcgisPromptSelect=${({ detail:
|
|
821
|
-
this.inputText =
|
|
1129
|
+
}} @arcgisPromptSelect=${({ detail: n }) => {
|
|
1130
|
+
this.inputText = n.prompt, requestAnimationFrame(() => {
|
|
822
1131
|
this.inputEl.value?.focusTextArea();
|
|
823
1132
|
});
|
|
824
|
-
}} ${
|
|
825
|
-
|
|
826
|
-
const
|
|
827
|
-
|
|
828
|
-
}} ${
|
|
829
|
-
|
|
830
|
-
}} @arcgisUserMentionableTextAreaChange=${({ detail:
|
|
831
|
-
this.inputText =
|
|
832
|
-
}} ${
|
|
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) => {
|
|
1134
|
+
n.preventDefault();
|
|
1135
|
+
const m = s.trim();
|
|
1136
|
+
m && (this.assistantEl.value?.submitMessage(m), this.inputText = "");
|
|
1137
|
+
}} ${A(this.formEl)}><arcgis-portal-mentionable-text-area .portal=${a} .user=${r} rows=3 .popoverListLabel=${t.mentionEntities} .placeholder=${t.placeholder} .value=${s} @arcgisUserMentionableTextAreaKeyDown=${({ detail: n }) => {
|
|
1138
|
+
n.key === "Enter" && !n.shiftKey && (n.preventDefault(), this.formEl.value?.requestSubmit());
|
|
1139
|
+
}} @arcgisUserMentionableTextAreaChange=${({ detail: n }) => {
|
|
1140
|
+
this.inputText = n ?? "";
|
|
1141
|
+
}} ${A(this.inputEl)}></arcgis-portal-mentionable-text-area><div class="chat-actions"><arcgis-portal-voice-input @arcgisVoiceInputStart=${() => {
|
|
833
1142
|
this.isListening = !0, this.isVoiceInputDisabled = !1;
|
|
834
1143
|
}} @arcgisVoiceInputStop=${() => {
|
|
835
1144
|
this.isListening = !1, this.isVoiceInputDisabled = !1;
|
|
836
|
-
}} @arcgisVoiceInputError=${(
|
|
837
|
-
|
|
838
|
-
}} @arcgisVoiceInputInterimTranscription=${(
|
|
839
|
-
this.inputText =
|
|
840
|
-
}} ${
|
|
1145
|
+
}} @arcgisVoiceInputError=${(n) => {
|
|
1146
|
+
n.detail.errorCode === "not-supported" && (this.showVoiceInput = !1);
|
|
1147
|
+
}} @arcgisVoiceInputInterimTranscription=${(n) => {
|
|
1148
|
+
this.inputText = n.detail.text;
|
|
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 () => {
|
|
841
1150
|
this.isVoiceInputDisabled = !0;
|
|
842
|
-
const
|
|
843
|
-
|
|
844
|
-
}}></calcite-button>` || ""}<calcite-button type=submit icon-start=send round .disabled=${!
|
|
845
|
-
this.assistantEl.value?.submitInterrupt(
|
|
1151
|
+
const n = this.voiceInputEl.value;
|
|
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 }) => {
|
|
1154
|
+
this.assistantEl.value?.submitInterrupt(n);
|
|
846
1155
|
}} @arcgisCancel=${() => {
|
|
847
1156
|
this.assistantEl.value?.cancelInterrupt();
|
|
848
1157
|
}}></arcgis-portal-ai-assistant-interrupt>` || ""}</arcgis-assistant>`;
|
|
849
1158
|
}
|
|
850
1159
|
}
|
|
851
|
-
|
|
1160
|
+
ut("arcgis-portal-ai-assistant", Ve);
|
|
852
1161
|
export {
|
|
853
|
-
|
|
1162
|
+
Ve as ArcgisPortalAiAssistant
|
|
854
1163
|
};
|