Merge remote-tracking branch 'origin/master' into fix/continuable-subagent-policy-inheritance
# Conflicts: # examples/acp-agent/tests/snapshots/advanced-toolchain/session.1.jsonl # examples/acp-agent/tests/snapshots/advanced-toolchain/session.2.jsonl # examples/acp-agent/tests/snapshots/advanced-toolchain/session.jsonl # examples/headless-agent/tests/snapshots/advanced-toolchain/session.1.jsonl # examples/headless-agent/tests/snapshots/advanced-toolchain/session.2.jsonl # examples/headless-agent/tests/snapshots/advanced-toolchain/session.jsonl
This commit is contained in:
@@ -1,9 +1,6 @@
|
||||
- id: cli-mock-llm
|
||||
name: './cli-mock-llm.ts'
|
||||
|
||||
- id: repository-plugin-fixture
|
||||
name: './repository-plugin/load.mjs'
|
||||
|
||||
- id: base
|
||||
name: '@cordisjs/plugin-include'
|
||||
config:
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
name: repository-fixture
|
||||
description: Repository fixture skill.
|
||||
---
|
||||
|
||||
Static instructions from a prepared repository plugin.
|
||||
@@ -1,19 +0,0 @@
|
||||
// Generated by dsh-plugin-prepare. Do not edit.
|
||||
const manifest = {"name":"headless-repository-fixture","skills":["dsh-plugin-assets/skills/0"]}
|
||||
// Value mirror: Cordis const enum FiberState.ACTIVE; keep aligned with dsh-repository-plugin source.ts.
|
||||
const FIBER_ACTIVE = 2
|
||||
export const name = "headless-repository-fixture"
|
||||
export const inject = ["loader","skills"]
|
||||
async function mount(ctx, plugin, label, config) {
|
||||
const fiber = ctx.plugin(plugin, config)
|
||||
await fiber
|
||||
if (fiber.state !== FIBER_ACTIVE) {
|
||||
const missing = Object.keys(fiber.inject).filter(service => fiber.ctx.get(service) === undefined)
|
||||
throw new Error(`${label} did not activate (waiting for services: ${missing.join(', ') || 'unknown'})`)
|
||||
}
|
||||
}
|
||||
export async function apply(ctx) {
|
||||
const runtime = ctx.loader.builtins["dsh-repository-plugin"]
|
||||
if (runtime === undefined) throw new Error("missing Cordis builtin dsh-repository-plugin")
|
||||
await mount(ctx, runtime, 'repository Plugin runtime', { baseUrl: import.meta.url, manifest })
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Keyless fixture owner that mounts the runtime before its prepared wrapper.
|
||||
* Cordis starts sibling Loader entries concurrently, so row order is not a dependency edge.
|
||||
*/
|
||||
import * as RepositoryPlugin from '@deepseek-ai/dsh-repository-plugin'
|
||||
import * as PreparedPlugin from './dsh-plugin.mjs'
|
||||
|
||||
export const name = 'headless-repository-fixture-loader'
|
||||
|
||||
export async function apply(ctx) {
|
||||
await ctx.plugin(RepositoryPlugin)
|
||||
await ctx.plugin(PreparedPlugin)
|
||||
}
|
||||
@@ -1,17 +1,10 @@
|
||||
import { cp, mkdir, mkdtemp, readFile, readdir, rm, writeFile } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { readFile, readdir } from 'node:fs/promises'
|
||||
import { zstdDecompress } from 'node:zlib'
|
||||
import { promisify } from 'node:util'
|
||||
import { join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { LOADER_SMOKE_TEST_TIMEOUT_MS, runLoaderSmoke } from '@deepseek-ai/dsh-loader-smoke'
|
||||
import {
|
||||
PREPARED_ENTRY_FILENAME,
|
||||
REPOSITORY_PLUGIN_PREPARE_COMMAND,
|
||||
REPOSITORY_PLUGIN_PACKAGE_NAME,
|
||||
prepareDshPlugin,
|
||||
} from '@deepseek-ai/dsh-repository-plugin'
|
||||
import type { SessionEvent } from '@deepseek-ai/dsh-session'
|
||||
|
||||
const binScript = fileURLToPath(new URL('./fixtures/headless-driver.ts', import.meta.url))
|
||||
@@ -44,16 +37,6 @@ describe('headless-agent keyless smoke', () => {
|
||||
const result = lines.at(-1)
|
||||
expect(stderr).toBe('')
|
||||
expect(events.some(event => event.type === 'tool/call' && event.data.name === 'bash')).toBe(true)
|
||||
const catalogMessage = events.find(event => event.type === 'user/message'
|
||||
&& event.data.source.kind === 'skill-catalog')
|
||||
const catalog = catalogMessage?.type === 'user/message'
|
||||
? catalogMessage.data.content.filter(block => block.type === 'text').map(block => block.text).join('\n')
|
||||
: ''
|
||||
expect(catalog.split('\n').find(line => line.includes('repository-fixture'))).toMatchInlineSnapshot(
|
||||
`
|
||||
"- \`repository-fixture\`: Repository fixture skill."
|
||||
`,
|
||||
)
|
||||
const toolResult = events.find(event => event.type === 'tool/result')
|
||||
expect(JSON.stringify(toolResult)).toContain('CLI_TOOL_ROUND_TRIP')
|
||||
expect(result).toMatchObject({
|
||||
@@ -63,30 +46,4 @@ describe('headless-agent keyless smoke', () => {
|
||||
expect(String(result?.['output'])).toContain('CLI_TOOL_ROUND_TRIP')
|
||||
expect(persistedHeader).toMatchObject({ type: 'session' })
|
||||
}, LOADER_SMOKE_TEST_TIMEOUT_MS)
|
||||
|
||||
it('keeps the checked-in prepared wrapper identical to the generator output for its manifest', async () => {
|
||||
// The fixture claims "Generated by dsh-plugin-prepare"; this pin makes the
|
||||
// claim true — a wrapper-template change fails here until the fixture is
|
||||
// regenerated, so the assembled smoke can never exercise stale generated fields.
|
||||
const fixture = fileURLToPath(new URL('./fixtures/repository-plugin/', import.meta.url))
|
||||
const root = await mkdtemp(join(tmpdir(), 'dsh-fixture-drift-'))
|
||||
try {
|
||||
const plugin = join(root, '.dsh-plugin')
|
||||
await mkdir(plugin, { recursive: true })
|
||||
await cp(join(fixture, 'dsh-plugin-assets/skills/0'), join(root, 'skills'), { recursive: true })
|
||||
await writeFile(join(plugin, 'package.json'), `${JSON.stringify({
|
||||
name: 'headless-repository-fixture',
|
||||
version: '0.0.0',
|
||||
scripts: { prepack: REPOSITORY_PLUGIN_PREPARE_COMMAND },
|
||||
devDependencies: { [REPOSITORY_PLUGIN_PACKAGE_NAME]: '0.0.1' },
|
||||
dsh: { skills: ['../skills'] },
|
||||
}, undefined, 2)}\n`)
|
||||
await prepareDshPlugin(plugin)
|
||||
const generated = await readFile(join(plugin, PREPARED_ENTRY_FILENAME), 'utf8')
|
||||
const checkedIn = await readFile(join(fixture, PREPARED_ENTRY_FILENAME), 'utf8')
|
||||
expect(checkedIn).toBe(generated)
|
||||
} finally {
|
||||
await rm(root, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user