openvibers/openvibe.actor Commits
The chat's sidebar is the network's one sidebar, with Actor's places as rows (#258)
Changes
@@@ -9,11 +9,11 @@"domain": "openvibe.actor","contracts": "openvibe-contracts v0.269.0","sdk": "openvibe-sdk v0.81.0",-- "shared": "openvibe-shared v4.96.0",++ "shared": "openvibe-shared v4.97.0","packages": ["openvibe-contracts v0.269.0","openvibe-sdk v0.81.0",-- "openvibe-shared v4.96.0"++ "openvibe-shared v4.97.0"],"summary": "Public at https://openvibe.actor (sudo ovhost deploy actor; unit openvibe-actor on 127.0.0.1:4950). A task in plain words is classified, routed by openvibe-sdk/placement to the agent system that can do it (the OpenVibe runtime acting through OpenVibe.Search and OpenVibe.Tools, OpenAI's web agent, an open model on OpenVibe's server for private mode), run with its steps streamed live, checked by a model of another family, and delivered as platform.task@1 with its cost to a fraction of a cent and the explanation; a failed agent or check hands it to the next agent. Free tier per person with an operator ceiling.","works": [@@@ -17,7 +17,7 @@"iovalkey": "^0.4.0","openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.269.0","openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.81.0",-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.96.0",++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.97.0","pg": "^8.23.0"},"devDependencies": {@@@ -1190,9 +1190,9 @@}},"node_modules/openvibe-shared": {-- "version": "4.96.0",-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.96.0",-- "integrity": "sha512-4+9RNAqu66FTRxYlWndmOVy7ZLFCXnQIJXiTO6n8LeUmX0eoL+y/70hKVbz7XmmX/3khqkehJYAn9Tq8mVmmVQ==",++ "version": "4.97.0",++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.97.0",++ "integrity": "sha512-1Lzemh84BvVaAV1oQNkMnOu6rtx/txsHedksKA1Xu/x24+Jtz43akAR/Yd/qpS2FFkQtc4+6nB79+iC05ny1Og==","license": "MIT","dependencies": {"jsonwebtoken": "^9.0.0",@@@ -30,7 +30,7 @@"iovalkey": "^0.4.0","openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.269.0","openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.81.0",-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.96.0",++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.97.0","pg": "^8.23.0"},"engines": {@@@ -272,7 +272,9 @@ ${acting ? '' : html`<form method="post" action="/tasks/${row.id}/answer" class=name: g.name,items: g.items.map((c) => ({ href: `/chat/${c.id}`, title: c.title, current: c.id === currentId, live: c.open })),})),-- foot: [{ href: '/console', label: 'Console' }, { href: '/me/agents', label: 'Your agents' }, { href: '/memory', label: 'Memory' }],++ findAction: '/chat',++ // Actor's places as the network sidebar's rows, as Codes' are (kit.sidebar, plan L35).++ nav: [{ href: '/console', label: 'Console', icon: 'grid' }, { href: '/me/agents', label: 'Your agents', icon: 'robot' }, { href: '/memory', label: 'Memory', icon: 'book' }],}));}@@@ -343,7 +345,8 @@ ${modelChip(model)}const title = first ? clip(first.task, 60) : 'New chat';return send(res, status, {viewer: req.viewer, config, path: req.originalUrl, title, app: true, noReferrer: true,-- css: ['css/chat.css'], scripts: ['js/chat.js'], styles: ['thread.css'], sharedScripts: ['ov-thread.js'],++ // The network's sidebar (kit.css, kit-web.js) and its conversation UI (thread.css, ov-thread.js).++ css: ['css/chat.css'], scripts: ['js/chat.js'], styles: ['kit.css', 'thread.css'], sharedScripts: ['kit-web.js', 'ov-thread.js'],body: html`${busy ? raw('<noscript><meta http-equiv="refresh" content="5"></noscript>') : ''}<div class="chat" data-chat="${first ? first.id : ''}">${raw(thread.page({sidebar: String(sidebar(chats, first ? first.id : null)),@@@ -60,7 +60,8 @@ const LOC = /^\/chat\/(tsk_[0-9A-HJKMNP-TV-Z]{26})#t-\1$/;assert.match(page.text, new RegExp(`<a class="ovt-act" href="/tasks/${first}\\?view=details">`), 'Details is the full task page');assert.match(page.text, /<div class="ovt-meta"><span>Balanced/);assert.match(page.text, new RegExp(`<input type="hidden" name="parent" value="${first}">`), 'the composer replies to the last turn');-- assert.match(page.text, new RegExp(`<a href="/chat/${first}" aria-current="page"`), 'the chat is in the list, marked as the one open');++ assert.match(page.text, new RegExp(`<a class="ovk-sidebar-item is-here" href="/chat/${first}" aria-current="page"`), 'the chat is in the list (the network\'s sidebar), marked as the one open');++ assert.match(page.text, /<nav class="ovk-sidebar-nav"[^>]*>[\s\S]*Console[\s\S]*Your agents[\s\S]*Memory/, 'Actor\'s places as rows, as Codes\' are');});await check('a reply continues the chat: both turns, in order, one chat in the list, with the turn before in mind', async () => {@@@ -74,8 +75,8 @@ const LOC = /^\/chat\/(tsk_[0-9A-HJKMNP-TV-Z]{26})#t-\1$/;const page = await t.get(`/chat/${at}`, { as: kim });const a = page.text.indexOf(`id="t-${first}"`), b = page.text.indexOf(`id="t-${second}"`);assert.ok(a > 0 && b > a, `the chat through ${at} shows both turns, oldest first`);-- assert.strictEqual((page.text.match(/<a href="\/chat\/tsk_/g) || []).length, 1, 'one chat in the list');-- assert.match(page.text, new RegExp(`<a href="/chat/${first}" aria-current="page"`), 'the list names a chat by its first turn');++ assert.strictEqual((page.text.match(/<a class="ovk-sidebar-item[^"]*" href="\/chat\/tsk_/g) || []).length, 1, 'one chat in the list');++ assert.match(page.text, new RegExp(`<a class="ovk-sidebar-item is-here" href="/chat/${first}" aria-current="page"`), 'the list names a chat by its first turn');}});
@@ -9,11 +9,11 @@
@@ -9,11 +9,11 @@
"domain": "openvibe.actor",
"domain": "openvibe.actor",
"contracts": "openvibe-contracts v0.269.0",
"contracts": "openvibe-contracts v0.269.0",
"sdk": "openvibe-sdk v0.81.0",
"sdk": "openvibe-sdk v0.81.0",
- "shared": "openvibe-shared v4.96.0",
+ "shared": "openvibe-shared v4.97.0",
"packages": [
"packages": [
"openvibe-contracts v0.269.0",
"openvibe-contracts v0.269.0",
"openvibe-sdk v0.81.0",
"openvibe-sdk v0.81.0",
- "openvibe-shared v4.96.0"
+ "openvibe-shared v4.97.0"
],
],
"summary": "Public at https://openvibe.actor (sudo ovhost deploy actor; unit openvibe-actor on 127.0.0.1:4950). A task in plain words is classified, routed by openvibe-sdk/placement to the agent system that can do it (the OpenVibe runtime acting through OpenVibe.Search and OpenVibe.Tools, OpenAI's web agent, an open model on OpenVibe's server for private mode), run with its steps streamed live, checked by a model of another family, and delivered as platform.task@1 with its cost to a fraction of a cent and the explanation; a failed agent or check hands it to the next agent. Free tier per person with an operator ceiling.",
"summary": "Public at https://openvibe.actor (sudo ovhost deploy actor; unit openvibe-actor on 127.0.0.1:4950). A task in plain words is classified, routed by openvibe-sdk/placement to the agent system that can do it (the OpenVibe runtime acting through OpenVibe.Search and OpenVibe.Tools, OpenAI's web agent, an open model on OpenVibe's server for private mode), run with its steps streamed live, checked by a model of another family, and delivered as platform.task@1 with its cost to a fraction of a cent and the explanation; a failed agent or check hands it to the next agent. Free tier per person with an operator ceiling.",
"works": [
"works": [
@@ -17,7 +17,7 @@
@@ -17,7 +17,7 @@
"iovalkey": "^0.4.0",
"iovalkey": "^0.4.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.269.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.269.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.81.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.81.0",
- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.96.0",
+ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.97.0",
"pg": "^8.23.0"
"pg": "^8.23.0"
},
},
"devDependencies": {
"devDependencies": {
@@ -1190,9 +1190,9 @@
@@ -1190,9 +1190,9 @@
}
}
},
},
"node_modules/openvibe-shared": {
"node_modules/openvibe-shared": {
- "version": "4.96.0",
- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.96.0",
- "integrity": "sha512-4+9RNAqu66FTRxYlWndmOVy7ZLFCXnQIJXiTO6n8LeUmX0eoL+y/70hKVbz7XmmX/3khqkehJYAn9Tq8mVmmVQ==",
+ "version": "4.97.0",
+ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.97.0",
+ "integrity": "sha512-1Lzemh84BvVaAV1oQNkMnOu6rtx/txsHedksKA1Xu/x24+Jtz43akAR/Yd/qpS2FFkQtc4+6nB79+iC05ny1Og==",
"license": "MIT",
"license": "MIT",
"dependencies": {
"dependencies": {
"jsonwebtoken": "^9.0.0",
"jsonwebtoken": "^9.0.0",
@@ -30,7 +30,7 @@
@@ -30,7 +30,7 @@
"iovalkey": "^0.4.0",
"iovalkey": "^0.4.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.269.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.269.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.81.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.81.0",
- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.96.0",
+ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.97.0",
"pg": "^8.23.0"
"pg": "^8.23.0"
},
},
"engines": {
"engines": {
@@ -272,7 +272,9 @@ ${acting ? '' : html`<form method="post" action="/tasks/${row.id}/answer" class=
@@ -272,7 +272,9 @@ ${acting ? '' : html`<form method="post" action="/tasks/${row.id}/answer" class=
name: g.name,
name: g.name,
items: g.items.map((c) => ({ href: `/chat/${c.id}`, title: c.title, current: c.id === currentId, live: c.open })),
items: g.items.map((c) => ({ href: `/chat/${c.id}`, title: c.title, current: c.id === currentId, live: c.open })),
})),
})),
- foot: [{ href: '/console', label: 'Console' }, { href: '/me/agents', label: 'Your agents' }, { href: '/memory', label: 'Memory' }],
+ findAction: '/chat',
+ // Actor's places as the network sidebar's rows, as Codes' are (kit.sidebar, plan L35).
+ nav: [{ href: '/console', label: 'Console', icon: 'grid' }, { href: '/me/agents', label: 'Your agents', icon: 'robot' }, { href: '/memory', label: 'Memory', icon: 'book' }],
}));
}));
}
}
@@ -343,7 +345,8 @@ ${modelChip(model)}
@@ -343,7 +345,8 @@ ${modelChip(model)}
const title = first ? clip(first.task, 60) : 'New chat';
const title = first ? clip(first.task, 60) : 'New chat';
return send(res, status, {
return send(res, status, {
viewer: req.viewer, config, path: req.originalUrl, title, app: true, noReferrer: true,
viewer: req.viewer, config, path: req.originalUrl, title, app: true, noReferrer: true,
- css: ['css/chat.css'], scripts: ['js/chat.js'], styles: ['thread.css'], sharedScripts: ['ov-thread.js'],
+ // The network's sidebar (kit.css, kit-web.js) and its conversation UI (thread.css, ov-thread.js).
+ css: ['css/chat.css'], scripts: ['js/chat.js'], styles: ['kit.css', 'thread.css'], sharedScripts: ['kit-web.js', 'ov-thread.js'],
body: html`${busy ? raw('<noscript><meta http-equiv="refresh" content="5"></noscript>') : ''}
body: html`${busy ? raw('<noscript><meta http-equiv="refresh" content="5"></noscript>') : ''}
<div class="chat" data-chat="${first ? first.id : ''}">${raw(thread.page({
<div class="chat" data-chat="${first ? first.id : ''}">${raw(thread.page({
sidebar: String(sidebar(chats, first ? first.id : null)),
sidebar: String(sidebar(chats, first ? first.id : null)),
@@ -60,7 +60,8 @@ const LOC = /^\/chat\/(tsk_[0-9A-HJKMNP-TV-Z]{26})#t-\1$/;
@@ -60,7 +60,8 @@ const LOC = /^\/chat\/(tsk_[0-9A-HJKMNP-TV-Z]{26})#t-\1$/;
assert.match(page.text, new RegExp(`<a class="ovt-act" href="/tasks/${first}\\?view=details">`), 'Details is the full task page');
assert.match(page.text, new RegExp(`<a class="ovt-act" href="/tasks/${first}\\?view=details">`), 'Details is the full task page');
assert.match(page.text, /<div class="ovt-meta"><span>Balanced/);
assert.match(page.text, /<div class="ovt-meta"><span>Balanced/);
assert.match(page.text, new RegExp(`<input type="hidden" name="parent" value="${first}">`), 'the composer replies to the last turn');
assert.match(page.text, new RegExp(`<input type="hidden" name="parent" value="${first}">`), 'the composer replies to the last turn');
- assert.match(page.text, new RegExp(`<a href="/chat/${first}" aria-current="page"`), 'the chat is in the list, marked as the one open');
+ assert.match(page.text, new RegExp(`<a class="ovk-sidebar-item is-here" href="/chat/${first}" aria-current="page"`), 'the chat is in the list (the network\'s sidebar), marked as the one open');
+ assert.match(page.text, /<nav class="ovk-sidebar-nav"[^>]*>[\s\S]*Console[\s\S]*Your agents[\s\S]*Memory/, 'Actor\'s places as rows, as Codes\' are');
});
});
await check('a reply continues the chat: both turns, in order, one chat in the list, with the turn before in mind', async () => {
await check('a reply continues the chat: both turns, in order, one chat in the list, with the turn before in mind', async () => {
@@ -74,8 +75,8 @@ const LOC = /^\/chat\/(tsk_[0-9A-HJKMNP-TV-Z]{26})#t-\1$/;
@@ -74,8 +75,8 @@ const LOC = /^\/chat\/(tsk_[0-9A-HJKMNP-TV-Z]{26})#t-\1$/;
const page = await t.get(`/chat/${at}`, { as: kim });
const page = await t.get(`/chat/${at}`, { as: kim });
const a = page.text.indexOf(`id="t-${first}"`), b = page.text.indexOf(`id="t-${second}"`);
const a = page.text.indexOf(`id="t-${first}"`), b = page.text.indexOf(`id="t-${second}"`);
assert.ok(a > 0 && b > a, `the chat through ${at} shows both turns, oldest first`);
assert.ok(a > 0 && b > a, `the chat through ${at} shows both turns, oldest first`);
- assert.strictEqual((page.text.match(/<a href="\/chat\/tsk_/g) || []).length, 1, 'one chat in the list');
- assert.match(page.text, new RegExp(`<a href="/chat/${first}" aria-current="page"`), 'the list names a chat by its first turn');
+ assert.strictEqual((page.text.match(/<a class="ovk-sidebar-item[^"]*" href="\/chat\/tsk_/g) || []).length, 1, 'one chat in the list');
+ assert.match(page.text, new RegExp(`<a class="ovk-sidebar-item is-here" href="/chat/${first}" aria-current="page"`), 'the list names a chat by its first turn');
}
}
});
});