From 642b1c29d3a2155bb101194d8c0d0bb31f6f0977 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Sun, 19 Jul 2026 23:03:08 +0800 Subject: [PATCH] feat(examples): configure max-token success via env --- examples/jsonrpc-agent/README.md | 1 + examples/jsonrpc-agent/cordis.yml | 2 +- .../jsonrpc-agent/tests/keyless-smoke.e2e.ts | 52 ++++++++++++++++++- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/examples/jsonrpc-agent/README.md b/examples/jsonrpc-agent/README.md index cfbf6787b1..83c6e98fa5 100644 --- a/examples/jsonrpc-agent/README.md +++ b/examples/jsonrpc-agent/README.md @@ -18,6 +18,7 @@ The surrounding runtime also loads JSONL session persistence and automatic conte | `DEEPSEEK_API_KEY` | Credential passed to the OpenAI-compatible host endpoint | | `DEEPSEEK_BASE_URL` | Host endpoint used by `dsh-llm-deepseek` | | `DSH_CWD` | Agent workspace for bash and filesystem tools | +| `DSH_MAX_TOKENS_AS_SUCCESS` | `true` (default) accepts token-limited results; `false` reports them as errors | | `DSH_SESSION_ROOT` | JSONL trajectory directory | | `DSH_SYSTEM_PROMPT` | Deployment-provided coding persona | diff --git a/examples/jsonrpc-agent/cordis.yml b/examples/jsonrpc-agent/cordis.yml index de19b3da94..00ef48f4ed 100644 --- a/examples/jsonrpc-agent/cordis.yml +++ b/examples/jsonrpc-agent/cordis.yml @@ -4,7 +4,7 @@ - id: jsonrpc name: '@deepseek-ai/dsh-jsonrpc' config: - maxTokensAsSuccess: true + maxTokensAsSuccess: !!js "process.env.DSH_MAX_TOKENS_AS_SUCCESS === undefined ? true : JSON.parse(process.env.DSH_MAX_TOKENS_AS_SUCCESS)" - id: llm-deepseek name: '@deepseek-ai/dsh-llm-deepseek' diff --git a/examples/jsonrpc-agent/tests/keyless-smoke.e2e.ts b/examples/jsonrpc-agent/tests/keyless-smoke.e2e.ts index 41afb03574..c99b2c3c50 100644 --- a/examples/jsonrpc-agent/tests/keyless-smoke.e2e.ts +++ b/examples/jsonrpc-agent/tests/keyless-smoke.e2e.ts @@ -43,7 +43,11 @@ function waitForLine( } describe('jsonrpc-agent keyless smoke', () => { - it('boots the real Cordis tree and serves initialize/shutdown over clean stdout', async () => { + it.each([ + { label: 'accepts max-token results by default', envValue: undefined, expectedStatus: 'ok' }, + { label: 'accepts max-token results when enabled through env', envValue: 'true', expectedStatus: 'ok' }, + { label: 'reports max-token results as errors when disabled through env', envValue: 'false', expectedStatus: 'error' }, + ])('$label', async ({ envValue, expectedStatus }) => { const root = await mkdtemp(join(tmpdir(), 'dsh-jsonrpc-agent-smoke-')) const modelRequests: Record[] = [] const modelServer = createServer((request, response) => { @@ -55,7 +59,7 @@ describe('jsonrpc-agent keyless smoke', () => { response.writeHead(200, { 'content-type': 'text/event-stream' }) response.write('data: {"choices":[{"delta":{"role":"assistant","content":null}}]}\n\n') response.write('data: {"choices":[{"delta":{"content":"done"}}]}\n\n') - response.write('data: {"choices":[{"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":3,"completion_tokens":1}}\n\n') + response.write('data: {"choices":[{"delta":{},"finish_reason":"length"}],"usage":{"prompt_tokens":3,"completion_tokens":1}}\n\n') response.end('data: [DONE]\n\n') }) }) @@ -76,6 +80,7 @@ describe('jsonrpc-agent keyless smoke', () => { DEEPSEEK_BASE_URL: `http://127.0.0.1:${address.port}`, DSH_CWD: root, DSH_SESSION_ROOT: join(root, '.sessions'), + ...(envValue === undefined ? {} : { DSH_MAX_TOKENS_AS_SUCCESS: envValue }), }, stdio: ['pipe', 'pipe', 'pipe'], }) @@ -112,6 +117,16 @@ describe('jsonrpc-agent keyless smoke', () => { method: 'session/prompt', params: { sessionId: 'main', contentBlocks: [{ type: 'text', text: 'inspect tools' }] }, })}\n`) + const finished = await waitForLine(lines, value => value.method === 'session.finished', () => stderr) + expect(finished).toMatchObject({ + jsonrpc: '2.0', + method: 'session.finished', + params: { + sessionId: 'main', + status: expectedStatus, + reason: { kind: 'max-tokens' }, + }, + }) const prompt = await waitForLine(lines, value => value.id === 2, () => stderr) expect(prompt).toMatchObject({ jsonrpc: '2.0', id: 2, result: { accepted: true } }) const tools = modelRequests[0]?.tools as { function?: { name?: string } }[] @@ -143,4 +158,37 @@ describe('jsonrpc-agent keyless smoke', () => { await rm(root, { recursive: true, force: true }) } }, 40_000) + + it('rejects an invalid max-token success env value', async () => { + const child = spawn(process.execPath, [ + '--expose-internals', + '--import', + 'tsx', + binScript, + configPath, + ], { + cwd: repoRoot, + env: { + ...process.env, + DEEPSEEK_API_KEY: 'keyless-smoke-no-call', + DSH_MAX_TOKENS_AS_SUCCESS: 'sometimes', + }, + stdio: ['ignore', 'pipe', 'pipe'], + }) + let stdout = '' + let stderr = '' + child.stdout.setEncoding('utf8') + child.stdout.on('data', (chunk: string) => { stdout += chunk }) + child.stderr.setEncoding('utf8') + child.stderr.on('data', (chunk: string) => { stderr += chunk }) + + const exitCode = await new Promise((resolve, reject) => { + child.once('error', reject) + child.once('exit', resolve) + }) + + expect(exitCode, stderr).toBe(1) + expect(stdout).toBe('') + expect(stderr).toContain('plugin(s) failed to load: @deepseek-ai/dsh-jsonrpc') + }, 10_000) })