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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anentrypoint-design",
3
- "version": "0.0.462",
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
- st.sessions.length ? h('div', { class: 'fd-chat-picker' },
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
- })) : null,
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,