clementine-agent 1.18.40 → 1.18.41

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.
@@ -12,7 +12,28 @@ const MAX_STEPS = 10;
12
12
  const MAX_CONCURRENT_STEPS = 3;
13
13
  const RESULT_TRUNCATE_CHARS = 4000;
14
14
  const LONG_PLAN_WARNING_MS = 30 * 60 * 1000; // 30 minutes
15
+ // Step models the planner is allowed to assign to per-step execution.
16
+ // Opus is intentionally NOT in this list — it's reserved for the planner
17
+ // itself + final synthesis. Steps that need reasoning use Sonnet; routine
18
+ // extraction/lookup steps use Haiku. This keeps the high-cost Opus calls
19
+ // bounded (one planner call + one synthesis call per task) while
20
+ // execution stays cheap.
15
21
  const ALLOWED_MODELS = ['haiku', 'sonnet'];
22
+ // The planner's job is the highest-leverage decision in the orchestrator:
23
+ // a smart decomposition saves N sub-agent calls, a bad decomposition wastes
24
+ // them. So we default to Opus here even though it's the most expensive
25
+ // per-call model — one Opus call (~$0.30-0.50, no tools, ~500 input
26
+ // tokens, 1 turn) routinely saves $1-3 in retried sub-agent work.
27
+ //
28
+ // Override via CLEMENTINE_PLANNER_MODEL (haiku|sonnet|opus). Synthesis
29
+ // (combining all step results into the user-facing response) uses the
30
+ // same model — both are reasoning-heavy single-turn calls.
31
+ const PLANNER_MODEL = (() => {
32
+ const env = process.env.CLEMENTINE_PLANNER_MODEL?.toLowerCase();
33
+ if (env === 'haiku' || env === 'sonnet' || env === 'opus')
34
+ return env;
35
+ return 'opus';
36
+ })();
16
37
  const PLANNER_PROMPT = `You are a task planner for an AI assistant. Decompose the following request into executable steps.
17
38
 
18
39
  **Planning Principles:**
@@ -475,6 +496,10 @@ export class PlanOrchestrator {
475
496
  finalResult = await this.assistant.runPlanStep(synthesisStepId, synthesisPrompt, {
476
497
  tier: 2,
477
498
  maxTurns: 5,
499
+ // Synthesis is reasoning-heavy: combine N step outputs into one
500
+ // coherent user-facing response. Same model tier as the planner —
501
+ // smart in, cheap-execution-out.
502
+ model: PLANNER_MODEL,
478
503
  disableTools: true,
479
504
  abortSignal: this.abortSignal,
480
505
  });
@@ -674,7 +699,7 @@ export class PlanOrchestrator {
674
699
  `If a step matches an agent's specialty, add "delegateTo": "agent-slug" to that step. ` +
675
700
  `The delegated agent will run the step with their own personality, tools, and expertise.\n`;
676
701
  }
677
- const plannerResult = await this.assistant.runPlanStep('planner', PLANNER_PROMPT + agentContext + task + PLANNER_PROMPT_SUFFIX, { tier: 2, maxTurns: 1, model: 'sonnet', disableTools: true, abortSignal: this.abortSignal });
702
+ const plannerResult = await this.assistant.runPlanStep('planner', PLANNER_PROMPT + agentContext + task + PLANNER_PROMPT_SUFFIX, { tier: 2, maxTurns: 1, model: PLANNER_MODEL, disableTools: true, abortSignal: this.abortSignal });
678
703
  // Parse JSON from the planner response
679
704
  const parsed = this.parseJsonFromResponse(plannerResult);
680
705
  if (!parsed?.steps || !Array.isArray(parsed.steps) || parsed.steps.length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clementine-agent",
3
- "version": "1.18.40",
3
+ "version": "1.18.41",
4
4
  "description": "Clementine — Personal AI Assistant (TypeScript)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",