Merge branch 'master' of https://github.com/deepseek-harness/deepseek-harness into xtr/react-loop-simplification

# Conflicts:
#	.agents/notes/implemented/feature/2026-07-17-dedicated-full-screen-tui-front-door.i18n.yaml
#	docs/architecture.i18n.yaml
#	docs/cookbook/extension-cookbook.i18n.yaml
#	docs/cordis-catalog/events.md
#	docs/cordis-catalog/services.md
#	docs/core-data-structures/core.i18n.yaml
#	docs/core-data-structures/core.md
#	docs/core-data-structures/core.zh.md
#	docs/core-data-structures/llm-streaming.i18n.yaml
#	docs/core-data-structures/llm-streaming.md
#	docs/core-data-structures/llm-streaming.zh.md
#	docs/core-data-structures/session.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/persistence-catalog.md
#	packages/cordis/tool-cordis/src/api-catalog.ts
#	packages/core/agent-loop/README.i18n.yaml
#	packages/core/agent-loop/src/agent.ts
#	packages/core/agent/README.i18n.yaml
#	packages/core/session/README.i18n.yaml
#	packages/core/session/src/types.ts
#	packages/llm/llm/README.i18n.yaml
#	packages/llm/llm/README.md
#	packages/llm/llm/README.zh.md
#	packages/llm/llm/src/index.ts
#	packages/llm/llm/tests/service.spec.ts
#	packages/sdk/sdk-client/README.i18n.yaml
#	packages/sdk/sdk-protocol/README.i18n.yaml
#	packages/sdk/sdk-protocol/README.md
#	packages/sdk/sdk-protocol/README.zh.md
#	packages/subagent/subagent-dsh-sdk/README.i18n.yaml
#	packages/ui/jsonrpc/README.i18n.yaml
#	packages/ui/jsonrpc/README.md
#	packages/ui/jsonrpc/README.zh.md
#	packages/ui/tui/src/index.ts
#	python/sdk/README.i18n.yaml
#	scripts/gen-cordis-catalog.ts
This commit is contained in:
_Kerman
2026-07-31 10:16:14 +08:00
1106 changed files with 33236 additions and 7168 deletions

View File

