clementine-agent 1.18.152 → 1.18.154
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/dist/agent/run-agent-cron.d.ts +12 -0
- package/dist/agent/run-agent-cron.js +54 -17
- package/dist/cli/dashboard.js +9 -3
- package/dist/gateway/cron-scheduler.js +5 -3
- package/dist/gateway/router.d.ts +3 -0
- package/dist/gateway/router.js +4 -0
- package/dist/types.d.ts +9 -0
- package/package.json +1 -1
|
@@ -175,6 +175,18 @@ export interface RunAgentCronOptions {
|
|
|
175
175
|
* prior progress. The fix for fire-time memory drift. Undefined =
|
|
176
176
|
* legacy behavior (inject everything). */
|
|
177
177
|
predictable?: boolean;
|
|
178
|
+
/** Lean mode — strictest possible context envelope, used by meta-jobs
|
|
179
|
+
* (insight-check, outcome-grader, route-classifier, failure-diagnostics,
|
|
180
|
+
* __heartbeat__) that ALSO have to stay under Haiku's prompt cap.
|
|
181
|
+
* Implies predictable + drops progress/goal/criteria/skill-context blocks
|
|
182
|
+
* + prunes MCP catalog to just the explicit allowed servers (no Composio
|
|
183
|
+
* auto-discovery, no claude.ai connector inventory). When unset, behaves
|
|
184
|
+
* like predictable. The 1.18.148 fix patched outcome-grader / route-
|
|
185
|
+
* classifier / failure-diagnostics directly; this 1.18.154 flag covers
|
|
186
|
+
* insight-check (which still failed 65/70 because predictable alone
|
|
187
|
+
* wasn't strict enough) and is the canonical hook for any future
|
|
188
|
+
* meta-job that needs a tiny prompt. */
|
|
189
|
+
lean?: boolean;
|
|
178
190
|
/** Extra read+execute scope for the agent's Read/Bash/Glob tools. Maps
|
|
179
191
|
* directly to the CronJobDefinition.addDirs YAML field. Combined with
|
|
180
192
|
* every pinned-skill folder so `Bash python3 scripts/render.py` works
|
|
@@ -548,13 +548,32 @@ export async function buildCronExecutionPlan(opts) {
|
|
|
548
548
|
// fire time. Legacy tricks (predictable === undefined) preserve existing
|
|
549
549
|
// behavior so we don't surprise anyone.
|
|
550
550
|
const predictable = opts.predictable === true;
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
551
|
+
// 1.18.154 — lean mode goes one tier stricter for meta-jobs (insight-check,
|
|
552
|
+
// outcome-grader, route-classifier, failure-diagnostics, __heartbeat__).
|
|
553
|
+
// Drops progress / goal / criteria / skill-context blocks too, leaving
|
|
554
|
+
// the agent with [jobName] + [jobPrompt] + [howToRespond] only. Implies
|
|
555
|
+
// predictable. Anything that ALSO needs a tiny MCP catalog uses the
|
|
556
|
+
// pruning logic below.
|
|
557
|
+
//
|
|
558
|
+
// Auto-apply for known meta-jobs even if the CRON.md/registry entry
|
|
559
|
+
// doesn't carry `lean: true` — these names are hard-coded singletons in
|
|
560
|
+
// heartbeat-scheduler.ts and we know they need the strict envelope. Lets
|
|
561
|
+
// existing user installs benefit from the fix without requiring them to
|
|
562
|
+
// hand-edit CRON.md.
|
|
563
|
+
const KNOWN_META_JOBS = new Set([
|
|
564
|
+
'insight-check', 'outcome-grader', 'route-classifier',
|
|
565
|
+
'failure-diagnostics', '__heartbeat__',
|
|
566
|
+
]);
|
|
567
|
+
const lean = opts.lean === true || KNOWN_META_JOBS.has(opts.jobName);
|
|
568
|
+
const memoryContext = predictable || lean ? '' : buildAutonomousMemoryContext(opts.profile);
|
|
569
|
+
const progressContext = lean ? '' : buildProgressContext(opts.jobName); // opt-in via cron_progress writes
|
|
570
|
+
const goalContext = lean ? '' : buildGoalContext(opts.jobName); // explicit links; not auto-inferred
|
|
571
|
+
const delegationContext = predictable || lean ? '' : buildDelegationContext(agentSlug);
|
|
572
|
+
const teamContext = predictable || lean ? '' : buildTeamContext(agentSlug);
|
|
573
|
+
const criteriaContext = lean ? '' : buildCriteriaContext(opts.successCriteria);
|
|
574
|
+
const skillResult = lean
|
|
575
|
+
? { text: '', applied: [], missing: [], pinnedBodies: [], pinnedToolsRequested: [] }
|
|
576
|
+
: await buildSkillContext(opts.jobName, opts.jobPrompt, agentSlug, opts.pinnedSkills, opts.memoryStore, { skipAutoMatch: predictable, projectWorkDir: opts.workDir });
|
|
558
577
|
const skillContext = skillResult.text;
|
|
559
578
|
const howToRespond = `## How to respond\n` +
|
|
560
579
|
`You're sending this directly to ${ownerName} as a DM. ` +
|
|
@@ -577,15 +596,24 @@ export async function buildCronExecutionPlan(opts) {
|
|
|
577
596
|
criteriaContext +
|
|
578
597
|
`${opts.jobPrompt}\n\n` +
|
|
579
598
|
howToRespond;
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
599
|
+
// 1.18.154 — lean mode skips Composio + claude.ai MCP discovery entirely.
|
|
600
|
+
// Meta-jobs (insight-check etc.) only need the always-on Clementine MCP
|
|
601
|
+
// server (which is added in run-agent.ts and has cron_list, discord_*,
|
|
602
|
+
// etc.). Loading 200+ extra MCP tool schemas just to call cron_list is
|
|
603
|
+
// what was tipping the prompt over Haiku's cap. If a lean job DOES need
|
|
604
|
+
// extras, declare them explicitly via `allowedMcpServers` and the helper
|
|
605
|
+
// narrows discovery to those names.
|
|
606
|
+
const mcp = lean && (!opts.allowedMcpServers || opts.allowedMcpServers.length === 0)
|
|
607
|
+
? { servers: {}, composioConnected: [], externalConnected: [] }
|
|
608
|
+
: await buildExtraMcpForRunAgent({
|
|
609
|
+
scopeText: [
|
|
610
|
+
opts.jobName,
|
|
611
|
+
opts.jobPrompt,
|
|
612
|
+
opts.profile?.description,
|
|
613
|
+
opts.profile?.systemPromptBody,
|
|
614
|
+
].filter(Boolean).join('\n\n'),
|
|
615
|
+
profile: opts.profile,
|
|
616
|
+
});
|
|
589
617
|
// 1.18.125 — pinned-skill scope widening (SDK alignment).
|
|
590
618
|
// A pinned skill that declares `clementine.tools.allow` or references
|
|
591
619
|
// `mcp__server__tool` in its body needs those tools/servers to actually
|
|
@@ -701,19 +729,28 @@ export async function buildCronExecutionPlan(opts) {
|
|
|
701
729
|
export async function runAgentCron(opts) {
|
|
702
730
|
const plan = await buildCronExecutionPlan(opts);
|
|
703
731
|
const { builtPrompt, agentSlug, effort, maxBudgetUsd: maxBudget, effectiveAllowedTools, mcpServerMap, composioConnected, externalConnected, mcpServersApplied, additionalDirectories, } = plan;
|
|
704
|
-
|
|
732
|
+
// 1.18.154 — surface lean + promptChars for meta-job diagnostics. The
|
|
733
|
+
// self-improve / insight-check failure mode is "small prompt, fat context"
|
|
734
|
+
// which only shows in promptChars; plain log level was previously info but
|
|
735
|
+
// anything > 50KB is on the cusp of Haiku's cap and worth a warn.
|
|
736
|
+
const promptBytes = Buffer.byteLength(builtPrompt, 'utf8');
|
|
737
|
+
const promptOversized = promptBytes > 50_000;
|
|
738
|
+
logger[promptOversized ? 'warn' : 'info']({
|
|
705
739
|
job: opts.jobName,
|
|
706
740
|
tier: plan.tier,
|
|
707
741
|
profile: agentSlug,
|
|
742
|
+
lean: opts.lean === true || ['insight-check', 'outcome-grader', 'route-classifier', 'failure-diagnostics', '__heartbeat__'].includes(opts.jobName),
|
|
708
743
|
composioConnected,
|
|
709
744
|
externalConnected,
|
|
710
745
|
promptChars: builtPrompt.length,
|
|
746
|
+
promptBytes,
|
|
711
747
|
pinnedSkills: opts.pinnedSkills?.length ?? 0,
|
|
712
748
|
skillsApplied: plan.skillsApplied.length,
|
|
713
749
|
skillsMissing: plan.skillsMissing.length,
|
|
714
750
|
trickAllowedTools: effectiveAllowedTools?.length,
|
|
715
751
|
trickAllowedMcp: opts.allowedMcpServers?.length,
|
|
716
752
|
widenedFromSkills: plan.widenedFromSkills,
|
|
753
|
+
...(promptOversized ? { warning: 'prompt > 50KB; risk of "Prompt is too long" failure' } : {}),
|
|
717
754
|
}, 'runAgentCron: dispatching to runAgent');
|
|
718
755
|
const startedAt = Date.now();
|
|
719
756
|
const result = await runAgent(builtPrompt, {
|
package/dist/cli/dashboard.js
CHANGED
|
@@ -39485,9 +39485,15 @@ async function runWorkflow(name) {
|
|
|
39485
39485
|
// the list so the migrated workflow disappears (its .md is renamed to
|
|
39486
39486
|
// .md.migrated server-side and parseAllWorkflows stops picking it up).
|
|
39487
39487
|
async function migrateWorkflowToSkill(name) {
|
|
39488
|
-
|
|
39489
|
-
|
|
39490
|
-
|
|
39488
|
+
// 1.18.153 — escape \\n through the outer template literal. Without the
|
|
39489
|
+
// double-backslash the served HTML gets literal newlines INSIDE a single-
|
|
39490
|
+
// quoted JS string, which the browser parser rejects as
|
|
39491
|
+
// "Uncaught SyntaxError: Invalid or unexpected token". That kills the
|
|
39492
|
+
// entire inline script block, so no API calls fire, no data renders,
|
|
39493
|
+
// dashboard appears completely broken even though the server is healthy.
|
|
39494
|
+
if (!confirm('Migrate "' + name + '" into a skill folder?\\n\\n' +
|
|
39495
|
+
'• A new skill will be created at vault/00-System/skills/<slug>/SKILL.md\\n' +
|
|
39496
|
+
'• The original workflow .md will be renamed to .md.migrated (kept for rollback)\\n' +
|
|
39491
39497
|
'• The workflow stops firing; the skill is ready to schedule from the Skills tab')) return;
|
|
39492
39498
|
try {
|
|
39493
39499
|
var r = await apiFetch('/api/workflows/' + encodeURIComponent(name) + '/migrate-to-skill', {
|
|
@@ -169,6 +169,8 @@ function parseJobYaml(job) {
|
|
|
169
169
|
? categoryRaw.trim().slice(0, 64)
|
|
170
170
|
: undefined;
|
|
171
171
|
const predictable = typeof job.predictable === 'boolean' ? job.predictable : undefined;
|
|
172
|
+
// 1.18.154 — strictest envelope for meta-jobs (insight-check, heartbeat).
|
|
173
|
+
const lean = typeof job.lean === 'boolean' ? job.lean : undefined;
|
|
172
174
|
const description = typeof job.description === 'string' && job.description.trim()
|
|
173
175
|
? job.description.trim().slice(0, 500)
|
|
174
176
|
: undefined;
|
|
@@ -177,7 +179,7 @@ function parseJobYaml(job) {
|
|
|
177
179
|
maxHours, maxRetries, after, successCriteria, successCriteriaText, successSchema, addDirs,
|
|
178
180
|
alwaysDeliver, context, preCheck, attachments, requiresConfirmation, confirmationTimeoutMin,
|
|
179
181
|
agentSlug,
|
|
180
|
-
skills, allowedTools, allowedMcpServers, tags, category, predictable,
|
|
182
|
+
skills, allowedTools, allowedMcpServers, tags, category, predictable, lean,
|
|
181
183
|
};
|
|
182
184
|
}
|
|
183
185
|
/**
|
|
@@ -1224,12 +1226,12 @@ export class CronScheduler {
|
|
|
1224
1226
|
const startedAt = new Date();
|
|
1225
1227
|
try {
|
|
1226
1228
|
// Standard cron jobs get a timeout via SDK AbortController (advisor may override)
|
|
1227
|
-
let response = await this.gateway.handleCronJob(job.name, jobPrompt, job.tier, job.maxTurns, job.model, job.workDir, job.mode, job.maxHours, effectiveTimeoutMs, job.successCriteria, job.agentSlug, job.skills, job.allowedTools, job.allowedMcpServers, job.predictable, job.addDirs);
|
|
1229
|
+
let response = await this.gateway.handleCronJob(job.name, jobPrompt, job.tier, job.maxTurns, job.model, job.workDir, job.mode, job.maxHours, effectiveTimeoutMs, job.successCriteria, job.agentSlug, job.skills, job.allowedTools, job.allowedMcpServers, job.predictable, job.lean, job.addDirs);
|
|
1228
1230
|
// alwaysDeliver: retry once if the response is empty/noise
|
|
1229
1231
|
if (job.alwaysDeliver && (!response || CronScheduler.isCronNoise(response))) {
|
|
1230
1232
|
logger.info({ job: job.name }, 'alwaysDeliver: empty/noise response — retrying once');
|
|
1231
1233
|
try {
|
|
1232
|
-
const retryResponse = await this.gateway.handleCronJob(job.name, jobPrompt + '\n\nYou MUST produce a brief status update. Do NOT return __NOTHING__.', job.tier, job.maxTurns, job.model, job.workDir, job.mode, job.maxHours, effectiveTimeoutMs, job.successCriteria, job.agentSlug, job.skills, job.allowedTools, job.allowedMcpServers, job.predictable, job.addDirs);
|
|
1234
|
+
const retryResponse = await this.gateway.handleCronJob(job.name, jobPrompt + '\n\nYou MUST produce a brief status update. Do NOT return __NOTHING__.', job.tier, job.maxTurns, job.model, job.workDir, job.mode, job.maxHours, effectiveTimeoutMs, job.successCriteria, job.agentSlug, job.skills, job.allowedTools, job.allowedMcpServers, job.predictable, job.lean, job.addDirs);
|
|
1233
1235
|
if (retryResponse && !CronScheduler.isCronNoise(retryResponse)) {
|
|
1234
1236
|
response = retryResponse;
|
|
1235
1237
|
}
|
package/dist/gateway/router.d.ts
CHANGED
|
@@ -183,6 +183,9 @@ export declare class Gateway {
|
|
|
183
183
|
_mode?: 'standard' | 'unleashed', maxHours?: number, timeoutMs?: number, successCriteria?: string[], agentSlug?: string, pinnedSkills?: string[], allowedTools?: string[], allowedMcpServers?: string[],
|
|
184
184
|
/** Predictable (contract) mode — runner skips memory/team/auto-skills. */
|
|
185
185
|
predictable?: boolean,
|
|
186
|
+
/** Lean (meta-job) mode — strictest envelope, drops every auto-injected
|
|
187
|
+
* context block. For insight-check, the four meta-routers, heartbeat. */
|
|
188
|
+
lean?: boolean,
|
|
186
189
|
/** Extra read+exec scope for the SDK's Read/Bash/Glob tools. From the
|
|
187
190
|
* CronJobDefinition.addDirs YAML field. Combined inside runAgentCron
|
|
188
191
|
* with each pinned-skill folder. (1.18.121) */
|
package/dist/gateway/router.js
CHANGED
|
@@ -1977,6 +1977,9 @@ export class Gateway {
|
|
|
1977
1977
|
pinnedSkills, allowedTools, allowedMcpServers,
|
|
1978
1978
|
/** Predictable (contract) mode — runner skips memory/team/auto-skills. */
|
|
1979
1979
|
predictable,
|
|
1980
|
+
/** Lean (meta-job) mode — strictest envelope, drops every auto-injected
|
|
1981
|
+
* context block. For insight-check, the four meta-routers, heartbeat. */
|
|
1982
|
+
lean,
|
|
1980
1983
|
/** Extra read+exec scope for the SDK's Read/Bash/Glob tools. From the
|
|
1981
1984
|
* CronJobDefinition.addDirs YAML field. Combined inside runAgentCron
|
|
1982
1985
|
* with each pinned-skill folder. (1.18.121) */
|
|
@@ -2026,6 +2029,7 @@ export class Gateway {
|
|
|
2026
2029
|
allowedTools,
|
|
2027
2030
|
allowedMcpServers,
|
|
2028
2031
|
predictable,
|
|
2032
|
+
lean,
|
|
2029
2033
|
addDirs,
|
|
2030
2034
|
});
|
|
2031
2035
|
scanner.refreshIntegrity();
|
package/dist/types.d.ts
CHANGED
|
@@ -550,6 +550,15 @@ export interface CronJobDefinition {
|
|
|
550
550
|
* Existing tricks (no field set) keep current behavior — backward compat.
|
|
551
551
|
*/
|
|
552
552
|
predictable?: boolean;
|
|
553
|
+
/** 1.18.154 — strictest possible context envelope, for meta-jobs that
|
|
554
|
+
* need to stay under Haiku's prompt cap (insight-check, the four
|
|
555
|
+
* meta-routers, __heartbeat__). Implies predictable + drops progress/
|
|
556
|
+
* goal/criteria/skill blocks entirely. Use only for jobs whose prompt
|
|
557
|
+
* is self-contained and whose tools are explicitly allow-listed. The
|
|
558
|
+
* fix for the 1.18.148 regression where insight-check kept failing
|
|
559
|
+
* with "Prompt is too long" because predictable alone wasn't strict
|
|
560
|
+
* enough. */
|
|
561
|
+
lean?: boolean;
|
|
553
562
|
/** 1.18.129 — where this cron job came from. 'cron-md' is the legacy
|
|
554
563
|
* fat-cron format in vault/00-System/CRON.md (or per-agent CRON.md).
|
|
555
564
|
* 'scheduled-skill' is the Anthropic-pure registry — a thin entry in
|