Skip to content

Commit 9c7d012

Browse files
Improve OpenClaw Autonomy
- Implement atomic task checkout in heartbeat flow - Filter locked objectives in loadObjectives - Pass objective_context in advance_plan calls - Wire CMS schema into operate mode and fix CMS load - Prevent heartbeat state leakage into memory loading - Update agent-execute cors headers and agent-operate cms integration X-Lovable-Edit-ID: edt-fa9ad225-c1d1-4b74-b025-a2797e44852e Co-authored-by: magnusfroste <38864257+magnusfroste@users.noreply.github.com>
2 parents 606b31d + 304f91a commit 9c7d012

File tree

3 files changed

+17
-4
lines changed

3 files changed

+17
-4
lines changed

supabase/functions/_shared/agent-reason.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ export async function loadMemories(supabase: any): Promise<string> {
467467
const { data } = await supabase
468468
.from('agent_memory')
469469
.select('key, value, category')
470-
.not('key', 'in', '("soul","identity")')
470+
.not('key', 'in', '("soul","identity","heartbeat_state")')
471471
.order('updated_at', { ascending: false })
472472
.limit(30);
473473

@@ -694,8 +694,9 @@ async function summarizeMessages(messages: any[], supabase: any): Promise<string
694694
export async function loadObjectives(supabase: any): Promise<string> {
695695
const { data } = await supabase
696696
.from('agent_objectives')
697-
.select('id, goal, status, constraints, success_criteria, progress, created_at, updated_at')
697+
.select('id, goal, status, constraints, success_criteria, progress, created_at, updated_at, locked_by, locked_at')
698698
.eq('status', 'active')
699+
.is('locked_by', null)
699700
.order('created_at', { ascending: false })
700701
.limit(10);
701702

@@ -855,6 +856,12 @@ async function handleAdvancePlan(supabase: any, supabaseUrl: string, serviceKey:
855856
const maxSteps = chain ? MAX_CHAIN_DEPTH : 1;
856857
const chainResults: any[] = [];
857858

859+
// Atomic checkout — prevent concurrent heartbeat instances from advancing the same objective
860+
const locked = await checkoutObjective(supabase, objective_id);
861+
if (!locked) {
862+
return { status: 'locked', message: 'Objective is currently being worked on by another process.' };
863+
}
864+
858865
for (let depth = 0; depth < maxSteps; depth++) {
859866
const { data: obj, error } = await supabase.from('agent_objectives')
860867
.select('id, goal, progress')
@@ -931,6 +938,9 @@ async function handleAdvancePlan(supabase: any, supabaseUrl: string, serviceKey:
931938
if (!success || !nextStep.skill_name || allDone) break;
932939
}
933940

941+
// Release the lock
942+
await releaseObjective(supabase, objective_id);
943+
934944
const lastResult = chainResults[chainResults.length - 1];
935945
return {
936946
status: chainResults.some(r => r.status === 'failed') ? 'chain_partial' : 'chain_completed',

supabase/functions/agent-execute/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { createClient, SupabaseClient } from 'https://esm.sh/@supabase/supabase-
33

44
const corsHeaders = {
55
'Access-Control-Allow-Origin': '*',
6-
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
6+
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type, x-supabase-client-platform, x-supabase-client-platform-version, x-supabase-client-runtime, x-supabase-client-runtime-version',
77
};
88

99
interface ExecuteRequest {

supabase/functions/agent-operate/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
getBuiltInTools,
1414
executeBuiltInTool,
1515
isBuiltInTool,
16+
loadCMSSchema,
1617
} from "../_shared/agent-reason.ts";
1718

1819
/**
@@ -47,10 +48,11 @@ serve(async (req) => {
4748
const { apiKey, apiUrl, model } = await resolveAiConfig(supabase);
4849

4950
// Load context in parallel
50-
const [{ soul, identity }, memoryContext, objectiveContext] = await Promise.all([
51+
const [{ soul, identity }, memoryContext, objectiveContext, cmsSchemaCtx] = await Promise.all([
5152
loadSoulIdentity(supabase),
5253
loadMemories(supabase),
5354
loadObjectives(supabase),
55+
loadCMSSchema(supabase),
5456
]);
5557

5658
// Use prompt compiler (OpenClaw Layer 1)
@@ -59,6 +61,7 @@ serve(async (req) => {
5961
soulPrompt: buildSoulPrompt(soul, identity),
6062
memoryContext,
6163
objectiveContext,
64+
cmsSchemaContext: cmsSchemaCtx,
6265
});
6366

6467
// Build tools

0 commit comments

Comments
 (0)