loopengine 0.1.90 → 0.1.92
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/README.md +17 -0
- package/dist/bin/cli.js +3 -2
- package/dist/core/system-agents/interviewer.d.ts +76 -0
- package/dist/core/system-agents/interviewer.js +233 -0
- package/dist/core/system-agents/templates.d.ts +10 -0
- package/dist/core/system-agents/templates.js +146 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/web/agents-list-page.js +3 -1
- package/dist/web/console-shell.js +3 -1
- package/dist/web/dev-ui-styles.js +3 -0
- package/dist/web/interview-admin.d.ts +96 -0
- package/dist/web/interview-admin.js +258 -0
- package/dist/web/interview-page.d.ts +1 -0
- package/dist/web/interview-page.js +247 -0
- package/dist/web/templates-admin.d.ts +19 -0
- package/dist/web/templates-admin.js +37 -0
- package/dist/web/templates-page.d.ts +1 -0
- package/dist/web/templates-page.js +130 -0
- package/package.json +2 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Backs the console's Templates page (/templates): the ready-made agents
|
|
2
|
+
// in core/system-agents/templates.ts, previewed and created the same way
|
|
3
|
+
// as a "Find your first agent" suggestion (web/interview-admin.ts), so a
|
|
4
|
+
// template agent starts exactly like one: its instructions, every tool
|
|
5
|
+
// asking first, a paused schedule when it runs on a timer, and a Finish
|
|
6
|
+
// setup checklist. Unlike the interview it needs no model call, so it
|
|
7
|
+
// works before any agent has a model or key.
|
|
8
|
+
import { STARTER_TEMPLATES, starterTemplate } from '../core/system-agents/templates.js';
|
|
9
|
+
import { createAgentFromCandidate, describeCandidate } from './interview-admin.js';
|
|
10
|
+
export class TemplateError extends Error {
|
|
11
|
+
}
|
|
12
|
+
function templateAt(id) {
|
|
13
|
+
const template = starterTemplate(id);
|
|
14
|
+
if (!template)
|
|
15
|
+
throw new TemplateError('No such template');
|
|
16
|
+
return template;
|
|
17
|
+
}
|
|
18
|
+
export function listTemplates() {
|
|
19
|
+
return STARTER_TEMPLATES.map(({ id, category, candidate: c }) => ({
|
|
20
|
+
id,
|
|
21
|
+
category,
|
|
22
|
+
title: c.title,
|
|
23
|
+
summary: c.summary,
|
|
24
|
+
trigger: c.trigger.description,
|
|
25
|
+
asksFirst: c.asksFirst,
|
|
26
|
+
needs: c.needs.map((n) => (n.kind === 'key' ? n.description : n.name ?? n.description)),
|
|
27
|
+
schedule: c.trigger.kind === 'schedule',
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
export function previewTemplate(id, deps) {
|
|
31
|
+
return describeCandidate(templateAt(id).candidate, deps);
|
|
32
|
+
}
|
|
33
|
+
/** Creates a new agent from the template, under the first free name, so
|
|
34
|
+
* the same template can be used more than once. */
|
|
35
|
+
export async function createFromTemplate(id, deps) {
|
|
36
|
+
return createAgentFromCandidate(templateAt(id).candidate, deps);
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const templatesPageHtml: string;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// The console's Templates page (/templates): ready-made agents
|
|
2
|
+
// (core/system-agents/templates.ts) a person can preview and create in
|
|
3
|
+
// one click (web/templates-admin.ts behind /starter-templates/*). Same
|
|
4
|
+
// shell and styles as the other console pages. Like them, its inline
|
|
5
|
+
// script avoids backslashes and template placeholders, since it lives
|
|
6
|
+
// inside a template literal.
|
|
7
|
+
import { devUiCss } from './dev-ui-styles.js';
|
|
8
|
+
import { consoleShellScript, consoleSidebarHtml } from './console-shell.js';
|
|
9
|
+
export const templatesPageHtml = `<!doctype html>
|
|
10
|
+
<html lang="en">
|
|
11
|
+
<head>
|
|
12
|
+
<meta charset="utf-8">
|
|
13
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
14
|
+
<title>Templates</title>
|
|
15
|
+
<style>${devUiCss}
|
|
16
|
+
.tp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; max-width: 1000px; }
|
|
17
|
+
.tp-card { border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; display: grid; gap: 8px; align-content: start; }
|
|
18
|
+
.tp-card h3 { margin: 0; font-size: 15px; }
|
|
19
|
+
.tp-cat { justify-self: start; font-size: 11.5px; font-weight: 600; color: var(--ink-muted); background: var(--surface); padding: 2px 8px; border-radius: 999px; }
|
|
20
|
+
.tp-card .meta { font-size: 12.5px; color: var(--ink-muted); display: grid; gap: 4px; }
|
|
21
|
+
.tp-card .row { display: flex; gap: 8px; flex-wrap: wrap; }
|
|
22
|
+
.tp-preview { border-top: 1px solid var(--line); padding-top: 10px; display: grid; gap: 8px; font-size: 13px; }
|
|
23
|
+
.tp-preview pre { white-space: pre-wrap; max-height: 220px; overflow: auto; margin: 0; }
|
|
24
|
+
.tp-btn { display: inline-block; padding: 6px 12px; border-radius: 6px; text-decoration: none; font-size: 13px; font-weight: 500; background: var(--accent); color: var(--on-accent); }
|
|
25
|
+
.tp-btn.plain { background: none; color: var(--ink); border: 1px solid var(--line); }
|
|
26
|
+
.hint { font-size: 12px; color: var(--ink-muted); }
|
|
27
|
+
.error { font-size: 13px; color: var(--bad); }
|
|
28
|
+
</style>
|
|
29
|
+
</head>
|
|
30
|
+
<body data-le-page="templates">
|
|
31
|
+
<div class="le-app">
|
|
32
|
+
${consoleSidebarHtml}
|
|
33
|
+
<main class="le-main">
|
|
34
|
+
<div class="le-head plain">
|
|
35
|
+
<div class="le-head-row">
|
|
36
|
+
<div class="le-title"><button type="button" class="le-menu-btn" data-le-menu aria-label="Open navigation">☰</button>
|
|
37
|
+
<div><h1>Templates</h1><p>Ready-made agents to start from. Each one asks you before it sends, pays, changes or deletes anything.</p></div>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
<div class="le-scroll"><div class="le-page" id="tpPage"><p class="hint">Loading…</p></div></div>
|
|
42
|
+
</main>
|
|
43
|
+
</div>
|
|
44
|
+
${consoleShellScript}
|
|
45
|
+
<script>
|
|
46
|
+
(function () {
|
|
47
|
+
var page = document.getElementById('tpPage');
|
|
48
|
+
var ELLIPSIS = String.fromCharCode(8230);
|
|
49
|
+
|
|
50
|
+
function esc(s) {
|
|
51
|
+
return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
|
|
52
|
+
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c];
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function api(method, path) {
|
|
56
|
+
return fetch(path, { method: method, cache: 'no-store' })
|
|
57
|
+
.then(function (r) { return r.json().then(function (j) { return { ok: r.ok, body: j }; }); });
|
|
58
|
+
}
|
|
59
|
+
function checklistHtml(items) {
|
|
60
|
+
if (!items.length) return '<p>Nothing else to set up.</p>';
|
|
61
|
+
return '<ul style="margin:0;padding-left:18px">' + items.map(function (it) {
|
|
62
|
+
return '<li>' + (it.href ? '<a href="' + esc(it.href) + '">' + esc(it.label) + '</a>' : esc(it.label)) + '</li>';
|
|
63
|
+
}).join('') + '</ul>';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function cardHtml(t) {
|
|
67
|
+
return '<div class="tp-card" data-id="' + esc(t.id) + '">' +
|
|
68
|
+
'<span class="tp-cat">' + esc(t.category) + '</span>' +
|
|
69
|
+
'<h3>' + esc(t.title) + '</h3>' +
|
|
70
|
+
'<div>' + esc(t.summary) + '</div>' +
|
|
71
|
+
'<div class="meta">' +
|
|
72
|
+
'<div><strong>Starts:</strong> ' + esc(t.trigger) + '</div>' +
|
|
73
|
+
(t.asksFirst.length ? '<div><strong>Asks you first:</strong> ' + esc(t.asksFirst.join(', ')) + '</div>' : '') +
|
|
74
|
+
(t.needs.length ? '<div><strong>Needs:</strong> ' + esc(t.needs.join(', ')) + '</div>' : '') +
|
|
75
|
+
'</div>' +
|
|
76
|
+
'<div class="row"><button type="button" class="primary tp-use">Use this template</button></div>' +
|
|
77
|
+
'<div class="tp-slot"></div></div>';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function show() {
|
|
81
|
+
api('GET', '/starter-templates').then(function (r) {
|
|
82
|
+
if (!r.ok) { page.innerHTML = '<p class="error">' + esc(r.body.error || 'Could not load the templates') + '</p>'; return; }
|
|
83
|
+
page.innerHTML = '<div class="tp-grid">' + r.body.templates.map(cardHtml).join('') + '</div>' +
|
|
84
|
+
'<p class="hint" style="margin-top:16px">Not what you need? <a href="/interview">Find your first agent</a> suggests one from your own work, or <a href="/agents?new=1">start from a blank agent</a>.</p>';
|
|
85
|
+
Array.prototype.forEach.call(page.querySelectorAll('.tp-use'), function (btn) {
|
|
86
|
+
btn.addEventListener('click', function () { preview(btn.closest('.tp-card')); });
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function preview(card) {
|
|
92
|
+
var id = card.getAttribute('data-id');
|
|
93
|
+
var slot = card.querySelector('.tp-slot');
|
|
94
|
+
slot.innerHTML = '<p class="hint">Loading' + ELLIPSIS + '</p>';
|
|
95
|
+
api('GET', '/starter-templates/' + encodeURIComponent(id) + '/preview').then(function (r) {
|
|
96
|
+
if (!r.ok) { slot.innerHTML = '<p class="error">' + esc(r.body.error || 'Could not prepare it') + '</p>'; return; }
|
|
97
|
+
var p = r.body;
|
|
98
|
+
slot.innerHTML = '<div class="tp-preview">' +
|
|
99
|
+
'<div><strong>Agent:</strong> <code>' + esc(p.name) + '</code></div>' +
|
|
100
|
+
'<div><strong>Instructions</strong> <span class="hint">(edit them later in its Overview tab)</span><pre>' + esc(p.systemPrompt) + '</pre></div>' +
|
|
101
|
+
'<div><strong>Permissions:</strong> ' + esc(p.permissions) + '</div>' +
|
|
102
|
+
(p.schedule ? '<div><strong>Schedule:</strong> ' + esc(p.schedule) + '</div>' : '') +
|
|
103
|
+
'<div><strong>Then, to finish setup:</strong>' + checklistHtml(p.checklist) + '</div>' +
|
|
104
|
+
'<div class="row"><button type="button" class="primary tp-create">Create it</button><button type="button" class="tp-cancel">Cancel</button></div>' +
|
|
105
|
+
'<div class="hint tp-status"></div></div>';
|
|
106
|
+
slot.querySelector('.tp-cancel').addEventListener('click', function () { slot.innerHTML = ''; });
|
|
107
|
+
slot.querySelector('.tp-create').addEventListener('click', function (ev) {
|
|
108
|
+
var btn = ev.currentTarget;
|
|
109
|
+
btn.disabled = true;
|
|
110
|
+
slot.querySelector('.tp-status').textContent = 'Creating' + ELLIPSIS;
|
|
111
|
+
api('POST', '/starter-templates/' + encodeURIComponent(id) + '/create').then(function (r2) {
|
|
112
|
+
if (!r2.ok) { btn.disabled = false; slot.querySelector('.tp-status').textContent = r2.body.error || 'Could not create it'; return; }
|
|
113
|
+
var c = r2.body;
|
|
114
|
+
slot.innerHTML = '<div class="tp-preview">' +
|
|
115
|
+
'<div><strong>Created <code>' + esc(c.name) + '</code>.</strong> It asks you before every tool until you change that in its Permissions tab.</div>' +
|
|
116
|
+
(c.scheduleError ? '<div class="error">Its schedule wasn' + String.fromCharCode(8217) + 't created: ' + esc(c.scheduleError) + '. Add one in its Schedules tab.</div>' : '') +
|
|
117
|
+
'<div><strong>Finish setup:</strong>' + checklistHtml(c.checklist) + '</div>' +
|
|
118
|
+
(c.exampleMessage ? '<div><strong>Try it</strong> in Chat with: <em>' + esc(c.exampleMessage) + '</em></div>' : '') +
|
|
119
|
+
'<div class="row"><a class="tp-btn" href="/agents/config?agent=' + encodeURIComponent(c.name) + '">Open ' + esc(c.name) + '</a>' +
|
|
120
|
+
'<a class="tp-btn plain" href="' + esc(leShell.tabHref(c.name, 'chat')) + '">Try it in Chat</a></div></div>';
|
|
121
|
+
}).catch(function () { btn.disabled = false; slot.querySelector('.tp-status').textContent = 'Could not reach the server; try again.'; });
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
show();
|
|
127
|
+
})();
|
|
128
|
+
</script>
|
|
129
|
+
</body>
|
|
130
|
+
</html>`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "loopengine",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.92",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Runtime for tool-using AI agents with a transparent ReAct loop.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -95,6 +95,7 @@
|
|
|
95
95
|
"dist/core/http-notifier.d.ts",
|
|
96
96
|
"dist/core/http-notify-triggers",
|
|
97
97
|
"dist/core/system-tools",
|
|
98
|
+
"dist/core/system-agents",
|
|
98
99
|
"dist/core/system-skills",
|
|
99
100
|
"dist/core/skillgarden",
|
|
100
101
|
"dist/core/durable-approvals.js",
|