Ship the batch: undo, parallel subagents, lazy MCP, hot-reloaded skills; docs and CI/CD
Loop and ergonomics batch across Now/Next and Maintenance:
- /undo and /redo via pre-prompt file snapshots (snapshot.ts)
- task takes a tasks[] array and runs investigations concurrently (subagent.ts)
- lazy MCP tools: mcp_list/mcp_inspect/mcp_call meta-tools, eager opt-in (mcp.ts, config.ts)
- skill tool reads its list live so a mid-session install is callable next turn (skills.ts)
- tool-name lists (tool-kinds.ts) derived from a mutating() marker; gates previously ungated writes
- prune/session recovery path summarized, and step-back doom-loop primitive (step-back.ts)
- @file completion re-walks on a slow cooldown; estimateTokens and pricing labeled as estimates
Docs: README, CHANGELOG, docs/{mcp,architecture,development} updated to match.
CI/CD: bun install-store cache and concurrency gates on both workflows; release.yml now
composes file-based release notes via scripts/make-release-notes.ts and verifies every binary.
This commit is contained in:
+69
-14
@@ -14,18 +14,19 @@ const call = async (tools: ToolSet, name: string, input: Record<string, unknown>
|
||||
return tool.execute(input as never, { toolCallId: 'x', messages: [] } as never);
|
||||
};
|
||||
|
||||
test('a stdio server contributes its tools under an mcp__ namespace', async () => {
|
||||
const mcp = await connectMcp({ stub: stdioServer() });
|
||||
test('a stdio server contributes its tools under an mcp__ namespace (eager)', async () => {
|
||||
const mcp = await connectMcp({ stub: stdioServer() }, 'eager');
|
||||
try {
|
||||
expect(Object.keys(mcp.tools).sort()).toEqual(['mcp__stub__ping', 'mcp__stub__search']);
|
||||
expect(mcp.errors).toEqual([]);
|
||||
expect(mcp.servers).toEqual([]);
|
||||
} finally {
|
||||
await mcp.close();
|
||||
}
|
||||
}, 30_000);
|
||||
|
||||
test('an mcp tool actually executes against the server', async () => {
|
||||
const mcp = await connectMcp({ stub: stdioServer() });
|
||||
test('an mcp tool actually executes against the server (eager)', async () => {
|
||||
const mcp = await connectMcp({ stub: stdioServer() }, 'eager');
|
||||
try {
|
||||
const out = await call(mcp.tools, 'mcp__stub__ping', { note: 'hello' });
|
||||
expect(JSON.stringify(out)).toContain('pong: hello');
|
||||
@@ -34,8 +35,8 @@ test('an mcp tool actually executes against the server', async () => {
|
||||
}
|
||||
}, 30_000);
|
||||
|
||||
test('two servers exposing the same tool name do not shadow each other', async () => {
|
||||
const mcp = await connectMcp({ a: stdioServer(), b: stdioServer() });
|
||||
test('two servers exposing the same tool name do not shadow each other (eager)', async () => {
|
||||
const mcp = await connectMcp({ a: stdioServer(), b: stdioServer() }, 'eager');
|
||||
try {
|
||||
expect(Object.keys(mcp.tools).sort()).toEqual([
|
||||
'mcp__a__ping',
|
||||
@@ -48,11 +49,14 @@ test('two servers exposing the same tool name do not shadow each other', async (
|
||||
}
|
||||
}, 30_000);
|
||||
|
||||
test('a server that fails to start is reported, not fatal', async () => {
|
||||
const mcp = await connectMcp({
|
||||
ok: stdioServer(),
|
||||
broken: { command: 'definitely-not-a-real-binary-xyz' },
|
||||
});
|
||||
test('a server that fails to start is reported, not fatal (eager)', async () => {
|
||||
const mcp = await connectMcp(
|
||||
{
|
||||
ok: stdioServer(),
|
||||
broken: { command: 'definitely-not-a-real-binary-xyz' },
|
||||
},
|
||||
'eager',
|
||||
);
|
||||
try {
|
||||
expect(Object.keys(mcp.tools)).toEqual(['mcp__ok__ping', 'mcp__ok__search']);
|
||||
expect(mcp.errors.map((e) => e.server)).toEqual(['broken']);
|
||||
@@ -62,9 +66,10 @@ test('a server that fails to start is reported, not fatal', async () => {
|
||||
}
|
||||
}, 30_000);
|
||||
|
||||
test('no configured servers yields no tools and no errors', async () => {
|
||||
test('no configured servers leaves the meta-tools naming none, with no errors', async () => {
|
||||
const mcp = await connectMcp({});
|
||||
expect(mcp.tools).toEqual({});
|
||||
expect(Object.keys(mcp.tools).sort()).toEqual(['mcp_call', 'mcp_inspect', 'mcp_list']);
|
||||
expect(mcp.servers).toEqual([]);
|
||||
expect(mcp.errors).toEqual([]);
|
||||
await mcp.close();
|
||||
});
|
||||
@@ -76,8 +81,58 @@ test('close is safe to call twice', async () => {
|
||||
});
|
||||
|
||||
test('an http server config is attempted and its failure reported', async () => {
|
||||
const mcp = await connectMcp({ remote: { url: 'http://127.0.0.1:1/mcp', type: 'http' } });
|
||||
const mcp = await connectMcp({ remote: { url: 'http://127.0.0.1:1/mcp', type: 'http' } }, 'eager');
|
||||
expect(Object.keys(mcp.tools)).toEqual([]);
|
||||
expect(mcp.errors.map((e) => e.server)).toEqual(['remote']);
|
||||
await mcp.close();
|
||||
}, 30_000);
|
||||
|
||||
test('lazy mode (default) registers only meta-tools, never server schemas', async () => {
|
||||
const mcp = await connectMcp({ stub: stdioServer() });
|
||||
try {
|
||||
// The request is spared every server schema: only three meta-tools exist.
|
||||
expect(Object.keys(mcp.tools).sort()).toEqual(['mcp_call', 'mcp_inspect', 'mcp_list']);
|
||||
// But the prompt knows which servers are connected.
|
||||
expect(mcp.servers).toEqual(['stub']);
|
||||
} finally {
|
||||
await mcp.close();
|
||||
}
|
||||
}, 30_000);
|
||||
|
||||
test('mcp_list names a server tools and mcp_inspect reads a schema without calling it', async () => {
|
||||
const mcp = await connectMcp({ stub: stdioServer() });
|
||||
try {
|
||||
await call(mcp.tools, 'mcp_list', { server: 'stub' }).then((out) =>
|
||||
expect(JSON.stringify(out)).toContain('search'),
|
||||
);
|
||||
await call(mcp.tools, 'mcp_inspect', { server: 'stub', toolName: 'ping' }).then((out) =>
|
||||
expect(JSON.stringify(out)).toContain('note'),
|
||||
);
|
||||
} finally {
|
||||
await mcp.close();
|
||||
}
|
||||
}, 30_000);
|
||||
|
||||
test('mcp_call executes a server tool by name', async () => {
|
||||
const mcp = await connectMcp({ stub: stdioServer() });
|
||||
try {
|
||||
const out = await call(mcp.tools, 'mcp_call', { server: 'stub', toolName: 'ping', args: { note: 'lazy' } });
|
||||
expect(JSON.stringify(out)).toContain('pong: lazy');
|
||||
} finally {
|
||||
await mcp.close();
|
||||
}
|
||||
}, 30_000);
|
||||
|
||||
test('mcp_call against an unknown server names the live set', async () => {
|
||||
const mcp = await connectMcp({ stub: stdioServer() });
|
||||
try {
|
||||
await call(mcp.tools, 'mcp_call', { server: 'nope', toolName: 'ping', args: {} }).then(
|
||||
() => {
|
||||
throw new Error('an unknown server must reject');
|
||||
},
|
||||
(e) => expect(String(e)).toContain('nope'),
|
||||
);
|
||||
} finally {
|
||||
await mcp.close();
|
||||
}
|
||||
}, 30_000);
|
||||
|
||||
Reference in New Issue
Block a user