Merge remote-tracking branch 'origin/master' into jsonl-packed-chunk-rows

# Conflicts:
#	docs/event-producer-consumer.md
This commit is contained in:
kingwl
2026-07-15 22:14:42 +08:00
117 changed files with 5089 additions and 2688 deletions

View File

@@ -30,6 +30,8 @@ Because the package wires no logger entry, an ACP leaf has **nothing to get wron
| `toolOrder` | — | explicit model-facing tool order (a name list with one `'<unlisted-tools>'` rest entry; absent — lexicographic; an unregistered name fails each turn at prompt assembly), routed to `dsh-system-prompt` |
| `tools` | `{ mode: 'native' }` | tool-registry presentation config (`native` / `code` / `both`), routed through `dsh-agent-spine-demo` |
| `skills` | owner defaults | registry-cache, local-provider, and model-facing skill-tool config, routed through `dsh-agent-spine-demo` |
| `toolBash` | owner defaults | model-facing bash config routed through `dsh-agent-spine-demo`, including bash's producer-local `enableRunInBackground` |
| `toolTasks` | owner defaults | generic `task_output` wait bounds routed through `dsh-agent-spine-demo` |
| `persistenceRoot` | `./.sessions` | the JSONL backend's root directory |
| `packChunks` | `false` | write delta-chunk runs as packed storage rows (the JSONL backend's `packChunks`) |

View File

@@ -43,6 +43,10 @@ export interface Config {
packChunks?: boolean
/** Skill registry, local-provider, and model-facing consumer config forwarded to agent-spine-demo. */
skills?: agentCore.SkillConfig
/** Model-facing bash tool config forwarded through agent-core. */
toolBash?: NonNullable<agentCore.Config['toolBash']>
/** Generic background-task control-tool config forwarded through agent-core. */
toolTasks?: NonNullable<agentCore.Config['toolTasks']>
}
// Each front door owns a complete, directly readable config schema; extracting
@@ -61,6 +65,8 @@ export const Config: z<Config> = z.object({
persistenceRoot: z.string().default('./.sessions'),
packChunks: z.boolean().default(false),
skills: agentCore.SkillConfigSchema,
toolBash: agentCore.ToolBashConfigSchema,
toolTasks: agentCore.ToolTasksConfigSchema,
})
/* jscpd:ignore-end */
@@ -77,6 +83,8 @@ export function apply(ctx: Context, config: Config): void {
...config.toolOrder !== undefined ? { toolOrder: config.toolOrder } : {},
...config.tools !== undefined ? { tools: config.tools } : {},
...config.skills !== undefined ? { skills: config.skills } : {},
...config.toolBash !== undefined ? { toolBash: config.toolBash } : {},
...config.toolTasks !== undefined ? { toolTasks: config.toolTasks } : {},
})
ctx.plugin(UserInteractionService)
ctx.plugin(SessionPersistenceJsonl, {

View File

@@ -19,8 +19,9 @@ import * as acpAgent from '../src/index.ts'
* ACP operations end-to-end) is the keyless bin smoke in `load-path.e2e.ts`;
* this spec asserts the composition and the persistenceRoot default branch.
*/
async function mount(config: acpAgent.Config): Promise<Context> {
async function mount(config: acpAgent.Config, withBash = false): Promise<Context> {
const ctx = new Context()
if (withBash) ctx.provide('bash', { sandboxMode: undefined })
await ctx.plugin(acpAgent, config)
// The bundle mounts its children inside apply() (not awaited there); let their
// fibers settle so the spine services are ready.
@@ -112,6 +113,19 @@ describe('dsh-acp-demo composition', () => {
await ctx.fiber.dispose()
})
it('forwards bundled tool config into agent-core', async () => {
const ctx = await mount({
model: 'mock',
toolBash: { enableRunInBackground: false },
toolTasks: { waitTimeoutMs: 7, maxWaitTimeoutMs: 11 },
skills: await isolatedSkillsConfig(),
}, true)
const bash = ctx.tools.schemas().find(tool => tool.name === 'bash')
expect(Object.keys((bash!.parameters as { properties: Record<string, unknown> }).properties))
.not.toContain('run_in_background')
await ctx.fiber.dispose()
})
it('exposes its plugin shape', () => {
expect(acpAgent.name).toBe('acp-demo')
expect(acpAgent.Config).toBeDefined()
@@ -134,7 +148,7 @@ describe('dsh-acp-demo composition', () => {
})
}
const assembly = await ctx.get('systemPrompt')!.assemble()
expect(assembly.tools.map(tool => tool.name)).toEqual(['zulu', 'alpha', 'skill'])
expect(assembly.tools.map(tool => tool.name)).toEqual(['zulu', 'alpha', 'skill', 'task_kill', 'task_list', 'task_output'])
await ctx.fiber.dispose()
})