freddie 0.0.121 → 0.0.122
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/AGENTS.md +35 -10
- package/package.json +3 -2
- package/plugins/core-cli/plugin.js +132 -5
- package/plugins/gm-skill/plugin.js +16 -4
- package/plugins/gui-auth/plugin.js +45 -0
- package/plugins/gui-chat/plugin.js +21 -4
- package/plugins/gui-env/plugin.js +14 -1
- package/plugins/gui-sessions/plugin.js +7 -1
- package/plugins/memory/handler.js +23 -46
- package/plugins/platform-discord/handler.js +83 -1
- package/plugins/platform-whatsapp/handler.js +31 -5
- package/src/acp/server.js +1 -1
- package/src/acp/tools.js +5 -1
- package/src/agent/acptoapi-bridge.js +33 -9
- package/src/agent/llm_resolver.js +10 -1
- package/src/agent/machine.js +61 -12
- package/src/agent/tool_call_text.js +68 -0
- package/src/batch.js +4 -3
- package/src/browser/index.js +4 -0
- package/src/cli/cli_output.js +4 -4
- package/src/cli/interactive.js +58 -9
- package/src/cli/memory_setup.js +18 -4
- package/src/cli/relaunch.js +2 -2
- package/src/cli/stdin_secret.js +31 -0
- package/src/context/engine.js +7 -4
- package/src/gateway/run.js +18 -6
- package/src/index.js +1 -0
- package/src/learn/gm-learn.js +179 -0
- package/src/plugins/case/index.js +28 -0
- package/src/plugins/case/toolset.js +312 -0
- package/src/sessions.js +38 -1
- package/src/toolset_distributions.js +3 -0
- package/src/toolsets.js +1 -1
- package/src/web/app.js +55 -12
- package/src/web/index.html +30 -3
- package/src/web/server.js +51 -2
- package/src/web/state.js +74 -32
package/src/web/state.js
CHANGED
|
@@ -1,8 +1,37 @@
|
|
|
1
1
|
import { h } from 'anentrypoint-design';
|
|
2
2
|
|
|
3
|
-
export const j = async (u, opts) => {
|
|
3
|
+
export const j = async (u, opts) => {
|
|
4
|
+
const r = await fetch(u, opts);
|
|
5
|
+
if (!r.ok) {
|
|
6
|
+
let detail = '';
|
|
7
|
+
try {
|
|
8
|
+
const ct = r.headers.get('content-type') || '';
|
|
9
|
+
const raw = await r.text();
|
|
10
|
+
if (ct.includes('json')) {
|
|
11
|
+
try { const b = JSON.parse(raw); detail = b.error ? (b.error + (b.hint ? ' — ' + b.hint : '')) : raw; } catch { detail = raw; }
|
|
12
|
+
} else { detail = raw; }
|
|
13
|
+
} catch { /* body unreadable */ }
|
|
14
|
+
throw new Error(r.status + ' ' + r.statusText + (detail ? ': ' + String(detail).slice(0, 500) : ''));
|
|
15
|
+
}
|
|
16
|
+
return r.json();
|
|
17
|
+
};
|
|
4
18
|
export const post = (u, b) => j(u, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(b) });
|
|
5
19
|
|
|
20
|
+
// Wrap a mutation so a rejection is surfaced to the user (app.js installs
|
|
21
|
+
// window.__fd_notify — a transient toast) AND still rejected, so callers that
|
|
22
|
+
// have their own catch/finally (e.g. button spinners) keep working. Without
|
|
23
|
+
// this, a thrown mutation error vanished silently into the console.
|
|
24
|
+
export function wrapMutation(label, fn) {
|
|
25
|
+
return async (...args) => {
|
|
26
|
+
try { return await fn(...args); }
|
|
27
|
+
catch (e) {
|
|
28
|
+
const msg = label + ' failed: ' + String(e && e.message || e);
|
|
29
|
+
try { if (typeof window !== 'undefined' && window.__fd_notify) window.__fd_notify(msg); } catch { /* notify unavailable */ }
|
|
30
|
+
throw e;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
6
35
|
export function reg(arr, keyFn = x => x.name) {
|
|
7
36
|
const m = new Map();
|
|
8
37
|
for (const it of arr || []) m.set(keyFn(it), it);
|
|
@@ -10,20 +39,26 @@ export function reg(arr, keyFn = x => x.name) {
|
|
|
10
39
|
}
|
|
11
40
|
|
|
12
41
|
export async function fetchHost() {
|
|
42
|
+
// Track boot fetch failures so app.js can surface a degraded-backend warning.
|
|
43
|
+
let _fails = 0;
|
|
44
|
+
const settled = (p, fb) => p.catch(() => { _fails++; return fb; });
|
|
13
45
|
const [tools, skillsR, cron, projR, env, gateway, health, commands] = await Promise.all([
|
|
14
|
-
j('/api/tools/detail')
|
|
15
|
-
j('/api/skills')
|
|
16
|
-
j('/api/cron')
|
|
17
|
-
j('/api/projects')
|
|
18
|
-
j('/api/env')
|
|
19
|
-
j('/api/gateway')
|
|
20
|
-
j('/api/health')
|
|
21
|
-
j('/api/commands')
|
|
46
|
+
settled(j('/api/tools/detail'), []),
|
|
47
|
+
settled(j('/api/skills'), { home: [], bundled: [] }),
|
|
48
|
+
settled(j('/api/cron'), []),
|
|
49
|
+
settled(j('/api/projects'), { active: null, projects: [] }),
|
|
50
|
+
settled(j('/api/env'), []),
|
|
51
|
+
settled(j('/api/gateway'), { platforms: [] }),
|
|
52
|
+
settled(j('/api/health'), { ok: false }),
|
|
53
|
+
settled(j('/api/commands'), []),
|
|
22
54
|
]);
|
|
23
55
|
const skillList = [...(skillsR.home || []), ...(skillsR.bundled || [])];
|
|
24
56
|
const projList = projR.projects || [];
|
|
57
|
+
// degraded: every boot endpoint failed — the backend is unreachable/broken.
|
|
58
|
+
const degraded = _fails >= 8;
|
|
25
59
|
return {
|
|
26
60
|
kind: 'freddie-web', version: 'web',
|
|
61
|
+
degraded,
|
|
27
62
|
pi: {
|
|
28
63
|
tools: reg(tools),
|
|
29
64
|
skills: reg(skillList, s => s.name || s.id),
|
|
@@ -31,9 +66,9 @@ export async function fetchHost() {
|
|
|
31
66
|
projects: {
|
|
32
67
|
list: () => projList,
|
|
33
68
|
active: () => projR.active,
|
|
34
|
-
create: ({ name, path }) => post('/api/projects', { name, path }).then(() => location.reload()),
|
|
35
|
-
remove: name => fetch('/api/projects/' + encodeURIComponent(name), { method: 'DELETE' }).then(() => location.reload()),
|
|
36
|
-
setActive: name => post('/api/projects/active', { name }).then(() => location.reload()),
|
|
69
|
+
create: wrapMutation('create project', ({ name, path }) => post('/api/projects', { name, path }).then(() => location.reload())),
|
|
70
|
+
remove: wrapMutation('delete project', name => fetch('/api/projects/' + encodeURIComponent(name), { method: 'DELETE' }).then(() => location.reload())),
|
|
71
|
+
setActive: wrapMutation('switch project', name => post('/api/projects/active', { name }).then(() => location.reload())),
|
|
37
72
|
},
|
|
38
73
|
sessions: {
|
|
39
74
|
list: () => j('/api/sessions').catch(() => []),
|
|
@@ -42,8 +77,8 @@ export async function fetchHost() {
|
|
|
42
77
|
},
|
|
43
78
|
cron: {
|
|
44
79
|
list: () => Promise.resolve(cron),
|
|
45
|
-
create: job => post('/api/cron', job),
|
|
46
|
-
delete: id => fetch('/api/cron/' + id, { method: 'DELETE' }),
|
|
80
|
+
create: wrapMutation('create cron job', job => post('/api/cron', job)),
|
|
81
|
+
delete: wrapMutation('delete cron job', id => fetch('/api/cron/' + id, { method: 'DELETE' })),
|
|
47
82
|
},
|
|
48
83
|
env: { list: () => env, isSet: k => (env.find(e => e.key === k) || {}).set || false },
|
|
49
84
|
gateway: { platforms: () => gateway.platforms || [] },
|
|
@@ -51,31 +86,38 @@ export async function fetchHost() {
|
|
|
51
86
|
health: () => health,
|
|
52
87
|
config: {
|
|
53
88
|
load: () => j('/api/config').catch(() => ({})),
|
|
54
|
-
saveValue: (key, value) => post('/api/config', { key, value }),
|
|
89
|
+
saveValue: wrapMutation('save config', (key, value) => post('/api/config', { key, value })),
|
|
55
90
|
},
|
|
56
|
-
|
|
57
|
-
|
|
91
|
+
// Handler reads `prompt` and (for plain fetch) returns `{ result }`.
|
|
92
|
+
chat: { send: wrapMutation('send message', prompt => post('/api/chat', { prompt })) },
|
|
93
|
+
batch: { run: wrapMutation('run batch', (prompts, conc) => post('/api/batch', { prompts, concurrency: conc })) },
|
|
58
94
|
hooks: {},
|
|
59
95
|
},
|
|
60
96
|
};
|
|
61
97
|
}
|
|
62
98
|
|
|
99
|
+
// `icon` is an anentrypoint-design SDK Icon() name (monochrome inline SVG),
|
|
100
|
+
// not a decorative unicode glyph — the nav chrome reads as one icon set.
|
|
63
101
|
export const ROUTES = [
|
|
64
|
-
{ path: 'home', label: 'home',
|
|
65
|
-
{ path: 'chat', label: 'chat',
|
|
66
|
-
{ path: 'voice', label: 'voice',
|
|
67
|
-
{ path: 'sessions', label: 'sessions',
|
|
68
|
-
{ path: 'projects', label: 'projects',
|
|
69
|
-
{ path: 'agents', label: 'agents',
|
|
70
|
-
{ path: 'analytics', label: 'analytics',
|
|
71
|
-
{ path: 'models', label: 'models',
|
|
72
|
-
{ path: 'cron', label: 'cron',
|
|
73
|
-
{ path: 'skills', label: 'skills',
|
|
74
|
-
{ path: 'config', label: 'config',
|
|
75
|
-
{ path: 'env', label: 'keys',
|
|
76
|
-
{ path: 'tools', label: 'tools',
|
|
77
|
-
{ path: 'batch', label: 'batch',
|
|
78
|
-
{ path: 'gateway', label: 'gateway',
|
|
102
|
+
{ path: 'home', label: 'home', icon: 'page' },
|
|
103
|
+
{ path: 'chat', label: 'chat', icon: 'forum' },
|
|
104
|
+
{ path: 'voice', label: 'voice', icon: 'mic' },
|
|
105
|
+
{ path: 'sessions', label: 'sessions', icon: 'thread' },
|
|
106
|
+
{ path: 'projects', label: 'projects', icon: 'square' },
|
|
107
|
+
{ path: 'agents', label: 'agents', icon: 'members' },
|
|
108
|
+
{ path: 'analytics', label: 'analytics', icon: 'activity' },
|
|
109
|
+
{ path: 'models', label: 'models', icon: 'circle-dot' },
|
|
110
|
+
{ path: 'cron', label: 'cron', icon: 'play' },
|
|
111
|
+
{ path: 'skills', label: 'skills', icon: 'check' },
|
|
112
|
+
{ path: 'config', label: 'config', icon: 'settings' },
|
|
113
|
+
{ path: 'env', label: 'keys', icon: 'hash' },
|
|
114
|
+
{ path: 'tools', label: 'tools', icon: 'more-horizontal' },
|
|
115
|
+
{ path: 'batch', label: 'batch', icon: 'square' },
|
|
116
|
+
{ path: 'gateway', label: 'gateway', icon: 'arrow-right' },
|
|
117
|
+
{ path: 'chains', label: 'chains', icon: 'chevron-right' },
|
|
118
|
+
{ path: 'machines', label: 'machines', icon: 'settings' },
|
|
119
|
+
{ path: 'health', label: 'health', icon: 'activity' },
|
|
120
|
+
{ path: 'debug', label: 'debug', icon: 'circle' },
|
|
79
121
|
];
|
|
80
122
|
|
|
81
123
|
export function pre(obj) {
|