@kodaris/krubble-app-components 1.0.126 → 1.0.127
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/chatbot.d.ts +6 -13
- package/dist/chatbot.d.ts.map +1 -1
- package/dist/chatbot.js +121 -100
- package/dist/chatbot.js.map +1 -1
- package/dist/krubble-app.bundled.js +121 -100
- package/dist/krubble-app.bundled.js.map +1 -1
- package/dist/krubble-app.bundled.min.js +19 -19
- package/dist/krubble-app.bundled.min.js.map +1 -1
- package/dist/krubble-app.umd.js +121 -100
- package/dist/krubble-app.umd.js.map +1 -1
- package/dist/krubble-app.umd.min.js +21 -21
- package/dist/krubble-app.umd.min.js.map +1 -1
- package/package.json +1 -1
package/dist/krubble-app.umd.js
CHANGED
|
@@ -3473,10 +3473,9 @@
|
|
|
3473
3473
|
}
|
|
3474
3474
|
}
|
|
3475
3475
|
// `this.load` is always set by here (defaulted above when the consumer didn't
|
|
3476
|
-
// supply one)
|
|
3477
|
-
//
|
|
3478
|
-
|
|
3479
|
-
resolveConversationId.then(() => load()).then((messages) => {
|
|
3476
|
+
// supply one); the `!` is because TS can't narrow the nullable property across
|
|
3477
|
+
// the promise boundary.
|
|
3478
|
+
resolveConversationId.then(() => this.load()).then((messages) => {
|
|
3480
3479
|
if (messages && messages.length) {
|
|
3481
3480
|
this.messages = messages;
|
|
3482
3481
|
}
|
|
@@ -3745,11 +3744,10 @@
|
|
|
3745
3744
|
}
|
|
3746
3745
|
_saveState() {
|
|
3747
3746
|
try {
|
|
3748
|
-
// `toolDetail`
|
|
3749
|
-
//
|
|
3750
|
-
// stale conversation list.
|
|
3747
|
+
// `toolDetail` is a transient peek, not a saved view — persist only the two
|
|
3748
|
+
// real preference views so a reload never reopens a stale tool.
|
|
3751
3749
|
let persistedDrawerView = this._drawerView;
|
|
3752
|
-
if (persistedDrawerView === 'toolDetail'
|
|
3750
|
+
if (persistedDrawerView === 'toolDetail') {
|
|
3753
3751
|
persistedDrawerView = 'settings';
|
|
3754
3752
|
}
|
|
3755
3753
|
const state = {
|
|
@@ -3808,8 +3806,14 @@
|
|
|
3808
3806
|
this._showToolInputs = state.showToolInputs === 'true';
|
|
3809
3807
|
this._showConfirmationInput = state.showConfirmationInput === 'true';
|
|
3810
3808
|
this._drawerOpen = state.drawerOpen === 'true';
|
|
3811
|
-
if (state.drawerView === 'settings' || state.drawerView === 'debug') {
|
|
3809
|
+
if (state.drawerView === 'settings' || state.drawerView === 'debug' || state.drawerView === 'history') {
|
|
3812
3810
|
this._drawerView = state.drawerView;
|
|
3811
|
+
// History's list isn't persisted (it can go stale); refetch it so a reload
|
|
3812
|
+
// that was on the conversations panel comes back to a populated list rather
|
|
3813
|
+
// than an empty one.
|
|
3814
|
+
if (state.drawerView === 'history') {
|
|
3815
|
+
this._loadConversations();
|
|
3816
|
+
}
|
|
3813
3817
|
}
|
|
3814
3818
|
const w = Number(state.drawerWidth);
|
|
3815
3819
|
if (w >= 300) {
|
|
@@ -4953,41 +4957,47 @@
|
|
|
4953
4957
|
else {
|
|
4954
4958
|
this._drawerOpen = true;
|
|
4955
4959
|
this._drawerView = view;
|
|
4956
|
-
// Opening the history view refetches the
|
|
4957
|
-
//
|
|
4958
|
-
// shows without a reload. Ownership is enforced server-side (the endpoint
|
|
4959
|
-
// scopes to the current administrator), so we only filter to active ones.
|
|
4960
|
+
// Opening the history view refetches the list so a just-created or renamed
|
|
4961
|
+
// conversation shows without a reload.
|
|
4960
4962
|
if (view === 'history') {
|
|
4961
|
-
this.
|
|
4962
|
-
krubbleHttp.Http.fetch({
|
|
4963
|
-
url: '/api/system/conversation/list',
|
|
4964
|
-
method: 'POST',
|
|
4965
|
-
body: {
|
|
4966
|
-
page: 0,
|
|
4967
|
-
size: 50,
|
|
4968
|
-
sortBy: 'lastModified',
|
|
4969
|
-
sortDirection: 'desc',
|
|
4970
|
-
filterFields: [{
|
|
4971
|
-
name: 'active',
|
|
4972
|
-
operation: 'IS',
|
|
4973
|
-
value: 'true',
|
|
4974
|
-
}],
|
|
4975
|
-
},
|
|
4976
|
-
})
|
|
4977
|
-
.then((r) => r.json())
|
|
4978
|
-
.then((res) => {
|
|
4979
|
-
this._conversations = res?.data?.content || [];
|
|
4980
|
-
})
|
|
4981
|
-
.catch(() => {
|
|
4982
|
-
this._conversations = [];
|
|
4983
|
-
})
|
|
4984
|
-
.then(() => {
|
|
4985
|
-
this._conversationsLoading = false;
|
|
4986
|
-
});
|
|
4963
|
+
this._loadConversations();
|
|
4987
4964
|
}
|
|
4988
4965
|
}
|
|
4989
4966
|
this._saveState();
|
|
4990
4967
|
}
|
|
4968
|
+
/**
|
|
4969
|
+
* Fetch the user's previous conversations for the history list, most-recently
|
|
4970
|
+
* modified first. Ownership is enforced server-side (the endpoint scopes to the
|
|
4971
|
+
* current administrator), so we only filter to active ones.
|
|
4972
|
+
*/
|
|
4973
|
+
_loadConversations() {
|
|
4974
|
+
this._conversationsLoading = true;
|
|
4975
|
+
krubbleHttp.Http.fetch({
|
|
4976
|
+
url: '/api/system/conversation/list',
|
|
4977
|
+
method: 'POST',
|
|
4978
|
+
body: {
|
|
4979
|
+
page: 0,
|
|
4980
|
+
size: 50,
|
|
4981
|
+
sortBy: 'lastModified',
|
|
4982
|
+
sortDirection: 'desc',
|
|
4983
|
+
filterFields: [{
|
|
4984
|
+
name: 'active',
|
|
4985
|
+
operation: 'IS',
|
|
4986
|
+
value: 'true',
|
|
4987
|
+
}],
|
|
4988
|
+
},
|
|
4989
|
+
})
|
|
4990
|
+
.then((r) => r.json())
|
|
4991
|
+
.then((res) => {
|
|
4992
|
+
this._conversations = res?.data?.content || [];
|
|
4993
|
+
})
|
|
4994
|
+
.catch(() => {
|
|
4995
|
+
this._conversations = [];
|
|
4996
|
+
})
|
|
4997
|
+
.then(() => {
|
|
4998
|
+
this._conversationsLoading = false;
|
|
4999
|
+
});
|
|
5000
|
+
}
|
|
4991
5001
|
/**
|
|
4992
5002
|
* Switch the floating widget to a previously-created conversation (clicked in the
|
|
4993
5003
|
* history list): stop any live turn, reset the transient turn/context state, pin
|
|
@@ -5006,7 +5016,22 @@
|
|
|
5006
5016
|
// one, so the header falls back to the default label).
|
|
5007
5017
|
this._conversationTitle = this._conversations.find((c) => c.conversationID === conversationID)?.title || '';
|
|
5008
5018
|
this._persistConversationId();
|
|
5009
|
-
|
|
5019
|
+
// Clear the transient, per-conversation state so it doesn't bleed into the one
|
|
5020
|
+
// we're switching to — pending confirmations, context banners, errors, the
|
|
5021
|
+
// reconnect counter, and staged composer files (the transcript is loaded below).
|
|
5022
|
+
this._pendingActions = [];
|
|
5023
|
+
this._inlineConfirm = true;
|
|
5024
|
+
this._contextWarning = '';
|
|
5025
|
+
this._contextLimitReached = false;
|
|
5026
|
+
this._contextLimitMessage = '';
|
|
5027
|
+
this._error = '';
|
|
5028
|
+
this._reconnectAttempts = 0;
|
|
5029
|
+
this._pendingConversationFiles.forEach((p) => {
|
|
5030
|
+
if (p.previewUrl) {
|
|
5031
|
+
URL.revokeObjectURL(p.previewUrl);
|
|
5032
|
+
}
|
|
5033
|
+
});
|
|
5034
|
+
this._pendingConversationFiles = [];
|
|
5010
5035
|
this._drawerOpen = false;
|
|
5011
5036
|
this._saveState();
|
|
5012
5037
|
if (this.load) {
|
|
@@ -5033,17 +5058,9 @@
|
|
|
5033
5058
|
this._conversationTitle = '';
|
|
5034
5059
|
this._persistConversationId();
|
|
5035
5060
|
this.messages = [];
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
}
|
|
5040
|
-
/**
|
|
5041
|
-
* Clear the transient, per-conversation state that must not bleed across a
|
|
5042
|
-
* conversation switch/new — pending confirmations, context banners, errors, the
|
|
5043
|
-
* reconnect counter, and staged composer files. The transcript itself is set by
|
|
5044
|
-
* the caller (loaded for a switch, emptied for new).
|
|
5045
|
-
*/
|
|
5046
|
-
_resetConversationState() {
|
|
5061
|
+
// Clear the transient, per-conversation state so it doesn't bleed into the new
|
|
5062
|
+
// conversation — pending confirmations, context banners, errors, the reconnect
|
|
5063
|
+
// counter, and staged composer files.
|
|
5047
5064
|
this._pendingActions = [];
|
|
5048
5065
|
this._inlineConfirm = true;
|
|
5049
5066
|
this._contextWarning = '';
|
|
@@ -5057,6 +5074,8 @@
|
|
|
5057
5074
|
}
|
|
5058
5075
|
});
|
|
5059
5076
|
this._pendingConversationFiles = [];
|
|
5077
|
+
this._drawerOpen = false;
|
|
5078
|
+
this._saveState();
|
|
5060
5079
|
}
|
|
5061
5080
|
/** Close the drawer. `_drawerView` is left intact so its content stays visible
|
|
5062
5081
|
* while the drawer slides shut. */
|
|
@@ -5939,55 +5958,58 @@
|
|
|
5939
5958
|
<div class="history__empty">No previous conversations</div>
|
|
5940
5959
|
` : b `
|
|
5941
5960
|
<div class="history__list">
|
|
5942
|
-
${this._conversations.map((conversation) =>
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
'
|
|
5947
|
-
|
|
5961
|
+
${this._conversations.map((conversation) => {
|
|
5962
|
+
// Format lastModified for the row: today shows the time, this year
|
|
5963
|
+
// shows month/day, older shows month/day/year; the raw value if it
|
|
5964
|
+
// isn't a parseable date. Empty when the conversation has no date.
|
|
5965
|
+
let dateLabel = '';
|
|
5966
|
+
if (conversation.lastModified) {
|
|
5967
|
+
const date = new Date(conversation.lastModified);
|
|
5968
|
+
const now = new Date();
|
|
5969
|
+
if (isNaN(date.getTime())) {
|
|
5970
|
+
dateLabel = conversation.lastModified;
|
|
5971
|
+
}
|
|
5972
|
+
else if (date.toDateString() === now.toDateString()) {
|
|
5973
|
+
dateLabel = date.toLocaleTimeString('en-US', {
|
|
5974
|
+
hour: 'numeric',
|
|
5975
|
+
minute: '2-digit',
|
|
5976
|
+
});
|
|
5977
|
+
}
|
|
5978
|
+
else if (date.getFullYear() === now.getFullYear()) {
|
|
5979
|
+
dateLabel = date.toLocaleDateString('en-US', {
|
|
5980
|
+
month: 'short',
|
|
5981
|
+
day: 'numeric',
|
|
5982
|
+
});
|
|
5983
|
+
}
|
|
5984
|
+
else {
|
|
5985
|
+
dateLabel = date.toLocaleDateString('en-US', {
|
|
5986
|
+
month: 'short',
|
|
5987
|
+
day: 'numeric',
|
|
5988
|
+
year: 'numeric',
|
|
5989
|
+
});
|
|
5990
|
+
}
|
|
5991
|
+
}
|
|
5992
|
+
return b `
|
|
5993
|
+
<button
|
|
5994
|
+
type="button"
|
|
5995
|
+
class=${e({
|
|
5996
|
+
'history__item': true,
|
|
5997
|
+
'history__item--active': conversation.conversationID === this.conversationId,
|
|
5998
|
+
})}
|
|
5999
|
+
@click=${() => this._handleSwitchConversation(conversation.conversationID)}
|
|
6000
|
+
>
|
|
6001
|
+
<span class="history__item-title">${conversation.title || 'Untitled conversation'}</span>
|
|
6002
|
+
${dateLabel ? b `
|
|
6003
|
+
<span class="history__item-date">${dateLabel}</span>
|
|
6004
|
+
` : A}
|
|
6005
|
+
</button>
|
|
6006
|
+
`;
|
|
5948
6007
|
})}
|
|
5949
|
-
@click=${() => this._handleSwitchConversation(conversation.conversationID)}
|
|
5950
|
-
>
|
|
5951
|
-
<span class="history__item-title">${conversation.title || 'Untitled conversation'}</span>
|
|
5952
|
-
${conversation.lastModified ? b `
|
|
5953
|
-
<span class="history__item-date">${this._renderConversationDate(conversation.lastModified)}</span>
|
|
5954
|
-
` : A}
|
|
5955
|
-
</button>
|
|
5956
|
-
`)}
|
|
5957
6008
|
</div>
|
|
5958
6009
|
`}
|
|
5959
6010
|
</div>
|
|
5960
6011
|
`;
|
|
5961
6012
|
}
|
|
5962
|
-
/**
|
|
5963
|
-
* Format a conversation's lastModified for the history list: today shows the
|
|
5964
|
-
* time, this year shows month/day, older shows month/day/year. Falls back to the
|
|
5965
|
-
* raw value if it isn't a parseable date.
|
|
5966
|
-
*/
|
|
5967
|
-
_renderConversationDate(lastModified) {
|
|
5968
|
-
const date = new Date(lastModified);
|
|
5969
|
-
if (isNaN(date.getTime())) {
|
|
5970
|
-
return lastModified;
|
|
5971
|
-
}
|
|
5972
|
-
const now = new Date();
|
|
5973
|
-
if (date.toDateString() === now.toDateString()) {
|
|
5974
|
-
return date.toLocaleTimeString('en-US', {
|
|
5975
|
-
hour: 'numeric',
|
|
5976
|
-
minute: '2-digit',
|
|
5977
|
-
});
|
|
5978
|
-
}
|
|
5979
|
-
if (date.getFullYear() === now.getFullYear()) {
|
|
5980
|
-
return date.toLocaleDateString('en-US', {
|
|
5981
|
-
month: 'short',
|
|
5982
|
-
day: 'numeric',
|
|
5983
|
-
});
|
|
5984
|
-
}
|
|
5985
|
-
return date.toLocaleDateString('en-US', {
|
|
5986
|
-
month: 'short',
|
|
5987
|
-
day: 'numeric',
|
|
5988
|
-
year: 'numeric',
|
|
5989
|
-
});
|
|
5990
|
-
}
|
|
5991
6013
|
/**
|
|
5992
6014
|
* The side drawer — one sliding panel that holds the Settings, Debug, History,
|
|
5993
6015
|
* and tool-detail views. The header buttons switch `_drawerView`; the title and
|
|
@@ -6018,25 +6040,24 @@
|
|
|
6018
6040
|
// In the floating widget the drawer fills the panel over the transcript (a
|
|
6019
6041
|
// full-panel view with a back button) rather than sliding in beside it — the
|
|
6020
6042
|
// panel is too narrow to show both. Inline keeps the side-drawer behavior.
|
|
6021
|
-
const fullPanel = this.variant === 'floating';
|
|
6022
6043
|
return b `
|
|
6023
6044
|
<div
|
|
6024
6045
|
class=${e({
|
|
6025
6046
|
'drawer': true,
|
|
6026
6047
|
'drawer--open': this._drawerOpen,
|
|
6027
6048
|
'drawer--resizing': this._isDrawerResizing,
|
|
6028
|
-
'drawer--full':
|
|
6049
|
+
'drawer--full': this.variant === 'floating',
|
|
6029
6050
|
})}
|
|
6030
|
-
style=${o(
|
|
6051
|
+
style=${o(this.variant === 'floating' ? {} : { width: `${this._drawerWidth}px` })}
|
|
6031
6052
|
>
|
|
6032
|
-
${
|
|
6053
|
+
${this.variant === 'floating' ? A : b `
|
|
6033
6054
|
<div
|
|
6034
6055
|
class="drawer__resize"
|
|
6035
6056
|
@mousedown=${this._handleDrawerResizeMouseDown}
|
|
6036
6057
|
></div>
|
|
6037
6058
|
`}
|
|
6038
6059
|
<div class="drawer__header">
|
|
6039
|
-
${
|
|
6060
|
+
${this.variant === 'floating' ? b `
|
|
6040
6061
|
<button
|
|
6041
6062
|
class="header-action"
|
|
6042
6063
|
@click=${this._handleCloseDrawer}
|
|
@@ -6084,7 +6105,7 @@
|
|
|
6084
6105
|
New conversation
|
|
6085
6106
|
</kr-button>
|
|
6086
6107
|
` : A}
|
|
6087
|
-
${
|
|
6108
|
+
${this.variant === 'floating' ? A : b `
|
|
6088
6109
|
<button
|
|
6089
6110
|
class="header-action"
|
|
6090
6111
|
@click=${this._handleCloseDrawer}
|