anentrypoint-design 0.0.79 → 0.0.81

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.79",
3
+ "version": "0.0.81",
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",
@@ -1,6 +1,5 @@
1
1
  import * as webjsx from '../../../vendor/webjsx/index.js';
2
2
  import { Panel, Hero, Receipt } from '../content.js';
3
- import { Chip } from '../shell.js';
4
3
  import { skillLabel, getRecentPaths, saveRecentPath, renderChatMessages } from './helpers.js';
5
4
  const h = webjsx.createElement;
6
5
 
@@ -105,6 +104,6 @@ export async function chat(h0) {
105
104
  ] }),
106
105
  configured.length === 0
107
106
  ? Panel({ title: 'no providers configured', children: Receipt({ rows: [['set API key', 'keys tab → click chip'], ['or use acptoapi', 'run acptoapi server on localhost:4800']] }) })
108
- : Panel({ title: 'providers', children: h('div', { class: 'fd-chips' }, ...providers.map(p => Chip({ tone: p.configured ? (p.available ? 'ok' : 'warn') : 'miss', children: p.name + (p.configured ? (p.available ? ' ●' : ' ○') : '') }))) })
107
+ : null
109
108
  ];
110
109
  }
@@ -25,7 +25,7 @@ export async function models(h0) {
25
25
  const loading = probeState[p.name] === 'loading';
26
26
  if (loading) probedPanels.push(Panel({ title: p.name + ' ⏳', children: h('span', { class: 'fd-muted' }, 'probing…') }));
27
27
  else if (ms && ms.length > 0) probedPanels.push(Panel({ title: p.name + (p.available ? ' ●' : ' ○'), count: ms.length, children: Table({ headers: ['model id'], rows: ms.map(m => [m]) }) }));
28
- else unprobedRows.push([p.name, p.available ? 'available' : 'unavailable', p.modelsError ? 'error: '+p.modelsError : 'click "probe all"']);
28
+ else unprobedRows.push([p.name, p.available ? 'available' : 'unavailable', p.modelsError ? 'error: '+p.modelsError : '']);
29
29
  }
