aimeat 1.2.5 → 1.3.0

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.
Files changed (128) hide show
  1. package/dist/.env.example +4 -0
  2. package/dist/locales/en.json +74 -2
  3. package/dist/locales/fi.json +74 -2
  4. package/dist/public/css/views/capabilities.css +211 -0
  5. package/dist/public/llms-template.txt +152 -89
  6. package/dist/public/spa.html +2 -62
  7. package/dist/public/views/admin/capabilities-tab.js +114 -0
  8. package/dist/public/views/admin.js +2 -0
  9. package/dist/public/views/aimeat-os.js +194 -34
  10. package/dist/public/views/profile/capabilities-tab.js +252 -0
  11. package/dist/public/views/profile/extensions-tab.js +404 -50
  12. package/dist/public/views/profile/landing-page.js +2 -0
  13. package/dist/public/views/profile.js +2 -0
  14. package/dist/src/config.d.ts +11 -0
  15. package/dist/src/config.d.ts.map +1 -1
  16. package/dist/src/config.js +11 -0
  17. package/dist/src/config.js.map +1 -1
  18. package/dist/src/mcp/apps.d.ts +18 -0
  19. package/dist/src/mcp/apps.d.ts.map +1 -0
  20. package/dist/src/mcp/apps.js +241 -0
  21. package/dist/src/mcp/apps.js.map +1 -0
  22. package/dist/src/mcp/capabilities.d.ts +12 -0
  23. package/dist/src/mcp/capabilities.d.ts.map +1 -0
  24. package/dist/src/mcp/capabilities.js +187 -0
  25. package/dist/src/mcp/capabilities.js.map +1 -0
  26. package/dist/src/mcp/cortex.d.ts +17 -0
  27. package/dist/src/mcp/cortex.d.ts.map +1 -0
  28. package/dist/src/mcp/cortex.js +237 -0
  29. package/dist/src/mcp/cortex.js.map +1 -0
  30. package/dist/src/mcp/extensions.d.ts +4 -3
  31. package/dist/src/mcp/extensions.d.ts.map +1 -1
  32. package/dist/src/mcp/extensions.js +233 -3
  33. package/dist/src/mcp/extensions.js.map +1 -1
  34. package/dist/src/mcp/index.d.ts.map +1 -1
  35. package/dist/src/mcp/index.js +6 -0
  36. package/dist/src/mcp/index.js.map +1 -1
  37. package/dist/src/routes/admin-capabilities.d.ts +11 -0
  38. package/dist/src/routes/admin-capabilities.d.ts.map +1 -0
  39. package/dist/src/routes/admin-capabilities.js +54 -0
  40. package/dist/src/routes/admin-capabilities.js.map +1 -0
  41. package/dist/src/routes/capabilities.d.ts +11 -0
  42. package/dist/src/routes/capabilities.d.ts.map +1 -0
  43. package/dist/src/routes/capabilities.js +289 -0
  44. package/dist/src/routes/capabilities.js.map +1 -0
  45. package/dist/src/routes/cortex.d.ts.map +1 -1
  46. package/dist/src/routes/cortex.js +2 -0
  47. package/dist/src/routes/cortex.js.map +1 -1
  48. package/dist/src/routes/extensions.d.ts.map +1 -1
  49. package/dist/src/routes/extensions.js +9 -0
  50. package/dist/src/routes/extensions.js.map +1 -1
  51. package/dist/src/routes/lib-capabilities.d.ts +9 -0
  52. package/dist/src/routes/lib-capabilities.d.ts.map +1 -0
  53. package/dist/src/routes/lib-capabilities.js +190 -0
  54. package/dist/src/routes/lib-capabilities.js.map +1 -0
  55. package/dist/src/routes/libs.d.ts.map +1 -1
  56. package/dist/src/routes/libs.js +13 -0
  57. package/dist/src/routes/libs.js.map +1 -1
  58. package/dist/src/routes/verification.d.ts +10 -1
  59. package/dist/src/routes/verification.d.ts.map +1 -1
  60. package/dist/src/routes/verification.js +174 -24
  61. package/dist/src/routes/verification.js.map +1 -1
  62. package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
  63. package/dist/src/server-bootstrap/routes-loader.js +35 -2
  64. package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
  65. package/dist/src/services/capability-aggregator.d.ts +8 -0
  66. package/dist/src/services/capability-aggregator.d.ts.map +1 -0
  67. package/dist/src/services/capability-aggregator.js +239 -0
  68. package/dist/src/services/capability-aggregator.js.map +1 -0
  69. package/dist/src/services/capability-invoke.d.ts +20 -0
  70. package/dist/src/services/capability-invoke.d.ts.map +1 -0
  71. package/dist/src/services/capability-invoke.js +95 -0
  72. package/dist/src/services/capability-invoke.js.map +1 -0
  73. package/dist/src/services/config-schema.d.ts.map +1 -1
  74. package/dist/src/services/config-schema.js +4 -0
  75. package/dist/src/services/config-schema.js.map +1 -1
  76. package/dist/src/services/core-jobs.d.ts.map +1 -1
  77. package/dist/src/services/core-jobs.js +16 -0
  78. package/dist/src/services/core-jobs.js.map +1 -1
  79. package/dist/src/services/did-document.d.ts +25 -0
  80. package/dist/src/services/did-document.d.ts.map +1 -0
  81. package/dist/src/services/did-document.js +31 -0
  82. package/dist/src/services/did-document.js.map +1 -0
  83. package/dist/src/services/eudiw.d.ts +11 -1
  84. package/dist/src/services/eudiw.d.ts.map +1 -1
  85. package/dist/src/services/eudiw.js +43 -48
  86. package/dist/src/services/eudiw.js.map +1 -1
  87. package/dist/src/services/extension-runtime.d.ts.map +1 -1
  88. package/dist/src/services/extension-runtime.js +8 -5
  89. package/dist/src/services/extension-runtime.js.map +1 -1
  90. package/dist/src/services/job-seeding.d.ts.map +1 -1
  91. package/dist/src/services/job-seeding.js +4 -0
  92. package/dist/src/services/job-seeding.js.map +1 -1
  93. package/dist/src/services/oidc-client.d.ts +32 -0
  94. package/dist/src/services/oidc-client.d.ts.map +1 -0
  95. package/dist/src/services/oidc-client.js +67 -0
  96. package/dist/src/services/oidc-client.js.map +1 -0
  97. package/dist/src/services/sd-jwt.d.ts +21 -0
  98. package/dist/src/services/sd-jwt.d.ts.map +1 -0
  99. package/dist/src/services/sd-jwt.js +87 -0
  100. package/dist/src/services/sd-jwt.js.map +1 -0
  101. package/dist/src/services/vc-issuer.d.ts +20 -1
  102. package/dist/src/services/vc-issuer.d.ts.map +1 -1
  103. package/dist/src/services/vc-issuer.js +75 -15
  104. package/dist/src/services/vc-issuer.js.map +1 -1
  105. package/dist/src/storage/interface.d.ts +118 -1
  106. package/dist/src/storage/interface.d.ts.map +1 -1
  107. package/dist/src/storage/providers/mongodb/index.d.ts +37 -1
  108. package/dist/src/storage/providers/mongodb/index.d.ts.map +1 -1
  109. package/dist/src/storage/providers/mongodb/index.js +282 -0
  110. package/dist/src/storage/providers/mongodb/index.js.map +1 -1
  111. package/dist/src/storage/providers/sqlite/index.d.ts +37 -1
  112. package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
  113. package/dist/src/storage/providers/sqlite/index.js +241 -0
  114. package/dist/src/storage/providers/sqlite/index.js.map +1 -1
  115. package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
  116. package/dist/src/storage/providers/sqlite/schema.js +77 -0
  117. package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
  118. package/dist/src/storage/repositories/capability.repository.d.ts +35 -0
  119. package/dist/src/storage/repositories/capability.repository.d.ts.map +1 -0
  120. package/dist/src/storage/repositories/capability.repository.js +2 -0
  121. package/dist/src/storage/repositories/capability.repository.js.map +1 -0
  122. package/dist/src/storage/repositories/index.d.ts +1 -0
  123. package/dist/src/storage/repositories/index.d.ts.map +1 -1
  124. package/dist/src/storage/repositories/node.repository.d.ts +5 -1
  125. package/dist/src/storage/repositories/node.repository.d.ts.map +1 -1
  126. package/dist/static/app-catalog.html +156 -29
  127. package/package.json +6 -1
  128. package/prisma/schema.prisma +86 -0
