clementine-agent 1.18.88 → 1.18.89

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/cron.js CHANGED
@@ -149,6 +149,7 @@ export async function cmdCronRun(jobName) {
149
149
  // to the Event store.
150
150
  const sideChannel = gateway.consumeLastCronRunMetadata?.();
151
151
  const runIdFromGateway = sideChannel?.runId;
152
+ const totalCostFromGateway = sideChannel?.totalCostUsd;
152
153
  const entry = {
153
154
  jobName: job.name,
154
155
  startedAt: startedAt.toISOString(),
@@ -159,6 +160,8 @@ export async function cmdCronRun(jobName) {
159
160
  outputPreview: response ? response.slice(0, 200) : undefined,
160
161
  trigger,
161
162
  ...(runIdFromGateway ? { id: runIdFromGateway } : {}),
163
+ // 1.18.89: per-run cost for the dashboard Cost column / Health Strip tile.
164
+ ...(totalCostFromGateway != null ? { totalCostUsd: totalCostFromGateway } : {}),
162
165
  };
163
166
  // PRD Phase 1.1: goal-orientation evaluator (mirrors the daemon path).
164
167
  if (job.successSchema || (job.successCriteriaText && job.successCriteriaText.trim())) {
@@ -23835,9 +23835,24 @@ async function refreshHealthStrip() {
23835
23835
  : successRate >= 95 ? 'var(--green)'
23836
23836
  : successRate >= 80 ? 'var(--yellow)'
23837
23837
  : 'var(--red)';
23838
+ // 1.18.89: cost tile. Sums totalCostUsd across the 24h window. Runs that
23839
+ // pre-date 1.18.89 don't have the field — they contribute 0 (the user
23840
+ // sees a partial number that grows as new runs land).
23841
+ var totalCost = 0;
23842
+ var runsWithCost = 0;
23843
+ for (var ci = 0; ci < last24.length; ci++) {
23844
+ if (typeof last24[ci].totalCostUsd === 'number') {
23845
+ totalCost += last24[ci].totalCostUsd;
23846
+ runsWithCost++;
23847
+ }
23848
+ }
23849
+ var costLabel = runsWithCost === 0 ? '—' : (totalCost < 0.01 ? '$' + totalCost.toFixed(4) : '$' + totalCost.toFixed(2));
23850
+ var costSub = runsWithCost === 0 ? 'no priced runs yet' : runsWithCost + ' of ' + last24.length + ' runs priced';
23851
+
23838
23852
  var html = '';
23839
23853
  html += tile('Runs · 24h', last24.length, ok + ' ok · ' + failed + ' failed');
23840
23854
  html += tile('Success rate', successRate === null ? '—' : (successRate + '%'), null, srColor);
23855
+ html += tile('Cost · 24h', costLabel, costSub);
23841
23856
  html += tile('P50 latency', p50 === null ? '—' : formatDurationMs(p50), 'median run time');
23842
23857
  html += tile('P95 latency', p95 === null ? '—' : formatDurationMs(p95), '95th percentile');
23843
23858
  html += tile('Running now', activeRuns, activeRuns === 0 ? 'idle' : 'live');
@@ -23981,10 +23996,10 @@ function renderRunListBody(allRuns) {
23981
23996
  return html;
23982
23997
  }
23983
23998
  // Table — same shape as the Recent History list on the Tasks page,
23984
- // but sortable and with a Trigger column.
23999
+ // but sortable and with a Trigger + Cost column.
23985
24000
  html += '<div style="background:var(--bg-secondary);border:1px solid var(--border);border-radius:var(--radius)">';
23986
- html += '<div style="display:grid;grid-template-columns:24px 24px minmax(180px,1.2fr) 90px minmax(180px,1fr) 90px auto;gap:10px;padding:8px 14px;border-bottom:1px solid var(--border);font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.04em;font-weight:500">'
23987
- + '<div></div><div title="Goal verdict">Goal</div><div>Task</div><div>Trigger</div><div>Started</div><div>Duration</div><div></div>'
24001
+ html += '<div style="display:grid;grid-template-columns:24px 24px minmax(180px,1.2fr) 80px minmax(160px,1fr) 70px 70px auto;gap:10px;padding:8px 14px;border-bottom:1px solid var(--border);font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.04em;font-weight:500">'
24002
+ + '<div></div><div title="Goal verdict">Goal</div><div>Task</div><div>Trigger</div><div>Started</div><div>Duration</div><div title="Total cost in USD">Cost</div><div></div>'
23988
24003
  + '</div>';
23989
24004
  for (var i = 0; i < filtered.length; i++) {
23990
24005
  var entry = filtered[i] || {};
@@ -24032,7 +24047,14 @@ function renderRunListBody(allRuns) {
24032
24047
  } else if (entry.outputPreview) {
24033
24048
  preview = '<div style="font-size:11px;color:var(--text-muted);margin-top:2px;word-break:break-word">' + esc(String(entry.outputPreview).slice(0, 120)) + '</div>';
24034
24049
  }
24035
- html += '<div class="history-row" data-trace-job="' + esc(jobName) + '" style="display:grid;grid-template-columns:24px 24px minmax(180px,1.2fr) 90px minmax(180px,1fr) 90px auto;gap:10px;align-items:start;padding:8px 14px;border-bottom:1px solid var(--border);cursor:pointer">'
24050
+ // 1.18.89: cost label. Showing 4 decimals for sub-penny costs (Haiku
24051
+ // runs land in fractions of a cent), 2 decimals when ≥ $0.01.
24052
+ var costLabel = '—';
24053
+ if (entry.totalCostUsd != null) {
24054
+ var c = entry.totalCostUsd;
24055
+ costLabel = c < 0.01 ? '$' + c.toFixed(4) : '$' + c.toFixed(2);
24056
+ }
24057
+ html += '<div class="history-row" data-trace-job="' + esc(jobName) + '" style="display:grid;grid-template-columns:24px 24px minmax(180px,1.2fr) 80px minmax(160px,1fr) 70px 70px auto;gap:10px;align-items:start;padding:8px 14px;border-bottom:1px solid var(--border);cursor:pointer">'
24036
24058
  + '<div style="color:' + statusColor + ';font-size:14px;line-height:18px;text-align:center" title="' + esc(status) + '">' + statusIcon + '</div>'
24037
24059
  + goalCell
24038
24060
  + '<div style="min-width:0">'
@@ -24043,6 +24065,7 @@ function renderRunListBody(allRuns) {
24043
24065
  + '<div style="font-size:11px;color:' + triggerColor + ';line-height:18px">' + esc(triggerLabel) + '</div>'
24044
24066
  + '<div style="font-size:12px;color:var(--text-secondary);line-height:18px">' + esc(startedLabel) + '</div>'
24045
24067
  + '<div style="font-size:12px;color:var(--text-muted);line-height:18px">' + esc(durationLabel) + '</div>'
24068
+ + '<div style="font-size:12px;color:var(--text-muted);line-height:18px;font-family:\\x27JetBrains Mono\\x27,monospace">' + esc(costLabel) + '</div>'
24046
24069
  + '<div style="display:flex;gap:6px;align-items:center"><button class="btn-sm" onclick="event.stopPropagation();openRunOrTrace(\\x27' + safeName + '\\x27,' + (entry.id ? '\\x27' + jsStr(entry.id) + '\\x27' : 'null') + ')" style="font-size:11px;padding:3px 8px">' + (entry.id ? 'Open run' : 'Trace') + '</button></div>'
24047
24070
  + '</div>';
24048
24071
  }
@@ -1210,6 +1210,9 @@ export class CronScheduler {
1210
1210
  trigger,
1211
1211
  // 1.18.85: stable UUID linking this run to its Event store entries.
1212
1212
  ...(cronMetadata?.runId ? { id: cronMetadata.runId } : {}),
1213
+ // 1.18.89: per-run cost for the Run list + Health Strip. Comes from
1214
+ // SDK's ResultMessage.total_cost_usd via runAgent's side-channel.
1215
+ ...(cronMetadata?.totalCostUsd != null ? { totalCostUsd: cronMetadata.totalCostUsd } : {}),
1213
1216
  // Trick capability metadata — surfaced by the dashboard's
1214
1217
  // "ran with: …" line. Omit empty arrays to keep the JSONL light.
1215
1218
  ...(cronMetadata?.skillsApplied?.length ? { skillsApplied: cronMetadata.skillsApplied } : {}),
@@ -1306,6 +1309,9 @@ export class CronScheduler {
1306
1309
  // can show trigger + open the partial Event log if any.
1307
1310
  trigger,
1308
1311
  ...(errCronMetadata?.runId ? { id: errCronMetadata.runId } : {}),
1312
+ // 1.18.89: cost on the error path too — partial-completion runs may
1313
+ // still have spent budget before the throw.
1314
+ ...(errCronMetadata?.totalCostUsd != null ? { totalCostUsd: errCronMetadata.totalCostUsd } : {}),
1309
1315
  ...(errCronMetadata?.skillsApplied?.length ? { skillsApplied: errCronMetadata.skillsApplied } : {}),
1310
1316
  ...(errCronMetadata?.skillsMissing?.length ? { skillsMissing: errCronMetadata.skillsMissing } : {}),
1311
1317
  ...(errCronMetadata?.allowedToolsApplied?.length ? { allowedToolsApplied: errCronMetadata.allowedToolsApplied } : {}),
@@ -239,6 +239,8 @@ export declare class Gateway {
239
239
  mcpServersApplied: string[];
240
240
  /** PRD §6 / 1.18.85: run UUID from runAgent. */
241
241
  runId?: string;
242
+ /** PRD §12 / 1.18.89: total cost in USD from runAgent's SDK result. */
243
+ totalCostUsd?: number;
242
244
  } | undefined;
243
245
  requestApproval(descriptionOrId: string, explicitId?: string): Promise<boolean | string>;
244
246
  resolveApproval(requestId: string, result: boolean | string): void;
@@ -2024,6 +2024,7 @@ export class Gateway {
2024
2024
  allowedToolsApplied: cronResult.allowedToolsApplied,
2025
2025
  mcpServersApplied: cronResult.mcpServersApplied,
2026
2026
  runId: cronResult.runId,
2027
+ totalCostUsd: cronResult.totalCostUsd,
2027
2028
  };
2028
2029
  logger.info({
2029
2030
  jobName,
package/dist/types.d.ts CHANGED
@@ -514,6 +514,11 @@ export interface CronRunEntry {
514
514
  * whose status indicates a failure (error/timeout/lost/cancelled). The
515
515
  * Run list filter chip and Run detail header read from this field. */
516
516
  failureCategory?: RunFailureCategory;
517
+ /** PRD §12 / 1.18.89: total cost in USD as reported by the SDK's
518
+ * ResultMessage.total_cost_usd. Stamped on success/error entries by
519
+ * the scheduler from the runAgent result side-channel. Powers the
520
+ * Run list Cost column and the Health Strip's 24h cost tile. */
521
+ totalCostUsd?: number;
517
522
  /** PRD Phase 1: did the run accomplish what it was supposed to?
518
523
  * Computed at run-end when the Task has successSchema or successCriteriaText.
519
524
  * - status='pass' both configured checks passed (or the only one configured did)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clementine-agent",
3
- "version": "1.18.88",
3
+ "version": "1.18.89",
4
4
  "description": "Clementine — Personal AI Assistant (TypeScript)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",