Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
300d2c9339 | ||
|
|
cae7e3451f |
@ -14,6 +14,7 @@ Docs: https://docs.clawd.bot
|
|||||||
- Browser: add node-host proxy auto-routing for remote gateways (configurable per gateway/node).
|
- Browser: add node-host proxy auto-routing for remote gateways (configurable per gateway/node).
|
||||||
- Heartbeat: add per-channel visibility controls (OK/alerts/indicator). (#1452) Thanks @dlauer.
|
- Heartbeat: add per-channel visibility controls (OK/alerts/indicator). (#1452) Thanks @dlauer.
|
||||||
- Plugins: add optional llm-task JSON-only tool for workflows. (#1498) Thanks @vignesh07.
|
- Plugins: add optional llm-task JSON-only tool for workflows. (#1498) Thanks @vignesh07.
|
||||||
|
- Docs: add emoji reaction guidance to AGENTS.md template. (#1591) Thanks @EnzeD.
|
||||||
- CLI: restart the gateway by default after `clawdbot update`; add `--no-restart` to skip it.
|
- CLI: restart the gateway by default after `clawdbot update`; add `--no-restart` to skip it.
|
||||||
- CLI: add live auth probes to `clawdbot models status` for per-profile verification.
|
- CLI: add live auth probes to `clawdbot models status` for per-profile verification.
|
||||||
- CLI: add `clawdbot system` for system events + heartbeat controls; remove standalone `wake`.
|
- CLI: add `clawdbot system` for system events + heartbeat controls; remove standalone `wake`.
|
||||||
@ -27,6 +28,7 @@ Docs: https://docs.clawd.bot
|
|||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
- Sessions: accept non-UUID sessionIds for history/send/status while preserving agent scoping. (#1518)
|
- Sessions: accept non-UUID sessionIds for history/send/status while preserving agent scoping. (#1518)
|
||||||
|
- Routing/Cron: normalize agentId casing for bindings and cron payloads. (#1591)
|
||||||
- Gateway: compare Linux process start time to avoid PID recycling lock loops; keep locks unless stale. (#1572) Thanks @steipete.
|
- Gateway: compare Linux process start time to avoid PID recycling lock loops; keep locks unless stale. (#1572) Thanks @steipete.
|
||||||
- Messaging: mirror outbound sends into target session keys (threads + dmScope) and create session entries on send. (#1520)
|
- Messaging: mirror outbound sends into target session keys (threads + dmScope) and create session entries on send. (#1520)
|
||||||
- Sessions: normalize session key casing to lowercase for consistent routing.
|
- Sessions: normalize session key casing to lowercase for consistent routing.
|
||||||
|
|||||||
@ -92,6 +92,21 @@ In group chats where you receive every message, be **smart about when to contrib
|
|||||||
|
|
||||||
Participate, don't dominate.
|
Participate, don't dominate.
|
||||||
|
|
||||||
|
### 😊 React Like a Human!
|
||||||
|
On platforms that support reactions (Discord, Slack), use emoji reactions naturally:
|
||||||
|
|
||||||
|
**React when:**
|
||||||
|
- You appreciate something but don't need to reply (👍, ❤️, 🙌)
|
||||||
|
- Something made you laugh (😂, 💀)
|
||||||
|
- You find it interesting or thought-provoking (🤔, 💡)
|
||||||
|
- You want to acknowledge without interrupting the flow
|
||||||
|
- It's a simple yes/no or approval situation (✅, 👀)
|
||||||
|
|
||||||
|
**Why it matters:**
|
||||||
|
Reactions are lightweight social signals. Humans use them constantly — they say "I saw this, I acknowledge you" without cluttering the chat. You should too.
|
||||||
|
|
||||||
|
**Don't overdo it:** One reaction per message max. Pick the one that fits best.
|
||||||
|
|
||||||
## Tools
|
## Tools
|
||||||
|
|
||||||
Skills provide your tools. When you need one, check its `SKILL.md`. Keep local notes (camera names, SSH details, voice preferences) in `TOOLS.md`.
|
Skills provide your tools. When you need one, check its `SKILL.md`. Keep local notes (camera names, SSH details, voice preferences) in `TOOLS.md`.
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import type { Command } from "commander";
|
|||||||
import type { CronJob } from "../../cron/types.js";
|
import type { CronJob } from "../../cron/types.js";
|
||||||
import { danger } from "../../globals.js";
|
import { danger } from "../../globals.js";
|
||||||
import { defaultRuntime } from "../../runtime.js";
|
import { defaultRuntime } from "../../runtime.js";
|
||||||
|
import { normalizeAgentId } from "../../routing/session-key.js";
|
||||||
import type { GatewayRpcOpts } from "../gateway-rpc.js";
|
import type { GatewayRpcOpts } from "../gateway-rpc.js";
|
||||||
import { addGatewayClientOptions, callGatewayFromCli } from "../gateway-rpc.js";
|
import { addGatewayClientOptions, callGatewayFromCli } from "../gateway-rpc.js";
|
||||||
import { parsePositiveIntOrUndefined } from "../program/helpers.js";
|
import { parsePositiveIntOrUndefined } from "../program/helpers.js";
|
||||||
@ -138,7 +139,9 @@ export function registerCronAddCommand(cron: Command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const agentId =
|
const agentId =
|
||||||
typeof opts.agent === "string" && opts.agent.trim() ? opts.agent.trim() : undefined;
|
typeof opts.agent === "string" && opts.agent.trim()
|
||||||
|
? normalizeAgentId(opts.agent)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
const payload = (() => {
|
const payload = (() => {
|
||||||
const systemEvent = typeof opts.systemEvent === "string" ? opts.systemEvent.trim() : "";
|
const systemEvent = typeof opts.systemEvent === "string" ? opts.systemEvent.trim() : "";
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import type { Command } from "commander";
|
import type { Command } from "commander";
|
||||||
import { danger } from "../../globals.js";
|
import { danger } from "../../globals.js";
|
||||||
import { defaultRuntime } from "../../runtime.js";
|
import { defaultRuntime } from "../../runtime.js";
|
||||||
|
import { normalizeAgentId } from "../../routing/session-key.js";
|
||||||
import { addGatewayClientOptions, callGatewayFromCli } from "../gateway-rpc.js";
|
import { addGatewayClientOptions, callGatewayFromCli } from "../gateway-rpc.js";
|
||||||
import {
|
import {
|
||||||
getCronChannelOptions,
|
getCronChannelOptions,
|
||||||
@ -90,7 +91,7 @@ export function registerCronEditCommand(cron: Command) {
|
|||||||
throw new Error("Use --agent or --clear-agent, not both");
|
throw new Error("Use --agent or --clear-agent, not both");
|
||||||
}
|
}
|
||||||
if (typeof opts.agent === "string" && opts.agent.trim()) {
|
if (typeof opts.agent === "string" && opts.agent.trim()) {
|
||||||
patch.agentId = opts.agent.trim();
|
patch.agentId = normalizeAgentId(opts.agent);
|
||||||
}
|
}
|
||||||
if (opts.clearAgent) {
|
if (opts.clearAgent) {
|
||||||
patch.agentId = null;
|
patch.agentId = null;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { parseAbsoluteTimeMs } from "./parse.js";
|
import { parseAbsoluteTimeMs } from "./parse.js";
|
||||||
import { migrateLegacyCronPayload } from "./payload-migration.js";
|
import { migrateLegacyCronPayload } from "./payload-migration.js";
|
||||||
import type { CronJobCreate, CronJobPatch } from "./types.js";
|
import type { CronJobCreate, CronJobPatch } from "./types.js";
|
||||||
|
import { normalizeAgentId } from "../routing/session-key.js";
|
||||||
|
|
||||||
type UnknownRecord = Record<string, unknown>;
|
type UnknownRecord = Record<string, unknown>;
|
||||||
|
|
||||||
@ -75,7 +76,7 @@ export function normalizeCronJobInput(
|
|||||||
next.agentId = null;
|
next.agentId = null;
|
||||||
} else if (typeof agentId === "string") {
|
} else if (typeof agentId === "string") {
|
||||||
const trimmed = agentId.trim();
|
const trimmed = agentId.trim();
|
||||||
if (trimmed) next.agentId = trimmed;
|
if (trimmed) next.agentId = normalizeAgentId(trimmed);
|
||||||
else delete next.agentId;
|
else delete next.agentId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -95,7 +95,13 @@ function formatDiscordDeployErrorDetails(err: unknown): string {
|
|||||||
try {
|
try {
|
||||||
bodyText = JSON.stringify(rawBody);
|
bodyText = JSON.stringify(rawBody);
|
||||||
} catch {
|
} catch {
|
||||||
bodyText = String(rawBody);
|
if (typeof rawBody === "string") {
|
||||||
|
bodyText = rawBody;
|
||||||
|
} else if (rawBody instanceof Error) {
|
||||||
|
bodyText = rawBody.message;
|
||||||
|
} else {
|
||||||
|
bodyText = "[unserializable]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (bodyText) {
|
if (bodyText) {
|
||||||
const maxLen = 800;
|
const maxLen = 800;
|
||||||
|
|||||||
@ -96,9 +96,9 @@ function pickFirstExistingAgentId(cfg: ClawdbotConfig, agentId: string): string
|
|||||||
if (!trimmed) return normalizeAgentId(resolveDefaultAgentId(cfg));
|
if (!trimmed) return normalizeAgentId(resolveDefaultAgentId(cfg));
|
||||||
const normalized = normalizeAgentId(trimmed);
|
const normalized = normalizeAgentId(trimmed);
|
||||||
const agents = listAgents(cfg);
|
const agents = listAgents(cfg);
|
||||||
if (agents.length === 0) return trimmed;
|
if (agents.length === 0) return normalized;
|
||||||
const match = agents.find((agent) => normalizeAgentId(agent.id) === normalized);
|
const match = agents.find((agent) => normalizeAgentId(agent.id) === normalized);
|
||||||
if (match?.id?.trim()) return match.id.trim();
|
if (match?.id?.trim()) return normalizeAgentId(match.id);
|
||||||
return normalizeAgentId(resolveDefaultAgentId(cfg));
|
return normalizeAgentId(resolveDefaultAgentId(cfg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user