@@ -0,0 +1,252 @@
1
+ /**
2
+ * @file capabilities-tab.js
3
+ * @description Profile tab showing all node capabilities (auto-aggregated from extensions,
4
+ * cortex, actions) plus capability policy settings and optional manual creation.
5
+ * @version-history
6
+ * v1.0.0 — 2026-05-02 — Initial capability tab (CRUD form)
7
+ * v2.0.0 — 2026-05-02 — Redesigned: node capabilities listing, policy display, source filter
8
+ */
9
+ import { h } from 'preact';
10
+ import { useState, useEffect, useCallback } from 'preact/hooks';
11
+ import htm from 'htm';
12
+ const html = htm.bind(h);
13
+ import { t } from '/js/i18n.js';
14
+ import { escHtml, copyToClipboard } from '/js/utils.js';
15
+ import { Spinner } from './shared.js';
16
+ import { getSession } from '/js/services/auth.js';
17
+
18
+ const SOURCE_ICONS = { extension: '\u{1F50C}', cortex: '\u{1F9E0}', action: '\u{1F6E0}️', manual: '✍️', app: '\u{1F4F1}' };
19
+ const POLICY_LABELS = {
20
+ publishing: { disabled: 'policyDisabled', self_only: 'policySelfOnly', moderated: 'policyModerated', open: 'policyOpen' },
21
+ publishers: { all_users: 'policyAllUsers', trusted_only: 'policyTrustedOnly', allowlist: 'policyAllowlist' },
22
+ webhooks: { disabled: 'policyDisabled', allowlist_only: 'policyAllowlistOnly', open: 'policyOpen' },
23
+ };
24
+
25
+ export default function CapabilitiesTab() {
26
+ const [caps, setCaps] = useState([]);
27
+ const [policy, setPolicy] = useState(null);
28
+ const [loading, setLoading] = useState(true);
29
+ const [filter, setFilter] = useState('all');
30
+ const [search, setSearch] = useState('');
31
+ const [showCreate, setShowCreate] = useState(false);
32
+ const [newCap, setNewCap] = useState({ id: '', name: '', summary: '', callable: false, visibility: 'private', tags: '' });
33
+ const [detail, setDetail] = useState(null);
34
+
35
+ const loadCaps = useCallback(async () => {
36
+ const session = getSession();
37
+ if (!session) return;
38
+ try {
39
+ const res = await session.fetch('/v1/capabilities?per_page=100');
40
+ setCaps(res.data?.capabilities || []);
41
+ if (res.data?.policy) setPolicy(res.data.policy);
42
+ } catch { setCaps([]); }
43
+ setLoading(false);
44
+ }, []);
45
+
46
+ useEffect(() => { loadCaps(); }, [loadCaps]);
47
+
48
+ useEffect(() => {
49
+ const handler = () => loadCaps();
50
+ window.addEventListener('aimeat-live-update', handler);
51
+ return () => window.removeEventListener('aimeat-live-update', handler);
52
+ }, [loadCaps]);
53
+
54
+ const handleCreate = async () => {
55
+ const session = getSession();
56
+ if (!session) return;
57
+ try {
58
+ await session.fetch('/v1/capabilities', {
59
+ method: 'POST',
60
+ body: JSON.stringify({
61
+ id: newCap.id || undefined,
62
+ name: newCap.name,
63
+ summary: newCap.summary,
64
+ callable: newCap.callable,
65
+ visibility: newCap.visibility,
66
+ source: { type: 'manual', ref: 'manual', version: '1.0.0' },
67
+ tags: newCap.tags ? newCap.tags.split(',').map(s => s.trim()).filter(Boolean) : [],
68
+ }),
69
+ });
70
+ setShowCreate(false);
71
+ setNewCap({ id: '', name: '', summary: '', callable: false, visibility: 'private', tags: '' });
72
+ loadCaps();
73
+ } catch (e) {
74
+ alert(e.message || 'Failed to create');
75
+ }
76
+ };
77
+
78
+ const handleDelete = async (id) => {
79
+ if (!confirm(t('capabilities.deleteConfirm'))) return;
80
+ const session = getSession();
81
+ if (!session) return;
82
+ try {
83
+ await session.fetch('/v1/capabilities/' + encodeURIComponent(id), { method: 'DELETE' });
84
+ loadCaps();
85
+ } catch (e) {
86
+ alert(e.message || 'Failed to delete');
87
+ }
88
+ };
89
+
90
+ if (loading) return html`<${Spinner} />`;
91
+
92
+ const filtered = caps.filter(c => {
93
+ if (filter !== 'all' && c.source?.type !== filter) return false;
94
+ if (search && !c.name.toLowerCase().includes(search.toLowerCase()) && !c.summary?.toLowerCase().includes(search.toLowerCase())) return false;
95
+ return true;
96
+ });
97
+
98
+ const sourceCounts = {};
99
+ for (const c of caps) {
100
+ const st = c.source?.type || 'manual';
101
+ sourceCounts[st] = (sourceCounts[st] || 0) + 1;
102
+ }
103
+
104
+ const canCreate = policy && policy.publishing !== 'disabled';
105
+
106
+ return html`
107
+ <div class="pf-section">
108
+ <div class="section-title">${t('capabilities.nodeCapabilities')}</div>
109
+ <div class="section-desc">${t('capabilities.nodeCapabilitiesDesc')}</div>
110
+
111
+ <!-- Filter bar -->
112
+ <div class="cap-filter-bar">
113
+ <input
114
+ type="text"
115
+ class="cap-search-input"
116
+ placeholder="${t('common.search') || 'Search...'}"
117
+ value=${search}
118
+ onInput=${e => setSearch(e.target.value)}
119
+ />
120
+ <select class="cap-filter-select" value=${filter} onChange=${e => setFilter(e.target.value)}>
121
+ <option value="all">${t('capabilities.allTypes')} (${caps.length})</option>
122
+ ${Object.entries(sourceCounts).map(([type, count]) => html`
123
+ <option value=${type}>${SOURCE_ICONS[type] || ''} ${t('capabilities.' + type) || type} (${count})</option>
124
+ `)}
125
+ </select>
126
+ </div>
127
+
128
+ <!-- Capability list -->
129
+ ${!filtered.length ? html`<div class="pf-empty">${t('capabilities.noCapabilities')}</div>` : ''}
130
+
131
+ ${filtered.map(c => {
132
+ const s = c.stats || {};
133
+ const srcType = c.source?.type || 'manual';
134
+ const icon = SOURCE_ICONS[srcType] || '';
135
+ const isSelected = detail?.id === c.id;
136
+ return html`
137
+ <div class="cap-item ${isSelected ? 'cap-item-selected' : ''}" onClick=${() => setDetail(isSelected ? null : c)}>
138
+ <div class="cap-item-header">
139
+ <div class="cap-item-name">
140
+ <span class="cap-source-icon">${icon}</span>
141
+ <strong>${escHtml(c.name)}</strong>
142
+ ${c.callable ? html`<span class="cap-badge cap-badge-callable">${t('capabilities.callable')}</span>` : ''}
143
+ ${srcType === 'cortex' ? html`<span class="cap-badge cap-badge-browser">${t('capabilities.browserOnly')}</span>` : ''}
144
+ ${c.status !== 'active' ? html`<span class="cap-badge cap-badge-status">${c.status}</span>` : ''}
145
+ </div>
146
+ <div class="cap-item-stats">
147
+ ${s.totalInvocations ? html`<span>${s.totalInvocations} ${t('capabilities.invocations').toLowerCase()}</span>` : ''}
148
+ ${c.trust?.vouchCount ? html`<span>${c.trust.vouchCount} ${t('capabilities.vouchCount').toLowerCase()}</span>` : ''}
149
+ </div>
150
+ </div>
151
+ ${c.summary ? html`<div class="cap-item-summary">${escHtml(c.summary)}</div>` : ''}
152
+ ${(c.tags || []).length ? html`
153
+ <div class="cap-item-tags">
154
+ ${c.tags.map(tag => html`<span class="cap-tag">${escHtml(tag)}</span>`)}
155
+ </div>
156
+ ` : ''}
157
+
158
+ ${isSelected ? html`
159
+ <div class="cap-detail" onClick=${e => e.stopPropagation()}>
160
+ <div class="cap-detail-row"><span class="cap-detail-label">ID:</span> <code class="cap-detail-code">${c.id}</code></div>
161
+ <div class="cap-detail-row"><span class="cap-detail-label">${t('capabilities.source')}:</span> ${srcType} ${c.source?.ref ? html` — <code class="cap-detail-code">${c.source.ref}</code>` : ''}</div>
162
+ <div class="cap-detail-row"><span class="cap-detail-label">${t('capabilities.visibility')}:</span> ${c.visibility === 'public' ? '\u{1F310} Public' : '\u{1F512} Private'}</div>
163
+ <div class="cap-detail-row"><span class="cap-detail-label">${t('capabilities.authRequired')}:</span> ${c.authRequired || 'registered'}</div>
164
+ ${c.usage ? html`<div class="cap-detail-row"><span class="cap-detail-label">Usage:</span> <code class="cap-detail-code">${c.usage}</code></div>` : ''}
165
+ ${c.whenToUse ? html`<div class="cap-detail-row"><span class="cap-detail-label">When to use:</span> ${escHtml(c.whenToUse)}</div>` : ''}
166
+ ${s.totalInvocations ? html`
167
+ <div class="cap-detail-row">
168
+ <span class="cap-detail-label">Stats:</span>
169
+ ${s.totalInvocations} calls, ${s.successCount} ok, ${s.errorCount} errors
170
+ ${s.avgResponseMs ? html` — avg ${Math.round(s.avgResponseMs)}ms` : ''}
171
+ </div>
172
+ ` : ''}
173
+ ${c.inputSchema && Object.keys(c.inputSchema).length > 1 ? html`
174
+ <details class="cap-schema-details">
175
+ <summary>Input Schema</summary>
176
+ <pre class="cap-schema-pre">${JSON.stringify(c.inputSchema, null, 2)}</pre>
177
+ </details>
178
+ ` : ''}
179
+ ${c.outputSchema && Object.keys(c.outputSchema).length > 1 ? html`
180
+ <details class="cap-schema-details">
181
+ <summary>Output Schema</summary>
182
+ <pre class="cap-schema-pre">${JSON.stringify(c.outputSchema, null, 2)}</pre>
183
+ </details>
184
+ ` : ''}
185
+ ${c.source?.type === 'manual' ? html`
186
+ <button class="btn-danger" style="margin-top:8px;font-size:.8rem" onClick=${() => handleDelete(c.id)}>
187
+ ${t('capabilities.delete')}
188
+ </button>
189
+ ` : ''}
190
+ </div>
191
+ ` : ''}
192
+ </div>
193
+ `;
194
+ })}
195
+
196
+ <!-- How capabilities are created -->
197
+ <div class="cap-info-section">
198
+ <div class="cap-info-title">${t('capabilities.howCreated')}</div>
199
+ <div class="cap-info-desc">${t('capabilities.howCreatedDesc')}</div>
200
+ </div>
201
+
202
+ <!-- Policy settings -->
203
+ ${policy ? html`
204
+ <div class="cap-info-section">
205
+ <div class="cap-info-title">${t('capabilities.policyTitle')}</div>
206
+ <div class="cap-policy-grid">
207
+ <div class="cap-policy-item">
208
+ <span class="cap-policy-label">${t('capabilities.policyPublishing')}</span>
209
+ <span class="cap-policy-value">${t('capabilities.' + (POLICY_LABELS.publishing[policy.publishing] || 'policyDisabled'))}</span>
210
+ </div>
211
+ <div class="cap-policy-item">
212
+ <span class="cap-policy-label">${t('capabilities.policyPublishers')}</span>
213
+ <span class="cap-policy-value">${t('capabilities.' + (POLICY_LABELS.publishers[policy.publishers] || 'policyAllUsers'))}</span>
214
+ </div>
215
+ <div class="cap-policy-item">
216
+ <span class="cap-policy-label">${t('capabilities.policyWebhooks')}</span>
217
+ <span class="cap-policy-value">${t('capabilities.' + (POLICY_LABELS.webhooks[policy.webhooks] || 'policyDisabled'))}</span>
218
+ </div>
219
+ </div>
220
+ </div>
221
+ ` : ''}
222
+
223
+ <!-- Create manual capability (if allowed) -->
224
+ ${canCreate ? html`
225
+ <div class="cap-create-section">
226
+ <button class="btn-outline" onClick=${() => setShowCreate(!showCreate)}>
227
+ ${showCreate ? t('common.cancel') : t('capabilities.create')}
228
+ </button>
229
+ ${showCreate ? html`
230
+ <div class="cap-create-form">
231
+ <input class="cap-form-input" placeholder="ID (optional)" value=${newCap.id} onInput=${e => setNewCap({ ...newCap, id: e.target.value })} />
232
+ <input class="cap-form-input" placeholder=${t('capabilities.name')} value=${newCap.name} onInput=${e => setNewCap({ ...newCap, name: e.target.value })} />
233
+ <textarea class="cap-form-input" placeholder=${t('capabilities.summary')} value=${newCap.summary} onInput=${e => setNewCap({ ...newCap, summary: e.target.value })} rows="2" />
234
+ <input class="cap-form-input" placeholder="Tags (comma-separated)" value=${newCap.tags} onInput=${e => setNewCap({ ...newCap, tags: e.target.value })} />
235
+ <label class="cap-form-checkbox">
236
+ <input type="checkbox" checked=${newCap.callable} onChange=${e => setNewCap({ ...newCap, callable: e.target.checked })} />
237
+ ${t('capabilities.callable')}
238
+ </label>
239
+ <select class="cap-form-input" value=${newCap.visibility} onChange=${e => setNewCap({ ...newCap, visibility: e.target.value })}>
240
+ <option value="private">Private</option>
241
+ <option value="public">Public</option>
242
+ </select>
243
+ <button class="btn-primary" onClick=${handleCreate} disabled=${!newCap.name}>
244
+ ${t('capabilities.create')}
245
+ </button>
246
+ </div>
247
+ ` : ''}
248
+ </div>
249
+ ` : ''}
250
+ </div>
251
+ `;
252
+ }