Compare commits
3 Commits
main
...
fix/cron-s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c93143c4a | ||
|
|
11a6f6db2e | ||
|
|
19e0b701cf |
@ -48,6 +48,7 @@ Docs: https://docs.clawd.bot
|
||||
- Google Chat: normalize space targets without double `spaces/` prefix.
|
||||
- Agents: auto-compact on context overflow prompt errors before failing. (#1627) Thanks @rodrigouroz.
|
||||
- Agents: use the active auth profile for auto-compaction recovery.
|
||||
- Agents: let cron isolated runs inherit subagent allowlists from the parent agent. (#1771) Thanks @Noctivoro.
|
||||
- Media understanding: skip image understanding when the primary model already supports vision. (#1747) Thanks @tyler6204.
|
||||
- Models: default missing custom provider fields so minimal configs are accepted.
|
||||
- Messaging: keep newline chunking safe for fenced markdown blocks across channels.
|
||||
|
||||
@ -157,4 +157,44 @@ describe("agents_list", () => {
|
||||
const research = agents?.find((agent) => agent.id === "research");
|
||||
expect(research?.configured).toBe(false);
|
||||
});
|
||||
|
||||
it("uses requesterAgentIdOverride when resolving allowlists", async () => {
|
||||
configOverride = {
|
||||
session: {
|
||||
mainKey: "main",
|
||||
scope: "per-sender",
|
||||
},
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "cron-owner",
|
||||
subagents: {
|
||||
allowAgents: ["research"],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "research",
|
||||
name: "Research",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const tool = createClawdbotTools({
|
||||
agentSessionKey: "cron:job-1",
|
||||
requesterAgentIdOverride: "cron-owner",
|
||||
}).find((candidate) => candidate.name === "agents_list");
|
||||
if (!tool) throw new Error("missing agents_list tool");
|
||||
|
||||
const result = await tool.execute("call5", {});
|
||||
const agents = (
|
||||
result.details as {
|
||||
agents?: Array<{ id: string }>;
|
||||
}
|
||||
).agents;
|
||||
expect(agents?.map((agent) => agent.id)).toEqual(["cron-owner", "research"]);
|
||||
expect(result.details).toMatchObject({
|
||||
requester: "cron-owner",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -87,6 +87,52 @@ describe("clawdbot-tools: subagents", () => {
|
||||
});
|
||||
expect(childSessionKey?.startsWith("agent:research:subagent:")).toBe(true);
|
||||
});
|
||||
|
||||
it("sessions_spawn honors requesterAgentIdOverride for cron sessions", async () => {
|
||||
resetSubagentRegistryForTests();
|
||||
callGatewayMock.mockReset();
|
||||
configOverride = {
|
||||
session: {
|
||||
mainKey: "main",
|
||||
scope: "per-sender",
|
||||
},
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "cron-owner",
|
||||
subagents: {
|
||||
allowAgents: ["research"],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
callGatewayMock.mockImplementation(async (opts: unknown) => {
|
||||
const request = opts as { method?: string; params?: unknown };
|
||||
if (request.method === "agent") {
|
||||
return { runId: "run-2", status: "accepted", acceptedAt: 5200 };
|
||||
}
|
||||
return {};
|
||||
});
|
||||
|
||||
const tool = createClawdbotTools({
|
||||
agentSessionKey: "cron:job-1",
|
||||
requesterAgentIdOverride: "cron-owner",
|
||||
agentChannel: "whatsapp",
|
||||
}).find((candidate) => candidate.name === "sessions_spawn");
|
||||
if (!tool) throw new Error("missing sessions_spawn tool");
|
||||
|
||||
const result = await tool.execute("call11", {
|
||||
task: "do thing",
|
||||
agentId: "research",
|
||||
});
|
||||
|
||||
expect(result.details).toMatchObject({
|
||||
status: "accepted",
|
||||
runId: "run-2",
|
||||
});
|
||||
});
|
||||
it("sessions_spawn forbids cross-agent spawning when not allowed", async () => {
|
||||
resetSubagentRegistryForTests();
|
||||
callGatewayMock.mockReset();
|
||||
|
||||
@ -54,6 +54,8 @@ export function createClawdbotTools(options?: {
|
||||
hasRepliedRef?: { value: boolean };
|
||||
/** If true, the model has native vision capability */
|
||||
modelHasVision?: boolean;
|
||||
/** Explicit agent ID override for cron/hook sessions. */
|
||||
requesterAgentIdOverride?: string;
|
||||
}): AnyAgentTool[] {
|
||||
const imageTool = options?.agentDir?.trim()
|
||||
? createImageTool({
|
||||
@ -105,7 +107,10 @@ export function createClawdbotTools(options?: {
|
||||
agentSessionKey: options?.agentSessionKey,
|
||||
config: options?.config,
|
||||
}),
|
||||
createAgentsListTool({ agentSessionKey: options?.agentSessionKey }),
|
||||
createAgentsListTool({
|
||||
agentSessionKey: options?.agentSessionKey,
|
||||
requesterAgentIdOverride: options?.requesterAgentIdOverride,
|
||||
}),
|
||||
createSessionsListTool({
|
||||
agentSessionKey: options?.agentSessionKey,
|
||||
sandboxed: options?.sandboxed,
|
||||
@ -129,6 +134,7 @@ export function createClawdbotTools(options?: {
|
||||
agentGroupChannel: options?.agentGroupChannel,
|
||||
agentGroupSpace: options?.agentGroupSpace,
|
||||
sandboxed: options?.sandboxed,
|
||||
requesterAgentIdOverride: options?.requesterAgentIdOverride,
|
||||
}),
|
||||
createSessionStatusTool({
|
||||
agentSessionKey: options?.agentSessionKey,
|
||||
@ -144,10 +150,12 @@ export function createClawdbotTools(options?: {
|
||||
config: options?.config,
|
||||
workspaceDir: options?.workspaceDir,
|
||||
agentDir: options?.agentDir,
|
||||
agentId: resolveSessionAgentId({
|
||||
sessionKey: options?.agentSessionKey,
|
||||
config: options?.config,
|
||||
}),
|
||||
agentId:
|
||||
options?.requesterAgentIdOverride ??
|
||||
resolveSessionAgentId({
|
||||
sessionKey: options?.agentSessionKey,
|
||||
config: options?.config,
|
||||
}),
|
||||
sessionKey: options?.agentSessionKey,
|
||||
messageChannel: options?.agentChannel,
|
||||
agentAccountId: options?.agentAccountId,
|
||||
|
||||
@ -293,6 +293,7 @@ export function createClawdbotCodingTools(options?: {
|
||||
agentGroupChannel: options?.groupChannel ?? null,
|
||||
agentGroupSpace: options?.groupSpace ?? null,
|
||||
agentDir: options?.agentDir,
|
||||
requesterAgentIdOverride: agentId,
|
||||
sandboxRoot,
|
||||
workspaceDir: options?.workspaceDir,
|
||||
sandboxed: !!sandbox,
|
||||
|
||||
@ -19,7 +19,11 @@ type AgentListEntry = {
|
||||
configured: boolean;
|
||||
};
|
||||
|
||||
export function createAgentsListTool(opts?: { agentSessionKey?: string }): AnyAgentTool {
|
||||
export function createAgentsListTool(opts?: {
|
||||
agentSessionKey?: string;
|
||||
/** Explicit agent ID override for cron/hook sessions. */
|
||||
requesterAgentIdOverride?: string;
|
||||
}): AnyAgentTool {
|
||||
return {
|
||||
label: "Agents",
|
||||
name: "agents_list",
|
||||
@ -37,7 +41,9 @@ export function createAgentsListTool(opts?: { agentSessionKey?: string }): AnyAg
|
||||
})
|
||||
: alias;
|
||||
const requesterAgentId = normalizeAgentId(
|
||||
parseAgentSessionKey(requesterInternalKey)?.agentId ?? DEFAULT_AGENT_ID,
|
||||
opts?.requesterAgentIdOverride ??
|
||||
parseAgentSessionKey(requesterInternalKey)?.agentId ??
|
||||
DEFAULT_AGENT_ID,
|
||||
);
|
||||
|
||||
const allowAgents = resolveAgentConfig(cfg, requesterAgentId)?.subagents?.allowAgents ?? [];
|
||||
|
||||
@ -67,6 +67,8 @@ export function createSessionsSpawnTool(opts?: {
|
||||
agentGroupChannel?: string | null;
|
||||
agentGroupSpace?: string | null;
|
||||
sandboxed?: boolean;
|
||||
/** Explicit agent ID override for cron/hook sessions where session key parsing may not work. */
|
||||
requesterAgentIdOverride?: string;
|
||||
}): AnyAgentTool {
|
||||
return {
|
||||
label: "Sessions",
|
||||
@ -129,7 +131,7 @@ export function createSessionsSpawnTool(opts?: {
|
||||
});
|
||||
|
||||
const requesterAgentId = normalizeAgentId(
|
||||
parseAgentSessionKey(requesterInternalKey)?.agentId,
|
||||
opts?.requesterAgentIdOverride ?? parseAgentSessionKey(requesterInternalKey)?.agentId,
|
||||
);
|
||||
const targetAgentId = requestedAgentId
|
||||
? normalizeAgentId(requestedAgentId)
|
||||
|
||||
@ -170,6 +170,7 @@ export async function handleInlineActions(params: {
|
||||
agentAccountId: (ctx as { AccountId?: string }).AccountId,
|
||||
agentTo: ctx.OriginatingTo ?? ctx.To,
|
||||
agentThreadId: ctx.MessageThreadId ?? undefined,
|
||||
requesterAgentIdOverride: agentId,
|
||||
agentDir,
|
||||
workspaceDir,
|
||||
config: cfg,
|
||||
|
||||
@ -148,6 +148,7 @@ export async function handleToolsInvokeHttpRequest(
|
||||
agentSessionKey: sessionKey,
|
||||
agentChannel: messageChannel ?? undefined,
|
||||
agentAccountId: accountId,
|
||||
requesterAgentIdOverride: agentId,
|
||||
config: cfg,
|
||||
pluginToolAllowlist: collectExplicitAllowlist([
|
||||
profilePolicy,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user