@hamp10/agentforge 0.2.29 → 0.2.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/check-task-semantics.js +15 -0
- package/src/OpenClawCLI.js +19 -17
- package/src/worker.js +2 -1
package/package.json
CHANGED
|
@@ -949,6 +949,21 @@ assert.match(
|
|
|
949
949
|
/taskId,\n\s*iteration,/i,
|
|
950
950
|
'direct fast path should receive taskId so UI peer context is task-scoped'
|
|
951
951
|
);
|
|
952
|
+
assert.match(
|
|
953
|
+
openClawSource,
|
|
954
|
+
/const semanticTask = String\(directOptions\.rawUserTask \|\| task \|\| ''\);[\s\S]*_guardDirectFileWritePath\(fileWriteTarget, workDir, \{ task: semanticTask \}\)/i,
|
|
955
|
+
'direct scope guards should use the raw user task, not expanded retry/platform context'
|
|
956
|
+
);
|
|
957
|
+
assert.match(
|
|
958
|
+
openClawSource,
|
|
959
|
+
/rawUserTask: rawUserTask \|\| task/i,
|
|
960
|
+
'direct fast path should pass the raw task separately from the expanded runtime prompt'
|
|
961
|
+
);
|
|
962
|
+
assert.match(
|
|
963
|
+
workerSource,
|
|
964
|
+
/imageGenerationModel \|\| null,\n\s*scopeAwareUserMessage/i,
|
|
965
|
+
'worker should pass the resolved raw user scope into direct agent execution'
|
|
966
|
+
);
|
|
952
967
|
assert.match(
|
|
953
968
|
openClawSource,
|
|
954
969
|
/persistDirectUiContext\(\);/i,
|
package/src/OpenClawCLI.js
CHANGED
|
@@ -4352,9 +4352,10 @@ export class OpenClawCLI extends EventEmitter {
|
|
|
4352
4352
|
'For local browser verification, use the URL or port proven by project code, server output, or an already successful browser result. Do not try arbitrary localhost ports such as 3000 or 5000 just because they are common defaults.',
|
|
4353
4353
|
'For git-backed projects with a remote, do not finish with intended changes only on disk. Stage the final intended changes, commit them, push to the configured upstream, and verify the resulting state unless the user explicitly asked not to. Do not create confirmation/status files just to prove the task is done.',
|
|
4354
4354
|
].join('\n');
|
|
4355
|
-
const
|
|
4356
|
-
const
|
|
4357
|
-
const
|
|
4355
|
+
const semanticTask = String(directOptions.rawUserTask || task || '');
|
|
4356
|
+
const taskRequiresFileChange = /\b(make|create|build|add|implement|update|edit|change|fix|improve|redesign|refactor|write|generate|scaffold|wire|ship|work on|delete|remove|drop|unpublish|decommission|take down|take offline)\b/i.test(semanticTask);
|
|
4357
|
+
const taskAllowsDeletedScopedPages = this._allowsDirectScopedPageSourcesToRemainDeleted(semanticTask);
|
|
4358
|
+
const taskRequiresVisualVerification = !taskAllowsDeletedScopedPages && /\b(ui|ux|visual|design|frontend|css|html|pages?|dashboard|website|web app|app screen|layout|component|responsive|professional|polish(?:ed)?|vibecoded|vibe-coded|interface|screen|arena|competitive|competition|scoreboard|ranking|visual hierarchy|user experience|design system|readability|readable|legibility|contrast|accessibility)\b/i.test(semanticTask);
|
|
4358
4359
|
const directRequestTimeoutMs = Math.max(
|
|
4359
4360
|
30_000,
|
|
4360
4361
|
Number(process.env.AGENTFORGE_DIRECT_LLM_REQUEST_TIMEOUT_MS || (taskRequiresVisualVerification ? 120_000 : 90_000))
|
|
@@ -4370,7 +4371,7 @@ export class OpenClawCLI extends EventEmitter {
|
|
|
4370
4371
|
let directMutationCount = 0;
|
|
4371
4372
|
let lastCleanLocalVerificationMutationCount = 0;
|
|
4372
4373
|
let lastDirectVisualWarning = '';
|
|
4373
|
-
const explicitScopeForTask = this._extractDirectExplicitScope(
|
|
4374
|
+
const explicitScopeForTask = this._extractDirectExplicitScope(semanticTask);
|
|
4374
4375
|
const explicitScopeSlugsForTask = explicitScopeForTask.slugs || [];
|
|
4375
4376
|
const taskRequiresComparableUiContext =
|
|
4376
4377
|
taskRequiresVisualVerification &&
|
|
@@ -4815,7 +4816,7 @@ export class OpenClawCLI extends EventEmitter {
|
|
|
4815
4816
|
});
|
|
4816
4817
|
const result = await this._runDirectTool(agentId, 'browser', { action: 'open', url }, workDir, {
|
|
4817
4818
|
signal: directAbortController.signal,
|
|
4818
|
-
task,
|
|
4819
|
+
task: semanticTask,
|
|
4819
4820
|
imageModel: directOptions.imageModel,
|
|
4820
4821
|
agentModel: directOptions.agentModel || model,
|
|
4821
4822
|
fallbackVisionModels: directOptions.fallbackVisionModels,
|
|
@@ -4856,7 +4857,7 @@ export class OpenClawCLI extends EventEmitter {
|
|
|
4856
4857
|
const match = text.match(/^URL:\s*(.+)$/mi);
|
|
4857
4858
|
const urlText = match?.[1]?.trim() || '';
|
|
4858
4859
|
if (!urlText) return false;
|
|
4859
|
-
const { slugs } = this._extractDirectExplicitScope(
|
|
4860
|
+
const { slugs } = this._extractDirectExplicitScope(semanticTask);
|
|
4860
4861
|
if (slugs.length > 0 && scopeSlugsMatchingText(urlText, slugs).length === 0) return false;
|
|
4861
4862
|
return /^(?:https?:\/\/(?:localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(?::\d+)?(?:\/|$)|file:)/i.test(urlText);
|
|
4862
4863
|
};
|
|
@@ -4868,7 +4869,7 @@ export class OpenClawCLI extends EventEmitter {
|
|
|
4868
4869
|
return warnings.join('\n').slice(0, 1200);
|
|
4869
4870
|
};
|
|
4870
4871
|
const directStopResponse = (reason, forceIncomplete = false) => {
|
|
4871
|
-
const pendingGitDelivery = this._directGitPendingDeliveryMessage(workDir,
|
|
4872
|
+
const pendingGitDelivery = this._directGitPendingDeliveryMessage(workDir, semanticTask, { directMutationCount, taskRequiresFileChange });
|
|
4872
4873
|
const noDeliverable = taskRequiresFileChange && directMutationCount === 0 && !pendingGitDelivery;
|
|
4873
4874
|
const missingScopedMutation = missingScopedMutationSlugs();
|
|
4874
4875
|
const missingVisualVerification = taskRequiresVisualVerification && directMutationCount > 0 && !hasCleanLocalVerificationForLatestMutation();
|
|
@@ -4955,7 +4956,7 @@ export class OpenClawCLI extends EventEmitter {
|
|
|
4955
4956
|
usedTools: directToolCount > 0,
|
|
4956
4957
|
};
|
|
4957
4958
|
}
|
|
4958
|
-
const delivery = this._directMaybeAutoDeliverGitChanges(workDir,
|
|
4959
|
+
const delivery = this._directMaybeAutoDeliverGitChanges(workDir, semanticTask, { directMutationCount, taskRequiresFileChange });
|
|
4959
4960
|
if (delivery.delivered) {
|
|
4960
4961
|
recordDirectToolSummary('git', delivery.message);
|
|
4961
4962
|
} else if (delivery.pending) {
|
|
@@ -4990,7 +4991,7 @@ export class OpenClawCLI extends EventEmitter {
|
|
|
4990
4991
|
return `I am checking the live browser${url} to judge the actual product surface before deciding the next change.`;
|
|
4991
4992
|
}
|
|
4992
4993
|
if (name === 'read_file' || name === 'read') {
|
|
4993
|
-
const scope = extractExplicitScope(
|
|
4994
|
+
const scope = extractExplicitScope(semanticTask);
|
|
4994
4995
|
const targetText = String(targetPath || base || '').toLowerCase();
|
|
4995
4996
|
const looksLikePageSource = /\.(html?|css|s[ac]ss|jsx?|tsx?|vue|svelte|astro|mdx?)$/i.test(targetText);
|
|
4996
4997
|
const isNamedTarget = scope.slugs.length > 0 && scopeSlugsMatchingText(targetText, scope.slugs).length > 0;
|
|
@@ -5073,7 +5074,7 @@ export class OpenClawCLI extends EventEmitter {
|
|
|
5073
5074
|
const text = parts.filter(p => p.text).map(p => p.text).join('');
|
|
5074
5075
|
if (!functionCalls.length) {
|
|
5075
5076
|
if (step > 0) {
|
|
5076
|
-
const pendingGitDelivery = this._directGitPendingDeliveryMessage(workDir,
|
|
5077
|
+
const pendingGitDelivery = this._directGitPendingDeliveryMessage(workDir, semanticTask, { directMutationCount, taskRequiresFileChange });
|
|
5077
5078
|
if (taskRequiresFileChange && directMutationCount === 0 && !pendingGitDelivery && directInternalNudgeCount < 2) {
|
|
5078
5079
|
directInternalNudgeCount += 1;
|
|
5079
5080
|
contents.push(content);
|
|
@@ -5215,7 +5216,7 @@ export class OpenClawCLI extends EventEmitter {
|
|
|
5215
5216
|
const fileWriteTarget = directFileWriteTargetPath(name, args);
|
|
5216
5217
|
if (fileWriteTarget) {
|
|
5217
5218
|
try {
|
|
5218
|
-
this._guardDirectFileWritePath(fileWriteTarget, workDir, { task });
|
|
5219
|
+
this._guardDirectFileWritePath(fileWriteTarget, workDir, { task: semanticTask });
|
|
5219
5220
|
} catch (err) {
|
|
5220
5221
|
if (err.code === 'AGENTFORGE_SCOPE_VIOLATION') {
|
|
5221
5222
|
directScopeViolationCount += 1;
|
|
@@ -5270,7 +5271,7 @@ export class OpenClawCLI extends EventEmitter {
|
|
|
5270
5271
|
responses.push({ functionResponse: { name, response: { error: message } } });
|
|
5271
5272
|
continue;
|
|
5272
5273
|
}
|
|
5273
|
-
const dirtyDeliveryMessage = this._directGitDirtyDeliveryMessage(workDir,
|
|
5274
|
+
const dirtyDeliveryMessage = this._directGitDirtyDeliveryMessage(workDir, semanticTask, command);
|
|
5274
5275
|
if (/\bgit\b[\s\S]*\b(?:commit|push)\b/i.test(command) && dirtyDeliveryMessage) {
|
|
5275
5276
|
emitDirectThought('AgentForge blocked commit/push because the staged delivery does not match the final working tree.');
|
|
5276
5277
|
this.emit('tool_activity', {
|
|
@@ -5295,7 +5296,7 @@ export class OpenClawCLI extends EventEmitter {
|
|
|
5295
5296
|
try {
|
|
5296
5297
|
const result = await this._runDirectTool(agentId, name, args, workDir, {
|
|
5297
5298
|
signal: directAbortController.signal,
|
|
5298
|
-
task,
|
|
5299
|
+
task: semanticTask,
|
|
5299
5300
|
imageModel: directOptions.imageModel,
|
|
5300
5301
|
agentModel: directOptions.agentModel || model,
|
|
5301
5302
|
fallbackVisionModels: directOptions.fallbackVisionModels,
|
|
@@ -5701,7 +5702,7 @@ export class OpenClawCLI extends EventEmitter {
|
|
|
5701
5702
|
* Run an agent task
|
|
5702
5703
|
* Images are saved to workspace and referenced in message for vision model analysis
|
|
5703
5704
|
*/
|
|
5704
|
-
async runAgentTask(agentId, task, workDir, sessionId = null, image = null, browserProfile = null, imageWorkDir = null, agentModel = null, customSystemPrompt = null, conversationHistory = null, allImages = null, providerKeys = null, imageModel = null, taskId = null, iteration = 1, fallbackVisionModels = null, imageGenerationModel = null) {
|
|
5705
|
+
async runAgentTask(agentId, task, workDir, sessionId = null, image = null, browserProfile = null, imageWorkDir = null, agentModel = null, customSystemPrompt = null, conversationHistory = null, allImages = null, providerKeys = null, imageModel = null, taskId = null, iteration = 1, fallbackVisionModels = null, imageGenerationModel = null, rawUserTask = null) {
|
|
5705
5706
|
// Gateway auth comes from per-agent auth-profiles.json, not subprocess env.
|
|
5706
5707
|
// Seed real Anthropic API keys up front so anthropic/* models do not fall back
|
|
5707
5708
|
// to Claude account/OAuth tokens and fail with claude.ai "extra usage" limits.
|
|
@@ -5840,10 +5841,10 @@ export class OpenClawCLI extends EventEmitter {
|
|
|
5840
5841
|
// OpenClaw subprocess after a model compatibility fallback.
|
|
5841
5842
|
// If LLM answers with plain text → done in ~1-3s.
|
|
5842
5843
|
// If LLM returns tool calls → fall through to gateway/subprocess as usual.
|
|
5843
|
-
const
|
|
5844
|
-
const directTaskRequiresFileChange = /\b(make|create|build|add|implement|update|edit|change|fix|improve|redesign|refactor|write|generate|scaffold|wire|ship|work on)\b/i.test(
|
|
5844
|
+
const directSemanticTaskText = String(rawUserTask || task || taskForRuntime || '');
|
|
5845
|
+
const directTaskRequiresFileChange = /\b(make|create|build|add|implement|update|edit|change|fix|improve|redesign|refactor|write|generate|scaffold|wire|ship|work on)\b/i.test(directSemanticTaskText);
|
|
5845
5846
|
const directTaskRequiresVisualImplementation = directTaskRequiresFileChange &&
|
|
5846
|
-
/\b(ui|ux|visual|design|frontend|css|html|pages?|dashboard|website|web app|app screen|layout|component|responsive|professional|polish(?:ed)?|vibecoded|vibe-coded|interface|screen|visual hierarchy|user experience|design system)\b/i.test(
|
|
5847
|
+
/\b(ui|ux|visual|design|frontend|css|html|pages?|dashboard|website|web app|app screen|layout|component|responsive|professional|polish(?:ed)?|vibecoded|vibe-coded|interface|screen|visual hierarchy|user experience|design system)\b/i.test(directSemanticTaskText);
|
|
5847
5848
|
const forceSubprocessForVisual = /^(1|true|yes)$/i.test(process.env.AGENTFORGE_FORCE_OPENCLAW_VISUAL || '');
|
|
5848
5849
|
const skipDirectFastPath = directTaskRequiresVisualImplementation && forceSubprocessForVisual;
|
|
5849
5850
|
if (skipDirectFastPath && agentModel) {
|
|
@@ -5858,6 +5859,7 @@ export class OpenClawCLI extends EventEmitter {
|
|
|
5858
5859
|
fallbackVisionModels,
|
|
5859
5860
|
taskId,
|
|
5860
5861
|
iteration,
|
|
5862
|
+
rawUserTask: rawUserTask || task,
|
|
5861
5863
|
});
|
|
5862
5864
|
if (fastResult !== null) {
|
|
5863
5865
|
if (fastResult.hasToolCalls) {
|
package/src/worker.js
CHANGED
|
@@ -3768,7 +3768,8 @@ export class AgentForgeWorker extends EventEmitter {
|
|
|
3768
3768
|
providerKeys || null, effectiveImageModel || null,
|
|
3769
3769
|
taskId, iteration,
|
|
3770
3770
|
effectiveFallbackVisionModels,
|
|
3771
|
-
imageGenerationModel || null
|
|
3771
|
+
imageGenerationModel || null,
|
|
3772
|
+
scopeAwareUserMessage
|
|
3772
3773
|
);
|
|
3773
3774
|
runtimeStallRetryCount = 0;
|
|
3774
3775
|
} catch (runError) {
|