shennian 0.2.54 → 0.2.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,10 +2,10 @@
2
2
  // @test src/__tests__/model-switching.test.ts
3
3
  import { createInterface } from 'node:readline';
4
4
  import { resolveBuiltinCommand, spawnResolvedCommand } from '../command-spec.js';
5
- import { fallbackClaudeAliasModels, fallbackGeminiModels, parseCodexAppServerModels, parseCursorModels, parseOpenCodeModels, } from './parsers.js';
5
+ import { fallbackClaudeAliasModels, discoverClaudeAliasModelsFromEnv, fallbackGeminiModels, parseCodexAppServerModels, parseCursorModels, parseOpenCodeModels, } from './parsers.js';
6
6
  import { runResolvedCommand } from './runner.js';
7
7
  import { DISCOVERY_WORKDIR } from './types.js';
8
- import { buildAgentProcessEnv } from '../../agent-env.js';
8
+ import { buildAgentProcessEnv, readLatestUserEnv } from '../../agent-env.js';
9
9
  function sendAppServerRpc(proc, pending, id, method, params, timeoutMs) {
10
10
  if (!proc.stdin)
11
11
  return Promise.reject(new Error('codex app-server stdin unavailable'));
@@ -108,6 +108,9 @@ async function discoverOpenCodeModels() {
108
108
  async function discoverClaudeModels() {
109
109
  if (!resolveBuiltinCommand('claude'))
110
110
  return [];
111
+ const shellEnvModels = discoverClaudeAliasModelsFromEnv(readLatestUserEnv());
112
+ if (shellEnvModels.length > 0)
113
+ return shellEnvModels;
111
114
  return fallbackClaudeAliasModels();
112
115
  }
113
116
  async function discoverCodexModels() {
@@ -4,12 +4,14 @@ export declare function parseCursorModels(raw: string): ModelInfo[];
4
4
  export declare function parseOpenClawModels(raw: string): ModelInfo[];
5
5
  export declare function parseOpenCodeModels(raw: string): ModelInfo[];
6
6
  export declare function parseClaudeModels(raw: string): ModelInfo[];
7
- type EnvLike = Record<string, string | undefined>;
7
+ export type EnvLike = Record<string, string | undefined>;
8
+ export declare function readEnvValue(env: EnvLike, key: string): string | null;
9
+ export declare function inferClaudeOverrideProvider(modelName: string, env: EnvLike): string;
10
+ export declare function discoverClaudeAliasModelsFromEnv(env?: EnvLike): ModelInfo[];
8
11
  export declare function applyClaudeModelEnvOverrides(models: ModelInfo[], env?: EnvLike): ModelInfo[];
9
12
  export declare function parseClaudeBinaryModels(raw: string): ModelInfo[];
10
- export declare function fallbackClaudeAliasModels(): ModelInfo[];
13
+ export declare function fallbackClaudeAliasModels(env?: EnvLike): ModelInfo[];
11
14
  export declare function parseCodexModels(raw: string): ModelInfo[];
12
15
  export declare function parseCodexAppServerModels(raw: unknown): ModelInfo[];
13
16
  export declare function parseGeminiModels(raw: string): ModelInfo[];
14
17
  export declare function fallbackGeminiModels(): ModelInfo[];
15
- export {};
@@ -193,6 +193,9 @@ const CLAUDE_ALIAS_MODEL_ENV = {
193
193
  opus: 'ANTHROPIC_DEFAULT_OPUS_MODEL',
194
194
  haiku: 'ANTHROPIC_DEFAULT_HAIKU_MODEL',
195
195
  };
196
+ const CLAUDE_DEEPSEEK_REASONING_EFFORTS = [
197
+ { id: 'max', name: 'Max' },
198
+ ];
196
199
  const CLAUDE_REASONING_EFFORTS = [
197
200
  { id: 'low', name: 'Low' },
198
201
  { id: 'medium', name: 'Medium' },
@@ -207,17 +210,46 @@ function withClaudeReasoningEfforts(model) {
207
210
  defaultReasoningEffort: 'medium',
208
211
  };
209
212
  }
210
- function readEnvValue(env, key) {
213
+ export function readEnvValue(env, key) {
211
214
  const value = env[key]?.trim();
212
215
  return value || null;
213
216
  }
214
- function inferClaudeOverrideProvider(modelName, env) {
217
+ export function inferClaudeOverrideProvider(modelName, env) {
215
218
  const baseUrl = readEnvValue(env, 'ANTHROPIC_BASE_URL')?.toLowerCase() ?? '';
216
219
  if (baseUrl.includes('deepseek.com') || modelName.toLowerCase().startsWith('deepseek-')) {
217
220
  return 'deepseek';
218
221
  }
219
222
  return baseUrl ? 'custom' : 'anthropic';
220
223
  }
224
+ function configuredClaudeAliasModels(env) {
225
+ const configured = new Set();
226
+ for (const key of Object.values(CLAUDE_ALIAS_MODEL_ENV)) {
227
+ const modelName = readEnvValue(env, key);
228
+ if (modelName)
229
+ configured.add(modelName);
230
+ }
231
+ const models = Array.from(configured).map((modelName, index) => {
232
+ const provider = inferClaudeOverrideProvider(modelName, env);
233
+ const model = {
234
+ id: modelName,
235
+ name: modelName,
236
+ provider,
237
+ isDefault: index === 0,
238
+ };
239
+ if (provider === 'deepseek') {
240
+ return {
241
+ ...model,
242
+ supportedReasoningEfforts: CLAUDE_DEEPSEEK_REASONING_EFFORTS,
243
+ defaultReasoningEffort: readEnvValue(env, 'CLAUDE_CODE_EFFORT_LEVEL') ?? 'max',
244
+ };
245
+ }
246
+ return withClaudeReasoningEfforts(model);
247
+ });
248
+ return uniqueModels(models);
249
+ }
250
+ export function discoverClaudeAliasModelsFromEnv(env = process.env) {
251
+ return configuredClaudeAliasModels(env);
252
+ }
221
253
  export function applyClaudeModelEnvOverrides(models, env = process.env) {
222
254
  return models.map((model) => {
223
255
  if (!['default', 'sonnet', 'opus', 'haiku'].includes(model.id))
@@ -268,13 +300,16 @@ export function parseClaudeBinaryModels(raw) {
268
300
  }
269
301
  return uniqueModels(models);
270
302
  }
271
- export function fallbackClaudeAliasModels() {
303
+ export function fallbackClaudeAliasModels(env = process.env) {
304
+ const configuredModels = configuredClaudeAliasModels(env);
305
+ if (configuredModels.length > 0)
306
+ return configuredModels;
272
307
  return applyClaudeModelEnvOverrides([
273
308
  { id: 'default', name: 'Default (recommended)', provider: 'anthropic', isDefault: true },
274
309
  { id: 'sonnet', name: 'Sonnet', provider: 'anthropic' },
275
310
  { id: 'opus', name: 'Opus', provider: 'anthropic' },
276
311
  { id: 'haiku', name: 'Haiku', provider: 'anthropic' },
277
- ]).map(withClaudeReasoningEfforts);
312
+ ], env).map(withClaudeReasoningEfforts);
278
313
  }
279
314
  export function parseCodexModels(raw) {
280
315
  const clean = stripAnsi(raw);
@@ -1,8 +1,10 @@
1
1
  export { getCachedAgentInfos, refreshAgentInfos, resolveAgentInfos, } from './model-registry/service.js';
2
- import { applyClaudeModelEnvOverrides, parseClaudeBinaryModels, parseClaudeModels, parseCodexModels, parseCodexAppServerModels, parseCursorModels, parseGeminiModels, parseOpenClawModels, stripAnsi } from './model-registry/parsers.js';
2
+ import { applyClaudeModelEnvOverrides, discoverClaudeAliasModelsFromEnv, fallbackClaudeAliasModels, parseClaudeBinaryModels, parseClaudeModels, parseCodexModels, parseCodexAppServerModels, parseCursorModels, parseGeminiModels, parseOpenClawModels, stripAnsi } from './model-registry/parsers.js';
3
3
  /** Used by Vitest / `model-switching-e2e.ts` — not a stable public API. */
4
4
  export declare const modelSwitchingTestExports: {
5
5
  readonly applyClaudeModelEnvOverrides: typeof applyClaudeModelEnvOverrides;
6
+ readonly discoverClaudeAliasModelsFromEnv: typeof discoverClaudeAliasModelsFromEnv;
7
+ readonly fallbackClaudeAliasModels: typeof fallbackClaudeAliasModels;
6
8
  readonly parseClaudeBinaryModels: typeof parseClaudeBinaryModels;
7
9
  readonly parseClaudeModels: typeof parseClaudeModels;
8
10
  readonly parseCodexModels: typeof parseCodexModels;
@@ -1,10 +1,12 @@
1
1
  // @arch docs/architecture/cli/model-discovery.md
2
2
  // @test src/__tests__/model-switching.test.ts
3
3
  export { getCachedAgentInfos, refreshAgentInfos, resolveAgentInfos, } from './model-registry/service.js';
4
- import { applyClaudeModelEnvOverrides, parseClaudeBinaryModels, parseClaudeModels, parseCodexModels, parseCodexAppServerModels, parseCursorModels, parseGeminiModels, parseOpenClawModels, stripAnsi, } from './model-registry/parsers.js';
4
+ import { applyClaudeModelEnvOverrides, discoverClaudeAliasModelsFromEnv, fallbackClaudeAliasModels, parseClaudeBinaryModels, parseClaudeModels, parseCodexModels, parseCodexAppServerModels, parseCursorModels, parseGeminiModels, parseOpenClawModels, stripAnsi, } from './model-registry/parsers.js';
5
5
  /** Used by Vitest / `model-switching-e2e.ts` — not a stable public API. */
6
6
  export const modelSwitchingTestExports = {
7
7
  applyClaudeModelEnvOverrides,
8
+ discoverClaudeAliasModelsFromEnv,
9
+ fallbackClaudeAliasModels,
8
10
  parseClaudeBinaryModels,
9
11
  parseClaudeModels,
10
12
  parseCodexModels,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shennian",
3
- "version": "0.2.54",
3
+ "version": "0.2.55",
4
4
  "description": "Shennian — AI Agent Control Plane CLI",
5
5
  "type": "module",
6
6
  "bin": {