clementine-agent 1.18.192 → 1.18.193
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.
|
@@ -76,6 +76,34 @@ export declare function classifyMessageShape(text: string, opts?: {
|
|
|
76
76
|
*/
|
|
77
77
|
export type PlanApprovalSignal = 'approve' | 'revise' | 'cancel' | 'other';
|
|
78
78
|
export declare function detectPlanApproval(message: string): PlanApprovalSignal;
|
|
79
|
+
/**
|
|
80
|
+
* 1.18.193 — plan-mode opt-in detector.
|
|
81
|
+
*
|
|
82
|
+
* Plan-mode used to auto-trigger when `classifyMessageShape` flagged a
|
|
83
|
+
* message as 'multi-step'. That was too aggressive — Nora's April 28-29
|
|
84
|
+
* work (38 Bash calls in one chat session) would have been routed through
|
|
85
|
+
* the planner unnecessarily. Comparison vs friend's 1.18.62 install showed
|
|
86
|
+
* the auto-route was the main behavior divergence.
|
|
87
|
+
*
|
|
88
|
+
* Now plan-mode is opt-in via explicit owner intent:
|
|
89
|
+
* - Message starts with `/plan` (case-insensitive)
|
|
90
|
+
* - Message contains the `[plan-mode]` token anywhere
|
|
91
|
+
*
|
|
92
|
+
* The chat-overflow recovery path (queueBackgroundTaskAfterContextOverflow)
|
|
93
|
+
* still routes to the planner when the SDK session ACTUALLY overflows —
|
|
94
|
+
* that's a separate escape hatch, not an auto-trigger.
|
|
95
|
+
*
|
|
96
|
+
* Returns `{ requested: true, cleaned }` if the owner asked for plan mode,
|
|
97
|
+
* where `cleaned` is the message with the trigger token stripped.
|
|
98
|
+
* Returns `{ requested: false }` otherwise.
|
|
99
|
+
*/
|
|
100
|
+
export type PlanModeRequest = {
|
|
101
|
+
requested: true;
|
|
102
|
+
cleaned: string;
|
|
103
|
+
} | {
|
|
104
|
+
requested: false;
|
|
105
|
+
};
|
|
106
|
+
export declare function detectPlanModeRequest(message: string): PlanModeRequest;
|
|
79
107
|
/**
|
|
80
108
|
* Generate a follow-up suggestion prompt suffix based on completed work.
|
|
81
109
|
*
|
|
@@ -332,6 +332,16 @@ export function detectPlanApproval(message) {
|
|
|
332
332
|
return 'revise';
|
|
333
333
|
return 'other';
|
|
334
334
|
}
|
|
335
|
+
const PLAN_MODE_TRIGGER = /^\s*\/plan\b|\[plan-mode\]/i;
|
|
336
|
+
export function detectPlanModeRequest(message) {
|
|
337
|
+
if (!message || !PLAN_MODE_TRIGGER.test(message))
|
|
338
|
+
return { requested: false };
|
|
339
|
+
const cleaned = message
|
|
340
|
+
.replace(/^\s*\/plan\b\s*/i, '')
|
|
341
|
+
.replace(/\[plan-mode\]/gi, '')
|
|
342
|
+
.trim();
|
|
343
|
+
return { requested: true, cleaned };
|
|
344
|
+
}
|
|
335
345
|
/**
|
|
336
346
|
* Generate a follow-up suggestion prompt suffix based on completed work.
|
|
337
347
|
*
|
package/dist/gateway/router.js
CHANGED
|
@@ -493,7 +493,7 @@ export class Gateway {
|
|
|
493
493
|
*/
|
|
494
494
|
async _maybeHandlePlanMode(opts) {
|
|
495
495
|
const sess = this.sessions.get(opts.sessionKey);
|
|
496
|
-
const { detectPlanApproval } = await import('../agent/intent-classifier.js');
|
|
496
|
+
const { detectPlanApproval, detectPlanModeRequest } = await import('../agent/intent-classifier.js');
|
|
497
497
|
const { planRequest, savePlan, loadPlan } = await import('../agent/bg-planner.js');
|
|
498
498
|
const { dispatchChain } = await import('../agent/bg-orchestrator.js');
|
|
499
499
|
// ── Path A: approval-pending ────────────────────────────────────
|
|
@@ -564,11 +564,31 @@ export class Gateway {
|
|
|
564
564
|
// pending state. The model will see the user message normally.
|
|
565
565
|
return { handled: false };
|
|
566
566
|
}
|
|
567
|
-
// ── Path B:
|
|
568
|
-
|
|
567
|
+
// ── Path B: explicit plan-mode entry (1.18.193) ─────────────────
|
|
568
|
+
//
|
|
569
|
+
// Plan mode is now OPT-IN, not auto-triggered by message shape.
|
|
570
|
+
// Default chat behavior matches 1.18.62: the SDK query runs the
|
|
571
|
+
// work in one continuous Sonnet session, like Nora did on April
|
|
572
|
+
// 28-29 (38 Bash calls in one session — no decomposition needed).
|
|
573
|
+
//
|
|
574
|
+
// The planner-orchestrator remains available for genuinely huge
|
|
575
|
+
// jobs, but the owner has to opt in:
|
|
576
|
+
//
|
|
577
|
+
// - Message starts with `/plan` (case-insensitive)
|
|
578
|
+
// - Message contains `[plan-mode]` token anywhere
|
|
579
|
+
//
|
|
580
|
+
// The chat-overflow escape hatch (queueBackgroundTaskAfterContext-
|
|
581
|
+
// Overflow → planner) still works as a separate path when the SDK
|
|
582
|
+
// session ACTUALLY overflows. That's the legitimate "this job is
|
|
583
|
+
// too big for one session" trigger.
|
|
584
|
+
//
|
|
585
|
+
// We keep shape classification (it still gates turn-context
|
|
586
|
+
// density for token savings on 'simple' messages), but shape no
|
|
587
|
+
// longer routes execution.
|
|
588
|
+
const planRequestSignal = detectPlanModeRequest(opts.userMessage);
|
|
589
|
+
if (planRequestSignal.requested && sess) {
|
|
590
|
+
const cleanedRequest = planRequestSignal.cleaned;
|
|
569
591
|
try {
|
|
570
|
-
// Stream a "thinking..." update so the user knows planning is
|
|
571
|
-
// happening rather than seeing 30s of silence.
|
|
572
592
|
if (opts.onText) {
|
|
573
593
|
try {
|
|
574
594
|
opts.onText('🤔 Planning the steps...');
|
|
@@ -576,7 +596,7 @@ export class Gateway {
|
|
|
576
596
|
catch { /* non-fatal */ }
|
|
577
597
|
}
|
|
578
598
|
const plan = await planRequest({
|
|
579
|
-
userRequest: opts.userMessage,
|
|
599
|
+
userRequest: cleanedRequest || opts.userMessage,
|
|
580
600
|
originatingSessionKey: opts.sessionKey,
|
|
581
601
|
...(opts.activeProject ? { project: opts.activeProject } : {}),
|
|
582
602
|
});
|
|
@@ -592,12 +612,14 @@ export class Gateway {
|
|
|
592
612
|
};
|
|
593
613
|
}
|
|
594
614
|
catch (err) {
|
|
595
|
-
logger.warn({ err, sessionKey: opts.sessionKey }, 'Plan mode: planRequest failed at entry');
|
|
615
|
+
logger.warn({ err, sessionKey: opts.sessionKey }, 'Plan mode: planRequest failed at explicit entry');
|
|
596
616
|
// Fall through to normal chat. Better than blocking the owner.
|
|
597
617
|
return { handled: false };
|
|
598
618
|
}
|
|
599
619
|
}
|
|
600
620
|
// Not a plan-mode case — fall through to normal chat.
|
|
621
|
+
// This is the path 99% of messages take. Like 1.18.62 — the SDK
|
|
622
|
+
// query runs the work in one continuous Sonnet session.
|
|
601
623
|
return { handled: false };
|
|
602
624
|
}
|
|
603
625
|
/** Format a plan for owner approval in chat. */
|