30
30
  const modelPanels = [
31
31
  ...probedPanels,
@@ -33,7 +33,7 @@ export async function models(h0) {
33
33
  ].filter(Boolean);
34
34
  return [
35
35
  Hero({ title: 'models', body: 'pick a provider, pick a model. probe to list available models.', accent: configured.length+' configured' }),
36
- Kpi({ items: [[configured.length,'configured'],[providers.filter(p => p.available).length,'available']] }),
36
+ Kpi({ items: [[configured.length,'configured'],[probedPanels.length,'probed'],[providers.length-configured.length,'unconfigured']] }),
37
37
  Panel({ title: 'change active model', children: Form({ fields: [
38
38
  { name: 'provider', placeholder: 'provider', value: cfg.agent?.provider || '' },
39
39
  { name: 'model', placeholder: 'model id', value: cfg.agent?.model || '' }
@@ -52,12 +52,19 @@ export async function cron(h0) {
52
52
  const list = await h0.pi.cron.list();
53
53
  return [
54
54
  Hero({ title: 'cron', body: 'scheduled prompts. cron syntax, fired by freddie.', accent: list.length+' jobs' }),
55
- Kpi({ items: [[list.length,'jobs']] }),
55
+ Kpi({ items: [[list.length,'jobs'],[list.filter(j => j.enabled).length,'enabled']] }),
56
56
  Panel({ title: 'add job', children: Form({ fields: [
57
- { name: 'cron', placeholder: '* * * * *', required: true },
58
- { name: 'prompt', placeholder: 'prompt', required: true }
59
- ], submit: 'create', onSubmit: async ev => { await h0.pi.cron.create({ cron: ev.target.elements.cron.value, prompt: ev.target.elements.prompt.value }); } }) }),
60
- Panel({ title: 'jobs', count: list.length, children: list.length === 0 ? EmptyState({ text: 'no cron jobs', glyph: '◷' }) : Table({ headers: ['id','cron','prompt','enabled'], rows: list.map(j => [j.id, j.cron, (j.prompt||'').slice(0,40), j.enabled ? 'yes' : 'no']) }) })
57
+ { name: 'cron', placeholder: '0 * * * * (m h dom mon dow)', required: true },
58
+ { name: 'prompt', placeholder: 'prompt to run', required: true }
59
+ ], submit: 'create', onSubmit: async ev => { await h0.pi.cron.create({ cron: ev.target.elements.cron.value, prompt: ev.target.elements.prompt.value }); if (typeof window.__fd_nav === 'function') window.__fd_nav('cron'); } }) }),
60
+ Panel({ title: 'cron syntax', children: Receipt({ rows: [
61
+ ['every minute', '* * * * *'],
62
+ ['every hour (top)', '0 * * * *'],
63
+ ['daily 09:00', '0 9 * * *'],
64
+ ['weekdays 18:00', '0 18 * * 1-5'],
65
+ ['every 15 min', '*/15 * * * *']
66
+ ] }) }),
67
+ Panel({ title: 'jobs', count: list.length, children: list.length === 0 ? EmptyState({ text: 'no cron jobs — add one with the form above', glyph: '◷' }) : Table({ headers: ['id','cron','prompt','enabled'], rows: list.map(j => [j.id, j.cron, (j.prompt||'').slice(0,40), j.enabled ? 'yes' : 'no']) }) })
61
68
  ];
62
69
  }
63
70
 
@@ -117,10 +124,15 @@ export async function env(h0) {
117
124
  export async function tools(h0) {
118
125
  const list = [...h0.pi.tools.values()];
119
126
  const envIsSet = k => typeof h0.pi.env?.isSet === 'function' ? h0.pi.env.isSet(k) : false;
120
- const bySet = list.reduce((a, t) => { (a[t.toolset||'core'] = a[t.toolset||'core'] || []).push(t); return a; }, {});
127
+ const f = window.__fd_toolFilter = window.__fd_toolFilter || { q: '' };
128
+ const q = (f.q || '').toLowerCase();
129
+ const filtered = q ? list.filter(t => (t.name||'').toLowerCase().includes(q) || (t.description||'').toLowerCase().includes(q) || (t.toolset||'').toLowerCase().includes(q)) : list;
130
+ const bySet = filtered.reduce((a, t) => { (a[t.toolset||'core'] = a[t.toolset||'core'] || []).push(t); return a; }, {});
131
+ const search = h('input', { type: 'search', placeholder: 'filter tools…', value: f.q, oninput: ev => { f.q = ev.target.value; if (typeof window.__fd_nav === 'function') window.__fd_nav('tools'); }, class: 'fd-search' });
121
132
  return [
122
133
  Hero({ title: 'tools', body: 'every tool the agent can call. param count + required env per row.', accent: list.length+' tools' }),
123
- Kpi({ items: [[list.length,'tools'],[Object.keys(bySet).length,'toolsets']] }),
134
+ Kpi({ items: [[list.length,'tools'],[filtered.length,'shown'],[Object.keys(bySet).length,'toolsets']] }),
135
+ Panel({ title: 'filter', right: search, children: filtered.length === 0 ? EmptyState({ text: 'no matches for "'+f.q+'"', glyph: '⌕' }) : h('span', { class: 'fd-muted' }, filtered.length+' / '+list.length+' tools shown') }),
124
136
  ...Object.entries(bySet).map(([ts, items]) => Panel({ title: 'toolset · '+ts, count: items.length, children: items.map(t => {
125
137
  const params = t.schema?.parameters?.properties ? Object.keys(t.schema.parameters.properties).length : 0;
126
138
  const reqEnv = Array.isArray(t.requiresEnv) ? t.requiresEnv : [];
@@ -7,6 +7,11 @@ const h = webjsx.createElement;
7
7
  export async function home(h0) {
8
8
  const sessions = await h0.pi.sessions.list();
9
9
  const health = h0.pi.health();
10
+ const fmt = (k, v) => {
11
+ if (k === 'ts' && typeof v === 'number') { const d = new Date(v); return d.toISOString().replace('T', ' ').slice(0, 19) + ' UTC'; }
12
+ if (typeof v === 'boolean') return v ? '✓' : '✗';
13
+ return String(v);
14
+ };
10
15
  return [
11
16
  Hero({ title: 'freddie', body: 'open js agent harness.', accent: h0.version || 'web' }),
12
17
  Kpi({ items: [[sessions.length,'sessions'],[h0.pi.tools.size,'tools'],[h0.pi.skills.size,'skills']] }),
@@ -16,13 +21,16 @@ export async function home(h0) {
16
21
  ['set api key','keys tab → click chip'],
17
22
  ['add cron','cron tab → form']
18
23
  ] }) }),
19
- Panel({ title: 'host', children: Receipt({ rows: Object.entries(health).map(([k,v]) => [k, String(v)]) }) })
24
+ Panel({ title: 'system status', children: Receipt({ rows: Object.entries(health).map(([k,v]) => [k, fmt(k, v)]) }) })
20
25
  ];
21
26
  }
22
27
 
23
28
  export async function sessions(h0) {
24
29
  const list = await h0.pi.sessions.list();
25
- const rows = list.map(s => {
30
+ const f = window.__fd_sessFilter = window.__fd_sessFilter || { q: '' };
31
+ const q = (f.q || '').toLowerCase();
32
+ const filtered = q ? list.filter(s => (s.title||'').toLowerCase().includes(q) || (s.id||'').includes(q) || (s.platform||'').toLowerCase().includes(q) || (s.cwd||'').toLowerCase().includes(q)) : list;
33
+ const rows = filtered.map(s => {
26
34
  const cont = h('button', { class: 'btn-primary', onclick: async () => {
27
35
  const msgs = await h0.pi.sessions.getMessages(s.id);
28
36
  const cs = window.__fd_chatState = window.__fd_chatState || { messages: [], busy: false, sessionId: null, cwd: '', skill: '', provider: '', model: '' };
@@ -34,10 +42,11 @@ export async function sessions(h0) {
34
42
  } }, 'continue');
35
43
  return [(s.id||'').slice(0,8), s.title||'—', s.platform||'—', s.model||'—', s.cwd?s.cwd.slice(-30):'—', s.skill?skillLabel({name:s.skill}):'—', cont];
36
44
  });
45
+ const search = h('input', { type: 'search', placeholder: 'filter by title / id / platform / cwd…', value: f.q, oninput: ev => { f.q = ev.target.value; if (typeof window.__fd_nav === 'function') window.__fd_nav('sessions'); }, class: 'fd-search' });
37
46
  return [
38
47
  Hero({ title: 'sessions', body: 'every chat turn lives here.', accent: list.length+' total' }),
39
- Kpi({ items: [[list.length,'sessions']] }),
40
- Panel({ title: 'sessions', count: list.length, children: list.length === 0 ? EmptyState({ text: 'no sessions yet', glyph: '✉' }) : Table({ headers: ['id','title','platform','model','cwd','skill',''], rows }) })
48
+ Kpi({ items: [[list.length,'sessions'],[filtered.length,'shown']] }),
49
+ Panel({ title: 'sessions', count: filtered.length, right: search, children: list.length === 0 ? EmptyState({ text: 'no sessions yet — start one in /chat', glyph: '✉' }) : filtered.length === 0 ? EmptyState({ text: 'no matches for "'+f.q+'"', glyph: '⌕' }) : Table({ headers: ['id','title','platform','model','cwd','skill',''], rows }) })
41
50
  ];
42
51
  }
43
52
 
@@ -67,16 +76,19 @@ export async function agents(h0) {
67
76
  const a = typeof h0.pi.agents === 'function' ? await h0.pi.agents() : { count: 0, turns: 0, active: null };
68
77
  const sList = await h0.pi.sessions.list();
69
78
  const recent = sList.slice(0, 10);
79
+ const idle = !a.count;
70
80
  return [
71
- Hero({ title: 'agents', body: 'agent state machine snapshot. one xstate per turn.', accent: (a.count||0)+' active' }),
72
- Kpi({ items: [[a.count||0,'active'],[a.turns||0,'turns'],[sList.length,'total sessions']] }),
73
- Panel({ title: 'current agent', children: Receipt({ rows: [
74
- ['active session', a.active || '(none)'],
75
- ['total turns', String(a.turns || 0)],
76
- ['count', String(a.count || 0)]
77
- ] }) }),
81
+ Hero({ title: 'agents', body: 'agent state machine snapshot. one xstate per turn.', accent: idle ? 'idle' : (a.count+' active') }),
82
+ Kpi({ items: [[a.count||0,'active'],[a.turns||0,'turns total'],[sList.length,'sessions in store']] }),
83
+ idle
84
+ ? Panel({ title: 'no agent running', children: EmptyState({ text: 'start an agent by sending a prompt in /chat', glyph: '◌' }) })
85
+ : Panel({ title: 'current agent', children: Receipt({ rows: [
86
+ ['active session', a.active || '(none)'],
87
+ ['total turns', String(a.turns || 0)],
88
+ ['last activity', a.last_activity ? new Date(a.last_activity).toISOString().replace('T',' ').slice(0,19)+' UTC' : '—']
89
+ ] }) }),
78
90
  Panel({ title: 'recent sessions', count: recent.length, children: recent.length === 0
79
- ? EmptyState({ text: 'no recent sessions', glyph: '' })
91
+ ? EmptyState({ text: 'no recent sessions', glyph: '' })
80
92
  : Table({ headers: ['id','title','platform','turns'], rows: recent.map(s => [(s.id||'').slice(0,8), s.title||'—', s.platform||'—', String(s.turns ?? s.message_count ?? '—')]) })
81
93
  })
82
94
  ];
@@ -86,8 +98,8 @@ export async function analytics(h0) {
86
98
  const list = await h0.pi.sessions.list();
87
99
  const tools = [...h0.pi.tools.values()];
88
100
  const skills = [...h0.pi.skills.values()];
89
- const byPlat = list.reduce((a,s) => { const k = s.platform||'?'; a[k] = (a[k]||0)+1; return a; }, {});
90
- const byModel = list.reduce((a,s) => { const k = s.model||'?'; a[k] = (a[k]||0)+1; return a; }, {});
101
+ const byPlat = list.reduce((a,s) => { const k = s.platform||'(unset)'; a[k] = (a[k]||0)+1; return a; }, {});
102
+ const byModel = list.reduce((a,s) => { const k = s.model||'(unset)'; a[k] = (a[k]||0)+1; return a; }, {});
91
103
  const byToolset = tools.reduce((a,t) => { const k = t.toolset||'core'; a[k] = (a[k]||0)+1; return a; }, {});
92
104
  const bySkillCat = skills.reduce((a,s) => { const k = s.category||'other'; a[k] = (a[k]||0)+1; return a; }, {});
93
105
  const sortDesc = obj => Object.entries(obj).sort((a,b) => b[1]-a[1]).map(([k,v]) => [k, String(v)]);