Adds plugin kind `channel` (interfaceVersion 1, dispatch(request, {call}))
with cli and webui modules. Project and thread surfaces and thread
talk/follow in the CLI and the Console chat go through the selected
channel. An empty or absent channel selection is off: the CLI exits 3 and
the Console answers 503, each naming `mosaic plugins` and `mosaic plugins
set` with the business selector. Management plugins and plugins.set stay
on the core transport. The loader gains a synchronous snapshot(kind)
getter; loaded(), modules() and last-good handling are unchanged. No lock
is held across dispatch. serve.mjs, public/ and the bus are untouched.
Owner Rocko. Reviewer Dewey: r1 changes (comment 28980, B1: the recovery
sentence was never asserted), r2 approve (comment 28984) on candidate
manifest ae2fcfda...1fc8, the B1 assert killing mutant D1. Design accepted
by Mos (mos-0768, mos-0773). Fixture rewrite at project.test.mjs:47 acked
by Mos (mos-0789) on Dewey's line-by-line check: lines 48-51 identical,
one added assert. Sage gate on e5b10d275: 25 steps green, 2081 package tests, 156 queue node tests, 422 script selftests, 0 failed.
Live stays as pinned. The re-pin that takes this live puts `mosaic
plugins set` in Jason's window right after activate (mos-0768).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
27 lines
1.4 KiB
JavaScript
27 lines
1.4 KiB
JavaScript
// Row 129: the single seam between Console chat operations and the current human transport.
|
|
// No browser-selected bus verb, tenant, owner, capability or message class crosses this seam.
|
|
import { createChannelCaller } from '../../plugins/src/channel.mjs';
|
|
import { PluginError } from '../../plugins/src/kinds.mjs';
|
|
import { BusReadError } from './bus.mjs';
|
|
|
|
export function createChat({ call }) {
|
|
if (typeof call !== 'function') throw new TypeError('chat needs a human transport');
|
|
const dispatch = createChannelCaller({ name: 'webui', call });
|
|
const channel = async (verb, args) => {
|
|
try { return await dispatch(verb, args); }
|
|
catch (err) {
|
|
if (err instanceof PluginError) throw new BusReadError(err.code, err.message);
|
|
throw err;
|
|
}
|
|
};
|
|
return Object.freeze({
|
|
projects: () => channel('project.list', {}),
|
|
createProject: ({ name, repo }) => channel('project.create', { name, ...(repo === undefined ? {} : { repo }) }),
|
|
threads: ({ project } = {}) => channel('thread.list', project === undefined ? {} : { project }),
|
|
createThread: ({ project, name }) => channel('thread.create', { project, name }),
|
|
messages: ({ thread, after, limit }) => channel('thread.messages', { thread, ...(after ? { after } : {}), limit }),
|
|
send: ({ thread, body }) => channel('thread.send', { thread, body, class: 'REQUEST' }),
|
|
open: ({ thread }) => channel('thread.open', { thread }),
|
|
});
|
|
}
|