Merge branch 'codex/goal-session' into codex/commands

# Conflicts:
#	docs/architecture.md
#	docs/capability-seams.md
#	docs/config-catalog.md
#	docs/module-graph.md
#	knip.json
#	packages/examples/README.md
#	packages/examples/stdio-demo/README.md
#	packages/examples/stdio-demo/src/index.ts
#	packages/examples/tui-demo/package.json
#	packages/ui/README.md
#	packages/ui/tui/src/index.ts
This commit is contained in:
Tianyi Cui
2026-07-20 22:05:51 +08:00
237 changed files with 2872 additions and 4495 deletions
+11 -11
View File
@@ -29,7 +29,7 @@ const ID = featureId('app')
function appProjectResources(
profile: ProjectProfile,
runInterface: 'acp' | 'stdio' | 'embed',
runInterface: 'acp' | 'tui' | 'embed',
): readonly ProjectResource[] {
const context = createProjectTemplateContext(profile, runInterface)
const scripts = createAppPackageScripts(context)
@@ -43,10 +43,10 @@ function appProjectResources(
}
class AppOption extends FeatureOption {
override readonly id: 'acp' | 'stdio' | 'embed'
override readonly id: 'acp' | 'tui' | 'embed'
override readonly label: string
constructor(id: 'acp' | 'stdio' | 'embed', label: string) {
constructor(id: 'acp' | 'tui' | 'embed', label: string) {
super()
this.id = id
this.label = label
@@ -56,7 +56,7 @@ 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 'stdio': return [{ id: 'stdio', name: '@deepseek-ai/dsh-stdio' }]
case 'tui': return [{ id: 'tui', name: '@deepseek-ai/dsh-tui' }]
case 'embed': return []
}
}
@@ -65,7 +65,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-stdio')
&& !entries.some(entry => entry.name === '@deepseek-ai/dsh-acp' || entry.name === '@deepseek-ai/dsh-tui')
}
override contribution(profile: ProjectProfile): ProjectContribution {
@@ -87,7 +87,7 @@ class AppOption extends FeatureOption {
config: { model: profile.runtime.model },
}, ['model'], config => requiredString(config, 'model')),
])
case 'stdio':
case 'tui':
return new ProjectContribution([
...appProjectResources(profile, this.id),
...npmCordisConfigEntry(ID, {
@@ -95,10 +95,10 @@ class AppOption extends FeatureOption {
name: '@deepseek-ai/dsh-user-interaction',
}),
...npmCordisConfigEntry(ID, {
id: 'stdio',
name: '@deepseek-ai/dsh-stdio',
id: 'tui',
name: '@deepseek-ai/dsh-tui',
config: {
welcome: 'agent REPL ready. Give it a coding task.',
welcome: 'TUI agent ready. Give it a coding task.',
sessionId: new JsExpression('process.env.DSH_SDK_SESSION_ID'),
},
}, ['welcome', 'sessionId'], config => [
@@ -112,7 +112,7 @@ class AppOption extends FeatureOption {
}
}
/** Required app selection represented by acp, stdio, or embed options. */
/** Required app selection represented by ACP, TUI, or embed options. */
export class AppFeature extends ExclusiveOptionFeature {
override readonly id = ID
override readonly summary = 'Run interface'
@@ -120,7 +120,7 @@ export class AppFeature extends ExclusiveOptionFeature {
override readonly requires = [featureId('spine')]
override readonly options = [
new AppOption('acp', 'ACP server'),
new AppOption('stdio', 'Terminal REPL'),
new AppOption('tui', 'Terminal TUI'),
new AppOption('embed', 'Embedded context'),
]
@@ -347,7 +347,7 @@ config:
id: 'ask-user',
summary: 'Ask the user from the model loop',
mode: 'single',
supportedInterfaces: ['acp', 'stdio'],
supportedInterfaces: ['acp', 'tui'],
options: [{
id: 'default',
label: 'ask_user_question tool',
@@ -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', 'stdio', 'embed']
this.supportedInterfaces = spec.supportedInterfaces ?? ['acp', 'tui', 'embed']
}
override defaultOptions(): readonly string[] {
+1 -1
View File
@@ -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', 'stdio', 'embed']
readonly supportedInterfaces: readonly RunInterface[] = ['acp', 'tui', 'embed']
/**
* Options selected when installation has no override.