openvibers/openvibe.shared Commits
4.24.3: agent-session's web steps read as lookups (web_search and web_fetch before file searches) (#153)
Changes
@@@ -6,6 +6,12 @@ A release is the git tag `vX.Y.Z`; consumers pin the tag's tarball (see README).## Unreleased++## 4.24.3 — 2026-10-28++++- **`agent-session.js`: web steps read as lookups.** A tool whose name speaks of the web (`web_search`, `web_fetch`) is++ a web step before a file search, and a query given as its description reads "Looked up …". An address reads++ "Opened …". OpenVibe.Actor's web searches showed as "Listed …".++## 4.24.2 — 2026-10-28- **`agent-session.js` takes `link(url)`**, which decides which https addresses in an agent's text become links; the@@@ -2,7 +2,7 @@> Versioned UI, the OpenVibe Frame (the navbar, footer and "shipped" views every site sits in), SEO, legal and release-client packages every OpenVibe site renders.--**Status:** alpha, v4.24.2 (every release is a tag; see [CHANGELOG.md](CHANGELOG.md)). Every deployed++**Status:** alpha, v4.24.3 (every release is a tag; see [CHANGELOG.md](CHANGELOG.md)). Every deployedconsumer installs a tagged release and none keeps a vendored copy([docs/migration-plan.md](docs/migration-plan.md) is done); each repository's `package.json` namesthe tag it pins.@@@ -4,7 +4,7 @@"code": true,"wave": "W2","package": "openvibe-shared",-- "version": "4.24.2",++ "version": "4.24.3","plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)","deployed": false,"deployment": "none of its own: a package released as git tags; OpenVibe.Network serves /shared/* from its pinned tag, and a site can serve its own pinned copy (openvibe-shared/serve)",@@@ -55,8 +55,9 @@if (KIND[name]) return KIND[name];const w = new Set(String(name || '').replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase().split(/[^a-z]+/).filter(Boolean));const any = (...xs) => xs.some((x) => w.has(x));-- return any('bash', 'shell', 'command', 'exec', 'run', 'terminal') ? 'command' : any('edit', 'patch', 'replace') ? 'edit' : any('write', 'create') ? 'write'-- : any('read', 'cat', 'view', 'open') ? 'read' : any('grep', 'glob', 'find', 'search', 'list', 'ls') ? 'search' : any('web', 'fetch', 'http', 'browse', 'url') ? 'web' : 'tool';++ // The web first: web_search and web_fetch are looking things up, not searching files.++ return any('web', 'fetch', 'http', 'browse', 'url', 'internet') ? 'web' : any('bash', 'shell', 'command', 'exec', 'run', 'terminal') ? 'command' : any('edit', 'patch', 'replace') ? 'edit'++ : any('write', 'create') ? 'write' : any('read', 'cat', 'view', 'open') ? 'read' : any('grep', 'glob', 'find', 'search', 'list', 'ls') ? 'search' : 'tool';}const NOUN = { command: ['command', 'commands'], read: ['read', 'reads'], search: ['search', 'searches'], edit: ['edit', 'edits'], write: ['new file', 'new files'], web: ['lookup', 'lookups'], agent: ['helper', 'helpers'], plan: ['plan', 'plan'], tool: ['tool', 'tools'] };const VERB = {@@@ -208,7 +209,11 @@if (edits.length) { out.diff = []; edits.forEach((e, n) => { if (n) out.diff.push(['@', '…']); out.diff.push(...diffLines(e.old_string, e.new_string)); }); }else if (typeof i.content === 'string') { out.preview = i.content; out.diff = i.content.split('\n').map((l) => ['+', l]); }if (out.diff) out.diff.forEach(([op]) => { if (op === '+') out.added++; else if (op === '-') out.removed++; });-- } else if (k === 'web') { out.title = i.query ? `Looked up ${i.query}` : `Opened ${String(i.url || step.what || '').replace(/^https?:\/\//, '').slice(0, 60)}`; out.sub = String(i.url || ''); }++ } else if (k === 'web') {++ const asked = i.query || (!i.url && !/^https?:\/\//.test(String(i.description || step.what || '')) ? i.description || step.what : '');++ const url = i.url || (/^https?:\/\//.test(String(i.description || step.what || '')) ? i.description || step.what : '');++ out.title = asked ? `Looked up ${asked}` : `Opened ${String(url).replace(/^https?:\/\//, '').slice(0, 60)}`; out.sub = asked ? '' : String(url);++ }else if (k === 'agent') { out.title = String(i.description || 'A helper agent'); out.sub = i.subagent_type ? `${i.subagent_type} helper` : 'helper'; out.preview = String(i.prompt || ''); }else if (k === 'plan') { out.title = 'Updated the plan'; }else { out.title = String(step.name || 'Tool'); out.sub = String(step.what || ''); }@@@ -1,6 +1,6 @@{"name": "openvibe-shared",-- "version": "4.24.2",++ "version": "4.24.3","description": "Shared navbar, footer, themes, icons, legal pages, SEO, auth and analytics for every OpenVibe site","main": "index.js","bin": {@@@ -21,6 +21,7 @@ assert.deepStrictEqual(['Bash', 'run_command', 'Read', 'Grep', 'Edit', 'write_fi['command', 'command', 'read', 'search', 'edit', 'write', 'web', 'agent', 'plan', 'command', 'tool'], 'every agent\'s tools map to the same kinds');assert.deepStrictEqual(as.diffLines('a\nb\nc', 'a\nB\nc'), [['=', 'a'], ['-', 'b'], ['+', 'B'], ['=', 'c']], 'a changed line is a removal and an addition');assert.deepStrictEqual(as.diffLines('', 'x'), [['-', ''], ['+', 'x']]);++assert.deepStrictEqual(['web_search', 'web_fetch', 'search_files'].map(as.kindOf), ['web', 'web', 'search'], 'the web before files (4.24.3)');// OpenVibe.Actor's task events (actor.task-event@1) read like the rest (4.24.1).assert.deepStrictEqual(as.normalize({ kind: 'state', state: 'running', seq: 2 }), [{ t: 'state', state: 'running' }]);assert.deepStrictEqual(as.normalize({ kind: 'output', step: 'plan', agent: 'deepseek', text: 'DeepSeek takes it' }), [{ t: 'step', text: 'DeepSeek takes it', agent: 'deepseek' }]);
@@ -6,6 +6,12 @@ A release is the git tag `vX.Y.Z`; consumers pin the tag's tarball (see README).
@@ -6,6 +6,12 @@ A release is the git tag `vX.Y.Z`; consumers pin the tag's tarball (see README).
## Unreleased
## Unreleased
+## 4.24.3 — 2026-10-28
+
+- **`agent-session.js`: web steps read as lookups.** A tool whose name speaks of the web (`web_search`, `web_fetch`) is
+ a web step before a file search, and a query given as its description reads "Looked up …". An address reads
+ "Opened …". OpenVibe.Actor's web searches showed as "Listed …".
+
## 4.24.2 — 2026-10-28
## 4.24.2 — 2026-10-28
- **`agent-session.js` takes `link(url)`**, which decides which https addresses in an agent's text become links; the
- **`agent-session.js` takes `link(url)`**, which decides which https addresses in an agent's text become links; the
@@ -2,7 +2,7 @@
@@ -2,7 +2,7 @@
> Versioned UI, the OpenVibe Frame (the navbar, footer and "shipped" views every site sits in), SEO, legal and release-client packages every OpenVibe site renders.
> Versioned UI, the OpenVibe Frame (the navbar, footer and "shipped" views every site sits in), SEO, legal and release-client packages every OpenVibe site renders.
-**Status:** alpha, v4.24.2 (every release is a tag; see [CHANGELOG.md](CHANGELOG.md)). Every deployed
+**Status:** alpha, v4.24.3 (every release is a tag; see [CHANGELOG.md](CHANGELOG.md)). Every deployed
consumer installs a tagged release and none keeps a vendored copy
consumer installs a tagged release and none keeps a vendored copy
([docs/migration-plan.md](docs/migration-plan.md) is done); each repository's `package.json` names
([docs/migration-plan.md](docs/migration-plan.md) is done); each repository's `package.json` names
the tag it pins.
the tag it pins.
@@ -4,7 +4,7 @@
@@ -4,7 +4,7 @@
"code": true,
"code": true,
"wave": "W2",
"wave": "W2",
"package": "openvibe-shared",
"package": "openvibe-shared",
- "version": "4.24.2",
+ "version": "4.24.3",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"deployed": false,
"deployed": false,
"deployment": "none of its own: a package released as git tags; OpenVibe.Network serves /shared/* from its pinned tag, and a site can serve its own pinned copy (openvibe-shared/serve)",
"deployment": "none of its own: a package released as git tags; OpenVibe.Network serves /shared/* from its pinned tag, and a site can serve its own pinned copy (openvibe-shared/serve)",
@@ -55,8 +55,9 @@
@@ -55,8 +55,9 @@
if (KIND[name]) return KIND[name];
if (KIND[name]) return KIND[name];
const w = new Set(String(name || '').replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase().split(/[^a-z]+/).filter(Boolean));
const w = new Set(String(name || '').replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase().split(/[^a-z]+/).filter(Boolean));
const any = (...xs) => xs.some((x) => w.has(x));
const any = (...xs) => xs.some((x) => w.has(x));
- return any('bash', 'shell', 'command', 'exec', 'run', 'terminal') ? 'command' : any('edit', 'patch', 'replace') ? 'edit' : any('write', 'create') ? 'write'
- : any('read', 'cat', 'view', 'open') ? 'read' : any('grep', 'glob', 'find', 'search', 'list', 'ls') ? 'search' : any('web', 'fetch', 'http', 'browse', 'url') ? 'web' : 'tool';
+ // The web first: web_search and web_fetch are looking things up, not searching files.
+ return any('web', 'fetch', 'http', 'browse', 'url', 'internet') ? 'web' : any('bash', 'shell', 'command', 'exec', 'run', 'terminal') ? 'command' : any('edit', 'patch', 'replace') ? 'edit'
+ : any('write', 'create') ? 'write' : any('read', 'cat', 'view', 'open') ? 'read' : any('grep', 'glob', 'find', 'search', 'list', 'ls') ? 'search' : 'tool';
}
}
const NOUN = { command: ['command', 'commands'], read: ['read', 'reads'], search: ['search', 'searches'], edit: ['edit', 'edits'], write: ['new file', 'new files'], web: ['lookup', 'lookups'], agent: ['helper', 'helpers'], plan: ['plan', 'plan'], tool: ['tool', 'tools'] };
const NOUN = { command: ['command', 'commands'], read: ['read', 'reads'], search: ['search', 'searches'], edit: ['edit', 'edits'], write: ['new file', 'new files'], web: ['lookup', 'lookups'], agent: ['helper', 'helpers'], plan: ['plan', 'plan'], tool: ['tool', 'tools'] };
const VERB = {
const VERB = {
@@ -208,7 +209,11 @@
@@ -208,7 +209,11 @@
if (edits.length) { out.diff = []; edits.forEach((e, n) => { if (n) out.diff.push(['@', '…']); out.diff.push(...diffLines(e.old_string, e.new_string)); }); }
if (edits.length) { out.diff = []; edits.forEach((e, n) => { if (n) out.diff.push(['@', '…']); out.diff.push(...diffLines(e.old_string, e.new_string)); }); }
else if (typeof i.content === 'string') { out.preview = i.content; out.diff = i.content.split('\n').map((l) => ['+', l]); }
else if (typeof i.content === 'string') { out.preview = i.content; out.diff = i.content.split('\n').map((l) => ['+', l]); }
if (out.diff) out.diff.forEach(([op]) => { if (op === '+') out.added++; else if (op === '-') out.removed++; });
if (out.diff) out.diff.forEach(([op]) => { if (op === '+') out.added++; else if (op === '-') out.removed++; });
- } else if (k === 'web') { out.title = i.query ? `Looked up ${i.query}` : `Opened ${String(i.url || step.what || '').replace(/^https?:\/\//, '').slice(0, 60)}`; out.sub = String(i.url || ''); }
+ } else if (k === 'web') {
+ const asked = i.query || (!i.url && !/^https?:\/\//.test(String(i.description || step.what || '')) ? i.description || step.what : '');
+ const url = i.url || (/^https?:\/\//.test(String(i.description || step.what || '')) ? i.description || step.what : '');
+ out.title = asked ? `Looked up ${asked}` : `Opened ${String(url).replace(/^https?:\/\//, '').slice(0, 60)}`; out.sub = asked ? '' : String(url);
+ }
else if (k === 'agent') { out.title = String(i.description || 'A helper agent'); out.sub = i.subagent_type ? `${i.subagent_type} helper` : 'helper'; out.preview = String(i.prompt || ''); }
else if (k === 'agent') { out.title = String(i.description || 'A helper agent'); out.sub = i.subagent_type ? `${i.subagent_type} helper` : 'helper'; out.preview = String(i.prompt || ''); }
else if (k === 'plan') { out.title = 'Updated the plan'; }
else if (k === 'plan') { out.title = 'Updated the plan'; }
else { out.title = String(step.name || 'Tool'); out.sub = String(step.what || ''); }
else { out.title = String(step.name || 'Tool'); out.sub = String(step.what || ''); }
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-shared",
"name": "openvibe-shared",
- "version": "4.24.2",
+ "version": "4.24.3",
"description": "Shared navbar, footer, themes, icons, legal pages, SEO, auth and analytics for every OpenVibe site",
"description": "Shared navbar, footer, themes, icons, legal pages, SEO, auth and analytics for every OpenVibe site",
"main": "index.js",
"main": "index.js",
"bin": {
"bin": {
@@ -21,6 +21,7 @@ assert.deepStrictEqual(['Bash', 'run_command', 'Read', 'Grep', 'Edit', 'write_fi
@@ -21,6 +21,7 @@ assert.deepStrictEqual(['Bash', 'run_command', 'Read', 'Grep', 'Edit', 'write_fi
['command', 'command', 'read', 'search', 'edit', 'write', 'web', 'agent', 'plan', 'command', 'tool'], 'every agent\'s tools map to the same kinds');
['command', 'command', 'read', 'search', 'edit', 'write', 'web', 'agent', 'plan', 'command', 'tool'], 'every agent\'s tools map to the same kinds');
assert.deepStrictEqual(as.diffLines('a\nb\nc', 'a\nB\nc'), [['=', 'a'], ['-', 'b'], ['+', 'B'], ['=', 'c']], 'a changed line is a removal and an addition');
assert.deepStrictEqual(as.diffLines('a\nb\nc', 'a\nB\nc'), [['=', 'a'], ['-', 'b'], ['+', 'B'], ['=', 'c']], 'a changed line is a removal and an addition');
assert.deepStrictEqual(as.diffLines('', 'x'), [['-', ''], ['+', 'x']]);
assert.deepStrictEqual(as.diffLines('', 'x'), [['-', ''], ['+', 'x']]);
+assert.deepStrictEqual(['web_search', 'web_fetch', 'search_files'].map(as.kindOf), ['web', 'web', 'search'], 'the web before files (4.24.3)');
// OpenVibe.Actor's task events (actor.task-event@1) read like the rest (4.24.1).
// OpenVibe.Actor's task events (actor.task-event@1) read like the rest (4.24.1).
assert.deepStrictEqual(as.normalize({ kind: 'state', state: 'running', seq: 2 }), [{ t: 'state', state: 'running' }]);
assert.deepStrictEqual(as.normalize({ kind: 'state', state: 'running', seq: 2 }), [{ t: 'state', state: 'running' }]);
assert.deepStrictEqual(as.normalize({ kind: 'output', step: 'plan', agent: 'deepseek', text: 'DeepSeek takes it' }), [{ t: 'step', text: 'DeepSeek takes it', agent: 'deepseek' }]);
assert.deepStrictEqual(as.normalize({ kind: 'output', step: 'plan', agent: 'deepseek', text: 'DeepSeek takes it' }), [{ t: 'step', text: 'DeepSeek takes it', agent: 'deepseek' }]);