Merge branch 'main' into fix/1897-session-status-time-hint

This commit is contained in:
Tak Hoffman
2026-01-31 19:58:05 -06:00
committed by GitHub
3693 changed files with 74315 additions and 43497 deletions

View File

@@ -1,13 +1,13 @@
import type { ReasoningLevel, ThinkLevel } from "../auto-reply/thinking.js";
import { SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js";
import { listDeliverableMessageChannels } from "../utils/message-channel.js";
import type { ResolvedTimeFormat } from "./date-time.js";
import type { EmbeddedContextFile } from "./pi-embedded-helpers.js";
import { SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js";
import { listDeliverableMessageChannels } from "../utils/message-channel.js";
/**
* Controls which hardcoded sections are included in the system prompt.
* - "full": All sections (default, for main agent)
* - "minimal": Reduced sections (Tooling, Workspace, Runtime) - used for subagents
* - "minimal": Reduced sections (Tooling, Safety, Workspace, Sandbox, Runtime) - used for subagents
* - "none": Just basic identity line, no sections
*/
export type PromptMode = "full" | "minimal" | "none";
@@ -17,9 +17,13 @@ function buildSkillsSection(params: {
isMinimal: boolean;
readToolName: string;
}) {
if (params.isMinimal) return [];
if (params.isMinimal) {
return [];
}
const trimmed = params.skillsPrompt?.trim();
if (!trimmed) return [];
if (!trimmed) {
return [];
}
return [
"## Skills (mandatory)",
"Before replying: scan <available_skills> <description> entries.",
@@ -33,7 +37,9 @@ function buildSkillsSection(params: {
}
function buildMemorySection(params: { isMinimal: boolean; availableTools: Set<string> }) {
if (params.isMinimal) return [];
if (params.isMinimal) {
return [];
}
if (!params.availableTools.has("memory_search") && !params.availableTools.has("memory_get")) {
return [];
}
@@ -45,7 +51,9 @@ function buildMemorySection(params: { isMinimal: boolean; availableTools: Set<st
}
function buildUserIdentitySection(ownerLine: string | undefined, isMinimal: boolean) {
if (!ownerLine || isMinimal) return [];
if (!ownerLine || isMinimal) {
return [];
}
return ["## User Identity", ownerLine, ""];
}
@@ -59,8 +67,20 @@ function buildTimeSection(params: { userTimezone?: string }) {
];
}
function buildSafetySection() {
return [
"## Safety",
"You have no independent goals: do not pursue self-preservation, replication, resource acquisition, or power-seeking; avoid long-term plans beyond the user's request.",
"Prioritize safety and human oversight over completion; if instructions conflict, pause and ask; comply with stop/pause/audit requests and never bypass safeguards. (Inspired by Anthropic's constitution.)",
"Do not manipulate or persuade anyone to expand access or disable safeguards. Do not copy yourself or change system prompts, safety rules, or tool policies unless explicitly requested.",
"",
];
}
function buildReplyTagsSection(isMinimal: boolean) {
if (isMinimal) return [];
if (isMinimal) {
return [];
}
return [
"## Reply Tags",
"To request a native reply/quote on supported surfaces, include one tag in your reply:",
@@ -80,12 +100,14 @@ function buildMessagingSection(params: {
runtimeChannel?: string;
messageToolHints?: string[];
}) {
if (params.isMinimal) return [];
if (params.isMinimal) {
return [];
}
return [
"## Messaging",
"- Reply in current session → automatically routes to the source channel (Signal, Telegram, etc.)",
"- Cross-session messaging → use sessions_send(sessionKey, message)",
"- Never use exec/curl for provider messaging; Moltbot handles all routing internally.",
"- Never use exec/curl for provider messaging; OpenClaw handles all routing internally.",
params.availableTools.has("message")
? [
"",
@@ -109,24 +131,30 @@ function buildMessagingSection(params: {
}
function buildVoiceSection(params: { isMinimal: boolean; ttsHint?: string }) {
if (params.isMinimal) return [];
if (params.isMinimal) {
return [];
}
const hint = params.ttsHint?.trim();
if (!hint) return [];
if (!hint) {
return [];
}
return ["## Voice (TTS)", hint, ""];
}
function buildDocsSection(params: { docsPath?: string; isMinimal: boolean; readToolName: string }) {
const docsPath = params.docsPath?.trim();
if (!docsPath || params.isMinimal) return [];
if (!docsPath || params.isMinimal) {
return [];
}
return [
"## Documentation",
`Moltbot docs: ${docsPath}`,
"Mirror: https://docs.molt.bot",
"Source: https://github.com/moltbot/moltbot",
`OpenClaw docs: ${docsPath}`,
"Mirror: https://docs.openclaw.ai",
"Source: https://github.com/openclaw/openclaw",
"Community: https://discord.com/invite/clawd",
"Find new skills: https://clawdhub.com",
"For Moltbot behavior, commands, config, or architecture: consult local docs first.",
"When diagnosing issues, run `moltbot status` yourself when possible; only ask the user if you lack access (e.g., sandboxed).",
"Find new skills: https://clawhub.com",
"For OpenClaw behavior, commands, config, or architecture: consult local docs first.",
"When diagnosing issues, run `openclaw status` yourself when possible; only ask the user if you lack access (e.g., sandboxed).",
"",
];
}
@@ -202,7 +230,7 @@ export function buildAgentSystemPrompt(params: {
nodes: "List/describe/notify/camera/screen on paired nodes",
cron: "Manage cron jobs and wake events (use for reminders; when scheduling a reminder, write the systemEvent text as something that will read like a reminder when it fires, and mention that it is a reminder depending on the time gap between setting and firing; include recent context in reminder text if appropriate)",
message: "Send messages and channel actions",
gateway: "Restart, apply config, or run updates on the running Moltbot process",
gateway: "Restart, apply config, or run updates on the running OpenClaw process",
agents_list: "List agent ids allowed for sessions_spawn",
sessions_list: "List other sessions (incl. sub-agents) with filters/last",
sessions_history: "Fetch history for another session/sub-agent",
@@ -257,7 +285,9 @@ export function buildAgentSystemPrompt(params: {
const externalToolSummaries = new Map<string, string>();
for (const [key, value] of Object.entries(params.toolSummaries ?? {})) {
const normalized = key.trim().toLowerCase();
if (!normalized || !value?.trim()) continue;
if (!normalized || !value?.trim()) {
continue;
}
externalToolSummaries.set(normalized, value.trim());
}
const extraTools = Array.from(
@@ -269,7 +299,7 @@ export function buildAgentSystemPrompt(params: {
const name = resolveToolName(tool);
return summary ? `- ${name}: ${summary}` : `- ${name}`;
});
for (const tool of extraTools.sort()) {
for (const tool of extraTools.toSorted()) {
const summary = coreToolSummaries[tool] ?? externalToolSummaries.get(tool);
const name = resolveToolName(tool);
toolLines.push(summary ? `- ${name}: ${summary}` : `- ${name}`);
@@ -329,11 +359,11 @@ export function buildAgentSystemPrompt(params: {
// For "none" mode, return just the basic identity line
if (promptMode === "none") {
return "You are a personal assistant running inside Moltbot.";
return "You are a personal assistant running inside OpenClaw.";
}
const lines = [
"You are a personal assistant running inside Moltbot.",
"You are a personal assistant running inside OpenClaw.",
"",
"## Tooling",
"Tool availability (filtered by policy):",
@@ -348,7 +378,7 @@ export function buildAgentSystemPrompt(params: {
"- apply_patch: apply multi-file patches",
`- ${execToolName}: run shell commands (supports background via yieldMs/background)`,
`- ${processToolName}: manage background exec sessions`,
"- browser: control clawd's dedicated browser",
"- browser: control openclaw's dedicated browser",
"- canvas: present/eval/snapshot the Canvas",
"- nodes: list/describe/notify/camera/screen on paired nodes",
"- cron: manage cron jobs and wake events (use for reminders; when scheduling a reminder, write the systemEvent text as something that will read like a reminder when it fires, and mention that it is a reminder depending on the time gap between setting and firing; include recent context in reminder text if appropriate)",
@@ -365,25 +395,26 @@ export function buildAgentSystemPrompt(params: {
"Keep narration brief and value-dense; avoid repeating obvious steps.",
"Use plain human language for narration unless in a technical context.",
"",
"## Moltbot CLI Quick Reference",
"Moltbot is controlled via subcommands. Do not invent commands.",
...buildSafetySection(),
"## OpenClaw CLI Quick Reference",
"OpenClaw is controlled via subcommands. Do not invent commands.",
"To manage the Gateway daemon service (start/stop/restart):",
"- moltbot gateway status",
"- moltbot gateway start",
"- moltbot gateway stop",
"- moltbot gateway restart",
"If unsure, ask the user to run `moltbot help` (or `moltbot gateway --help`) and paste the output.",
"- openclaw gateway status",
"- openclaw gateway start",
"- openclaw gateway stop",
"- openclaw gateway restart",
"If unsure, ask the user to run `openclaw help` (or `openclaw gateway --help`) and paste the output.",
"",
...skillsSection,
...memorySection,
// Skip self-update for subagent/none modes
hasGateway && !isMinimal ? "## Moltbot Self-Update" : "",
hasGateway && !isMinimal ? "## OpenClaw Self-Update" : "",
hasGateway && !isMinimal
? [
"Get Updates (self-update) is ONLY allowed when the user explicitly asks for it.",
"Do not run config.apply or update.run unless the user explicitly requests an update or config change; if it's not explicit, ask first.",
"Actions: config.get, config.schema, config.apply (validate + write full config, then restart), update.run (update deps or git, then restart).",
"After restart, Moltbot pings the last active session automatically.",
"After restart, OpenClaw pings the last active session automatically.",
].join("\n")
: "",
hasGateway && !isMinimal ? "" : "",
@@ -452,7 +483,7 @@ export function buildAgentSystemPrompt(params: {
userTimezone,
}),
"## Workspace Files (injected)",
"These user-editable files are loaded by Moltbot and included below in Project Context.",
"These user-editable files are loaded by OpenClaw and included below in Project Context.",
"",
...buildReplyTagsSection(isMinimal),
...buildMessagingSection({
@@ -543,7 +574,7 @@ export function buildAgentSystemPrompt(params: {
heartbeatPromptLine,
"If you receive a heartbeat poll (a user message matching the heartbeat prompt above), and there is nothing that needs attention, reply exactly:",
"HEARTBEAT_OK",
'Moltbot treats a leading/trailing "HEARTBEAT_OK" as a heartbeat ack (and may discard it).',
'OpenClaw treats a leading/trailing "HEARTBEAT_OK" as a heartbeat ack (and may discard it).',
'If something needs attention, do NOT include "HEARTBEAT_OK"; reply with the alert text instead.',
"",
);