update agents skill design

This commit is contained in:
2026-08-20 18:18:10 +05:30
parent 161b237695
commit b2e6868824
75 changed files with 14586 additions and 98 deletions

View File

@@ -27,7 +27,52 @@
*/
import { getContext } from './contexts';
import { toSnapshots } from './blocks';
import { note, toSnapshots } from './blocks';
/**
* An answer, at the depth the agent asked for.
*
* Three modes, and only two of them do anything: `balanced` is today's
* behaviour exactly, so every existing answer and every agent that declares no
* reasoning is unchanged.
*
* `webSearch` is handled here too, and handled honestly. No search provider is
* configured in this deployment, so an agent with the flag set gets a note
* saying so rather than an answer that quietly came from nowhere. Silently
* ignoring the flag would be worse: the configuration would read as working.
*/
function shapeForDepth(document, agent, facts) {
if (!agent || !document?.blocks?.length) return document;
const blocks = [...document.blocks];
if (agent.reasoning === 'fast') {
/* The headline and the first supporting block. Enough to answer, without
the breakdown someone asking a quick question did not want. */
const trimmed = blocks.slice(0, 2);
return { ...document, blocks: trimmed.length ? trimmed : blocks };
}
if (agent.reasoning === 'deep') {
const counted = [
facts?.applications?.length != null && `${facts.applications.length} applications`,
facts?.postings?.length != null && `${facts.postings.length} positions`,
facts?.staff?.length != null && `${facts.staff.length} hires`,
].filter(Boolean);
if (counted.length) {
blocks.push(note(`Read from ${counted.join(', ')} on this page.`));
}
}
if (agent.webSearch) {
blocks.push(note(
'Web search is enabled on this agent, but no search provider is configured '
+ 'in this deployment, so nothing outside this workspace was consulted.'
));
}
return { ...document, blocks };
}
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
@@ -41,7 +86,7 @@ export function createLocalProvider({ latency = 380, frameDelay = 26 } = {}) {
return {
id: 'local',
async *stream({ contextId, capability, question, facts, signal }) {
async *stream({ contextId, capability, question, facts, agent = null, signal }) {
const context = getContext(contextId);
if (!context) throw new Error(`Unknown assistant context: ${contextId}`);
@@ -50,12 +95,25 @@ export function createLocalProvider({ latency = 380, frameDelay = 26 } = {}) {
?? context.respond(question, facts)
: context.respond(question, facts);
/**
* The agent's reasoning mode, as answer depth.
*
* A real configuration effect rather than a label: `fast` returns the
* headline and stops, `deep` says which records the reading counted.
* `balanced` — the default, and what an agent that declares nothing gets
* — is untouched, so this cannot change any existing answer.
*
* Depth never changes *what* was read. The page decided that before the
* provider was called; this only decides how much of it to say.
*/
const shaped = shapeForDepth(document, agent, facts);
// A brief pause before the first frame, so the answer reads as considered
// rather than precomputed.
await sleep(latency);
if (signal?.aborted) return;
for (const snapshot of toSnapshots(document)) {
for (const snapshot of toSnapshots(shaped)) {
if (signal?.aborted) return;
yield snapshot;
await sleep(frameDelay);
@@ -83,11 +141,15 @@ export function createHttpProvider({ endpoint, headers = {} }) {
return {
id: 'http',
async *stream({ contextId, capability, question, signal }) {
async *stream({ contextId, capability, question, agent = null, owliverContext = null, signal }) {
const response = await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json', ...headers },
body: JSON.stringify({ contextId, capability, question }),
/* `agent` and `owliverContext` travel; the fact sheet still does not.
Dashboard records are read server-side from the caller's own session,
so the client cannot ask about records it is not entitled to see —
and an agent cannot widen that by being named in the body. */
body: JSON.stringify({ contextId, capability, question, agent, owliverContext }),
signal,
});