Merge remote-tracking branch 'origin/master' into feat/plugin-detail-slots
This commit is contained in:
commit
aba8b3a29f
259 files changed
+6650
-1951
No files matched your search
@@ -433,7 +433,9 @@ export const LINK_MAP: Readonly<Record<string, string>> = {
|
||||
StoredImageAttachment: 'attachment.md',
|
||||
ShellExecRequest: 'shell.md',
|
||||
ShellExecSpec: 'shell.md',
|
||||
ShellExecution: 'shell.md',
|
||||
ShellProcess: 'shell.md',
|
||||
ShellPromotionOffer: 'shell.md',
|
||||
ShellRunResult: 'shell.md',
|
||||
DshEnvironment: 'subprocess.md',
|
||||
SubprocessHandle: 'subprocess.md',
|
||||
@@ -588,6 +590,8 @@ export const LINK_MAP: Readonly<Record<string, string>> = {
|
||||
SystemPrompt: 'system-prompt.md',
|
||||
ToolProviderResult: 'system-prompt.md',
|
||||
JobId: 'jobs.md',
|
||||
JobKillRequest: 'jobs.md',
|
||||
JobKillValue: 'jobs.md',
|
||||
JobFollowFrame: 'jobs.md',
|
||||
JobFollowRequest: 'jobs.md',
|
||||
JobListFrame: 'jobs.md',
|
||||
|
||||
@@ -286,16 +286,19 @@ const TOOL_PACKAGES: ToolPackage[] = [
|
||||
pkg: '@deepseek-ai/dsh-tool-bash',
|
||||
dir: 'tool-bash',
|
||||
source: 'packages/shell/tool-bash/src/index.ts',
|
||||
requires: ['ctx.tools', 'ctx.shell', 'ctx.systemPrompt', 'ctx.shellEnv', 'ctx.jobs at call time for run_in_background'],
|
||||
requires: ['ctx.tools', 'ctx.shell', 'ctx.systemPrompt', 'ctx.shellEnv', 'ctx.jobs for run_in_background and the job-backed foreground path'],
|
||||
writes: ['tool/call', 'tool/result'],
|
||||
async mount(ctx) {
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(BashEnvPlugin)
|
||||
await ctx.plugin(LocalBashExecutor)
|
||||
// The shipped profiles compose the job registry, and the tool's
|
||||
// background surface follows it: harvest the job-backed schema.
|
||||
await ctx.plugin(LocalJobRegistry)
|
||||
await ctx.plugin(ToolBash)
|
||||
},
|
||||
note:
|
||||
'The bash tool is the model-facing consumer of the bash executor seam. A `run_in_background` run registers with the generic `ctx.jobs` runtime and is collected/stopped through the `job_*` tools from `@deepseek-ai/dsh-tool-jobs`; the `enableRunInBackground` config (default true) removes the parameter entirely when disabled.',
|
||||
'The bash tool is the model-facing consumer of the bash executor seam. With a job registry composed every call registers with the generic `ctx.jobs` runtime as it starts, collected/stopped through the `job_*` tools from `@deepseek-ai/dsh-tool-jobs`; without one, or with `enableRunInBackground: false`, the tool registers a foreground-only schema without the `run_in_background` parameter.',
|
||||
},
|
||||
{
|
||||
pkg: '@deepseek-ai/dsh-tool-present',
|
||||
@@ -313,15 +316,17 @@ const TOOL_PACKAGES: ToolPackage[] = [
|
||||
pkg: '@deepseek-ai/dsh-tool-pwsh',
|
||||
dir: 'tool-pwsh',
|
||||
source: 'packages/shell/tool-pwsh/src/index.ts',
|
||||
requires: ['ctx.tools', 'ctx.shell', 'ctx.systemPrompt', 'ctx.shellEnv', 'ctx.jobs at call time for run_in_background'],
|
||||
requires: ['ctx.tools', 'ctx.shell', 'ctx.systemPrompt', 'ctx.shellEnv', 'ctx.jobs for run_in_background and the job-backed foreground path'],
|
||||
writes: ['tool/call', 'tool/result'],
|
||||
async mount(ctx) {
|
||||
// The pwsh tool consumes the bash executor seam; the schema harvest
|
||||
// mounts the pwsh-local implementation so the inject resolves without
|
||||
// executing anything (registration never spawns a process).
|
||||
// executing anything (registration never spawns a process). The job
|
||||
// registry is composed for the same reason as the bash entry.
|
||||
await ctx.plugin(LocalSubprocessRuntime)
|
||||
await ctx.plugin(BashEnvPlugin)
|
||||
await ctx.plugin(PwshLocalExecutor)
|
||||
await ctx.plugin(LocalJobRegistry)
|
||||
await ctx.plugin(ToolPwsh)
|
||||
},
|
||||
note:
|
||||
|
||||
@@ -1388,9 +1388,6 @@
|
||||
"packages/hooks/hook-protocol/tests/events.spec.ts": {
|
||||
"a59fe57e5f3994018a6bd25208b9c2f56a7bcf7353d6ec2d453564f3f5c225f2": 1
|
||||
},
|
||||
"packages/hooks/hook-protocol/tests/runner.spec.ts": {
|
||||
"09500884210bc2ec2161286a539ca63f8c2627ca73a82ca00d24c58d600118f3": 1
|
||||
},
|
||||
"packages/hooks/hooks-claude-code/tests/bridge.spec.ts": {
|
||||
"38a7cf3dfd5da2f739390f5b233b97731f3bfa1ac3a51fdb8e1594735764bb80": 1
|
||||
},
|
||||
|
||||
@@ -40,24 +40,24 @@ it.skipIf(process.platform === 'win32')('resolves the exact spill verifier, reta
|
||||
await adapter
|
||||
const command = 'file="' + saved.locator + '"' + "; grep -Fq request/header \"$file\" && grep -Fq session_event_search \"$file\" && printf 'SPILL_CANONICAL_OK\\n'"
|
||||
const spec = ctx.shell.resolve({ command })
|
||||
const output = await ctx.shell.run(spec)
|
||||
const output = await (await ctx.shell.execute(spec)).result()
|
||||
expect(output.timedOut).toBe(false)
|
||||
expect(output.exitCode).toBe(0)
|
||||
expect(output.stdout.text).toBe('SPILL_CANONICAL_OK\n')
|
||||
expect(spec.command).toBe(command)
|
||||
const other = await ctx.shell.run(ctx.shell.resolve({ command: 'printf ordinary; exit 7' }))
|
||||
const other = await (await ctx.shell.execute(ctx.shell.resolve({ command: 'printf ordinary; exit 7' }))).result()
|
||||
expect(other.exitCode).toBe(7)
|
||||
expect(other.stdout.text).toBe('ordinary')
|
||||
const unmatched = await ctx.shell.run(ctx.shell.resolve({ command: command + '; exit 9' }))
|
||||
const unmatched = await (await ctx.shell.execute(ctx.shell.resolve({ command: command + '; exit 9' }))).result()
|
||||
expect(unmatched.exitCode).toBe(9)
|
||||
expect(unmatched.stderr.text).toContain('No such file')
|
||||
const physical = ctx.fs.processPath(await ctx.fs.resolve(saved.locator))
|
||||
await rm(physical)
|
||||
const missing = await ctx.shell.run(spec)
|
||||
const missing = await (await ctx.shell.execute(spec)).result()
|
||||
expect(missing.exitCode).not.toBe(0)
|
||||
expect(missing.stdout.text).toBe('')
|
||||
await adapter.dispose()
|
||||
const restored = await ctx.shell.run(spec)
|
||||
const restored = await (await ctx.shell.execute(spec)).result()
|
||||
expect(restored.exitCode).not.toBe(0)
|
||||
expect(restored.stderr.text).toContain(saved.locator)
|
||||
} finally {
|
||||
|
||||
@@ -23,16 +23,16 @@ it.skipIf(process.platform === 'win32')('translates only the exact fixture comma
|
||||
const fork = ctx.plugin(adapter, { command, recordedPath: '/fixture/recorded.txt', livePath })
|
||||
disposers.push(() => fork.dispose())
|
||||
await fork
|
||||
const outcome = await ctx.shell.run(ctx.shell.resolve({ command }))
|
||||
const outcome = await (await ctx.shell.execute(ctx.shell.resolve({ command }))).result()
|
||||
expect(outcome.timedOut).toBe(false)
|
||||
expect(outcome.exitCode).toBe(0)
|
||||
expect(await readFile(livePath, 'utf8')).toBe('actual bytes')
|
||||
const untouched = await ctx.shell.run(ctx.shell.resolve({ command: "printf '/fixture/recorded.txt'; exit 7" }))
|
||||
const untouched = await (await ctx.shell.execute(ctx.shell.resolve({ command: "printf '/fixture/recorded.txt'; exit 7" }))).result()
|
||||
expect(untouched.exitCode).toBe(7)
|
||||
expect(untouched.stdout.text).toBe('/fixture/recorded.txt')
|
||||
await fork.dispose()
|
||||
await rm(livePath)
|
||||
const restored = await ctx.shell.run(ctx.shell.resolve({ command }))
|
||||
const restored = await (await ctx.shell.execute(ctx.shell.resolve({ command }))).result()
|
||||
expect(restored.exitCode).not.toBe(0)
|
||||
await expect(readFile(livePath)).rejects.toMatchObject({ code: 'ENOENT' })
|
||||
} finally {
|
||||
|
||||
@@ -20,11 +20,11 @@ export interface Config {
|
||||
export function apply(ctx: Context, config: Config): void {
|
||||
const shell = ctx.shell
|
||||
// oxlint-disable-next-line typescript/unbound-method -- preserve method identity for restoration; calls bind the receiver.
|
||||
const run = shell.run
|
||||
const execute = shell.execute
|
||||
ctx.effect(() => {
|
||||
shell.run = spec => run.call(shell, spec.command === config.command
|
||||
shell.execute = spec => execute.call(shell, spec.command === config.command
|
||||
? { ...spec, command: spec.command.replaceAll(config.recordedPath, "'" + config.livePath.replaceAll("'", "'\"'\"'") + "'") }
|
||||
: spec)
|
||||
return () => { shell.run = run }
|
||||
return () => { shell.execute = execute }
|
||||
})
|
||||
}
|
||||
@@ -44,15 +44,19 @@ it.each([false, true])('keeps concurrent physical spill files private while reta
|
||||
expect(target.displayPath).toBe(ref.locator)
|
||||
const physicalPath = ctx.fs.processPath(target)
|
||||
expect(physicalPath.startsWith(await realpath(root))).toBe(true)
|
||||
expect(await realpath(ctx.fs.processPathFromHostPath(ref.locator)!)).toBe(physicalPath)
|
||||
expect(await readFile(physicalPath, 'utf8')).toBe(content)
|
||||
expect(await ctx.fs.readText(target)).toBe(content)
|
||||
await expect(ctx.fs.resolve(join(locatorRoot, 'missing.txt'))).rejects.toThrow('not saved by this run')
|
||||
expect(() => ctx.fs.processPathFromHostPath(join(locatorRoot, 'missing.txt'))).toThrow('not saved by this run')
|
||||
const ordinary = join(root, 'ordinary.txt')
|
||||
await writeFile(ordinary, 'ordinary')
|
||||
expect(ctx.fs.processPathFromHostPath(ordinary)).toBe(ordinary)
|
||||
expect(await ctx.fs.readText(await ctx.fs.resolve(ordinary))).toBe('ordinary')
|
||||
await fork.dispose()
|
||||
const restored = await ctx.fs.resolve(ref.locator)
|
||||
expect(ctx.fs.processPath(restored)).not.toBe(physicalPath)
|
||||
expect(ctx.fs.processPathFromHostPath(ref.locator)).toBe(ref.locator)
|
||||
expect(await ctx.fs.stat(restored)).toBeUndefined()
|
||||
return { root, physicalPath, locator: ref.locator, content }
|
||||
}))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/** Fixture-only logical locators over real local spill files; preview budgets retain recorded path lengths. */
|
||||
/** Fixture-only logical locators for filesystem and subprocess reads of real spill files; preview budgets retain recorded path lengths. */
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import { join, relative, resolve, sep } from 'node:path'
|
||||
import type { SpillLocator } from '@deepseek-ai/dsh-spill'
|
||||
@@ -28,6 +28,17 @@ export function apply(ctx: Context, config: Config): void {
|
||||
const saveText = store.saveText
|
||||
// oxlint-disable-next-line typescript/unbound-method -- preserve method identity for restoration; calls bind the receiver.
|
||||
const resolvePath = fs.resolve
|
||||
// oxlint-disable-next-line typescript/unbound-method -- preserve method identity for restoration; calls bind the receiver.
|
||||
const processPathFromHostPath = fs.processPathFromHostPath
|
||||
|
||||
const mappedPath = (path: string): string => {
|
||||
const live = paths.get(path)
|
||||
if (live !== undefined) return live
|
||||
if (path.startsWith(locatorRoot + sep)) {
|
||||
throw new Error('snapshot spill locator was not saved by this run')
|
||||
}
|
||||
return path
|
||||
}
|
||||
ctx.effect(() => {
|
||||
store.saveText = async (input) => {
|
||||
const saved = await saveText.call(store, input)
|
||||
@@ -40,19 +51,15 @@ export function apply(ctx: Context, config: Config): void {
|
||||
return { ...saved, locator }
|
||||
}
|
||||
fs.resolve = async (path, opts) => {
|
||||
const live = paths.get(path)
|
||||
if (live !== undefined) {
|
||||
const target = await resolvePath.call(fs, live, opts)
|
||||
return { ...target, displayPath: path }
|
||||
}
|
||||
if (path.startsWith(locatorRoot + sep)) {
|
||||
throw new Error('snapshot spill locator was not saved by this run')
|
||||
}
|
||||
return resolvePath.call(fs, path, opts)
|
||||
const live = mappedPath(path)
|
||||
const target = await resolvePath.call(fs, live, opts)
|
||||
return live === path ? target : { ...target, displayPath: path }
|
||||
}
|
||||
fs.processPathFromHostPath = path => processPathFromHostPath.call(fs, mappedPath(path))
|
||||
return () => {
|
||||
store.saveText = saveText
|
||||
fs.resolve = resolvePath
|
||||
fs.processPathFromHostPath = processPathFromHostPath
|
||||
paths.clear()
|
||||
}
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user