Merge remote-tracking branch 'origin/master' into codex/session-scoped-sandbox-roots
# Conflicts: # examples/acp-agent/tests/acp.snapshot.ts # packages/examples/agent-spine-demo/package.json # pnpm-lock.yaml
This commit is contained in:
@@ -11,11 +11,16 @@
|
||||
"types": "./lib/types/index.d.ts",
|
||||
"default": "./lib/index.js"
|
||||
},
|
||||
"./invariant": {
|
||||
"types": "./lib/types/invariant.d.ts",
|
||||
"default": "./lib/invariant.js"
|
||||
},
|
||||
"./src/*": "./src/*",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"files": [
|
||||
"lib/index.js",
|
||||
"lib/invariant.js",
|
||||
"lib/types/**/*.d.ts",
|
||||
"lib/types/**/*.d.ts.map",
|
||||
"src"
|
||||
@@ -23,12 +28,14 @@
|
||||
"license": "BSD-3-Clause",
|
||||
"peerDependencies": {
|
||||
"@deepseek-ai/dsh-brand": "^0.0.1",
|
||||
"@deepseek-ai/dsh-invariants": "^0.0.1",
|
||||
"@deepseek-ai/dsh-llm": "^0.0.1",
|
||||
"@deepseek-ai/dsh-sandbox": "^0.0.1",
|
||||
"cordis": "^4.0.0-rc.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@deepseek-ai/dsh-brand": "workspace:^",
|
||||
"@deepseek-ai/dsh-invariants": "workspace:^",
|
||||
"@deepseek-ai/dsh-llm": "workspace:^",
|
||||
"@deepseek-ai/dsh-sandbox": "workspace:^",
|
||||
"cordis": "^4.0.0-rc.7"
|
||||
|
||||
39
packages/fs/fs/src/invariant.ts
Normal file
39
packages/fs/fs/src/invariant.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/** Package-owned filesystem event-data invariants. @module @deepseek-ai/dsh-fs/invariant */
|
||||
|
||||
import type { Context } from 'cordis'
|
||||
import type { InvariantInstaller } from '@deepseek-ai/dsh-invariants'
|
||||
import type { FsTarget, FsVersion } from './types.ts'
|
||||
|
||||
const PACKAGE_NAME = '@deepseek-ai/dsh-fs'
|
||||
|
||||
/** Cordis companion plugin name. */
|
||||
export const name = 'fs-invariant'
|
||||
/** Service required before the companion can reserve package ownership. */
|
||||
export const inject = ['invariants']
|
||||
|
||||
/** Assert that an event carries a usable opaque target identity. */
|
||||
function validateTarget(target: FsTarget, fail: (message: string) => never): void {
|
||||
if (target.targetKey.length === 0) fail('filesystem event targetKey must be non-empty')
|
||||
if (target.displayPath.length === 0) fail('filesystem event displayPath must be non-empty')
|
||||
}
|
||||
|
||||
/** Install checks over the filesystem decision and observation event stream. */
|
||||
const install: InvariantInstaller = (ctx, fail) => {
|
||||
ctx.on('internal/dispatch', (_mode, eventName, args) => {
|
||||
if (eventName !== 'fs/write-intent'
|
||||
&& eventName !== 'fs/edit-intent'
|
||||
&& eventName !== 'fs/observed') return
|
||||
validateTarget(args[0] as FsTarget, fail)
|
||||
if (eventName === 'fs/observed' && (args[1] as FsVersion).length === 0) {
|
||||
fail('fs/observed version must be non-empty')
|
||||
}
|
||||
}, { global: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the filesystem invariant companion.
|
||||
* @param ctx - Cordis context carrying the invariant service.
|
||||
* @returns the installed registration's disposer after setup succeeds.
|
||||
*/
|
||||
export const apply = (ctx: Context): Promise<() => void> =>
|
||||
Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install))
|
||||
44
packages/fs/fs/tests/invariant.spec.ts
Normal file
44
packages/fs/fs/tests/invariant.spec.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { Context } from 'cordis'
|
||||
import { FsTargetKey, FsVersion } from '@deepseek-ai/dsh-fs'
|
||||
import type { FsTarget } from '@deepseek-ai/dsh-fs'
|
||||
import * as FsInvariant from '@deepseek-ai/dsh-fs/invariant'
|
||||
import InvariantService from '@deepseek-ai/dsh-invariants'
|
||||
|
||||
async function setup(): Promise<Context> {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(InvariantService)
|
||||
await ctx.plugin(FsInvariant)
|
||||
return ctx
|
||||
}
|
||||
|
||||
const target = (key = 'file:1', displayPath = 'file.txt'): FsTarget => ({
|
||||
targetKey: FsTargetKey(key),
|
||||
displayPath,
|
||||
})
|
||||
|
||||
describe('filesystem invariants', () => {
|
||||
it('accepts decision and observation events with usable identities', async () => {
|
||||
const ctx = await setup()
|
||||
await expect(ctx.waterfall(
|
||||
ctx as never, 'fs/write-intent', target(), undefined,
|
||||
() => Promise.resolve(undefined),
|
||||
)).resolves.toBeUndefined()
|
||||
await expect(ctx.waterfall(
|
||||
ctx as never, 'fs/edit-intent', target(), undefined,
|
||||
() => Promise.resolve(undefined),
|
||||
)).resolves.toBeUndefined()
|
||||
expect(() => { ctx.emit('fs/observed', target(), FsVersion('v1'), undefined) }).not.toThrow()
|
||||
expect(() => { ctx.emit('tools/change') }).not.toThrow()
|
||||
})
|
||||
|
||||
it('rejects empty target and version identities', async () => {
|
||||
const ctx = await setup()
|
||||
expect(() => { ctx.emit('fs/observed', target(''), FsVersion('v1'), undefined) })
|
||||
.toThrow(/targetKey must be non-empty/)
|
||||
expect(() => { ctx.emit('fs/observed', target('file:1', ''), FsVersion('v1'), undefined) })
|
||||
.toThrow(/displayPath must be non-empty/)
|
||||
expect(() => { ctx.emit('fs/observed', target(), FsVersion(''), undefined) })
|
||||
.toThrow(/version must be non-empty/)
|
||||
})
|
||||
})
|
||||
@@ -6,10 +6,23 @@
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [
|
||||
{ "path": "../../../vendor/cosmokit" },
|
||||
{ "path": "../../../vendor/cordis" },
|
||||
{ "path": "../../util/brand" },
|
||||
{ "path": "../../llm/llm" },
|
||||
{ "path": "../../sandbox/sandbox" }
|
||||
{
|
||||
"path": "../../../vendor/cosmokit"
|
||||
},
|
||||
{
|
||||
"path": "../../../vendor/cordis"
|
||||
},
|
||||
{
|
||||
"path": "../../util/brand"
|
||||
},
|
||||
{
|
||||
"path": "../../llm/llm"
|
||||
},
|
||||
{
|
||||
"path": "../../support/invariants"
|
||||
},
|
||||
{
|
||||
"path": "../../sandbox/sandbox"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user