feat(invariants): add package-owned service seam
This commit is contained in:
@@ -15,8 +15,19 @@ import type {
|
||||
PackageScriptResource,
|
||||
} from '../resources.ts'
|
||||
|
||||
/** Return the installable package name for a bare package or package subpath. */
|
||||
function installablePackageName(specifier: string): string {
|
||||
const segments = specifier.split('/')
|
||||
const expectedSegments = specifier.startsWith('@') ? 2 : 1
|
||||
if (segments.length < expectedSegments || segments.slice(0, expectedSegments).some(segment => segment.length === 0)) {
|
||||
throw new Error(`invalid bare package specifier: ${JSON.stringify(specifier)}`)
|
||||
}
|
||||
return segments.slice(0, expectedSegments).join('/')
|
||||
}
|
||||
|
||||
/** Create a runtime NPM dependency resource. */
|
||||
function npmDependency(_owner: string, name: string): NpmDependencyResource {
|
||||
function npmDependency(_owner: string, specifier: string): NpmDependencyResource {
|
||||
const name = installablePackageName(specifier)
|
||||
return {
|
||||
kind: 'npm-dependency',
|
||||
key: resourceKey(`npm-dependency:${name}`),
|
||||
@@ -52,7 +63,7 @@ export function cordisConfigEntry(
|
||||
}
|
||||
}
|
||||
|
||||
/** Couple one bare-package Cordis config entry to its mandatory runtime NPM dependency. */
|
||||
/** Couple one bare-package or subpath Cordis entry to its installable NPM package. */
|
||||
export function npmCordisConfigEntry(
|
||||
owner: string,
|
||||
value: CordisConfigEntry,
|
||||
|
||||
@@ -9,7 +9,7 @@ import type { ProjectProfile } from '../../project/types.ts'
|
||||
import { loadHelperTemplate } from '../../templates/template-assets.ts'
|
||||
import { FeatureOption, FixedFeature } from '../feature.ts'
|
||||
import { ProjectContribution } from '../resources.ts'
|
||||
import { npmCordisConfigEntry, requiredString } from './helpers.ts'
|
||||
import { cordisConfigEntry, npmCordisConfigEntry, requiredString } from './helpers.ts'
|
||||
|
||||
const ID = featureId('spine')
|
||||
const PERSONA = loadHelperTemplate<Record<string, never>>('persona.txt.tpl').render({}).trimEnd()
|
||||
@@ -37,6 +37,10 @@ class SpineOption extends FeatureOption {
|
||||
...npmCordisConfigEntry(ID, { id: 'tools', name: '@deepseek-ai/dsh-tools' }, []),
|
||||
...npmCordisConfigEntry(ID, { id: 'agent', name: '@deepseek-ai/dsh-agent' }),
|
||||
...npmCordisConfigEntry(ID, { id: 'invariants', name: '@deepseek-ai/dsh-invariants' }),
|
||||
cordisConfigEntry(ID, { id: 'session-invariant', name: '@deepseek-ai/dsh-session/invariant' }),
|
||||
cordisConfigEntry(ID, { id: 'agent-invariant', name: '@deepseek-ai/dsh-agent/invariant' }),
|
||||
...npmCordisConfigEntry(ID, { id: 'scope-invariant', name: '@deepseek-ai/dsh-scope/invariant' }),
|
||||
cordisConfigEntry(ID, { id: 'agent-loop-invariant', name: '@deepseek-ai/dsh-agent-loop/invariant' }),
|
||||
...npmCordisConfigEntry(ID, {
|
||||
id: 'agent-loop',
|
||||
name: '@deepseek-ai/dsh-agent-loop',
|
||||
|
||||
@@ -188,9 +188,15 @@ describe('SdkProject and ProjectEditSession', () => {
|
||||
.toContain('sessionId: !!js process.env.DSH_SDK_SESSION_ID')
|
||||
expect(project.cordis.entry('stdio')?.config).not.toHaveProperty('model')
|
||||
expect(project.cordis.entry('agent-loop')?.config).toEqual({ agents: [] })
|
||||
expect(project.cordis.entry('session-invariant')?.name).toBe('@deepseek-ai/dsh-session/invariant')
|
||||
expect(project.cordis.entry('agent-invariant')?.name).toBe('@deepseek-ai/dsh-agent/invariant')
|
||||
expect(project.cordis.entry('scope-invariant')?.name).toBe('@deepseek-ai/dsh-scope/invariant')
|
||||
expect(project.cordis.entry('agent-loop-invariant')?.name).toBe('@deepseek-ai/dsh-agent-loop/invariant')
|
||||
expect(project.cordis.entry('system-prompt')?.config?.persona).toContain('{{cwd}}')
|
||||
expect(project.packageManifest().dependencies?.['@cordisjs/plugin-timer']).toBe('^1.1.2')
|
||||
expect(project.packageManifest().dependencies?.['@cordisjs/plugin-hmr']).toBe('^1.0.15')
|
||||
expect(project.packageManifest().dependencies?.['@deepseek-ai/dsh-scope']).toBe('^0.0.1')
|
||||
expect(project.packageManifest().dependencies).not.toHaveProperty('@deepseek-ai/dsh-scope/invariant')
|
||||
expect(project.packageManifest().dependencies).not.toHaveProperty('node-addon-require-builtin')
|
||||
expect(project.cordis.entry('hmr')).toMatchObject({ name: '@cordisjs/plugin-hmr' })
|
||||
expect(project.cordis.entry('llm-deepseek')?.config).not.toHaveProperty('baseURL')
|
||||
@@ -865,6 +871,11 @@ describe('extension points', () => {
|
||||
expect(stringArray({ value: [1] }, 'value')).toHaveLength(1)
|
||||
expect(cordisConfigEntry('owner', { id: 'entry', name: 'pkg' }).ownedConfigKeys).toEqual([])
|
||||
expect(npmCordisConfigEntry('owner', { id: 'entry', name: 'pkg' })[1].ownedConfigKeys).toEqual([])
|
||||
expect(npmCordisConfigEntry('owner', { id: 'entry', name: '@scope/pkg/subpath' })[0].name).toBe('@scope/pkg')
|
||||
expect(npmCordisConfigEntry('owner', { id: 'entry', name: 'pkg/subpath' })[0].name).toBe('pkg')
|
||||
for (const invalid of ['', '@scope', '@scope/']) {
|
||||
expect(() => npmCordisConfigEntry('owner', { id: 'entry', name: invalid })).toThrow('invalid bare package specifier')
|
||||
}
|
||||
expect(environmentResource('owner', 'EMPTY', undefined)).not.toHaveProperty('value')
|
||||
const builtins = createBuiltinRegistry(profile)
|
||||
expect(builtins.get(featureId('app')).defaultOptions(profile)).toEqual(['embed'])
|
||||
|
||||
Reference in New Issue
Block a user