@arcgis/portal-components 5.2.0-next.60 → 5.2.0-next.62
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/2YI5PHJ6.js +2 -0
- package/dist/cdn/{25BWGJFT.js → 332KSPIN.js} +1 -1
- package/dist/cdn/5KADGOPQ.js +2 -0
- package/dist/cdn/6RLJVPF6.js +2 -0
- package/dist/cdn/CG4WYBHN.js +2 -0
- package/dist/cdn/{NMAP3FYP.js → DML7662F.js} +1 -1
- package/dist/cdn/{UL2NWFFH.js → EEELQMTE.js} +1 -1
- package/dist/cdn/{IXATTQKO.js → G2KWSRCG.js} +1 -1
- package/dist/cdn/JZTBGLFH.js +2 -0
- package/dist/cdn/{R2CAXYXG.js → KZVNGOD4.js} +99 -83
- package/dist/cdn/{5DE3XVTY.js → L2BME3WC.js} +1 -1
- package/dist/cdn/{UDTQ7U6L.js → LUT4IGPP.js} +1 -1
- package/dist/cdn/{IZOGASBD.js → PGCNY5GO.js} +1 -1
- package/dist/cdn/QCJQXOSH.js +2 -0
- package/dist/cdn/SOJU4OFZ.js +2 -0
- package/dist/cdn/{6LMJGR6F.js → WEJQVIN4.js} +1 -1
- package/dist/cdn/XW42SAEJ.js +2 -0
- package/dist/cdn/{THRK2DGY.js → ZK2VXTNX.js} +1 -1
- package/dist/cdn/{5VMPZXL3.js → ZXIRKL4X.js} +1 -1
- package/dist/cdn/assets/portal-ai-assistant/t9n/messages.en.json +1 -1
- package/dist/cdn/assets/portal-navigation/apps/notebook.avif +0 -0
- package/dist/cdn/assets/portal-navigation/t9n/messages.en.json +1 -1
- package/dist/cdn/index.js +1 -1
- package/dist/cdn/main.css +1 -1
- package/dist/chunks/portal-browser.js +0 -3
- package/dist/components/arcgis-portal-account-switcher/customElement.d.ts +3 -2
- package/dist/components/arcgis-portal-account-switcher/customElement.js +98 -92
- package/dist/components/arcgis-portal-ai-assistant/agents/types.d.ts +52 -16
- package/dist/components/arcgis-portal-ai-assistant/customElement.d.ts +28 -2
- package/dist/components/arcgis-portal-ai-assistant/customElement.js +1206 -673
- package/dist/components/arcgis-portal-browser/customElement.js +2 -5
- package/dist/components/arcgis-portal-browser/utils/store.d.ts +7 -3
- package/dist/components/arcgis-portal-classification-config/customElement.js +6 -6
- package/dist/components/arcgis-portal-group-browser/customElement.d.ts +174 -0
- package/dist/components/arcgis-portal-group-browser/customElement.js +66 -68
- package/dist/components/arcgis-portal-group-browser/types.d.ts +3 -3
- package/dist/components/arcgis-portal-navigation/customElement.d.ts +7 -0
- package/dist/components/arcgis-portal-navigation/customElement.js +422 -417
- package/dist/components/arcgis-portal-navigation/index.js +0 -2
- package/dist/components/portal-browser/components/portal-browser-filter/customElement.js +14 -0
- package/dist/components/{arcgis-portal-browser-filter → portal-browser/components/portal-browser-filter}/index.js +0 -1
- package/dist/components/portal-browser/components/portal-browser-filter-date/customElement.js +59 -0
- package/dist/components/{arcgis-portal-browser-filter-date → portal-browser/components/portal-browser-filter-date}/index.js +1 -2
- package/dist/components/portal-browser/components/portal-browser-filter-date/portal-browser-filter-date.d.ts +122 -0
- package/dist/components/portal-browser/components/portal-browser-filters/customElement.js +11 -0
- package/dist/components/portal-group-browser-filters/customElement.js +113 -86
- package/dist/components/portal-group-browser-filters/index.js +0 -3
- package/dist/docs/api.json +1 -1
- package/dist/docs/docs.json +1 -1
- package/dist/docs/vscode.css-custom-data.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 +0 -24
- package/dist/loader.js +3 -6
- package/dist/types/lumina.d.ts +3 -19
- package/dist/types/preact.d.ts +3 -22
- package/dist/types/react.d.ts +3 -25
- package/dist/types/stencil.d.ts +3 -19
- package/package.json +4 -4
- package/dist/cdn/2YEGKG66.js +0 -2
- package/dist/cdn/3527GI5O.js +0 -2
- package/dist/cdn/3Y33UPZ6.js +0 -2
- package/dist/cdn/744FUP4K.js +0 -2
- package/dist/cdn/FGJNEKPQ.js +0 -2
- package/dist/cdn/HEA66RTI.js +0 -2
- package/dist/cdn/IQFYKVRG.js +0 -2
- package/dist/cdn/JPHGWARN.js +0 -2
- package/dist/cdn/JUNNQTQU.js +0 -2
- package/dist/cdn/MNU537SB.js +0 -2
- package/dist/cdn/XMUR4HRH.js +0 -2
- package/dist/cdn/XX4U6IRN.js +0 -2
- package/dist/cdn/Y3RUZTB3.js +0 -2
- package/dist/cdn/YIU7GBUN.js +0 -2
- package/dist/cdn/ZOEF7HBV.js +0 -2
- package/dist/components/arcgis-portal-browser-filter/customElement.d.ts +0 -226
- package/dist/components/arcgis-portal-browser-filter/customElement.js +0 -32
- package/dist/components/arcgis-portal-browser-filter/index.d.ts +0 -1
- package/dist/components/arcgis-portal-browser-filter-date/customElement.d.ts +0 -233
- package/dist/components/arcgis-portal-browser-filter-date/customElement.js +0 -118
- package/dist/components/arcgis-portal-browser-filter-date/index.d.ts +0 -1
- package/dist/components/arcgis-portal-browser-filters/customElement.d.ts +0 -7
- package/dist/components/arcgis-portal-browser-filters/customElement.js +0 -29
- package/dist/components/arcgis-portal-browser-filters/index.d.ts +0 -1
- /package/dist/cdn/{F3PB42AG.js → 4E65YWCP.js} +0 -0
- /package/dist/components/{arcgis-portal-browser-filters → portal-browser/components/portal-browser-filters}/index.js +0 -0
|
@@ -1,29 +1,30 @@
|
|
|
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
|
|
6
|
-
import { u as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import { ChatPromptTemplate as
|
|
15
|
-
import { tool as
|
|
16
|
-
import { s as
|
|
17
|
-
import { g as
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
2
|
+
import { c as zt } from "../../chunks/runtime.js";
|
|
3
|
+
import { LitElement as Et, createEvent as $t } from "@arcgis/lumina";
|
|
4
|
+
import { css as Rt, render as Dt, html as M } from "lit";
|
|
5
|
+
import { createRef as P, ref as k } from "lit/directives/ref.js";
|
|
6
|
+
import { u as Ut } from "../../chunks/useT9n.js";
|
|
7
|
+
import { NodeInterrupt as dt, Annotation as h, StateGraph as C, START as A, END as w } from "@langchain/langgraph/web";
|
|
8
|
+
import { sendTraceMessage as g, invokeStructuredPrompt as b, sendUXSuggestion as j, createAgentRuntimeStateWithSharedState as N, createChatModel as L, getEmbeddings as Ft } from "@arcgis/ai-components/utils/index.js";
|
|
9
|
+
import r from "zod";
|
|
10
|
+
import { a as Ot, c as Kt, q as Vt } from "../../chunks/groups.js";
|
|
11
|
+
import jt from "@arcgis/core/identity/IdentityManager.js";
|
|
12
|
+
import W from "@arcgis/core/request.js";
|
|
13
|
+
import { a as z, t as Lt, b as Bt } from "../../chunks/functionalities.js";
|
|
14
|
+
import { ChatPromptTemplate as B } from "@langchain/core/prompts";
|
|
15
|
+
import { tool as pt } from "@langchain/core/tools";
|
|
16
|
+
import { s as Qt, a as Wt } from "../../chunks/item2.js";
|
|
17
|
+
import { g as Jt, e as _t, i as Yt, c as Ht, a as Xt } from "../../chunks/groups2.js";
|
|
18
|
+
import Zt from "@arcgis/core/portal/Portal.js";
|
|
19
|
+
const mt = (t) => {
|
|
20
|
+
const { portal: e, user: a } = t ?? {};
|
|
21
|
+
return !!t && !!e && !!a;
|
|
21
22
|
};
|
|
22
|
-
function
|
|
23
|
-
if (!
|
|
23
|
+
function x(t) {
|
|
24
|
+
if (!mt(t))
|
|
24
25
|
throw new Error("Invalid context: PortalAssistantContext with portal and user is required.");
|
|
25
26
|
}
|
|
26
|
-
const
|
|
27
|
+
const te = `
|
|
27
28
|
Write a concise, friendly success message for adding members to a group.
|
|
28
29
|
|
|
29
30
|
Rules:
|
|
@@ -38,83 +39,83 @@ Added members:
|
|
|
38
39
|
|
|
39
40
|
Not added members:
|
|
40
41
|
{notAddedMembers}
|
|
41
|
-
`,
|
|
42
|
-
successMessage:
|
|
43
|
-
}),
|
|
44
|
-
if (
|
|
42
|
+
`, ee = (t) => t.map((e) => `"${e}"`).join(", "), ae = r.object({
|
|
43
|
+
successMessage: r.string().default("")
|
|
44
|
+
}), J = "portal-group-creation", _ = "approveAddMembers", ne = async (t, e) => {
|
|
45
|
+
if (t.intentParams.intent !== "addMembers")
|
|
45
46
|
return {
|
|
46
47
|
status: "success",
|
|
47
48
|
outputMessage: "Use @mention usernames for the members you want to add."
|
|
48
49
|
};
|
|
49
|
-
const
|
|
50
|
-
if (!
|
|
50
|
+
const a = t.agentExecutionContext.sharedState.createdGroupId?.value;
|
|
51
|
+
if (!a)
|
|
51
52
|
return {
|
|
52
53
|
status: "success",
|
|
53
54
|
outputMessage: "Create a group first, then add members using @mention usernames."
|
|
54
55
|
};
|
|
55
|
-
const
|
|
56
|
-
if (!
|
|
56
|
+
const n = t.intentParams.memberInfo.memberIdentifiers.map((p) => p.trim()).filter(Boolean);
|
|
57
|
+
if (!n.length)
|
|
57
58
|
return {
|
|
58
59
|
status: "success",
|
|
59
60
|
outputMessage: "Use @mention usernames for the members you want to add."
|
|
60
61
|
};
|
|
61
|
-
const
|
|
62
|
+
const s = `The following member(s) will be added to the newly created group:
|
|
62
63
|
|
|
63
|
-
${
|
|
64
|
+
${n.map((p) => `- **@${p}**`).join(`
|
|
64
65
|
`)}
|
|
65
66
|
|
|
66
|
-
Do you want to continue?`, { hitlResponse:
|
|
67
|
-
if (
|
|
68
|
-
const
|
|
69
|
-
agentId:
|
|
70
|
-
id:
|
|
67
|
+
Do you want to continue?`, { hitlResponse: i } = e?.configurable ?? {};
|
|
68
|
+
if (i?.agentId !== J || i.id !== _) {
|
|
69
|
+
const p = {
|
|
70
|
+
agentId: J,
|
|
71
|
+
id: _,
|
|
71
72
|
kind: "booleanChoice",
|
|
72
|
-
message:
|
|
73
|
+
message: s,
|
|
73
74
|
metadata: {
|
|
74
75
|
action: "addMembers",
|
|
75
|
-
groupId:
|
|
76
|
-
members: [...
|
|
76
|
+
groupId: a,
|
|
77
|
+
members: [...n]
|
|
77
78
|
}
|
|
78
79
|
};
|
|
79
|
-
throw new
|
|
80
|
+
throw new dt(p);
|
|
80
81
|
}
|
|
81
|
-
if (
|
|
82
|
+
if (i.payload !== !0)
|
|
82
83
|
return {
|
|
83
84
|
status: "success",
|
|
84
85
|
outputMessage: "Okay, I cancelled adding members to the group."
|
|
85
86
|
};
|
|
86
87
|
await g(
|
|
87
|
-
{ text: `Adding members ${
|
|
88
|
-
|
|
88
|
+
{ text: `Adding members ${ee(n)}...`, agentName: "group-creation" },
|
|
89
|
+
e
|
|
89
90
|
);
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
const { result:
|
|
93
|
-
if (
|
|
91
|
+
const u = e?.configurable?.context;
|
|
92
|
+
x(u);
|
|
93
|
+
const { result: c, error: d } = await Ot(u.portal, a, n);
|
|
94
|
+
if (d || !c)
|
|
94
95
|
return {
|
|
95
96
|
status: "success",
|
|
96
97
|
outputMessage: "I could not add members to that group. Please confirm group access and user accounts, then try again."
|
|
97
98
|
};
|
|
98
|
-
const { addedUsernames:
|
|
99
|
+
const { addedUsernames: l, notAddedUsers: m } = c;
|
|
99
100
|
try {
|
|
100
|
-
const
|
|
101
|
-
promptText:
|
|
102
|
-
schema:
|
|
101
|
+
const f = (await b({
|
|
102
|
+
promptText: te,
|
|
103
|
+
schema: ae,
|
|
103
104
|
modelTier: "fast",
|
|
104
105
|
inputVariables: {
|
|
105
|
-
addedMembers:
|
|
106
|
+
addedMembers: l.join(", "),
|
|
106
107
|
notAddedMembers: JSON.stringify(
|
|
107
|
-
m.map((
|
|
108
|
+
m.map((y) => ({ username: y.username, reason: y.error.message }))
|
|
108
109
|
)
|
|
109
110
|
}
|
|
110
111
|
})).successMessage;
|
|
111
|
-
if (
|
|
112
|
-
return { status: "success", outputMessage:
|
|
113
|
-
} catch (
|
|
114
|
-
console.error("Error generating add-members success message:",
|
|
112
|
+
if (f)
|
|
113
|
+
return { status: "success", outputMessage: f };
|
|
114
|
+
} catch (p) {
|
|
115
|
+
console.error("Error generating add-members success message:", p);
|
|
115
116
|
}
|
|
116
117
|
return {};
|
|
117
|
-
},
|
|
118
|
+
}, oe = `
|
|
118
119
|
Write a concise, friendly success message after creating a portal group.
|
|
119
120
|
|
|
120
121
|
Rules:
|
|
@@ -125,7 +126,7 @@ Rules:
|
|
|
125
126
|
|
|
126
127
|
Group title:
|
|
127
128
|
{groupTitle}
|
|
128
|
-
`,
|
|
129
|
+
`, se = `
|
|
129
130
|
Write a concise, friendly failure message after an attempt to create a portal group.
|
|
130
131
|
|
|
131
132
|
Rules:
|
|
@@ -140,59 +141,59 @@ Group title:
|
|
|
140
141
|
|
|
141
142
|
Failure reason:
|
|
142
143
|
{failureReason}
|
|
143
|
-
`,
|
|
144
|
-
successMessage:
|
|
145
|
-
}),
|
|
146
|
-
failureMessage:
|
|
147
|
-
}),
|
|
148
|
-
if (
|
|
144
|
+
`, Y = "portal-group-creation", H = "approveCreateGroup", re = r.object({
|
|
145
|
+
successMessage: r.string().default("")
|
|
146
|
+
}), ie = r.object({
|
|
147
|
+
failureMessage: r.string().default("")
|
|
148
|
+
}), ue = async (t, e) => {
|
|
149
|
+
if (t.intentParams.intent !== "create")
|
|
149
150
|
return {
|
|
150
151
|
status: "success",
|
|
151
152
|
outputMessage: "Tell me the group title you want to use."
|
|
152
153
|
};
|
|
153
|
-
const
|
|
154
|
-
if (!
|
|
154
|
+
const a = t.intentParams.title.trim();
|
|
155
|
+
if (!a)
|
|
155
156
|
return {
|
|
156
157
|
status: "success",
|
|
157
158
|
outputMessage: "What title would you like for the new group?"
|
|
158
159
|
};
|
|
159
|
-
const
|
|
160
|
-
if (o?.agentId !==
|
|
161
|
-
const
|
|
162
|
-
agentId:
|
|
163
|
-
id:
|
|
160
|
+
const n = `A group with the title **${a}** will be created. Do you want to continue?`, { hitlResponse: o } = e?.configurable;
|
|
161
|
+
if (o?.agentId !== Y || o.id !== H) {
|
|
162
|
+
const d = {
|
|
163
|
+
agentId: Y,
|
|
164
|
+
id: H,
|
|
164
165
|
kind: "booleanChoice",
|
|
165
|
-
message:
|
|
166
|
+
message: n,
|
|
166
167
|
metadata: {
|
|
167
168
|
action: "createGroup",
|
|
168
|
-
title:
|
|
169
|
+
title: a,
|
|
169
170
|
access: "private"
|
|
170
171
|
}
|
|
171
172
|
};
|
|
172
|
-
throw new
|
|
173
|
+
throw new dt(d);
|
|
173
174
|
}
|
|
174
175
|
if (o.payload !== !0)
|
|
175
176
|
return {
|
|
176
177
|
status: "success",
|
|
177
|
-
outputMessage: `Okay, I cancelled creating **${
|
|
178
|
+
outputMessage: `Okay, I cancelled creating **${a}**.`
|
|
178
179
|
};
|
|
179
|
-
await g({ text: `Creating group "${
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
const { result:
|
|
183
|
-
title:
|
|
180
|
+
await g({ text: `Creating group "${a}"...`, agentName: "group-creation" }, e);
|
|
181
|
+
const s = e?.configurable?.context;
|
|
182
|
+
x(s);
|
|
183
|
+
const { result: i, error: u } = await Kt(s.portal, {
|
|
184
|
+
title: a,
|
|
184
185
|
access: "private"
|
|
185
186
|
});
|
|
186
|
-
if (
|
|
187
|
-
const
|
|
187
|
+
if (u || !i) {
|
|
188
|
+
const d = u?.message?.trim() || "No additional details were provided.";
|
|
188
189
|
try {
|
|
189
|
-
const m = (await
|
|
190
|
-
promptText:
|
|
191
|
-
schema:
|
|
190
|
+
const m = (await b({
|
|
191
|
+
promptText: se,
|
|
192
|
+
schema: ie,
|
|
192
193
|
modelTier: "fast",
|
|
193
194
|
inputVariables: {
|
|
194
|
-
groupTitle:
|
|
195
|
-
failureReason:
|
|
195
|
+
groupTitle: a,
|
|
196
|
+
failureReason: d
|
|
196
197
|
}
|
|
197
198
|
})).failureMessage.trim();
|
|
198
199
|
if (m)
|
|
@@ -200,50 +201,50 @@ Failure reason:
|
|
|
200
201
|
status: "success",
|
|
201
202
|
outputMessage: m
|
|
202
203
|
};
|
|
203
|
-
} catch (
|
|
204
|
-
console.error("Error generating create-group failure message:",
|
|
204
|
+
} catch (l) {
|
|
205
|
+
console.error("Error generating create-group failure message:", l);
|
|
205
206
|
}
|
|
206
207
|
return {
|
|
207
208
|
status: "success",
|
|
208
209
|
outputMessage: "I could not create that group. Please confirm your permissions and try again with the group title."
|
|
209
210
|
};
|
|
210
211
|
}
|
|
211
|
-
const
|
|
212
|
+
const c = i.id;
|
|
212
213
|
try {
|
|
213
|
-
const
|
|
214
|
-
promptText:
|
|
215
|
-
schema:
|
|
214
|
+
const l = (await b({
|
|
215
|
+
promptText: oe,
|
|
216
|
+
schema: re,
|
|
216
217
|
modelTier: "fast",
|
|
217
218
|
inputVariables: {
|
|
218
|
-
groupTitle:
|
|
219
|
+
groupTitle: a
|
|
219
220
|
}
|
|
220
221
|
})).successMessage.trim();
|
|
221
|
-
if (
|
|
222
|
+
if (l)
|
|
222
223
|
return {
|
|
223
224
|
status: "success",
|
|
224
|
-
outputMessage:
|
|
225
|
-
sharedStatePatch: { createdGroupId: { value:
|
|
226
|
-
createdGroupId:
|
|
225
|
+
outputMessage: l,
|
|
226
|
+
sharedStatePatch: { createdGroupId: { value: c } },
|
|
227
|
+
createdGroupId: c
|
|
227
228
|
};
|
|
228
|
-
} catch (
|
|
229
|
-
console.error("Error generating create-group success message:",
|
|
229
|
+
} catch (d) {
|
|
230
|
+
console.error("Error generating create-group success message:", d);
|
|
230
231
|
}
|
|
231
232
|
return {};
|
|
232
|
-
},
|
|
233
|
-
for (let
|
|
234
|
-
const
|
|
235
|
-
if (
|
|
233
|
+
}, v = (t) => {
|
|
234
|
+
for (let e = t.length - 1; e >= 0; e -= 1) {
|
|
235
|
+
const a = t[e];
|
|
236
|
+
if (a.type !== "human")
|
|
236
237
|
continue;
|
|
237
|
-
const
|
|
238
|
-
if (typeof
|
|
239
|
-
return
|
|
240
|
-
if (Array.isArray(
|
|
241
|
-
return
|
|
238
|
+
const n = a.content;
|
|
239
|
+
if (typeof n == "string")
|
|
240
|
+
return n;
|
|
241
|
+
if (Array.isArray(n))
|
|
242
|
+
return n.map(
|
|
242
243
|
(o) => typeof o == "string" ? o : "text" in o && typeof o.text == "string" ? o.text : ""
|
|
243
244
|
).join(" ").trim();
|
|
244
245
|
}
|
|
245
246
|
return "";
|
|
246
|
-
},
|
|
247
|
+
}, ce = `
|
|
247
248
|
You classify whether a user is asking to create a new ArcGIS Portal group or add members to an existing group.
|
|
248
249
|
|
|
249
250
|
Rules:
|
|
@@ -269,69 +270,77 @@ Examples:
|
|
|
269
270
|
|
|
270
271
|
User message:
|
|
271
272
|
{userMessage}
|
|
272
|
-
`,
|
|
273
|
-
intent:
|
|
274
|
-
title:
|
|
275
|
-
memberIdentifiers:
|
|
276
|
-
clarifyMessage:
|
|
277
|
-
}),
|
|
278
|
-
await g({ text: "Thinking about groups...", agentName: "group-creation" },
|
|
279
|
-
const
|
|
280
|
-
promptText:
|
|
281
|
-
schema:
|
|
273
|
+
`, le = r.object({
|
|
274
|
+
intent: r.enum(["clarify", "create", "addMembers"]).default("clarify"),
|
|
275
|
+
title: r.string().default(""),
|
|
276
|
+
memberIdentifiers: r.array(r.string()).default([]),
|
|
277
|
+
clarifyMessage: r.string().default("")
|
|
278
|
+
}), de = async (t, e) => {
|
|
279
|
+
await g({ text: "Thinking about groups...", agentName: "group-creation" }, e);
|
|
280
|
+
const a = v(t.agentExecutionContext.messages).trim(), n = await b({
|
|
281
|
+
promptText: ce,
|
|
282
|
+
schema: le,
|
|
282
283
|
modelTier: "default",
|
|
283
|
-
inputVariables: { userMessage:
|
|
284
|
-
}), o =
|
|
284
|
+
inputVariables: { userMessage: a }
|
|
285
|
+
}), o = n.title.trim(), s = n.memberIdentifiers.filter(Boolean), i = n.clarifyMessage.trim(), u = n.intent === "create" && !!o, c = n.intent === "addMembers" && s.length > 0;
|
|
285
286
|
return {
|
|
286
|
-
intentParams:
|
|
287
|
+
intentParams: u ? { intent: "create", title: o } : c ? { intent: "addMembers", memberInfo: { memberIdentifiers: s } } : { intent: "clarify" },
|
|
287
288
|
status: "success",
|
|
288
|
-
outputMessage: !
|
|
289
|
+
outputMessage: !u && !c ? i : ""
|
|
289
290
|
};
|
|
290
|
-
},
|
|
291
|
-
"portal-content",
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
"portal-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
"portal-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
"portal-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
291
|
+
}, pe = ["favorites", "group", "living-atlas", "org"], me = ["featured", "my", "organization"], ge = ["licenses", "members", "overview", "reports", "settings", "status"], he = r.object({
|
|
292
|
+
destinationType: r.literal("portal-content"),
|
|
293
|
+
hash: r.enum(pe).optional(),
|
|
294
|
+
t9nKey: r.string().min(1).optional()
|
|
295
|
+
}), fe = r.object({
|
|
296
|
+
destinationType: r.literal("portal-groups"),
|
|
297
|
+
hash: r.enum(me).optional(),
|
|
298
|
+
t9nKey: r.string().min(1).optional()
|
|
299
|
+
}), ye = r.object({
|
|
300
|
+
destinationType: r.literal("portal-org"),
|
|
301
|
+
hash: r.enum(ge).optional(),
|
|
302
|
+
t9nKey: r.string().min(1).optional()
|
|
303
|
+
}), we = r.object({
|
|
304
|
+
destinationType: r.literal("portal-item"),
|
|
305
|
+
itemId: r.string().trim().min(1),
|
|
306
|
+
t9nKey: r.string().min(1).optional()
|
|
307
|
+
}), ve = r.object({
|
|
308
|
+
destinationType: r.literal("portal-group"),
|
|
309
|
+
groupId: r.string().trim().min(1),
|
|
310
|
+
t9nKey: r.string().min(1).optional()
|
|
311
|
+
}), be = r.object({
|
|
312
|
+
destinationType: r.union([
|
|
313
|
+
r.literal("portal-gallery"),
|
|
314
|
+
r.literal("portal-map-viewer"),
|
|
315
|
+
r.literal("portal-notebooks"),
|
|
316
|
+
r.literal("portal-scene-viewer")
|
|
317
|
+
]),
|
|
318
|
+
t9nKey: r.string().min(1).optional()
|
|
319
|
+
}), Ie = r.union([
|
|
320
|
+
he,
|
|
321
|
+
fe,
|
|
322
|
+
ye,
|
|
323
|
+
we,
|
|
324
|
+
ve,
|
|
325
|
+
be
|
|
326
|
+
]), gt = "portal-navigation", E = async (t, e) => {
|
|
327
|
+
const a = e?.configurable?.context;
|
|
328
|
+
!mt(a) || !a.navigationTargetMap?.[t.destinationType] || await j({ type: gt, data: { ...t } }, e);
|
|
329
|
+
}, xe = async (t, e) => {
|
|
330
|
+
const a = t.createdGroupId ?? t.agentExecutionContext.sharedState.createdGroupId?.value;
|
|
331
|
+
return a ? (await g({ text: "Preparing navigation...", agentName: "group-creation" }, e), await E({ destinationType: "portal-group", groupId: a }, e), {}) : {};
|
|
332
|
+
}, X = (t, e) => e ?? t, ht = h.Root({
|
|
333
|
+
...N(),
|
|
325
334
|
// * Shared state between nodes (but not persisted to the agent execution context)
|
|
326
335
|
/** Parameters related to the user's intent for group creation actions */
|
|
327
|
-
intentParams:
|
|
336
|
+
intentParams: h({ reducer: X, default: () => ({ intent: "clarify" }) }),
|
|
328
337
|
/** The ID of the group that was created
|
|
329
338
|
* even though we already have this in the shared state
|
|
330
339
|
* we still need it here to also share between nodes
|
|
331
340
|
*/
|
|
332
|
-
createdGroupId:
|
|
333
|
-
}),
|
|
334
|
-
switch (
|
|
341
|
+
createdGroupId: h({ reducer: X, default: () => "" })
|
|
342
|
+
}), Se = () => new C(ht).addNode("detectGroupCreationIntent", de).addNode("createPortalGroup", ue).addNode("addMembersToPortalGroup", ne).addNode("suggestCreatedGroupNavigation", xe).addEdge(A, "detectGroupCreationIntent").addConditionalEdges("detectGroupCreationIntent", (e) => {
|
|
343
|
+
switch (e.intentParams.intent) {
|
|
335
344
|
case "create":
|
|
336
345
|
return "createPortalGroup";
|
|
337
346
|
case "addMembers":
|
|
@@ -339,152 +348,152 @@ User message:
|
|
|
339
348
|
default:
|
|
340
349
|
return w;
|
|
341
350
|
}
|
|
342
|
-
}).addEdge("createPortalGroup", "suggestCreatedGroupNavigation").addEdge("addMembersToPortalGroup", "suggestCreatedGroupNavigation").addEdge("suggestCreatedGroupNavigation", w),
|
|
351
|
+
}).addEdge("createPortalGroup", "suggestCreatedGroupNavigation").addEdge("addMembersToPortalGroup", "suggestCreatedGroupNavigation").addEdge("suggestCreatedGroupNavigation", w), Me = String.raw`- **portal-group-creation** - Portal group creation assistant:
|
|
343
352
|
- creates a new ArcGIS Portal group for the signed-in user
|
|
344
353
|
- adds users to the newly created group using @mention usernames
|
|
345
|
-
`,
|
|
354
|
+
`, Te = {
|
|
346
355
|
id: "portal-group-creation",
|
|
347
356
|
name: "Portal Group Creation",
|
|
348
|
-
description:
|
|
349
|
-
createGraph:
|
|
350
|
-
workspace:
|
|
351
|
-
},
|
|
352
|
-
const
|
|
353
|
-
if (!
|
|
354
|
-
return
|
|
355
|
-
const
|
|
357
|
+
description: Me,
|
|
358
|
+
createGraph: Se,
|
|
359
|
+
workspace: ht
|
|
360
|
+
}, ft = "portalDocAssistantMemory", Ge = () => ({ conversationId: "" }), Ce = (t) => {
|
|
361
|
+
const e = t?.[ft]?.value;
|
|
362
|
+
if (!e || typeof e != "object")
|
|
363
|
+
return Ge();
|
|
364
|
+
const a = e;
|
|
356
365
|
return {
|
|
357
|
-
conversationId: typeof
|
|
366
|
+
conversationId: typeof a.conversationId == "string" ? a.conversationId : ""
|
|
358
367
|
};
|
|
359
|
-
},
|
|
360
|
-
[
|
|
361
|
-
}),
|
|
368
|
+
}, Ae = (t) => ({
|
|
369
|
+
[ft]: { value: t }
|
|
370
|
+
}), Ne = {
|
|
362
371
|
pipeline: {
|
|
363
372
|
follow_up: { allow: !1 }
|
|
364
373
|
}
|
|
365
374
|
};
|
|
366
|
-
function
|
|
375
|
+
function Pe(t) {
|
|
367
376
|
return {
|
|
368
377
|
kind: "DocAIAssistantRequest",
|
|
369
378
|
filters: {
|
|
370
|
-
...
|
|
371
|
-
persona: { persona:
|
|
379
|
+
...Ne,
|
|
380
|
+
persona: { persona: t }
|
|
372
381
|
}
|
|
373
382
|
};
|
|
374
383
|
}
|
|
375
|
-
async function
|
|
376
|
-
portal:
|
|
377
|
-
question:
|
|
378
|
-
persona:
|
|
379
|
-
previousConversationId:
|
|
384
|
+
async function ke({
|
|
385
|
+
portal: t,
|
|
386
|
+
question: e,
|
|
387
|
+
persona: a,
|
|
388
|
+
previousConversationId: n,
|
|
380
389
|
signal: o,
|
|
381
|
-
skillId:
|
|
390
|
+
skillId: s
|
|
382
391
|
}) {
|
|
383
|
-
|
|
384
|
-
const
|
|
385
|
-
portal:
|
|
386
|
-
skillId:
|
|
387
|
-
message:
|
|
388
|
-
options: { context:
|
|
392
|
+
s ??= "doc_ai_assistant";
|
|
393
|
+
const i = Pe(a), u = await qe({
|
|
394
|
+
portal: t,
|
|
395
|
+
skillId: s,
|
|
396
|
+
message: e,
|
|
397
|
+
options: { context: i, previousConversationId: n, signal: o }
|
|
389
398
|
});
|
|
390
399
|
return {
|
|
391
|
-
reply:
|
|
392
|
-
conversationId:
|
|
400
|
+
reply: ze(u, s),
|
|
401
|
+
conversationId: u[0]?.conversationId ?? ""
|
|
393
402
|
};
|
|
394
403
|
}
|
|
395
|
-
async function
|
|
396
|
-
portal:
|
|
397
|
-
skillId:
|
|
398
|
-
message:
|
|
399
|
-
options:
|
|
404
|
+
async function qe({
|
|
405
|
+
portal: t,
|
|
406
|
+
skillId: e,
|
|
407
|
+
message: a,
|
|
408
|
+
options: n
|
|
400
409
|
}) {
|
|
401
|
-
const
|
|
410
|
+
const s = `${t.helperServices.aiAssistantServices.url}/skills/${e}/chat`, i = {
|
|
402
411
|
"Content-Type": "application/json",
|
|
403
|
-
token:
|
|
404
|
-
},
|
|
412
|
+
token: jt.findCredential(t.url)?.token ?? ""
|
|
413
|
+
}, u = await W(s, {
|
|
405
414
|
method: "post",
|
|
406
415
|
body: JSON.stringify({
|
|
407
|
-
message:
|
|
408
|
-
context:
|
|
409
|
-
conversationId:
|
|
416
|
+
message: a,
|
|
417
|
+
context: n.context,
|
|
418
|
+
conversationId: n.previousConversationId
|
|
410
419
|
}),
|
|
411
|
-
headers:
|
|
412
|
-
signal:
|
|
420
|
+
headers: i,
|
|
421
|
+
signal: n.signal
|
|
413
422
|
});
|
|
414
|
-
if (
|
|
415
|
-
throw new Error(`Doc assistant chat failed (${
|
|
416
|
-
cause:
|
|
423
|
+
if (u.httpStatus !== 200)
|
|
424
|
+
throw new Error(`Doc assistant chat failed (${u.httpStatus})`, {
|
|
425
|
+
cause: u.data
|
|
417
426
|
});
|
|
418
|
-
const
|
|
419
|
-
if (!
|
|
427
|
+
const c = u.data, d = [c], { conversationId: l, inquiryId: m } = c, p = async (f, y) => {
|
|
428
|
+
if (!y)
|
|
420
429
|
return;
|
|
421
|
-
await
|
|
422
|
-
const
|
|
430
|
+
await Lt(500);
|
|
431
|
+
const I = await W(s, {
|
|
423
432
|
method: "post",
|
|
424
|
-
body: JSON.stringify({ conversationId:
|
|
425
|
-
headers:
|
|
426
|
-
signal:
|
|
433
|
+
body: JSON.stringify({ conversationId: l, inquiryId: m, ackSequenceNumber: f }),
|
|
434
|
+
headers: i,
|
|
435
|
+
signal: n.signal
|
|
427
436
|
});
|
|
428
|
-
if (
|
|
429
|
-
throw new Error(`Doc assistant poll failed (${
|
|
430
|
-
cause:
|
|
437
|
+
if (I.httpStatus !== 200)
|
|
438
|
+
throw new Error(`Doc assistant poll failed (${I.httpStatus})`, {
|
|
439
|
+
cause: I.data
|
|
431
440
|
});
|
|
432
|
-
const S =
|
|
433
|
-
|
|
441
|
+
const S = I.data;
|
|
442
|
+
d.push(S), await p(S.sequenceNumber, S.hasMore);
|
|
434
443
|
};
|
|
435
|
-
return
|
|
444
|
+
return c.hasMore && await p(c.sequenceNumber, c.hasMore), d;
|
|
436
445
|
}
|
|
437
|
-
function
|
|
438
|
-
switch (
|
|
446
|
+
function ze(t, e) {
|
|
447
|
+
switch (e) {
|
|
439
448
|
case "doc_chat":
|
|
440
|
-
return
|
|
449
|
+
return t.find((a) => a.message != null)?.message ?? "";
|
|
441
450
|
case "doc_ai_assistant":
|
|
442
|
-
for (let
|
|
443
|
-
const
|
|
444
|
-
if (
|
|
445
|
-
const o =
|
|
451
|
+
for (let a = t.length - 1; a >= 0; a -= 1) {
|
|
452
|
+
const n = t[a];
|
|
453
|
+
if (n.context?.kind === "DocAIAssistantContext") {
|
|
454
|
+
const o = n.context.results?.[0]?.reply;
|
|
446
455
|
if (o)
|
|
447
456
|
return o;
|
|
448
457
|
}
|
|
449
458
|
}
|
|
450
459
|
return "";
|
|
451
460
|
default:
|
|
452
|
-
return
|
|
461
|
+
return z(e);
|
|
453
462
|
}
|
|
454
463
|
}
|
|
455
|
-
const
|
|
456
|
-
await g({ text: "Asking documentation assistant...", agentName: "doc-assistant" },
|
|
457
|
-
const
|
|
458
|
-
if (!
|
|
464
|
+
const Ee = async (t, e) => {
|
|
465
|
+
await g({ text: "Asking documentation assistant...", agentName: "doc-assistant" }, e);
|
|
466
|
+
const a = v(t.agentExecutionContext.messages).trim();
|
|
467
|
+
if (!a)
|
|
459
468
|
return {
|
|
460
469
|
status: "success",
|
|
461
470
|
outputMessage: "Please share your question and I can help with ArcGIS and Portal documentation."
|
|
462
471
|
};
|
|
463
|
-
const
|
|
464
|
-
|
|
465
|
-
const o =
|
|
466
|
-
portal:
|
|
467
|
-
question:
|
|
472
|
+
const n = e?.configurable?.context;
|
|
473
|
+
x(n);
|
|
474
|
+
const o = Ce(t.agentExecutionContext.sharedState), { reply: s, conversationId: i } = await ke({
|
|
475
|
+
portal: n.portal,
|
|
476
|
+
question: a,
|
|
468
477
|
previousConversationId: o.conversationId || void 0,
|
|
469
478
|
skillId: "doc_ai_assistant",
|
|
470
479
|
persona: "doc-online"
|
|
471
480
|
});
|
|
472
481
|
return {
|
|
473
482
|
status: "success",
|
|
474
|
-
outputMessage:
|
|
475
|
-
sharedStatePatch:
|
|
476
|
-
conversationId:
|
|
483
|
+
outputMessage: s.trim() || "I could not retrieve a response from the documentation assistant.",
|
|
484
|
+
sharedStatePatch: Ae({
|
|
485
|
+
conversationId: i || o.conversationId
|
|
477
486
|
})
|
|
478
487
|
};
|
|
479
|
-
},
|
|
480
|
-
async ({ groupTitle:
|
|
481
|
-
const
|
|
482
|
-
if (!
|
|
488
|
+
}, yt = pt(
|
|
489
|
+
async ({ groupTitle: t }, e) => {
|
|
490
|
+
const a = t.trim();
|
|
491
|
+
if (!a)
|
|
483
492
|
return null;
|
|
484
|
-
const
|
|
485
|
-
|
|
493
|
+
const n = e?.configurable?.context;
|
|
494
|
+
x(n);
|
|
486
495
|
try {
|
|
487
|
-
return (await
|
|
496
|
+
return (await Vt(n.portal, { query: `title:${a}`, num: 1 }))?.results[0]?.id || null;
|
|
488
497
|
} catch (o) {
|
|
489
498
|
return console.error("Error searching for portal group by title:", o), null;
|
|
490
499
|
}
|
|
@@ -492,126 +501,108 @@ const se = async (a, t) => {
|
|
|
492
501
|
{
|
|
493
502
|
name: "resolvePortalGroupIdByTitle",
|
|
494
503
|
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.",
|
|
495
|
-
schema:
|
|
496
|
-
groupTitle:
|
|
504
|
+
schema: r.object({
|
|
505
|
+
groupTitle: r.string().describe("The portal group title to resolve to a group id.")
|
|
497
506
|
})
|
|
498
507
|
}
|
|
499
|
-
),
|
|
500
|
-
async ({ itemTitle:
|
|
501
|
-
const
|
|
502
|
-
if (!
|
|
508
|
+
), wt = pt(
|
|
509
|
+
async ({ itemTitle: t }, e) => {
|
|
510
|
+
const a = t.trim();
|
|
511
|
+
if (!a)
|
|
503
512
|
return null;
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
const { result: o, error:
|
|
507
|
-
return
|
|
513
|
+
const n = e?.configurable?.context;
|
|
514
|
+
x(n);
|
|
515
|
+
const { result: o, error: s } = await Qt(n.portal, a, { num: 1 });
|
|
516
|
+
return s && console.error("Error searching for portal item by title:", s), o?.results[0]?.id || null;
|
|
508
517
|
},
|
|
509
518
|
{
|
|
510
519
|
name: "resolvePortalItemIdByTitle",
|
|
511
520
|
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.',
|
|
512
|
-
schema:
|
|
513
|
-
itemTitle:
|
|
521
|
+
schema: r.object({
|
|
522
|
+
itemTitle: r.string().describe("The portal item title to resolve to an item id.")
|
|
514
523
|
})
|
|
515
524
|
}
|
|
516
525
|
);
|
|
517
|
-
function G(
|
|
518
|
-
const
|
|
519
|
-
if (
|
|
520
|
-
return
|
|
521
|
-
const
|
|
522
|
-
return
|
|
526
|
+
function G(t, e = "#") {
|
|
527
|
+
const a = t.match(new RegExp(`\\${e}"([^"]+)"`, "u"));
|
|
528
|
+
if (a?.[1])
|
|
529
|
+
return a[1].trim();
|
|
530
|
+
const n = t.match(new RegExp(`\\${e}([^\\s"']+)`, "u"));
|
|
531
|
+
return n?.[1] ? n[1].trim() : null;
|
|
523
532
|
}
|
|
524
|
-
const
|
|
533
|
+
const vt = {
|
|
525
534
|
"portal-content": {
|
|
526
535
|
description: "The main content page of the portal.",
|
|
527
|
-
hints: ["My content", "Content"]
|
|
528
|
-
scope: "root"
|
|
536
|
+
hints: ["My content", "Content"]
|
|
529
537
|
},
|
|
530
538
|
"portal-content-favorites": {
|
|
531
|
-
description: "The
|
|
532
|
-
hints: ["My favorites", "Favorites", "Content favorites"]
|
|
533
|
-
scope: "collection"
|
|
539
|
+
description: "The Favorites view under Content in the portal.",
|
|
540
|
+
hints: ["My favorites", "Favorites", "Content favorites"]
|
|
534
541
|
},
|
|
535
542
|
"portal-content-group": {
|
|
536
|
-
description: "The
|
|
537
|
-
hints: ["Content
|
|
538
|
-
scope: "collection"
|
|
543
|
+
description: "The Groups view under Content in the portal.",
|
|
544
|
+
hints: ["Content groups", "Group content", "My groups content"]
|
|
539
545
|
},
|
|
540
546
|
"portal-content-living-atlas": {
|
|
541
547
|
description: "The Living Atlas view under Content in the portal.",
|
|
542
|
-
hints: ["Living Atlas", "Content
|
|
543
|
-
scope: "collection"
|
|
548
|
+
hints: ["Living Atlas", "Content living atlas"]
|
|
544
549
|
},
|
|
545
550
|
"portal-content-organization": {
|
|
546
|
-
description: "The
|
|
547
|
-
hints: ["
|
|
548
|
-
scope: "collection"
|
|
551
|
+
description: "The Organization view under Content in the portal.",
|
|
552
|
+
hints: ["Organization content", "Content organization", "My organization content"]
|
|
549
553
|
},
|
|
550
554
|
"portal-gallery": {
|
|
551
555
|
description: "The gallery page of the portal.",
|
|
552
|
-
hints: ["Gallery", "Featured content", "Maps and apps"]
|
|
553
|
-
scope: "collection"
|
|
556
|
+
hints: ["Gallery", "Featured content", "Maps and apps"]
|
|
554
557
|
},
|
|
555
558
|
"portal-group": {
|
|
556
559
|
description: "A specific group page in the portal.",
|
|
557
|
-
hints: ["Group", "group page"]
|
|
558
|
-
scope: "entity"
|
|
560
|
+
hints: ["Group", "group page"]
|
|
559
561
|
},
|
|
560
562
|
"portal-groups": {
|
|
561
563
|
description: "The groups listing page of the portal.",
|
|
562
|
-
hints: ["
|
|
563
|
-
scope: "collection"
|
|
564
|
+
hints: ["Groups", "Browse groups"]
|
|
564
565
|
},
|
|
565
566
|
"portal-groups-featured": {
|
|
566
567
|
description: "The Featured groups view under Groups in the portal.",
|
|
567
|
-
hints: ["Featured groups", "Groups featured"]
|
|
568
|
-
scope: "collection"
|
|
568
|
+
hints: ["Featured groups", "Groups featured"]
|
|
569
569
|
},
|
|
570
570
|
"portal-groups-my": {
|
|
571
571
|
description: "The My groups view under Groups in the portal.",
|
|
572
|
-
hints: ["My groups", "Groups my"]
|
|
573
|
-
scope: "collection"
|
|
572
|
+
hints: ["My groups", "Groups my"]
|
|
574
573
|
},
|
|
575
574
|
"portal-groups-organization": {
|
|
576
|
-
description: "The
|
|
577
|
-
hints: ["Organization
|
|
578
|
-
scope: "collection"
|
|
575
|
+
description: "The Organization groups view under Groups in the portal.",
|
|
576
|
+
hints: ["Organization groups", "Groups organization", "My organization groups"]
|
|
579
577
|
},
|
|
580
578
|
"portal-item": {
|
|
581
579
|
description: "A specific item page in the portal.",
|
|
582
|
-
hints: ["Item", "item page"]
|
|
583
|
-
scope: "entity"
|
|
580
|
+
hints: ["Item", "item page"]
|
|
584
581
|
},
|
|
585
582
|
"portal-map-viewer": {
|
|
586
583
|
description: "The Map Viewer app of the portal.",
|
|
587
|
-
hints: ["Map Viewer", "Map", "Open map"]
|
|
588
|
-
scope: "entity"
|
|
584
|
+
hints: ["Map Viewer", "Map", "Open map"]
|
|
589
585
|
},
|
|
590
586
|
"portal-notebooks": {
|
|
591
587
|
description: "The Notebooks home page of the portal.",
|
|
592
|
-
hints: ["Notebooks", "Notebook home", "My notebooks"]
|
|
593
|
-
scope: "collection"
|
|
588
|
+
hints: ["Notebooks", "Notebook home", "My notebooks"]
|
|
594
589
|
},
|
|
595
590
|
"portal-scene-viewer": {
|
|
596
591
|
description: "The Scene Viewer app of the portal.",
|
|
597
|
-
hints: ["Scene Viewer", "Scene", "3D scene"]
|
|
598
|
-
scope: "entity"
|
|
592
|
+
hints: ["Scene Viewer", "Scene", "3D scene"]
|
|
599
593
|
},
|
|
600
|
-
"portal-
|
|
594
|
+
"portal-org-security": {
|
|
601
595
|
description: "The Organization > Settings > Security page of the portal.",
|
|
602
|
-
hints: ["Organization settings", "Security", "Organization > Settings > Security"]
|
|
603
|
-
scope: "entity"
|
|
596
|
+
hints: ["Organization settings", "Security", "Organization > Settings > Security"]
|
|
604
597
|
}
|
|
605
|
-
},
|
|
606
|
-
|
|
607
|
-
).join(`
|
|
608
|
-
`), ne = `
|
|
598
|
+
}, $e = Bt(vt), Re = Object.entries(vt).map(([t, { description: e, hints: a }]) => ` - ${t}: ${e} (hints: ${a.join(", ")})`).join(`
|
|
599
|
+
`), De = `
|
|
609
600
|
You decide whether the assistant response should include a navigation action to ArcGIS Portal.
|
|
610
601
|
|
|
611
602
|
Given the user question and assistant response:
|
|
612
603
|
- Decide if a navigation action would help the user complete the task.
|
|
613
|
-
- If yes, choose one
|
|
614
|
-
${
|
|
604
|
+
- If yes, choose one destinationType:
|
|
605
|
+
${Re}
|
|
615
606
|
|
|
616
607
|
Rules:
|
|
617
608
|
- Only suggest navigation when you are highly confident the destination will help complete the user's task.
|
|
@@ -634,90 +625,98 @@ User question:
|
|
|
634
625
|
|
|
635
626
|
Assistant response:
|
|
636
627
|
{response}
|
|
637
|
-
`,
|
|
638
|
-
shouldSuggestNavigation:
|
|
639
|
-
destinationType:
|
|
640
|
-
itemId:
|
|
641
|
-
groupId:
|
|
642
|
-
confidence:
|
|
643
|
-
}),
|
|
644
|
-
await g({ text: "Extracting navigation intent...", agentName: "doc-assistant" },
|
|
645
|
-
const
|
|
646
|
-
if (!
|
|
628
|
+
`, Z = r.object({
|
|
629
|
+
shouldSuggestNavigation: r.boolean().default(!1),
|
|
630
|
+
destinationType: r.enum(["none", ...$e]).default("none"),
|
|
631
|
+
itemId: r.string().default(""),
|
|
632
|
+
groupId: r.string().default(""),
|
|
633
|
+
confidence: r.number().min(0).max(1).default(0)
|
|
634
|
+
}), Ue = async (t, e) => {
|
|
635
|
+
await g({ text: "Extracting navigation intent...", agentName: "doc-assistant" }, e);
|
|
636
|
+
const a = t.outputMessage.trim();
|
|
637
|
+
if (!a)
|
|
647
638
|
return {};
|
|
648
|
-
const
|
|
649
|
-
question:
|
|
650
|
-
response:
|
|
651
|
-
}),
|
|
652
|
-
if (!
|
|
639
|
+
const n = v(t.agentExecutionContext.messages).trim(), o = await B.fromTemplate(De).format({
|
|
640
|
+
question: n,
|
|
641
|
+
response: a
|
|
642
|
+
}), i = (await L({ modelTier: "fast" })).withStructuredOutput(Z), u = Z.parse(await i.invoke(o));
|
|
643
|
+
if (!u.shouldSuggestNavigation || u.destinationType === "none")
|
|
653
644
|
return {};
|
|
654
|
-
if (
|
|
655
|
-
const
|
|
656
|
-
|
|
645
|
+
if (u.destinationType === "portal-item" && !u.itemId) {
|
|
646
|
+
const d = G(n, "#");
|
|
647
|
+
d && (u.itemId = await wt.invoke({ itemTitle: d }, e) ?? "");
|
|
657
648
|
}
|
|
658
|
-
if (
|
|
659
|
-
const
|
|
660
|
-
|
|
649
|
+
if (u.destinationType === "portal-group" && !u.groupId) {
|
|
650
|
+
const d = G(n, "$") ?? G(n, "#");
|
|
651
|
+
d && (u.groupId = await yt.invoke({ groupTitle: d }, e) ?? "");
|
|
661
652
|
}
|
|
662
|
-
const
|
|
663
|
-
return
|
|
653
|
+
const c = Fe(u);
|
|
654
|
+
return c ? (await E(c, e), {}) : {};
|
|
664
655
|
};
|
|
665
|
-
function
|
|
666
|
-
destinationType:
|
|
667
|
-
itemId:
|
|
668
|
-
groupId:
|
|
656
|
+
function Fe({
|
|
657
|
+
destinationType: t,
|
|
658
|
+
itemId: e,
|
|
659
|
+
groupId: a
|
|
669
660
|
}) {
|
|
670
|
-
switch (
|
|
661
|
+
switch (t) {
|
|
671
662
|
case "portal-content":
|
|
663
|
+
case "portal-gallery":
|
|
664
|
+
case "portal-groups":
|
|
665
|
+
case "portal-map-viewer":
|
|
666
|
+
case "portal-notebooks":
|
|
667
|
+
case "portal-scene-viewer":
|
|
668
|
+
return { destinationType: t };
|
|
669
|
+
case "portal-org-security":
|
|
670
|
+
return { destinationType: "portal-org", hash: "settings" };
|
|
672
671
|
case "portal-content-favorites":
|
|
672
|
+
return { destinationType: "portal-content", hash: "favorites" };
|
|
673
673
|
case "portal-content-group":
|
|
674
|
+
return { destinationType: "portal-content", hash: "group" };
|
|
674
675
|
case "portal-content-living-atlas":
|
|
676
|
+
return { destinationType: "portal-content", hash: "living-atlas" };
|
|
675
677
|
case "portal-content-organization":
|
|
676
|
-
|
|
677
|
-
case "portal-groups":
|
|
678
|
+
return { destinationType: "portal-content", hash: "org" };
|
|
678
679
|
case "portal-groups-featured":
|
|
680
|
+
return { destinationType: "portal-groups", hash: "featured" };
|
|
679
681
|
case "portal-groups-my":
|
|
682
|
+
return { destinationType: "portal-groups", hash: "my" };
|
|
680
683
|
case "portal-groups-organization":
|
|
681
|
-
|
|
682
|
-
case "portal-notebooks":
|
|
683
|
-
case "portal-scene-viewer":
|
|
684
|
-
case "portal-settings-security":
|
|
685
|
-
return { destinationType: a };
|
|
684
|
+
return { destinationType: "portal-groups", hash: "organization" };
|
|
686
685
|
case "portal-item":
|
|
687
|
-
return
|
|
686
|
+
return e ? { destinationType: t, itemId: e } : null;
|
|
688
687
|
case "portal-group":
|
|
689
|
-
return
|
|
688
|
+
return a ? { destinationType: t, groupId: a } : null;
|
|
690
689
|
case "none":
|
|
691
690
|
return null;
|
|
692
691
|
default:
|
|
693
|
-
return
|
|
692
|
+
return z(t);
|
|
694
693
|
}
|
|
695
694
|
}
|
|
696
|
-
const
|
|
697
|
-
...
|
|
698
|
-
}),
|
|
695
|
+
const bt = h.Root({
|
|
696
|
+
...N()
|
|
697
|
+
}), Oe = () => new C(bt).addNode("answerDocQuestion", Ee).addNode("extractNavigationIntent", Ue).addEdge(A, "answerDocQuestion").addEdge("answerDocQuestion", "extractNavigationIntent").addEdge("extractNavigationIntent", w), Ke = String.raw`- **portal-doc-assistant** - General ArcGIS documentation and Portal help assistant:
|
|
699
698
|
- answers general ArcGIS, Portal, Enterprise, and JavaScript SDK questions
|
|
700
699
|
- acts as a fallback when specialized agents are not applicable
|
|
701
|
-
`,
|
|
700
|
+
`, Ve = {
|
|
702
701
|
id: "portal-doc-assistant",
|
|
703
702
|
name: "Portal Doc Assistant",
|
|
704
|
-
description:
|
|
705
|
-
createGraph:
|
|
706
|
-
workspace:
|
|
707
|
-
},
|
|
708
|
-
const
|
|
709
|
-
return
|
|
710
|
-
},
|
|
703
|
+
description: Ke,
|
|
704
|
+
createGraph: Oe,
|
|
705
|
+
workspace: bt
|
|
706
|
+
}, je = () => ({ latestGroupId: null, memory: {} }), $ = (t) => {
|
|
707
|
+
const e = t?.agentExecutionContext.sharedState.portalGroupSummaryMemory?.value;
|
|
708
|
+
return e ? { latestGroupId: e.latestGroupId, memory: e.memory } : je();
|
|
709
|
+
}, It = `
|
|
711
710
|
Shared markdown formatting rules:
|
|
712
711
|
- Use clear markdown headings (##) to separate sections.
|
|
713
712
|
- Use concise bullet points for lists of facts, counts, or signals.
|
|
714
713
|
- Emphasize key metrics with bold labels (for example: **Recent items:** 4).
|
|
715
714
|
- Keep wording direct and analytical; avoid filler language but make sure the language is friendly.
|
|
716
715
|
- Do not include raw internal IDs unless explicitly requested.
|
|
717
|
-
`,
|
|
716
|
+
`, Le = `
|
|
718
717
|
You answer follow-up questions about ArcGIS group analytics.
|
|
719
718
|
|
|
720
|
-
${
|
|
719
|
+
${It}
|
|
721
720
|
|
|
722
721
|
Ground your answer in the provided group analytics summary and context.
|
|
723
722
|
If the answer is not available from the provided context, state that clearly and suggest what to check next.
|
|
@@ -739,18 +738,18 @@ Group full context:
|
|
|
739
738
|
|
|
740
739
|
Question:
|
|
741
740
|
{question}
|
|
742
|
-
`,
|
|
743
|
-
await g({ text: "Answering group follow-up...", agentName: "group-analytics" },
|
|
744
|
-
const
|
|
741
|
+
`, Be = async (t, e) => {
|
|
742
|
+
await g({ text: "Answering group follow-up...", agentName: "group-analytics" }, e);
|
|
743
|
+
const a = $(t), n = t.groupSummaryGroupId ?? a.latestGroupId, o = n ? a.memory[n] : void 0, s = t.groupSummaryQuestion || v(t.agentExecutionContext.messages);
|
|
745
744
|
return o ? {
|
|
746
745
|
status: "success",
|
|
747
|
-
outputMessage: (await
|
|
748
|
-
promptText:
|
|
749
|
-
schema:
|
|
746
|
+
outputMessage: (await b({
|
|
747
|
+
promptText: Le,
|
|
748
|
+
schema: Qe,
|
|
750
749
|
modelTier: "default",
|
|
751
750
|
inputVariables: {
|
|
752
751
|
summary: o.summary,
|
|
753
|
-
question:
|
|
752
|
+
question: s,
|
|
754
753
|
fullContext: JSON.stringify(o.fullContext)
|
|
755
754
|
}
|
|
756
755
|
})).answer
|
|
@@ -758,10 +757,10 @@ Question:
|
|
|
758
757
|
status: "success",
|
|
759
758
|
outputMessage: "I do not have group analytics context yet. Ask me to analyze a group first with analyze group <group id>."
|
|
760
759
|
};
|
|
761
|
-
},
|
|
762
|
-
answer:
|
|
763
|
-
isRelevant:
|
|
764
|
-
}),
|
|
760
|
+
}, Qe = r.object({
|
|
761
|
+
answer: r.string(),
|
|
762
|
+
isRelevant: r.boolean()
|
|
763
|
+
}), We = `
|
|
765
764
|
Classify the user's request for ArcGIS Portal group analytics.
|
|
766
765
|
|
|
767
766
|
Rules:
|
|
@@ -790,121 +789,121 @@ hasAnalyticsContext:
|
|
|
790
789
|
|
|
791
790
|
User message:
|
|
792
791
|
{userMessage}
|
|
793
|
-
`,
|
|
794
|
-
await g({ text: "Analyzing group-analytics intent...", agentName: "group-analytics" },
|
|
795
|
-
const
|
|
796
|
-
userMessage:
|
|
797
|
-
hasAnalyticsContext: String(
|
|
798
|
-
}),
|
|
799
|
-
let
|
|
800
|
-
if ((
|
|
801
|
-
const
|
|
802
|
-
|
|
792
|
+
`, Je = async (t, e) => {
|
|
793
|
+
await g({ text: "Analyzing group-analytics intent...", agentName: "group-analytics" }, e);
|
|
794
|
+
const a = v(t.agentExecutionContext.messages), n = !!$(t).latestGroupId, o = await B.fromTemplate(We).format({
|
|
795
|
+
userMessage: a,
|
|
796
|
+
hasAnalyticsContext: String(n)
|
|
797
|
+
}), i = (await L({ modelTier: "fast" })).withStructuredOutput(tt), u = tt.parse(await i.invoke(o));
|
|
798
|
+
let c = u.groupId;
|
|
799
|
+
if ((u.intent === "summarize" || u.intent === "navigation") && !c) {
|
|
800
|
+
const y = G(a, "$");
|
|
801
|
+
y && (c = await yt.invoke({ groupTitle: y }, e) ?? "");
|
|
803
802
|
}
|
|
804
|
-
const { intent:
|
|
803
|
+
const { intent: d, question: l } = u, m = d === "summarize" && !c, p = d === "followUp" && !(l ?? "").trim(), f = d === "clarify" || m || p;
|
|
805
804
|
return {
|
|
806
|
-
groupSummaryIntent:
|
|
807
|
-
groupSummaryGroupId:
|
|
808
|
-
groupSummaryQuestion:
|
|
805
|
+
groupSummaryIntent: f ? "clarify" : d,
|
|
806
|
+
groupSummaryGroupId: c || null,
|
|
807
|
+
groupSummaryQuestion: l || "",
|
|
809
808
|
status: "success",
|
|
810
|
-
outputMessage:
|
|
809
|
+
outputMessage: f ? "Please clarify with a group id or title" : ""
|
|
811
810
|
};
|
|
812
|
-
},
|
|
813
|
-
intent:
|
|
814
|
-
groupId:
|
|
815
|
-
question:
|
|
816
|
-
}),
|
|
817
|
-
const
|
|
818
|
-
return await g({ text: "Preparing navigation...", agentName: "group-analytics" },
|
|
819
|
-
|
|
820
|
-
|
|
811
|
+
}, tt = r.object({
|
|
812
|
+
intent: r.enum(["summarize", "followUp", "navigation", "clarify"]),
|
|
813
|
+
groupId: r.string().default(""),
|
|
814
|
+
question: r.string().default("")
|
|
815
|
+
}), _e = async (t, e) => {
|
|
816
|
+
const a = $(t), n = t.groupSummaryGroupId ?? a.latestGroupId;
|
|
817
|
+
return await g({ text: "Preparing navigation...", agentName: "group-analytics" }, e), await E(
|
|
818
|
+
n ? { destinationType: "portal-group", groupId: n } : { destinationType: "portal-groups" },
|
|
819
|
+
e
|
|
821
820
|
), { status: "success" };
|
|
822
821
|
};
|
|
823
|
-
function
|
|
824
|
-
return
|
|
822
|
+
function xt({ timestamp: t, now: e, windowMs: a }) {
|
|
823
|
+
return t ? e - t <= a : !1;
|
|
825
824
|
}
|
|
826
|
-
const
|
|
827
|
-
function
|
|
828
|
-
const
|
|
825
|
+
const Ye = 720 * 60 * 60 * 1e3;
|
|
826
|
+
function He(t) {
|
|
827
|
+
const e = Jt(t);
|
|
829
828
|
return {
|
|
830
|
-
id:
|
|
831
|
-
title:
|
|
832
|
-
description:
|
|
833
|
-
snippet:
|
|
834
|
-
access:
|
|
835
|
-
owner:
|
|
836
|
-
tags:
|
|
837
|
-
created:
|
|
838
|
-
modified:
|
|
839
|
-
isInvitationOnly:
|
|
829
|
+
id: t.id ?? "",
|
|
830
|
+
title: t.title ?? "",
|
|
831
|
+
description: t.description ?? "",
|
|
832
|
+
snippet: t.snippet ?? "",
|
|
833
|
+
access: t.access ?? null,
|
|
834
|
+
owner: t.owner ?? "",
|
|
835
|
+
tags: t.tags ?? [],
|
|
836
|
+
created: t.created?.getTime(),
|
|
837
|
+
modified: t.modified?.getTime(),
|
|
838
|
+
isInvitationOnly: t.isInvitationOnly,
|
|
840
839
|
sourceSignals: {
|
|
841
|
-
capabilities:
|
|
842
|
-
membershipAccess:
|
|
843
|
-
isOpenData:
|
|
844
|
-
isDistributedCollaborationGroup:
|
|
845
|
-
orgId:
|
|
846
|
-
hiddenMembers:
|
|
847
|
-
isViewOnly:
|
|
848
|
-
isReadOnly:
|
|
849
|
-
leavingDisallowed:
|
|
840
|
+
capabilities: Xt(t),
|
|
841
|
+
membershipAccess: Ht(t),
|
|
842
|
+
isOpenData: Yt(t),
|
|
843
|
+
isDistributedCollaborationGroup: _t(t),
|
|
844
|
+
orgId: e.orgId,
|
|
845
|
+
hiddenMembers: e.hiddenMembers,
|
|
846
|
+
isViewOnly: e.isViewOnly,
|
|
847
|
+
isReadOnly: e.isReadOnly,
|
|
848
|
+
leavingDisallowed: e.leavingDisallowed
|
|
850
849
|
}
|
|
851
850
|
};
|
|
852
851
|
}
|
|
853
|
-
async function
|
|
854
|
-
const
|
|
852
|
+
async function Xe(t) {
|
|
853
|
+
const e = { owner: t.owner ?? "", admins: [], users: [] };
|
|
855
854
|
try {
|
|
856
|
-
return await
|
|
857
|
-
} catch (
|
|
858
|
-
return console.warn("Unable to fetch group members for analytics context",
|
|
855
|
+
return await t.fetchMembers();
|
|
856
|
+
} catch (a) {
|
|
857
|
+
return console.warn("Unable to fetch group members for analytics context", a), e;
|
|
859
858
|
}
|
|
860
859
|
}
|
|
861
|
-
function
|
|
862
|
-
return
|
|
863
|
-
id:
|
|
864
|
-
title:
|
|
865
|
-
type:
|
|
866
|
-
owner:
|
|
867
|
-
created:
|
|
868
|
-
modified:
|
|
860
|
+
function Ze(t) {
|
|
861
|
+
return t.map((e) => ({
|
|
862
|
+
id: e.id ?? "",
|
|
863
|
+
title: e.title ?? "Untitled",
|
|
864
|
+
type: e.type ?? "Unknown",
|
|
865
|
+
owner: e.owner ?? "",
|
|
866
|
+
created: e.created?.getTime(),
|
|
867
|
+
modified: e.modified?.getTime()
|
|
869
868
|
}));
|
|
870
869
|
}
|
|
871
|
-
function
|
|
872
|
-
return
|
|
873
|
-
(
|
|
870
|
+
function ta(t, e) {
|
|
871
|
+
return t.filter(
|
|
872
|
+
(a) => a.modified ? xt({ timestamp: a.modified, now: e, windowMs: Ye }) : !1
|
|
874
873
|
);
|
|
875
874
|
}
|
|
876
|
-
function
|
|
877
|
-
const
|
|
878
|
-
for (const
|
|
879
|
-
|
|
880
|
-
return [...
|
|
875
|
+
function ea(t) {
|
|
876
|
+
const e = /* @__PURE__ */ new Map();
|
|
877
|
+
for (const a of t)
|
|
878
|
+
e.set(a.type, (e.get(a.type) ?? 0) + 1);
|
|
879
|
+
return [...e.entries()].sort((a, n) => n[1] - a[1] || a[0].localeCompare(n[0])).slice(0, 6).map(([a, n]) => ({ type: a, count: n }));
|
|
881
880
|
}
|
|
882
|
-
async function
|
|
883
|
-
const
|
|
881
|
+
async function aa(t) {
|
|
882
|
+
const e = await t.queryItems({ num: 20, sortField: "modified", sortOrder: "desc" }), a = Ze(e.results), n = Date.now();
|
|
884
883
|
return {
|
|
885
|
-
total:
|
|
886
|
-
topItems:
|
|
887
|
-
recentlyModifiedItems:
|
|
888
|
-
topItemTypes:
|
|
884
|
+
total: e.total,
|
|
885
|
+
topItems: a,
|
|
886
|
+
recentlyModifiedItems: ta(a, n),
|
|
887
|
+
topItemTypes: ea(a)
|
|
889
888
|
};
|
|
890
889
|
}
|
|
891
|
-
async function
|
|
892
|
-
if (!
|
|
890
|
+
async function na(t, e) {
|
|
891
|
+
if (!e)
|
|
893
892
|
return { error: { code: "missingGroupId", message: "Group id is required." } };
|
|
894
893
|
try {
|
|
895
|
-
const
|
|
896
|
-
if (!
|
|
897
|
-
return { error: { code: "groupNotFound", message: `No group found for id: ${
|
|
898
|
-
const o =
|
|
899
|
-
return { result: { group: o, members:
|
|
900
|
-
} catch (
|
|
901
|
-
return console.error("Error fetching portal group analytics context:",
|
|
894
|
+
const n = (await t.queryGroups({ query: `id:${e}`, num: 1 })).results[0];
|
|
895
|
+
if (!n)
|
|
896
|
+
return { error: { code: "groupNotFound", message: `No group found for id: ${e}` } };
|
|
897
|
+
const o = He(n), s = await Xe(n), i = await aa(n);
|
|
898
|
+
return { result: { group: o, members: s, items: i } };
|
|
899
|
+
} catch (a) {
|
|
900
|
+
return console.error("Error fetching portal group analytics context:", a), { error: { code: "unhandledError" } };
|
|
902
901
|
}
|
|
903
902
|
}
|
|
904
|
-
const
|
|
903
|
+
const oa = `
|
|
905
904
|
You summarize ArcGIS Portal groups based on structured context and deterministic activity signals.
|
|
906
905
|
|
|
907
|
-
${
|
|
906
|
+
${It}
|
|
908
907
|
|
|
909
908
|
Output format requirements:
|
|
910
909
|
- Return concise markdown with clear sections in this order:
|
|
@@ -940,82 +939,82 @@ Group context:
|
|
|
940
939
|
|
|
941
940
|
Deterministic signals:
|
|
942
941
|
{deterministicSignals}
|
|
943
|
-
`,
|
|
944
|
-
const
|
|
945
|
-
if (!
|
|
942
|
+
`, sa = 2160 * 60 * 60 * 1e3, ra = async (t, e) => {
|
|
943
|
+
const a = t.groupSummaryGroupId;
|
|
944
|
+
if (!a)
|
|
946
945
|
return {
|
|
947
946
|
status: "success",
|
|
948
947
|
outputMessage: 'Please clarify with analyze group <group id>, analyze group $<title>, or analyze group $"<title with spaces>".'
|
|
949
948
|
};
|
|
950
|
-
await g({ text: `Analyzing group ${
|
|
951
|
-
const
|
|
952
|
-
|
|
953
|
-
const { result: o, error:
|
|
954
|
-
if (
|
|
955
|
-
return await g({ text: "Failed to fetch group context", agentName: "group-analytics" },
|
|
949
|
+
await g({ text: `Analyzing group ${a}...`, agentName: "group-analytics" }, e);
|
|
950
|
+
const n = e?.configurable?.context;
|
|
951
|
+
x(n);
|
|
952
|
+
const { result: o, error: s } = await na(n.portal, a);
|
|
953
|
+
if (s || !o)
|
|
954
|
+
return await g({ text: "Failed to fetch group context", agentName: "group-analytics" }, e), {
|
|
956
955
|
status: "success",
|
|
957
956
|
outputMessage: "Unable to retrieve group context for analytics."
|
|
958
957
|
};
|
|
959
|
-
const { group:
|
|
960
|
-
promptText:
|
|
961
|
-
schema:
|
|
958
|
+
const { group: i, items: u } = o, c = Date.now(), d = i.modified, l = d ? xt({ timestamp: d, now: c, windowMs: sa }) : !1, m = u.recentlyModifiedItems.length, p = m > 0, f = l || p, y = await b({
|
|
959
|
+
promptText: oa,
|
|
960
|
+
schema: ia,
|
|
962
961
|
modelTier: "default",
|
|
963
962
|
inputVariables: {
|
|
964
963
|
context: JSON.stringify(o),
|
|
965
964
|
deterministicSignals: JSON.stringify({
|
|
966
|
-
isGroupActive:
|
|
967
|
-
isGroupRecentlyModified:
|
|
968
|
-
hasRecentlyAddedOrUpdatedContent:
|
|
965
|
+
isGroupActive: f,
|
|
966
|
+
isGroupRecentlyModified: l,
|
|
967
|
+
hasRecentlyAddedOrUpdatedContent: p,
|
|
969
968
|
recentItemCount: m
|
|
970
969
|
})
|
|
971
970
|
}
|
|
972
|
-
}), { followUpQuestions:
|
|
973
|
-
latestGroupId:
|
|
971
|
+
}), { followUpQuestions: I, summary: S } = y, kt = $(t), qt = {
|
|
972
|
+
latestGroupId: a,
|
|
974
973
|
memory: {
|
|
975
|
-
...
|
|
976
|
-
[
|
|
974
|
+
...kt.memory,
|
|
975
|
+
[a]: { summary: S, followUpQuestions: I, fullContext: o }
|
|
977
976
|
}
|
|
978
977
|
};
|
|
979
|
-
return
|
|
978
|
+
return I.length && await j({ type: "suggested-prompts", data: { prompts: I } }, e), {
|
|
980
979
|
status: "success",
|
|
981
980
|
outputMessage: S,
|
|
982
|
-
sharedStatePatch: { portalGroupSummaryMemory: { value:
|
|
981
|
+
sharedStatePatch: { portalGroupSummaryMemory: { value: qt } }
|
|
983
982
|
};
|
|
984
|
-
},
|
|
985
|
-
summary:
|
|
986
|
-
followUpQuestions:
|
|
987
|
-
}),
|
|
988
|
-
...
|
|
989
|
-
groupSummaryIntent:
|
|
990
|
-
reducer:
|
|
983
|
+
}, ia = r.object({
|
|
984
|
+
summary: r.string(),
|
|
985
|
+
followUpQuestions: r.array(r.string()).default([])
|
|
986
|
+
}), R = (t, e) => e ?? t, St = h.Root({
|
|
987
|
+
...N(),
|
|
988
|
+
groupSummaryIntent: h({
|
|
989
|
+
reducer: R,
|
|
991
990
|
default: () => "clarify"
|
|
992
991
|
}),
|
|
993
|
-
groupSummaryGroupId:
|
|
994
|
-
reducer:
|
|
992
|
+
groupSummaryGroupId: h({
|
|
993
|
+
reducer: R,
|
|
995
994
|
default: () => null
|
|
996
995
|
}),
|
|
997
|
-
groupSummaryQuestion:
|
|
998
|
-
reducer:
|
|
996
|
+
groupSummaryQuestion: h({
|
|
997
|
+
reducer: R,
|
|
999
998
|
default: () => ""
|
|
1000
999
|
})
|
|
1001
|
-
}),
|
|
1000
|
+
}), ua = () => new C(St).addNode("detectGroupSummaryIntent", Je).addNode("summarizePortalGroup", ra).addNode("answerGroupSummaryFollowUp", Be).addNode("suggestGroupSummaryNavigation", _e).addEdge(A, "detectGroupSummaryIntent").addConditionalEdges("detectGroupSummaryIntent", (e) => e.groupSummaryIntent === "summarize" ? "summarizePortalGroup" : e.groupSummaryIntent === "followUp" ? "answerGroupSummaryFollowUp" : e.groupSummaryIntent === "navigation" ? "suggestGroupSummaryNavigation" : w).addEdge("summarizePortalGroup", w).addEdge("answerGroupSummaryFollowUp", w).addEdge("suggestGroupSummaryNavigation", w), ca = String.raw`- **portal-group-analytics** - Portal group analytics assistant:
|
|
1002
1001
|
- summarizes ArcGIS portal groups from group context and sourceJSON details
|
|
1003
1002
|
- answers follow-up questions grounded in the summarized group
|
|
1004
1003
|
- suggests navigation to groups when relevant
|
|
1005
|
-
`,
|
|
1004
|
+
`, la = {
|
|
1006
1005
|
id: "portal-group-analytics",
|
|
1007
1006
|
name: "Portal Group Analytics",
|
|
1008
|
-
description:
|
|
1009
|
-
createGraph:
|
|
1010
|
-
workspace:
|
|
1011
|
-
},
|
|
1012
|
-
const
|
|
1013
|
-
return
|
|
1014
|
-
},
|
|
1015
|
-
intent:
|
|
1016
|
-
itemId:
|
|
1017
|
-
question:
|
|
1018
|
-
}),
|
|
1007
|
+
description: ca,
|
|
1008
|
+
createGraph: ua,
|
|
1009
|
+
workspace: St
|
|
1010
|
+
}, da = () => ({ latestItemId: null, memory: {} }), Q = (t) => {
|
|
1011
|
+
const e = t?.agentExecutionContext.sharedState.portalItemAnalyticsSummaryMemory?.value;
|
|
1012
|
+
return e ? { latestItemId: e.latestItemId, memory: e.memory } : da();
|
|
1013
|
+
}, et = r.object({
|
|
1014
|
+
intent: r.enum(["summarize", "followUp", "clarify"]),
|
|
1015
|
+
itemId: r.string().default(""),
|
|
1016
|
+
question: r.string().default("")
|
|
1017
|
+
}), pa = r.object({ summary: r.string(), followUpQuestions: r.array(r.string()).default([]) }), ma = r.object({ answer: r.string(), isRelevant: r.boolean() }), ga = `
|
|
1019
1018
|
You answer follow-up questions about an ArcGIS item.
|
|
1020
1019
|
|
|
1021
1020
|
Ground your answer in the provided item context.
|
|
@@ -1035,18 +1034,18 @@ Item full context
|
|
|
1035
1034
|
|
|
1036
1035
|
Question:
|
|
1037
1036
|
{question}
|
|
1038
|
-
`,
|
|
1039
|
-
await g({ text: "Answering follow-up...", agentName: "analytics" },
|
|
1040
|
-
const
|
|
1037
|
+
`, ha = async (t, e) => {
|
|
1038
|
+
await g({ text: "Answering follow-up...", agentName: "analytics" }, e);
|
|
1039
|
+
const a = Q(t), n = t.analyticsItemId ?? a.latestItemId, o = n ? a.memory[n] : void 0, s = t.analyticsQuestion || v(t.agentExecutionContext.messages);
|
|
1041
1040
|
return o ? {
|
|
1042
1041
|
status: "success",
|
|
1043
|
-
outputMessage: (await
|
|
1044
|
-
promptText:
|
|
1045
|
-
schema:
|
|
1042
|
+
outputMessage: (await b({
|
|
1043
|
+
promptText: ga,
|
|
1044
|
+
schema: ma,
|
|
1046
1045
|
modelTier: "default",
|
|
1047
1046
|
inputVariables: {
|
|
1048
1047
|
summary: o.summary,
|
|
1049
|
-
question:
|
|
1048
|
+
question: s,
|
|
1050
1049
|
fullContext: JSON.stringify(o.fullContext)
|
|
1051
1050
|
}
|
|
1052
1051
|
})).answer
|
|
@@ -1054,7 +1053,7 @@ Question:
|
|
|
1054
1053
|
status: "success",
|
|
1055
1054
|
outputMessage: "I don't have enough information yet. Please ask me to summarize the item first using summarize item <item id>."
|
|
1056
1055
|
};
|
|
1057
|
-
},
|
|
1056
|
+
}, fa = `
|
|
1058
1057
|
Classify the user analytics request.
|
|
1059
1058
|
|
|
1060
1059
|
Rules:
|
|
@@ -1084,27 +1083,27 @@ hasSummaryContext:
|
|
|
1084
1083
|
|
|
1085
1084
|
User message:
|
|
1086
1085
|
{userMessage}
|
|
1087
|
-
`,
|
|
1088
|
-
await g({ text: "Analyzing intent...", agentName: "analytics" },
|
|
1089
|
-
const
|
|
1090
|
-
userMessage:
|
|
1091
|
-
hasSummaryContext: String(
|
|
1092
|
-
}),
|
|
1093
|
-
let
|
|
1094
|
-
if (
|
|
1095
|
-
const
|
|
1096
|
-
|
|
1086
|
+
`, ya = async (t, e) => {
|
|
1087
|
+
await g({ text: "Analyzing intent...", agentName: "analytics" }, e);
|
|
1088
|
+
const a = v(t.agentExecutionContext.messages), n = !!Q(t).latestItemId, o = await B.fromTemplate(fa).format({
|
|
1089
|
+
userMessage: a,
|
|
1090
|
+
hasSummaryContext: String(n)
|
|
1091
|
+
}), i = (await L({ modelTier: "fast" })).withStructuredOutput(et), u = et.parse(await i.invoke(o));
|
|
1092
|
+
let c = u.itemId;
|
|
1093
|
+
if (u.intent === "summarize" && !c) {
|
|
1094
|
+
const y = G(a, "#");
|
|
1095
|
+
y && (c = await wt.invoke({ itemTitle: y }, e) ?? "");
|
|
1097
1096
|
}
|
|
1098
|
-
const { intent:
|
|
1097
|
+
const { intent: d, question: l } = u, f = d === "clarify" || d === "summarize" && !c || d === "followUp" && !l;
|
|
1099
1098
|
return {
|
|
1100
|
-
agentExecutionContext: { ...
|
|
1101
|
-
analyticsIntent:
|
|
1102
|
-
analyticsItemId:
|
|
1103
|
-
analyticsQuestion:
|
|
1099
|
+
agentExecutionContext: { ...t.agentExecutionContext },
|
|
1100
|
+
analyticsIntent: f ? "clarify" : d,
|
|
1101
|
+
analyticsItemId: c || null,
|
|
1102
|
+
analyticsQuestion: l || "",
|
|
1104
1103
|
status: "success",
|
|
1105
|
-
outputMessage:
|
|
1104
|
+
outputMessage: f ? 'Please clarify with summarize item <item id>, summarize item #<title>, or summarize item #"<title with spaces>".' : ""
|
|
1106
1105
|
};
|
|
1107
|
-
},
|
|
1106
|
+
}, wa = `
|
|
1108
1107
|
You are a item summary tool for ArcGIS. Your job is to summarize an item's info based on the provided context.
|
|
1109
1108
|
Summary rules:
|
|
1110
1109
|
- The summary should be concise markdown, make sure to format the output nicely so it's easy to read.
|
|
@@ -1119,215 +1118,749 @@ Do not include internal identifiers.
|
|
|
1119
1118
|
If the user asks for a detailed summary, you may expand the response up to 300 words.
|
|
1120
1119
|
Item context:
|
|
1121
1120
|
{context}
|
|
1122
|
-
`,
|
|
1123
|
-
const
|
|
1124
|
-
if (!
|
|
1121
|
+
`, va = async (t, e) => {
|
|
1122
|
+
const a = t.analyticsItemId;
|
|
1123
|
+
if (!a)
|
|
1125
1124
|
return {
|
|
1126
1125
|
status: "success",
|
|
1127
1126
|
outputMessage: 'Please clarify with summarize item <item id>, summarize item #<title>, or summarize item #"<title with spaces>".'
|
|
1128
1127
|
};
|
|
1129
|
-
await g({ text: `Summarizing item ${
|
|
1130
|
-
const
|
|
1131
|
-
|
|
1132
|
-
const { portal: o, user:
|
|
1133
|
-
if (
|
|
1134
|
-
return await g({ text: "Failed to get item context for summarization", agentName: "analytics" },
|
|
1128
|
+
await g({ text: `Summarizing item ${a}...`, agentName: "analytics" }, e);
|
|
1129
|
+
const n = e?.configurable?.context;
|
|
1130
|
+
x(n);
|
|
1131
|
+
const { portal: o, user: s } = n, { result: i, error: u } = await Wt(s, o, a);
|
|
1132
|
+
if (u || !i)
|
|
1133
|
+
return await g({ text: "Failed to get item context for summarization", agentName: "analytics" }, e), {
|
|
1135
1134
|
status: "success",
|
|
1136
1135
|
outputMessage: "Unable to retrieve item context for summarization."
|
|
1137
1136
|
};
|
|
1138
|
-
const { context:
|
|
1139
|
-
promptText:
|
|
1140
|
-
schema:
|
|
1137
|
+
const { context: c } = i, d = await b({
|
|
1138
|
+
promptText: wa,
|
|
1139
|
+
schema: pa,
|
|
1141
1140
|
modelTier: "default",
|
|
1142
|
-
inputVariables: { context: JSON.stringify(
|
|
1143
|
-
}), { followUpQuestions:
|
|
1144
|
-
latestItemId:
|
|
1141
|
+
inputVariables: { context: JSON.stringify(c) }
|
|
1142
|
+
}), { followUpQuestions: l, summary: m } = d, p = Q(t), f = {
|
|
1143
|
+
latestItemId: a,
|
|
1145
1144
|
memory: {
|
|
1146
|
-
...
|
|
1147
|
-
[
|
|
1145
|
+
...p.memory,
|
|
1146
|
+
[a]: { summary: m, followUpQuestions: l, fullContext: c }
|
|
1148
1147
|
}
|
|
1149
1148
|
};
|
|
1150
|
-
return
|
|
1149
|
+
return l.length && await j({ type: "suggested-prompts", data: { prompts: l } }, e), {
|
|
1151
1150
|
status: "success",
|
|
1152
1151
|
outputMessage: m,
|
|
1153
|
-
sharedStatePatch: { portalItemAnalyticsSummaryMemory: { value:
|
|
1152
|
+
sharedStatePatch: { portalItemAnalyticsSummaryMemory: { value: f } }
|
|
1154
1153
|
};
|
|
1155
|
-
},
|
|
1156
|
-
...
|
|
1154
|
+
}, D = (t, e) => e ?? t, Mt = h.Root({
|
|
1155
|
+
...N(),
|
|
1157
1156
|
// States shared only across nodes in the graph, not between invocations
|
|
1158
|
-
analyticsIntent:
|
|
1159
|
-
reducer:
|
|
1157
|
+
analyticsIntent: h({
|
|
1158
|
+
reducer: D,
|
|
1160
1159
|
default: () => "clarify"
|
|
1161
1160
|
}),
|
|
1162
|
-
analyticsItemId:
|
|
1163
|
-
reducer:
|
|
1161
|
+
analyticsItemId: h({
|
|
1162
|
+
reducer: D,
|
|
1164
1163
|
default: () => null
|
|
1165
1164
|
}),
|
|
1166
|
-
analyticsQuestion:
|
|
1167
|
-
reducer:
|
|
1165
|
+
analyticsQuestion: h({
|
|
1166
|
+
reducer: D,
|
|
1168
1167
|
default: () => ""
|
|
1169
1168
|
})
|
|
1170
|
-
}),
|
|
1169
|
+
}), ba = () => new C(Mt).addNode("detectAnalyticsIntent", ya).addNode("summarizePortalItem", va).addNode("answerAnalyticsFollowUp", ha).addEdge(A, "detectAnalyticsIntent").addConditionalEdges("detectAnalyticsIntent", (e) => e.analyticsIntent === "summarize" ? "summarizePortalItem" : e.analyticsIntent === "followUp" ? "answerAnalyticsFollowUp" : w).addEdge("summarizePortalItem", w).addEdge("answerAnalyticsFollowUp", w), Ia = String.raw`- **portal-item-analytics** - Portal item analytics assistant:
|
|
1171
1170
|
- answers questions about one specific ArcGIS portal item when item context is present
|
|
1172
1171
|
- summarizes item details, metadata, and context grounded in that item
|
|
1173
1172
|
- suggests follow-up prompts grounded in the same item
|
|
1174
1173
|
- use for item-specific requests, not for gallery browsing, featured content, or opening Map Viewer
|
|
1175
|
-
`,
|
|
1174
|
+
`, xa = {
|
|
1176
1175
|
id: "portal-item-analytics",
|
|
1177
1176
|
name: "Portal Item Analytics",
|
|
1178
|
-
description:
|
|
1179
|
-
createGraph:
|
|
1180
|
-
workspace:
|
|
1181
|
-
},
|
|
1182
|
-
|
|
1183
|
-
|
|
1177
|
+
description: Ia,
|
|
1178
|
+
createGraph: ba,
|
|
1179
|
+
workspace: Mt
|
|
1180
|
+
}, Sa = {
|
|
1181
|
+
schemaVersion: "1.0",
|
|
1182
|
+
capabilities: [
|
|
1183
|
+
{
|
|
1184
|
+
id: "my-content",
|
|
1185
|
+
title: "My content",
|
|
1186
|
+
description: "Browse, discover, search, and filter ArcGIS content—including maps, apps, datasets, and other items—that you own or can access.",
|
|
1187
|
+
hints: ["view my content", "show my content", "my content"],
|
|
1188
|
+
platforms: ["online", "enterprise"],
|
|
1189
|
+
resolutions: {
|
|
1190
|
+
navigate: {
|
|
1191
|
+
routeKey: "content"
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
},
|
|
1195
|
+
{
|
|
1196
|
+
id: "create-feature-layer",
|
|
1197
|
+
title: "Create feature layer",
|
|
1198
|
+
description: "Generate an editable feature layer by copying fields from templates or existing layers.",
|
|
1199
|
+
hints: ["add a feature layer", "make a feature layer", "generate a feature layer"],
|
|
1200
|
+
platforms: ["online", "enterprise"],
|
|
1201
|
+
resolutions: {
|
|
1202
|
+
navigate: {
|
|
1203
|
+
routeKey: "content"
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
},
|
|
1207
|
+
{
|
|
1208
|
+
id: "create-folder",
|
|
1209
|
+
title: "Create folder",
|
|
1210
|
+
description: "Create a new folder in your ArcGIS content to organize your items.",
|
|
1211
|
+
hints: ["create a folder", "make a folder", "set up a folder", "new folder"],
|
|
1212
|
+
platforms: ["online", "enterprise"],
|
|
1213
|
+
resolutions: {
|
|
1214
|
+
navigate: {
|
|
1215
|
+
routeKey: "content"
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
]
|
|
1220
|
+
}, Ma = {
|
|
1221
|
+
schemaVersion: "1.0",
|
|
1222
|
+
capabilities: [
|
|
1223
|
+
{
|
|
1224
|
+
id: "my groups",
|
|
1225
|
+
title: "My groups",
|
|
1226
|
+
description: "Browse, discover, search, and filter ArcGIS content collections—including maps, apps, datasets, and other items—that you own, belong to, or can access.",
|
|
1227
|
+
hints: ["view my groups", "show my groups", "my groups"],
|
|
1228
|
+
platforms: ["online", "enterprise"],
|
|
1229
|
+
resolutions: {
|
|
1230
|
+
navigate: {
|
|
1231
|
+
routeKey: "groups"
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
},
|
|
1235
|
+
{
|
|
1236
|
+
id: "create-group",
|
|
1237
|
+
title: "Create group",
|
|
1238
|
+
description: "Create a new ArcGIS Portal group owned by the signed-in user.",
|
|
1239
|
+
hints: ["create a group", "make a group", "set up a group", "new group"],
|
|
1240
|
+
platforms: ["online", "enterprise"],
|
|
1241
|
+
resolutions: {
|
|
1242
|
+
navigate: {
|
|
1243
|
+
routeKey: "groups"
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
},
|
|
1247
|
+
{
|
|
1248
|
+
id: "featured-groups",
|
|
1249
|
+
title: "Featured groups",
|
|
1250
|
+
description: "Browse, discover, search, and filter ArcGIS content collections—including maps, apps, datasets, and other items—that organization administrators choose to highlight in ArcGIS.",
|
|
1251
|
+
hints: ["view featured groups", "show featured groups", "highlighted groups", "top groups"],
|
|
1252
|
+
platforms: ["online", "enterprise"],
|
|
1253
|
+
resolutions: {
|
|
1254
|
+
navigate: {
|
|
1255
|
+
routeKey: "groups",
|
|
1256
|
+
hash: "featured"
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
},
|
|
1260
|
+
{
|
|
1261
|
+
id: "organization-groups",
|
|
1262
|
+
title: "Organization groups",
|
|
1263
|
+
description: "Browse, discover, search, and filter ArcGIS content collections—including maps, apps, datasets, and other items—that are specific to your organization in ArcGIS.",
|
|
1264
|
+
hints: ["view organization groups", "show organization groups"],
|
|
1265
|
+
platforms: ["online", "enterprise"],
|
|
1266
|
+
resolutions: {
|
|
1267
|
+
navigate: {
|
|
1268
|
+
routeKey: "groups",
|
|
1269
|
+
hash: "organization"
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
]
|
|
1274
|
+
}, Ta = {
|
|
1275
|
+
schemaVersion: "1.0",
|
|
1276
|
+
capabilities: [
|
|
1277
|
+
{
|
|
1278
|
+
id: "org-config-mfa",
|
|
1279
|
+
title: "Multifactor Authentication (MFA)",
|
|
1280
|
+
description: "Configure organization-level multifactor authentication (MFA) settings. Administrators can enable MFA for ArcGIS logins, allow recovery codes for members, view MFA adoption status, enforce MFA requirements for all members, manage the MFA exemption list, and designate administrators who can troubleshoot MFA issues.",
|
|
1281
|
+
hints: ["config MFA", "set up MFA"],
|
|
1282
|
+
platforms: ["online", "enterprise"],
|
|
1283
|
+
resolutions: {
|
|
1284
|
+
navigate: {
|
|
1285
|
+
routeKey: "organization",
|
|
1286
|
+
queryParams: {
|
|
1287
|
+
tab: "security"
|
|
1288
|
+
},
|
|
1289
|
+
hash: "settings"
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
]
|
|
1294
|
+
}, Ga = {
|
|
1295
|
+
"contentRouteRegistry.ts": Sa,
|
|
1296
|
+
"groupsRouteRegistry.ts": Ma,
|
|
1297
|
+
"orgSettingsRouteRegistry.ts": Ta
|
|
1298
|
+
};
|
|
1299
|
+
function Ca(t) {
|
|
1300
|
+
const e = [], a = /* @__PURE__ */ new Set();
|
|
1301
|
+
for (const [n, o] of Object.entries(t))
|
|
1302
|
+
for (const s of o.capabilities) {
|
|
1303
|
+
if (a.has(s.id))
|
|
1304
|
+
throw new Error(`${n}: duplicate capability id "${s.id}" across registries`);
|
|
1305
|
+
a.add(s.id), e.push(s);
|
|
1306
|
+
}
|
|
1307
|
+
return e;
|
|
1308
|
+
}
|
|
1309
|
+
let at;
|
|
1310
|
+
function T() {
|
|
1311
|
+
return at ??= Ca(Ga), at;
|
|
1312
|
+
}
|
|
1313
|
+
const Aa = /^(?:take me to|navigate to|go to|show me|open)\s+(?:the\s+)?/u;
|
|
1314
|
+
function q(t) {
|
|
1315
|
+
return t.toLowerCase().replace(/[^a-z0-9]+/gu, " ").trim().replace(Aa, "").trim();
|
|
1316
|
+
}
|
|
1317
|
+
const Na = r.object({
|
|
1318
|
+
capabilityIds: r.array(r.string()).default([]),
|
|
1319
|
+
confidence: r.number().min(0).max(1).default(0),
|
|
1320
|
+
reason: r.string().default("")
|
|
1321
|
+
}), nt = 0.8, Pa = String.raw`You select Portal navigation capabilities for a user's request.
|
|
1322
|
+
|
|
1323
|
+
Select only capability IDs from the supplied candidates. Return an empty array when none fit.
|
|
1324
|
+
A named surface is required: do not select a capability on another Portal surface.
|
|
1325
|
+
Retrieval scores are hints only, not ground truth.
|
|
1326
|
+
|
|
1327
|
+
User request:
|
|
1328
|
+
{userRequest}
|
|
1329
|
+
|
|
1330
|
+
Candidates:
|
|
1331
|
+
{candidates}`, ka = async (t, e) => {
|
|
1332
|
+
if (t.outputMessage || t.targets.length === 0)
|
|
1333
|
+
return {};
|
|
1334
|
+
const a = v(t.agentExecutionContext.messages).trim(), n = qa(a, t);
|
|
1335
|
+
if (n.length === 1)
|
|
1336
|
+
return console.info("[arcgis-portal-ai-assistant] navigation capability selection:", {
|
|
1337
|
+
method: "exact-match",
|
|
1338
|
+
request: a,
|
|
1339
|
+
selectedCapabilityIds: n
|
|
1340
|
+
}), { chosenCapabilityIds: n };
|
|
1341
|
+
await g({ text: "Choosing a navigation destination...", agentName: "navigation" }, e);
|
|
1342
|
+
const o = JSON.stringify(
|
|
1343
|
+
t.targets.map(({ capability: s, keywordScore: i, semanticScore: u }) => ({
|
|
1344
|
+
id: s.id,
|
|
1345
|
+
title: s.title,
|
|
1346
|
+
description: s.description,
|
|
1347
|
+
route: s.resolutions.navigate,
|
|
1348
|
+
keywordScore: i,
|
|
1349
|
+
semanticScore: u
|
|
1350
|
+
}))
|
|
1351
|
+
);
|
|
1352
|
+
try {
|
|
1353
|
+
const s = await b({
|
|
1354
|
+
promptText: Pa,
|
|
1355
|
+
schema: Na,
|
|
1356
|
+
modelTier: "fast",
|
|
1357
|
+
inputVariables: { candidates: o, userRequest: a }
|
|
1358
|
+
}), i = new Set(t.targets.map(({ capability: c }) => c.id)), u = s.capabilityIds.filter((c) => i.has(c));
|
|
1359
|
+
return console.info("[arcgis-portal-ai-assistant] navigation capability selection:", {
|
|
1360
|
+
confidence: s.confidence,
|
|
1361
|
+
method: "structured-model",
|
|
1362
|
+
reason: s.reason,
|
|
1363
|
+
request: a,
|
|
1364
|
+
selectedCapabilityIds: u
|
|
1365
|
+
}), s.confidence < nt ? {
|
|
1366
|
+
chosenCapabilityIds: [],
|
|
1367
|
+
status: "failed",
|
|
1368
|
+
summary: `Navigation selection confidence ${s.confidence} is below the required ${nt}; defer to the Portal Doc Assistant.`
|
|
1369
|
+
} : { chosenCapabilityIds: u };
|
|
1370
|
+
} catch {
|
|
1371
|
+
return console.info("[arcgis-portal-ai-assistant] navigation capability selection:", {
|
|
1372
|
+
method: "structured-model-unavailable",
|
|
1373
|
+
request: a,
|
|
1374
|
+
selectedCapabilityIds: []
|
|
1375
|
+
}), { chosenCapabilityIds: [] };
|
|
1376
|
+
}
|
|
1377
|
+
};
|
|
1378
|
+
function qa(t, e) {
|
|
1379
|
+
const a = q(t);
|
|
1380
|
+
return e.targets.filter(
|
|
1381
|
+
({ capability: n }) => [n.title, ...n.hints].some(
|
|
1382
|
+
(o) => q(o) === a
|
|
1383
|
+
)
|
|
1384
|
+
).map(({ capability: n }) => n.id);
|
|
1385
|
+
}
|
|
1386
|
+
function za(t) {
|
|
1387
|
+
return T().flatMap((e) => {
|
|
1388
|
+
const a = $a(e);
|
|
1389
|
+
return a && Ra(a, t) ? [{ capability: e, target: a }] : [];
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
function Ea(t, e) {
|
|
1393
|
+
return za(e).find(({ capability: a }) => a.id === t);
|
|
1394
|
+
}
|
|
1395
|
+
function $a(t) {
|
|
1396
|
+
const { hash: e, queryParams: a, routeKey: n } = t.resolutions.navigate;
|
|
1397
|
+
switch (n) {
|
|
1398
|
+
case "content":
|
|
1399
|
+
switch (t.id) {
|
|
1400
|
+
case "my-content":
|
|
1401
|
+
return { destinationType: "portal-content", t9nKey: "myContent" };
|
|
1402
|
+
case "create-feature-layer":
|
|
1403
|
+
return { destinationType: "portal-content", t9nKey: "createFeatureLayer" };
|
|
1404
|
+
case "create-folder":
|
|
1405
|
+
return { destinationType: "portal-content", t9nKey: "createFolder" };
|
|
1406
|
+
default:
|
|
1407
|
+
return { destinationType: "portal-content" };
|
|
1408
|
+
}
|
|
1409
|
+
case "groups":
|
|
1410
|
+
if (e === "featured")
|
|
1411
|
+
return { destinationType: "portal-groups", hash: "featured", t9nKey: "featuredGroups" };
|
|
1412
|
+
if (e === "organization")
|
|
1413
|
+
return { destinationType: "portal-groups", hash: "organization", t9nKey: "organizationGroups" };
|
|
1414
|
+
switch (t.id) {
|
|
1415
|
+
case "my groups":
|
|
1416
|
+
return { destinationType: "portal-groups", hash: "my", t9nKey: "myGroups" };
|
|
1417
|
+
case "create-group":
|
|
1418
|
+
return { destinationType: "portal-groups", t9nKey: "createGroup" };
|
|
1419
|
+
default:
|
|
1420
|
+
return { destinationType: "portal-groups" };
|
|
1421
|
+
}
|
|
1422
|
+
case "organization":
|
|
1423
|
+
return a?.tab !== "security" ? void 0 : t.id === "org-config-mfa" ? { destinationType: "portal-org", hash: "settings", t9nKey: "configureMultifactorAuthentication" } : { destinationType: "portal-org", hash: "settings" };
|
|
1424
|
+
default:
|
|
1425
|
+
return;
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
function Ra(t, e) {
|
|
1429
|
+
return !e || !!e[t.destinationType];
|
|
1430
|
+
}
|
|
1431
|
+
const Da = async (t, e) => {
|
|
1432
|
+
if (t.outputMessage || t.status === "failed")
|
|
1433
|
+
return {};
|
|
1434
|
+
const a = t.targets.find(({ capability: o }) => t.chosenCapabilityIds.includes(o.id)) ?? t.targets[0];
|
|
1435
|
+
if (!a)
|
|
1436
|
+
return {
|
|
1437
|
+
outputMessage: "I couldn't find a matching Portal page. Try asking to open your content, groups, or organization settings.",
|
|
1438
|
+
sharedStatePatch: { navLastAnsweredRequest: { value: U(t) } },
|
|
1439
|
+
status: "success",
|
|
1440
|
+
summary: "Navigation could not find a matching capability; route another agent if appropriate."
|
|
1441
|
+
};
|
|
1442
|
+
const n = Ea(a.capability.id);
|
|
1443
|
+
return n ? (await g({ text: "Preparing navigation...", agentName: "navigation" }, e), await E(n.target, e), {
|
|
1444
|
+
outputMessage: t.chosenCapabilityIds.length ? `Click the button below to open ${a.capability.title}.` : `The closest place to start is ${a.capability.title}. Click the button below to open it.`,
|
|
1445
|
+
status: "success",
|
|
1446
|
+
summary: `Navigation suggested ${a.capability.id}${t.retrievalDegraded ? " using keyword-only retrieval" : ""}.`,
|
|
1447
|
+
sharedStatePatch: { navLastAnsweredRequest: { value: U(t) } }
|
|
1448
|
+
}) : (console.warn(`Navigation capability ${a.capability.id} was not found in the resolver.`), {
|
|
1449
|
+
outputMessage: "I found a possible destination, but couldn't resolve a valid Portal navigation target. Try asking to open your content, groups, or organization settings.",
|
|
1450
|
+
status: "success",
|
|
1451
|
+
summary: `Navigation resolver could not map ${a.capability.id}.`,
|
|
1452
|
+
sharedStatePatch: { navLastAnsweredRequest: { value: U(t) } }
|
|
1453
|
+
});
|
|
1454
|
+
};
|
|
1455
|
+
function U(t) {
|
|
1456
|
+
return v(t.agentExecutionContext.messages) || t.agentExecutionContext.userRequest;
|
|
1457
|
+
}
|
|
1458
|
+
async function Tt(t) {
|
|
1459
|
+
return t.length === 0 ? [] : (await Zt.getDefault().load(), await Ft(t));
|
|
1460
|
+
}
|
|
1461
|
+
const Ua = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1462
|
+
__proto__: null,
|
|
1463
|
+
generateEmbeddings: Tt
|
|
1464
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
1465
|
+
function Fa(t) {
|
|
1466
|
+
const e = [], a = `${t.title}. ${t.description}`;
|
|
1467
|
+
a.trim().length > 0 && e.push({ field: "summary", text: a });
|
|
1468
|
+
const n = t.hints;
|
|
1469
|
+
if (Array.isArray(n))
|
|
1470
|
+
for (const o of n)
|
|
1471
|
+
typeof o == "string" && o.trim().length > 0 && e.push({ field: "hint", text: o });
|
|
1472
|
+
return e;
|
|
1473
|
+
}
|
|
1474
|
+
let F, Gt;
|
|
1475
|
+
async function Oa(t = {}) {
|
|
1476
|
+
return F ??= Va(t.embed ?? ja).then((e) => (Gt = e, e)).catch((e) => {
|
|
1477
|
+
throw F = void 0, e;
|
|
1478
|
+
}), await F;
|
|
1479
|
+
}
|
|
1480
|
+
function Ka() {
|
|
1481
|
+
return Gt;
|
|
1482
|
+
}
|
|
1483
|
+
async function Va(t) {
|
|
1484
|
+
const e = La(), a = await t(e.map((n) => n.text));
|
|
1485
|
+
if (a.length !== e.length)
|
|
1486
|
+
throw new Error(`Expected ${e.length} vectors, got ${a.length}`);
|
|
1487
|
+
return e.map((n, o) => ({
|
|
1488
|
+
...n,
|
|
1489
|
+
vector: a[o]
|
|
1490
|
+
}));
|
|
1491
|
+
}
|
|
1492
|
+
async function ja(t) {
|
|
1493
|
+
const { generateEmbeddings: e } = await Promise.resolve().then(() => Ua);
|
|
1494
|
+
return await e(t);
|
|
1495
|
+
}
|
|
1496
|
+
function La() {
|
|
1497
|
+
return T().flatMap(
|
|
1498
|
+
(t) => Fa(t).map(({ field: e, text: a }) => ({
|
|
1499
|
+
capabilityId: t.id,
|
|
1500
|
+
field: e,
|
|
1501
|
+
text: a
|
|
1502
|
+
}))
|
|
1503
|
+
);
|
|
1504
|
+
}
|
|
1505
|
+
const ot = 1.2, st = 0.75, Ba = 60, Qa = 0.65, O = {
|
|
1506
|
+
description: 1,
|
|
1507
|
+
hint: 2,
|
|
1508
|
+
title: 3
|
|
1509
|
+
};
|
|
1510
|
+
let rt;
|
|
1511
|
+
async function Wa(t, e = {}) {
|
|
1512
|
+
const a = Ha(Ct(t));
|
|
1513
|
+
let n = [], o = !1, s;
|
|
1514
|
+
if (t.trim()) {
|
|
1515
|
+
const i = e.loadEmbeddings, u = Ka();
|
|
1516
|
+
if (!i && !u)
|
|
1517
|
+
o = !0, s = "Capability embeddings are still loading.";
|
|
1518
|
+
else
|
|
1519
|
+
try {
|
|
1520
|
+
if (i) {
|
|
1521
|
+
const [c, d] = await Promise.all([
|
|
1522
|
+
(e.embedQuery ?? ut)(t),
|
|
1523
|
+
i()
|
|
1524
|
+
]);
|
|
1525
|
+
n = it(c, d);
|
|
1526
|
+
} else if (u) {
|
|
1527
|
+
const c = await (e.embedQuery ?? ut)(t);
|
|
1528
|
+
n = it(c, u);
|
|
1529
|
+
}
|
|
1530
|
+
} catch {
|
|
1531
|
+
o = !0, s = "Semantic search is unavailable.";
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
return {
|
|
1535
|
+
degraded: o,
|
|
1536
|
+
...s ? { degradedReason: s } : {},
|
|
1537
|
+
// RRF combines ranks rather than raw scores because BM25 and cosine
|
|
1538
|
+
// similarity are on different scales.
|
|
1539
|
+
matches: Za(a, n, e.topN ?? 5)
|
|
1540
|
+
};
|
|
1541
|
+
}
|
|
1542
|
+
function Ja() {
|
|
1543
|
+
return rt ??= _a(T()), rt;
|
|
1544
|
+
}
|
|
1545
|
+
function _a(t) {
|
|
1546
|
+
const e = /* @__PURE__ */ new Map(), a = t.map((n) => {
|
|
1547
|
+
const o = /* @__PURE__ */ new Map();
|
|
1548
|
+
K(o, n.title, O.title), K(o, n.description, O.description);
|
|
1549
|
+
for (const s of n.hints)
|
|
1550
|
+
K(o, s, O.hint);
|
|
1551
|
+
for (const s of o.keys())
|
|
1552
|
+
e.set(s, (e.get(s) ?? 0) + 1);
|
|
1553
|
+
return {
|
|
1554
|
+
capability: n,
|
|
1555
|
+
length: Ya(o),
|
|
1556
|
+
termFrequencies: o
|
|
1557
|
+
};
|
|
1558
|
+
});
|
|
1559
|
+
return {
|
|
1560
|
+
averageDocumentLength: a.length ? a.reduce((n, o) => n + o.length, 0) / a.length : 0,
|
|
1561
|
+
documentFrequency: e,
|
|
1562
|
+
documents: a
|
|
1563
|
+
};
|
|
1564
|
+
}
|
|
1565
|
+
function K(t, e, a) {
|
|
1566
|
+
for (const n of Ct(e))
|
|
1567
|
+
t.set(n, (t.get(n) ?? 0) + a);
|
|
1568
|
+
}
|
|
1569
|
+
function Ya(t) {
|
|
1570
|
+
return [...t.values()].reduce((e, a) => e + a, 0);
|
|
1571
|
+
}
|
|
1572
|
+
function Ct(t) {
|
|
1573
|
+
return t.toLowerCase().split(/[^a-z0-9]+/u).filter(Boolean);
|
|
1574
|
+
}
|
|
1575
|
+
function Ha(t) {
|
|
1576
|
+
const e = Ja(), a = new Set(t), n = e.documents.length;
|
|
1577
|
+
return e.documents.map(({ capability: o, length: s, termFrequencies: i }) => {
|
|
1578
|
+
let u = 0;
|
|
1579
|
+
for (const c of a) {
|
|
1580
|
+
const d = i.get(c), l = e.documentFrequency.get(c);
|
|
1581
|
+
if (!d || !l)
|
|
1582
|
+
continue;
|
|
1583
|
+
const m = Math.log(1 + (n - l + 0.5) / (l + 0.5)), p = ot * (1 - st + st * (s / e.averageDocumentLength));
|
|
1584
|
+
u += m * (d * (ot + 1) / (d + p));
|
|
1585
|
+
}
|
|
1586
|
+
return { capability: o, score: u };
|
|
1587
|
+
}).filter(({ score: o }) => o > 0).sort(At);
|
|
1588
|
+
}
|
|
1589
|
+
function it(t, e) {
|
|
1590
|
+
const a = /* @__PURE__ */ new Map();
|
|
1591
|
+
for (const o of e) {
|
|
1592
|
+
const s = Xa(t, o.vector);
|
|
1593
|
+
if (s === void 0)
|
|
1594
|
+
continue;
|
|
1595
|
+
const i = a.get(o.capabilityId);
|
|
1596
|
+
(i === void 0 || s > i) && a.set(o.capabilityId, s);
|
|
1597
|
+
}
|
|
1598
|
+
const n = new Map(T().map((o) => [o.id, o]));
|
|
1599
|
+
return [...a.entries()].flatMap(([o, s]) => {
|
|
1600
|
+
const i = n.get(o);
|
|
1601
|
+
return i && s >= Qa ? [{ capability: i, score: s }] : [];
|
|
1602
|
+
}).sort(At);
|
|
1603
|
+
}
|
|
1604
|
+
function Xa(t, e) {
|
|
1605
|
+
if (t.length === 0 || t.length !== e.length)
|
|
1184
1606
|
return;
|
|
1185
|
-
|
|
1186
|
-
|
|
1607
|
+
let a = 0, n = 0, o = 0;
|
|
1608
|
+
for (let i = 0; i < t.length; i += 1)
|
|
1609
|
+
a += t[i] * e[i], n += t[i] ** 2, o += e[i] ** 2;
|
|
1610
|
+
const s = Math.sqrt(n) * Math.sqrt(o);
|
|
1611
|
+
return s === 0 ? void 0 : a / s;
|
|
1612
|
+
}
|
|
1613
|
+
async function ut(t) {
|
|
1614
|
+
const [e] = await Tt([t]);
|
|
1615
|
+
if (!e)
|
|
1616
|
+
throw new Error("Expected one query embedding.");
|
|
1617
|
+
return e;
|
|
1618
|
+
}
|
|
1619
|
+
function Za(t, e, a) {
|
|
1620
|
+
const n = /* @__PURE__ */ new Map();
|
|
1621
|
+
return ct(n, t, "keyword"), ct(n, e, "semantic"), [...n.values()].sort((o, s) => s.score !== o.score ? s.score - o.score : (s.semanticScore ?? 0) !== (o.semanticScore ?? 0) ? (s.semanticScore ?? 0) - (o.semanticScore ?? 0) : (s.keywordScore ?? 0) !== (o.keywordScore ?? 0) ? (s.keywordScore ?? 0) - (o.keywordScore ?? 0) : o.capability.id.localeCompare(s.capability.id)).slice(0, Math.max(0, a));
|
|
1622
|
+
}
|
|
1623
|
+
function ct(t, e, a) {
|
|
1624
|
+
for (const [n, { capability: o, score: s }] of e.entries()) {
|
|
1625
|
+
const i = n + 1, u = t.get(o.id) ?? { capability: o, score: 0 };
|
|
1626
|
+
u.score += 1 / (Ba + i), a === "keyword" ? (u.keywordRank = i, u.keywordScore = s) : (u.semanticRank = i, u.semanticScore = s), t.set(o.id, u);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
function At(t, e) {
|
|
1630
|
+
return e.score - t.score || t.capability.id.localeCompare(e.capability.id);
|
|
1631
|
+
}
|
|
1632
|
+
const tn = async (t, e) => {
|
|
1633
|
+
await g({ text: "Finding a place to navigate...", agentName: "navigation" }, e);
|
|
1634
|
+
const a = v(t.agentExecutionContext.messages).trim();
|
|
1635
|
+
try {
|
|
1636
|
+
const n = await Wa(a, { topN: 5 });
|
|
1637
|
+
return console.table(
|
|
1638
|
+
n.matches.map(({ capability: o, keywordRank: s, keywordScore: i, semanticRank: u, semanticScore: c, score: d }) => ({
|
|
1639
|
+
capability: o.title,
|
|
1640
|
+
fusedScore: d,
|
|
1641
|
+
keywordRank: s,
|
|
1642
|
+
keywordScore: i,
|
|
1643
|
+
semanticRank: u,
|
|
1644
|
+
semanticScore: c
|
|
1645
|
+
}))
|
|
1646
|
+
), n.degradedReason && console.info("[arcgis-portal-ai-assistant] navigation semantic search:", n.degradedReason), {
|
|
1647
|
+
chosenCapabilityIds: [],
|
|
1648
|
+
retrievalDegraded: n.degradedReason ?? "",
|
|
1649
|
+
targets: en(a, n.matches)
|
|
1650
|
+
};
|
|
1651
|
+
} catch {
|
|
1652
|
+
return {
|
|
1653
|
+
chosenCapabilityIds: [],
|
|
1654
|
+
outputMessage: "I couldn't look up a Portal page right now. Please try again.",
|
|
1655
|
+
status: "failed",
|
|
1656
|
+
targets: []
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1659
|
+
};
|
|
1660
|
+
function en(t, e) {
|
|
1661
|
+
const a = q(t), n = e.filter(
|
|
1662
|
+
({ capability: s }) => [s.title, ...s.hints].some(
|
|
1663
|
+
(i) => q(i) === a
|
|
1664
|
+
)
|
|
1665
|
+
);
|
|
1666
|
+
if (n.length !== 1)
|
|
1667
|
+
return e;
|
|
1668
|
+
const [o] = n;
|
|
1669
|
+
return [o, ...e.filter((s) => s !== o)];
|
|
1670
|
+
}
|
|
1671
|
+
const V = (t, e) => e ?? t, Nt = h.Root({
|
|
1672
|
+
...N(),
|
|
1673
|
+
chosenCapabilityIds: h({ reducer: V, default: () => [] }),
|
|
1674
|
+
// Empty when hybrid keyword-and-semantic retrieval succeeds; otherwise
|
|
1675
|
+
// contains the semantic-search failure reason for response diagnostics.
|
|
1676
|
+
retrievalDegraded: h({ reducer: V, default: () => "" }),
|
|
1677
|
+
targets: h({ reducer: V, default: () => [] })
|
|
1678
|
+
}), an = () => new C(Nt).addNode("retrieveNavigationTargets", tn).addNode("chooseNavigationTargets", ka).addNode("respondWithNavigation", Da).addEdge(A, "retrieveNavigationTargets").addEdge("retrieveNavigationTargets", "chooseNavigationTargets").addEdge("chooseNavigationTargets", "respondWithNavigation").addEdge("respondWithNavigation", w), nn = T().map(({ hints: t, title: e }) => t[0] ?? e).join(", "), on = String.raw`- **portal-navigation** - Portal page navigation assistant:
|
|
1679
|
+
- routes requests to open, show, or navigate to a Portal page, including creation-flow pages
|
|
1680
|
+
- falls back to the closest Portal page where a workflow starts when another agent cannot perform the action
|
|
1681
|
+
- handles short navigation follow-ups after asking the user to open a page
|
|
1682
|
+
- capability examples: ${nn}
|
|
1683
|
+
- do not use for general "how do I" questions unless the user explicitly asks to reach a page
|
|
1684
|
+
`, sn = {
|
|
1685
|
+
id: "navigation",
|
|
1686
|
+
name: "Portal Navigation",
|
|
1687
|
+
description: on,
|
|
1688
|
+
createGraph: an,
|
|
1689
|
+
workspace: Nt
|
|
1690
|
+
}, rn = Rt`: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)}`;
|
|
1691
|
+
function un(t, e) {
|
|
1692
|
+
if (!e)
|
|
1693
|
+
return;
|
|
1694
|
+
const { destinationType: a } = t;
|
|
1695
|
+
switch (a) {
|
|
1187
1696
|
case "portal-content":
|
|
1188
|
-
|
|
1189
|
-
case "portal-
|
|
1190
|
-
|
|
1191
|
-
case "portal-
|
|
1697
|
+
return e[a]?.(t.hash);
|
|
1698
|
+
case "portal-groups":
|
|
1699
|
+
return e[a]?.(t.hash);
|
|
1700
|
+
case "portal-org":
|
|
1701
|
+
return e[a]?.(t.hash);
|
|
1192
1702
|
case "portal-gallery":
|
|
1703
|
+
return e[a];
|
|
1704
|
+
case "portal-map-viewer":
|
|
1705
|
+
case "portal-notebooks":
|
|
1706
|
+
case "portal-scene-viewer":
|
|
1707
|
+
return e[a];
|
|
1708
|
+
case "portal-item":
|
|
1709
|
+
return e[a]?.(t.itemId);
|
|
1710
|
+
case "portal-group":
|
|
1711
|
+
return e[a]?.(t.groupId);
|
|
1712
|
+
default:
|
|
1713
|
+
return z(a);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
function cn(t) {
|
|
1717
|
+
const e = Ie.safeParse(t);
|
|
1718
|
+
return e.success ? e.data : void 0;
|
|
1719
|
+
}
|
|
1720
|
+
const ln = { myContent: "My content", createFeatureLayer: "Create feature layer", createFolder: "Create folder", myGroups: "My groups", createGroup: "Create group", featuredGroups: "Featured groups", organizationGroups: "Organization groups", configureMultifactorAuthentication: "Configure multifactor authentication" }, Pt = {
|
|
1721
|
+
navigationTargets: ln
|
|
1722
|
+
};
|
|
1723
|
+
function dn(t, e) {
|
|
1724
|
+
const a = lt(t.t9nKey, e.navigationTargets) ?? lt(t.t9nKey, Pt.navigationTargets);
|
|
1725
|
+
if (a)
|
|
1726
|
+
return a;
|
|
1727
|
+
const n = e.navigation;
|
|
1728
|
+
switch (t.destinationType) {
|
|
1729
|
+
case "portal-content":
|
|
1730
|
+
switch (t.hash) {
|
|
1731
|
+
case "favorites":
|
|
1732
|
+
return n.openContentFavorites;
|
|
1733
|
+
case "group":
|
|
1734
|
+
return n.openContentGroup;
|
|
1735
|
+
case "living-atlas":
|
|
1736
|
+
return n.openContentLivingAtlas;
|
|
1737
|
+
case "org":
|
|
1738
|
+
return n.openContentOrganization;
|
|
1739
|
+
default:
|
|
1740
|
+
return n.openContent;
|
|
1741
|
+
}
|
|
1742
|
+
case "portal-gallery":
|
|
1743
|
+
return n.openGallery;
|
|
1193
1744
|
case "portal-groups":
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1745
|
+
switch (t.hash) {
|
|
1746
|
+
case "featured":
|
|
1747
|
+
return n.openGroupsFeatured;
|
|
1748
|
+
case "my":
|
|
1749
|
+
return n.openGroupsMy;
|
|
1750
|
+
case "organization":
|
|
1751
|
+
return n.openGroupsOrganization;
|
|
1752
|
+
default:
|
|
1753
|
+
return n.openGroups;
|
|
1754
|
+
}
|
|
1197
1755
|
case "portal-map-viewer":
|
|
1756
|
+
return n.openMapViewer;
|
|
1198
1757
|
case "portal-notebooks":
|
|
1758
|
+
return n.openNotebooks;
|
|
1199
1759
|
case "portal-scene-viewer":
|
|
1200
|
-
|
|
1201
|
-
|
|
1760
|
+
return n.openSceneViewer;
|
|
1761
|
+
case "portal-org":
|
|
1762
|
+
return n.openOrgSettings;
|
|
1202
1763
|
case "portal-item":
|
|
1203
|
-
return
|
|
1764
|
+
return n.openItem;
|
|
1204
1765
|
case "portal-group":
|
|
1205
|
-
return
|
|
1766
|
+
return n.openGroup;
|
|
1206
1767
|
default:
|
|
1207
|
-
return
|
|
1768
|
+
return z(t);
|
|
1208
1769
|
}
|
|
1209
1770
|
}
|
|
1210
|
-
function
|
|
1211
|
-
|
|
1212
|
-
|
|
1771
|
+
function lt(t, e) {
|
|
1772
|
+
if (!(!t || !e || !pn(t)))
|
|
1773
|
+
return e[t];
|
|
1774
|
+
}
|
|
1775
|
+
function pn(t) {
|
|
1776
|
+
return t in Pt.navigationTargets;
|
|
1213
1777
|
}
|
|
1214
|
-
class
|
|
1778
|
+
class mn extends Et {
|
|
1215
1779
|
constructor() {
|
|
1216
|
-
super(
|
|
1217
|
-
const
|
|
1218
|
-
if (!
|
|
1780
|
+
super(), this.t9n = Ut({ blocking: !0 }), this.assistantEl = P(), this.formEl = P(), this.voiceInputEl = P(), this.inputEl = P(), this.navigationSlotElements = /* @__PURE__ */ new Map(), this.handleSlottableRequest = (e) => {
|
|
1781
|
+
const a = e.detail, n = a.data?.block;
|
|
1782
|
+
if (!n)
|
|
1219
1783
|
return;
|
|
1220
|
-
const o = this.getNavigationAction(
|
|
1221
|
-
o && this.upsertNavigationSlotElement(
|
|
1222
|
-
}, this.inputText = "", this.showVoiceInput = !0, this.isListening = !1, this.isVoiceInputDisabled = !1, this.interrupt = null, this.autoDestroyDisabled = !1, this.defaultClosed = !1, this.arcgisPortalNavigationRequest =
|
|
1784
|
+
const o = this.getNavigationAction(n);
|
|
1785
|
+
o && this.upsertNavigationSlotElement(a.slotName, o);
|
|
1786
|
+
}, this.inputText = "", this.showVoiceInput = !0, this.isListening = !1, this.isVoiceInputDisabled = !1, this.interrupt = null, this.autoDestroyDisabled = !1, this.navigationAgentEnabled = !0, this.defaultClosed = !1, this.arcgisPortalNavigationRequest = $t(), T();
|
|
1223
1787
|
}
|
|
1224
1788
|
static {
|
|
1225
|
-
this.properties = { inputText: 16, showVoiceInput: 16, isListening: 16, isVoiceInputDisabled: 16, interrupt: 16, autoDestroyDisabled: 5, portal: 0, user: 0, config: 0, navigationTargetMap: 0, defaultClosed: 5 };
|
|
1789
|
+
this.properties = { inputText: 16, showVoiceInput: 16, isListening: 16, isVoiceInputDisabled: 16, interrupt: 16, autoDestroyDisabled: 5, portal: 0, user: 0, config: 0, navigationTargetMap: 0, navigationAgentEnabled: 5, defaultClosed: 5 };
|
|
1226
1790
|
}
|
|
1227
1791
|
static {
|
|
1228
|
-
this.styles =
|
|
1792
|
+
this.styles = rn;
|
|
1229
1793
|
}
|
|
1230
|
-
|
|
1231
|
-
|
|
1794
|
+
async load() {
|
|
1795
|
+
try {
|
|
1796
|
+
await Oa();
|
|
1797
|
+
} catch (e) {
|
|
1798
|
+
console.warn("[arcgis-portal-ai-assistant] embeddings warm-up failed:", e);
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
getNavigationAction(e) {
|
|
1802
|
+
if (e?.type !== gt)
|
|
1232
1803
|
return;
|
|
1233
|
-
const
|
|
1234
|
-
if (!
|
|
1804
|
+
const a = cn(e.data);
|
|
1805
|
+
if (!a)
|
|
1235
1806
|
return;
|
|
1236
|
-
const
|
|
1237
|
-
if (
|
|
1238
|
-
return { href:
|
|
1807
|
+
const n = un(a, this.navigationTargetMap);
|
|
1808
|
+
if (n)
|
|
1809
|
+
return { href: n, targetDetail: a, label: dn(a, this.t9n) };
|
|
1239
1810
|
}
|
|
1240
|
-
upsertNavigationSlotElement(
|
|
1241
|
-
const
|
|
1242
|
-
if (!
|
|
1811
|
+
upsertNavigationSlotElement(e, a) {
|
|
1812
|
+
const n = this.assistantEl.value;
|
|
1813
|
+
if (!n)
|
|
1243
1814
|
return;
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1815
|
+
const o = `navigation:${e}`;
|
|
1816
|
+
let s = this.navigationSlotElements.get(o);
|
|
1817
|
+
s || (s = document.createElement("div"), s.slot = e, this.navigationSlotElements.set(o, s), n.append(s)), Dt(M`<div><calcite-button class="navigation-button" appearance=outline width=full .href=${a.href} icon-end=launch @click=${(i) => {
|
|
1818
|
+
i.preventDefault(), this.arcgisPortalNavigationRequest.emit({
|
|
1819
|
+
href: a.href,
|
|
1820
|
+
targetDetail: a.targetDetail
|
|
1249
1821
|
});
|
|
1250
|
-
}}>${
|
|
1251
|
-
}
|
|
1252
|
-
getNavigationText(t) {
|
|
1253
|
-
const e = this.t9n.navigation;
|
|
1254
|
-
switch (t) {
|
|
1255
|
-
case "portal-content":
|
|
1256
|
-
return e.openContent;
|
|
1257
|
-
case "portal-content-favorites":
|
|
1258
|
-
return e.openContentFavorites;
|
|
1259
|
-
case "portal-content-group":
|
|
1260
|
-
return e.openContentGroup;
|
|
1261
|
-
case "portal-content-living-atlas":
|
|
1262
|
-
return e.openContentLivingAtlas;
|
|
1263
|
-
case "portal-content-organization":
|
|
1264
|
-
return e.openContentOrganization;
|
|
1265
|
-
case "portal-gallery":
|
|
1266
|
-
return e.openGallery;
|
|
1267
|
-
case "portal-groups":
|
|
1268
|
-
return e.openGroups;
|
|
1269
|
-
case "portal-groups-featured":
|
|
1270
|
-
return e.openGroupsFeatured;
|
|
1271
|
-
case "portal-groups-my":
|
|
1272
|
-
return e.openGroupsMy;
|
|
1273
|
-
case "portal-groups-organization":
|
|
1274
|
-
return e.openGroupsOrganization;
|
|
1275
|
-
case "portal-map-viewer":
|
|
1276
|
-
return e.openMapViewer;
|
|
1277
|
-
case "portal-notebooks":
|
|
1278
|
-
return e.openNotebooks;
|
|
1279
|
-
case "portal-scene-viewer":
|
|
1280
|
-
return e.openSceneViewer;
|
|
1281
|
-
case "portal-settings-security":
|
|
1282
|
-
return e.openOrganizationSettingsSecurity;
|
|
1283
|
-
case "portal-item":
|
|
1284
|
-
return e.openItem;
|
|
1285
|
-
case "portal-group":
|
|
1286
|
-
return e.openGroup;
|
|
1287
|
-
default:
|
|
1288
|
-
return C(t);
|
|
1289
|
-
}
|
|
1822
|
+
}}>${a.label}</calcite-button>${a.description ? M`<div class="navigation-block-description">${a.description}</div>` : null}</div>`, s);
|
|
1290
1823
|
}
|
|
1291
1824
|
render() {
|
|
1292
|
-
const { t9n:
|
|
1293
|
-
return M`<arcgis-assistant log-enabled keep-suggested-prompts .heading=${
|
|
1294
|
-
this.interrupt =
|
|
1825
|
+
const { t9n: e, inputText: a, portal: n, user: o, navigationTargetMap: s, navigationAgentEnabled: i, showVoiceInput: u, isListening: c, isVoiceInputDisabled: d } = this;
|
|
1826
|
+
return M`<arcgis-assistant log-enabled keep-suggested-prompts .heading=${e.heading} .entryMessage=${e.entryMessage} @arcgisSlottableRequest=${this.handleSlottableRequest} @arcgisInterrupt=${({ detail: l }) => {
|
|
1827
|
+
this.interrupt = l;
|
|
1295
1828
|
}} @arcgisInterruptCancel=${() => {
|
|
1296
1829
|
this.interrupt = null;
|
|
1297
1830
|
}} @arcgisInterruptSubmit=${() => {
|
|
1298
1831
|
this.interrupt = null;
|
|
1299
|
-
}} @arcgisPromptSelect=${({ detail:
|
|
1300
|
-
this.inputText =
|
|
1832
|
+
}} @arcgisPromptSelect=${({ detail: l }) => {
|
|
1833
|
+
this.inputText = l.prompt, requestAnimationFrame(() => {
|
|
1301
1834
|
this.inputEl.value?.focusTextArea();
|
|
1302
1835
|
});
|
|
1303
|
-
}} ${
|
|
1304
|
-
|
|
1305
|
-
const
|
|
1306
|
-
|
|
1307
|
-
}} ${
|
|
1308
|
-
|
|
1309
|
-
}} @arcgisUserMentionableTextAreaChange=${({ detail:
|
|
1310
|
-
this.inputText =
|
|
1311
|
-
}} ${
|
|
1836
|
+
}} ${k(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=${(l) => {
|
|
1837
|
+
l.preventDefault();
|
|
1838
|
+
const m = a.trim();
|
|
1839
|
+
m && (this.assistantEl.value?.submitMessage(m), this.inputText = "");
|
|
1840
|
+
}} ${k(this.formEl)}><arcgis-portal-mentionable-text-area .portal=${n} .user=${o} rows=3 .popoverListLabel=${e.mentionEntities} .placeholder=${e.placeholder} .value=${a} @arcgisUserMentionableTextAreaKeyDown=${({ detail: l }) => {
|
|
1841
|
+
l.key === "Enter" && !l.shiftKey && (l.preventDefault(), this.formEl.value?.requestSubmit());
|
|
1842
|
+
}} @arcgisUserMentionableTextAreaChange=${({ detail: l }) => {
|
|
1843
|
+
this.inputText = l ?? "";
|
|
1844
|
+
}} ${k(this.inputEl)}></arcgis-portal-mentionable-text-area><div class="chat-actions"><arcgis-portal-voice-input @arcgisVoiceInputStart=${() => {
|
|
1312
1845
|
this.isListening = !0, this.isVoiceInputDisabled = !1;
|
|
1313
1846
|
}} @arcgisVoiceInputStop=${() => {
|
|
1314
1847
|
this.isListening = !1, this.isVoiceInputDisabled = !1;
|
|
1315
|
-
}} @arcgisVoiceInputError=${(
|
|
1316
|
-
|
|
1317
|
-
}} @arcgisVoiceInputInterimTranscription=${(
|
|
1318
|
-
this.inputText =
|
|
1319
|
-
}} ${
|
|
1848
|
+
}} @arcgisVoiceInputError=${(l) => {
|
|
1849
|
+
l.detail.errorCode === "not-supported" && (this.showVoiceInput = !1);
|
|
1850
|
+
}} @arcgisVoiceInputInterimTranscription=${(l) => {
|
|
1851
|
+
this.inputText = l.detail.text;
|
|
1852
|
+
}} ${k(this.voiceInputEl)}></arcgis-portal-voice-input>${u && M`<calcite-button icon-start=microphone .label=${e.voiceInput} round .disabled=${d} .appearance=${c ? "solid" : "outline-fill"} @click=${async () => {
|
|
1320
1853
|
this.isVoiceInputDisabled = !0;
|
|
1321
|
-
const
|
|
1322
|
-
|
|
1323
|
-
}}></calcite-button>` || ""}<calcite-button type=submit icon-start=send round .disabled=${!
|
|
1324
|
-
this.assistantEl.value?.submitInterrupt(
|
|
1854
|
+
const l = this.voiceInputEl.value;
|
|
1855
|
+
c ? await l?.stopListening() : await l?.startListening();
|
|
1856
|
+
}}></calcite-button>` || ""}<calcite-button type=submit icon-start=send round .disabled=${!a.trim()} .label=${e.send}>${e.send}</calcite-button></div></form><arcgis-assistant-agent .agent=${xa} .context=${{ portal: n, user: o, navigationTargetMap: s }}></arcgis-assistant-agent><arcgis-assistant-agent .agent=${Te} .context=${{ portal: n, user: o, navigationTargetMap: s }}></arcgis-assistant-agent><arcgis-assistant-agent .agent=${Ve} .context=${{ portal: n, user: o, navigationTargetMap: s }}></arcgis-assistant-agent><arcgis-assistant-agent .agent=${la} .context=${{ portal: n, user: o, navigationTargetMap: s }}></arcgis-assistant-agent>${i && M`<arcgis-assistant-agent .agent=${sn} .context=${{ portal: n, user: o, navigationTargetMap: s }}></arcgis-assistant-agent>` || ""}${this.interrupt && M`<arcgis-portal-ai-assistant-interrupt slot=interrupt .type=${this.interrupt.type} .message=${this.interrupt.message} .options=${this.interrupt.options} @arcgisSubmit=${({ detail: l }) => {
|
|
1857
|
+
this.assistantEl.value?.submitInterrupt(l);
|
|
1325
1858
|
}} @arcgisCancel=${() => {
|
|
1326
1859
|
this.assistantEl.value?.cancelInterrupt();
|
|
1327
1860
|
}}></arcgis-portal-ai-assistant-interrupt>` || ""}</arcgis-assistant>`;
|
|
1328
1861
|
}
|
|
1329
1862
|
}
|
|
1330
|
-
|
|
1863
|
+
zt("arcgis-portal-ai-assistant", mn);
|
|
1331
1864
|
export {
|
|
1332
|
-
|
|
1865
|
+
mn as ArcgisPortalAiAssistant
|
|
1333
1866
|
};
|