feat: add economy/maximum presets, tool-lab and subagent-cursor extensions
Some checks failed
CI / windows node 24 / wine blocking (push) Has been skipped
CI / node 22.19 (push) Has been skipped
CI / node 26 (push) Has been skipped
CI / python 3.10 / keyless SDK (push) Has been skipped
CI / python runtime / release-shaped Linux x64 (push) Has been skipped
CI / wine apt cache (push) Successful in 7s
CI / serial / linux (push) Has been skipped
Deploy documentation / build (push) Failing after 1m25s
Deploy documentation / deploy (push) Has been skipped
Landlock Run / Matrix (push) Successful in 5s
Release (vendor) / Pack npm tarballs (push) Failing after 2m47s
Release (dsh) / Pack npm tarballs (push) Failing after 1m56s
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Failing after 1m57s
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Failing after 1m19s
Release (vendor) / Publish to npm (push) Has been skipped
Release (dsh) / Publish to npm (push) Has been skipped
CI / serial / windows (self-hosted standby) (push) Has been cancelled
CI / larger-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, typecheck) (push) Has been cancelled
Landlock Run / darwin (no platform package — degradation proof) (push) Has been cancelled
Landlock Run / ${{ matrix.platform }} (push) Has been cancelled
CI / node 24 / static (push) Has been cancelled
CI / node 24 / coverage (push) Has been cancelled
CI / node 24 / snapshots and artifacts (push) Has been cancelled
CI / windows node 24 / native complete (push) Has been cancelled
CI / serial / linux (self-hosted standby) (push) Has been cancelled
CI / serial / macos (push) Has been cancelled
CI / larger-runner-benchmark (16, windows, dsh-windows-2025-16core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Has been cancelled
CI / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Has been cancelled
CI / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Has been cancelled
CI / consolidated-runner-benchmark (4, windows, dsh-windows-2025-4core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Has been cancelled
CI / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Has been cancelled
CI / all checks passed (push) Has been cancelled
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Has been cancelled
CI / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Has been cancelled
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Has been cancelled
E2E (real DeepSeek API) / e2e (push) Failing after 1m24s

- new economy and maximum agent presets with three-role pipeline skill
- new packages/extensions/tool-lab (home-lab ComfyUI/Docling/Whishper tools)
- new packages/subagent/subagent-cursor provider
- openrouter balance UI with on-demand refresh
- session projection context-seed boundary fold
- regenerate docs catalogs; keep local searxng benchmark scripts
This commit is contained in:
2026-08-23 22:12:30 +07:00
parent e818e37f0a
commit 8719fa84f0
112 changed files with 5686 additions and 169 deletions

View File

@@ -150,6 +150,21 @@ function enablePresetTool(composition: string, id: string): string {
return composition.slice(0, disabled) + composition.slice(disabled + ' disabled: true\n'.length)
}
function disablePresetTool(composition: string, id: string): string {
const row = ` - id: ${id}\n`
const start = composition.indexOf(row)
if (start < 0) throw new Error(`missing preset row ${id}`)
const end = composition.indexOf('\n - id:', start + row.length)
const disabled = composition.indexOf(' disabled: true\n', start)
if (disabled >= 0 && (end < 0 || disabled < end)) {
throw new Error(`preset row ${id} is already disabled`)
}
// `disabled` is entry metadata, so it goes beside `name` rather than inside
// the row's `config`.
const nameLine = composition.indexOf('\n', start + row.length) + 1
return `${composition.slice(0, nameLine)} disabled: true\n${composition.slice(nameLine)}`
}
let ctx: Context
beforeAll(async () => {
const settingsFile = join(await mkdtemp(join(tmpdir(), 'dsh-web-presets-')), 'settings.yaml')
@@ -197,7 +212,7 @@ describe('the shipped Web composition', () => {
it('supplies both shipped presets, and only those, from the system root', async () => {
const listed = await ctx.agentPresets.list()
expect(listed.map(preset => preset.id).sort()).toEqual(['code', 'cordis', 'minimal', 'standard'])
expect(listed.map(preset => preset.id).sort()).toEqual(['code', 'cordis', 'economy', 'maximum', 'minimal', 'standard'])
expect(listed.every(preset => preset.trust === 'system')).toBe(true)
expect(ctx.agentPresets.defaultId).toBe('standard')
})
@@ -216,7 +231,8 @@ describe('the shipped Web composition', () => {
expect(toolNames(ctx, handle.agent).filter(name => name !== 'glob' && name !== 'grep')).toEqual([
'ask_user_question', 'bash', 'create_goal', 'edit', 'exit_plan_mode',
'get_goal', 'interrupt_agent', 'job_kill', 'job_list', 'job_output', 'list_agents', 'ralph', 'read', 'read_image', 'send_message', 'skill',
'subagent', 'subagent_fork', 'todo_write', 'update_goal', 'web_search',
'subagent', 'subagent_claude_code', 'subagent_codex', 'subagent_cursor',
'subagent_fork', 'todo_write', 'update_goal', 'web_search',
'workflow', 'write',
])
} finally {
@@ -224,6 +240,75 @@ describe('the shipped Web composition', () => {
}
})
it('composes the economy agent without external subagent providers', async () => {
const handle = await ctx.agents.create({
sessionId: SessionId('preset-economy'),
setup: agentCtx => ctx.agentPresets.mount(agentCtx, 'economy').then(() => undefined),
})
try {
const toolList = toolNames(ctx, handle.agent).filter(name => name !== 'glob' && name !== 'grep')
// The shell row is platform-gated like `standard`'s: bash off Windows,
// pwsh on it. Everything else is the standard catalog.
const shell = process.platform === 'win32' ? 'pwsh' : 'bash'
// `economy` keeps every standard tool except the external product
// agents, which it disables to avoid paid delegations by default.
expect(toolList).toEqual(expect.arrayContaining([
'ask_user_question', shell, 'create_goal', 'edit', 'exit_plan_mode',
'get_goal', 'interrupt_agent', 'job_kill', 'job_list', 'job_output', 'list_agents', 'ralph', 'read', 'read_image', 'send_message', 'skill',
'subagent', 'subagent_fork', 'todo_write', 'update_goal', 'web_search',
'workflow', 'write',
]))
expect(toolList).not.toEqual(expect.arrayContaining([
'subagent_codex', 'subagent_claude_code', 'subagent_cursor',
]))
// The delegation tools default to foreground: one-shot, not the
// continuable background scheduling `standard` uses.
const subagent = ctx.tools.schemas(handle.agent).find(schema => schema.name === 'subagent')
expect(subagent?.description).toContain('This call waits for the result by default.')
} finally {
await handle.dispose()
}
})
it('composes every shipped capability and the three pipeline roles from `maximum`', async () => {
const handle = await ctx.agents.create({
sessionId: SessionId('preset-maximum'),
setup: agentCtx => ctx.agentPresets.mount(agentCtx, 'maximum').then(() => undefined),
})
try {
// The shell row is platform-gated like `standard`'s: bash off Windows,
// pwsh on it. The registry answers in name order, so the gated name is
// sorted in rather than written at a fixed position.
const shell = process.platform === 'win32' ? 'pwsh' : 'bash'
// The EXACT catalog, for the reason `standard`'s assertion states: a row
// that registers into the wrong layer mounts cleanly and contributes
// nothing, and this preset exists to carry every row at once.
expect(toolNames(ctx, handle.agent).filter(name => name !== 'glob' && name !== 'grep')).toEqual([
'ask_user_question', shell, 'cordis_define', 'cordis_inspect_list', 'cordis_inspect_query',
'cordis_inspect_self', 'cordis_run', 'cordis_stop', 'cordis_undefine', 'create_goal', 'edit',
'exit_plan_mode', 'get_goal', 'interrupt_agent', 'job_kill', 'job_list', 'job_output',
'list_agents', 'lsp', 'ralph', 'read', 'read_image', 'run_code', 'schedule_create',
'schedule_delete', 'schedule_list', 'send_message', 'session_event_read',
'session_event_search', 'session_event_trace', 'session_search', 'session_trace', 'skill',
'str_replace_editor', 'subagent', 'subagent_architect', 'subagent_claude_code',
'subagent_codex', 'subagent_cursor', 'subagent_fork', 'subagent_implementer',
'subagent_reviewer', 'terminal_close', 'terminal_list', 'terminal_open', 'terminal_read',
'terminal_send', 'terminal_signal', 'todo_write', 'update_goal', 'web_search', 'workflow',
'write',
].sort())
// Each role is one `spawn` instance carrying its own child persona, so
// the roles are distinguishable only by what their descriptions and
// personas say — the wire schemas are otherwise identical.
const schemas = ctx.tools.schemas(handle.agent)
for (const role of ['subagent_architect', 'subagent_implementer', 'subagent_reviewer']) {
expect(schemas.find(schema => schema.name === role)?.description)
.toContain('This call waits for the result by default.')
}
} finally {
await handle.dispose()
}
})
it('composes the exact RL prompt and two tools from `minimal`', async () => {
const handle = await ctx.agents.create({
sessionId: SessionId('preset-minimal'),
@@ -436,7 +521,7 @@ describe('the shipped Web composition', () => {
describe('product subagent rows in user presets', () => {
let productCtx: Context
const ids = ['products-none', 'products-codex', 'products-claude', 'products-both'] as const
const ids = ['products-none', 'products-codex', 'products-claude', 'products-all'] as const
beforeAll(async () => {
const root = await mkdtemp(join(tmpdir(), 'dsh-product-presets-'))
@@ -444,23 +529,26 @@ describe('product subagent rows in user presets', () => {
const settingsFile = join(root, 'settings.yaml')
const standard = await readFile(join(CONFIG_DIR, 'agent-presets', 'standard', 'agent.cordis.yml'), 'utf8')
await writeFile(settingsFile, '{}\n')
// `standard` ships every product row enabled, so each variant is built by
// REMOVING the rows it must not carry.
for (const id of ids) {
let composition = standard
if (id === 'products-codex' || id === 'products-both') {
composition = enablePresetTool(composition, 'tool-subagent-codex')
if (id !== 'products-all' && id !== 'products-codex') {
composition = disablePresetTool(composition, 'tool-subagent-codex')
}
if (id === 'products-claude' || id === 'products-both') {
composition = enablePresetTool(composition, 'tool-subagent-claude-code')
if (id !== 'products-all' && id !== 'products-claude') {
composition = disablePresetTool(composition, 'tool-subagent-claude-code')
}
if (id !== 'products-all') {
composition = disablePresetTool(composition, 'tool-subagent-cursor')
}
const directory = join(userRoot, id)
await mkdir(directory, { recursive: true })
await writeFile(join(directory, 'agent.cordis.yml'), composition)
}
// The base patch already mounts every product provider on the host plane,
// so this boot adds only the preset roster.
productCtx = await bootWeb(settingsFile, [
{ insert: [
{ id: 'subagent-codex', name: '@deepseek-ai/dsh-subagent-codex' },
{ id: 'subagent-claude-code', name: '@deepseek-ai/dsh-subagent-claude-code' },
] },
{
id: 'agent-presets',
config: {
@@ -479,15 +567,15 @@ describe('product subagent rows in user presets', () => {
await productCtx.fiber.dispose()
})
it('composes none, either product, or both without changing the shared host registry', async () => {
it('composes none, one product, or every product without changing the shared host registry', async () => {
const expected = new Map<string, string[]>([
['products-none', []],
['products-codex', ['subagent_codex']],
['products-claude', ['subagent_claude_code']],
['products-both', ['subagent_claude_code', 'subagent_codex']],
['products-all', ['subagent_claude_code', 'subagent_codex', 'subagent_cursor']],
])
expect(productCtx.subagents.list()).toEqual(expect.arrayContaining([
'spawn', 'fork', 'codex', 'claude-code',
'spawn', 'fork', 'codex', 'claude-code', 'cursor',
]))
for (const [id, productTools] of expected) {
@@ -497,7 +585,7 @@ describe('product subagent rows in user presets', () => {
})
try {
const tools = toolNames(productCtx, handle.agent)
expect(tools.filter(name => name === 'subagent_codex' || name === 'subagent_claude_code'))
expect(tools.filter(name => name.startsWith('subagent_') && name !== 'subagent_fork'))
.toEqual(productTools)
expect(tools).toEqual(expect.arrayContaining(['job_kill', 'job_list', 'job_output']))
for (const productTool of productTools) {