mirror of
https://github.com/garrytan/gbrain.git
synced 2026-08-14 00:48:18 +00:00
fix(skills): advertise usable tools on stdio transport (#3725)
Wave-assembled from PR #3725 by @gregario. Co-Authored-By: Greg Jackson <gregj64@gmail.com>
This commit is contained in:
committed by
Sina Matian
co-authored by
Greg Jackson
parent
8d5bdfe125
commit
9b6db85d39
@@ -295,6 +295,7 @@ export function confineManifestPath(skillsDir: string, entry: ManifestEntry): st
|
||||
function opCallableByCaller(op: Operation, ctx: OperationContext): boolean {
|
||||
if (ctx.remote === false) return true; // local CLI — OS is the trust boundary
|
||||
if (op.localOnly) return false; // not reachable over a remote transport
|
||||
if (ctx.transport === 'stdio') return true; // auth-less local pipe — dispatch enforces no scopes
|
||||
return hasScope(ctx.auth?.scopes ?? [], op.scope ?? 'read');
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ function unpack(res: { content: { text: string }[]; isError?: boolean }): {
|
||||
async function call(
|
||||
name: string,
|
||||
params: Record<string, unknown>,
|
||||
opts: { remote: boolean; auth?: AuthInfo },
|
||||
opts: { remote: boolean; auth?: AuthInfo; transport?: 'stdio' },
|
||||
) {
|
||||
return unpack(await dispatchToolCall(engine, name, params, { sourceId: 'default', ...opts }));
|
||||
}
|
||||
@@ -139,3 +139,32 @@ describe('get_skill over dispatch', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// #3635: stdio transport must see usable_tools, not empty
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('stdio transport — catalog advertises tools as usable (#3635)', () => {
|
||||
test('list_skills over stdio reports brain-ops tools in usable_tools', async () => {
|
||||
await withEnv({ GBRAIN_HOME: home }, async () => {
|
||||
await engine.setConfig('mcp.publish_skills', 'true');
|
||||
const r = await call('list_skills', {}, { remote: true, transport: 'stdio' });
|
||||
expect(r.isError).toBe(false);
|
||||
const bo = r.body.skills.find((s: any) => s.name === 'brain-ops');
|
||||
expect(bo.usable_tools).toContain('search');
|
||||
expect(bo.usable_tools).toContain('put_page');
|
||||
expect(bo.unavailable_tools).not.toContain('search');
|
||||
expect(bo.unavailable_tools).not.toContain('put_page');
|
||||
});
|
||||
});
|
||||
|
||||
test('localOnly ops remain unavailable on stdio', async () => {
|
||||
await withEnv({ GBRAIN_HOME: home }, async () => {
|
||||
await engine.setConfig('mcp.publish_skills', 'true');
|
||||
const r = await call('list_skills', {}, { remote: true, transport: 'stdio' });
|
||||
expect(r.isError).toBe(false);
|
||||
const allUsable = r.body.skills.flatMap((s: any) => s.usable_tools);
|
||||
expect(allUsable).not.toContain('purge_deleted_pages');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user