Update workspace agent file (#889)

This commit is contained in:
paisley
2026-04-22 13:16:48 +08:00
committed by GitHub
parent 1ed9f77a29
commit 285f8202c7
3 changed files with 219 additions and 2 deletions

View File

@@ -14,6 +14,7 @@ import { deleteChannelAccountConfig } from '../../utils/channel-config';
import { syncAgentModelOverrideToRuntime, syncAllProviderAuthToRuntime } from '../../services/providers/provider-runtime-sync';
import type { HostApiContext } from '../context';
import { parseJsonBody, sendJson } from '../route-utils';
import { ensureClawXContext } from '../../utils/openclaw-workspace';
function scheduleGatewayReload(ctx: HostApiContext, reason: string): void {
if (ctx.gatewayManager.getStatus().state !== 'stopped') {
@@ -128,6 +129,11 @@ export async function handleAgentRoutes(
console.warn('[agents] Failed to sync provider auth after agent creation:', err);
});
scheduleGatewayReload(ctx, 'create-agent');
// Ensure newly provisioned workspaces get ClawX context merge/cleanup
// even when gateway status events do not fire (e.g. in-process reload).
void ensureClawXContext().catch((err) => {
console.warn('[agents] Failed to ensure ClawX context after agent creation:', err);
});
sendJson(res, 200, { success: true, ...snapshot });
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });

View File

@@ -43,6 +43,66 @@ export function mergeClawXSection(existing: string, section: string): string {
return existing.trimEnd() + '\n\n' + wrapped + '\n';
}
/**
* Strip the "## First Run" section from workspace AGENTS.md content.
* This section is seeded by the OpenClaw Gateway but is unnecessary
* for ClawX-managed workspaces. Removes everything from the heading
* line until the next markdown heading (any level) or end of content.
*/
export function stripFirstRunSection(content: string): string {
const lines = content.split('\n');
const result: string[] = [];
let skipping = false;
let consumedFirstParagraph = false;
let seenBlankAfterParagraph = false;
for (const line of lines) {
const isHeading = /^#{1,6}\s/.test(line);
const trimmed = line.trim();
if (line.trim() === '## First Run') {
skipping = true;
consumedFirstParagraph = false;
seenBlankAfterParagraph = false;
continue;
}
if (skipping) {
// A new heading marks the end of the First Run block.
if (isHeading) {
skipping = false;
} else if (!consumedFirstParagraph) {
// Drop leading blank lines and the first guidance paragraph.
if (trimmed.length === 0) {
continue;
}
consumedFirstParagraph = true;
continue;
} else if (!seenBlankAfterParagraph) {
// Keep consuming the same paragraph until a blank line appears.
if (trimmed.length === 0) {
seenBlankAfterParagraph = true;
continue;
}
continue;
} else {
// After paragraph + blank line, preserve subsequent body content.
if (trimmed.length === 0) {
continue;
}
skipping = false;
}
}
if (!skipping) {
result.push(line);
}
}
// Collapse any resulting triple+ blank lines into double
return result.join('\n').replace(/\n{3,}/g, '\n\n');
}
// ── Workspace directory resolution ───────────────────────────────
/**
@@ -173,10 +233,22 @@ async function mergeClawXContextOnce(): Promise<number> {
}
const section = await readFile(join(contextDir, file), 'utf-8');
const existing = await readFile(targetPath, 'utf-8');
const originalExisting = await readFile(targetPath, 'utf-8');
let existing = originalExisting;
// Strip unwanted Gateway-seeded sections before merging
if (targetName === 'AGENTS.md') {
const stripped = stripFirstRunSection(existing);
if (stripped !== existing) {
existing = stripped;
logger.info(`Stripped First Run section from ${targetName} (${workspaceDir})`);
}
}
const merged = mergeClawXSection(existing, section);
if (merged !== existing) {
// Compare against on-disk content so we persist changes even when only
// First Run stripping happened and the ClawX section stayed identical.
if (merged !== originalExisting) {
await writeFile(targetPath, merged, 'utf-8');
logger.info(`Merged ClawX context into ${targetName} (${workspaceDir})`);
}