@jini-ai/chat 0.6.5 → 0.6.7
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/CHANGELOG.md +12 -0
- package/dist/core/accepted-input.d.ts +54 -0
- package/dist/core/accepted-input.js +165 -0
- package/dist/core/agent-plugin-chat-state.d.ts +43 -0
- package/dist/core/agent-plugin-chat-state.js +48 -0
- package/dist/core/assistant-client/a2ui-action-poster.js +32 -28
- package/dist/core/assistant-client/messages.d.ts +1 -1
- package/dist/core/assistant-client/messages.js +2 -2
- package/dist/core/assistant-client/transport.d.ts +2 -2
- package/dist/core/assistant-client/transport.js +184 -97
- package/dist/core/assistant-content.d.ts +2 -1
- package/dist/core/assistant-content.js +9 -11
- package/dist/core/browser/page-actions.js +4 -2
- package/dist/core/composer-history.d.ts +16 -9
- package/dist/core/composer-history.js +28 -16
- package/dist/core/conversation-title.d.ts +3 -0
- package/dist/core/conversation-title.js +3 -0
- package/dist/core/durable-projection.js +20 -13
- package/dist/core/durable-runs/continuation.d.ts +4 -0
- package/dist/core/durable-runs/continuation.js +35 -6
- package/dist/core/durable-runs/ledger-contracts.d.ts +2 -1
- package/dist/core/durable-runs/policies.d.ts +1 -0
- package/dist/core/durable-runs/policies.js +1 -0
- package/dist/core/durable-runs/ports.d.ts +6 -2
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +2 -0
- package/dist/core/messages.d.ts +2 -0
- package/dist/core/partial-json.d.ts +6 -7
- package/dist/core/partial-json.js +81 -47
- package/dist/core/persistence/title.js +4 -2
- package/dist/core/question-answer.d.ts +23 -0
- package/dist/core/question-answer.js +66 -0
- package/dist/core/question-form/format.d.ts +6 -6
- package/dist/core/question-form/format.js +16 -17
- package/dist/core/question-form/normalize.d.ts +18 -0
- package/dist/core/question-form/normalize.js +112 -122
- package/dist/core/question-form/scan.js +141 -203
- package/dist/core/run-activity.js +62 -49
- package/dist/core/run-events/entry.d.ts +10 -1
- package/dist/core/run-events/entry.js +117 -87
- package/dist/core/todos.d.ts +1 -1
- package/dist/core/todos.js +60 -85
- package/dist/core/tool-events.js +14 -12
- package/dist/core/transcript.js +62 -16
- package/dist/core/turn-usage.d.ts +2 -1
- package/dist/core/turn-usage.js +56 -27
- package/dist/core/user-text-redaction.js +3 -0
- package/dist/core/util/manifest.js +77 -82
- package/dist/core/util/markdown-context.js +51 -53
- package/dist/core/util/parser.js +136 -144
- package/dist/core/util/pointer.js +16 -16
- package/dist/core/util/strip.js +57 -67
- package/dist/core/util/validate.js +15 -17
- package/dist/embed-widget/browser/session-store.js +21 -12
- package/dist/embed-widget/transports/fetch-sse.js +108 -95
- package/dist/embed-widget/vanilla/index.js +81 -70
- package/dist/react/agent-bridge/frontend-session-bridge.js +80 -52
- package/dist/react/components/AttachmentPreviewModal.js +25 -1
- package/dist/react/components/ChatSettingsDialog.d.ts +13 -0
- package/dist/react/components/ChatSettingsDialog.hooks.d.ts +115 -0
- package/dist/react/components/ChatSettingsDialog.hooks.js +40 -0
- package/dist/react/components/ChatSettingsDialog.js +72 -0
- package/dist/react/components/ChatSettingsSegmented.d.ts +18 -0
- package/dist/react/components/ChatSettingsSegmented.js +11 -0
- package/dist/react/components/Composer.d.ts +5 -1
- package/dist/react/components/Composer.js +126 -82
- package/dist/react/components/ConversationList.js +25 -39
- package/dist/react/components/ConversationTitleEditor.d.ts +27 -0
- package/dist/react/components/ConversationTitleEditor.js +54 -0
- package/dist/react/components/Icon.d.ts +1 -1
- package/dist/react/components/Icon.js +25 -45
- package/dist/react/components/Markdown.js +134 -123
- package/dist/react/components/McpUiSurfaceCard.d.ts +2 -2
- package/dist/react/components/McpUiSurfaceCard.js +30 -9
- package/dist/react/components/MessageList.d.ts +13 -13
- package/dist/react/components/MessageList.hooks.d.ts +6 -1
- package/dist/react/components/MessageList.hooks.js +19 -3
- package/dist/react/components/MessageList.js +34 -10
- package/dist/react/components/MessageRow.js +48 -32
- package/dist/react/components/MessageRow.usage.d.ts +5 -2
- package/dist/react/components/MessageRow.usage.js +20 -11
- package/dist/react/components/MidRunUserMessage.js +16 -3
- package/dist/react/components/QuestionForm.js +148 -76
- package/dist/react/components/QuestionsPanel.js +1 -1
- package/dist/react/components/TodoCard.js +12 -6
- package/dist/react/components/ToolCard.js +47 -40
- package/dist/react/components/composer-discovery.js +6 -1
- package/dist/react/components/mcp-ui-surface-state.d.ts +6 -11
- package/dist/react/components/mcp-ui-surface-state.js +23 -8
- package/dist/react/ext-event-renderer-registry.d.ts +8 -0
- package/dist/react/ext-event-renderer-registry.js +5 -2
- package/dist/react/features/chat-pane/components/AgentPluginUsage.d.ts +7 -0
- package/dist/react/features/chat-pane/components/AgentPluginUsage.js +45 -0
- package/dist/react/features/chat-pane/components/AgentRuntimePicker.js +55 -19
- package/dist/react/features/chat-pane/components/ChatPane.d.ts +1 -1
- package/dist/react/features/chat-pane/components/ChatPane.js +192 -74
- package/dist/react/features/chat-pane/components/RuntimeDropUp.d.ts +29 -0
- package/dist/react/features/chat-pane/components/RuntimeDropUp.js +45 -0
- package/dist/react/features/chat-pane/create-daemon-attachment-uploader.js +80 -47
- package/dist/react/features/chat-pane/create-mcp-ui-tool-caller.js +44 -40
- package/dist/react/features/chat-pane/create-mid-run-message-poster.d.ts +6 -6
- package/dist/react/features/chat-pane/create-mid-run-message-poster.js +8 -8
- package/dist/react/features/chat-pane/create-typed-answer-poster.d.ts +3 -3
- package/dist/react/features/chat-pane/create-typed-answer-poster.js +3 -3
- package/dist/react/features/chat-pane/hooks/useAgentRuntimePicker.hooks.d.ts +6 -1
- package/dist/react/features/chat-pane/hooks/useAgentRuntimePicker.hooks.js +11 -5
- package/dist/react/features/chat-pane/hooks/useChatPane.hooks.d.ts +12 -7
- package/dist/react/features/chat-pane/hooks/useChatPane.hooks.js +340 -149
- package/dist/react/features/chat-pane/hooks/useChatPaneControlsHeight.hooks.js +7 -6
- package/dist/react/features/chat-pane/hooks/useChatPaneNewTabLinks.hooks.js +28 -10
- package/dist/react/features/chat-pane/hooks/useChatPaneRuntimeInventory.hooks.d.ts +3 -3
- package/dist/react/features/chat-pane/hooks/useChatPaneRuntimeInventory.hooks.js +60 -12
- package/dist/react/features/chat-pane/hooks/useRuntimeDropUp.hooks.d.ts +49 -0
- package/dist/react/features/chat-pane/hooks/useRuntimeDropUp.hooks.js +143 -0
- package/dist/react/features/chat-pane/model-options.d.ts +18 -1
- package/dist/react/features/chat-pane/model-options.js +49 -20
- package/dist/react/features/chat-pane/rules.d.ts +8 -9
- package/dist/react/features/chat-pane/rules.js +84 -46
- package/dist/react/features/chat-pane/styles.d.ts +1 -1
- package/dist/react/features/chat-pane/styles.js +156 -37
- package/dist/react/features/chat-pane/types.d.ts +17 -8
- package/dist/react/hooks/assistant-chats.js +12 -5
- package/dist/react/hooks/composer-draft-cache.js +116 -118
- package/dist/react/hooks/composer-history-storage.js +5 -5
- package/dist/react/hooks/fab-position.js +7 -4
- package/dist/react/hooks/useAnsweredCards.d.ts +21 -4
- package/dist/react/hooks/useAnsweredCards.js +38 -11
- package/dist/react/hooks/useArtifactStream.js +28 -22
- package/dist/react/hooks/useComposer.d.ts +20 -0
- package/dist/react/hooks/useComposer.js +22 -9
- package/dist/react/hooks/useComposerHistory.hooks.d.ts +6 -1
- package/dist/react/hooks/useComposerHistory.hooks.js +39 -19
- package/dist/react/hooks/useComposerHistoryKeys.hooks.js +24 -14
- package/dist/react/hooks/useConversation.d.ts +7 -0
- package/dist/react/hooks/useConversation.js +23 -10
- package/dist/react/hooks/useExtEventGroups.js +39 -39
- package/dist/react/hooks/useQuestionForms.js +21 -26
- package/dist/react/hooks/useRunStream.js +10 -2
- package/dist/react/index.d.ts +7 -1
- package/dist/react/index.js +9 -0
- package/dist/react/message-blocks.d.ts +6 -4
- package/dist/react/message-blocks.js +94 -72
- package/dist/react/slots.d.ts +2 -2
- package/dist/react/tool-call-display.js +19 -17
- package/dist/server/durable-runs/recover.d.ts +1 -1
- package/dist/server/durable-runs/recover.js +139 -76
- package/dist/server/run-finalizer/entry.js +25 -15
- package/dist/store/legacy/sqlite/conversations.d.ts +11 -11
- package/dist/store/legacy/sqlite/conversations.js +69 -98
- package/dist/store/legacy/sqlite/messages.d.ts +10 -2
- package/dist/store/legacy/sqlite/messages.js +113 -71
- package/dist/store/runtime/chat-history-store.js +9 -3
- package/dist/store/runtime/durable-run-store.d.ts +2 -2
- package/dist/store/runtime/durable-run-store.js +165 -117
- package/dist/store/runtime/history-tools.js +118 -82
- package/dist/store/runtime/run-ledger.d.ts +4 -1
- package/dist/store/runtime/run-ledger.js +56 -16
- package/dist/store/sql/cursor.js +38 -18
- package/dist/store/sql/store.d.ts +18 -0
- package/dist/store/sql/store.js +46 -15
- package/package.json +12 -10
|
@@ -37,7 +37,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
37
37
|
overflow: clip;
|
|
38
38
|
color: var(--jini-chat-text);
|
|
39
39
|
background: var(--jini-chat-bg);
|
|
40
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei UI", "Noto Sans", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
40
|
+
font-family: var(--jini-chat-font-body, -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei UI", "Noto Sans", Roboto, "Helvetica Neue", Arial, sans-serif);
|
|
41
41
|
font-size: 13.5px;
|
|
42
42
|
line-height: 1.5;
|
|
43
43
|
-webkit-font-smoothing: antialiased;
|
|
@@ -61,7 +61,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
61
61
|
display: block;
|
|
62
62
|
margin-bottom: 4px;
|
|
63
63
|
color: var(--jini-chat-muted);
|
|
64
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
64
|
+
font-family: var(--jini-chat-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
65
65
|
font-size: 10px;
|
|
66
66
|
letter-spacing: .1em;
|
|
67
67
|
text-transform: uppercase;
|
|
@@ -109,6 +109,39 @@ export const CHAT_PANE_STYLES = `
|
|
|
109
109
|
padding: 20px 22px calc(var(--jini-chat-controls-height, 240px) + 24px);
|
|
110
110
|
scrollbar-width: thin;
|
|
111
111
|
}
|
|
112
|
+
/*
|
|
113
|
+
* 'Jump to latest' (MessageList.tsx's JumpToLatest): a zero-height sticky last child, so it floats
|
|
114
|
+
* centred just above the composer overlay without taking layout space. Sticky offsets measure from
|
|
115
|
+
* the scrollport edge, not the padding, hence the controls height in 'bottom'.
|
|
116
|
+
*/
|
|
117
|
+
.jini-message-list__jump {
|
|
118
|
+
position: sticky;
|
|
119
|
+
bottom: calc(var(--jini-chat-controls-height, 240px) + 8px);
|
|
120
|
+
height: 0;
|
|
121
|
+
display: flex;
|
|
122
|
+
justify-content: center;
|
|
123
|
+
align-items: flex-end;
|
|
124
|
+
z-index: 2;
|
|
125
|
+
pointer-events: none;
|
|
126
|
+
}
|
|
127
|
+
.jini-message-list__jump-btn {
|
|
128
|
+
display: inline-flex;
|
|
129
|
+
align-items: center;
|
|
130
|
+
gap: 6px;
|
|
131
|
+
padding: 5px 12px;
|
|
132
|
+
border: 1px solid var(--jini-chat-border);
|
|
133
|
+
border-radius: 999px;
|
|
134
|
+
background: var(--jini-chat-panel);
|
|
135
|
+
color: var(--jini-chat-muted);
|
|
136
|
+
box-shadow: var(--jini-chat-popover-shadow);
|
|
137
|
+
font-size: 12px;
|
|
138
|
+
line-height: 1.2;
|
|
139
|
+
white-space: nowrap;
|
|
140
|
+
cursor: pointer;
|
|
141
|
+
pointer-events: auto;
|
|
142
|
+
}
|
|
143
|
+
.jini-message-list__jump-btn:hover { color: var(--jini-chat-text-strong); }
|
|
144
|
+
.jini-message-list__jump-btn:focus-visible { outline: 2px solid var(--jini-chat-accent); outline-offset: 2px; }
|
|
112
145
|
.jini-chat-pane .jini-message {
|
|
113
146
|
margin-bottom: 20px;
|
|
114
147
|
color: var(--jini-chat-text);
|
|
@@ -152,6 +185,9 @@ export const CHAT_PANE_STYLES = `
|
|
|
152
185
|
padding: 10px 13px;
|
|
153
186
|
width: fit-content;
|
|
154
187
|
max-width: 88%;
|
|
188
|
+
/* MOVE: Answers may contain long labels or pasted URLs; wrap them within narrow chat panes. */
|
|
189
|
+
white-space: pre-wrap;
|
|
190
|
+
overflow-wrap: anywhere;
|
|
155
191
|
/* User bubbles share this style at every nesting depth, regardless of message length. */
|
|
156
192
|
background: var(--jini-chat-user-bubble, #1a1b1c);
|
|
157
193
|
color: var(--jini-chat-user-bubble-ink, #fff);
|
|
@@ -645,8 +681,11 @@ export const CHAT_PANE_STYLES = `
|
|
|
645
681
|
}
|
|
646
682
|
/* Phones: the 25px "x" gets an invisible 44px tap area; the chip keeps its size. The area ends at the
|
|
647
683
|
chip's bottom edge and grows up into the tray's 8px top padding / row gap, because growing down
|
|
648
|
-
past the last row would make the 88px tray scroll by a few pixels.
|
|
684
|
+
past the last row would make the 88px tray scroll by a few pixels. Rows are 8px apart here, not
|
|
685
|
+
6: at a 42px row pitch the second row's area covered the bottom 2.5px of the first row's, leaving
|
|
686
|
+
the top row a 41.5px target. 8px top padding + two 36px rows + an 8px gap is exactly the 88px cap. */
|
|
649
687
|
@media (max-width: 640px), (pointer: coarse) {
|
|
688
|
+
.jini-chat-pane .jini-attachment-tray { row-gap: 8px; }
|
|
650
689
|
.jini-chat-pane .jini-attachment-remove { position: relative; }
|
|
651
690
|
.jini-chat-pane .jini-attachment-remove::before {
|
|
652
691
|
content: '';
|
|
@@ -882,7 +921,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
882
921
|
}
|
|
883
922
|
.jini-chat-pane .jini-composer-workdir-confirm {
|
|
884
923
|
padding: 6px 10px;
|
|
885
|
-
color:
|
|
924
|
+
color: var(--jini-chat-panel);
|
|
886
925
|
white-space: nowrap;
|
|
887
926
|
background: var(--jini-chat-text-strong);
|
|
888
927
|
border: 0;
|
|
@@ -895,34 +934,52 @@ export const CHAT_PANE_STYLES = `
|
|
|
895
934
|
.jini-runtime-spinner,
|
|
896
935
|
.jini-icon-spin { animation: jini-chat-spin .8s linear infinite; }
|
|
897
936
|
@keyframes jini-chat-spin { to { transform: rotate(360deg); } }
|
|
937
|
+
/* The model/effort cluster sits at the trailing edge beside send (owner, 2026-10-18); the "+"
|
|
938
|
+
stays at the start. The auto margin takes the free space, and gives it back first when a narrow
|
|
939
|
+
bar needs the room for the model label. */
|
|
898
940
|
.jini-chat-pane .jini-composer-footer-accessories {
|
|
899
941
|
display: flex;
|
|
900
|
-
margin-left: auto;
|
|
901
942
|
min-width: 0;
|
|
943
|
+
margin-left: auto;
|
|
944
|
+
}
|
|
945
|
+
/* Basis 0: the hint takes only the room the runtime row leaves and wraps into it, instead of
|
|
946
|
+
claiming its one-line width and squeezing the picker under its icon/effort labels. */
|
|
947
|
+
.jini-chat-pane .jini-composer-send-blocker {
|
|
948
|
+
flex: 1 1 0;
|
|
949
|
+
align-self: center;
|
|
950
|
+
margin-right: 8px;
|
|
951
|
+
color: var(--jini-chat-muted);
|
|
952
|
+
font-size: 12px;
|
|
902
953
|
}
|
|
954
|
+
/* Always pushed to the trailing edge. This also covers a footer with no attach/accessory controls
|
|
955
|
+
before the send group (a public visitor chat), which would otherwise leave the lone send button
|
|
956
|
+
at the start under the footer's space-between. */
|
|
903
957
|
.jini-chat-pane .jini-composer-send-group {
|
|
904
958
|
display: flex;
|
|
905
959
|
flex-shrink: 0;
|
|
906
960
|
gap: 6px;
|
|
961
|
+
margin-left: auto;
|
|
907
962
|
}
|
|
908
|
-
/*
|
|
909
|
-
|
|
910
|
-
|
|
963
|
+
/* After the cluster, the send group sits right beside it instead of splitting the free space. */
|
|
964
|
+
.jini-chat-pane .jini-composer-footer-accessories ~ .jini-composer-send-group { margin-left: 0; }
|
|
965
|
+
/* Inverse ink: the fill is the strong text colour, so the icon takes the panel colour rather than a
|
|
966
|
+
fixed white. A host dark theme flips text-strong to near-white, and fixed white icons then drew a
|
|
967
|
+
blank white square (owner report, 2026-10-21). Disabled uses the theme's subtle/faint pair too. */
|
|
911
968
|
.jini-chat-pane .jini-composer-send {
|
|
912
969
|
display: grid;
|
|
913
970
|
place-items: center;
|
|
914
971
|
width: 32px;
|
|
915
972
|
height: 32px;
|
|
916
973
|
padding: 0;
|
|
917
|
-
color:
|
|
974
|
+
color: var(--jini-chat-panel);
|
|
918
975
|
background: var(--jini-chat-text-strong);
|
|
919
976
|
border: 0;
|
|
920
977
|
border-radius: 8px;
|
|
921
978
|
cursor: pointer;
|
|
922
979
|
}
|
|
923
980
|
.jini-chat-pane .jini-composer-send:disabled {
|
|
924
|
-
color:
|
|
925
|
-
background:
|
|
981
|
+
color: var(--jini-chat-faint);
|
|
982
|
+
background: var(--jini-chat-subtle);
|
|
926
983
|
cursor: default;
|
|
927
984
|
}
|
|
928
985
|
.jini-chat-pane__workdir {
|
|
@@ -1095,40 +1152,100 @@ export const CHAT_PANE_STYLES = `
|
|
|
1095
1152
|
white-space: nowrap;
|
|
1096
1153
|
opacity: .7;
|
|
1097
1154
|
}
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1155
|
+
/* Composer-bar runtime row: [agent icon] [model ⌄] [effort ⌄] -- compact, borderless, muted text.
|
|
1156
|
+
The icon opens the runtime popover; model and effort each open a drop-up (RuntimeDropUp). */
|
|
1157
|
+
.jini-runtime-picker {
|
|
1158
|
+
position: relative;
|
|
1159
|
+
display: flex;
|
|
1160
|
+
align-items: center;
|
|
1161
|
+
min-width: 0;
|
|
1162
|
+
}
|
|
1163
|
+
.jini-runtime-trigger,
|
|
1164
|
+
.jini-runtime-dropup-trigger {
|
|
1165
|
+
display: inline-flex;
|
|
1102
1166
|
align-items: center;
|
|
1103
|
-
gap:
|
|
1167
|
+
gap: 4px;
|
|
1104
1168
|
height: 32px;
|
|
1105
1169
|
min-width: 0;
|
|
1106
|
-
padding: 3px
|
|
1107
|
-
color: var(--jini-chat-
|
|
1170
|
+
padding: 3px 6px;
|
|
1171
|
+
color: var(--jini-chat-muted);
|
|
1108
1172
|
background: transparent;
|
|
1109
1173
|
border: 0;
|
|
1110
1174
|
border-radius: 8px;
|
|
1175
|
+
font: inherit;
|
|
1176
|
+
font-size: 13px;
|
|
1111
1177
|
cursor: pointer;
|
|
1112
1178
|
}
|
|
1113
|
-
.jini-runtime-trigger
|
|
1114
|
-
|
|
1179
|
+
.jini-runtime-trigger { gap: 6px; padding: 3px 4px; }
|
|
1180
|
+
/* Local mode's trigger is the icon alone, so it has nothing to give way: shrunk under the shared
|
|
1181
|
+
\`min-width: 0\` on a narrow bar, the 22px icon spilled over the model/effort labels beside it
|
|
1182
|
+
(owner report, 2026-10-21). API mode keeps shrinking -- its model label ellipsizes. */
|
|
1183
|
+
.jini-runtime-trigger--icon-only { flex: none; }
|
|
1184
|
+
.jini-runtime-trigger:hover,
|
|
1185
|
+
.jini-runtime-dropup-trigger:hover,
|
|
1186
|
+
.jini-runtime-dropup-trigger[aria-expanded="true"] { color: var(--jini-chat-text); background: var(--jini-chat-subtle); }
|
|
1187
|
+
.jini-runtime-trigger:focus-visible,
|
|
1188
|
+
.jini-runtime-dropup-trigger:focus-visible { outline: 2px solid var(--jini-chat-accent); outline-offset: 1px; }
|
|
1189
|
+
/* 'contents' so the hidden name (absolutely positioned) adds no flex gap beside the icon-only
|
|
1190
|
+
local trigger, and the API-mode model label is a direct, shrinkable flex item. */
|
|
1191
|
+
.jini-runtime-trigger__copy { display: contents; }
|
|
1192
|
+
/* Kept in the text (see the component), not shown: the icon already names the agent. */
|
|
1115
1193
|
.jini-runtime-trigger__copy strong {
|
|
1194
|
+
position: absolute;
|
|
1195
|
+
width: 1px;
|
|
1196
|
+
height: 1px;
|
|
1116
1197
|
overflow: hidden;
|
|
1117
|
-
|
|
1118
|
-
font-size: 11px;
|
|
1119
|
-
font-weight: 650;
|
|
1120
|
-
text-overflow: ellipsis;
|
|
1198
|
+
clip: rect(0 0 0 0);
|
|
1121
1199
|
white-space: nowrap;
|
|
1122
1200
|
}
|
|
1123
|
-
.jini-runtime-trigger__copy small
|
|
1201
|
+
.jini-runtime-trigger__copy small,
|
|
1202
|
+
.jini-runtime-dropup-trigger__label {
|
|
1124
1203
|
overflow: hidden;
|
|
1125
|
-
max-width:
|
|
1126
|
-
|
|
1127
|
-
font-size: 9px;
|
|
1204
|
+
max-width: 180px;
|
|
1205
|
+
font-size: inherit;
|
|
1128
1206
|
text-overflow: ellipsis;
|
|
1129
1207
|
white-space: nowrap;
|
|
1130
1208
|
}
|
|
1131
|
-
.jini-runtime-trigger__chevron {
|
|
1209
|
+
.jini-runtime-trigger__chevron { flex: none; }
|
|
1210
|
+
/* The effort label is short; the model label is the one that gives way on a narrow bar. */
|
|
1211
|
+
.jini-runtime-dropup-trigger--effort { flex: none; }
|
|
1212
|
+
.jini-runtime-dropup {
|
|
1213
|
+
display: flex;
|
|
1214
|
+
flex-direction: column;
|
|
1215
|
+
gap: 1px;
|
|
1216
|
+
padding: 4px;
|
|
1217
|
+
color: var(--jini-chat-text);
|
|
1218
|
+
background: var(--jini-chat-panel);
|
|
1219
|
+
border: 1px solid var(--jini-chat-border);
|
|
1220
|
+
border-radius: 10px;
|
|
1221
|
+
box-shadow: var(--jini-chat-popover-shadow, 0 18px 46px rgba(13, 12, 10, .15), 0 2px 8px rgba(13, 12, 10, .06));
|
|
1222
|
+
font-size: 13px;
|
|
1223
|
+
line-height: 1.4;
|
|
1224
|
+
}
|
|
1225
|
+
.jini-runtime-dropup__note {
|
|
1226
|
+
padding: 4px 10px 6px;
|
|
1227
|
+
color: var(--jini-chat-muted);
|
|
1228
|
+
font-size: 11.5px;
|
|
1229
|
+
}
|
|
1230
|
+
.jini-runtime-dropup__item {
|
|
1231
|
+
display: flex;
|
|
1232
|
+
align-items: center;
|
|
1233
|
+
gap: 8px;
|
|
1234
|
+
width: 100%;
|
|
1235
|
+
min-height: 32px;
|
|
1236
|
+
padding: 6px 10px;
|
|
1237
|
+
color: inherit;
|
|
1238
|
+
background: transparent;
|
|
1239
|
+
border: 0;
|
|
1240
|
+
border-radius: 6px;
|
|
1241
|
+
font: inherit;
|
|
1242
|
+
text-align: left;
|
|
1243
|
+
cursor: pointer;
|
|
1244
|
+
}
|
|
1245
|
+
.jini-runtime-dropup__item:hover,
|
|
1246
|
+
.jini-runtime-dropup__item:focus-visible { background: var(--jini-chat-subtle); outline: none; }
|
|
1247
|
+
.jini-runtime-dropup__item.is-active { font-weight: 600; }
|
|
1248
|
+
.jini-runtime-dropup__item-label { flex: 1; min-width: 0; overflow-wrap: anywhere; }
|
|
1132
1249
|
.jini-runtime-agent-icon.agent-icon { flex: 0 0 auto; object-fit: contain; }
|
|
1133
1250
|
.jini-runtime-agent-icon.agent-icon-mono {
|
|
1134
1251
|
display: inline-block;
|
|
@@ -1165,8 +1282,8 @@ export const CHAT_PANE_STYLES = `
|
|
|
1165
1282
|
background: var(--jini-chat-panel);
|
|
1166
1283
|
border: 1px solid var(--jini-chat-border);
|
|
1167
1284
|
border-radius: 12px;
|
|
1168
|
-
box-shadow: 0 18px 46px rgba(13, 12, 10, .15), 0 2px 8px rgba(13, 12, 10, .06);
|
|
1169
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei UI", "Noto Sans", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
1285
|
+
box-shadow: var(--jini-chat-popover-shadow, 0 18px 46px rgba(13, 12, 10, .15), 0 2px 8px rgba(13, 12, 10, .06));
|
|
1286
|
+
font-family: var(--jini-chat-font-body, -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei UI", "Noto Sans", Roboto, "Helvetica Neue", Arial, sans-serif);
|
|
1170
1287
|
font-size: 13.5px;
|
|
1171
1288
|
line-height: 1.5;
|
|
1172
1289
|
-webkit-font-smoothing: antialiased;
|
|
@@ -1359,7 +1476,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
1359
1476
|
.jini-chat-pane .op-path,
|
|
1360
1477
|
.jini-chat-pane .op-command,
|
|
1361
1478
|
.jini-chat-pane .op-output {
|
|
1362
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
1479
|
+
font-family: var(--jini-chat-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
1363
1480
|
font-size: 12px;
|
|
1364
1481
|
background: var(--jini-chat-panel);
|
|
1365
1482
|
border: 1px solid var(--jini-chat-border);
|
|
@@ -1444,7 +1561,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
1444
1561
|
background: var(--jini-chat-subtle);
|
|
1445
1562
|
border: 1px solid var(--jini-chat-border);
|
|
1446
1563
|
border-radius: 8px;
|
|
1447
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
1564
|
+
font-family: var(--jini-chat-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
1448
1565
|
font-size: 12.5px;
|
|
1449
1566
|
line-height: 1.5;
|
|
1450
1567
|
}
|
|
@@ -1460,7 +1577,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
1460
1577
|
background: var(--jini-chat-subtle);
|
|
1461
1578
|
border: 1px solid var(--jini-chat-border);
|
|
1462
1579
|
border-radius: 4px;
|
|
1463
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
1580
|
+
font-family: var(--jini-chat-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
1464
1581
|
font-size: .9em;
|
|
1465
1582
|
}
|
|
1466
1583
|
/*
|
|
@@ -1593,7 +1710,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
1593
1710
|
background: var(--jini-chat-panel);
|
|
1594
1711
|
border: 1px solid var(--jini-chat-border);
|
|
1595
1712
|
border-radius: 12px;
|
|
1596
|
-
box-shadow: 0 18px 46px rgba(13, 12, 10, .15), 0 2px 8px rgba(13, 12, 10, .06);
|
|
1713
|
+
box-shadow: var(--jini-chat-popover-shadow, 0 18px 46px rgba(13, 12, 10, .15), 0 2px 8px rgba(13, 12, 10, .06));
|
|
1597
1714
|
}
|
|
1598
1715
|
.jini-md-table-modal::backdrop {
|
|
1599
1716
|
background: rgba(0, 0, 0, .4);
|
|
@@ -1638,7 +1755,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
1638
1755
|
background: var(--jini-chat-panel);
|
|
1639
1756
|
border: 1px solid var(--jini-chat-border);
|
|
1640
1757
|
border-radius: 12px;
|
|
1641
|
-
box-shadow: 0 18px 46px rgba(13, 12, 10, .15), 0 2px 8px rgba(13, 12, 10, .06);
|
|
1758
|
+
box-shadow: var(--jini-chat-popover-shadow, 0 18px 46px rgba(13, 12, 10, .15), 0 2px 8px rgba(13, 12, 10, .06));
|
|
1642
1759
|
}
|
|
1643
1760
|
.jini-attachment-preview-dialog::backdrop {
|
|
1644
1761
|
background: rgba(0, 0, 0, .4);
|
|
@@ -1694,6 +1811,8 @@ export const CHAT_PANE_STYLES = `
|
|
|
1694
1811
|
margin: auto;
|
|
1695
1812
|
}
|
|
1696
1813
|
.jini-attachment-preview-text {
|
|
1814
|
+
/* Preserve this preview's wider fallback stack when the host does not supply a chat font. */
|
|
1815
|
+
--jini-chat-font-mono: var(--jini-theme-chat-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
1697
1816
|
width: 100%;
|
|
1698
1817
|
max-height: calc(80vh - 90px);
|
|
1699
1818
|
margin: 0;
|
|
@@ -1703,7 +1822,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
1703
1822
|
background: var(--jini-chat-subtle);
|
|
1704
1823
|
border: 1px solid var(--jini-chat-border-soft);
|
|
1705
1824
|
border-radius: 8px;
|
|
1706
|
-
font-family:
|
|
1825
|
+
font-family: var(--jini-chat-font-mono);
|
|
1707
1826
|
font-size: 12px;
|
|
1708
1827
|
line-height: 1.5;
|
|
1709
1828
|
white-space: pre-wrap;
|
|
@@ -66,6 +66,10 @@ export interface ChatPaneAgentSelection {
|
|
|
66
66
|
/** Host I/O effects used by the package-owned runtime inventory controller. */
|
|
67
67
|
export interface ChatPaneRuntimeAccess {
|
|
68
68
|
listAgents: () => Promise<readonly ChatPaneAgent[]>;
|
|
69
|
+
/** Earliest time a cached inventory read can refresh (epoch ms); read after listAgents settles.
|
|
70
|
+
* Pending retries honor this deadline so a remounted pane does not spend its retry budget on
|
|
71
|
+
* cached answers. Omit for hosts without a cooldown. Example: () => cachedInventory.expiresAt. */
|
|
72
|
+
getAgentsRefreshAt?: () => number | undefined;
|
|
69
73
|
rescanAgents: () => Promise<readonly ChatPaneAgent[]>;
|
|
70
74
|
daemonOnline: () => Promise<boolean>;
|
|
71
75
|
}
|
|
@@ -177,10 +181,11 @@ export type DeliverTypedAnswer = ((input: {
|
|
|
177
181
|
* any more (it is ending); `'failed'` — the host could not tell (network error, unexpected status).
|
|
178
182
|
*/
|
|
179
183
|
export type MidRunMessageDelivery = 'delivered' | 'unsupported' | 'not-running' | 'failed';
|
|
180
|
-
/** Delivers
|
|
184
|
+
/** Delivers a complete turn to the live agent; unsupported attachments must reject the whole turn. */
|
|
181
185
|
export type DeliverMidRunMessage = (input: {
|
|
182
186
|
runId: string;
|
|
183
187
|
text: string;
|
|
188
|
+
attachments?: readonly ChatAttachment[];
|
|
184
189
|
}) => Promise<MidRunMessageDelivery>;
|
|
185
190
|
export interface ChatPaneProps extends UserTextRedactionOptions {
|
|
186
191
|
transport: ChatTransport;
|
|
@@ -217,6 +222,8 @@ export interface ChatPaneProps extends UserTextRedactionOptions {
|
|
|
217
222
|
composerHistoryScope?: string;
|
|
218
223
|
/** Optional storage effects; omitted uses bounded browser storage with memory fallback. */
|
|
219
224
|
composerHistoryStorage?: ComposerHistoryStoragePort;
|
|
225
|
+
/** Recall retention; defaults to 100. */
|
|
226
|
+
composerHistoryCap?: number;
|
|
220
227
|
/**
|
|
221
228
|
* Confirms which previously staged attachments still exist, so a draft restored after a reload
|
|
222
229
|
* never shows a chip for a file the backend has since garbage-collected — that looks intact and
|
|
@@ -241,19 +248,19 @@ export interface ChatPaneProps extends UserTextRedactionOptions {
|
|
|
241
248
|
* Called instead of queueing when the human types while the running agent is holding a question
|
|
242
249
|
* open in the transcript (an interactive surface whose call to `deliverTypedAnswer.toolName` has
|
|
243
250
|
* not returned — `isAwaitingTypedAnswer`) and the turn carries no attachments. `'delivered'` clears the draft
|
|
244
|
-
* (only if unchanged since it went out)
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
* human clears it or picks "Send as a new message" (`useChatPane`'s `sendAsNewMessage`).
|
|
251
|
+
* (only if unchanged since it went out). A definitive `'not-pending'` refusal falls back once to
|
|
252
|
+
* the ordinary message queue without a notice; a failure or throw retains the draft with a notice.
|
|
253
|
+
* Terminal runs and answered or superseded cards do not accept typed answers.
|
|
248
254
|
*
|
|
249
255
|
* Omit it and typing while a run streams queues exactly as before.
|
|
250
256
|
*/
|
|
251
257
|
deliverTypedAnswer?: DeliverTypedAnswer;
|
|
252
258
|
/**
|
|
253
|
-
* Called instead of queueing when the human sends
|
|
259
|
+
* Called instead of queueing when the human sends a message while a run streams, so
|
|
254
260
|
* the message reaches the running agent now rather than after it finishes. The draft clears at
|
|
255
|
-
* once. `'delivered'` leaves the run going; `'unsupported'`
|
|
256
|
-
* the
|
|
261
|
+
* once. `'delivered'` leaves the run going; `'unsupported'` queues attachment turns until the
|
|
262
|
+
* reply finishes, or stops the run for a text-only turn (a resuming agent keeps its session).
|
|
263
|
+
* `'not-running'`, `'failed'` or a throw
|
|
257
264
|
* queue it behind the ending run. Never silently dropped. A held-open question still goes to
|
|
258
265
|
* {@link deliverTypedAnswer} first.
|
|
259
266
|
*
|
|
@@ -311,6 +318,8 @@ export interface ChatPaneProps extends UserTextRedactionOptions {
|
|
|
311
318
|
toolCallDisplay?: ToolCallDisplay;
|
|
312
319
|
showUsageLine?: boolean;
|
|
313
320
|
showThinking?: boolean;
|
|
321
|
+
/** Hide prior automatic-usage chips immediately when the host selects Off. Loading policy stays server-owned. */
|
|
322
|
+
agentPluginsMode?: 'auto' | 'ask' | 'off';
|
|
314
323
|
uploadAttachments?: (files: File[], options?: ChatPaneAttachmentUploadOptions) => Promise<ChatAttachment[]>;
|
|
315
324
|
attachmentAccept?: string;
|
|
316
325
|
disabled?: boolean;
|
|
@@ -143,13 +143,20 @@ export function createAssistantChatsClient({ ports }, _options = {}) {
|
|
|
143
143
|
* {@link attemptSave}.
|
|
144
144
|
*
|
|
145
145
|
* Never rejects, so a caller can treat the result as data rather than wrapping every call.
|
|
146
|
+
*
|
|
147
|
+
* A `do…while` on the attempt's own verdict rather than `for (;;)` with an inner `return`: the
|
|
148
|
+
* unconditional loop had an exit path no input could ever reach (it only ever left by `return`),
|
|
149
|
+
* while this loop exits exactly when an attempt is done. Termination is unchanged — every
|
|
150
|
+
* attempt past the end of the delay ladder is done.
|
|
146
151
|
*/
|
|
147
152
|
async function saveWithRetry(port, conversationId, message, isDisposed) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
+
let attempt = 0;
|
|
154
|
+
let result;
|
|
155
|
+
do {
|
|
156
|
+
result = await attemptSave(port, conversationId, message, attempt, isDisposed);
|
|
157
|
+
attempt += 1;
|
|
158
|
+
} while (!result.done);
|
|
159
|
+
return result.outcome;
|
|
153
160
|
}
|
|
154
161
|
/**
|
|
155
162
|
* Decides what a settled batch of message-save outcomes means for `flush`'s bookkeeping: which
|