@esri/hub-web-components 0.0.5
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/LICENSE.md +13 -0
- package/README.md +35 -0
- package/dist/cdn/2NFBUAOJ.js +4 -0
- package/dist/cdn/3ZRJV7VD.js +3 -0
- package/dist/cdn/CADUTR4A.js +4 -0
- package/dist/cdn/E5QHKHGG.js +41 -0
- package/dist/cdn/IDWXUFCL.js +6 -0
- package/dist/cdn/MNXAWZSB.js +9 -0
- package/dist/cdn/YBCM3RPB.js +4 -0
- package/dist/cdn/assets/hub-ai-assistant/t9n/messages.en.json +1 -0
- package/dist/cdn/assets/hub-ai-assistant/t9n/messages.es.json +1 -0
- package/dist/cdn/index.js +4 -0
- package/dist/chunks/chat-action.js +41 -0
- package/dist/chunks/runtime.js +12 -0
- package/dist/components/arcgis-chat-shell/customElement.d.ts +27 -0
- package/dist/components/arcgis-chat-shell/customElement.js +44 -0
- package/dist/components/arcgis-chat-shell/index.d.ts +5 -0
- package/dist/components/arcgis-chat-shell/index.js +5 -0
- package/dist/components/arcgis-chat-ui/components/chat-action/customElement.d.ts +9 -0
- package/dist/components/arcgis-chat-ui/components/chat-action/customElement.js +9 -0
- package/dist/components/arcgis-chat-ui/components/chat-action/index.d.ts +2 -0
- package/dist/components/arcgis-chat-ui/components/chat-action/index.js +2 -0
- package/dist/components/arcgis-chat-ui/components/chat-response/customElement.d.ts +9 -0
- package/dist/components/arcgis-chat-ui/components/chat-response/customElement.js +42 -0
- package/dist/components/arcgis-chat-ui/components/chat-response/index.d.ts +8 -0
- package/dist/components/arcgis-chat-ui/components/chat-response/index.js +8 -0
- package/dist/components/arcgis-chat-ui/components/chat-status/customElement.d.ts +6 -0
- package/dist/components/arcgis-chat-ui/components/chat-status/customElement.js +8 -0
- package/dist/components/arcgis-chat-ui/components/chat-status/index.d.ts +1 -0
- package/dist/components/arcgis-chat-ui/components/chat-status/index.js +1 -0
- package/dist/components/arcgis-chat-ui/customElement.d.ts +58 -0
- package/dist/components/arcgis-chat-ui/customElement.js +127 -0
- package/dist/components/arcgis-chat-ui/index.d.ts +3 -0
- package/dist/components/arcgis-chat-ui/index.js +3 -0
- package/dist/components/arcgis-chat-ui/util/constants.d.ts +4 -0
- package/dist/components/arcgis-chat-ui/util/customElement.d.ts +3 -0
- package/dist/components/arcgis-chat-ui/util/types.d.ts +27 -0
- package/dist/components/arcgis-hub-ai-assistant/customElement.d.ts +90 -0
- package/dist/components/arcgis-hub-ai-assistant/customElement.js +210 -0
- package/dist/components/arcgis-hub-ai-assistant/index.d.ts +9 -0
- package/dist/components/arcgis-hub-ai-assistant/index.js +9 -0
- package/dist/components/arcgis-hub-ai-assistant/util/api.d.ts +25 -0
- package/dist/components/arcgis-hub-ai-assistant/util/customElement.d.ts +18 -0
- package/dist/components/arcgis-hub-ai-assistant/util/customElement.js +33 -0
- package/dist/components/arcgis-hub-ai-assistant/util/framework.d.ts +184 -0
- package/dist/components/arcgis-hub-ai-assistant/util/index.d.ts +1 -0
- package/dist/components/arcgis-hub-ai-assistant/util/index.js +1 -0
- package/dist/components/arcgis-hub-ai-assistant/util/test.d.ts +1387 -0
- package/dist/controllers/useT9n.d.ts +1 -0
- package/dist/docs/api.json +1113 -0
- package/dist/docs/docs.json +1010 -0
- package/dist/docs/vscode.css-custom-data.json +6 -0
- package/dist/docs/vscode.html-custom-data.json +133 -0
- package/dist/docs/web-types.json +413 -0
- package/dist/embed-config.d.ts +18 -0
- package/dist/embed-config.js +24 -0
- package/dist/enums.d.ts +10 -0
- package/dist/index.d.ts +74 -0
- package/dist/index.js +8 -0
- package/dist/loader.d.ts +2 -0
- package/dist/loader.js +13 -0
- package/dist/main.css +1 -0
- package/dist/runtime.d.ts +6 -0
- package/dist/types/components.d.ts +1 -0
- package/dist/types/lumina.d.ts +28 -0
- package/dist/types/preact.d.ts +36 -0
- package/dist/types/react.d.ts +47 -0
- package/dist/types/stencil.d.ts +35 -0
- package/dist/util/configuration.d.ts +16 -0
- package/package.json +99 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { html as c } from "lit-html";
|
|
2
|
+
import { c as h, C as v } from "../../../../chunks/chat-action.js";
|
|
3
|
+
import f from "@arcgis/core/portal/PortalItem.js";
|
|
4
|
+
import g from "@arcgis/core/layers/Layer.js";
|
|
5
|
+
/*! All material copyright Esri, All Rights Reserved, unless otherwise specified.
|
|
6
|
+
See https://js.arcgis.com/0.0/esri/copyright.txt for details.
|
|
7
|
+
v0.0.5 */
|
|
8
|
+
const C = ({ message: t, addDataClick: n, addLocationClick: s }) => {
|
|
9
|
+
function d(i) {
|
|
10
|
+
return c`<calcite-accordion-item heading=Reasoning description="Explanation of the AI Assistant process" icon-start=automation><ol>${i.map((o) => c`<li>Tool: ${o.name}${Object.keys(o.parameters).map((a) => {
|
|
11
|
+
let r = o.parameters[a];
|
|
12
|
+
return a === "sources" && Array.isArray(r) ? r = r.map((e) => e.title).join(", ") : a === "location" && (r = r.name), c`<div>${a}: ${JSON.stringify(r)}</div>`;
|
|
13
|
+
})}</li>`)}</ol></calcite-accordion-item>`;
|
|
14
|
+
}
|
|
15
|
+
function l(i) {
|
|
16
|
+
return c`<calcite-accordion-item description="Content to add to your context" heading=Sources icon-start=information><div class="sources">${i.map((o) => c`<div class="wrapper source">${v({ source: o, domain: "hub.arcgis.com", showOutlinks: !0, addDataClick: () => {
|
|
17
|
+
const a = {
|
|
18
|
+
type: "dataset",
|
|
19
|
+
title: o.title,
|
|
20
|
+
data: { id: o.id }
|
|
21
|
+
};
|
|
22
|
+
n?.(a);
|
|
23
|
+
} })}</div>`)}</div></calcite-accordion-item>`;
|
|
24
|
+
}
|
|
25
|
+
function p(i) {
|
|
26
|
+
return c`<calcite-accordion-item description="See the layers" heading=Map icon-start=map><div>${i.name}</div><arcgis-map .center=${[i.longitude, i.latitude]} .zoom=${i.zoom ?? void 0} basemap=gray-vector @arcgisViewReadyChange=${m}><arcgis-zoom position=top-left></arcgis-zoom><arcgis-expand position=top-right><arcgis-layer-list></arcgis-layer-list></arcgis-expand></arcgis-map><calcite-button round icon-start=extent @click=${() => s?.(i)}>Zoom To Location</calcite-button></calcite-accordion-item>`;
|
|
27
|
+
}
|
|
28
|
+
function m(i) {
|
|
29
|
+
const o = i.target;
|
|
30
|
+
o.map && t.sources?.length && t.sources.forEach((a) => {
|
|
31
|
+
const r = new f({ id: a.id });
|
|
32
|
+
g.fromPortalItem({ portalItem: r }).then((e) => {
|
|
33
|
+
o.map && o.map.add(e);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const u = t.sources?.length ?? t.tools?.length ?? !!t.location;
|
|
38
|
+
return c`<div class=${`message author-${t.author}`}><div class="response"><div class="text" .innerHTML=${h(t.text) ?? ""}></div>${u && c`<div class="actions"><link rel=stylesheet href=https://js.arcgis.com/4.33/@arcgis/core/assets/esri/themes/light/main.css><calcite-accordion>${t.location && p(t.location) || ""}${(t.sources ?? []).length > 0 && l(t.sources ?? []) || ""}${(t.tools ?? []).length > 0 && d(t.tools ?? []) || ""}</calcite-accordion></div>` || ""}</div></div>`;
|
|
39
|
+
};
|
|
40
|
+
export {
|
|
41
|
+
C as ChatResponse
|
|
42
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "@esri/calcite-components/components/calcite-accordion-item";
|
|
2
|
+
import "@arcgis/map-components/components/arcgis-map";
|
|
3
|
+
import "@arcgis/map-components/components/arcgis-zoom";
|
|
4
|
+
import "@arcgis/map-components/components/arcgis-expand";
|
|
5
|
+
import "@arcgis/map-components/components/arcgis-layer-list";
|
|
6
|
+
import "@esri/calcite-components/components/calcite-button";
|
|
7
|
+
import "@esri/calcite-components/components/calcite-accordion";
|
|
8
|
+
export * from "./customElement.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "@esri/calcite-components/components/calcite-accordion-item";
|
|
2
|
+
import "@arcgis/map-components/components/arcgis-map";
|
|
3
|
+
import "@arcgis/map-components/components/arcgis-zoom";
|
|
4
|
+
import "@arcgis/map-components/components/arcgis-expand";
|
|
5
|
+
import "@arcgis/map-components/components/arcgis-layer-list";
|
|
6
|
+
import "@esri/calcite-components/components/calcite-button";
|
|
7
|
+
import "@esri/calcite-components/components/calcite-accordion";
|
|
8
|
+
export * from "./customElement.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { html as e } from "lit-html";
|
|
2
|
+
/*! All material copyright Esri, All Rights Reserved, unless otherwise specified.
|
|
3
|
+
See https://js.arcgis.com/0.0/esri/copyright.txt for details.
|
|
4
|
+
v0.0.5 */
|
|
5
|
+
const l = ({ showSkeletonLoader: s, currentLoadingMessage: d }) => s ? e`<div class="loader"><div class="skeleton-loader"></div><div class="skeleton-loader"></div><div class="skeleton-loader"></div><div class="square-container"><div class="skeleton-loader square"></div><div class="skeleton-loader square"></div></div></div>` : e`<div class="status-message">${d}</div>`;
|
|
6
|
+
export {
|
|
7
|
+
l as ChatStatus
|
|
8
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./customElement.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./customElement.js";
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/// <reference types="../../index.d.ts" />
|
|
2
|
+
import { PublicLitElement as LitElement, JsxNode, TargetedEvent } from '@arcgis/lumina';
|
|
3
|
+
import { AddDataAction, ChatMessage } from './util/types';
|
|
4
|
+
import { DefaultSuggestion } from '../../types';
|
|
5
|
+
import { FinderLocation, ArcgisErrorResponse, FinderSkillResponse } from '../arcgis-hub-ai-assistant/util/framework';
|
|
6
|
+
|
|
7
|
+
export declare class ArcgisChatUI extends LitElement {
|
|
8
|
+
/** Stores a developer feature message for quick testing or shortcuts. */
|
|
9
|
+
devFeatureMessage: ChatMessage | undefined;
|
|
10
|
+
/** The current conversation ID, or null if starting a new conversation. */
|
|
11
|
+
conversationId: string | null;
|
|
12
|
+
/**
|
|
13
|
+
* The disclaimer text for the AI assistant
|
|
14
|
+
*
|
|
15
|
+
* @default ""
|
|
16
|
+
*/
|
|
17
|
+
botDescription: string;
|
|
18
|
+
/**
|
|
19
|
+
* The title of the AI assistant
|
|
20
|
+
*
|
|
21
|
+
* @default ""
|
|
22
|
+
*/
|
|
23
|
+
botTitle: string;
|
|
24
|
+
/** The default suggestions prompted to the user */
|
|
25
|
+
defaultSuggestions: (DefaultSuggestion | string)[];
|
|
26
|
+
/**
|
|
27
|
+
* The current text input value from the user.
|
|
28
|
+
*
|
|
29
|
+
* @default ""
|
|
30
|
+
*/
|
|
31
|
+
inputText: string;
|
|
32
|
+
/**
|
|
33
|
+
* Function property to get a Finder response.
|
|
34
|
+
* Should be provided by the parent component, `hub-ai-assistant`.
|
|
35
|
+
*
|
|
36
|
+
* @param message - The user message to send.
|
|
37
|
+
* @param conversationId - The current conversation ID, or null to start a new conversation.
|
|
38
|
+
* @returns A promise resolving to an array of ArcgisErrorResponse or FinderSkillResponse.
|
|
39
|
+
*/
|
|
40
|
+
getFinderResponse: (message: string, conversationId: string | null) => Promise<ArcgisErrorResponse[] | FinderSkillResponse[]>;
|
|
41
|
+
/**
|
|
42
|
+
* Submits the user's message to the chat.
|
|
43
|
+
* Clears the input, adds the message to the chat history, and triggers the AI response.
|
|
44
|
+
* Currently using the
|
|
45
|
+
*
|
|
46
|
+
* @method
|
|
47
|
+
* decorator to expose this method to the DOM,
|
|
48
|
+
* allowing it to be called from `embed-modal.html`. Once this application has been migrated,
|
|
49
|
+
* I assume there will be no need for the html component and the
|
|
50
|
+
* @method decorator can be removed.
|
|
51
|
+
* @param text The user's input message.
|
|
52
|
+
*/
|
|
53
|
+
submitUserMessage(text: string): void;
|
|
54
|
+
/** Event emitted when the user clicks to add data from a chat message. */
|
|
55
|
+
readonly arcgisAddDataClick: TargetedEvent<this, AddDataAction>;
|
|
56
|
+
/** Event emitted when the user clicks a zoom to location button in a chat message. */
|
|
57
|
+
readonly arcgisLocationClick: TargetedEvent<this, FinderLocation>;
|
|
58
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { c as h } from "../../chunks/runtime.js";
|
|
2
|
+
import { html as r } from "lit-html";
|
|
3
|
+
import { ref as m } from "lit-html/directives/ref.js";
|
|
4
|
+
import { LitElement as u, createEvent as l, nothing as p } from "@arcgis/lumina";
|
|
5
|
+
import { css as f } from "@lit/reactive-element/css-tag.js";
|
|
6
|
+
import { ChatResponse as n } from "./components/chat-response/customElement.js";
|
|
7
|
+
import { ChatStatus as x } from "./components/chat-status/customElement.js";
|
|
8
|
+
import { isFinderResponseContext as b, enrichSources as y } from "../arcgis-hub-ai-assistant/util/customElement.js";
|
|
9
|
+
/*! All material copyright Esri, All Rights Reserved, unless otherwise specified.
|
|
10
|
+
See https://js.arcgis.com/0.0/esri/copyright.txt for details.
|
|
11
|
+
v0.0.5 */
|
|
12
|
+
const v = f`.actions{margin:.5em;background-color:#ffffff80;width:100%;border-radius:10px;.thumbnail{background-size:cover;background-position:center center;height:150px;width:100%;display:flex;align-items:center;justify-content:center;border-top-left-radius:10px;border-top-right-radius:10px}.viewDetails{font-size:smaller}.bottom{padding:10px}.title{margin-bottom:5px}.viewDetails span{transform:rotate(90deg);display:inline-block}calcite-accordion{width:100%}}.sources{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:1em;width:100%}.source{margin:.5em;border-radius:10px;width:200px}calcite-accordion-item[heading=Map]>*{margin-bottom:1rem}arcgis-map{display:block;height:400px}.text{margin:0 .5rem}.message{display:grid;grid-column-gap:1px;justify-content:start;grid-template-areas:"avatar text" ". feedback "}.message.removed{display:none}.response{display:block;grid-area:text;width:fit-content;padding:.75rem;font-size:1rem;line-height:1.375rem;text-align:left}.response p{margin-block-start:0;margin-block-end:0}.response a{color:#00a0ff}.response .actions{width:100%;display:flex;flex-wrap:wrap;box-sizing:border-box}.author-Human{justify-content:end;grid-template-areas:"text avatar" "feedback ."}.author-Human .response{background-color:var(--color-primary);color:#fff;border-radius:15px 0 15px 15px}.author-AI .response{border-radius:0 15px 15px;background-color:var(--calcite-color-foreground-1);color:var(--calcite-color-text-1)}.status-message{opacity:0;font-size:1em;transition:opacity 2s ease-in-out;font-size:1.2rem;text-justify:auto}@keyframes fadeIn{0%{opacity:0;transform:translateY(20px)}50%{opacity:1;transform:translateY(0)}to{opacity:0}}.status-message{animation:fadeIn 6s infinite}.loader{display:flex;flex-direction:column;gap:.5rem;background:#fff;padding:1rem;width:65%;border-radius:0 16px 16px}.skeleton-loader{background:#eee;background:linear-gradient(110deg,#ececec 8%,#f5f5f5 18%,#ececec 33%);border-radius:5px;background-size:200% 100%;animation:1.5s shine linear infinite;height:24px;width:100%}.square-container{display:flex;gap:1rem;flex-direction:row}.square{width:120px;height:120px}@keyframes shine{to{background-position-x:-200%}}:host{--color-primary: dodgerblue;display:flex;flex-direction:column;height:100%;.messages{flex:1;flex-grow:1;display:flex;padding:10px;overflow-y:auto;flex-direction:column;gap:1rem}form{margin:0 .5rem;.action-buttons{display:flex;justify-content:space-around}.action-buttons calcite-button{width:auto;flex-grow:1;margin:.5rem}}}#request-input{margin:0 .5rem;height:2rem}.actionsTitle{display:block;font-weight:700;font-size:1.2rem;text-align:left}#actions{display:flex;flex-flow:row wrap;justify-content:flex-start;gap:1rem;margin:1rem}`;
|
|
13
|
+
var i = /* @__PURE__ */ ((a) => (a.USER = "Human", a.HUB = "AI", a.SYSTEM = "System", a))(i || {});
|
|
14
|
+
const c = [
|
|
15
|
+
"Searching for relevant datasets...",
|
|
16
|
+
"Analyzing your query...",
|
|
17
|
+
"Finding location details...",
|
|
18
|
+
"Loading data for your request...",
|
|
19
|
+
"Filtering data...",
|
|
20
|
+
"Creating map...",
|
|
21
|
+
"Fetching the latest statistics..."
|
|
22
|
+
];
|
|
23
|
+
class I extends u {
|
|
24
|
+
constructor() {
|
|
25
|
+
super(...arguments), this.loadingMessageIntervalMs = 6e3, this.handleFormSubmit = (e) => {
|
|
26
|
+
e.preventDefault(), this.inputText.trim() && this.submitUserMessage(this.inputText);
|
|
27
|
+
}, this.handleClearHistory = () => {
|
|
28
|
+
this.messages = [], this.conversationId = null, this.scrollToBottomAfterUpdate();
|
|
29
|
+
}, this.isLoading = !1, this.currentLoadingMessage = this.getRandomLoadingMessage(), this.messages = [], this.conversationId = null, this.botDescription = "", this.botTitle = "", this.defaultSuggestions = [], this.inputText = "", this.getFinderResponse = async () => [], this.arcgisAddDataClick = l(), this.arcgisLocationClick = l();
|
|
30
|
+
}
|
|
31
|
+
static {
|
|
32
|
+
this.properties = { isLoading: 16, currentLoadingMessage: 16, messages: 16, devFeatureMessage: 0, conversationId: 1, botDescription: 1, botTitle: 1, defaultSuggestions: 0, inputText: 1, getFinderResponse: 0 };
|
|
33
|
+
}
|
|
34
|
+
static {
|
|
35
|
+
this.styles = v;
|
|
36
|
+
}
|
|
37
|
+
submitUserMessage(e) {
|
|
38
|
+
this.inputText = "";
|
|
39
|
+
const t = structuredClone(this.messages), s = {
|
|
40
|
+
author: i.USER,
|
|
41
|
+
text: e,
|
|
42
|
+
messageId: t.length + 1
|
|
43
|
+
// Increment message ID for tracking
|
|
44
|
+
};
|
|
45
|
+
t.push(s), this.messages = t, this.scrollToBottomAfterUpdate(), this.handleDevFeatures(t, e) || this.handleUserMessage();
|
|
46
|
+
}
|
|
47
|
+
getRandomLoadingMessage() {
|
|
48
|
+
return c[Math.floor(Math.random() * c.length)];
|
|
49
|
+
}
|
|
50
|
+
setMessagesContainer(e) {
|
|
51
|
+
this.messagesContainer = e;
|
|
52
|
+
}
|
|
53
|
+
scrollToBottomAfterUpdate() {
|
|
54
|
+
this.updateComplete.then(() => {
|
|
55
|
+
this.scrollToBottom();
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
scrollToBottom() {
|
|
59
|
+
this.messagesContainer && this.messagesContainer.scrollTo({
|
|
60
|
+
top: this.messagesContainer.scrollHeight,
|
|
61
|
+
behavior: "smooth"
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
handleInputTextChange(e) {
|
|
65
|
+
this.inputText = e.target.value;
|
|
66
|
+
}
|
|
67
|
+
handleDevFeatures(e, t) {
|
|
68
|
+
if (t === "::trees" && this.devFeatureMessage) {
|
|
69
|
+
const s = { ...this.devFeatureMessage, messageId: e.length + 1 };
|
|
70
|
+
return e.push(s), this.messages = e, !0;
|
|
71
|
+
}
|
|
72
|
+
return !1;
|
|
73
|
+
}
|
|
74
|
+
handleChatError(e) {
|
|
75
|
+
this.setLoading(!1);
|
|
76
|
+
const t = {
|
|
77
|
+
text: "Sorry, I encountered an error while processing your request. Please try again.",
|
|
78
|
+
author: i.HUB,
|
|
79
|
+
messageId: e.length + 1
|
|
80
|
+
};
|
|
81
|
+
e.push(t), this.messages = e, this.scrollToBottomAfterUpdate();
|
|
82
|
+
}
|
|
83
|
+
setLoading(e) {
|
|
84
|
+
this.isLoading = e, e ? (this.currentLoadingMessage = this.getRandomLoadingMessage(), this.loadingIntervalId = window.setInterval(() => {
|
|
85
|
+
this.currentLoadingMessage = this.getRandomLoadingMessage();
|
|
86
|
+
}, this.loadingMessageIntervalMs), this.scrollToBottomAfterUpdate()) : this.loadingIntervalId && (clearInterval(this.loadingIntervalId), this.loadingIntervalId = void 0);
|
|
87
|
+
}
|
|
88
|
+
async handleUserMessage() {
|
|
89
|
+
const e = structuredClone(this.messages);
|
|
90
|
+
try {
|
|
91
|
+
this.setLoading(!0);
|
|
92
|
+
const s = (await this.getFinderResponse(e[e.length - 1].text, this.conversationId))[1];
|
|
93
|
+
if (this.conversationId ??= s.conversationId, b(s.context)) {
|
|
94
|
+
const o = s.context, g = Array.isArray(o.sources) && o.sources.length > 0 ? await y(o.sources) : [], d = {
|
|
95
|
+
...o,
|
|
96
|
+
sources: g,
|
|
97
|
+
messageId: e.length + 1,
|
|
98
|
+
author: i.HUB
|
|
99
|
+
};
|
|
100
|
+
e[e.length - 1].text === "trees" && (this.devFeatureMessage = d), this.setLoading(!1), e.push(d), this.messages = e;
|
|
101
|
+
} else
|
|
102
|
+
this.handleChatError(e);
|
|
103
|
+
this.scrollToBottomAfterUpdate();
|
|
104
|
+
} catch {
|
|
105
|
+
this.handleChatError(e);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
renderSuggestions(e) {
|
|
109
|
+
return e.map((t) => r`<calcite-button round icon-start=${(typeof t == "string" ? "effects" : t.icon) ?? p} @click=${() => this.submitUserMessage(typeof t == "string" ? t : t.label)} .disabled=${this.isLoading} appearance=outline-fill>${typeof t == "string" ? t : t.label}</calcite-button>`);
|
|
110
|
+
}
|
|
111
|
+
renderWelcomeMessages() {
|
|
112
|
+
return r`${this.botTitle && n({ message: { author: i.HUB, text: `Welcome to the ${this.botTitle}` } }) || ""}${this.botDescription && n({ message: { author: i.HUB, text: this.botDescription } }) || ""}${n({ message: { author: i.HUB, text: "How can I assist you today?" } })}`;
|
|
113
|
+
}
|
|
114
|
+
renderForm() {
|
|
115
|
+
return r`<form @submit=${this.handleFormSubmit}><calcite-input-text .disabled=${this.isLoading} id=request-input placeholder="What are you searching for...?" @calciteInputTextInput=${this.handleInputTextChange} .value=${this.inputText}></calcite-input-text><div class="action-buttons"><calcite-button appearance=outline icon-start=reset @click=${this.handleClearHistory} .disabled=${this.isLoading}>Clear History</calcite-button><calcite-button type=submit icon-start=send .disabled=${this.isLoading || !this.inputText.trim()}>Send</calcite-button></div></form>`;
|
|
116
|
+
}
|
|
117
|
+
renderMessageContainer() {
|
|
118
|
+
return r`<div class="messages" ${m(this.setMessagesContainer)}>${this.renderWelcomeMessages()}<div><div class="actionsTitle">Suggested prompts</div><div id=actions>${this.renderSuggestions(this.defaultSuggestions)}</div></div>${this.messages.map((e) => n({ message: e, addDataClick: (t) => this.arcgisAddDataClick.emit(t), addLocationClick: (t) => this.arcgisLocationClick.emit(t) }))}${this.isLoading && x({ showSkeletonLoader: !1, currentLoadingMessage: this.currentLoadingMessage }) || ""}</div>`;
|
|
119
|
+
}
|
|
120
|
+
render() {
|
|
121
|
+
return r`${this.renderMessageContainer()}${this.renderForm()}`;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
h("arcgis-chat-ui", I);
|
|
125
|
+
export {
|
|
126
|
+
I as ArcgisChatUI
|
|
127
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { FinderResponseContext, FinderSource } from '../../arcgis-hub-ai-assistant/util/framework';
|
|
2
|
+
export type ChatAction = {
|
|
3
|
+
action: string;
|
|
4
|
+
text: string;
|
|
5
|
+
properties: ChatActionPrompt;
|
|
6
|
+
};
|
|
7
|
+
export type ChatActionPrompt = {
|
|
8
|
+
prompt: string;
|
|
9
|
+
};
|
|
10
|
+
type DataItem = {
|
|
11
|
+
id: string;
|
|
12
|
+
};
|
|
13
|
+
export type AddDataAction = {
|
|
14
|
+
type: "dataset";
|
|
15
|
+
title?: string;
|
|
16
|
+
data: DataItem;
|
|
17
|
+
};
|
|
18
|
+
export type ChatSource = FinderSource & {
|
|
19
|
+
thumbnail?: string;
|
|
20
|
+
url?: string;
|
|
21
|
+
};
|
|
22
|
+
export type ChatMessage = Partial<FinderResponseContext> & {
|
|
23
|
+
author: string;
|
|
24
|
+
text: string;
|
|
25
|
+
messageId?: number;
|
|
26
|
+
};
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/// <reference types="../../index.d.ts" />
|
|
2
|
+
import { PublicLitElement as LitElement, JsxNode, TargetedEvent } from '@arcgis/lumina';
|
|
3
|
+
import { DefaultSuggestion } from '../../types';
|
|
4
|
+
import { ArcGISIdentityManager } from '@esri/arcgis-rest-request';
|
|
5
|
+
|
|
6
|
+
export declare class ArcGISHubAIAssistant extends LitElement {
|
|
7
|
+
/**
|
|
8
|
+
* If the map is enabled (able to be togged on within the component).
|
|
9
|
+
*
|
|
10
|
+
* @default false
|
|
11
|
+
*/
|
|
12
|
+
mapEnabled: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* If the map is currently visible. Only applicable if `mapEnabled` is true.
|
|
15
|
+
*
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
mapVisible: boolean;
|
|
19
|
+
/** ArcGIS Item id for assistant configuration */
|
|
20
|
+
itemId: string | null;
|
|
21
|
+
/**
|
|
22
|
+
* The base URL of the ArcGIS portal to use for authentication and data requests.
|
|
23
|
+
*
|
|
24
|
+
* @default ""
|
|
25
|
+
*/
|
|
26
|
+
portalUrl: string;
|
|
27
|
+
/**
|
|
28
|
+
* The API endpoint for the AI assistant's backend service.
|
|
29
|
+
*
|
|
30
|
+
* @default "/api/assistants/v1"
|
|
31
|
+
*/
|
|
32
|
+
apiUrl: string;
|
|
33
|
+
/**
|
|
34
|
+
* The title of the AI assistant bot, displayed in the UI.
|
|
35
|
+
*
|
|
36
|
+
* @default "Hub AI Assistant"
|
|
37
|
+
*/
|
|
38
|
+
botTitle: string;
|
|
39
|
+
/**
|
|
40
|
+
* The default map extent (bounding box) to use for the map view.
|
|
41
|
+
* Format: [[minX, minY], [maxX, maxY]]
|
|
42
|
+
*/
|
|
43
|
+
extent: number[][] | undefined;
|
|
44
|
+
/** Portal IDs of the layers on the map */
|
|
45
|
+
mapLayers: string[];
|
|
46
|
+
/**
|
|
47
|
+
* In the map, option to show the "Table" widget.
|
|
48
|
+
*
|
|
49
|
+
* @default false
|
|
50
|
+
*/
|
|
51
|
+
mapShowTable: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* The basemap for the map. List of options:
|
|
54
|
+
* https://developers.arcgis.com/javascript/latest/api-reference/esri-WebMap.html#basemap
|
|
55
|
+
*
|
|
56
|
+
* @default "gray-vector"
|
|
57
|
+
*/
|
|
58
|
+
mapBasemap: string;
|
|
59
|
+
/**
|
|
60
|
+
* Default geographic location to limit / focus results
|
|
61
|
+
*
|
|
62
|
+
* @default "Washington, DC"
|
|
63
|
+
*/
|
|
64
|
+
location: string;
|
|
65
|
+
/**
|
|
66
|
+
* Hub domain to use for finding relevant datasets
|
|
67
|
+
*
|
|
68
|
+
* @default "opendata.dc.gov"
|
|
69
|
+
*/
|
|
70
|
+
hub: string;
|
|
71
|
+
/** For information queries (infererence) which entity to get pages + documents */
|
|
72
|
+
entityId: string | null;
|
|
73
|
+
/**
|
|
74
|
+
* Context such as organization or theme for this AI Assistant
|
|
75
|
+
* e.g. "USGS" or "Oceans"
|
|
76
|
+
*/
|
|
77
|
+
context: string | null;
|
|
78
|
+
/** Language for the chatbot to use */
|
|
79
|
+
language: string | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* Basic info about the bot to display in the "About" panel
|
|
82
|
+
*
|
|
83
|
+
* @default "Hub AI Assistant helps you find and use open data in your community."
|
|
84
|
+
*/
|
|
85
|
+
botDescription: string;
|
|
86
|
+
/** The default suggestions for the user */
|
|
87
|
+
defaultSuggestions: (DefaultSuggestion | string)[];
|
|
88
|
+
authentication: ArcGISIdentityManager | undefined;
|
|
89
|
+
readonly arcgisAddLayer: TargetedEvent<this, undefined>;
|
|
90
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { c as T } from "../../chunks/runtime.js";
|
|
2
|
+
import { html as y } from "lit-html";
|
|
3
|
+
import { LitElement as $, createEvent as E, noShadowRoot as x } from "@arcgis/lumina";
|
|
4
|
+
import { getLocationCenter as D, calculateZoom as R } from "./util/customElement.js";
|
|
5
|
+
import { css as C } from "@lit/reactive-element/css-tag.js";
|
|
6
|
+
import { getPortalSettings as L, getItem as P, getItemData as U } from "@esri/arcgis-rest-portal";
|
|
7
|
+
import { createRef as _, ref as w } from "lit/directives/ref.js";
|
|
8
|
+
import z from "@arcgis/core/layers/Layer.js";
|
|
9
|
+
import F from "@arcgis/core/portal/PortalItem.js";
|
|
10
|
+
/*! All material copyright Esri, All Rights Reserved, unless otherwise specified.
|
|
11
|
+
See https://js.arcgis.com/0.0/esri/copyright.txt for details.
|
|
12
|
+
v0.0.5 */
|
|
13
|
+
async function H(s) {
|
|
14
|
+
const {
|
|
15
|
+
skillId: e,
|
|
16
|
+
message: t,
|
|
17
|
+
context: a,
|
|
18
|
+
token: n,
|
|
19
|
+
conversationId: i,
|
|
20
|
+
apiUrl: c = "https://api.example.com",
|
|
21
|
+
pauseMs: I = 1e3,
|
|
22
|
+
retries: S = 3
|
|
23
|
+
} = s, u = {
|
|
24
|
+
Authorization: `Bearer ${n}`,
|
|
25
|
+
Accept: "application/json",
|
|
26
|
+
"Content-Type": "application/json"
|
|
27
|
+
}, p = `${c}/skills/${e}/chat`, m = { message: t, context: a };
|
|
28
|
+
i && (m.conversationId = i);
|
|
29
|
+
try {
|
|
30
|
+
const r = await fetch(p, {
|
|
31
|
+
method: "POST",
|
|
32
|
+
headers: u,
|
|
33
|
+
body: JSON.stringify(m)
|
|
34
|
+
});
|
|
35
|
+
if (!r.ok)
|
|
36
|
+
throw new Error(`HTTP error! status: ${r.status}`);
|
|
37
|
+
const o = await r.json(), k = i ?? o.conversationId, v = o.inquiryId;
|
|
38
|
+
let g = o.hasMore || o.message == null, f = o.sequenceNumber;
|
|
39
|
+
const h = [];
|
|
40
|
+
o.message && h.push(o);
|
|
41
|
+
let b = 0;
|
|
42
|
+
for (; g && b < S; ) {
|
|
43
|
+
await new Promise((A) => setTimeout(A, I));
|
|
44
|
+
const d = await fetch(p, {
|
|
45
|
+
method: "POST",
|
|
46
|
+
headers: u,
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
conversationId: k,
|
|
49
|
+
inquiryId: v,
|
|
50
|
+
ackSequenceNumber: f
|
|
51
|
+
})
|
|
52
|
+
});
|
|
53
|
+
if (!d.ok)
|
|
54
|
+
throw new Error(`HTTP error! status: ${d.status}`);
|
|
55
|
+
const l = await d.json();
|
|
56
|
+
l.message && h.push(l), g = l.hasMore, l.message != null && (f += 1), b++;
|
|
57
|
+
}
|
|
58
|
+
return h;
|
|
59
|
+
} catch (r) {
|
|
60
|
+
return console.error("Error during request:", r), [];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function M({
|
|
64
|
+
message: s,
|
|
65
|
+
context: e,
|
|
66
|
+
token: t,
|
|
67
|
+
conversationId: a,
|
|
68
|
+
apiUrl: n = "https://hub.arcgis.com/api/assistants/v1",
|
|
69
|
+
pauseMs: i = 1e3,
|
|
70
|
+
retries: c = 50
|
|
71
|
+
}) {
|
|
72
|
+
return await H({
|
|
73
|
+
skillId: "finder",
|
|
74
|
+
message: s,
|
|
75
|
+
context: e,
|
|
76
|
+
token: t,
|
|
77
|
+
conversationId: a ?? void 0,
|
|
78
|
+
apiUrl: n,
|
|
79
|
+
pauseMs: i,
|
|
80
|
+
retries: c
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
const V = C`@layer{arcgis-hub-ai-assistant{arcgis-feature-table{height:200px}}}`, q = {
|
|
84
|
+
language: "en",
|
|
85
|
+
defaultSuggestions: ["What can I do with this assistant?"],
|
|
86
|
+
personality: "You are writing for a government websites readable by 8th graders.",
|
|
87
|
+
feedbackFormUrl: "https://survey123.arcgis.com/share/5661d0a398e4416984c2008ebf02a701",
|
|
88
|
+
allowChat: !1,
|
|
89
|
+
showHeader: !0
|
|
90
|
+
};
|
|
91
|
+
async function O({
|
|
92
|
+
portal: s,
|
|
93
|
+
authentication: e
|
|
94
|
+
}) {
|
|
95
|
+
try {
|
|
96
|
+
const a = await L(void 0, {
|
|
97
|
+
portal: s,
|
|
98
|
+
authentication: e
|
|
99
|
+
});
|
|
100
|
+
return console.log("orgSettingsData", a), a.aiAssistantsEnabled === void 0 || a.aiAssistantsEnabled && !a.blockBetaApps ? !0 : (console.warn("AI Assistants are not enabled for this organization."), !1);
|
|
101
|
+
} catch (t) {
|
|
102
|
+
return console.error("Error fetching organization assistant settings:", t), !1;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function j(s) {
|
|
106
|
+
return s.replace("http://", "").replace("https://", "").split(/[/?#]/u)[0];
|
|
107
|
+
}
|
|
108
|
+
async function B(s) {
|
|
109
|
+
try {
|
|
110
|
+
const [e, t] = await Promise.all([
|
|
111
|
+
P(s),
|
|
112
|
+
// , { authentication: state.context.hubRequestOptions.authentication }
|
|
113
|
+
U(s)
|
|
114
|
+
// , { authentication: state.context.hubRequestOptions.authentication }
|
|
115
|
+
]);
|
|
116
|
+
return {
|
|
117
|
+
...q,
|
|
118
|
+
title: e.title,
|
|
119
|
+
description: e.description,
|
|
120
|
+
extent: e.extent,
|
|
121
|
+
context: e.accessInformation,
|
|
122
|
+
placeholder: t.placeholder,
|
|
123
|
+
theme: t.theme,
|
|
124
|
+
avatar: t.avatar,
|
|
125
|
+
language: t.language,
|
|
126
|
+
clientId: t.clientId,
|
|
127
|
+
personality: t.personality,
|
|
128
|
+
feedbackFormUrl: t.feedbackFormUrl,
|
|
129
|
+
hub: j(t.hub),
|
|
130
|
+
allowChat: t.allowChat,
|
|
131
|
+
showHeader: t.showHeader,
|
|
132
|
+
entityId: t.entityId,
|
|
133
|
+
location: t.location,
|
|
134
|
+
tools: t.tools,
|
|
135
|
+
defaultSuggestions: t.defaultSuggestions,
|
|
136
|
+
informationSources: t.informationSources ?? [t.entityId]
|
|
137
|
+
};
|
|
138
|
+
} catch (e) {
|
|
139
|
+
throw console.error("Error fetching configuration:", e), e;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
class G extends $ {
|
|
143
|
+
constructor() {
|
|
144
|
+
super(...arguments), this._featureTable = _(), this.handleArcGISDataClick = (e) => {
|
|
145
|
+
const a = e.detail.data.id, n = new F({
|
|
146
|
+
id: a
|
|
147
|
+
});
|
|
148
|
+
z.fromPortalItem({
|
|
149
|
+
portalItem: n
|
|
150
|
+
}).then((i) => {
|
|
151
|
+
this._mapRef?.map?.add(i), this._featureTable.value && (this._featureTable.value.layer = i), this.mapLayers.push(a), this.arcgisAddLayer.emit(), this.mapVisible = !0;
|
|
152
|
+
}).catch((i) => {
|
|
153
|
+
console.log("could not add layer:", i);
|
|
154
|
+
});
|
|
155
|
+
}, this.handleArcGISLocationClick = (e) => {
|
|
156
|
+
const t = e.detail;
|
|
157
|
+
t.longitude && t.latitude && t.zoom && (this.mapVisible = !0, this._mapRef?.view.goTo({ center: [t.longitude, t.latitude], zoom: t.zoom }));
|
|
158
|
+
}, this.assistantsEnabled = !1, this.mapEnabled = !1, this.mapVisible = !1, this.itemId = null, this.portalUrl = "", this.apiUrl = "/api/assistants/v1", this.botTitle = "Hub AI Assistant", this.extent = [
|
|
159
|
+
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
|
160
|
+
[-77.119, 38.791],
|
|
161
|
+
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
|
162
|
+
[-76.909, 38.995]
|
|
163
|
+
], this.mapLayers = [], this.mapShowTable = !1, this.mapBasemap = "gray-vector", this.location = "Washington, DC", this.hub = "opendata.dc.gov", this.entityId = null, this.context = null, this.language = void 0, this.botDescription = "Hub AI Assistant helps you find and use open data in your community.", this.defaultSuggestions = [], this.authentication = void 0, this.arcgisAddLayer = E();
|
|
164
|
+
}
|
|
165
|
+
static {
|
|
166
|
+
this.properties = { assistantsEnabled: 16, _mapRef: 16, mapEnabled: 5, mapVisible: 5, itemId: 1, portalUrl: 1, apiUrl: 1, botTitle: 1, extent: 0, mapLayers: 0, mapShowTable: 5, mapBasemap: 1, location: 1, hub: 1, entityId: 1, context: 1, language: 1, botDescription: 1, defaultSuggestions: 0, authentication: 0 };
|
|
167
|
+
}
|
|
168
|
+
static {
|
|
169
|
+
this.shadowRootOptions = x;
|
|
170
|
+
}
|
|
171
|
+
static {
|
|
172
|
+
this.styles = V;
|
|
173
|
+
}
|
|
174
|
+
async load() {
|
|
175
|
+
if (this.assistantsEnabled = await O({
|
|
176
|
+
portal: "https://www.arcgis.com/sharing/rest",
|
|
177
|
+
authentication: this.authentication
|
|
178
|
+
}), this.itemId) {
|
|
179
|
+
const e = await B(this.itemId);
|
|
180
|
+
console.log("Hub AI Assistant configuration", e), this.botTitle = e.title, this.botDescription = e.description ? e.description : "", this.hub = e.hub, this.extent = e.extent, this.defaultSuggestions = e.defaultSuggestions;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
async handleFinderResponse(e, t) {
|
|
184
|
+
const a = await M({
|
|
185
|
+
message: e,
|
|
186
|
+
conversationId: t,
|
|
187
|
+
context: {
|
|
188
|
+
kind: "FinderRequest",
|
|
189
|
+
item: this.itemId ?? void 0
|
|
190
|
+
},
|
|
191
|
+
token: this.authentication?.token ?? "",
|
|
192
|
+
apiUrl: this.apiUrl
|
|
193
|
+
});
|
|
194
|
+
if (a.length === 0)
|
|
195
|
+
throw new Error("Finder response is empty or invalid");
|
|
196
|
+
return a;
|
|
197
|
+
}
|
|
198
|
+
_setMapRef(e) {
|
|
199
|
+
this._mapRef = e;
|
|
200
|
+
}
|
|
201
|
+
render() {
|
|
202
|
+
return y`<link rel=stylesheet href=https://js.arcgis.com/4.33/@arcgis/core/assets/esri/themes/light/main.css><arcgis-chat-shell .aboutContent=${this.botDescription} .mapEnabled=${this.mapEnabled} .mapVisible=${this.mapEnabled && this.mapVisible} @arcgisUpdateMapVisibility=${(e) => {
|
|
203
|
+
this.mapVisible = e.detail;
|
|
204
|
+
}}><arcgis-chat-ui .botDescription=${this.botDescription} .botTitle=${this.botTitle} .defaultSuggestions=${this.defaultSuggestions} slot=leftPanel .getFinderResponse=${this.handleFinderResponse.bind(this)} @arcgisAddDataClick=${this.handleArcGISDataClick} @arcgisLocationClick=${this.handleArcGISLocationClick}></arcgis-chat-ui><arcgis-map slot=map .center=${D(this.extent)} .zoom=${R(this.extent)} .basemap=${this.mapBasemap} ${w(this._setMapRef)}><arcgis-zoom position=top-left></arcgis-zoom><arcgis-expand position=top-right><arcgis-layer-list></arcgis-layer-list></arcgis-expand><arcgis-search position=bottom-trailing></arcgis-search></arcgis-map>${this.mapShowTable && y`<arcgis-feature-table .referenceElement=${this._mapRef} slot=featureTable ${w(this._featureTable)}></arcgis-feature-table>` || ""}</arcgis-chat-shell>`;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
T("arcgis-hub-ai-assistant", G);
|
|
208
|
+
export {
|
|
209
|
+
G as ArcGISHubAIAssistant
|
|
210
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "../arcgis-chat-shell/index.js";
|
|
2
|
+
import "../arcgis-chat-ui/index.js";
|
|
3
|
+
import "@arcgis/map-components/components/arcgis-map";
|
|
4
|
+
import "@arcgis/map-components/components/arcgis-zoom";
|
|
5
|
+
import "@arcgis/map-components/components/arcgis-expand";
|
|
6
|
+
import "@arcgis/map-components/components/arcgis-layer-list";
|
|
7
|
+
import "@arcgis/map-components/components/arcgis-search";
|
|
8
|
+
import "@arcgis/map-components/components/arcgis-feature-table";
|
|
9
|
+
export * from "./customElement.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "../arcgis-chat-shell/index.js";
|
|
2
|
+
import "../arcgis-chat-ui/index.js";
|
|
3
|
+
import "@arcgis/map-components/components/arcgis-map";
|
|
4
|
+
import "@arcgis/map-components/components/arcgis-zoom";
|
|
5
|
+
import "@arcgis/map-components/components/arcgis-expand";
|
|
6
|
+
import "@arcgis/map-components/components/arcgis-layer-list";
|
|
7
|
+
import "@arcgis/map-components/components/arcgis-search";
|
|
8
|
+
import "@arcgis/map-components/components/arcgis-feature-table";
|
|
9
|
+
export * from "./customElement.js";
|