@onmars/lunar-agent-claude 0.10.3 → 0.11.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onmars/lunar-agent-claude",
3
- "version": "0.10.3",
3
+ "version": "0.11.1",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -12,7 +12,7 @@
12
12
  "LICENSE"
13
13
  ],
14
14
  "dependencies": {
15
- "@onmars/lunar-core": "^0.10.3"
15
+ "@onmars/lunar-core": "^0.11.1"
16
16
  },
17
17
  "description": "Claude CLI agent adapter for Lunar",
18
18
  "author": "onMars Tech",
@@ -55,6 +55,7 @@ function callBuildArgs(
55
55
  systemPrompt?: string
56
56
  model?: string
57
57
  context1m?: boolean
58
+ thinking?: string
58
59
  },
59
60
  ): string[] {
60
61
  return (agent as any).buildArgs(input)
@@ -284,6 +285,67 @@ describe('buildArgs', () => {
284
285
  expect(args[args.indexOf('--model') + 1]).toBe('claude-sonnet-4-6[1m]')
285
286
  })
286
287
 
288
+ // --- Thinking / --effort flag ---
289
+
290
+ it('omits --effort when no thinking level is set', () => {
291
+ const agent = createAgent()
292
+ const args = callBuildArgs(agent, { prompt: 'hello' })
293
+
294
+ expect(args).not.toContain('--effort')
295
+ })
296
+
297
+ it('omits --effort when thinking is "off"', () => {
298
+ const agent = createAgent({ thinking: 'off' })
299
+ const args = callBuildArgs(agent, { prompt: 'hello' })
300
+
301
+ expect(args).not.toContain('--effort')
302
+ })
303
+
304
+ it('omits --effort for unknown thinking values', () => {
305
+ const agent = createAgent()
306
+ const args = callBuildArgs(agent, { prompt: 'hello', thinking: 'extreme' })
307
+
308
+ expect(args).not.toContain('--effort')
309
+ })
310
+
311
+ it('passes --effort from agent-level thinking option', () => {
312
+ const agent = createAgent({ thinking: 'high' })
313
+ const args = callBuildArgs(agent, { prompt: 'hello' })
314
+
315
+ expect(args).toContain('--effort')
316
+ expect(args[args.indexOf('--effort') + 1]).toBe('high')
317
+ })
318
+
319
+ it('passes --effort from per-query thinking input', () => {
320
+ const agent = createAgent()
321
+ const args = callBuildArgs(agent, { prompt: 'hello', thinking: 'medium' })
322
+
323
+ expect(args).toContain('--effort')
324
+ expect(args[args.indexOf('--effort') + 1]).toBe('medium')
325
+ })
326
+
327
+ it('per-query thinking overrides agent-level', () => {
328
+ const agent = createAgent({ thinking: 'low' })
329
+ const args = callBuildArgs(agent, { prompt: 'hello', thinking: 'high' })
330
+
331
+ expect(args[args.indexOf('--effort') + 1]).toBe('high')
332
+ })
333
+
334
+ it('per-query "off" overrides agent-level thinking by omitting flag', () => {
335
+ const agent = createAgent({ thinking: 'high' })
336
+ const args = callBuildArgs(agent, { prompt: 'hello', thinking: 'off' })
337
+
338
+ expect(args).not.toContain('--effort')
339
+ })
340
+
341
+ it('accepts xhigh and max effort levels', () => {
342
+ const xhighArgs = callBuildArgs(createAgent({ thinking: 'xhigh' }), { prompt: 'hi' })
343
+ expect(xhighArgs[xhighArgs.indexOf('--effort') + 1]).toBe('xhigh')
344
+
345
+ const maxArgs = callBuildArgs(createAgent({ thinking: 'max' }), { prompt: 'hi' })
346
+ expect(maxArgs[maxArgs.indexOf('--effort') + 1]).toBe('max')
347
+ })
348
+
287
349
  // --- Full argument order verification ---
288
350
 
289
351
  it('produces expected argument sequence for a full configuration', () => {
@@ -292,13 +354,15 @@ describe('buildArgs', () => {
292
354
  maxTurns: 5,
293
355
  systemPrompt: 'Be concise',
294
356
  context1m: true,
357
+ thinking: 'high',
295
358
  })
296
359
  const args = callBuildArgs(agent, {
297
360
  prompt: 'explain recursion',
298
361
  sessionId: 'sess_123',
299
362
  })
300
363
 
301
- // Verify ordering: binary, -p, prompt, output-format, verbose, resume, system-prompt, model, max-turns, permission-mode
364
+ // Verify ordering: binary, -p, prompt, output-format, verbose, resume,
365
+ // system-prompt, model, max-turns, effort, permission-mode
302
366
  expect(args[0]).toBe('claude')
303
367
  expect(args[1]).toBe('-p')
304
368
  expect(args[2]).toBe('explain recursion')
@@ -313,9 +377,11 @@ describe('buildArgs', () => {
313
377
  expect(args[11]).toBe('claude-opus-4-7[1m]')
314
378
  expect(args[12]).toBe('--max-turns')
315
379
  expect(args[13]).toBe('5')
316
- expect(args[14]).toBe('--permission-mode')
317
- expect(args[15]).toBe('bypassPermissions')
318
- expect(args).toHaveLength(16)
380
+ expect(args[14]).toBe('--effort')
381
+ expect(args[15]).toBe('high')
382
+ expect(args[16]).toBe('--permission-mode')
383
+ expect(args[17]).toBe('bypassPermissions')
384
+ expect(args).toHaveLength(18)
319
385
  })
320
386
  })
321
387
 
package/src/adapter.ts CHANGED
@@ -37,8 +37,19 @@ export interface ClaudeAgentOptions {
37
37
  * Pricing: same up to 200K tokens, 2x input / 1.5x output above 200K.
38
38
  */
39
39
  context1m?: boolean
40
+ /**
41
+ * Default thinking/effort level for this agent.
42
+ * Maps to Claude Code CLI's `--effort <level>` flag.
43
+ * Accepted: 'off' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'.
44
+ * 'off' (or undefined) omits the flag, leaving CLI default behavior.
45
+ * Per-query `input.thinking` overrides this.
46
+ */
47
+ thinking?: string
40
48
  }
41
49
 
50
+ /** Thinking levels accepted by Claude Code CLI's --effort flag. */
51
+ const VALID_EFFORT_LEVELS = new Set(['low', 'medium', 'high', 'xhigh', 'max'])
52
+
42
53
  /**
43
54
  * Model alias → full ID mapping for Claude Code CLI.
44
55
  *
@@ -299,6 +310,14 @@ export class ClaudeAgent implements Agent {
299
310
  args.push('--max-turns', String(this.options.maxTurns))
300
311
  }
301
312
 
313
+ // Thinking / effort — per-query (router → moon channel) takes priority
314
+ // over agent-level default. 'off' or unknown values omit the flag,
315
+ // leaving the CLI's default behavior intact.
316
+ const effectiveThinking = input.thinking ?? this.options.thinking
317
+ if (effectiveThinking && VALID_EFFORT_LEVELS.has(effectiveThinking)) {
318
+ args.push('--effort', effectiveThinking)
319
+ }
320
+
302
321
  // Permission mode
303
322
  args.push('--permission-mode', 'bypassPermissions')
304
323
 
@@ -482,7 +501,11 @@ export class ClaudeAgent implements Agent {
482
501
  // model name is unchanged. We tag internally for correct pricing/window size.
483
502
  // Only tag real Claude models — skip synthetic/error responses.
484
503
  const isContext1m = input.context1m ?? this.options.context1m
485
- let reportedModel = model
504
+ // Fallback chain: CLI-reported model first (source of truth when present),
505
+ // then the override Lunar passed via --model (input.model), then the adapter
506
+ // default. Fixes intermittent miss-logging when the CLI stream omits the
507
+ // model field on some turns and `model` stays undefined.
508
+ let reportedModel = model ?? input.model ?? this.options.model
486
509
  if (
487
510
  isContext1m &&
488
511
  reportedModel &&