Compare commits

..

1 Commits

Author SHA1 Message Date
operator
6d59741086 feat: align wakeup prompts with daily-routine skill workflows
Update CalendarScheduler prompt templates to reference daily-routine
skill workflows (task-handson, plan-schedule, slot-complete) instead
of generic instructions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 17:31:36 +00:00
3 changed files with 61 additions and 47 deletions

View File

@@ -611,13 +611,11 @@ Task Code: ${code}
Estimated Duration: ${duration} minutes Estimated Duration: ${duration} minutes
Slot Type: ${slot.slot_type} Slot Type: ${slot.slot_type}
Priority: ${slot.priority} Priority: ${slot.priority}
Working Sessions: ${jobData.working_sessions?.join(', ') || 'none recorded'}
Please focus on this task for the allocated time. When you finish or need to pause, Follow the daily-routine skill's task-handson workflow to execute this task.
report your progress back to the calendar system. Use harborforge_calendar_complete when finished, or harborforge_calendar_pause to pause.
Before going idle, check for overdue slots as described in the slot-complete workflow.`;
Working sessions: ${jobData.working_sessions?.join(', ') || 'none recorded'}
Start working on ${code} now.`;
} }
/** /**
@@ -630,19 +628,15 @@ Start working on ${code} now.`;
switch (sysData.event) { switch (sysData.event) {
case 'ScheduleToday': case 'ScheduleToday':
return `System Event: Schedule Today return `System Event: Schedule Today
Please review today's calendar and schedule any pending tasks or planning activities.
Estimated time: ${slot.estimated_duration} minutes. Estimated time: ${slot.estimated_duration} minutes.
Check your calendar and plan the day's work.`; Follow the daily-routine skill's plan-schedule workflow to plan today's work.`;
case 'SummaryToday': case 'SummaryToday':
return `System Event: Daily Summary return `System Event: Daily Summary
Please provide a summary of today's activities and progress.
Estimated time: ${slot.estimated_duration} minutes. Estimated time: ${slot.estimated_duration} minutes.
Review what was accomplished and prepare end-of-day notes.`; Review today's completed, deferred, and abandoned slots. Write a summary to your daily note (memory/YYYY-MM-DD.md).`;
case 'ScheduledGatewayRestart': case 'ScheduledGatewayRestart':
return `System Event: Scheduled Gateway Restart return `System Event: Scheduled Gateway Restart

View File

@@ -1,3 +1,8 @@
import { execFile } from 'child_process';
import { promisify } from 'util';
const execFileAsync = promisify(execFile);
export interface OpenClawAgentInfo { export interface OpenClawAgentInfo {
name: string; name: string;
isDefault?: boolean; isDefault?: boolean;
@@ -9,38 +14,70 @@ export interface OpenClawAgentInfo {
routing?: string; routing?: string;
} }
export async function listOpenClawAgents(_logger?: { debug?: (...args: any[]) => void; warn?: (...args: any[]) => void }): Promise<OpenClawAgentInfo[]> { export async function listOpenClawAgents(logger?: { debug?: (...args: any[]) => void; warn?: (...args: any[]) => void }): Promise<OpenClawAgentInfo[]> {
return []; try {
const { stdout } = await execFileAsync('openclaw', ['agents', 'list'], {
timeout: 15000,
maxBuffer: 1024 * 1024,
});
return parseOpenClawAgents(stdout);
} catch (err) {
logger?.warn?.('Failed to run `openclaw agents list`', err);
return [];
}
} }
export function parseOpenClawAgents(text: string): OpenClawAgentInfo[] { export function parseOpenClawAgents(text: string): OpenClawAgentInfo[] {
const lines = text.split(/\r?\n/); const lines = text.split(/\r?\n/);
const out: OpenClawAgentInfo[] = []; const out: OpenClawAgentInfo[] = [];
let current: OpenClawAgentInfo | null = null; let current: OpenClawAgentInfo | null = null;
const push = () => { if (current) out.push(current); current = null; };
const push = () => {
if (current) out.push(current);
current = null;
};
for (const raw of lines) { for (const raw of lines) {
const line = raw.trimEnd(); const line = raw.trimEnd();
if (!line.trim() || line.startsWith("Agents:") || line.startsWith("Routing rules map") || line.startsWith("Channel status reflects")) continue; if (!line.trim() || line.startsWith('Agents:') || line.startsWith('Routing rules map') || line.startsWith('Channel status reflects')) continue;
if (line.startsWith("- ")) { if (line.startsWith('- ')) {
push(); push();
const m = line.match(/^-\s+(.+?)(?:\s+\((default)\))?$/); const m = line.match(/^-\s+(.+?)(?:\s+\((default)\))?$/);
current = { name: m?.[1] || line.slice(2).trim(), isDefault: m?.[2] === "default" }; current = {
name: m?.[1] || line.slice(2).trim(),
isDefault: m?.[2] === 'default',
};
continue; continue;
} }
if (!current) continue; if (!current) continue;
const trimmed = line.trim(); const trimmed = line.trim();
const idx = trimmed.indexOf(":"); const idx = trimmed.indexOf(':');
if (idx === -1) continue; if (idx === -1) continue;
const key = trimmed.slice(0, idx).trim(); const key = trimmed.slice(0, idx).trim();
const value = trimmed.slice(idx + 1).trim(); const value = trimmed.slice(idx + 1).trim();
switch (key) { switch (key) {
case "Identity": current.identity = value; break; case 'Identity':
case "Workspace": current.workspace = value; break; current.identity = value;
case "Agent dir": current.agentDir = value; break; break;
case "Model": current.model = value; break; case 'Workspace':
case "Routing rules": { const n = Number(value); current.routingRules = Number.isFinite(n) ? n : undefined; break; } current.workspace = value;
case "Routing": current.routing = value; break; break;
default: break; case 'Agent dir':
current.agentDir = value;
break;
case 'Model':
current.model = value;
break;
case 'Routing rules': {
const n = Number(value);
current.routingRules = Number.isFinite(n) ? n : undefined;
break;
}
case 'Routing':
current.routing = value;
break;
default:
break;
} }
} }
push(); push();

View File

@@ -14,7 +14,7 @@
import { hostname, freemem, totalmem, uptime, loadavg, platform } from 'os'; import { hostname, freemem, totalmem, uptime, loadavg, platform } from 'os';
import { getPluginConfig } from './core/config'; import { getPluginConfig } from './core/config';
import { MonitorBridgeClient, type OpenClawMeta } from './core/monitor-bridge'; import { MonitorBridgeClient, type OpenClawMeta } from './core/monitor-bridge';
import type { OpenClawAgentInfo } from './core/openclaw-agents'; import { listOpenClawAgents } from './core/openclaw-agents';
import { registerGatewayStartHook } from './hooks/gateway-start'; import { registerGatewayStartHook } from './hooks/gateway-start';
import { registerGatewayStopHook } from './hooks/gateway-stop'; import { registerGatewayStopHook } from './hooks/gateway-stop';
import { import {
@@ -32,12 +32,6 @@ interface PluginAPI {
warn: (...args: any[]) => void; warn: (...args: any[]) => void;
}; };
version?: string; version?: string;
runtime?: {
version?: string;
config?: {
loadConfig?: () => any;
};
};
config?: Record<string, unknown>; config?: Record<string, unknown>;
pluginConfig?: Record<string, unknown>; pluginConfig?: Record<string, unknown>;
on: (event: string, handler: () => void) => void; on: (event: string, handler: () => void) => void;
@@ -102,7 +96,7 @@ export default {
avg15: load[2], avg15: load[2],
}, },
openclaw: { openclaw: {
version: api.runtime?.version || api.version || 'unknown', version: api.version || 'unknown',
pluginVersion: '0.3.1', // Bumped for PLG-CAL-004 pluginVersion: '0.3.1', // Bumped for PLG-CAL-004
}, },
timestamp: new Date().toISOString(), timestamp: new Date().toISOString(),
@@ -124,21 +118,10 @@ export default {
const bridgeClient = getBridgeClient(); const bridgeClient = getBridgeClient();
if (!bridgeClient) return; if (!bridgeClient) return;
let agentNames: string[] = [];
try {
const cfg = api.runtime?.config?.loadConfig?.();
const agentsList = cfg?.agents?.list;
if (Array.isArray(agentsList)) {
agentNames = agentsList
.map((a: any) => typeof a === 'string' ? a : a?.name)
.filter(Boolean);
}
} catch { /* non-fatal */ }
const meta: OpenClawMeta = { const meta: OpenClawMeta = {
version: api.runtime?.version || api.version || 'unknown', version: api.version || 'unknown',
plugin_version: '0.3.1', plugin_version: '0.3.1',
agents: agentNames.map(name => ({ name })), agents: await listOpenClawAgents(logger),
}; };
const ok = await bridgeClient.pushOpenClawMeta(meta); const ok = await bridgeClient.pushOpenClawMeta(meta);