clementine-agent 1.18.154 → 1.18.155
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/cli/dashboard.js
CHANGED
|
@@ -25418,8 +25418,18 @@ function renderScheduledTaskCard(task) {
|
|
|
25418
25418
|
} else {
|
|
25419
25419
|
badges += '<span class="badge badge-gray" title="Legacy CRON.md job. Carries its own prompt/tools/MCP. Convert to a scheduled skill when you can.">LEGACY CRON</span>';
|
|
25420
25420
|
}
|
|
25421
|
-
|
|
25422
|
-
|
|
25421
|
+
// 1.18.155 — replace the "🔒 predictable" lock icon (which appeared on
|
|
25422
|
+
// ~every row and added pure noise) with a single "Strict" pill that ONLY
|
|
25423
|
+
// appears when behavior diverges from the default. predictable=true is
|
|
25424
|
+
// the default for new tasks since 1.18.68, so suppress that badge — only
|
|
25425
|
+
// show one when the user has explicitly opted into dynamic mode (the
|
|
25426
|
+
// less safe path, worth flagging) or when lean mode is in effect for a
|
|
25427
|
+
// meta-job (worth showing because it explains why the prompt is small).
|
|
25428
|
+
if (task.lean === true) {
|
|
25429
|
+
badges += '<span class="badge badge-purple" title="Lean envelope — drops every auto-injected context block (memory, progress, goal, criteria, skills) and prunes the MCP catalog. Used for meta-jobs that must stay under Haiku\'s prompt cap.">Lean</span>';
|
|
25430
|
+
} else if (task.predictable === false) {
|
|
25431
|
+
badges += '<span class="badge badge-yellow" title="Dynamic mode — fire-time injects MEMORY.md, recent team activity, and auto-matched skills. Can drift from chat-time intent.">Reads memory</span>';
|
|
25432
|
+
}
|
|
25423
25433
|
if (task.mode === 'unleashed') badges += '<span class="badge badge-purple">long-running</span>';
|
|
25424
25434
|
if (task.after) badges += '<span class="badge badge-yellow" title="Triggered after ' + esc(task.after) + '">after ' + esc(task.after) + '</span>';
|
|
25425
25435
|
if (task.maxRetries != null) badges += '<span class="badge badge-gray">' + esc(task.maxRetries) + ' retries</span>';
|
|
@@ -25670,7 +25680,13 @@ function renderRecentHistoryList(runs) {
|
|
|
25670
25680
|
var msg = String(entry.error).slice(0, 120);
|
|
25671
25681
|
errorPreview = '<div style="font-size:11px;color:var(--red);margin-top:2px;word-break:break-word">' + esc(msg) + '</div>';
|
|
25672
25682
|
} else if (entry.outputPreview) {
|
|
25673
|
-
|
|
25683
|
+
// 1.18.155 — strip the __NOTHING__ sentinel agents emit when they
|
|
25684
|
+
// intentionally stay silent (it's the "no signal" contract from
|
|
25685
|
+
// run-agent-cron.ts howToRespond block, not output the user should see).
|
|
25686
|
+
var rawPreview = String(entry.outputPreview);
|
|
25687
|
+
var preview = (rawPreview === '__NOTHING__' || rawPreview.trim() === '__NOTHING__')
|
|
25688
|
+
? '(no output — agent reported nothing worth saying)'
|
|
25689
|
+
: rawPreview.slice(0, 140);
|
|
25674
25690
|
errorPreview = '<div style="font-size:11px;color:var(--text-muted);margin-top:2px;word-break:break-word">' + esc(preview) + '</div>';
|
|
25675
25691
|
}
|
|
25676
25692
|
// PRD Phase 1.1: goal cell. Empty cell when no goal configured (status='skipped'
|
|
@@ -25775,16 +25791,31 @@ async function refreshHealthStrip() {
|
|
|
25775
25791
|
var ops = await apiFetch('/api/build/operations?hours=1&limit=10').then(function(rr) { return rr.json(); });
|
|
25776
25792
|
activeRuns = ((ops && ops.runningNow) || []).length;
|
|
25777
25793
|
} catch (e) { /* fall back to 0 */ }
|
|
25778
|
-
// Top failure category for the day.
|
|
25794
|
+
// Top failure category for the day. 1.18.155 — when no failureCategory
|
|
25795
|
+
// is set on the failed runs (which is common for raw SDK errors like
|
|
25796
|
+
// "Prompt is too long"), fall back to grouping by jobName so the user
|
|
25797
|
+
// sees WHICH job is failing instead of a useless dash. Categories still
|
|
25798
|
+
// win when present (more semantic than a job name).
|
|
25779
25799
|
var catCounts = {};
|
|
25800
|
+
var jobCounts = {};
|
|
25780
25801
|
for (var i = 0; i < last24.length; i++) {
|
|
25781
25802
|
var c = last24[i].failureCategory;
|
|
25782
25803
|
if (c) catCounts[c] = (catCounts[c] || 0) + 1;
|
|
25804
|
+
if (last24[i].status === 'error' || last24[i].status === 'failed') {
|
|
25805
|
+
var jn = last24[i].jobName || last24[i].name;
|
|
25806
|
+
if (jn) jobCounts[jn] = (jobCounts[jn] || 0) + 1;
|
|
25807
|
+
}
|
|
25783
25808
|
}
|
|
25784
25809
|
var topCat = null, topCount = 0;
|
|
25785
25810
|
Object.keys(catCounts).forEach(function(k) {
|
|
25786
25811
|
if (catCounts[k] > topCount) { topCat = k; topCount = catCounts[k]; }
|
|
25787
25812
|
});
|
|
25813
|
+
var topJob = null, topJobCount = 0;
|
|
25814
|
+
Object.keys(jobCounts).forEach(function(k) {
|
|
25815
|
+
if (jobCounts[k] > topJobCount) { topJob = k; topJobCount = jobCounts[k]; }
|
|
25816
|
+
});
|
|
25817
|
+
// Prefer the categorized one (more semantic), fall back to job name.
|
|
25818
|
+
if (!topCat && topJob) { topCat = topJob; topCount = topJobCount; }
|
|
25788
25819
|
// Render six tiles.
|
|
25789
25820
|
function tile(label, value, sub, color) {
|
|
25790
25821
|
return '<div class="health-tile">'
|
|
@@ -26450,7 +26481,12 @@ function renderRunListBody(allRuns) {
|
|
|
26450
26481
|
if (status === 'error' && entry.error) {
|
|
26451
26482
|
preview = '<div style="font-size:11px;color:var(--red);margin-top:2px;word-break:break-word">' + esc(String(entry.error).slice(0, 140)) + '</div>';
|
|
26452
26483
|
} else if (entry.outputPreview) {
|
|
26453
|
-
|
|
26484
|
+
// 1.18.155 — see renderRecentHistoryList for the same __NOTHING__ strip.
|
|
26485
|
+
var rawOp = String(entry.outputPreview);
|
|
26486
|
+
var opText = (rawOp === '__NOTHING__' || rawOp.trim() === '__NOTHING__')
|
|
26487
|
+
? '(no output — agent reported nothing worth saying)'
|
|
26488
|
+
: rawOp.slice(0, 120);
|
|
26489
|
+
preview = '<div style="font-size:11px;color:var(--text-muted);margin-top:2px;word-break:break-word">' + esc(opText) + '</div>';
|
|
26454
26490
|
}
|
|
26455
26491
|
// 1.18.89: cost label. Showing 4 decimals for sub-penny costs (Haiku
|
|
26456
26492
|
// runs land in fractions of a cent), 2 decimals when ≥ $0.01.
|
|
@@ -27079,7 +27115,11 @@ async function refreshCron() {
|
|
|
27079
27115
|
var bannerHtml = '';
|
|
27080
27116
|
var dismissed = localStorage.getItem('clem-skill-migrate-banner-dismissed') === '1';
|
|
27081
27117
|
if (legacyCount > 0 && !dismissed) {
|
|
27082
|
-
|
|
27118
|
+
// 1.18.155 — data-banner-kind tags this as the legacy-cron soft-
|
|
27119
|
+
// deprecation banner so refreshCronMigrateBanner can suppress its
|
|
27120
|
+
// secondary "clean up preambles" banner when this one is showing
|
|
27121
|
+
// (full migration is a superset; showing both is confusing noise).
|
|
27122
|
+
bannerHtml = '<div data-banner-kind="legacy-cron-soft-deprecation" style="background:rgba(124,58,237,0.08);border:1px solid var(--purple);border-radius:8px;padding:12px 14px;margin-bottom:14px;display:flex;align-items:center;gap:12px;flex-wrap:wrap">'
|
|
27083
27123
|
+ '<span style="font-size:18px">⚡</span>'
|
|
27084
27124
|
+ '<div style="flex:1;min-width:200px">'
|
|
27085
27125
|
+ '<div style="font-size:13px;font-weight:500;color:var(--text-primary)">' + legacyCount + ' legacy cron task' + (legacyCount === 1 ? '' : 's') + ' can become scheduled skills</div>'
|
|
@@ -29049,6 +29089,19 @@ async function refreshCronMigrateBanner() {
|
|
|
29049
29089
|
return;
|
|
29050
29090
|
}
|
|
29051
29091
|
_cronMigratePreview = d;
|
|
29092
|
+
// 1.18.155 — suppress this banner when the upstream "X legacy crons
|
|
29093
|
+
// can become scheduled skills" banner is already showing. The full
|
|
29094
|
+
// migration there is a superset of this cleanup (the destination skill
|
|
29095
|
+
// gets a clean prompt automatically), so showing both at once is just
|
|
29096
|
+
// confusing noise. If the upstream banner is dismissed via localStorage
|
|
29097
|
+
// OR there are no legacy crons to migrate, this orange banner shows up
|
|
29098
|
+
// as the secondary action.
|
|
29099
|
+
var dismissed = localStorage.getItem('clem-skill-migrate-banner-dismissed') === '1';
|
|
29100
|
+
var hasLegacyCronBanner = !dismissed && document.querySelector('[data-banner-kind="legacy-cron-soft-deprecation"]');
|
|
29101
|
+
if (hasLegacyCronBanner) {
|
|
29102
|
+
host.innerHTML = '';
|
|
29103
|
+
return;
|
|
29104
|
+
}
|
|
29052
29105
|
var n = d.eligible.length;
|
|
29053
29106
|
host.innerHTML =
|
|
29054
29107
|
'<div style="margin:0 0 14px;padding:12px 16px;border:1px solid var(--accent);background:rgba(255,141,0,0.06);border-radius:8px;display:flex;align-items:center;gap:14px;flex-wrap:wrap">'
|
|
@@ -101,6 +101,10 @@ export interface ScheduledTaskCard {
|
|
|
101
101
|
* team comms / auto-matched skills. The visibility-on-card flag for
|
|
102
102
|
* "this trick will run with only what you see here." */
|
|
103
103
|
predictable?: boolean;
|
|
104
|
+
/** 1.18.154/155 — Lean envelope (meta-jobs). Surfaced in the row badge
|
|
105
|
+
* so the user understands why insight-check / outcome-grader / etc.
|
|
106
|
+
* show a tiny prompt + restricted MCP catalog. */
|
|
107
|
+
lean?: boolean;
|
|
104
108
|
}
|
|
105
109
|
export interface ScheduledWorkflowCard {
|
|
106
110
|
type: 'scheduled_workflow';
|
|
@@ -216,6 +216,7 @@ export function buildOperationsSnapshot(input) {
|
|
|
216
216
|
tags: asStringArray(job.tags),
|
|
217
217
|
category: typeof job.category === 'string' && job.category.trim() ? job.category.trim() : undefined,
|
|
218
218
|
predictable: typeof job.predictable === 'boolean' ? job.predictable : undefined,
|
|
219
|
+
lean: typeof job.lean === 'boolean' ? job.lean : undefined,
|
|
219
220
|
};
|
|
220
221
|
}).sort((a, b) => a.owner.localeCompare(b.owner) || a.displayName.localeCompare(b.displayName));
|
|
221
222
|
const scheduledWorkflows = input.workflowSummaries
|