anentrypoint-design 0.0.462 → 0.0.463
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/247420.js +20 -20
- package/package.json +1 -1
- package/src/components/freddie/pages-chat.js +30 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.463",
|
|
4
4
|
"description": "247420 design system SDK — webjsx + modified ripple-ui, single-file ESM bundle for reproducible use of the AnEntrypoint design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/247420.js",
|
|
@@ -86,13 +86,30 @@ function applyEnvelope(msgs, env, sendApprove) {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
export const chat = makePage((ctx) => {
|
|
89
|
-
Object.assign(ctx.state, { loading: false, messages: [], draft: '', busy: false, error: null, sessionId: null, ws: null, conn: 'closed', sessions: [] });
|
|
89
|
+
Object.assign(ctx.state, { loading: false, messages: [], draft: '', busy: false, error: null, sessionId: null, ws: null, conn: 'closed', sessions: [], staged: [] });
|
|
90
90
|
|
|
91
91
|
// Session picker (kimi web's sessions sidebar, compact form): recent
|
|
92
92
|
// conversations from /api/sessions, needsInput badges included. Picking
|
|
93
93
|
// one reconnects the WS under that id and rebuilds from server replay.
|
|
94
94
|
api('/api/sessions').then(rows => { ctx.state.sessions = Array.isArray(rows) ? rows : []; ctx.rerender(); }).catch(() => { /* swallow: picker degrades to new-chat-only */ });
|
|
95
95
|
|
|
96
|
+
// File upload (kimi web parity): files are staged to disk via the gui-agent
|
|
97
|
+
// endpoint and ride the next prompt frame as path references — the agent
|
|
98
|
+
// reads them with its file tools, so no model-capability negotiation here.
|
|
99
|
+
async function attachFiles(fileList) {
|
|
100
|
+
const st = ctx.state;
|
|
101
|
+
if (!st.sessionId) st.sessionId = newSessionId();
|
|
102
|
+
for (const file of fileList || []) {
|
|
103
|
+
try {
|
|
104
|
+
const dataUrl = await new Promise((res, rej) => { const r = new FileReader(); r.onload = () => res(r.result); r.onerror = rej; r.readAsDataURL(file); });
|
|
105
|
+
const base64 = String(dataUrl).split(',')[1] || '';
|
|
106
|
+
const r = await api('/api/sessions/' + encodeURIComponent(st.sessionId) + '/files', { method: 'POST', body: { name: file.name, contentBase64: base64 } });
|
|
107
|
+
if (r && r.path) { st.staged = [...st.staged, { name: r.name || file.name, path: r.path }]; }
|
|
108
|
+
} catch (e) { ctx.set({ error: 'upload failed: ' + (e && e.message || e) }); }
|
|
109
|
+
}
|
|
110
|
+
ctx.rerender();
|
|
111
|
+
}
|
|
112
|
+
|
|
96
113
|
function switchSession(id) {
|
|
97
114
|
const st = ctx.state;
|
|
98
115
|
if (!id || id === st.sessionId) return;
|
|
@@ -206,11 +223,13 @@ export const chat = makePage((ctx) => {
|
|
|
206
223
|
return;
|
|
207
224
|
}
|
|
208
225
|
|
|
209
|
-
if (!ensureWs() || !sendFrame({ type: 'prompt', text: t })) {
|
|
226
|
+
if (!ensureWs() || !sendFrame({ type: 'prompt', text: t, attachments: s().staged.map(f => ({ name: f.name, path: f.path })) })) {
|
|
210
227
|
curMsg.error = 'agent workspace connection unavailable';
|
|
211
228
|
delete curMsg._live;
|
|
212
229
|
ctx.set({ busy: false });
|
|
230
|
+
return;
|
|
213
231
|
}
|
|
232
|
+
ctx.set({ staged: [] });
|
|
214
233
|
}
|
|
215
234
|
|
|
216
235
|
function stop() {
|
|
@@ -223,14 +242,20 @@ export const chat = makePage((ctx) => {
|
|
|
223
242
|
return () => {
|
|
224
243
|
const st = s();
|
|
225
244
|
return h('div', { class: 'fd-chat' },
|
|
226
|
-
|
|
227
|
-
Select({
|
|
245
|
+
h('div', { class: 'fd-chat-picker' },
|
|
246
|
+
st.sessions.length ? Select({
|
|
228
247
|
value: st.sessionId || '',
|
|
229
248
|
placeholder: 'new conversation',
|
|
230
249
|
'aria-label': 'switch conversation',
|
|
231
250
|
options: st.sessions.map(row => ({ value: row.id, label: (row.title || '(untitled)').slice(0, 60) + (row.needsInput ? ' — needs input' : '') })),
|
|
232
251
|
onChange: switchSession,
|
|
233
|
-
})
|
|
252
|
+
}) : null,
|
|
253
|
+
h('label', { class: 'fd-chat-attach', title: 'attach files to the next message' },
|
|
254
|
+
'attach',
|
|
255
|
+
h('input', { type: 'file', multiple: true, style: 'display:none', onchange: (e) => { attachFiles(e.target.files); e.target.value = ''; } })),
|
|
256
|
+
...st.staged.map((f, i) => h('span', { key: 'st' + i, class: 'fd-chat-staged' },
|
|
257
|
+
f.name,
|
|
258
|
+
h('button', { type: 'button', class: 'fd-chat-staged-x', 'aria-label': 'remove ' + f.name, onclick: () => { st.staged = st.staged.filter((_, j) => j !== i); ctx.rerender(); } }, '×')))),
|
|
234
259
|
AgentChat({
|
|
235
260
|
messages: st.messages,
|
|
236
261
|
busy: st.busy,
|