onbuzz 3.3.0
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/LICENSE +267 -0
- package/README.md +425 -0
- package/bin/cli.js +556 -0
- package/bin/loxia-terminal-v2.js +162 -0
- package/bin/loxia-terminal.js +90 -0
- package/bin/start-with-terminal.js +200 -0
- package/node_modules/@isaacs/balanced-match/LICENSE.md +23 -0
- package/node_modules/@isaacs/balanced-match/README.md +60 -0
- package/node_modules/@isaacs/balanced-match/dist/commonjs/index.d.ts +9 -0
- package/node_modules/@isaacs/balanced-match/dist/commonjs/index.d.ts.map +1 -0
- package/node_modules/@isaacs/balanced-match/dist/commonjs/index.js +59 -0
- package/node_modules/@isaacs/balanced-match/dist/commonjs/index.js.map +1 -0
- package/node_modules/@isaacs/balanced-match/dist/commonjs/package.json +3 -0
- package/node_modules/@isaacs/balanced-match/dist/esm/index.d.ts +9 -0
- package/node_modules/@isaacs/balanced-match/dist/esm/index.d.ts.map +1 -0
- package/node_modules/@isaacs/balanced-match/dist/esm/index.js +54 -0
- package/node_modules/@isaacs/balanced-match/dist/esm/index.js.map +1 -0
- package/node_modules/@isaacs/balanced-match/dist/esm/package.json +3 -0
- package/node_modules/@isaacs/balanced-match/package.json +79 -0
- package/node_modules/@isaacs/brace-expansion/LICENSE +23 -0
- package/node_modules/@isaacs/brace-expansion/README.md +97 -0
- package/node_modules/@isaacs/brace-expansion/dist/commonjs/index.d.ts +6 -0
- package/node_modules/@isaacs/brace-expansion/dist/commonjs/index.d.ts.map +1 -0
- package/node_modules/@isaacs/brace-expansion/dist/commonjs/index.js +199 -0
- package/node_modules/@isaacs/brace-expansion/dist/commonjs/index.js.map +1 -0
- package/node_modules/@isaacs/brace-expansion/dist/commonjs/package.json +3 -0
- package/node_modules/@isaacs/brace-expansion/dist/esm/index.d.ts +6 -0
- package/node_modules/@isaacs/brace-expansion/dist/esm/index.d.ts.map +1 -0
- package/node_modules/@isaacs/brace-expansion/dist/esm/index.js +195 -0
- package/node_modules/@isaacs/brace-expansion/dist/esm/index.js.map +1 -0
- package/node_modules/@isaacs/brace-expansion/dist/esm/package.json +3 -0
- package/node_modules/@isaacs/brace-expansion/package.json +60 -0
- package/node_modules/glob/LICENSE.md +63 -0
- package/node_modules/glob/README.md +1177 -0
- package/node_modules/glob/dist/commonjs/glob.d.ts +388 -0
- package/node_modules/glob/dist/commonjs/glob.d.ts.map +1 -0
- package/node_modules/glob/dist/commonjs/glob.js +247 -0
- package/node_modules/glob/dist/commonjs/glob.js.map +1 -0
- package/node_modules/glob/dist/commonjs/has-magic.d.ts +14 -0
- package/node_modules/glob/dist/commonjs/has-magic.d.ts.map +1 -0
- package/node_modules/glob/dist/commonjs/has-magic.js +27 -0
- package/node_modules/glob/dist/commonjs/has-magic.js.map +1 -0
- package/node_modules/glob/dist/commonjs/ignore.d.ts +24 -0
- package/node_modules/glob/dist/commonjs/ignore.d.ts.map +1 -0
- package/node_modules/glob/dist/commonjs/ignore.js +119 -0
- package/node_modules/glob/dist/commonjs/ignore.js.map +1 -0
- package/node_modules/glob/dist/commonjs/index.d.ts +97 -0
- package/node_modules/glob/dist/commonjs/index.d.ts.map +1 -0
- package/node_modules/glob/dist/commonjs/index.js +68 -0
- package/node_modules/glob/dist/commonjs/index.js.map +1 -0
- package/node_modules/glob/dist/commonjs/index.min.js +4 -0
- package/node_modules/glob/dist/commonjs/index.min.js.map +7 -0
- package/node_modules/glob/dist/commonjs/package.json +3 -0
- package/node_modules/glob/dist/commonjs/pattern.d.ts +76 -0
- package/node_modules/glob/dist/commonjs/pattern.d.ts.map +1 -0
- package/node_modules/glob/dist/commonjs/pattern.js +219 -0
- package/node_modules/glob/dist/commonjs/pattern.js.map +1 -0
- package/node_modules/glob/dist/commonjs/processor.d.ts +59 -0
- package/node_modules/glob/dist/commonjs/processor.d.ts.map +1 -0
- package/node_modules/glob/dist/commonjs/processor.js +301 -0
- package/node_modules/glob/dist/commonjs/processor.js.map +1 -0
- package/node_modules/glob/dist/commonjs/walker.d.ts +97 -0
- package/node_modules/glob/dist/commonjs/walker.d.ts.map +1 -0
- package/node_modules/glob/dist/commonjs/walker.js +387 -0
- package/node_modules/glob/dist/commonjs/walker.js.map +1 -0
- package/node_modules/glob/dist/esm/glob.d.ts +388 -0
- package/node_modules/glob/dist/esm/glob.d.ts.map +1 -0
- package/node_modules/glob/dist/esm/glob.js +243 -0
- package/node_modules/glob/dist/esm/glob.js.map +1 -0
- package/node_modules/glob/dist/esm/has-magic.d.ts +14 -0
- package/node_modules/glob/dist/esm/has-magic.d.ts.map +1 -0
- package/node_modules/glob/dist/esm/has-magic.js +23 -0
- package/node_modules/glob/dist/esm/has-magic.js.map +1 -0
- package/node_modules/glob/dist/esm/ignore.d.ts +24 -0
- package/node_modules/glob/dist/esm/ignore.d.ts.map +1 -0
- package/node_modules/glob/dist/esm/ignore.js +115 -0
- package/node_modules/glob/dist/esm/ignore.js.map +1 -0
- package/node_modules/glob/dist/esm/index.d.ts +97 -0
- package/node_modules/glob/dist/esm/index.d.ts.map +1 -0
- package/node_modules/glob/dist/esm/index.js +55 -0
- package/node_modules/glob/dist/esm/index.js.map +1 -0
- package/node_modules/glob/dist/esm/index.min.js +4 -0
- package/node_modules/glob/dist/esm/index.min.js.map +7 -0
- package/node_modules/glob/dist/esm/package.json +3 -0
- package/node_modules/glob/dist/esm/pattern.d.ts +76 -0
- package/node_modules/glob/dist/esm/pattern.d.ts.map +1 -0
- package/node_modules/glob/dist/esm/pattern.js +215 -0
- package/node_modules/glob/dist/esm/pattern.js.map +1 -0
- package/node_modules/glob/dist/esm/processor.d.ts +59 -0
- package/node_modules/glob/dist/esm/processor.d.ts.map +1 -0
- package/node_modules/glob/dist/esm/processor.js +294 -0
- package/node_modules/glob/dist/esm/processor.js.map +1 -0
- package/node_modules/glob/dist/esm/walker.d.ts +97 -0
- package/node_modules/glob/dist/esm/walker.d.ts.map +1 -0
- package/node_modules/glob/dist/esm/walker.js +381 -0
- package/node_modules/glob/dist/esm/walker.js.map +1 -0
- package/node_modules/glob/node_modules/minimatch/LICENSE.md +55 -0
- package/node_modules/glob/node_modules/minimatch/README.md +453 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts +2 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.js +14 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.js.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.d.ts +20 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.d.ts.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.js +591 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.js.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts +8 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.js +152 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.js.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.d.ts +15 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.d.ts.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.js +30 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.js.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.d.ts +94 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.d.ts.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.js +1029 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.js.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/package.json +3 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.d.ts +22 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.d.ts.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.js +38 -0
- package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.js.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts +2 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.js +10 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.js.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/ast.d.ts +20 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/ast.d.ts.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/ast.js +587 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/ast.js.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.d.ts +8 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.d.ts.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.js +148 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.js.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/escape.d.ts +15 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/escape.d.ts.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/escape.js +26 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/escape.js.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/index.d.ts +94 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/index.d.ts.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/index.js +1016 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/index.js.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/package.json +3 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.d.ts +22 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.d.ts.map +1 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.js +34 -0
- package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.js.map +1 -0
- package/node_modules/glob/node_modules/minimatch/package.json +67 -0
- package/node_modules/glob/package.json +101 -0
- package/node_modules/minipass/LICENSE +15 -0
- package/node_modules/minipass/README.md +825 -0
- package/node_modules/minipass/dist/commonjs/index.d.ts +549 -0
- package/node_modules/minipass/dist/commonjs/index.d.ts.map +1 -0
- package/node_modules/minipass/dist/commonjs/index.js +1028 -0
- package/node_modules/minipass/dist/commonjs/index.js.map +1 -0
- package/node_modules/minipass/dist/commonjs/package.json +3 -0
- package/node_modules/minipass/dist/esm/index.d.ts +549 -0
- package/node_modules/minipass/dist/esm/index.d.ts.map +1 -0
- package/node_modules/minipass/dist/esm/index.js +1018 -0
- package/node_modules/minipass/dist/esm/index.js.map +1 -0
- package/node_modules/minipass/dist/esm/package.json +3 -0
- package/node_modules/minipass/package.json +82 -0
- package/node_modules/package-json-from-dist/LICENSE.md +63 -0
- package/node_modules/package-json-from-dist/README.md +110 -0
- package/node_modules/package-json-from-dist/dist/commonjs/index.d.ts +89 -0
- package/node_modules/package-json-from-dist/dist/commonjs/index.d.ts.map +1 -0
- package/node_modules/package-json-from-dist/dist/commonjs/index.js +134 -0
- package/node_modules/package-json-from-dist/dist/commonjs/index.js.map +1 -0
- package/node_modules/package-json-from-dist/dist/commonjs/package.json +3 -0
- package/node_modules/package-json-from-dist/dist/esm/index.d.ts +89 -0
- package/node_modules/package-json-from-dist/dist/esm/index.d.ts.map +1 -0
- package/node_modules/package-json-from-dist/dist/esm/index.js +129 -0
- package/node_modules/package-json-from-dist/dist/esm/index.js.map +1 -0
- package/node_modules/package-json-from-dist/dist/esm/package.json +3 -0
- package/node_modules/package-json-from-dist/package.json +68 -0
- package/node_modules/path-scurry/LICENSE.md +55 -0
- package/node_modules/path-scurry/README.md +636 -0
- package/node_modules/path-scurry/dist/commonjs/index.d.ts +1115 -0
- package/node_modules/path-scurry/dist/commonjs/index.d.ts.map +1 -0
- package/node_modules/path-scurry/dist/commonjs/index.js +2018 -0
- package/node_modules/path-scurry/dist/commonjs/index.js.map +1 -0
- package/node_modules/path-scurry/dist/commonjs/package.json +3 -0
- package/node_modules/path-scurry/dist/esm/index.d.ts +1115 -0
- package/node_modules/path-scurry/dist/esm/index.d.ts.map +1 -0
- package/node_modules/path-scurry/dist/esm/index.js +1983 -0
- package/node_modules/path-scurry/dist/esm/index.js.map +1 -0
- package/node_modules/path-scurry/dist/esm/package.json +3 -0
- package/node_modules/path-scurry/node_modules/lru-cache/LICENSE.md +55 -0
- package/node_modules/path-scurry/node_modules/lru-cache/README.md +383 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.d.ts +1323 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.js +1589 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.min.js +2 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.min.js.map +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/package.json +3 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.d.ts +1323 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.d.ts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js +1585 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.min.js +2 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.min.js.map +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/package.json +3 -0
- package/node_modules/path-scurry/node_modules/lru-cache/package.json +101 -0
- package/node_modules/path-scurry/package.json +88 -0
- package/node_modules/rimraf/LICENSE.md +55 -0
- package/node_modules/rimraf/README.md +226 -0
- package/node_modules/rimraf/dist/commonjs/default-tmp.d.ts +3 -0
- package/node_modules/rimraf/dist/commonjs/default-tmp.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/default-tmp.js +58 -0
- package/node_modules/rimraf/dist/commonjs/default-tmp.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/error.d.ts +6 -0
- package/node_modules/rimraf/dist/commonjs/error.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/error.js +10 -0
- package/node_modules/rimraf/dist/commonjs/error.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/fix-eperm.d.ts +3 -0
- package/node_modules/rimraf/dist/commonjs/fix-eperm.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/fix-eperm.js +38 -0
- package/node_modules/rimraf/dist/commonjs/fix-eperm.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/fs.d.ts +15 -0
- package/node_modules/rimraf/dist/commonjs/fs.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/fs.js +33 -0
- package/node_modules/rimraf/dist/commonjs/fs.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/ignore-enoent.d.ts +3 -0
- package/node_modules/rimraf/dist/commonjs/ignore-enoent.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/ignore-enoent.js +24 -0
- package/node_modules/rimraf/dist/commonjs/ignore-enoent.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/index.d.ts +50 -0
- package/node_modules/rimraf/dist/commonjs/index.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/index.js +78 -0
- package/node_modules/rimraf/dist/commonjs/index.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/opt-arg.d.ts +34 -0
- package/node_modules/rimraf/dist/commonjs/opt-arg.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/opt-arg.js +53 -0
- package/node_modules/rimraf/dist/commonjs/opt-arg.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/package.json +3 -0
- package/node_modules/rimraf/dist/commonjs/path-arg.d.ts +4 -0
- package/node_modules/rimraf/dist/commonjs/path-arg.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/path-arg.js +48 -0
- package/node_modules/rimraf/dist/commonjs/path-arg.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/readdir-or-error.d.ts +3 -0
- package/node_modules/rimraf/dist/commonjs/readdir-or-error.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/readdir-or-error.js +19 -0
- package/node_modules/rimraf/dist/commonjs/readdir-or-error.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/retry-busy.d.ts +8 -0
- package/node_modules/rimraf/dist/commonjs/retry-busy.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/retry-busy.js +65 -0
- package/node_modules/rimraf/dist/commonjs/retry-busy.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-manual.d.ts +3 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-manual.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-manual.js +8 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-manual.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-move-remove.d.ts +4 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-move-remove.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-move-remove.js +138 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-move-remove.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-native.d.ts +4 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-native.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-native.js +24 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-native.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-posix.d.ts +4 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-posix.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-posix.js +103 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-posix.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-windows.d.ts +4 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-windows.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-windows.js +159 -0
- package/node_modules/rimraf/dist/commonjs/rimraf-windows.js.map +1 -0
- package/node_modules/rimraf/dist/commonjs/use-native.d.ts +4 -0
- package/node_modules/rimraf/dist/commonjs/use-native.d.ts.map +1 -0
- package/node_modules/rimraf/dist/commonjs/use-native.js +18 -0
- package/node_modules/rimraf/dist/commonjs/use-native.js.map +1 -0
- package/node_modules/rimraf/dist/esm/bin.d.mts +3 -0
- package/node_modules/rimraf/dist/esm/bin.d.mts.map +1 -0
- package/node_modules/rimraf/dist/esm/bin.mjs +250 -0
- package/node_modules/rimraf/dist/esm/bin.mjs.map +1 -0
- package/node_modules/rimraf/dist/esm/default-tmp.d.ts +3 -0
- package/node_modules/rimraf/dist/esm/default-tmp.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/default-tmp.js +55 -0
- package/node_modules/rimraf/dist/esm/default-tmp.js.map +1 -0
- package/node_modules/rimraf/dist/esm/error.d.ts +6 -0
- package/node_modules/rimraf/dist/esm/error.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/error.js +5 -0
- package/node_modules/rimraf/dist/esm/error.js.map +1 -0
- package/node_modules/rimraf/dist/esm/fix-eperm.d.ts +3 -0
- package/node_modules/rimraf/dist/esm/fix-eperm.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/fix-eperm.js +33 -0
- package/node_modules/rimraf/dist/esm/fix-eperm.js.map +1 -0
- package/node_modules/rimraf/dist/esm/fs.d.ts +15 -0
- package/node_modules/rimraf/dist/esm/fs.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/fs.js +18 -0
- package/node_modules/rimraf/dist/esm/fs.js.map +1 -0
- package/node_modules/rimraf/dist/esm/ignore-enoent.d.ts +3 -0
- package/node_modules/rimraf/dist/esm/ignore-enoent.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/ignore-enoent.js +19 -0
- package/node_modules/rimraf/dist/esm/ignore-enoent.js.map +1 -0
- package/node_modules/rimraf/dist/esm/index.d.ts +50 -0
- package/node_modules/rimraf/dist/esm/index.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/index.js +70 -0
- package/node_modules/rimraf/dist/esm/index.js.map +1 -0
- package/node_modules/rimraf/dist/esm/opt-arg.d.ts +34 -0
- package/node_modules/rimraf/dist/esm/opt-arg.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/opt-arg.js +46 -0
- package/node_modules/rimraf/dist/esm/opt-arg.js.map +1 -0
- package/node_modules/rimraf/dist/esm/package.json +3 -0
- package/node_modules/rimraf/dist/esm/path-arg.d.ts +4 -0
- package/node_modules/rimraf/dist/esm/path-arg.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/path-arg.js +46 -0
- package/node_modules/rimraf/dist/esm/path-arg.js.map +1 -0
- package/node_modules/rimraf/dist/esm/readdir-or-error.d.ts +3 -0
- package/node_modules/rimraf/dist/esm/readdir-or-error.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/readdir-or-error.js +14 -0
- package/node_modules/rimraf/dist/esm/readdir-or-error.js.map +1 -0
- package/node_modules/rimraf/dist/esm/retry-busy.d.ts +8 -0
- package/node_modules/rimraf/dist/esm/retry-busy.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/retry-busy.js +60 -0
- package/node_modules/rimraf/dist/esm/retry-busy.js.map +1 -0
- package/node_modules/rimraf/dist/esm/rimraf-manual.d.ts +3 -0
- package/node_modules/rimraf/dist/esm/rimraf-manual.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/rimraf-manual.js +5 -0
- package/node_modules/rimraf/dist/esm/rimraf-manual.js.map +1 -0
- package/node_modules/rimraf/dist/esm/rimraf-move-remove.d.ts +4 -0
- package/node_modules/rimraf/dist/esm/rimraf-move-remove.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/rimraf-move-remove.js +133 -0
- package/node_modules/rimraf/dist/esm/rimraf-move-remove.js.map +1 -0
- package/node_modules/rimraf/dist/esm/rimraf-native.d.ts +4 -0
- package/node_modules/rimraf/dist/esm/rimraf-native.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/rimraf-native.js +19 -0
- package/node_modules/rimraf/dist/esm/rimraf-native.js.map +1 -0
- package/node_modules/rimraf/dist/esm/rimraf-posix.d.ts +4 -0
- package/node_modules/rimraf/dist/esm/rimraf-posix.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/rimraf-posix.js +98 -0
- package/node_modules/rimraf/dist/esm/rimraf-posix.js.map +1 -0
- package/node_modules/rimraf/dist/esm/rimraf-windows.d.ts +4 -0
- package/node_modules/rimraf/dist/esm/rimraf-windows.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/rimraf-windows.js +154 -0
- package/node_modules/rimraf/dist/esm/rimraf-windows.js.map +1 -0
- package/node_modules/rimraf/dist/esm/use-native.d.ts +4 -0
- package/node_modules/rimraf/dist/esm/use-native.d.ts.map +1 -0
- package/node_modules/rimraf/dist/esm/use-native.js +15 -0
- package/node_modules/rimraf/dist/esm/use-native.js.map +1 -0
- package/node_modules/rimraf/package.json +92 -0
- package/package.json +152 -0
- package/scripts/install-scanners.js +258 -0
- package/scripts/watchdog.js +147 -0
- package/src/analyzers/CSSAnalyzer.js +297 -0
- package/src/analyzers/ConfigValidator.js +690 -0
- package/src/analyzers/ESLintAnalyzer.js +320 -0
- package/src/analyzers/JavaScriptAnalyzer.js +261 -0
- package/src/analyzers/PrettierFormatter.js +247 -0
- package/src/analyzers/PythonAnalyzer.js +283 -0
- package/src/analyzers/SecurityAnalyzer.js +729 -0
- package/src/analyzers/SparrowAnalyzer.js +341 -0
- package/src/analyzers/TypeScriptAnalyzer.js +247 -0
- package/src/analyzers/codeCloneDetector/analyzer.js +344 -0
- package/src/analyzers/codeCloneDetector/detector.js +250 -0
- package/src/analyzers/codeCloneDetector/index.js +192 -0
- package/src/analyzers/codeCloneDetector/parser.js +199 -0
- package/src/analyzers/codeCloneDetector/reporter.js +148 -0
- package/src/analyzers/codeCloneDetector/scanner.js +88 -0
- package/src/core/agentPool.js +1957 -0
- package/src/core/agentScheduler.js +3212 -0
- package/src/core/contextManager.js +709 -0
- package/src/core/flowExecutor.js +928 -0
- package/src/core/messageProcessor.js +808 -0
- package/src/core/orchestrator.js +584 -0
- package/src/core/stateManager.js +1500 -0
- package/src/index.js +972 -0
- package/src/interfaces/cli.js +553 -0
- package/src/interfaces/terminal/__tests__/smoke/advancedFeatures.test.js +208 -0
- package/src/interfaces/terminal/__tests__/smoke/agentControl.test.js +236 -0
- package/src/interfaces/terminal/__tests__/smoke/agents.test.js +138 -0
- package/src/interfaces/terminal/__tests__/smoke/components.test.js +137 -0
- package/src/interfaces/terminal/__tests__/smoke/connection.test.js +350 -0
- package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +156 -0
- package/src/interfaces/terminal/__tests__/smoke/imports.test.js +332 -0
- package/src/interfaces/terminal/__tests__/smoke/messages.test.js +256 -0
- package/src/interfaces/terminal/__tests__/smoke/tools.test.js +388 -0
- package/src/interfaces/terminal/api/apiClient.js +299 -0
- package/src/interfaces/terminal/api/messageRouter.js +262 -0
- package/src/interfaces/terminal/api/session.js +266 -0
- package/src/interfaces/terminal/api/websocket.js +497 -0
- package/src/interfaces/terminal/components/AgentCreator.js +705 -0
- package/src/interfaces/terminal/components/AgentEditor.js +678 -0
- package/src/interfaces/terminal/components/AgentSwitcher.js +330 -0
- package/src/interfaces/terminal/components/ErrorBoundary.js +92 -0
- package/src/interfaces/terminal/components/ErrorPanel.js +264 -0
- package/src/interfaces/terminal/components/Header.js +28 -0
- package/src/interfaces/terminal/components/HelpPanel.js +231 -0
- package/src/interfaces/terminal/components/InputBox.js +118 -0
- package/src/interfaces/terminal/components/Layout.js +603 -0
- package/src/interfaces/terminal/components/LoadingSpinner.js +71 -0
- package/src/interfaces/terminal/components/MessageList.js +281 -0
- package/src/interfaces/terminal/components/MultilineTextInput.js +251 -0
- package/src/interfaces/terminal/components/SearchPanel.js +265 -0
- package/src/interfaces/terminal/components/SettingsPanel.js +415 -0
- package/src/interfaces/terminal/components/StatusBar.js +65 -0
- package/src/interfaces/terminal/components/TextInput.js +127 -0
- package/src/interfaces/terminal/config/agentEditorConstants.js +227 -0
- package/src/interfaces/terminal/config/constants.js +393 -0
- package/src/interfaces/terminal/index.js +168 -0
- package/src/interfaces/terminal/state/useAgentControl.js +496 -0
- package/src/interfaces/terminal/state/useAgents.js +537 -0
- package/src/interfaces/terminal/state/useConnection.js +444 -0
- package/src/interfaces/terminal/state/useMessages.js +630 -0
- package/src/interfaces/terminal/state/useTools.js +554 -0
- package/src/interfaces/terminal/utils/debugLogger.js +44 -0
- package/src/interfaces/terminal/utils/settingsStorage.js +232 -0
- package/src/interfaces/terminal/utils/theme.js +85 -0
- package/src/interfaces/webServer.js +5457 -0
- package/src/modules/fileExplorer/controller.js +413 -0
- package/src/modules/fileExplorer/index.js +37 -0
- package/src/modules/fileExplorer/middleware.js +92 -0
- package/src/modules/fileExplorer/routes.js +158 -0
- package/src/modules/fileExplorer/types.js +44 -0
- package/src/services/agentActivityService.js +399 -0
- package/src/services/aiService.js +2618 -0
- package/src/services/apiKeyManager.js +334 -0
- package/src/services/benchmarkService.js +196 -0
- package/src/services/budgetService.js +565 -0
- package/src/services/contextInjectionService.js +268 -0
- package/src/services/conversationCompactionService.js +1103 -0
- package/src/services/credentialVault.js +685 -0
- package/src/services/errorHandler.js +810 -0
- package/src/services/fileAttachmentService.js +547 -0
- package/src/services/flowContextService.js +189 -0
- package/src/services/memoryService.js +521 -0
- package/src/services/modelRouterService.js +365 -0
- package/src/services/modelsService.js +323 -0
- package/src/services/ollamaService.js +452 -0
- package/src/services/portRegistry.js +336 -0
- package/src/services/portTracker.js +223 -0
- package/src/services/projectDetector.js +404 -0
- package/src/services/promptService.js +372 -0
- package/src/services/qualityInspector.js +796 -0
- package/src/services/scheduleService.js +725 -0
- package/src/services/serviceRegistry.js +386 -0
- package/src/services/skillsService.js +486 -0
- package/src/services/telegramService.js +920 -0
- package/src/services/tokenCountingService.js +316 -0
- package/src/services/visualEditorBridge.js +1033 -0
- package/src/services/visualEditorServer.js +1727 -0
- package/src/services/whatsappService.js +663 -0
- package/src/tools/__tests__/webTool.e2e.test.js +569 -0
- package/src/tools/__tests__/webTool.unit.test.js +195 -0
- package/src/tools/agentCommunicationTool.js +1343 -0
- package/src/tools/agentDelayTool.js +498 -0
- package/src/tools/asyncToolManager.js +604 -0
- package/src/tools/baseTool.js +887 -0
- package/src/tools/browserTool.js +897 -0
- package/src/tools/cloneDetectionTool.js +581 -0
- package/src/tools/codeMapTool.js +857 -0
- package/src/tools/dependencyResolverTool.js +1212 -0
- package/src/tools/docxTool.js +623 -0
- package/src/tools/excelTool.js +636 -0
- package/src/tools/fileContentReplaceTool.js +840 -0
- package/src/tools/fileTreeTool.js +833 -0
- package/src/tools/filesystemTool.js +1217 -0
- package/src/tools/helpTool.js +198 -0
- package/src/tools/imageTool.js +1034 -0
- package/src/tools/importAnalyzerTool.js +1056 -0
- package/src/tools/jobDoneTool.js +388 -0
- package/src/tools/memoryTool.js +554 -0
- package/src/tools/pdfTool.js +627 -0
- package/src/tools/seekTool.js +883 -0
- package/src/tools/skillsTool.js +276 -0
- package/src/tools/staticAnalysisTool.js +2146 -0
- package/src/tools/taskManagerTool.js +2836 -0
- package/src/tools/terminalTool.js +2486 -0
- package/src/tools/userPromptTool.js +474 -0
- package/src/tools/videoTool.js +1139 -0
- package/src/tools/visionTool.js +507 -0
- package/src/tools/visualEditorTool.js +1175 -0
- package/src/tools/webTool.js +3114 -0
- package/src/tools/whatsappTool.js +457 -0
- package/src/types/agent.js +519 -0
- package/src/types/contextReference.js +972 -0
- package/src/types/conversation.js +730 -0
- package/src/types/toolCommand.js +747 -0
- package/src/utilities/attachmentValidator.js +288 -0
- package/src/utilities/browserStealth.js +630 -0
- package/src/utilities/configManager.js +618 -0
- package/src/utilities/constants.js +870 -0
- package/src/utilities/directoryAccessManager.js +566 -0
- package/src/utilities/fileProcessor.js +307 -0
- package/src/utilities/humanBehavior.js +453 -0
- package/src/utilities/jsonRepair.js +242 -0
- package/src/utilities/logger.js +436 -0
- package/src/utilities/platformUtils.js +255 -0
- package/src/utilities/platformUtils.test.js +98 -0
- package/src/utilities/stealthConstants.js +377 -0
- package/src/utilities/structuredFileValidator.js +699 -0
- package/src/utilities/tagParser.js +878 -0
- package/src/utilities/toolConstants.js +415 -0
- package/src/utilities/userDataDir.js +300 -0
- package/web-ui/build/brands/autopilot/favicon.svg +1 -0
- package/web-ui/build/brands/autopilot/logo.webp +0 -0
- package/web-ui/build/brands/onbuzz/favicon.svg +1 -0
- package/web-ui/build/brands/onbuzz/logo-text.webp +0 -0
- package/web-ui/build/brands/onbuzz/logo.webp +0 -0
- package/web-ui/build/index.html +15 -0
- package/web-ui/build/logo.png +0 -0
- package/web-ui/build/logo2.png +0 -0
- package/web-ui/build/static/index-SmQFfvBs.js +746 -0
- package/web-ui/build/static/index-V2ySwjHp.css +1 -0
|
@@ -0,0 +1,1033 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visual Editor Bridge Service
|
|
3
|
+
*
|
|
4
|
+
* Manages visual editor instances per agent, enabling users to interact
|
|
5
|
+
* with their web applications visually and give the AI agent pointers
|
|
6
|
+
* to code parts of interest.
|
|
7
|
+
*
|
|
8
|
+
* Key responsibilities:
|
|
9
|
+
* - Instance registry (one editor per agent)
|
|
10
|
+
* - Visual context storage (element selections)
|
|
11
|
+
* - Lifecycle management (create/stop/cleanup)
|
|
12
|
+
* - Multi-instance coordination
|
|
13
|
+
* - WebSocket connection to visual editor (Phase 3)
|
|
14
|
+
*
|
|
15
|
+
* @see VISUAL-EDITOR-INTEGRATION-PLAN.md for full architecture
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { EventEmitter } from 'events';
|
|
19
|
+
import WebSocket from 'ws';
|
|
20
|
+
import { getVisualEditorPort } from './visualEditorServer.js';
|
|
21
|
+
|
|
22
|
+
// Configuration defaults - port can be configured via config file, env var, or fallback
|
|
23
|
+
const DEFAULT_IDLE_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
|
|
24
|
+
const DEFAULT_MAX_INSTANCES = 3;
|
|
25
|
+
const DEFAULT_RECONNECT_INTERVAL_MS = 3000;
|
|
26
|
+
const DEFAULT_MAX_RECONNECT_ATTEMPTS = 5;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get the WebSocket URL for the visual editor (computed at runtime)
|
|
30
|
+
* Uses getVisualEditorPort which respects config file and env var settings
|
|
31
|
+
*/
|
|
32
|
+
function getVisualEditorWsUrl() {
|
|
33
|
+
const port = getVisualEditorPort();
|
|
34
|
+
return `ws://localhost:${port}/ws`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* WebSocket message types from visual editor
|
|
39
|
+
*/
|
|
40
|
+
export const MessageTypes = {
|
|
41
|
+
// Incoming from editor
|
|
42
|
+
ELEMENT_SELECTED: 'element-selected',
|
|
43
|
+
FILE_CHANGED: 'file-changed',
|
|
44
|
+
EDITOR_READY: 'editor-ready',
|
|
45
|
+
ERROR: 'error',
|
|
46
|
+
PONG: 'pong',
|
|
47
|
+
|
|
48
|
+
// Outgoing to editor
|
|
49
|
+
HIGHLIGHT: 'highlight',
|
|
50
|
+
SCROLL_TO: 'scroll-to',
|
|
51
|
+
RELOAD: 'reload',
|
|
52
|
+
SET_MODE: 'set-mode',
|
|
53
|
+
PING: 'ping',
|
|
54
|
+
SUBSCRIBE: 'subscribe',
|
|
55
|
+
UNSUBSCRIBE: 'unsubscribe'
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Instance status enum
|
|
60
|
+
*/
|
|
61
|
+
export const InstanceStatus = {
|
|
62
|
+
INITIALIZED: 'initialized',
|
|
63
|
+
CONNECTING: 'connecting',
|
|
64
|
+
READY: 'ready',
|
|
65
|
+
ERROR: 'error',
|
|
66
|
+
STOPPED: 'stopped'
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Visual Editor Bridge Service
|
|
71
|
+
* Manages visual editor instances and coordinates communication
|
|
72
|
+
*/
|
|
73
|
+
class VisualEditorBridge extends EventEmitter {
|
|
74
|
+
/**
|
|
75
|
+
* @param {Object} config - Configuration options
|
|
76
|
+
* @param {number} config.maxInstances - Maximum concurrent editors (default: 3)
|
|
77
|
+
* @param {number} config.idleTimeoutMs - Idle timeout in ms (default: 10 min)
|
|
78
|
+
* @param {string} config.visualEditorUrl - WebSocket URL for visual editor
|
|
79
|
+
* @param {number} config.reconnectIntervalMs - Reconnection interval
|
|
80
|
+
* @param {number} config.maxReconnectAttempts - Max reconnection attempts
|
|
81
|
+
* @param {Object} config.logger - Logger instance
|
|
82
|
+
*/
|
|
83
|
+
constructor(config = {}) {
|
|
84
|
+
super();
|
|
85
|
+
|
|
86
|
+
// Instance registry: agentId → InstanceRecord
|
|
87
|
+
this.instances = new Map();
|
|
88
|
+
|
|
89
|
+
// Configuration
|
|
90
|
+
this.maxInstances = config.maxInstances || DEFAULT_MAX_INSTANCES;
|
|
91
|
+
this.idleTimeoutMs = config.idleTimeoutMs || DEFAULT_IDLE_TIMEOUT_MS;
|
|
92
|
+
this.visualEditorUrl = config.visualEditorUrl || getVisualEditorWsUrl();
|
|
93
|
+
this.reconnectIntervalMs = config.reconnectIntervalMs || DEFAULT_RECONNECT_INTERVAL_MS;
|
|
94
|
+
this.maxReconnectAttempts = config.maxReconnectAttempts || DEFAULT_MAX_RECONNECT_ATTEMPTS;
|
|
95
|
+
this.logger = config.logger || console;
|
|
96
|
+
this.enabled = config.enabled !== false;
|
|
97
|
+
|
|
98
|
+
// Cleanup interval for orphaned instances
|
|
99
|
+
this.cleanupInterval = null;
|
|
100
|
+
if (this.enabled) {
|
|
101
|
+
this.cleanupInterval = setInterval(() => this._cleanupIdle(), 60000);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
this.logger.info?.('[VisualEditorBridge] Initialized', {
|
|
105
|
+
maxInstances: this.maxInstances,
|
|
106
|
+
idleTimeoutMs: this.idleTimeoutMs,
|
|
107
|
+
visualEditorUrl: this.visualEditorUrl,
|
|
108
|
+
enabled: this.enabled
|
|
109
|
+
}) || this.logger.log('[VisualEditorBridge] Initialized');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Check if bridge is enabled
|
|
114
|
+
* @returns {boolean}
|
|
115
|
+
*/
|
|
116
|
+
isEnabled() {
|
|
117
|
+
return this.enabled;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Get or create instance for agent
|
|
122
|
+
* @param {string} agentId - Agent identifier
|
|
123
|
+
* @param {Object} options - Instance options
|
|
124
|
+
* @param {string} options.projectRoot - Project root directory
|
|
125
|
+
* @param {string} options.appUrl - User's app URL to proxy
|
|
126
|
+
* @returns {Object} Instance record
|
|
127
|
+
* @throws {Error} If max instances reached
|
|
128
|
+
*/
|
|
129
|
+
async getInstance(agentId, options = {}) {
|
|
130
|
+
if (!agentId) {
|
|
131
|
+
throw new Error('agentId is required');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Return existing instance
|
|
135
|
+
if (this.instances.has(agentId)) {
|
|
136
|
+
const instance = this.instances.get(agentId);
|
|
137
|
+
instance.lastActivity = Date.now();
|
|
138
|
+
this._resetIdleTimer(agentId);
|
|
139
|
+
|
|
140
|
+
// Update options if provided
|
|
141
|
+
if (options.projectRoot) instance.projectRoot = options.projectRoot;
|
|
142
|
+
if (options.appUrl) instance.appUrl = options.appUrl;
|
|
143
|
+
|
|
144
|
+
return instance;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Check instance limit
|
|
148
|
+
if (this.instances.size >= this.maxInstances) {
|
|
149
|
+
// Try to evict oldest idle instance
|
|
150
|
+
const evicted = this._evictOldestIdle();
|
|
151
|
+
if (!evicted) {
|
|
152
|
+
throw new Error(
|
|
153
|
+
`Maximum visual editor instances (${this.maxInstances}) reached. ` +
|
|
154
|
+
`Stop an existing editor first.`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Create new instance record
|
|
160
|
+
const instance = {
|
|
161
|
+
agentId,
|
|
162
|
+
projectRoot: options.projectRoot || null,
|
|
163
|
+
appUrl: options.appUrl || null,
|
|
164
|
+
status: InstanceStatus.INITIALIZED,
|
|
165
|
+
wsConnection: null,
|
|
166
|
+
editorUrl: null,
|
|
167
|
+
lastActivity: Date.now(),
|
|
168
|
+
createdAt: Date.now(),
|
|
169
|
+
uiSubscribers: new Set(),
|
|
170
|
+
visualContext: null,
|
|
171
|
+
idleTimer: null,
|
|
172
|
+
error: null,
|
|
173
|
+
// WebSocket connection state (Phase 3)
|
|
174
|
+
reconnectAttempts: 0,
|
|
175
|
+
reconnectTimer: null,
|
|
176
|
+
pingInterval: null,
|
|
177
|
+
lastPong: null,
|
|
178
|
+
isConnecting: false
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
this.instances.set(agentId, instance);
|
|
182
|
+
this._resetIdleTimer(agentId);
|
|
183
|
+
|
|
184
|
+
this.logger.info?.(`[VisualEditorBridge] Created instance for agent: ${agentId}`, {
|
|
185
|
+
projectRoot: instance.projectRoot,
|
|
186
|
+
appUrl: instance.appUrl
|
|
187
|
+
}) || this.logger.log(`[VisualEditorBridge] Created instance: ${agentId}`);
|
|
188
|
+
|
|
189
|
+
this.emit('instance-created', { agentId, instance: this._sanitizeInstance(instance) });
|
|
190
|
+
|
|
191
|
+
return instance;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Check if instance exists for agent
|
|
196
|
+
* @param {string} agentId - Agent identifier
|
|
197
|
+
* @returns {boolean}
|
|
198
|
+
*/
|
|
199
|
+
hasInstance(agentId) {
|
|
200
|
+
return this.instances.has(agentId);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Store visual context (element selection) for agent
|
|
205
|
+
* @param {string} agentId - Agent identifier
|
|
206
|
+
* @param {Object} elementReference - Element reference from visual editor
|
|
207
|
+
* @returns {boolean} Success
|
|
208
|
+
*/
|
|
209
|
+
setVisualContext(agentId, elementReference) {
|
|
210
|
+
const instance = this.instances.get(agentId);
|
|
211
|
+
if (!instance) {
|
|
212
|
+
this.logger.warn?.(`[VisualEditorBridge] No instance for agent: ${agentId}`) ||
|
|
213
|
+
this.logger.log(`[VisualEditorBridge] No instance: ${agentId}`);
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
instance.visualContext = {
|
|
218
|
+
...elementReference,
|
|
219
|
+
receivedAt: new Date().toISOString()
|
|
220
|
+
};
|
|
221
|
+
instance.lastActivity = Date.now();
|
|
222
|
+
this._resetIdleTimer(agentId);
|
|
223
|
+
|
|
224
|
+
this.logger.info?.(`[VisualEditorBridge] Visual context set for agent: ${agentId}`, {
|
|
225
|
+
selector: elementReference.selector,
|
|
226
|
+
sourceFile: elementReference.sourceHint?.file
|
|
227
|
+
}) || this.logger.log(`[VisualEditorBridge] Context set: ${agentId}`);
|
|
228
|
+
|
|
229
|
+
this.emit('visual-context-updated', {
|
|
230
|
+
agentId,
|
|
231
|
+
context: instance.visualContext
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Get visual context for agent
|
|
239
|
+
* @param {string} agentId - Agent identifier
|
|
240
|
+
* @returns {Object|null} Visual context or null
|
|
241
|
+
*/
|
|
242
|
+
getVisualContext(agentId) {
|
|
243
|
+
const instance = this.instances.get(agentId);
|
|
244
|
+
return instance?.visualContext || null;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Clear visual context for agent
|
|
249
|
+
* @param {string} agentId - Agent identifier
|
|
250
|
+
* @returns {boolean} Success
|
|
251
|
+
*/
|
|
252
|
+
clearVisualContext(agentId) {
|
|
253
|
+
const instance = this.instances.get(agentId);
|
|
254
|
+
if (instance && instance.visualContext) {
|
|
255
|
+
instance.visualContext = null;
|
|
256
|
+
this.emit('visual-context-cleared', { agentId });
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Get instance status
|
|
264
|
+
* @param {string} agentId - Agent identifier
|
|
265
|
+
* @returns {Object} Status object
|
|
266
|
+
*/
|
|
267
|
+
getStatus(agentId) {
|
|
268
|
+
const instance = this.instances.get(agentId);
|
|
269
|
+
if (!instance) {
|
|
270
|
+
return {
|
|
271
|
+
exists: false,
|
|
272
|
+
agentId
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return {
|
|
277
|
+
exists: true,
|
|
278
|
+
agentId: instance.agentId,
|
|
279
|
+
status: instance.status,
|
|
280
|
+
projectRoot: instance.projectRoot,
|
|
281
|
+
appUrl: instance.appUrl,
|
|
282
|
+
editorUrl: instance.editorUrl,
|
|
283
|
+
hasVisualContext: !!instance.visualContext,
|
|
284
|
+
visualContext: instance.visualContext,
|
|
285
|
+
subscriberCount: instance.uiSubscribers.size,
|
|
286
|
+
createdAt: instance.createdAt,
|
|
287
|
+
lastActivity: instance.lastActivity,
|
|
288
|
+
idleMs: Date.now() - instance.lastActivity,
|
|
289
|
+
error: instance.error
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Update instance status
|
|
295
|
+
* @param {string} agentId - Agent identifier
|
|
296
|
+
* @param {string} status - New status
|
|
297
|
+
* @param {Object} extra - Additional fields to update
|
|
298
|
+
* @returns {boolean} Success
|
|
299
|
+
*/
|
|
300
|
+
updateStatus(agentId, status, extra = {}) {
|
|
301
|
+
const instance = this.instances.get(agentId);
|
|
302
|
+
if (!instance) {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
instance.status = status;
|
|
307
|
+
instance.lastActivity = Date.now();
|
|
308
|
+
|
|
309
|
+
if (extra.editorUrl) instance.editorUrl = extra.editorUrl;
|
|
310
|
+
if (extra.wsConnection) instance.wsConnection = extra.wsConnection;
|
|
311
|
+
if (extra.error) instance.error = extra.error;
|
|
312
|
+
|
|
313
|
+
this.emit('instance-status-changed', {
|
|
314
|
+
agentId,
|
|
315
|
+
status,
|
|
316
|
+
...extra
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Add UI subscriber to instance
|
|
324
|
+
* @param {string} agentId - Agent identifier
|
|
325
|
+
* @param {string} connectionId - UI connection identifier
|
|
326
|
+
* @returns {boolean} Success
|
|
327
|
+
*/
|
|
328
|
+
addSubscriber(agentId, connectionId) {
|
|
329
|
+
const instance = this.instances.get(agentId);
|
|
330
|
+
if (!instance) {
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
instance.uiSubscribers.add(connectionId);
|
|
335
|
+
instance.lastActivity = Date.now();
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Remove UI subscriber from instance
|
|
341
|
+
* @param {string} agentId - Agent identifier
|
|
342
|
+
* @param {string} connectionId - UI connection identifier
|
|
343
|
+
* @returns {boolean} Success
|
|
344
|
+
*/
|
|
345
|
+
removeSubscriber(agentId, connectionId) {
|
|
346
|
+
const instance = this.instances.get(agentId);
|
|
347
|
+
if (!instance) {
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return instance.uiSubscribers.delete(connectionId);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Stop and remove instance for agent
|
|
356
|
+
* @param {string} agentId - Agent identifier
|
|
357
|
+
* @returns {boolean} Success
|
|
358
|
+
*/
|
|
359
|
+
async stopInstance(agentId) {
|
|
360
|
+
const instance = this.instances.get(agentId);
|
|
361
|
+
if (!instance) {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Mark as stopped to prevent reconnection attempts
|
|
366
|
+
instance.status = InstanceStatus.STOPPED;
|
|
367
|
+
|
|
368
|
+
// Clear idle timer
|
|
369
|
+
if (instance.idleTimer) {
|
|
370
|
+
clearTimeout(instance.idleTimer);
|
|
371
|
+
instance.idleTimer = null;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Cleanup WebSocket connection (including ping interval and reconnect timer)
|
|
375
|
+
this._cleanupConnection(agentId);
|
|
376
|
+
|
|
377
|
+
// Remove from registry
|
|
378
|
+
this.instances.delete(agentId);
|
|
379
|
+
|
|
380
|
+
this.logger.info?.(`[VisualEditorBridge] Stopped instance for agent: ${agentId}`) ||
|
|
381
|
+
this.logger.log(`[VisualEditorBridge] Stopped: ${agentId}`);
|
|
382
|
+
|
|
383
|
+
this.emit('instance-stopped', { agentId });
|
|
384
|
+
|
|
385
|
+
return true;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Handle agent deletion - cleanup instance
|
|
390
|
+
* @param {string} agentId - Agent identifier
|
|
391
|
+
* @returns {boolean} Success
|
|
392
|
+
*/
|
|
393
|
+
onAgentDeleted(agentId) {
|
|
394
|
+
this.logger.info?.(`[VisualEditorBridge] Agent deleted, cleaning up: ${agentId}`);
|
|
395
|
+
return this.stopInstance(agentId);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Handle agent unload - cleanup instance
|
|
400
|
+
* @param {string} agentId - Agent identifier
|
|
401
|
+
* @returns {boolean} Success
|
|
402
|
+
*/
|
|
403
|
+
onAgentUnloaded(agentId) {
|
|
404
|
+
this.logger.info?.(`[VisualEditorBridge] Agent unloaded, cleaning up: ${agentId}`);
|
|
405
|
+
return this.stopInstance(agentId);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Check if project is used by another agent
|
|
410
|
+
* @param {string} agentId - Current agent identifier
|
|
411
|
+
* @param {string} projectRoot - Project root to check
|
|
412
|
+
* @returns {Object} Collision info
|
|
413
|
+
*/
|
|
414
|
+
checkProjectCollision(agentId, projectRoot) {
|
|
415
|
+
if (!projectRoot) {
|
|
416
|
+
return { collision: false };
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
for (const [otherId, instance] of this.instances) {
|
|
420
|
+
if (otherId !== agentId && instance.projectRoot === projectRoot) {
|
|
421
|
+
return {
|
|
422
|
+
collision: true,
|
|
423
|
+
otherAgentId: otherId,
|
|
424
|
+
message: `Project "${projectRoot}" is already being edited by agent "${otherId}"`
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
return { collision: false };
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* List all instances
|
|
433
|
+
* @returns {Array} Array of instance info objects
|
|
434
|
+
*/
|
|
435
|
+
listInstances() {
|
|
436
|
+
return Array.from(this.instances.entries()).map(([agentId, instance]) => ({
|
|
437
|
+
agentId,
|
|
438
|
+
status: instance.status,
|
|
439
|
+
projectRoot: instance.projectRoot,
|
|
440
|
+
appUrl: instance.appUrl,
|
|
441
|
+
hasContext: !!instance.visualContext,
|
|
442
|
+
subscriberCount: instance.uiSubscribers.size,
|
|
443
|
+
createdAt: instance.createdAt,
|
|
444
|
+
lastActivity: instance.lastActivity,
|
|
445
|
+
idleMs: Date.now() - instance.lastActivity
|
|
446
|
+
}));
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Get count of active instances
|
|
451
|
+
* @returns {number}
|
|
452
|
+
*/
|
|
453
|
+
getInstanceCount() {
|
|
454
|
+
return this.instances.size;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Touch instance to reset idle timer
|
|
459
|
+
* @param {string} agentId - Agent identifier
|
|
460
|
+
*/
|
|
461
|
+
touchInstance(agentId) {
|
|
462
|
+
const instance = this.instances.get(agentId);
|
|
463
|
+
if (instance) {
|
|
464
|
+
instance.lastActivity = Date.now();
|
|
465
|
+
this._resetIdleTimer(agentId);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// === WebSocket Methods (Phase 3) ===
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Connect to visual editor WebSocket
|
|
473
|
+
* @param {string} agentId - Agent identifier
|
|
474
|
+
* @param {Object} options - Connection options
|
|
475
|
+
* @param {string} options.editorUrl - Override editor URL
|
|
476
|
+
* @returns {Promise<boolean>} Connection success
|
|
477
|
+
*/
|
|
478
|
+
async connectToEditor(agentId, options = {}) {
|
|
479
|
+
const instance = this.instances.get(agentId);
|
|
480
|
+
if (!instance) {
|
|
481
|
+
throw new Error(`No instance for agent: ${agentId}`);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Already connected or connecting
|
|
485
|
+
if (instance.wsConnection?.readyState === WebSocket.OPEN) {
|
|
486
|
+
return true;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if (instance.isConnecting) {
|
|
490
|
+
return false;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
instance.isConnecting = true;
|
|
494
|
+
instance.status = InstanceStatus.CONNECTING;
|
|
495
|
+
this.emit('instance-status-changed', { agentId, status: InstanceStatus.CONNECTING });
|
|
496
|
+
|
|
497
|
+
const editorUrl = options.editorUrl || this.visualEditorUrl;
|
|
498
|
+
|
|
499
|
+
return new Promise((resolve) => {
|
|
500
|
+
try {
|
|
501
|
+
this.logger.info?.(`[VisualEditorBridge] Connecting to editor for agent: ${agentId}`, {
|
|
502
|
+
url: editorUrl
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
const ws = new WebSocket(editorUrl);
|
|
506
|
+
|
|
507
|
+
ws.on('open', () => {
|
|
508
|
+
instance.wsConnection = ws;
|
|
509
|
+
instance.status = InstanceStatus.READY;
|
|
510
|
+
instance.editorUrl = editorUrl;
|
|
511
|
+
instance.isConnecting = false;
|
|
512
|
+
instance.reconnectAttempts = 0;
|
|
513
|
+
instance.error = null;
|
|
514
|
+
instance.lastActivity = Date.now();
|
|
515
|
+
|
|
516
|
+
this.logger.info?.(`[VisualEditorBridge] Connected to editor for agent: ${agentId}`);
|
|
517
|
+
|
|
518
|
+
// Start heartbeat
|
|
519
|
+
this._startPingInterval(agentId);
|
|
520
|
+
|
|
521
|
+
// Subscribe to editor events for this agent
|
|
522
|
+
this.sendCommand(agentId, MessageTypes.SUBSCRIBE, {
|
|
523
|
+
agentId,
|
|
524
|
+
projectRoot: instance.projectRoot,
|
|
525
|
+
appUrl: instance.appUrl
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
this.emit('editor-connected', { agentId, editorUrl });
|
|
529
|
+
this.emit('instance-status-changed', { agentId, status: InstanceStatus.READY });
|
|
530
|
+
|
|
531
|
+
resolve(true);
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
ws.on('message', (data) => {
|
|
535
|
+
try {
|
|
536
|
+
const message = JSON.parse(data.toString());
|
|
537
|
+
this._handleEditorMessage(agentId, message);
|
|
538
|
+
} catch (err) {
|
|
539
|
+
this.logger.warn?.(`[VisualEditorBridge] Invalid message from editor: ${err.message}`);
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
ws.on('close', (code, reason) => {
|
|
544
|
+
this.logger.info?.(`[VisualEditorBridge] Editor connection closed for agent: ${agentId}`, {
|
|
545
|
+
code,
|
|
546
|
+
reason: reason?.toString()
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
this._cleanupConnection(agentId);
|
|
550
|
+
|
|
551
|
+
// Schedule reconnect if instance still exists and wasn't manually stopped
|
|
552
|
+
if (this.instances.has(agentId) && instance.status !== InstanceStatus.STOPPED) {
|
|
553
|
+
this._scheduleReconnect(agentId);
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
ws.on('error', (error) => {
|
|
558
|
+
this.logger.error?.(`[VisualEditorBridge] Editor connection error for agent: ${agentId}`, {
|
|
559
|
+
error: error.message
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
instance.error = error.message;
|
|
563
|
+
instance.isConnecting = false;
|
|
564
|
+
|
|
565
|
+
if (instance.status === InstanceStatus.CONNECTING) {
|
|
566
|
+
instance.status = InstanceStatus.ERROR;
|
|
567
|
+
this.emit('instance-status-changed', { agentId, status: InstanceStatus.ERROR, error: error.message });
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
this.emit('editor-error', { agentId, error: error.message });
|
|
571
|
+
resolve(false);
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
} catch (error) {
|
|
575
|
+
instance.isConnecting = false;
|
|
576
|
+
instance.status = InstanceStatus.ERROR;
|
|
577
|
+
instance.error = error.message;
|
|
578
|
+
this.logger.error?.(`[VisualEditorBridge] Failed to create WebSocket: ${error.message}`);
|
|
579
|
+
resolve(false);
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Disconnect from visual editor
|
|
586
|
+
* @param {string} agentId - Agent identifier
|
|
587
|
+
* @returns {boolean} Success
|
|
588
|
+
*/
|
|
589
|
+
disconnectFromEditor(agentId) {
|
|
590
|
+
const instance = this.instances.get(agentId);
|
|
591
|
+
if (!instance) {
|
|
592
|
+
return false;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// Send unsubscribe before closing
|
|
596
|
+
if (instance.wsConnection?.readyState === WebSocket.OPEN) {
|
|
597
|
+
this.sendCommand(agentId, MessageTypes.UNSUBSCRIBE, { agentId });
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
this._cleanupConnection(agentId);
|
|
601
|
+
|
|
602
|
+
this.logger.info?.(`[VisualEditorBridge] Disconnected from editor for agent: ${agentId}`);
|
|
603
|
+
this.emit('editor-disconnected', { agentId });
|
|
604
|
+
|
|
605
|
+
return true;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Send command to visual editor
|
|
610
|
+
* @param {string} agentId - Agent identifier
|
|
611
|
+
* @param {string} type - Message type
|
|
612
|
+
* @param {Object} data - Message data
|
|
613
|
+
* @returns {boolean} Success
|
|
614
|
+
*/
|
|
615
|
+
sendCommand(agentId, type, data = {}) {
|
|
616
|
+
const instance = this.instances.get(agentId);
|
|
617
|
+
if (!instance?.wsConnection || instance.wsConnection.readyState !== WebSocket.OPEN) {
|
|
618
|
+
this.logger.warn?.(`[VisualEditorBridge] Cannot send command - not connected: ${agentId}`);
|
|
619
|
+
return false;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
try {
|
|
623
|
+
const message = JSON.stringify({
|
|
624
|
+
type,
|
|
625
|
+
agentId,
|
|
626
|
+
timestamp: Date.now(),
|
|
627
|
+
...data
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
instance.wsConnection.send(message);
|
|
631
|
+
instance.lastActivity = Date.now();
|
|
632
|
+
this._resetIdleTimer(agentId);
|
|
633
|
+
|
|
634
|
+
this.logger.debug?.(`[VisualEditorBridge] Sent command: ${type} for agent: ${agentId}`);
|
|
635
|
+
return true;
|
|
636
|
+
|
|
637
|
+
} catch (error) {
|
|
638
|
+
this.logger.error?.(`[VisualEditorBridge] Failed to send command: ${error.message}`);
|
|
639
|
+
return false;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Highlight element in visual editor preview
|
|
645
|
+
* @param {string} agentId - Agent identifier
|
|
646
|
+
* @param {string} selector - CSS selector to highlight
|
|
647
|
+
* @param {number} durationMs - Highlight duration (default: 2000ms)
|
|
648
|
+
* @returns {boolean} Success
|
|
649
|
+
*/
|
|
650
|
+
highlightElement(agentId, selector, durationMs = 2000) {
|
|
651
|
+
return this.sendCommand(agentId, MessageTypes.HIGHLIGHT, {
|
|
652
|
+
selector,
|
|
653
|
+
duration: durationMs
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Scroll to element in visual editor preview
|
|
659
|
+
* @param {string} agentId - Agent identifier
|
|
660
|
+
* @param {string} selector - CSS selector to scroll to
|
|
661
|
+
* @returns {boolean} Success
|
|
662
|
+
*/
|
|
663
|
+
scrollToElement(agentId, selector) {
|
|
664
|
+
return this.sendCommand(agentId, MessageTypes.SCROLL_TO, { selector });
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Reload the visual editor preview
|
|
669
|
+
* @param {string} agentId - Agent identifier
|
|
670
|
+
* @returns {boolean} Success
|
|
671
|
+
*/
|
|
672
|
+
reloadPreview(agentId) {
|
|
673
|
+
return this.sendCommand(agentId, MessageTypes.RELOAD, {});
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* Set visual editor mode
|
|
678
|
+
* @param {string} agentId - Agent identifier
|
|
679
|
+
* @param {string} mode - Mode ('edit' or 'preview')
|
|
680
|
+
* @returns {boolean} Success
|
|
681
|
+
*/
|
|
682
|
+
setEditorMode(agentId, mode) {
|
|
683
|
+
if (!['edit', 'preview'].includes(mode)) {
|
|
684
|
+
throw new Error(`Invalid mode: ${mode}. Must be 'edit' or 'preview'`);
|
|
685
|
+
}
|
|
686
|
+
return this.sendCommand(agentId, MessageTypes.SET_MODE, { mode });
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* Check if instance is connected to editor
|
|
691
|
+
* @param {string} agentId - Agent identifier
|
|
692
|
+
* @returns {boolean}
|
|
693
|
+
*/
|
|
694
|
+
isConnected(agentId) {
|
|
695
|
+
const instance = this.instances.get(agentId);
|
|
696
|
+
return instance?.wsConnection?.readyState === WebSocket.OPEN;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// === Private methods ===
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* Reset idle timer for instance
|
|
703
|
+
* @private
|
|
704
|
+
*/
|
|
705
|
+
_resetIdleTimer(agentId) {
|
|
706
|
+
const instance = this.instances.get(agentId);
|
|
707
|
+
if (!instance) return;
|
|
708
|
+
|
|
709
|
+
if (instance.idleTimer) {
|
|
710
|
+
clearTimeout(instance.idleTimer);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
instance.idleTimer = setTimeout(() => {
|
|
714
|
+
this.logger.info?.(`[VisualEditorBridge] Idle timeout for agent: ${agentId}`);
|
|
715
|
+
this.stopInstance(agentId);
|
|
716
|
+
}, this.idleTimeoutMs);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* Evict the oldest idle instance to make room
|
|
721
|
+
* @private
|
|
722
|
+
* @returns {boolean} Whether an instance was evicted
|
|
723
|
+
*/
|
|
724
|
+
_evictOldestIdle() {
|
|
725
|
+
let oldest = null;
|
|
726
|
+
let oldestTime = Infinity;
|
|
727
|
+
|
|
728
|
+
// First pass: prefer instances without active subscribers
|
|
729
|
+
for (const [agentId, instance] of this.instances) {
|
|
730
|
+
const hasSubscribers = instance.uiSubscribers.size > 0;
|
|
731
|
+
|
|
732
|
+
if (!hasSubscribers && instance.lastActivity < oldestTime) {
|
|
733
|
+
oldest = agentId;
|
|
734
|
+
oldestTime = instance.lastActivity;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// Second pass: if no instance without subscribers, evict oldest overall
|
|
739
|
+
if (!oldest) {
|
|
740
|
+
oldestTime = Infinity;
|
|
741
|
+
for (const [agentId, instance] of this.instances) {
|
|
742
|
+
if (instance.lastActivity < oldestTime) {
|
|
743
|
+
oldest = agentId;
|
|
744
|
+
oldestTime = instance.lastActivity;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
if (oldest) {
|
|
750
|
+
this.logger.info?.(`[VisualEditorBridge] Evicting idle instance: ${oldest}`);
|
|
751
|
+
this.stopInstance(oldest);
|
|
752
|
+
return true;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
return false;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Cleanup idle instances (called periodically)
|
|
760
|
+
* @private
|
|
761
|
+
*/
|
|
762
|
+
_cleanupIdle() {
|
|
763
|
+
const now = Date.now();
|
|
764
|
+
const toCleanup = [];
|
|
765
|
+
|
|
766
|
+
for (const [agentId, instance] of this.instances) {
|
|
767
|
+
if (now - instance.lastActivity > this.idleTimeoutMs) {
|
|
768
|
+
toCleanup.push(agentId);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
for (const agentId of toCleanup) {
|
|
773
|
+
this.logger.info?.(`[VisualEditorBridge] Cleanup idle instance: ${agentId}`);
|
|
774
|
+
this.stopInstance(agentId);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* Sanitize instance for external exposure (remove internals)
|
|
780
|
+
* @private
|
|
781
|
+
*/
|
|
782
|
+
_sanitizeInstance(instance) {
|
|
783
|
+
return {
|
|
784
|
+
agentId: instance.agentId,
|
|
785
|
+
status: instance.status,
|
|
786
|
+
projectRoot: instance.projectRoot,
|
|
787
|
+
appUrl: instance.appUrl,
|
|
788
|
+
editorUrl: instance.editorUrl,
|
|
789
|
+
hasVisualContext: !!instance.visualContext,
|
|
790
|
+
subscriberCount: instance.uiSubscribers.size,
|
|
791
|
+
createdAt: instance.createdAt,
|
|
792
|
+
lastActivity: instance.lastActivity,
|
|
793
|
+
isConnected: instance.wsConnection?.readyState === WebSocket.OPEN
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* Handle incoming message from visual editor
|
|
799
|
+
* @private
|
|
800
|
+
*/
|
|
801
|
+
_handleEditorMessage(agentId, message) {
|
|
802
|
+
const instance = this.instances.get(agentId);
|
|
803
|
+
if (!instance) return;
|
|
804
|
+
|
|
805
|
+
instance.lastActivity = Date.now();
|
|
806
|
+
this._resetIdleTimer(agentId);
|
|
807
|
+
|
|
808
|
+
const { type } = message;
|
|
809
|
+
|
|
810
|
+
switch (type) {
|
|
811
|
+
case MessageTypes.ELEMENT_SELECTED:
|
|
812
|
+
// User selected an element in the visual editor
|
|
813
|
+
this.logger.info?.(`[VisualEditorBridge] Element selected for agent: ${agentId}`, {
|
|
814
|
+
selector: message.selector,
|
|
815
|
+
sourceFile: message.sourceHint?.file
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
// Store visual context
|
|
819
|
+
this.setVisualContext(agentId, {
|
|
820
|
+
selector: message.selector,
|
|
821
|
+
tagName: message.tagName,
|
|
822
|
+
text: message.text,
|
|
823
|
+
attributes: message.attributes,
|
|
824
|
+
boundingRect: message.boundingRect,
|
|
825
|
+
sourceHint: message.sourceHint
|
|
826
|
+
});
|
|
827
|
+
|
|
828
|
+
// Emit event for UI subscribers
|
|
829
|
+
this.emit('element-selected', {
|
|
830
|
+
agentId,
|
|
831
|
+
element: message
|
|
832
|
+
});
|
|
833
|
+
break;
|
|
834
|
+
|
|
835
|
+
case MessageTypes.FILE_CHANGED:
|
|
836
|
+
// File changed in the project
|
|
837
|
+
this.logger.info?.(`[VisualEditorBridge] File changed for agent: ${agentId}`, {
|
|
838
|
+
file: message.file,
|
|
839
|
+
type: message.changeType
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
this.emit('file-changed', {
|
|
843
|
+
agentId,
|
|
844
|
+
file: message.file,
|
|
845
|
+
changeType: message.changeType
|
|
846
|
+
});
|
|
847
|
+
break;
|
|
848
|
+
|
|
849
|
+
case MessageTypes.EDITOR_READY:
|
|
850
|
+
// Editor is ready and connected
|
|
851
|
+
this.logger.info?.(`[VisualEditorBridge] Editor ready for agent: ${agentId}`);
|
|
852
|
+
this.emit('editor-ready', { agentId });
|
|
853
|
+
break;
|
|
854
|
+
|
|
855
|
+
case MessageTypes.PONG:
|
|
856
|
+
// Heartbeat response
|
|
857
|
+
instance.lastPong = Date.now();
|
|
858
|
+
break;
|
|
859
|
+
|
|
860
|
+
case MessageTypes.ERROR:
|
|
861
|
+
// Error from editor
|
|
862
|
+
this.logger.error?.(`[VisualEditorBridge] Editor error for agent: ${agentId}`, {
|
|
863
|
+
error: message.error
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
instance.error = message.error;
|
|
867
|
+
this.emit('editor-error', {
|
|
868
|
+
agentId,
|
|
869
|
+
error: message.error
|
|
870
|
+
});
|
|
871
|
+
break;
|
|
872
|
+
|
|
873
|
+
default:
|
|
874
|
+
this.logger.debug?.(`[VisualEditorBridge] Unknown message type: ${type}`);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Cleanup WebSocket connection resources
|
|
880
|
+
* @private
|
|
881
|
+
*/
|
|
882
|
+
_cleanupConnection(agentId) {
|
|
883
|
+
const instance = this.instances.get(agentId);
|
|
884
|
+
if (!instance) return;
|
|
885
|
+
|
|
886
|
+
// Stop ping interval
|
|
887
|
+
if (instance.pingInterval) {
|
|
888
|
+
clearInterval(instance.pingInterval);
|
|
889
|
+
instance.pingInterval = null;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
// Cancel reconnect timer
|
|
893
|
+
if (instance.reconnectTimer) {
|
|
894
|
+
clearTimeout(instance.reconnectTimer);
|
|
895
|
+
instance.reconnectTimer = null;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// Close WebSocket
|
|
899
|
+
if (instance.wsConnection) {
|
|
900
|
+
try {
|
|
901
|
+
instance.wsConnection.close();
|
|
902
|
+
} catch (err) {
|
|
903
|
+
// Ignore
|
|
904
|
+
}
|
|
905
|
+
instance.wsConnection = null;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
instance.isConnecting = false;
|
|
909
|
+
instance.lastPong = null;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
/**
|
|
913
|
+
* Schedule reconnection with exponential backoff
|
|
914
|
+
* @private
|
|
915
|
+
*/
|
|
916
|
+
_scheduleReconnect(agentId) {
|
|
917
|
+
const instance = this.instances.get(agentId);
|
|
918
|
+
if (!instance) return;
|
|
919
|
+
|
|
920
|
+
if (instance.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
921
|
+
this.logger.error?.(`[VisualEditorBridge] Max reconnect attempts reached for agent: ${agentId}`);
|
|
922
|
+
instance.status = InstanceStatus.ERROR;
|
|
923
|
+
instance.error = 'Max reconnection attempts reached';
|
|
924
|
+
this.emit('instance-status-changed', {
|
|
925
|
+
agentId,
|
|
926
|
+
status: InstanceStatus.ERROR,
|
|
927
|
+
error: instance.error
|
|
928
|
+
});
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
instance.reconnectAttempts++;
|
|
933
|
+
|
|
934
|
+
// Exponential backoff: base * 2^attempts (capped at 30s)
|
|
935
|
+
const delay = Math.min(
|
|
936
|
+
this.reconnectIntervalMs * Math.pow(2, instance.reconnectAttempts - 1),
|
|
937
|
+
30000
|
|
938
|
+
);
|
|
939
|
+
|
|
940
|
+
this.logger.info?.(`[VisualEditorBridge] Scheduling reconnect for agent: ${agentId}`, {
|
|
941
|
+
attempt: instance.reconnectAttempts,
|
|
942
|
+
delayMs: delay
|
|
943
|
+
});
|
|
944
|
+
|
|
945
|
+
instance.reconnectTimer = setTimeout(() => {
|
|
946
|
+
if (this.instances.has(agentId)) {
|
|
947
|
+
this.connectToEditor(agentId).catch(err => {
|
|
948
|
+
this.logger.error?.(`[VisualEditorBridge] Reconnect failed: ${err.message}`);
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
}, delay);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
/**
|
|
955
|
+
* Start ping/pong heartbeat interval
|
|
956
|
+
* @private
|
|
957
|
+
*/
|
|
958
|
+
_startPingInterval(agentId) {
|
|
959
|
+
const instance = this.instances.get(agentId);
|
|
960
|
+
if (!instance) return;
|
|
961
|
+
|
|
962
|
+
// Clear existing interval
|
|
963
|
+
if (instance.pingInterval) {
|
|
964
|
+
clearInterval(instance.pingInterval);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// Ping every 30 seconds
|
|
968
|
+
instance.pingInterval = setInterval(() => {
|
|
969
|
+
if (instance.wsConnection?.readyState === WebSocket.OPEN) {
|
|
970
|
+
// Check if last pong was too long ago (60s timeout)
|
|
971
|
+
if (instance.lastPong && Date.now() - instance.lastPong > 60000) {
|
|
972
|
+
this.logger.warn?.(`[VisualEditorBridge] Ping timeout for agent: ${agentId}`);
|
|
973
|
+
this._cleanupConnection(agentId);
|
|
974
|
+
this._scheduleReconnect(agentId);
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
this.sendCommand(agentId, MessageTypes.PING, {});
|
|
979
|
+
}
|
|
980
|
+
}, 30000);
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
/**
|
|
984
|
+
* Graceful shutdown - stop all instances
|
|
985
|
+
*/
|
|
986
|
+
async shutdown() {
|
|
987
|
+
this.logger.info?.('[VisualEditorBridge] Shutting down...');
|
|
988
|
+
|
|
989
|
+
// Stop cleanup interval
|
|
990
|
+
if (this.cleanupInterval) {
|
|
991
|
+
clearInterval(this.cleanupInterval);
|
|
992
|
+
this.cleanupInterval = null;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
// Stop all instances
|
|
996
|
+
const stopPromises = [];
|
|
997
|
+
for (const agentId of this.instances.keys()) {
|
|
998
|
+
stopPromises.push(this.stopInstance(agentId));
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
await Promise.all(stopPromises);
|
|
1002
|
+
|
|
1003
|
+
this.logger.info?.('[VisualEditorBridge] Shutdown complete');
|
|
1004
|
+
this.emit('shutdown');
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
// Export singleton factory
|
|
1009
|
+
let bridgeInstance = null;
|
|
1010
|
+
|
|
1011
|
+
/**
|
|
1012
|
+
* Get or create the bridge singleton
|
|
1013
|
+
* @param {Object} config - Configuration (only used on first call)
|
|
1014
|
+
* @returns {VisualEditorBridge}
|
|
1015
|
+
*/
|
|
1016
|
+
export function getVisualEditorBridge(config = {}) {
|
|
1017
|
+
if (!bridgeInstance) {
|
|
1018
|
+
bridgeInstance = new VisualEditorBridge(config);
|
|
1019
|
+
}
|
|
1020
|
+
return bridgeInstance;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/**
|
|
1024
|
+
* Reset the singleton (for testing)
|
|
1025
|
+
*/
|
|
1026
|
+
export function resetVisualEditorBridge() {
|
|
1027
|
+
if (bridgeInstance) {
|
|
1028
|
+
bridgeInstance.shutdown();
|
|
1029
|
+
bridgeInstance = null;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
export default VisualEditorBridge;
|