@jini-ai/chat 0.6.6 → 0.6.10
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 +129 -1
- 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 +187 -98
- 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 +31 -6
- package/dist/core/durable-runs/ledger-contracts.d.ts +2 -1
- 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.js +54 -32
- 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.d.ts +1 -1
- package/dist/react/components/MessageRow.js +75 -47
- package/dist/react/components/MessageRow.usage.js +16 -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/ToolCallGroup.d.ts +4 -3
- package/dist/react/components/ToolCallGroup.js +7 -5
- 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 +14 -0
- package/dist/react/features/chat-pane/model-options.js +45 -25
- 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 +152 -36
- package/dist/react/features/chat-pane/types.d.ts +19 -9
- 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.d.ts +12 -6
- package/dist/react/tool-call-display.js +53 -24
- package/dist/server/durable-runs/recover.js +132 -80
- 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 +18 -16
|
@@ -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);
|
|
@@ -885,7 +921,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
885
921
|
}
|
|
886
922
|
.jini-chat-pane .jini-composer-workdir-confirm {
|
|
887
923
|
padding: 6px 10px;
|
|
888
|
-
color:
|
|
924
|
+
color: var(--jini-chat-panel);
|
|
889
925
|
white-space: nowrap;
|
|
890
926
|
background: var(--jini-chat-text-strong);
|
|
891
927
|
border: 0;
|
|
@@ -898,34 +934,52 @@ export const CHAT_PANE_STYLES = `
|
|
|
898
934
|
.jini-runtime-spinner,
|
|
899
935
|
.jini-icon-spin { animation: jini-chat-spin .8s linear infinite; }
|
|
900
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. */
|
|
901
940
|
.jini-chat-pane .jini-composer-footer-accessories {
|
|
902
941
|
display: flex;
|
|
903
|
-
margin-left: auto;
|
|
904
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;
|
|
905
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. */
|
|
906
957
|
.jini-chat-pane .jini-composer-send-group {
|
|
907
958
|
display: flex;
|
|
908
959
|
flex-shrink: 0;
|
|
909
960
|
gap: 6px;
|
|
961
|
+
margin-left: auto;
|
|
910
962
|
}
|
|
911
|
-
/*
|
|
912
|
-
|
|
913
|
-
|
|
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. */
|
|
914
968
|
.jini-chat-pane .jini-composer-send {
|
|
915
969
|
display: grid;
|
|
916
970
|
place-items: center;
|
|
917
971
|
width: 32px;
|
|
918
972
|
height: 32px;
|
|
919
973
|
padding: 0;
|
|
920
|
-
color:
|
|
974
|
+
color: var(--jini-chat-panel);
|
|
921
975
|
background: var(--jini-chat-text-strong);
|
|
922
976
|
border: 0;
|
|
923
977
|
border-radius: 8px;
|
|
924
978
|
cursor: pointer;
|
|
925
979
|
}
|
|
926
980
|
.jini-chat-pane .jini-composer-send:disabled {
|
|
927
|
-
color:
|
|
928
|
-
background:
|
|
981
|
+
color: var(--jini-chat-faint);
|
|
982
|
+
background: var(--jini-chat-subtle);
|
|
929
983
|
cursor: default;
|
|
930
984
|
}
|
|
931
985
|
.jini-chat-pane__workdir {
|
|
@@ -1098,40 +1152,100 @@ export const CHAT_PANE_STYLES = `
|
|
|
1098
1152
|
white-space: nowrap;
|
|
1099
1153
|
opacity: .7;
|
|
1100
1154
|
}
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
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;
|
|
1105
1166
|
align-items: center;
|
|
1106
|
-
gap:
|
|
1167
|
+
gap: 4px;
|
|
1107
1168
|
height: 32px;
|
|
1108
1169
|
min-width: 0;
|
|
1109
|
-
padding: 3px
|
|
1110
|
-
color: var(--jini-chat-
|
|
1170
|
+
padding: 3px 6px;
|
|
1171
|
+
color: var(--jini-chat-muted);
|
|
1111
1172
|
background: transparent;
|
|
1112
1173
|
border: 0;
|
|
1113
1174
|
border-radius: 8px;
|
|
1175
|
+
font: inherit;
|
|
1176
|
+
font-size: 13px;
|
|
1114
1177
|
cursor: pointer;
|
|
1115
1178
|
}
|
|
1116
|
-
.jini-runtime-trigger
|
|
1117
|
-
|
|
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. */
|
|
1118
1193
|
.jini-runtime-trigger__copy strong {
|
|
1194
|
+
position: absolute;
|
|
1195
|
+
width: 1px;
|
|
1196
|
+
height: 1px;
|
|
1119
1197
|
overflow: hidden;
|
|
1120
|
-
|
|
1121
|
-
font-size: 11px;
|
|
1122
|
-
font-weight: 650;
|
|
1123
|
-
text-overflow: ellipsis;
|
|
1198
|
+
clip: rect(0 0 0 0);
|
|
1124
1199
|
white-space: nowrap;
|
|
1125
1200
|
}
|
|
1126
|
-
.jini-runtime-trigger__copy small
|
|
1201
|
+
.jini-runtime-trigger__copy small,
|
|
1202
|
+
.jini-runtime-dropup-trigger__label {
|
|
1127
1203
|
overflow: hidden;
|
|
1128
|
-
max-width:
|
|
1129
|
-
|
|
1130
|
-
font-size: 9px;
|
|
1204
|
+
max-width: 180px;
|
|
1205
|
+
font-size: inherit;
|
|
1131
1206
|
text-overflow: ellipsis;
|
|
1132
1207
|
white-space: nowrap;
|
|
1133
1208
|
}
|
|
1134
|
-
.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; }
|
|
1135
1249
|
.jini-runtime-agent-icon.agent-icon { flex: 0 0 auto; object-fit: contain; }
|
|
1136
1250
|
.jini-runtime-agent-icon.agent-icon-mono {
|
|
1137
1251
|
display: inline-block;
|
|
@@ -1168,8 +1282,8 @@ export const CHAT_PANE_STYLES = `
|
|
|
1168
1282
|
background: var(--jini-chat-panel);
|
|
1169
1283
|
border: 1px solid var(--jini-chat-border);
|
|
1170
1284
|
border-radius: 12px;
|
|
1171
|
-
box-shadow: 0 18px 46px rgba(13, 12, 10, .15), 0 2px 8px rgba(13, 12, 10, .06);
|
|
1172
|
-
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);
|
|
1173
1287
|
font-size: 13.5px;
|
|
1174
1288
|
line-height: 1.5;
|
|
1175
1289
|
-webkit-font-smoothing: antialiased;
|
|
@@ -1362,7 +1476,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
1362
1476
|
.jini-chat-pane .op-path,
|
|
1363
1477
|
.jini-chat-pane .op-command,
|
|
1364
1478
|
.jini-chat-pane .op-output {
|
|
1365
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
1479
|
+
font-family: var(--jini-chat-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
1366
1480
|
font-size: 12px;
|
|
1367
1481
|
background: var(--jini-chat-panel);
|
|
1368
1482
|
border: 1px solid var(--jini-chat-border);
|
|
@@ -1447,7 +1561,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
1447
1561
|
background: var(--jini-chat-subtle);
|
|
1448
1562
|
border: 1px solid var(--jini-chat-border);
|
|
1449
1563
|
border-radius: 8px;
|
|
1450
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
1564
|
+
font-family: var(--jini-chat-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
1451
1565
|
font-size: 12.5px;
|
|
1452
1566
|
line-height: 1.5;
|
|
1453
1567
|
}
|
|
@@ -1463,7 +1577,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
1463
1577
|
background: var(--jini-chat-subtle);
|
|
1464
1578
|
border: 1px solid var(--jini-chat-border);
|
|
1465
1579
|
border-radius: 4px;
|
|
1466
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
1580
|
+
font-family: var(--jini-chat-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
1467
1581
|
font-size: .9em;
|
|
1468
1582
|
}
|
|
1469
1583
|
/*
|
|
@@ -1596,7 +1710,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
1596
1710
|
background: var(--jini-chat-panel);
|
|
1597
1711
|
border: 1px solid var(--jini-chat-border);
|
|
1598
1712
|
border-radius: 12px;
|
|
1599
|
-
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));
|
|
1600
1714
|
}
|
|
1601
1715
|
.jini-md-table-modal::backdrop {
|
|
1602
1716
|
background: rgba(0, 0, 0, .4);
|
|
@@ -1641,7 +1755,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
1641
1755
|
background: var(--jini-chat-panel);
|
|
1642
1756
|
border: 1px solid var(--jini-chat-border);
|
|
1643
1757
|
border-radius: 12px;
|
|
1644
|
-
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));
|
|
1645
1759
|
}
|
|
1646
1760
|
.jini-attachment-preview-dialog::backdrop {
|
|
1647
1761
|
background: rgba(0, 0, 0, .4);
|
|
@@ -1697,6 +1811,8 @@ export const CHAT_PANE_STYLES = `
|
|
|
1697
1811
|
margin: auto;
|
|
1698
1812
|
}
|
|
1699
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);
|
|
1700
1816
|
width: 100%;
|
|
1701
1817
|
max-height: calc(80vh - 90px);
|
|
1702
1818
|
margin: 0;
|
|
@@ -1706,7 +1822,7 @@ export const CHAT_PANE_STYLES = `
|
|
|
1706
1822
|
background: var(--jini-chat-subtle);
|
|
1707
1823
|
border: 1px solid var(--jini-chat-border-soft);
|
|
1708
1824
|
border-radius: 8px;
|
|
1709
|
-
font-family:
|
|
1825
|
+
font-family: var(--jini-chat-font-mono);
|
|
1710
1826
|
font-size: 12px;
|
|
1711
1827
|
line-height: 1.5;
|
|
1712
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
|
*
|
|
@@ -305,12 +312,15 @@ export interface ChatPaneProps extends UserTextRedactionOptions {
|
|
|
305
312
|
/**
|
|
306
313
|
* Transcript display choices (a host's chat settings, 2026-10-11), passed straight to
|
|
307
314
|
* `MessageList`: how tool calls show (`'show'` default, `'collapsed'` one line per turn, `'hidden'`
|
|
308
|
-
*
|
|
315
|
+
* hides recovered calls and folds unrecovered failures — see `tool-call-display.ts`), whether the
|
|
316
|
+
* "Done · time · cost" lines show
|
|
309
317
|
* (default `true`), and whether the model's reasoning shows (default `false`).
|
|
310
318
|
*/
|
|
311
319
|
toolCallDisplay?: ToolCallDisplay;
|
|
312
320
|
showUsageLine?: boolean;
|
|
313
321
|
showThinking?: boolean;
|
|
322
|
+
/** Hide prior automatic-usage chips immediately when the host selects Off. Loading policy stays server-owned. */
|
|
323
|
+
agentPluginsMode?: 'auto' | 'ask' | 'off';
|
|
314
324
|
uploadAttachments?: (files: File[], options?: ChatPaneAttachmentUploadOptions) => Promise<ChatAttachment[]>;
|
|
315
325
|
attachmentAccept?: string;
|
|
316
326
|
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
|