Merge commit 'refs/codex/pr1006/master' into worktree/pr1006-merge-20260731
# Conflicts: # docs/architecture.i18n.yaml # docs/config-catalog.md # docs/cordis-catalog/services.md # docs/core-data-structures/core.i18n.yaml # examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/session.jsonl # examples/headless-agent/cordis.yml # packages/cordis/tool-cordis/src/api-catalog.ts # packages/llm/llm-deepseek/README.i18n.yaml # packages/llm/llm-deepseek/README.md # packages/llm/llm-deepseek/README.zh.md # packages/llm/llm-deepseek/src/adapter.ts # packages/llm/llm-deepseek/src/index.ts # packages/llm/llm-deepseek/tests/adapter.spec.ts # packages/llm/llm/README.i18n.yaml # packages/llm/llm/README.md # packages/llm/llm/README.zh.md # packages/subagent/subagent-dsh-sdk/README.i18n.yaml # packages/ui/jsonrpc/README.i18n.yaml
This commit is contained in:
@@ -29,6 +29,8 @@ const goalScenarioDir = join(snapshotsDir, 'goal-tools')
|
||||
const goalConfigPath = fileURLToPath(new URL('../goal.cordis.snapshot.yml', import.meta.url))
|
||||
const retryScenarioDir = join(snapshotsDir, 'provider-retry')
|
||||
const retryConfigPath = fileURLToPath(new URL('../retry.cordis.snapshot.yml', import.meta.url))
|
||||
const credentialsScenarioDir = join(snapshotsDir, 'missing-credential')
|
||||
const credentialsConfigPath = fileURLToPath(new URL('../credentials.cordis.snapshot.yml', import.meta.url))
|
||||
const ralphScenarioDir = join(snapshotsDir, 'ralph-loop')
|
||||
const ralphConfigPath = fileURLToPath(new URL('../ralph.cordis.snapshot.yml', import.meta.url))
|
||||
const binScript = fileURLToPath(new URL('../../../packages/examples/cli-demo/src/bin.ts', import.meta.url))
|
||||
@@ -188,7 +190,7 @@ describe('headless stream-json snapshots', () => {
|
||||
const retries = records.filter(record => record.type === 'llm/retry')
|
||||
expect(retries).toHaveLength(1)
|
||||
expect(retries[0]?.data).toMatchObject({
|
||||
provider: 'deepseek',
|
||||
provider: 'deepseek-official',
|
||||
mode: 'normal',
|
||||
policyKey: '["normal",1,["RATE_LIMIT"],1,1,0]',
|
||||
retry: 1,
|
||||
@@ -205,6 +207,40 @@ describe('headless stream-json snapshots', () => {
|
||||
expect(normalized).toBe(await readFile(streamExpected, 'utf8'))
|
||||
}, LOADER_SMOKE_TEST_TIMEOUT_MS)
|
||||
|
||||
it('surfaces actionable missing-credential guidance through the one-shot app', async () => {
|
||||
const streamExpected = join(credentialsScenarioDir, 'stream-json.expected.jsonl')
|
||||
let runCwd = ''
|
||||
const result = await runLoaderSmoke({
|
||||
label: 'missing-credential headless stream-json snapshot',
|
||||
tempDirPrefix: 'headless-snapshot-missing-credential-',
|
||||
binScript,
|
||||
configPath: credentialsConfigPath,
|
||||
binArgs: ['--config', credentialsConfigPath, '--output-format', 'stream-json', 'say pong'],
|
||||
tsconfigPath,
|
||||
env: {
|
||||
// First-run posture: no key in the environment, none under ./.dsh.
|
||||
DEEPSEEK_API_KEY: '',
|
||||
DEEPSEEK_BASE_URL: '',
|
||||
NODE_OPTIONS: [process.env.NODE_OPTIONS, '--disable-warning=ExperimentalWarning'].filter(Boolean).join(' '),
|
||||
},
|
||||
// The designed failure surface: the one-shot app reports the failed turn.
|
||||
expectedExitCode: 1,
|
||||
prepare: (cwd) => { runCwd = cwd },
|
||||
})
|
||||
|
||||
// The guidance leads with the credential store — the path that keeps the
|
||||
// secret out of configuration files — and offers a literal key last.
|
||||
expect(result.stderr).toBe(
|
||||
'dsh-cli-demo: turn 1 failed at step 1: llm-deepseek: no API key for provider route "deepseek-official";'
|
||||
+ ' store DEEPSEEK_API_KEY through the credentials service (the web Models page writes it),'
|
||||
+ ' export DEEPSEEK_API_KEY in the launching environment, or — as a last resort — set a literal'
|
||||
+ ' "apiKey" in the llm-deepseek settings section\n',
|
||||
)
|
||||
const normalized = normalizeHeadlessStream(result.stdout, runCwd)
|
||||
if (refreshing) await writeFile(streamExpected, normalized)
|
||||
expect(normalized).toBe(await readFile(streamExpected, 'utf8'))
|
||||
}, LOADER_SMOKE_TEST_TIMEOUT_MS)
|
||||
|
||||
it('logs the model default and a dynamic next-step reasoning effort', async () => {
|
||||
const result = await runLoaderSmoke({
|
||||
label: 'reasoning effort headless stream-json snapshot',
|
||||
@@ -283,7 +319,7 @@ describe('headless stream-json snapshots', () => {
|
||||
{
|
||||
"maxTokens": 256000,
|
||||
"model": "deepseek-v4-flash",
|
||||
"provider": "deepseek",
|
||||
"provider": "deepseek-official",
|
||||
"reasoningEffort": "off",
|
||||
}
|
||||
`)
|
||||
|
||||
Reference in New Issue
Block a user