@hamp10/agentforge 0.2.42 → 0.2.43

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hamp10/agentforge",
3
- "version": "0.2.42",
3
+ "version": "0.2.43",
4
4
  "description": "AgentForge worker — connect your machine to agentforge.ai",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1064,6 +1064,21 @@ assert.match(
1064
1064
  /isHttpUiReferenceUrl/i,
1065
1065
  'comparable UI visual context should allow same-site non-target reference pages, not only localhost'
1066
1066
  );
1067
+ assert.match(
1068
+ openClawSource,
1069
+ /browser verification used a file:\/\/ URL/i,
1070
+ 'scoped UI verification should reject file:// after edits because it can bypass local server behavior'
1071
+ );
1072
+ assert.doesNotMatch(
1073
+ openClawSource,
1074
+ /localhost\/127\.0\.0\.1 or file:\/\//i,
1075
+ 'post-edit scoped UI verification should require localhost/127.0.0.1 instead of file://'
1076
+ );
1077
+ assert.doesNotMatch(
1078
+ openClawSource,
1079
+ /pathToFileURL/i,
1080
+ 'auto-verification should not fall back to file:// URLs for edited scoped pages'
1081
+ );
1067
1082
  assert.match(
1068
1083
  openClawSource,
1069
1084
  /scopeViolationThisBatch \|\| comparableContextBlockThisBatch\) break/i,
@@ -3,7 +3,6 @@ import { mkdirSync, writeFileSync, readFileSync, existsSync, readdirSync, unlink
3
3
  import { EventEmitter } from 'events';
4
4
  import { homedir } from 'os';
5
5
  import path from 'path';
6
- import { pathToFileURL } from 'url';
7
6
  import { inflateSync } from 'zlib';
8
7
  import { resolveOpenclawBin } from './resolveOpenclaw.js';
9
8
  import {
@@ -4159,11 +4158,20 @@ export class OpenClawCLI extends EventEmitter {
4159
4158
  summary.text ? `Visible text:\n${summary.text}` : '',
4160
4159
  ].filter(Boolean).join('\n');
4161
4160
  }
4162
- const isLocalVerificationUrl = /^(?:https?:\/\/(?:localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(?::\d+)?(?:\/|$)|file:)/i.test(summaryUrl || requestedUrl || '');
4161
+ const isFileVerificationUrl = /^file:/i.test(summaryUrl || requestedUrl || '');
4162
+ const isLocalVerificationUrl = /^(?:https?:\/\/(?:localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(?::\d+)?(?:\/|$))/i.test(summaryUrl || requestedUrl || '');
4163
+ if (options?.afterMutation && isScopedBrowserTarget && isFileVerificationUrl) {
4164
+ return [
4165
+ `Visual warning: browser verification used a file:// URL (${summaryUrl || requestedUrl || '(current tab)'}) after local file edits.`,
4166
+ 'File URLs can skip the project server, component includes, routing, assets, and browser permissions that real users get. Start or use the local dev/static server and verify the changed target screen on localhost or 127.0.0.1.',
4167
+ `URL: ${summary.url || requestedUrl || '(current tab)'}`,
4168
+ summary.text ? `Visible text:\n${summary.text}` : '',
4169
+ ].filter(Boolean).join('\n');
4170
+ }
4163
4171
  if (options?.afterMutation && isScopedBrowserTarget && !isLocalVerificationUrl) {
4164
4172
  return [
4165
4173
  `Visual warning: browser verification used a remote URL (${summaryUrl || requestedUrl || '(current tab)'}) after local file edits.`,
4166
- 'Remote pages do not prove the edited local files render correctly before commit/push. Start or use the local preview server and verify the changed target screen on localhost, 127.0.0.1, or file://.',
4174
+ 'Remote pages do not prove the edited local files render correctly before commit/push. Start or use the local preview server and verify the changed target screen on localhost or 127.0.0.1.',
4167
4175
  `URL: ${summary.url || requestedUrl || '(current tab)'}`,
4168
4176
  summary.text ? `Visible text:\n${summary.text}` : '',
4169
4177
  ].filter(Boolean).join('\n');
@@ -4940,7 +4948,7 @@ export class OpenClawCLI extends EventEmitter {
4940
4948
  }
4941
4949
  };
4942
4950
  const isLocalUiUrl = (url) =>
4943
- /^(?:https?:\/\/(?:localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(?::\d+)?(?:\/|$)|file:)/i.test(String(url || ''));
4951
+ /^(?:https?:\/\/(?:localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(?::\d+)?(?:\/|$))/i.test(String(url || ''));
4944
4952
  const isHttpUiReferenceUrl = (url) => {
4945
4953
  try {
4946
4954
  const parsed = new URL(String(url || ''));
@@ -5021,7 +5029,7 @@ export class OpenClawCLI extends EventEmitter {
5021
5029
  const inferredText = inferred.length > 0
5022
5030
  ? ` Suggested local target URL(s): ${inferred.map(item => `${item.slug} -> ${item.url}`).join('; ')}.`
5023
5031
  : '';
5024
- return `Missing clean local browser verification for edited scoped target(s): ${missing.join(', ')}. Each edited scoped page must be opened on localhost/127.0.0.1 or file:// after its latest edit.${inferredText} Do not use a site index, listing index, shared style file, or reference page as final verification for a scoped page edit.`;
5032
+ return `Missing clean local browser verification for edited scoped target(s): ${missing.join(', ')}. Each edited scoped page must be opened on localhost/127.0.0.1 after its latest edit.${inferredText} Do not use a site index, listing index, shared style file, or reference page as final verification for a scoped page edit.`;
5025
5033
  };
5026
5034
  const inferLocalUrlForScope = (slug) => {
5027
5035
  if (directLocalUrlsByScope.has(slug)) return directLocalUrlsByScope.get(slug);
@@ -5032,10 +5040,6 @@ export class OpenClawCLI extends EventEmitter {
5032
5040
  }
5033
5041
  }
5034
5042
  }
5035
- const mutationFile = directScopeLastMutationFiles.get(slug);
5036
- if (mutationFile && this._isDirectPageSourcePath(mutationFile) && existsSync(mutationFile)) {
5037
- return pathToFileURL(mutationFile).href;
5038
- }
5039
5043
  return '';
5040
5044
  };
5041
5045
  const autoVerifyMissingScopedTargets = async () => {
@@ -5098,7 +5102,7 @@ export class OpenClawCLI extends EventEmitter {
5098
5102
  if (!urlText) return false;
5099
5103
  const { slugs } = this._extractDirectExplicitScope(semanticTask);
5100
5104
  if (slugs.length > 0 && scopeSlugsMatchingText(urlText, slugs).length === 0) return false;
5101
- return /^(?:https?:\/\/(?:localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(?::\d+)?(?:\/|$)|file:)/i.test(urlText);
5105
+ return /^(?:https?:\/\/(?:localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(?::\d+)?(?:\/|$))/i.test(urlText);
5102
5106
  };
5103
5107
  const extractVisualWarning = (result) => {
5104
5108
  const warnings = String(result || '')