@@ -11,7 +11,7 @@ import type { PackageManagerName, RunInterface } from '@deepseek-ai/dsh-helper'
export interface CreateArgs {
directory?: string
description?: string
provider?: 'deepseek' | 'custom'
provider?: 'deepseek-official' | 'custom'
baseURL?: string
apiKey?: string
model?: string
@@ -27,7 +27,7 @@ export interface CreateArgs {
interface CommanderCreateOptions {
description?: string
provider?: 'deepseek' | 'custom'
provider?: 'deepseek-official' | 'custom'
baseUrl?: string
apiKey?: string
model?: string
@@ -57,7 +57,7 @@ function createProgram(): Command {
.argument('[directory]')
.option('-h, --help')
.option('--description <text>')
.addOption(new Option('--provider <name>').choices(['deepseek', 'custom']))
.addOption(new Option('--provider <name>').choices(['deepseek-official', 'custom']))
.option('--base-url <url>')
.option('--api-key <key>')
.option('--model <name>')

View File

@@ -24,7 +24,7 @@ export interface ProjectAnswers {
directory: string
name: string
description: string
provider: 'deepseek' | 'custom'
provider: 'deepseek-official' | 'custom'
baseURL: string
apiKey: string
model: string
@@ -142,14 +142,14 @@ const PROJECT_QUESTION_STEPS: readonly WizardStep<ProjectAnswerState>[] = [
apply: (state, value) => { state.description = value },
}),
questionStep({
question: () => new SelectQuestion<'deepseek' | 'custom'>({
question: () => new SelectQuestion<'deepseek-official' | 'custom'>({
id: 'provider',
message: 'Model provider',
options: [
{ value: 'deepseek', label: 'DeepSeek' },
{ value: 'deepseek-official', label: 'DeepSeek' },
{ value: 'custom', label: 'Custom endpoint (pi-ai)' },
],
initialValue: 'deepseek',
initialValue: 'deepseek-official',
}),
prefilled: state => state.args.provider,
apply: (state, value) => { state.provider = value },

View File

@@ -18,7 +18,7 @@ import type { CreateArgs } from './args.ts'
interface HeadlessCreateSpec {
directory?: string
description?: string
provider?: 'deepseek' | 'custom'
provider?: 'deepseek-official' | 'custom'
baseURL?: string
apiKey?: string
model?: string

View File

@@ -2,7 +2,7 @@ Usage: create-sdk [directory] [options]
Options:
--description <text>
--provider <deepseek|custom>
--provider <deepseek-official|custom>
--base-url <url>
--api-key <key>
--model <name>

View File

@@ -87,7 +87,7 @@ describe.skipIf(process.platform === 'win32')('create-sdk terminal contract', ()
'my-agent',
'my-agent',
'Snapshot agent',
'deepseek',
'deepseek-official',
'secret-key',
'acp',
[
@@ -166,7 +166,7 @@ describe.skipIf(process.platform === 'win32')('create-sdk terminal contract', ()
"message": "Project description",
},
{
"initialValue": "deepseek",
"initialValue": "deepseek-official",
"kind": "select",
"message": "Model provider",
"options": [
@@ -330,7 +330,7 @@ describe.skipIf(process.platform === 'win32')('create-sdk terminal contract', ()
{
"id": "provider",
"options": [
"deepseek",
"deepseek-official",
],
},
{

View File

@@ -131,13 +131,13 @@ afterEach(async () => {
describe('create arguments', () => {
it('parses public options and the private repository link mode', () => {
expect(parseCreateArgs([
'agent', '--description=demo', '--provider', 'deepseek', '--base-url=https://api.example',
'agent', '--description=demo', '--provider', 'deepseek-official', '--base-url=https://api.example',
'--api-key', 'key', '--model=m', '--interface', 'acp', '--pm=pnpm', '--no-install',
'--link-workspace',
])).toEqual({
directory: 'agent',
description: 'demo',
provider: 'deepseek',
provider: 'deepseek-official',
baseURL: 'https://api.example',
apiKey: 'key',
model: 'm',
@@ -205,7 +205,7 @@ describe('CreateWizard and scaffolder', () => {
const args = parseCreateArgs([
'my-agent',
'--description=demo',
'--provider=deepseek',
'--provider=deepseek-official',
'--api-key=deepseek-key',
'--model=deepseek-v4-flash',
'--interface=tui',
@@ -246,7 +246,7 @@ describe('CreateWizard and scaffolder', () => {
]
const resolved = await new CreateWizard({
args: parseCreateArgs([
'my-agent', '--description=demo', '--provider=deepseek', '--api-key=deepseek-key',
'my-agent', '--description=demo', '--provider=deepseek-official', '--api-key=deepseek-key',
'--model=deepseek-v4-flash', '--interface=tui', '--pm=npm', '--no-install',
]),
port: new HeadlessPromptPort(),
@@ -274,7 +274,7 @@ describe('CreateWizard and scaffolder', () => {
] as unknown as FeatureSelection[]
await expect(new CreateWizard({
args: parseCreateArgs([
'my-agent', '--description=demo', '--provider=deepseek', '--api-key=k',
'my-agent', '--description=demo', '--provider=deepseek-official', '--api-key=k',
'--model=m', '--interface=tui', '--pm=npm', '--no-install',
]),
port: new HeadlessPromptPort(),
@@ -295,7 +295,7 @@ describe('CreateWizard and scaffolder', () => {
packageManager: new NpmPackageManager('10.0.0'),
releaseVersion: '0.0.1',
features: [
{ id: featureId('provider'), options: ['deepseek'], secrets: { apiKey: 'key' } },
{ id: featureId('provider'), options: ['deepseek-official'], secrets: { apiKey: 'key' } },
{ id: featureId('bash'), options: ['local'] },
{ id: featureId('app'), options: ['embed'] },
{ id: featureId('persistence'), options: ['jsonl'] },
@@ -346,7 +346,7 @@ describe('CreateWizard and scaffolder', () => {
])
const resolved = await new CreateWizard({
args: parseCreateArgs([
'workflow-agent', '--description=test', '--provider=deepseek', '--api-key=key',
'workflow-agent', '--description=test', '--provider=deepseek-official', '--api-key=key',
'--interface=embed', '--pm=npm', '--no-install',
]),
port,
@@ -371,7 +371,7 @@ describe('CreateWizard and scaffolder', () => {
])
const resolved = await new CreateWizard({
args: parseCreateArgs([
'empty-key-agent', '--description=test', '--provider=deepseek',
'empty-key-agent', '--description=test', '--provider=deepseek-official',
'--interface=embed', '--pm=npm', '--no-install',
]),
port,
@@ -398,7 +398,7 @@ describe('CreateWizard and scaffolder', () => {
'embed',
[
{ value: featureId('persistence'), choices: ['jsonl'] },
{ value: featureId('web'), choices: ['deepseek'] },
{ value: featureId('web'), choices: ['deepseek-official'] },
],
true,
'none',
@@ -426,14 +426,14 @@ describe('CreateWizard and scaffolder', () => {
'agent',
[
{ value: featureId('persistence'), choices: ['jsonl'] },
{ value: featureId('web'), choices: ['deepseek'] },
{ value: featureId('web'), choices: ['deepseek-official'] },
{ value: featureId('timeout-policy'), choices: ['default'] },
],
'none',
])
const resolved = await new CreateWizard({
args: parseCreateArgs([
'agent', '--description=test', '--provider=deepseek', '--api-key=key',
'agent', '--description=test', '--provider=deepseek-official', '--api-key=key',
'--interface=embed', '--pm=npm', '--no-install',
]),
port,
@@ -451,7 +451,7 @@ describe('CreateWizard and scaffolder', () => {
])
const resolved = await new CreateWizard({
args: parseCreateArgs([
name, '--description=test', '--provider=deepseek', '--api-key=key',
name, '--description=test', '--provider=deepseek-official', '--api-key=key',
'--interface=embed', '--pm=npm', '--no-install',
]),
port,
@@ -467,7 +467,7 @@ describe('CreateWizard and scaffolder', () => {
describe('create command composition', () => {
const argv = (directory: string, install: boolean): string[] => [
directory, '--description=test', '--provider=deepseek', '--api-key=key',
directory, '--description=test', '--provider=deepseek-official', '--api-key=key',
'--interface=embed', '--pm=npm', install ? '--install' : '--no-install',
]
@@ -490,7 +490,7 @@ describe('create command composition', () => {
const root = await mkdtemp(join(tmpdir(), 'create-headless-cmd-'))
temporary.push(root)
const spec = JSON.stringify({
directory: 'agent', description: 'test', provider: 'deepseek', apiKey: 'key',
directory: 'agent', description: 'test', provider: 'deepseek-official', apiKey: 'key',
model: 'deepseek-v4-flash', interface: 'embed', pm: 'npm', install: false,
features: [{ id: 'persistence', options: ['jsonl'] }],
})
@@ -510,7 +510,7 @@ describe('create command composition', () => {
const ok = commandContext(root)
ok.stdin.isTTY = false
ok.stdout.isTTY = false
const okSpec = JSON.stringify({ ...base, directory: 'done-agent', provider: 'deepseek', apiKey: 'key', features: [] })
const okSpec = JSON.stringify({ ...base, directory: 'done-agent', provider: 'deepseek-official', apiKey: 'key', features: [] })
await expect(runCreateCommand(['--config-json', okSpec, '--json'], ok)).resolves.toBe(0)
expect(ok.readStdout()).toContain('{"type":"done"}')
// stdout stays pure NDJSON: every line parses, human progress goes to stderr
@@ -573,7 +573,7 @@ describe('create command composition', () => {
expect(install).toHaveBeenCalledOnce()
expect(build).toHaveBeenCalledOnce()
const spec = JSON.stringify({
directory: 'json-agent', description: 'test', provider: 'deepseek', apiKey: 'key',
directory: 'json-agent', description: 'test', provider: 'deepseek-official', apiKey: 'key',
model: 'deepseek-v4-flash', interface: 'embed', pm: 'npm', install: true, features: [],
})
const json = commandContext(root)

View File

@@ -64,7 +64,7 @@ describe.skipIf(!existsSync(builtScripts))('live-linked generated projects', ()
releaseVersion: '0.0.1',
linkWorkspaceRoot: repoRoot,
features: [
{ id: featureId('provider'), options: ['deepseek'], secrets: { apiKey: 'test-key' } },
{ id: featureId('provider'), options: ['deepseek-official'], secrets: { apiKey: 'test-key' } },
{ id: featureId('bash'), options: ['local'] },
{ id: featureId('app'), options: ['embed'] },
{ id: featureId('persistence'), options: ['jsonl'] },

View File

@@ -154,7 +154,7 @@ config:
],
options: [
{
id: 'deepseek',
id: 'deepseek-official',
label: 'DeepSeek search',
default: true,
markers: [{ id: 'web-search-deepseek', name: '@deepseek-ai/dsh-web-search-deepseek' }],

View File

@@ -20,7 +20,7 @@ const DEFAULT_MODEL = 'deepseek-v4-flash'
const API_KEY_COMMENT = 'Required before start; an empty value makes provider startup fail.'
class DeepSeekOption extends FeatureOption {
override readonly id = 'deepseek'
override readonly id = 'deepseek-official'
override readonly label = 'DeepSeek'
override readonly secrets = [{
id: 'apiKey',
@@ -76,7 +76,7 @@ export class ProviderFeature extends ExclusiveOptionFeature {
/** Prefer the direct-fetch adapter and its public endpoint defaults. */
override defaultOptions(): readonly string[] {
return ['deepseek']
return ['deepseek-official']
}
/** Recover literal endpoint overrides from either provider entry. */

View File

@@ -61,7 +61,7 @@ function request(
packageManager: new NpmPackageManager('10.0.0'),
releaseVersion: '0.0.1',
features: [
selection('provider', ['deepseek'], { apiKey: 'test-key' }),
selection('provider', ['deepseek-official'], { apiKey: 'test-key' }),
selection('bash', [bash]),
selection('app', [app]),
selection('persistence', ['jsonl']),
@@ -344,7 +344,7 @@ describe('SdkProject and ProjectEditSession', () => {
const edit = project.edit(registry)
expect(edit.inspections()).not.toHaveLength(0)
const todo = registry.get(featureId('todo'))
edit.configureFeature(registry.get(featureId('web')), selection('web', ['deepseek']))
edit.configureFeature(registry.get(featureId('web')), selection('web', ['deepseek-official']))
edit.disableFeature(todo)
edit.configureFeature(todo, selection('todo', ['default']))
edit.enableFeature(todo)
@@ -598,7 +598,7 @@ describe('SdkProject and ProjectEditSession', () => {
expect(installation.diagnostics).toContain('missing package.json dependencies entry @deepseek-ai/dsh-llm-deepseek')
const partialEdit = partial.edit(createBuiltinRegistry(partial.profile))
const provider = createBuiltinRegistry(partial.profile).get(featureId('provider'))
expect(() => { partialEdit.configureFeature(provider, selection('provider', ['deepseek'])) }).toThrow('inconsistent')
expect(() => { partialEdit.configureFeature(provider, selection('provider', ['deepseek-official'])) }).toThrow('inconsistent')
expect(() => { partialEdit.enableFeature(provider) }).toThrow('inconsistent')
expect(() => { partialEdit.disableFeature(provider) }).toThrow('required feature')
})
@@ -615,7 +615,7 @@ describe('SdkProject and ProjectEditSession', () => {
const edit = project.edit(builtin)
const web = builtin.get(featureId('web'))
expect(() => { edit.disableFeature(web) }).toThrow('inconsistent')
expect(() => { edit.installFeature(web, selection('web', ['deepseek'])) }).toThrow('inconsistent')
expect(() => { edit.installFeature(web, selection('web', ['deepseek-official'])) }).toThrow('inconsistent')
class RequiresWeb extends FixedFeature {
override readonly id = featureId('requires-web')
@@ -656,7 +656,7 @@ describe('SdkProject and ProjectEditSession', () => {
const project = await createCommitted([selection('web', ['exa'], { apiKey: 'exa' })])
const registry = createBuiltinRegistry(project.profile)
const edit = project.edit(registry)
edit.configureFeature(registry.get(featureId('web')), selection('web', ['deepseek']))
edit.configureFeature(registry.get(featureId('web')), selection('web', ['deepseek-official']))
expect(edit.readEnvironment('.env.example', 'EXA_API_KEY')).toBeUndefined()
})
@@ -676,7 +676,7 @@ describe('SdkProject and ProjectEditSession', () => {
const edit = reopened.edit(registry)
edit.configureFeature(
registry.get(featureId('provider')),
selection('provider', ['deepseek'], { apiKey: 'replacement' }),
selection('provider', ['deepseek-official'], { apiKey: 'replacement' }),
)
edit.installFeature(registry.get(featureId('web')), selection('web', ['exa'], { apiKey: 'exa-key' }))
const withExa = (await edit.commit()).project
@@ -686,7 +686,7 @@ describe('SdkProject and ProjectEditSession', () => {
}
const nextRegistry = createBuiltinRegistry(withExa.profile)
const remove = withExa.edit(nextRegistry)
remove.configureFeature(nextRegistry.get(featureId('web')), selection('web', ['deepseek']))
remove.configureFeature(nextRegistry.get(featureId('web')), selection('web', ['deepseek-official']))
await remove.commit()
expect(await readFile(join(withExa.root, '.env'), 'utf8')).toBe(`${original}EXA_API_KEY=exa-key\n`)
})
@@ -936,12 +936,12 @@ describe('extension points', () => {
expect(spineAgentLoop?.validateConfig?.({ agents: 'main' })).toEqual(['agents must be an array'])
expect(spineAgentLoop?.validateConfig?.({ agents: ['main'] })).toEqual(['agents must be empty'])
expect(spineAgentLoop?.validateConfig?.({ agents: [] })).toEqual([])
expect(builtins.get(featureId('provider')).defaultOptions(profile)).toEqual(['deepseek'])
expect(builtins.get(featureId('provider')).defaultOptions(profile)).toEqual(['deepseek-official'])
expect(() => builtins.get(featureId('provider')).contribution({
id: featureId('provider'), options: ['custom'], values: { baseURL: 1 },
}, profile)).toThrow('baseURL must be a string')
const alternateModel = builtins.get(featureId('provider')).contribution({
id: featureId('provider'), options: ['deepseek'],
id: featureId('provider'), options: ['deepseek-official'],
}, { ...profile, runtime: { model: 'other' } }).resources
.find(resource => resource.kind === 'cordis-config-entry')
expect(alternateModel?.entry.config?.models).toEqual(['other'])

View File

@@ -383,7 +383,7 @@ describe('feature configurator', () => {
it('shares exclusive, multiple, fixed, and secret behavior', async () => {
const registry = createBuiltinRegistry(profile)
const port = new QueuePromptPort(['sqlite', ['spawn', 'fork'], 'deepseek', 'new-key'])
const port = new QueuePromptPort(['sqlite', ['spawn', 'fork'], 'deepseek-official', 'new-key'])
const configurator = new FeatureConfigurator(port)
await expect(configurator.configure(registry.get(featureId('persistence')), profile)).resolves.toMatchObject({
options: ['sqlite'],
@@ -394,7 +394,7 @@ describe('feature configurator', () => {
await expect(configurator.configure(
registry.get(featureId('provider')),
profile,
{ id: featureId('provider'), options: ['deepseek'], secrets: { apiKey: 'old-key' } },
{ id: featureId('provider'), options: ['deepseek-official'], secrets: { apiKey: 'old-key' } },
)).resolves.toMatchObject({ secrets: { apiKey: 'new-key' } })
expect(port.requests).toEqual([
'Choose durable session storage',
@@ -412,13 +412,13 @@ describe('feature configurator', () => {
})
const requiredSecret = new FeatureConfigurator(new QueuePromptPort([]))
await expect(requiredSecret.configure(
registry.get(featureId('provider')), profile, undefined, ['deepseek'], { apiKey: '' },
registry.get(featureId('provider')), profile, undefined, ['deepseek-official'], { apiKey: '' },
)).rejects.toThrow('required')
const keep = new FeatureConfigurator(new QueuePromptPort(['deepseek', '']))
const keep = new FeatureConfigurator(new QueuePromptPort(['deepseek-official', '']))
await expect(keep.configure(
registry.get(featureId('provider')),
profile,
{ id: featureId('provider'), options: ['deepseek'], secrets: { apiKey: 'old' } },
{ id: featureId('provider'), options: ['deepseek-official'], secrets: { apiKey: 'old' } },
)).resolves.toMatchObject({ secrets: { apiKey: 'old' } })
const custom = registry.get(featureId('provider'))
await expect(new FeatureConfigurator(new QueuePromptPort(['custom'])).configure(

View File

@@ -39,7 +39,7 @@
"@deepseek-ai/dsh-helper": "workspace:^",
"@deepseek-ai/dsh-telemetry": "workspace:^",
"commander": "^15.0.0",
"node-addon-require-builtin": "^0.1.0"
"node-addon-require-builtin": "^0.1.3"
},
"peerDependencies": {
"@deepseek-ai/dsh-app-boot": "workspace:^",

View File

@@ -34,7 +34,7 @@ Change file: package.json
{
"default": true,
"label": "DeepSeek",
"value": "deepseek",
"value": "deepseek-official",
},
{
"default": false,
@@ -173,7 +173,7 @@ Change file: package.json
{
"default": true,
"label": "DeepSeek search",
"value": "deepseek",
"value": "deepseek-official",
},
{
"default": false,

View File

@@ -92,7 +92,7 @@ async function baseProject(): Promise<SdkProject> {
packageManager: new NpmPackageManager('10.0.0'),
releaseVersion: '0.0.1',
features: [
{ id: featureId('provider'), options: ['deepseek'], secrets: { apiKey: 'key' } },
{ id: featureId('provider'), options: ['deepseek-official'], secrets: { apiKey: 'key' } },
{ id: featureId('bash'), options: ['local'] },
{ id: featureId('app'), options: ['tui'] },
{ id: featureId('persistence'), options: ['jsonl'] },

View File

@@ -94,7 +94,7 @@ function creation(
packageManager: new NpmPackageManager('10.0.0'),
releaseVersion: '0.0.1',
features: [
{ id: featureId('provider'), options: ['deepseek'], secrets: { apiKey: 'key' } },
{ id: featureId('provider'), options: ['deepseek-official'], secrets: { apiKey: 'key' } },
{ id: featureId('bash'), options: ['local'] },
{ id: featureId('app'), options: [app] },
{ id: featureId('persistence'), options: ['jsonl'] },
@@ -550,7 +550,7 @@ describe('ConfigWorkflow', () => {
const output = outputBuffer()
const workflow = new ConfigWorkflow(new QueuePort([
[
{ value: 'feature:provider', choices: ['deepseek'] },
{ value: 'feature:provider', choices: ['deepseek-official'] },
{ value: 'feature:app', choices: ['acp'] },
{ value: 'feature:persistence', choices: ['jsonl'] },
{ value: 'feature:ask-user', choices: ['default'] },

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/sdk/sdk-client/README.md
README.md: 9c441e8538a62f7139f789eef78cf70d8008418a
README.zh.md: fbf638c9160d0356da0eae0566a2775146c47750
README.md: 8b1e981befd041b6dd92ad4364dc9dfbe9b3cee1
README.zh.md: 614be1c45b3dd0c1241e40bf43ee25aa4897498d

View File

@@ -13,7 +13,7 @@ import { DeepSeekHarness } from '@deepseek-ai/dsh-sdk-client'
await using harness = new DeepSeekHarness({
launch: { command: 'node', args: ['lib/bin.js', 'cordis.yml'] },
provider: 'deepseek',
provider: 'deepseek-official',
model: 'deepseek-v4-flash',
maxTokens: 49_152,
})

View File

@@ -13,7 +13,7 @@ import { DeepSeekHarness } from '@deepseek-ai/dsh-sdk-client'
await using harness = new DeepSeekHarness({
launch: { command: 'node', args: ['lib/bin.js', 'cordis.yml'] },
provider: 'deepseek',
provider: 'deepseek-official',
model: 'deepseek-v4-flash',
maxTokens: 49_152,
})

View File

@@ -37,7 +37,7 @@ export class DeepSeekHarness implements AsyncDisposable {
// process's cwd, but the wire cwd is resolved again inside the child — a
// relative value would double-resolve (e.g. `worker` → `worker/worker`).
this.cwd = resolve(options.cwd ?? options.launch.cwd ?? process.cwd())
this.provider = options.provider ?? 'deepseek'
this.provider = options.provider ?? 'deepseek-official'
this.model = options.model ?? 'deepseek-v4-flash'
this.maxTokens = options.maxTokens
}

View File

@@ -50,7 +50,7 @@ export interface DeepSeekHarnessOptions {
launch: HarnessClientOptions
/** Workspace cwd recorded on every SDK-created session (default: the launch cwd, else `process.cwd()`). */
cwd?: string
/** Provider route for SDK-created agents (default `deepseek`). */
/** Provider route for SDK-created agents (default `deepseek-official`). */
provider?: string
/** Model for SDK-created agents (default `deepseek-v4-flash`). */
model?: string

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/sdk/sdk-protocol/README.md
README.md: 2120e6090fcc5d5f4a543424e9c5647e6009bad6
README.zh.md: 70b046cf1dedbf01031e3e0a4441f522d6153fbc
README.md: 2d141e6f62ac0d324933996c282a2d0380af29f2
README.zh.md: ffaa515be6da26ef0e35b6c2d9ca6bfc34ae2944

View File

@@ -22,7 +22,7 @@ The shared wire protocol for the DeepSeek Harness SDK runtime: one newline-delim
| server→client | `subagent.started` | `SubagentStartedNotification` |
| server→client | `subagent.finished` | `SubagentFinishedNotification` (in-process runs only) |
`HarnessSdkRequestMap` and `HarnessSdkNotificationMap` index these by method name. `SessionPromptResult.messageId` identifies the queued `UserMessage`; it does not identify a later assistant message, turn ending, or prompt result. Clients combine the open-ended `session.event` stream with agent-wide `session.status` according to their own activity ownership. `InitializeParams.maxTokens` is an optional positive safe integer that caps each conversation-model output for SDK-created agents and their in-process descendants; omission leaves the provider default in control. The notification payload types depend on `SessionEvent` (`dsh-session`), `ContentBlock` (`dsh-llm`), and `SubagentStopReason` (`dsh-subagent`) — the protocol streams full session-log envelopes, so the session vocabulary is part of the wire contract. `serverInfo.name` stays the wire-stable `deepseek-harness-sdk-runtime`.
`HarnessSdkRequestMap` and `HarnessSdkNotificationMap` index these by method name. `SessionPromptResult.messageId` identifies the queued `UserMessage`; it does not identify a later assistant message, turn ending, or prompt result. Clients combine the open-ended `session.event` stream with agent-wide `session.status` according to their own activity ownership. `InitializeParams.maxTokens` is an optional positive safe integer that caps each conversation-model output for SDK-created agents and their in-process descendants; omission allows the selected adapter's exact-model default to apply, or otherwise preserves provider behavior. The notification payload types depend on `SessionEvent` (`dsh-session`), `ContentBlock` (`dsh-llm`), and `SubagentStopReason` (`dsh-subagent`) — the protocol streams full session-log envelopes, so the session vocabulary is part of the wire contract. `serverInfo.name` stays the wire-stable `deepseek-harness-sdk-runtime`.
## Model Experience

View File

@@ -22,7 +22,7 @@ DeepSeek Harness SDK 运行时的共享协议格式(wire format):一个按
| server→client | `subagent.started` | `SubagentStartedNotification` |
| server→client | `subagent.finished` | `SubagentFinishedNotification`(仅进程内运行) |
`HarnessSdkRequestMap` 与 `HarnessSdkNotificationMap` 按方法名索引这些类型。`SessionPromptResult.messageId` 标识已排队的 `UserMessage`;它不标识后续的助手消息、轮次结束或提示词结果。客户端根据自己对活动区间的所有权,组合持续开放的 `session.event` 流与 agent 级的 `session.status`。`InitializeParams.maxTokens` 是可选的正的安全整数,用于限制 SDK 创建的 agent 及其进程内后代的每次对话模型输出;省略时由提供方默认值控制。通知载荷类型依赖 `SessionEvent`(`dsh-session`)、`ContentBlock`(`dsh-llm`)与 `SubagentStopReason`(`dsh-subagent`)——协议以完整会话日志封套进行流式传输,因此会话词汇是协议格式契约的一部分。`serverInfo.name` 的协议值固定为 `deepseek-harness-sdk-runtime`。
`HarnessSdkRequestMap` 与 `HarnessSdkNotificationMap` 按方法名索引这些类型。`SessionPromptResult.messageId` 标识已排队的 `UserMessage`;它不标识后续的助手消息、轮次结束或提示词结果。客户端根据自己对活动区间的所有权,组合持续开放的 `session.event` 流与 agent 级的 `session.status`。`InitializeParams.maxTokens` 是可选的正的安全整数,用于限制 SDK 创建的 agent 及其进程内后代的每次对话模型输出;省略时会应用所选适配器的确切模型默认值,否则提供方行为保持不变。通知载荷类型依赖 `SessionEvent`(`dsh-session`)、`ContentBlock`(`dsh-llm`)与 `SubagentStopReason`(`dsh-subagent`)——协议以完整会话日志封套进行流式传输,因此会话词汇是协议格式契约的一部分。`serverInfo.name` 的协议值固定为 `deepseek-harness-sdk-runtime`。
## 模型体验