anentrypoint-design 0.0.374 → 0.0.375
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 +19 -19
- package/package.json +1 -1
- package/src/components/agent-chat.js +30 -2
- package/src/components/freddie.js +73 -43
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.375",
|
|
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",
|
|
@@ -17,6 +17,7 @@ import { Btn, Icon } from './shell.js';
|
|
|
17
17
|
import { BreadcrumbPath } from './files.js';
|
|
18
18
|
import { SplitPanel } from './editor-primitives.js';
|
|
19
19
|
import { initializeCachesEagerly } from '../markdown-cache.js';
|
|
20
|
+
import { ChatMinimap } from './chat-minimap.js';
|
|
20
21
|
|
|
21
22
|
const h = webjsx.createElement;
|
|
22
23
|
|
|
@@ -224,6 +225,17 @@ export function AgentChat(props = {}) {
|
|
|
224
225
|
onPasteFiles, onDropFiles, onEmoji,
|
|
225
226
|
shownMessages, onShowEarlier,
|
|
226
227
|
streamingSince, detectAttachment,
|
|
228
|
+
// @-mention file autocomplete in the composer — a flat list of file paths
|
|
229
|
+
// the host already has (e.g. its Files tab data source). Purely forwarded
|
|
230
|
+
// to ChatComposer; omitting it keeps every existing caller unchanged (no
|
|
231
|
+
// mention affordance appears without it).
|
|
232
|
+
mentionFiles,
|
|
233
|
+
// Optional scroll-position minimap alongside the thread (ChatMinimap).
|
|
234
|
+
// false/omitted keeps every existing caller byte-identical (no minimap
|
|
235
|
+
// column at all). true renders the strip using this component's own
|
|
236
|
+
// thread ref via a shared getter — no extra DOM wiring needed from the
|
|
237
|
+
// host beyond passing showMinimap.
|
|
238
|
+
showMinimap = false,
|
|
227
239
|
// Optional inline content viewer beside the thread (a docstudio-cue
|
|
228
240
|
// addition: its chat view keeps a live document/PDF preview open next to
|
|
229
241
|
// the conversation instead of forcing a separate tab/window). The host
|
|
@@ -414,6 +426,7 @@ export function AgentChat(props = {}) {
|
|
|
414
426
|
onEmoji,
|
|
415
427
|
streamingSince,
|
|
416
428
|
detectAttachment,
|
|
429
|
+
mentionFiles,
|
|
417
430
|
});
|
|
418
431
|
|
|
419
432
|
// Contextual follow-up chips below the last SETTLED assistant turn (claude.ai/
|
|
@@ -472,8 +485,18 @@ export function AgentChat(props = {}) {
|
|
|
472
485
|
: null)
|
|
473
486
|
: null;
|
|
474
487
|
|
|
488
|
+
// ChatMinimap needs a getter that resolves the live thread element lazily
|
|
489
|
+
// (it may mount before the thread's own ref fires). A holder object keeps
|
|
490
|
+
// the element across re-renders without introducing component state.
|
|
491
|
+
const threadElHolder = { el: null };
|
|
492
|
+
const combinedThreadRef = (el) => {
|
|
493
|
+
threadElHolder.el = el;
|
|
494
|
+
const dispose = threadRef(messages.length)(el);
|
|
495
|
+
return dispose;
|
|
496
|
+
};
|
|
497
|
+
|
|
475
498
|
const threadBody = h('div', { class: 'agentchat-thread-wrap' },
|
|
476
|
-
h('div', { class: 'agentchat-thread', ref:
|
|
499
|
+
h('div', { class: 'agentchat-thread', ref: combinedThreadRef, role: 'log', 'aria-label': 'conversation', 'aria-live': 'polite', 'aria-relevant': 'additions' },
|
|
477
500
|
emptyState,
|
|
478
501
|
earlierRow,
|
|
479
502
|
...rows.filter(Boolean),
|
|
@@ -488,7 +511,12 @@ export function AgentChat(props = {}) {
|
|
|
488
511
|
// stateless chrome, so the host needn't thread scroll state through state.
|
|
489
512
|
h('button', { class: 'agentchat-jump', type: 'button', 'aria-label': 'jump to latest', title: 'jump to latest',
|
|
490
513
|
onclick: (e) => scrollThreadToBottom(e.currentTarget) },
|
|
491
|
-
Icon('arrow-down', { size: 16 }), h('span', { class: 'agentchat-jump-label' }, 'latest'))
|
|
514
|
+
Icon('arrow-down', { size: 16 }), h('span', { class: 'agentchat-jump-label' }, 'latest')),
|
|
515
|
+
// Optional scroll-position overview strip, sharing the same live thread
|
|
516
|
+
// element the auto-scroll/jump logic already resolves via threadElHolder.
|
|
517
|
+
showMinimap
|
|
518
|
+
? ChatMinimap({ messages, getThreadEl: () => threadElHolder.el })
|
|
519
|
+
: null);
|
|
492
520
|
|
|
493
521
|
const mainColumn = h('div', { class: 'agentchat-main-col' },
|
|
494
522
|
h('div', { class: 'agentchat-head' },
|
|
@@ -14,6 +14,9 @@ import { register as registerDebug, unregister as unregisterDebug } from '../deb
|
|
|
14
14
|
import { queueMessage, watchReconnect, isOnline } from '../idb-outbox.js';
|
|
15
15
|
import { ChatMessage, ChatComposer } from './chat.js';
|
|
16
16
|
import { fmtTime, fmtAgo } from './sessions.js';
|
|
17
|
+
import { ModelsConfig } from './models-config.js';
|
|
18
|
+
import { SkillsConfig } from './skills-config.js';
|
|
19
|
+
import { PluginsConfig } from './plugins-config.js';
|
|
17
20
|
import { createVirtualizer, measureRef } from '../virtual-scroll.js';
|
|
18
21
|
import { GitStatusPanel, GitDiffView } from './git-status.js';
|
|
19
22
|
import { WorktreeSwitcher } from './worktree-switcher.js';
|
|
@@ -364,44 +367,34 @@ export const analytics = makePage((ctx) => {
|
|
|
364
367
|
// ---- models ----------------------------------------------------------------
|
|
365
368
|
|
|
366
369
|
export const models = makePage((ctx) => {
|
|
367
|
-
Object.assign(ctx.state, {
|
|
370
|
+
Object.assign(ctx.state, { rebuilding: false, selectedProviderId: null, selectedModel: null });
|
|
371
|
+
// GET /api/models/availability — the real per-(provider x model x mode)
|
|
372
|
+
// availability matrix (plugins/gui-models-discover), per freddie's AGENTS.md
|
|
373
|
+
// "Model availability matrix" section. 404 with {error,hint} when the
|
|
374
|
+
// matrix file hasn't been built yet — ModelsConfig itself renders that
|
|
375
|
+
// as an empty state with a "build availability matrix" action.
|
|
368
376
|
async function load() {
|
|
369
|
-
try {
|
|
370
|
-
|
|
371
|
-
api('/api/models/providers').catch(() => []),
|
|
372
|
-
api('/api/models/cached').catch(() => ({})),
|
|
373
|
-
api('/api/models/sampler').catch(() => ({})),
|
|
374
|
-
]);
|
|
375
|
-
ctx.set({ loading: false, providers, cached, sampler, error: null });
|
|
376
|
-
} catch (e) { ctx.set({ loading: false, error: e }); }
|
|
377
|
+
try { ctx.set({ loading: false, data: await api('/api/models/availability'), error: null }); }
|
|
378
|
+
catch (e) { ctx.set({ loading: false, data: null, error: (e && e.body) || e }); }
|
|
377
379
|
}
|
|
378
|
-
async function
|
|
379
|
-
if (ctx.state.
|
|
380
|
-
ctx.set({
|
|
381
|
-
try { await api('/api/models/
|
|
382
|
-
catch (e) { ctx.set({
|
|
383
|
-
ctx.set({
|
|
380
|
+
async function rebuild() {
|
|
381
|
+
if (ctx.state.rebuilding) return;
|
|
382
|
+
ctx.set({ rebuilding: true, rebuildError: null });
|
|
383
|
+
try { await api('/api/models/availability/rebuild', { method: 'POST', body: {} }); await load(); }
|
|
384
|
+
catch (e) { ctx.set({ rebuildError: e }); }
|
|
385
|
+
ctx.set({ rebuilding: false });
|
|
384
386
|
}
|
|
385
387
|
load();
|
|
386
388
|
return () => {
|
|
387
389
|
const s = ctx.state;
|
|
388
|
-
if (s.loading) return loadingState('loading models…');
|
|
389
|
-
if (s.error && !s.providers) return errorState(s.error, load);
|
|
390
|
-
const providers = Array.isArray(s.providers) ? s.providers : [];
|
|
391
|
-
const cached = s.cached || {};
|
|
392
|
-
const status = s.sampler?.status || {};
|
|
393
390
|
return [
|
|
394
|
-
PageHeader({ eyebrow: 'freddie', title: 'models', lede:
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
const cm = (cached[name] || []);
|
|
402
|
-
return [name, st ? (st.available === false ? Chip({ tone: 'miss', children: 'down' }) : Chip({ tone: 'ok', children: 'up' })) : '—', Array.isArray(cm) ? cm.length : '—'];
|
|
403
|
-
}),
|
|
404
|
-
}) : emptyState('no providers; set provider API keys')),
|
|
391
|
+
PageHeader({ eyebrow: 'freddie', title: 'models', lede: s.data ? (s.data.summary?.total_models ?? 0) + ' models across ' + (s.data.summary?.total_providers ?? 0) + ' providers' : 'model availability matrix' }),
|
|
392
|
+
ModelsConfig({
|
|
393
|
+
data: s.data, loading: s.loading, error: s.error,
|
|
394
|
+
selectedProviderId: s.selectedProviderId, onSelectProvider: (id) => ctx.set({ selectedProviderId: id, selectedModel: null }),
|
|
395
|
+
selectedModel: s.selectedModel, onSelectModel: (m) => ctx.set({ selectedModel: m }),
|
|
396
|
+
onRefresh: load, onRebuild: rebuild, rebuilding: s.rebuilding, rebuildError: s.rebuildError,
|
|
397
|
+
}),
|
|
405
398
|
];
|
|
406
399
|
};
|
|
407
400
|
});
|
|
@@ -444,22 +437,59 @@ export const cron = makePage((ctx) => {
|
|
|
444
437
|
// ---- skills ----------------------------------------------------------------
|
|
445
438
|
|
|
446
439
|
export const skills = makePage((ctx) => {
|
|
447
|
-
Object.assign(ctx.state, {
|
|
440
|
+
Object.assign(ctx.state, { selected: null, query: '', busyName: null });
|
|
448
441
|
async function load() { try { ctx.set({ loading: false, list: await api('/api/skills'), error: null }); } catch (e) { ctx.set({ loading: false, error: e }); } }
|
|
449
442
|
load();
|
|
450
443
|
return () => {
|
|
451
444
|
const s = ctx.state;
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
445
|
+
// GET /api/skills returns {home:[...], bundled:[...], skillState} —
|
|
446
|
+
// two source lists (user ~/.freddie/skills vs bundled skills/ dirs)
|
|
447
|
+
// plus a per-skill enabled/disabled state map, not a flat array.
|
|
448
|
+
// Concat both sources (home overrides bundled on name collision,
|
|
449
|
+
// matching src/skills/index.js's own findSkill() precedence) and
|
|
450
|
+
// resolve enabled state from skillState (default true when absent).
|
|
451
|
+
const raw = s.list && typeof s.list === 'object' ? s.list : {};
|
|
452
|
+
const rawList = Array.isArray(raw) ? raw : [...(raw.bundled || []), ...(raw.home || [])];
|
|
453
|
+
const skillState = raw.skillState || {};
|
|
454
|
+
const mapped = rawList.map((sk) => ({
|
|
455
|
+
file: sk.file || sk.path || sk.name,
|
|
456
|
+
name: sk.name,
|
|
457
|
+
description: sk.description || (sk.frontmatter && sk.frontmatter.description) || '',
|
|
458
|
+
platforms: sk.platforms || (sk.frontmatter && sk.frontmatter.platforms),
|
|
459
|
+
enabled: skillState[sk.name] !== false,
|
|
460
|
+
}));
|
|
455
461
|
return [
|
|
456
|
-
PageHeader({ eyebrow: 'freddie', title: 'skills', lede:
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
)
|
|
462
|
-
]
|
|
462
|
+
PageHeader({ eyebrow: 'freddie', title: 'skills', lede: mapped.length + ' skills' }),
|
|
463
|
+
SkillsConfig({
|
|
464
|
+
skills: mapped, selected: s.selected, loading: s.loading, error: s.error,
|
|
465
|
+
busyName: s.busyName, query: s.query, onQuery: (q) => ctx.set({ query: q }),
|
|
466
|
+
onSelect: (name) => ctx.set({ selected: s.selected === name ? null : name }),
|
|
467
|
+
}),
|
|
468
|
+
];
|
|
469
|
+
};
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
// ---- plugins -----------------------------------------------------------------
|
|
473
|
+
|
|
474
|
+
export const plugins = makePage((ctx) => {
|
|
475
|
+
Object.assign(ctx.state, { selected: null });
|
|
476
|
+
// GET /api/plugins — flat {name,version,surfaces,requires,source,enabled}
|
|
477
|
+
// list, per plugins/gui-plugins-list/plugin.js (distinct from
|
|
478
|
+
// /api/plugin-graph's D3 {nodes,edges} shape built for the dependency
|
|
479
|
+
// visualization, not a flat list UI).
|
|
480
|
+
async function load() { try { ctx.set({ loading: false, list: await api('/api/plugins'), error: null }); } catch (e) { ctx.set({ loading: false, error: e }); } }
|
|
481
|
+
load();
|
|
482
|
+
return () => {
|
|
483
|
+
const s = ctx.state;
|
|
484
|
+
const list = Array.isArray(s.list) ? s.list : (s.list?.plugins || []);
|
|
485
|
+
return [
|
|
486
|
+
PageHeader({ eyebrow: 'freddie', title: 'plugins', lede: list.length + ' plugins loaded' }),
|
|
487
|
+
PluginsConfig({
|
|
488
|
+
plugins: list, selected: s.selected, loading: s.loading, error: s.error,
|
|
489
|
+
onSelect: (name) => ctx.set({ selected: s.selected === name ? null : name }),
|
|
490
|
+
onReload: load,
|
|
491
|
+
}),
|
|
492
|
+
];
|
|
463
493
|
};
|
|
464
494
|
});
|
|
465
495
|
|
|
@@ -950,7 +980,7 @@ export const git = makePage((ctx) => {
|
|
|
950
980
|
|
|
951
981
|
export const FREDDIE_PAGES = {
|
|
952
982
|
home, chat, voice, sessions, projects, agents, analytics,
|
|
953
|
-
models, cron, skills, config, env, tools, batch, gateway, chains,
|
|
983
|
+
models, cron, skills, plugins, config, env, tools, batch, gateway, chains,
|
|
954
984
|
machines, health, debug, logs, git,
|
|
955
985
|
};
|
|
956
986
|
|