cleanup: remove TUI package and legacy dsh entrypoints
This commit is contained in:
@@ -4,9 +4,8 @@
|
||||
* @module @deepseek-ai/dsh-helper/features/builtin/app
|
||||
*/
|
||||
|
||||
import { JsExpression } from '../../documents/cordis-yaml-file.ts'
|
||||
import { featureId } from '../../ids.ts'
|
||||
import type { ProjectProfile } from '../../project/types.ts'
|
||||
import type { ProjectProfile, RunInterface } from '../../project/types.ts'
|
||||
import {
|
||||
createAppPackageScripts,
|
||||
createAppProjectArtifacts,
|
||||
@@ -18,9 +17,7 @@ import {
|
||||
} from '../feature.ts'
|
||||
import { ProjectContribution, type ProjectResource } from '../resources.ts'
|
||||
import {
|
||||
cordisConfigEntry,
|
||||
npmCordisConfigEntry,
|
||||
optionalString,
|
||||
ownedTextFile,
|
||||
packageScript,
|
||||
requiredString,
|
||||
@@ -30,10 +27,10 @@ const ID = featureId('app')
|
||||
|
||||
function appProjectResources(
|
||||
profile: ProjectProfile,
|
||||
runInterface: 'acp' | 'tui' | 'embed',
|
||||
runInterface: RunInterface,
|
||||
): readonly ProjectResource[] {
|
||||
const context = createProjectTemplateContext(profile, runInterface)
|
||||
const scripts = createAppPackageScripts(context)
|
||||
const scripts = createAppPackageScripts()
|
||||
return [
|
||||
...createAppProjectArtifacts(context).map(document => (
|
||||
ownedTextFile(ID, document.relativePath, document.serialize())
|
||||
@@ -44,10 +41,10 @@ function appProjectResources(
|
||||
}
|
||||
|
||||
class AppOption extends FeatureOption {
|
||||
override readonly id: 'acp' | 'tui' | 'embed'
|
||||
override readonly id: RunInterface
|
||||
override readonly label: string
|
||||
|
||||
constructor(id: 'acp' | 'tui' | 'embed', label: string) {
|
||||
constructor(id: RunInterface, label: string) {
|
||||
super()
|
||||
this.id = id
|
||||
this.label = label
|
||||
@@ -57,7 +54,6 @@ class AppOption extends FeatureOption {
|
||||
override markerConfigEntries(): readonly { id: string; name: string }[] {
|
||||
switch (this.id) {
|
||||
case 'acp': return [{ id: 'acp', name: '@deepseek-ai/dsh-acp' }]
|
||||
case 'tui': return [{ id: 'tui', name: '@deepseek-ai/dsh-tui' }]
|
||||
case 'embed': return []
|
||||
}
|
||||
}
|
||||
@@ -66,7 +62,7 @@ class AppOption extends FeatureOption {
|
||||
override matchesConfigEntries(entries: readonly { id: string; name: string }[], profile: ProjectProfile): boolean {
|
||||
if (this.id !== 'embed') return super.matchesConfigEntries(entries, profile)
|
||||
return entries.some(entry => entry.id === 'agent-loop' && entry.name === '@deepseek-ai/dsh-agent-loop')
|
||||
&& !entries.some(entry => entry.name === '@deepseek-ai/dsh-acp' || entry.name === '@deepseek-ai/dsh-tui')
|
||||
&& !entries.some(entry => entry.name === '@deepseek-ai/dsh-acp')
|
||||
}
|
||||
|
||||
override contribution(profile: ProjectProfile): ProjectContribution {
|
||||
@@ -80,36 +76,13 @@ class AppOption extends FeatureOption {
|
||||
config: { model: profile.runtime.model },
|
||||
}, ['model'], config => requiredString(config, 'model')),
|
||||
])
|
||||
case 'tui':
|
||||
return new ProjectContribution([
|
||||
...appProjectResources(profile, this.id),
|
||||
...npmCordisConfigEntry(ID, {
|
||||
id: 'user-interaction',
|
||||
name: '@deepseek-ai/dsh-user-interaction',
|
||||
}),
|
||||
cordisConfigEntry(ID, {
|
||||
id: 'tui-prompt',
|
||||
name: '@deepseek-ai/dsh-tui/prompt',
|
||||
}),
|
||||
...npmCordisConfigEntry(ID, {
|
||||
id: 'tui',
|
||||
name: '@deepseek-ai/dsh-tui',
|
||||
config: {
|
||||
welcome: 'TUI agent ready. Give it a coding task.',
|
||||
sessionId: new JsExpression('process.env.DSH_SDK_SESSION_ID'),
|
||||
},
|
||||
}, ['welcome', 'sessionId'], config => [
|
||||
...optionalString(config, 'welcome'),
|
||||
...config.sessionId instanceof JsExpression ? [] : requiredString(config, 'sessionId'),
|
||||
]),
|
||||
])
|
||||
case 'embed':
|
||||
return new ProjectContribution(appProjectResources(profile, this.id))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Required app selection represented by ACP, TUI, or embed options. */
|
||||
/** Required app selection represented by ACP or embed options. */
|
||||
export class AppFeature extends ExclusiveOptionFeature {
|
||||
override readonly id = ID
|
||||
override readonly summary = 'Run interface'
|
||||
@@ -117,7 +90,6 @@ export class AppFeature extends ExclusiveOptionFeature {
|
||||
override readonly requires = [featureId('spine')]
|
||||
override readonly options = [
|
||||
new AppOption('acp', 'ACP automation server'),
|
||||
new AppOption('tui', 'Terminal TUI'),
|
||||
new AppOption('embed', 'Embedded context'),
|
||||
]
|
||||
|
||||
|
||||
@@ -357,21 +357,5 @@ config:
|
||||
}],
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'ask-user',
|
||||
summary: 'Ask the user from the model loop',
|
||||
mode: 'single',
|
||||
supportedInterfaces: ['tui'],
|
||||
options: [{
|
||||
id: 'default',
|
||||
label: 'ask_user_question tool',
|
||||
default: true,
|
||||
resources: [{
|
||||
kind: 'npm-cordis-config-entry',
|
||||
id: 'tool-ask-user',
|
||||
package: '@deepseek-ai/dsh-tool-ask-user',
|
||||
}],
|
||||
}],
|
||||
},
|
||||
]), profile)
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ class DefinedFeature extends Feature {
|
||||
this.required = spec.required ?? false
|
||||
this.requires = (spec.requires ?? []).map(requirement => featureId(requirement.id))
|
||||
this.suggests = (spec.suggests ?? []).map(featureId)
|
||||
this.supportedInterfaces = spec.supportedInterfaces ?? ['acp', 'tui', 'embed']
|
||||
this.supportedInterfaces = spec.supportedInterfaces ?? ['acp', 'embed']
|
||||
}
|
||||
|
||||
override defaultOptions(): readonly string[] {
|
||||
|
||||
@@ -113,7 +113,7 @@ export abstract class Feature {
|
||||
/** Features recommended during creation. */
|
||||
readonly suggests: readonly FeatureId[] = []
|
||||
/** Front doors under which this feature is meaningful. */
|
||||
readonly supportedInterfaces: readonly RunInterface[] = ['acp', 'tui', 'embed']
|
||||
readonly supportedInterfaces: readonly RunInterface[] = ['acp', 'embed']
|
||||
|
||||
/**
|
||||
* Options selected when installation has no override.
|
||||
|
||||
@@ -90,6 +90,7 @@ export class ProjectEditSession implements FeatureProjectView {
|
||||
this.profile = source.profile
|
||||
this.documents = source.cloneDocuments()
|
||||
for (const feature of registry.all()) {
|
||||
/* v8 ignore next -- no current builtin is interface-specific after TUI removal */
|
||||
if (!feature.isApplicable(this.profile)) continue
|
||||
const installation = feature.inspect(this)
|
||||
this.states.set(feature.id, {
|
||||
@@ -507,6 +508,7 @@ export class ProjectEditSession implements FeatureProjectView {
|
||||
const view = this.projectView(profile)
|
||||
for (const feature of this.registry.all()) {
|
||||
const state = this.states.get(feature.id)
|
||||
/* v8 ignore next 5 -- no current builtin is interface-specific after TUI removal */
|
||||
if (!feature.isApplicable(profile)) {
|
||||
if (state?.state === 'enabled') {
|
||||
throw new Error(`feature ${feature.id} is not available for ${profile.runInterface}`)
|
||||
@@ -549,7 +551,7 @@ export class ProjectEditSession implements FeatureProjectView {
|
||||
|
||||
private finalProfile(): ProjectProfile {
|
||||
const runInterface = this.states.get(featureId('app'))?.selection?.options[0]
|
||||
if (runInterface !== 'acp' && runInterface !== 'tui' && runInterface !== 'embed') return this.profile
|
||||
if (runInterface !== 'acp' && runInterface !== 'embed') return this.profile
|
||||
return { ...this.profile, runInterface }
|
||||
}
|
||||
|
||||
|
||||
@@ -41,8 +41,11 @@ const OPTIONAL_DOCUMENTS = [
|
||||
] as const
|
||||
|
||||
function runInterface(entries: readonly CordisConfigEntry[]): RunInterface {
|
||||
if (entries.some(entry => entry.name === '@deepseek-ai/dsh-tui'
|
||||
|| entry.name.startsWith('@deepseek-ai/dsh-tui/'))) {
|
||||
throw new Error('unsupported run interface: @deepseek-ai/dsh-tui has been removed')
|
||||
}
|
||||
if (entries.some(entry => entry.name === '@deepseek-ai/dsh-acp')) return 'acp'
|
||||
if (entries.some(entry => entry.name === '@deepseek-ai/dsh-tui')) return 'tui'
|
||||
return 'embed'
|
||||
}
|
||||
|
||||
@@ -146,7 +149,7 @@ export class SdkProject {
|
||||
static create(root: string, request: ProjectCreationRequest): SdkProject {
|
||||
const app = request.features.find(selection => selection.id === 'app')
|
||||
const selectedInterface = app?.options[0]
|
||||
if (selectedInterface !== 'acp' && selectedInterface !== 'tui' && selectedInterface !== 'embed') {
|
||||
if (selectedInterface !== 'acp' && selectedInterface !== 'embed') {
|
||||
throw new Error('project creation requires one app feature option')
|
||||
}
|
||||
const profile: ProjectProfile = {
|
||||
@@ -178,6 +181,7 @@ export class SdkProject {
|
||||
* Load an existing project from required and SDK-managed optional files.
|
||||
* @param root - existing project directory.
|
||||
* @returns disk-backed project snapshot.
|
||||
* @throws When the config references the removed `@deepseek-ai/dsh-tui` root or a subpath.
|
||||
*/
|
||||
static async open(root: string): Promise<SdkProject> {
|
||||
const absolute = resolve(root)
|
||||
|
||||
@@ -9,7 +9,7 @@ import type { LocalPluginBlueprint } from '../plugins/local-plugin-blueprint.ts'
|
||||
import type { FeatureId } from '../ids.ts'
|
||||
|
||||
/** Runtime front door selected for a generated project. */
|
||||
export type RunInterface = 'acp' | 'tui' | 'embed'
|
||||
export type RunInterface = 'acp' | 'embed'
|
||||
|
||||
/** Values shared by the required provider and app features. */
|
||||
interface ProjectRuntimeOptions {
|
||||
|
||||
@@ -9,16 +9,10 @@ Built with the DeepSeek Harness SDK using the {{model}} model.
|
||||
|
||||
Run `{{packageManager}} start` and configure a programmatic ACP client to launch this project. Standard output is reserved for ACP JSON-RPC.
|
||||
{{else}}
|
||||
{{#if isTui}}
|
||||
## Run in a terminal
|
||||
|
||||
Run `{{packageManager}} start` to start the interactive agent.
|
||||
{{else}}
|
||||
## Embed the harness
|
||||
|
||||
Import and call the exported `main()` from `index.ts` in your host application.
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
## Development
|
||||
|
||||
|
||||
@@ -8,47 +8,13 @@ import { startSDK, type SdkBootContext } from '@deepseek-ai/dsh-scripts'
|
||||
|
||||
/** Boot this project's cordis.yml when invoked by dsh-scripts. */
|
||||
export async function main(boot: SdkBootContext) {
|
||||
{{#if isTui}}
|
||||
const model = boot.args.model
|
||||
if (typeof model !== 'string' || model.length === 0) throw new Error('TUI startup requires --model=<name>')
|
||||
const resume = boot.args.resume
|
||||
if (resume !== undefined && (typeof resume !== 'string' || resume.length === 0)) {
|
||||
throw new Error('TUI startup requires --resume=<session-id>')
|
||||
}
|
||||
const sessionId = SessionId(resume ?? `main-session-${randomUUID()}`)
|
||||
process.env.DSH_SDK_SESSION_ID = sessionId
|
||||
{{/if}}
|
||||
const ctx = await startSDK(new URL('./cordis.yml', import.meta.url))
|
||||
{{#if isTui}}
|
||||
try {
|
||||
if (resume === undefined) {
|
||||
await ctx.agents.create({
|
||||
sessionId,
|
||||
meta: { cwd: boot.cwd },
|
||||
agentOptions: { model },
|
||||
})
|
||||
} else {
|
||||
await ctx.agents.resume({
|
||||
resumeSessionId: sessionId,
|
||||
agentOptions: { model },
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
try {
|
||||
await ctx.fiber.dispose()
|
||||
} catch (disposeError) {
|
||||
throw new AggregateError([error, disposeError], 'TUI startup and cleanup failed')
|
||||
}
|
||||
throw error
|
||||
}
|
||||
{{else}}
|
||||
{{#if isEmbed}}
|
||||
await ctx.agents.create({
|
||||
sessionId: SessionId(`main-session-${randomUUID()}`),
|
||||
meta: { cwd: boot.cwd },
|
||||
agentOptions: { model: {{modelLiteral}} },
|
||||
})
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
return ctx
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ export interface ProjectTemplateContext {
|
||||
model: string
|
||||
modelLiteral: string
|
||||
isAcp: boolean
|
||||
isTui: boolean
|
||||
isEmbed: boolean
|
||||
packageManager: PackageManagerName
|
||||
installArgs: string
|
||||
@@ -60,7 +59,6 @@ export function createProjectTemplateContext(
|
||||
model: profile.runtime.model,
|
||||
modelLiteral: JSON.stringify(profile.runtime.model),
|
||||
isAcp: runInterface === 'acp',
|
||||
isTui: runInterface === 'tui',
|
||||
isEmbed: runInterface === 'embed',
|
||||
packageManager: profile.packageManager.name,
|
||||
installArgs: profile.packageManager.installCommand().join(' '),
|
||||
@@ -104,10 +102,9 @@ export function createAppProjectArtifacts(
|
||||
}
|
||||
|
||||
/** Build package scripts owned by the selected app feature option. */
|
||||
export function createAppPackageScripts(context: ProjectTemplateContext): Readonly<Record<'dev' | 'start', string>> {
|
||||
const modelArg = context.isTui ? ` -- --model=${JSON.stringify(context.model)}` : ''
|
||||
export function createAppPackageScripts(): Readonly<Record<'dev' | 'start', string>> {
|
||||
return {
|
||||
dev: `dsh-sdk dev index.ts${modelArg}`,
|
||||
start: `dsh-sdk start index.js${modelArg}`,
|
||||
dev: 'dsh-sdk dev index.ts',
|
||||
start: 'dsh-sdk start index.js',
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user