@different-ai/opencode-browser 4.5.1 → 4.6.1
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/.opencode/skill/browser-automation/SKILL.md +14 -1
- package/README.md +53 -2
- package/bin/broker.cjs +18 -2
- package/bin/cli.js +395 -52
- package/bin/native-host.cjs +17 -1
- package/dist/plugin.js +374 -103
- package/extension/background.js +627 -20
- package/extension/manifest.json +4 -2
- package/package.json +15 -9
- package/.opencode/skill/github-release/SKILL.md +0 -12
package/dist/plugin.js
CHANGED
|
@@ -9,7 +9,7 @@ var __export = (target, all) => {
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
// node_modules
|
|
12
|
+
// node_modules/zod/v4/classic/external.js
|
|
13
13
|
var exports_external = {};
|
|
14
14
|
__export(exports_external, {
|
|
15
15
|
xid: () => xid2,
|
|
@@ -239,7 +239,7 @@ __export(exports_external, {
|
|
|
239
239
|
$brand: () => $brand
|
|
240
240
|
});
|
|
241
241
|
|
|
242
|
-
// node_modules
|
|
242
|
+
// node_modules/zod/v4/core/index.js
|
|
243
243
|
var exports_core2 = {};
|
|
244
244
|
__export(exports_core2, {
|
|
245
245
|
version: () => version,
|
|
@@ -503,7 +503,7 @@ __export(exports_core2, {
|
|
|
503
503
|
$ZodAny: () => $ZodAny
|
|
504
504
|
});
|
|
505
505
|
|
|
506
|
-
// node_modules
|
|
506
|
+
// node_modules/zod/v4/core/core.js
|
|
507
507
|
var NEVER = Object.freeze({
|
|
508
508
|
status: "aborted"
|
|
509
509
|
});
|
|
@@ -570,7 +570,7 @@ function config(newConfig) {
|
|
|
570
570
|
Object.assign(globalConfig, newConfig);
|
|
571
571
|
return globalConfig;
|
|
572
572
|
}
|
|
573
|
-
// node_modules
|
|
573
|
+
// node_modules/zod/v4/core/util.js
|
|
574
574
|
var exports_util = {};
|
|
575
575
|
__export(exports_util, {
|
|
576
576
|
unwrapMessage: () => unwrapMessage,
|
|
@@ -1199,7 +1199,7 @@ class Class {
|
|
|
1199
1199
|
constructor(..._args) {}
|
|
1200
1200
|
}
|
|
1201
1201
|
|
|
1202
|
-
// node_modules
|
|
1202
|
+
// node_modules/zod/v4/core/errors.js
|
|
1203
1203
|
var initializer = (inst, def) => {
|
|
1204
1204
|
inst.name = "$ZodError";
|
|
1205
1205
|
Object.defineProperty(inst, "_zod", {
|
|
@@ -1342,7 +1342,7 @@ function prettifyError(error) {
|
|
|
1342
1342
|
`);
|
|
1343
1343
|
}
|
|
1344
1344
|
|
|
1345
|
-
// node_modules
|
|
1345
|
+
// node_modules/zod/v4/core/parse.js
|
|
1346
1346
|
var _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
1347
1347
|
const ctx = _ctx ? Object.assign(_ctx, { async: false }) : { async: false };
|
|
1348
1348
|
const result = schema._zod.run({ value, issues: [] }, ctx);
|
|
@@ -1429,7 +1429,7 @@ var _safeDecodeAsync = (_Err) => async (schema, value, _ctx) => {
|
|
|
1429
1429
|
return _safeParseAsync(_Err)(schema, value, _ctx);
|
|
1430
1430
|
};
|
|
1431
1431
|
var safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync($ZodRealError);
|
|
1432
|
-
// node_modules
|
|
1432
|
+
// node_modules/zod/v4/core/regexes.js
|
|
1433
1433
|
var exports_regexes = {};
|
|
1434
1434
|
__export(exports_regexes, {
|
|
1435
1435
|
xid: () => xid,
|
|
@@ -1581,7 +1581,7 @@ var sha512_hex = /^[0-9a-fA-F]{128}$/;
|
|
|
1581
1581
|
var sha512_base64 = /* @__PURE__ */ fixedBase64(86, "==");
|
|
1582
1582
|
var sha512_base64url = /* @__PURE__ */ fixedBase64url(86);
|
|
1583
1583
|
|
|
1584
|
-
// node_modules
|
|
1584
|
+
// node_modules/zod/v4/core/checks.js
|
|
1585
1585
|
var $ZodCheck = /* @__PURE__ */ $constructor("$ZodCheck", (inst, def) => {
|
|
1586
1586
|
var _a;
|
|
1587
1587
|
inst._zod ?? (inst._zod = {});
|
|
@@ -2122,7 +2122,7 @@ var $ZodCheckOverwrite = /* @__PURE__ */ $constructor("$ZodCheckOverwrite", (ins
|
|
|
2122
2122
|
};
|
|
2123
2123
|
});
|
|
2124
2124
|
|
|
2125
|
-
// node_modules
|
|
2125
|
+
// node_modules/zod/v4/core/doc.js
|
|
2126
2126
|
class Doc {
|
|
2127
2127
|
constructor(args = []) {
|
|
2128
2128
|
this.content = [];
|
|
@@ -2160,14 +2160,14 @@ class Doc {
|
|
|
2160
2160
|
}
|
|
2161
2161
|
}
|
|
2162
2162
|
|
|
2163
|
-
// node_modules
|
|
2163
|
+
// node_modules/zod/v4/core/versions.js
|
|
2164
2164
|
var version = {
|
|
2165
2165
|
major: 4,
|
|
2166
2166
|
minor: 1,
|
|
2167
2167
|
patch: 8
|
|
2168
2168
|
};
|
|
2169
2169
|
|
|
2170
|
-
// node_modules
|
|
2170
|
+
// node_modules/zod/v4/core/schemas.js
|
|
2171
2171
|
var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
2172
2172
|
var _a;
|
|
2173
2173
|
inst ?? (inst = {});
|
|
@@ -3990,7 +3990,7 @@ function handleRefineResult(result, payload, input, inst) {
|
|
|
3990
3990
|
payload.issues.push(issue(_iss));
|
|
3991
3991
|
}
|
|
3992
3992
|
}
|
|
3993
|
-
// node_modules
|
|
3993
|
+
// node_modules/zod/v4/locales/index.js
|
|
3994
3994
|
var exports_locales = {};
|
|
3995
3995
|
__export(exports_locales, {
|
|
3996
3996
|
zhTW: () => zh_TW_default,
|
|
@@ -4041,7 +4041,7 @@ __export(exports_locales, {
|
|
|
4041
4041
|
ar: () => ar_default
|
|
4042
4042
|
});
|
|
4043
4043
|
|
|
4044
|
-
// node_modules
|
|
4044
|
+
// node_modules/zod/v4/locales/ar.js
|
|
4045
4045
|
var error = () => {
|
|
4046
4046
|
const Sizable = {
|
|
4047
4047
|
string: { unit: "حرف", verb: "أن يحوي" },
|
|
@@ -4157,7 +4157,7 @@ function ar_default() {
|
|
|
4157
4157
|
localeError: error()
|
|
4158
4158
|
};
|
|
4159
4159
|
}
|
|
4160
|
-
// node_modules
|
|
4160
|
+
// node_modules/zod/v4/locales/az.js
|
|
4161
4161
|
var error2 = () => {
|
|
4162
4162
|
const Sizable = {
|
|
4163
4163
|
string: { unit: "simvol", verb: "olmalıdır" },
|
|
@@ -4272,7 +4272,7 @@ function az_default() {
|
|
|
4272
4272
|
localeError: error2()
|
|
4273
4273
|
};
|
|
4274
4274
|
}
|
|
4275
|
-
// node_modules
|
|
4275
|
+
// node_modules/zod/v4/locales/be.js
|
|
4276
4276
|
function getBelarusianPlural(count, one, few, many) {
|
|
4277
4277
|
const absCount = Math.abs(count);
|
|
4278
4278
|
const lastDigit = absCount % 10;
|
|
@@ -4436,7 +4436,7 @@ function be_default() {
|
|
|
4436
4436
|
localeError: error3()
|
|
4437
4437
|
};
|
|
4438
4438
|
}
|
|
4439
|
-
// node_modules
|
|
4439
|
+
// node_modules/zod/v4/locales/ca.js
|
|
4440
4440
|
var error4 = () => {
|
|
4441
4441
|
const Sizable = {
|
|
4442
4442
|
string: { unit: "caràcters", verb: "contenir" },
|
|
@@ -4553,7 +4553,7 @@ function ca_default() {
|
|
|
4553
4553
|
localeError: error4()
|
|
4554
4554
|
};
|
|
4555
4555
|
}
|
|
4556
|
-
// node_modules
|
|
4556
|
+
// node_modules/zod/v4/locales/cs.js
|
|
4557
4557
|
var error5 = () => {
|
|
4558
4558
|
const Sizable = {
|
|
4559
4559
|
string: { unit: "znaků", verb: "mít" },
|
|
@@ -4688,7 +4688,7 @@ function cs_default() {
|
|
|
4688
4688
|
localeError: error5()
|
|
4689
4689
|
};
|
|
4690
4690
|
}
|
|
4691
|
-
// node_modules
|
|
4691
|
+
// node_modules/zod/v4/locales/da.js
|
|
4692
4692
|
var error6 = () => {
|
|
4693
4693
|
const Sizable = {
|
|
4694
4694
|
string: { unit: "tegn", verb: "havde" },
|
|
@@ -4819,7 +4819,7 @@ function da_default() {
|
|
|
4819
4819
|
localeError: error6()
|
|
4820
4820
|
};
|
|
4821
4821
|
}
|
|
4822
|
-
// node_modules
|
|
4822
|
+
// node_modules/zod/v4/locales/de.js
|
|
4823
4823
|
var error7 = () => {
|
|
4824
4824
|
const Sizable = {
|
|
4825
4825
|
string: { unit: "Zeichen", verb: "zu haben" },
|
|
@@ -4935,7 +4935,7 @@ function de_default() {
|
|
|
4935
4935
|
localeError: error7()
|
|
4936
4936
|
};
|
|
4937
4937
|
}
|
|
4938
|
-
// node_modules
|
|
4938
|
+
// node_modules/zod/v4/locales/en.js
|
|
4939
4939
|
var parsedType = (data) => {
|
|
4940
4940
|
const t = typeof data;
|
|
4941
4941
|
switch (t) {
|
|
@@ -5052,7 +5052,7 @@ function en_default() {
|
|
|
5052
5052
|
localeError: error8()
|
|
5053
5053
|
};
|
|
5054
5054
|
}
|
|
5055
|
-
// node_modules
|
|
5055
|
+
// node_modules/zod/v4/locales/eo.js
|
|
5056
5056
|
var parsedType2 = (data) => {
|
|
5057
5057
|
const t = typeof data;
|
|
5058
5058
|
switch (t) {
|
|
@@ -5168,7 +5168,7 @@ function eo_default() {
|
|
|
5168
5168
|
localeError: error9()
|
|
5169
5169
|
};
|
|
5170
5170
|
}
|
|
5171
|
-
// node_modules
|
|
5171
|
+
// node_modules/zod/v4/locales/es.js
|
|
5172
5172
|
var error10 = () => {
|
|
5173
5173
|
const Sizable = {
|
|
5174
5174
|
string: { unit: "caracteres", verb: "tener" },
|
|
@@ -5316,7 +5316,7 @@ function es_default() {
|
|
|
5316
5316
|
localeError: error10()
|
|
5317
5317
|
};
|
|
5318
5318
|
}
|
|
5319
|
-
// node_modules
|
|
5319
|
+
// node_modules/zod/v4/locales/fa.js
|
|
5320
5320
|
var error11 = () => {
|
|
5321
5321
|
const Sizable = {
|
|
5322
5322
|
string: { unit: "کاراکتر", verb: "داشته باشد" },
|
|
@@ -5438,7 +5438,7 @@ function fa_default() {
|
|
|
5438
5438
|
localeError: error11()
|
|
5439
5439
|
};
|
|
5440
5440
|
}
|
|
5441
|
-
// node_modules
|
|
5441
|
+
// node_modules/zod/v4/locales/fi.js
|
|
5442
5442
|
var error12 = () => {
|
|
5443
5443
|
const Sizable = {
|
|
5444
5444
|
string: { unit: "merkkiä", subject: "merkkijonon" },
|
|
@@ -5560,7 +5560,7 @@ function fi_default() {
|
|
|
5560
5560
|
localeError: error12()
|
|
5561
5561
|
};
|
|
5562
5562
|
}
|
|
5563
|
-
// node_modules
|
|
5563
|
+
// node_modules/zod/v4/locales/fr.js
|
|
5564
5564
|
var error13 = () => {
|
|
5565
5565
|
const Sizable = {
|
|
5566
5566
|
string: { unit: "caractères", verb: "avoir" },
|
|
@@ -5676,7 +5676,7 @@ function fr_default() {
|
|
|
5676
5676
|
localeError: error13()
|
|
5677
5677
|
};
|
|
5678
5678
|
}
|
|
5679
|
-
// node_modules
|
|
5679
|
+
// node_modules/zod/v4/locales/fr-CA.js
|
|
5680
5680
|
var error14 = () => {
|
|
5681
5681
|
const Sizable = {
|
|
5682
5682
|
string: { unit: "caractères", verb: "avoir" },
|
|
@@ -5793,7 +5793,7 @@ function fr_CA_default() {
|
|
|
5793
5793
|
localeError: error14()
|
|
5794
5794
|
};
|
|
5795
5795
|
}
|
|
5796
|
-
// node_modules
|
|
5796
|
+
// node_modules/zod/v4/locales/he.js
|
|
5797
5797
|
var error15 = () => {
|
|
5798
5798
|
const Sizable = {
|
|
5799
5799
|
string: { unit: "אותיות", verb: "לכלול" },
|
|
@@ -5909,7 +5909,7 @@ function he_default() {
|
|
|
5909
5909
|
localeError: error15()
|
|
5910
5910
|
};
|
|
5911
5911
|
}
|
|
5912
|
-
// node_modules
|
|
5912
|
+
// node_modules/zod/v4/locales/hu.js
|
|
5913
5913
|
var error16 = () => {
|
|
5914
5914
|
const Sizable = {
|
|
5915
5915
|
string: { unit: "karakter", verb: "legyen" },
|
|
@@ -6025,7 +6025,7 @@ function hu_default() {
|
|
|
6025
6025
|
localeError: error16()
|
|
6026
6026
|
};
|
|
6027
6027
|
}
|
|
6028
|
-
// node_modules
|
|
6028
|
+
// node_modules/zod/v4/locales/id.js
|
|
6029
6029
|
var error17 = () => {
|
|
6030
6030
|
const Sizable = {
|
|
6031
6031
|
string: { unit: "karakter", verb: "memiliki" },
|
|
@@ -6141,7 +6141,7 @@ function id_default() {
|
|
|
6141
6141
|
localeError: error17()
|
|
6142
6142
|
};
|
|
6143
6143
|
}
|
|
6144
|
-
// node_modules
|
|
6144
|
+
// node_modules/zod/v4/locales/is.js
|
|
6145
6145
|
var parsedType3 = (data) => {
|
|
6146
6146
|
const t = typeof data;
|
|
6147
6147
|
switch (t) {
|
|
@@ -6258,7 +6258,7 @@ function is_default() {
|
|
|
6258
6258
|
localeError: error18()
|
|
6259
6259
|
};
|
|
6260
6260
|
}
|
|
6261
|
-
// node_modules
|
|
6261
|
+
// node_modules/zod/v4/locales/it.js
|
|
6262
6262
|
var error19 = () => {
|
|
6263
6263
|
const Sizable = {
|
|
6264
6264
|
string: { unit: "caratteri", verb: "avere" },
|
|
@@ -6374,7 +6374,7 @@ function it_default() {
|
|
|
6374
6374
|
localeError: error19()
|
|
6375
6375
|
};
|
|
6376
6376
|
}
|
|
6377
|
-
// node_modules
|
|
6377
|
+
// node_modules/zod/v4/locales/ja.js
|
|
6378
6378
|
var error20 = () => {
|
|
6379
6379
|
const Sizable = {
|
|
6380
6380
|
string: { unit: "文字", verb: "である" },
|
|
@@ -6489,7 +6489,7 @@ function ja_default() {
|
|
|
6489
6489
|
localeError: error20()
|
|
6490
6490
|
};
|
|
6491
6491
|
}
|
|
6492
|
-
// node_modules
|
|
6492
|
+
// node_modules/zod/v4/locales/ka.js
|
|
6493
6493
|
var parsedType4 = (data) => {
|
|
6494
6494
|
const t = typeof data;
|
|
6495
6495
|
switch (t) {
|
|
@@ -6614,7 +6614,7 @@ function ka_default() {
|
|
|
6614
6614
|
localeError: error21()
|
|
6615
6615
|
};
|
|
6616
6616
|
}
|
|
6617
|
-
// node_modules
|
|
6617
|
+
// node_modules/zod/v4/locales/km.js
|
|
6618
6618
|
var error22 = () => {
|
|
6619
6619
|
const Sizable = {
|
|
6620
6620
|
string: { unit: "តួអក្សរ", verb: "គួរមាន" },
|
|
@@ -6732,11 +6732,11 @@ function km_default() {
|
|
|
6732
6732
|
};
|
|
6733
6733
|
}
|
|
6734
6734
|
|
|
6735
|
-
// node_modules
|
|
6735
|
+
// node_modules/zod/v4/locales/kh.js
|
|
6736
6736
|
function kh_default() {
|
|
6737
6737
|
return km_default();
|
|
6738
6738
|
}
|
|
6739
|
-
// node_modules
|
|
6739
|
+
// node_modules/zod/v4/locales/ko.js
|
|
6740
6740
|
var error23 = () => {
|
|
6741
6741
|
const Sizable = {
|
|
6742
6742
|
string: { unit: "문자", verb: "to have" },
|
|
@@ -6857,7 +6857,7 @@ function ko_default() {
|
|
|
6857
6857
|
localeError: error23()
|
|
6858
6858
|
};
|
|
6859
6859
|
}
|
|
6860
|
-
// node_modules
|
|
6860
|
+
// node_modules/zod/v4/locales/lt.js
|
|
6861
6861
|
var parsedType5 = (data) => {
|
|
6862
6862
|
const t = typeof data;
|
|
6863
6863
|
return parsedTypeFromType(t, data);
|
|
@@ -7086,7 +7086,7 @@ function lt_default() {
|
|
|
7086
7086
|
localeError: error24()
|
|
7087
7087
|
};
|
|
7088
7088
|
}
|
|
7089
|
-
// node_modules
|
|
7089
|
+
// node_modules/zod/v4/locales/mk.js
|
|
7090
7090
|
var error25 = () => {
|
|
7091
7091
|
const Sizable = {
|
|
7092
7092
|
string: { unit: "знаци", verb: "да имаат" },
|
|
@@ -7203,7 +7203,7 @@ function mk_default() {
|
|
|
7203
7203
|
localeError: error25()
|
|
7204
7204
|
};
|
|
7205
7205
|
}
|
|
7206
|
-
// node_modules
|
|
7206
|
+
// node_modules/zod/v4/locales/ms.js
|
|
7207
7207
|
var error26 = () => {
|
|
7208
7208
|
const Sizable = {
|
|
7209
7209
|
string: { unit: "aksara", verb: "mempunyai" },
|
|
@@ -7319,7 +7319,7 @@ function ms_default() {
|
|
|
7319
7319
|
localeError: error26()
|
|
7320
7320
|
};
|
|
7321
7321
|
}
|
|
7322
|
-
// node_modules
|
|
7322
|
+
// node_modules/zod/v4/locales/nl.js
|
|
7323
7323
|
var error27 = () => {
|
|
7324
7324
|
const Sizable = {
|
|
7325
7325
|
string: { unit: "tekens" },
|
|
@@ -7436,7 +7436,7 @@ function nl_default() {
|
|
|
7436
7436
|
localeError: error27()
|
|
7437
7437
|
};
|
|
7438
7438
|
}
|
|
7439
|
-
// node_modules
|
|
7439
|
+
// node_modules/zod/v4/locales/no.js
|
|
7440
7440
|
var error28 = () => {
|
|
7441
7441
|
const Sizable = {
|
|
7442
7442
|
string: { unit: "tegn", verb: "å ha" },
|
|
@@ -7552,7 +7552,7 @@ function no_default() {
|
|
|
7552
7552
|
localeError: error28()
|
|
7553
7553
|
};
|
|
7554
7554
|
}
|
|
7555
|
-
// node_modules
|
|
7555
|
+
// node_modules/zod/v4/locales/ota.js
|
|
7556
7556
|
var error29 = () => {
|
|
7557
7557
|
const Sizable = {
|
|
7558
7558
|
string: { unit: "harf", verb: "olmalıdır" },
|
|
@@ -7668,7 +7668,7 @@ function ota_default() {
|
|
|
7668
7668
|
localeError: error29()
|
|
7669
7669
|
};
|
|
7670
7670
|
}
|
|
7671
|
-
// node_modules
|
|
7671
|
+
// node_modules/zod/v4/locales/ps.js
|
|
7672
7672
|
var error30 = () => {
|
|
7673
7673
|
const Sizable = {
|
|
7674
7674
|
string: { unit: "توکي", verb: "ولري" },
|
|
@@ -7790,7 +7790,7 @@ function ps_default() {
|
|
|
7790
7790
|
localeError: error30()
|
|
7791
7791
|
};
|
|
7792
7792
|
}
|
|
7793
|
-
// node_modules
|
|
7793
|
+
// node_modules/zod/v4/locales/pl.js
|
|
7794
7794
|
var error31 = () => {
|
|
7795
7795
|
const Sizable = {
|
|
7796
7796
|
string: { unit: "znaków", verb: "mieć" },
|
|
@@ -7907,7 +7907,7 @@ function pl_default() {
|
|
|
7907
7907
|
localeError: error31()
|
|
7908
7908
|
};
|
|
7909
7909
|
}
|
|
7910
|
-
// node_modules
|
|
7910
|
+
// node_modules/zod/v4/locales/pt.js
|
|
7911
7911
|
var error32 = () => {
|
|
7912
7912
|
const Sizable = {
|
|
7913
7913
|
string: { unit: "caracteres", verb: "ter" },
|
|
@@ -8023,7 +8023,7 @@ function pt_default() {
|
|
|
8023
8023
|
localeError: error32()
|
|
8024
8024
|
};
|
|
8025
8025
|
}
|
|
8026
|
-
// node_modules
|
|
8026
|
+
// node_modules/zod/v4/locales/ru.js
|
|
8027
8027
|
function getRussianPlural(count, one, few, many) {
|
|
8028
8028
|
const absCount = Math.abs(count);
|
|
8029
8029
|
const lastDigit = absCount % 10;
|
|
@@ -8187,7 +8187,7 @@ function ru_default() {
|
|
|
8187
8187
|
localeError: error33()
|
|
8188
8188
|
};
|
|
8189
8189
|
}
|
|
8190
|
-
// node_modules
|
|
8190
|
+
// node_modules/zod/v4/locales/sl.js
|
|
8191
8191
|
var error34 = () => {
|
|
8192
8192
|
const Sizable = {
|
|
8193
8193
|
string: { unit: "znakov", verb: "imeti" },
|
|
@@ -8304,7 +8304,7 @@ function sl_default() {
|
|
|
8304
8304
|
localeError: error34()
|
|
8305
8305
|
};
|
|
8306
8306
|
}
|
|
8307
|
-
// node_modules
|
|
8307
|
+
// node_modules/zod/v4/locales/sv.js
|
|
8308
8308
|
var error35 = () => {
|
|
8309
8309
|
const Sizable = {
|
|
8310
8310
|
string: { unit: "tecken", verb: "att ha" },
|
|
@@ -8422,7 +8422,7 @@ function sv_default() {
|
|
|
8422
8422
|
localeError: error35()
|
|
8423
8423
|
};
|
|
8424
8424
|
}
|
|
8425
|
-
// node_modules
|
|
8425
|
+
// node_modules/zod/v4/locales/ta.js
|
|
8426
8426
|
var error36 = () => {
|
|
8427
8427
|
const Sizable = {
|
|
8428
8428
|
string: { unit: "எழுத்துக்கள்", verb: "கொண்டிருக்க வேண்டும்" },
|
|
@@ -8539,7 +8539,7 @@ function ta_default() {
|
|
|
8539
8539
|
localeError: error36()
|
|
8540
8540
|
};
|
|
8541
8541
|
}
|
|
8542
|
-
// node_modules
|
|
8542
|
+
// node_modules/zod/v4/locales/th.js
|
|
8543
8543
|
var error37 = () => {
|
|
8544
8544
|
const Sizable = {
|
|
8545
8545
|
string: { unit: "ตัวอักษร", verb: "ควรมี" },
|
|
@@ -8656,7 +8656,7 @@ function th_default() {
|
|
|
8656
8656
|
localeError: error37()
|
|
8657
8657
|
};
|
|
8658
8658
|
}
|
|
8659
|
-
// node_modules
|
|
8659
|
+
// node_modules/zod/v4/locales/tr.js
|
|
8660
8660
|
var parsedType6 = (data) => {
|
|
8661
8661
|
const t = typeof data;
|
|
8662
8662
|
switch (t) {
|
|
@@ -8771,7 +8771,7 @@ function tr_default() {
|
|
|
8771
8771
|
localeError: error38()
|
|
8772
8772
|
};
|
|
8773
8773
|
}
|
|
8774
|
-
// node_modules
|
|
8774
|
+
// node_modules/zod/v4/locales/uk.js
|
|
8775
8775
|
var error39 = () => {
|
|
8776
8776
|
const Sizable = {
|
|
8777
8777
|
string: { unit: "символів", verb: "матиме" },
|
|
@@ -8888,11 +8888,11 @@ function uk_default() {
|
|
|
8888
8888
|
};
|
|
8889
8889
|
}
|
|
8890
8890
|
|
|
8891
|
-
// node_modules
|
|
8891
|
+
// node_modules/zod/v4/locales/ua.js
|
|
8892
8892
|
function ua_default() {
|
|
8893
8893
|
return uk_default();
|
|
8894
8894
|
}
|
|
8895
|
-
// node_modules
|
|
8895
|
+
// node_modules/zod/v4/locales/ur.js
|
|
8896
8896
|
var error40 = () => {
|
|
8897
8897
|
const Sizable = {
|
|
8898
8898
|
string: { unit: "حروف", verb: "ہونا" },
|
|
@@ -9009,7 +9009,7 @@ function ur_default() {
|
|
|
9009
9009
|
localeError: error40()
|
|
9010
9010
|
};
|
|
9011
9011
|
}
|
|
9012
|
-
// node_modules
|
|
9012
|
+
// node_modules/zod/v4/locales/vi.js
|
|
9013
9013
|
var error41 = () => {
|
|
9014
9014
|
const Sizable = {
|
|
9015
9015
|
string: { unit: "ký tự", verb: "có" },
|
|
@@ -9125,7 +9125,7 @@ function vi_default() {
|
|
|
9125
9125
|
localeError: error41()
|
|
9126
9126
|
};
|
|
9127
9127
|
}
|
|
9128
|
-
// node_modules
|
|
9128
|
+
// node_modules/zod/v4/locales/zh-CN.js
|
|
9129
9129
|
var error42 = () => {
|
|
9130
9130
|
const Sizable = {
|
|
9131
9131
|
string: { unit: "字符", verb: "包含" },
|
|
@@ -9241,7 +9241,7 @@ function zh_CN_default() {
|
|
|
9241
9241
|
localeError: error42()
|
|
9242
9242
|
};
|
|
9243
9243
|
}
|
|
9244
|
-
// node_modules
|
|
9244
|
+
// node_modules/zod/v4/locales/zh-TW.js
|
|
9245
9245
|
var error43 = () => {
|
|
9246
9246
|
const Sizable = {
|
|
9247
9247
|
string: { unit: "字元", verb: "擁有" },
|
|
@@ -9358,7 +9358,7 @@ function zh_TW_default() {
|
|
|
9358
9358
|
localeError: error43()
|
|
9359
9359
|
};
|
|
9360
9360
|
}
|
|
9361
|
-
// node_modules
|
|
9361
|
+
// node_modules/zod/v4/locales/yo.js
|
|
9362
9362
|
var error44 = () => {
|
|
9363
9363
|
const Sizable = {
|
|
9364
9364
|
string: { unit: "àmi", verb: "ní" },
|
|
@@ -9473,7 +9473,7 @@ function yo_default() {
|
|
|
9473
9473
|
localeError: error44()
|
|
9474
9474
|
};
|
|
9475
9475
|
}
|
|
9476
|
-
// node_modules
|
|
9476
|
+
// node_modules/zod/v4/core/registries.js
|
|
9477
9477
|
var $output = Symbol("ZodOutput");
|
|
9478
9478
|
var $input = Symbol("ZodInput");
|
|
9479
9479
|
|
|
@@ -9524,7 +9524,7 @@ function registry() {
|
|
|
9524
9524
|
return new $ZodRegistry;
|
|
9525
9525
|
}
|
|
9526
9526
|
var globalRegistry = /* @__PURE__ */ registry();
|
|
9527
|
-
// node_modules
|
|
9527
|
+
// node_modules/zod/v4/core/api.js
|
|
9528
9528
|
function _string(Class2, params) {
|
|
9529
9529
|
return new Class2({
|
|
9530
9530
|
type: "string",
|
|
@@ -10402,7 +10402,7 @@ function _stringFormat(Class2, format, fnOrRegex, _params = {}) {
|
|
|
10402
10402
|
const inst = new Class2(def);
|
|
10403
10403
|
return inst;
|
|
10404
10404
|
}
|
|
10405
|
-
// node_modules
|
|
10405
|
+
// node_modules/zod/v4/core/to-json-schema.js
|
|
10406
10406
|
class JSONSchemaGenerator {
|
|
10407
10407
|
constructor(params) {
|
|
10408
10408
|
this.counter = 0;
|
|
@@ -11206,9 +11206,9 @@ function isTransforming(_schema, _ctx) {
|
|
|
11206
11206
|
}
|
|
11207
11207
|
throw new Error(`Unknown schema type: ${def.type}`);
|
|
11208
11208
|
}
|
|
11209
|
-
// node_modules
|
|
11209
|
+
// node_modules/zod/v4/core/json-schema.js
|
|
11210
11210
|
var exports_json_schema = {};
|
|
11211
|
-
// node_modules
|
|
11211
|
+
// node_modules/zod/v4/classic/iso.js
|
|
11212
11212
|
var exports_iso = {};
|
|
11213
11213
|
__export(exports_iso, {
|
|
11214
11214
|
time: () => time2,
|
|
@@ -11249,7 +11249,7 @@ function duration2(params) {
|
|
|
11249
11249
|
return _isoDuration(ZodISODuration, params);
|
|
11250
11250
|
}
|
|
11251
11251
|
|
|
11252
|
-
// node_modules
|
|
11252
|
+
// node_modules/zod/v4/classic/errors.js
|
|
11253
11253
|
var initializer2 = (inst, issues) => {
|
|
11254
11254
|
$ZodError.init(inst, issues);
|
|
11255
11255
|
inst.name = "ZodError";
|
|
@@ -11284,7 +11284,7 @@ var ZodRealError = $constructor("ZodError", initializer2, {
|
|
|
11284
11284
|
Parent: Error
|
|
11285
11285
|
});
|
|
11286
11286
|
|
|
11287
|
-
// node_modules
|
|
11287
|
+
// node_modules/zod/v4/classic/parse.js
|
|
11288
11288
|
var parse3 = /* @__PURE__ */ _parse(ZodRealError);
|
|
11289
11289
|
var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
11290
11290
|
var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
@@ -11298,7 +11298,7 @@ var safeDecode2 = /* @__PURE__ */ _safeDecode(ZodRealError);
|
|
|
11298
11298
|
var safeEncodeAsync2 = /* @__PURE__ */ _safeEncodeAsync(ZodRealError);
|
|
11299
11299
|
var safeDecodeAsync2 = /* @__PURE__ */ _safeDecodeAsync(ZodRealError);
|
|
11300
11300
|
|
|
11301
|
-
// node_modules
|
|
11301
|
+
// node_modules/zod/v4/classic/schemas.js
|
|
11302
11302
|
var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
11303
11303
|
$ZodType.init(inst, def);
|
|
11304
11304
|
inst.def = def;
|
|
@@ -12273,7 +12273,7 @@ function json(params) {
|
|
|
12273
12273
|
function preprocess(fn, schema) {
|
|
12274
12274
|
return pipe(transform(fn), schema);
|
|
12275
12275
|
}
|
|
12276
|
-
// node_modules
|
|
12276
|
+
// node_modules/zod/v4/classic/compat.js
|
|
12277
12277
|
var ZodIssueCode = {
|
|
12278
12278
|
invalid_type: "invalid_type",
|
|
12279
12279
|
too_big: "too_big",
|
|
@@ -12297,7 +12297,7 @@ function getErrorMap() {
|
|
|
12297
12297
|
}
|
|
12298
12298
|
var ZodFirstPartyTypeKind;
|
|
12299
12299
|
(function(ZodFirstPartyTypeKind2) {})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
|
|
12300
|
-
// node_modules
|
|
12300
|
+
// node_modules/zod/v4/classic/coerce.js
|
|
12301
12301
|
var exports_coerce = {};
|
|
12302
12302
|
__export(exports_coerce, {
|
|
12303
12303
|
string: () => string3,
|
|
@@ -12322,7 +12322,7 @@ function date4(params) {
|
|
|
12322
12322
|
return _coercedDate(ZodDate, params);
|
|
12323
12323
|
}
|
|
12324
12324
|
|
|
12325
|
-
// node_modules
|
|
12325
|
+
// node_modules/zod/v4/classic/external.js
|
|
12326
12326
|
config(en_default());
|
|
12327
12327
|
// node_modules/@opencode-ai/plugin/dist/tool.js
|
|
12328
12328
|
function tool(input) {
|
|
@@ -12334,9 +12334,9 @@ import net2 from "net";
|
|
|
12334
12334
|
|
|
12335
12335
|
// src/agent-backend.ts
|
|
12336
12336
|
import net from "net";
|
|
12337
|
-
import { readFileSync } from "fs";
|
|
12338
|
-
import { tmpdir } from "os";
|
|
12339
|
-
import { join } from "path";
|
|
12337
|
+
import { mkdirSync, readFileSync } from "fs";
|
|
12338
|
+
import { homedir, tmpdir } from "os";
|
|
12339
|
+
import { basename, dirname, isAbsolute, join, resolve } from "path";
|
|
12340
12340
|
import { spawn } from "child_process";
|
|
12341
12341
|
import { createRequire } from "module";
|
|
12342
12342
|
var agentRequire = createRequire(import.meta.url);
|
|
@@ -12344,6 +12344,8 @@ var REQUEST_TIMEOUT_MS = 60000;
|
|
|
12344
12344
|
var DEFAULT_PAGE_TEXT_LIMIT = 20000;
|
|
12345
12345
|
var DEFAULT_LIST_LIMIT = 50;
|
|
12346
12346
|
var DEFAULT_POLL_MS = 200;
|
|
12347
|
+
var BASE_DIR = join(homedir(), ".opencode-browser");
|
|
12348
|
+
var DEFAULT_DOWNLOADS_DIR = join(BASE_DIR, "downloads");
|
|
12347
12349
|
function createJsonLineParser(onMessage) {
|
|
12348
12350
|
let buffer = "";
|
|
12349
12351
|
return (chunk) => {
|
|
@@ -12368,7 +12370,7 @@ function writeJsonLine(socket, msg) {
|
|
|
12368
12370
|
`);
|
|
12369
12371
|
}
|
|
12370
12372
|
async function sleep(ms) {
|
|
12371
|
-
return await new Promise((
|
|
12373
|
+
return await new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
12372
12374
|
}
|
|
12373
12375
|
function parseEnvNumber(value) {
|
|
12374
12376
|
if (!value)
|
|
@@ -12670,13 +12672,40 @@ function ensureEvalResult(result, fallback) {
|
|
|
12670
12672
|
function createAgentBackend(sessionId) {
|
|
12671
12673
|
const session = getAgentSession(sessionId);
|
|
12672
12674
|
const connection = getAgentConnectionInfo(session);
|
|
12675
|
+
const downloadsDir = (() => {
|
|
12676
|
+
const raw = process.env.OPENCODE_BROWSER_AGENT_DOWNLOADS_DIR?.trim();
|
|
12677
|
+
if (!raw)
|
|
12678
|
+
return DEFAULT_DOWNLOADS_DIR;
|
|
12679
|
+
return isAbsolute(raw) ? raw : resolve(process.cwd(), raw);
|
|
12680
|
+
})();
|
|
12681
|
+
mkdirSync(downloadsDir, { recursive: true });
|
|
12682
|
+
const downloads = [];
|
|
12683
|
+
function resolveDownloadPath(filename, urlValue) {
|
|
12684
|
+
let name = typeof filename === "string" ? filename.trim() : "";
|
|
12685
|
+
if (!name && typeof urlValue === "string") {
|
|
12686
|
+
try {
|
|
12687
|
+
const u = new URL(urlValue);
|
|
12688
|
+
name = basename(u.pathname) || "";
|
|
12689
|
+
} catch {}
|
|
12690
|
+
}
|
|
12691
|
+
if (!name)
|
|
12692
|
+
name = `download-${Date.now()}`;
|
|
12693
|
+
const fullPath = isAbsolute(name) ? name : join(downloadsDir, name);
|
|
12694
|
+
mkdirSync(dirname(fullPath), { recursive: true });
|
|
12695
|
+
return fullPath;
|
|
12696
|
+
}
|
|
12697
|
+
function recordDownload(entry) {
|
|
12698
|
+
downloads.unshift({ ...entry, timestamp: new Date().toISOString() });
|
|
12699
|
+
if (downloads.length > 50)
|
|
12700
|
+
downloads.length = 50;
|
|
12701
|
+
}
|
|
12673
12702
|
let agentSocket = null;
|
|
12674
12703
|
let agentReqId = 0;
|
|
12675
12704
|
const agentPending = new Map;
|
|
12676
12705
|
async function connectToAgent() {
|
|
12677
|
-
return await new Promise((
|
|
12706
|
+
return await new Promise((resolve2, reject) => {
|
|
12678
12707
|
const socket = connection.type === "unix" ? net.createConnection(connection.path) : net.createConnection({ host: connection.host, port: connection.port });
|
|
12679
|
-
socket.once("connect", () =>
|
|
12708
|
+
socket.once("connect", () => resolve2(socket));
|
|
12680
12709
|
socket.once("error", (err) => reject(err));
|
|
12681
12710
|
});
|
|
12682
12711
|
}
|
|
@@ -12729,8 +12758,8 @@ function createAgentBackend(sessionId) {
|
|
|
12729
12758
|
async function agentRequest(action, payload) {
|
|
12730
12759
|
const socket = await ensureAgentSocket();
|
|
12731
12760
|
const id = `a${++agentReqId}`;
|
|
12732
|
-
return await new Promise((
|
|
12733
|
-
agentPending.set(id, { resolve, reject });
|
|
12761
|
+
return await new Promise((resolve2, reject) => {
|
|
12762
|
+
agentPending.set(id, { resolve: resolve2, reject });
|
|
12734
12763
|
writeJsonLine(socket, { id, action, ...payload });
|
|
12735
12764
|
setTimeout(() => {
|
|
12736
12765
|
if (!agentPending.has(id))
|
|
@@ -12847,6 +12876,9 @@ function createAgentBackend(sessionId) {
|
|
|
12847
12876
|
}));
|
|
12848
12877
|
return { content: JSON.stringify(mapped, null, 2) };
|
|
12849
12878
|
}
|
|
12879
|
+
case "list_downloads": {
|
|
12880
|
+
return { content: JSON.stringify({ downloads }, null, 2) };
|
|
12881
|
+
}
|
|
12850
12882
|
case "open_tab": {
|
|
12851
12883
|
const active = args.active;
|
|
12852
12884
|
let previousActive = null;
|
|
@@ -12880,6 +12912,48 @@ function createAgentBackend(sessionId) {
|
|
|
12880
12912
|
return { content: `Navigated to ${args.url}` };
|
|
12881
12913
|
});
|
|
12882
12914
|
}
|
|
12915
|
+
case "download": {
|
|
12916
|
+
return await withTab(args.tabId, async () => {
|
|
12917
|
+
const url2 = typeof args.url === "string" ? args.url.trim() : "";
|
|
12918
|
+
const selector = typeof args.selector === "string" ? args.selector.trim() : "";
|
|
12919
|
+
const filename = typeof args.filename === "string" ? args.filename.trim() : "";
|
|
12920
|
+
const waitValue = args.wait === undefined ? false : !!args.wait;
|
|
12921
|
+
const timeoutValue = Number.isFinite(args.downloadTimeoutMs) ? args.downloadTimeoutMs : undefined;
|
|
12922
|
+
if (!url2 && !selector)
|
|
12923
|
+
throw new Error("url or selector is required");
|
|
12924
|
+
if (url2 && selector)
|
|
12925
|
+
throw new Error("Provide either url or selector, not both");
|
|
12926
|
+
if (!waitValue) {
|
|
12927
|
+
if (selector) {
|
|
12928
|
+
await agentCommand("click", { selector });
|
|
12929
|
+
return { content: JSON.stringify({ ok: true, started: true, selector }, null, 2) };
|
|
12930
|
+
}
|
|
12931
|
+
await agentCommand("navigate", { url: url2 });
|
|
12932
|
+
return { content: JSON.stringify({ ok: true, started: true, url: url2 }, null, 2) };
|
|
12933
|
+
}
|
|
12934
|
+
if (selector) {
|
|
12935
|
+
const path2 = resolveDownloadPath(filename || undefined);
|
|
12936
|
+
const data2 = await agentCommand("download", { selector, path: path2 });
|
|
12937
|
+
const entry2 = {
|
|
12938
|
+
path: String(data2?.path || path2),
|
|
12939
|
+
filename: typeof data2?.suggestedFilename === "string" ? data2.suggestedFilename : undefined,
|
|
12940
|
+
url: url2 || undefined
|
|
12941
|
+
};
|
|
12942
|
+
recordDownload({ path: entry2.path, filename: entry2.filename, url: entry2.url });
|
|
12943
|
+
return { content: JSON.stringify({ ok: true, ...entry2 }, null, 2) };
|
|
12944
|
+
}
|
|
12945
|
+
const path = resolveDownloadPath(filename || undefined, url2);
|
|
12946
|
+
await agentCommand("navigate", { url: url2 });
|
|
12947
|
+
const data = await agentCommand("waitfordownload", { path, timeout: timeoutValue });
|
|
12948
|
+
const entry = {
|
|
12949
|
+
path: String(data?.path || path),
|
|
12950
|
+
filename: typeof data?.filename === "string" ? data.filename : undefined,
|
|
12951
|
+
url: typeof data?.url === "string" ? data.url : url2
|
|
12952
|
+
};
|
|
12953
|
+
recordDownload({ path: entry.path, filename: entry.filename, url: entry.url });
|
|
12954
|
+
return { content: JSON.stringify({ ok: true, ...entry }, null, 2) };
|
|
12955
|
+
});
|
|
12956
|
+
}
|
|
12883
12957
|
case "click": {
|
|
12884
12958
|
return await withTab(args.tabId, async () => {
|
|
12885
12959
|
if (!args.selector)
|
|
@@ -12941,6 +13015,22 @@ function createAgentBackend(sessionId) {
|
|
|
12941
13015
|
return { content: `Selected ${summary} in ${args.selector}` };
|
|
12942
13016
|
});
|
|
12943
13017
|
}
|
|
13018
|
+
case "set_file_input": {
|
|
13019
|
+
return await withTab(args.tabId, async () => {
|
|
13020
|
+
if (!args.selector)
|
|
13021
|
+
throw new Error("Selector is required");
|
|
13022
|
+
if (!args.filePath)
|
|
13023
|
+
throw new Error("filePath is required");
|
|
13024
|
+
const rawPath = String(args.filePath).trim();
|
|
13025
|
+
if (!rawPath)
|
|
13026
|
+
throw new Error("filePath is required");
|
|
13027
|
+
const absPath = isAbsolute(rawPath) ? rawPath : resolve(process.cwd(), rawPath);
|
|
13028
|
+
const data = await agentCommand("upload", { selector: args.selector, files: absPath });
|
|
13029
|
+
return {
|
|
13030
|
+
content: JSON.stringify({ ok: true, selector: args.selector, uploaded: data?.uploaded ?? [absPath] }, null, 2)
|
|
13031
|
+
};
|
|
13032
|
+
});
|
|
13033
|
+
}
|
|
12944
13034
|
case "screenshot": {
|
|
12945
13035
|
return await withTab(args.tabId, async () => {
|
|
12946
13036
|
const data = await agentCommand("screenshot", { format: "png" });
|
|
@@ -13018,13 +13108,13 @@ function createAgentBackend(sessionId) {
|
|
|
13018
13108
|
}
|
|
13019
13109
|
|
|
13020
13110
|
// src/plugin.ts
|
|
13021
|
-
import { existsSync, mkdirSync, readFileSync as readFileSync2 } from "fs";
|
|
13022
|
-
import { homedir } from "os";
|
|
13023
|
-
import { dirname, join as join2 } from "path";
|
|
13111
|
+
import { appendFileSync, existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, statSync } from "fs";
|
|
13112
|
+
import { homedir as homedir2, userInfo } from "os";
|
|
13113
|
+
import { basename as basename2, dirname as dirname2, isAbsolute as isAbsolute2, join as join2, resolve as resolve2 } from "path";
|
|
13024
13114
|
import { spawn as spawn2 } from "child_process";
|
|
13025
13115
|
import { fileURLToPath } from "url";
|
|
13026
13116
|
var __filename2 = fileURLToPath(import.meta.url);
|
|
13027
|
-
var __dirname2 =
|
|
13117
|
+
var __dirname2 = dirname2(__filename2);
|
|
13028
13118
|
var PACKAGE_JSON_PATH = join2(__dirname2, "..", "package.json");
|
|
13029
13119
|
var cachedVersion = null;
|
|
13030
13120
|
function getPackageVersion() {
|
|
@@ -13041,9 +13131,60 @@ function getPackageVersion() {
|
|
|
13041
13131
|
return cachedVersion;
|
|
13042
13132
|
}
|
|
13043
13133
|
var { schema } = tool;
|
|
13044
|
-
var
|
|
13045
|
-
var SOCKET_PATH =
|
|
13046
|
-
|
|
13134
|
+
var BASE_DIR2 = join2(homedir2(), ".opencode-browser");
|
|
13135
|
+
var SOCKET_PATH = getBrokerSocketPath();
|
|
13136
|
+
var LOG_PATH = join2(BASE_DIR2, "plugin.log");
|
|
13137
|
+
function getSafePipeName() {
|
|
13138
|
+
try {
|
|
13139
|
+
const username = userInfo().username || "user";
|
|
13140
|
+
return `opencode-browser-${username}`.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
13141
|
+
} catch {
|
|
13142
|
+
return "opencode-browser";
|
|
13143
|
+
}
|
|
13144
|
+
}
|
|
13145
|
+
function getBrokerSocketPath() {
|
|
13146
|
+
const override = process.env.OPENCODE_BROWSER_BROKER_SOCKET;
|
|
13147
|
+
if (override)
|
|
13148
|
+
return override;
|
|
13149
|
+
if (process.platform === "win32")
|
|
13150
|
+
return `\\\\.\\pipe\\${getSafePipeName()}`;
|
|
13151
|
+
return join2(BASE_DIR2, "broker.sock");
|
|
13152
|
+
}
|
|
13153
|
+
mkdirSync2(BASE_DIR2, { recursive: true });
|
|
13154
|
+
function logDebug(message) {
|
|
13155
|
+
try {
|
|
13156
|
+
appendFileSync(LOG_PATH, `[${new Date().toISOString()}] ${message}
|
|
13157
|
+
`, "utf8");
|
|
13158
|
+
} catch {}
|
|
13159
|
+
}
|
|
13160
|
+
logDebug(`plugin loaded v${getPackageVersion()} pid=${process.pid} socket=${SOCKET_PATH}`);
|
|
13161
|
+
var DEFAULT_MAX_UPLOAD_BYTES = 512 * 1024;
|
|
13162
|
+
var MAX_UPLOAD_BYTES = (() => {
|
|
13163
|
+
const raw = process.env.OPENCODE_BROWSER_MAX_UPLOAD_BYTES;
|
|
13164
|
+
const value = raw ? Number(raw) : NaN;
|
|
13165
|
+
if (Number.isFinite(value) && value > 0)
|
|
13166
|
+
return value;
|
|
13167
|
+
return DEFAULT_MAX_UPLOAD_BYTES;
|
|
13168
|
+
})();
|
|
13169
|
+
function resolveUploadPath(filePath) {
|
|
13170
|
+
const trimmed = typeof filePath === "string" ? filePath.trim() : "";
|
|
13171
|
+
if (!trimmed)
|
|
13172
|
+
throw new Error("filePath is required");
|
|
13173
|
+
return isAbsolute2(trimmed) ? trimmed : resolve2(process.cwd(), trimmed);
|
|
13174
|
+
}
|
|
13175
|
+
function buildFileUploadPayload(filePath, fileName, mimeType) {
|
|
13176
|
+
const absPath = resolveUploadPath(filePath);
|
|
13177
|
+
const stats = statSync(absPath);
|
|
13178
|
+
if (!stats.isFile())
|
|
13179
|
+
throw new Error(`Not a file: ${absPath}`);
|
|
13180
|
+
if (stats.size > MAX_UPLOAD_BYTES) {
|
|
13181
|
+
throw new Error(`File too large (${stats.size} bytes). Max is ${MAX_UPLOAD_BYTES} bytes (OPENCODE_BROWSER_MAX_UPLOAD_BYTES). ` + `For larger uploads, use OPENCODE_BROWSER_BACKEND=agent.`);
|
|
13182
|
+
}
|
|
13183
|
+
const base643 = readFileSync2(absPath).toString("base64");
|
|
13184
|
+
const name = typeof fileName === "string" && fileName.trim() ? fileName.trim() : basename2(absPath);
|
|
13185
|
+
const mt = typeof mimeType === "string" && mimeType.trim() ? mimeType.trim() : undefined;
|
|
13186
|
+
return { name, mimeType: mt, base64: base643 };
|
|
13187
|
+
}
|
|
13047
13188
|
function createJsonLineParser2(onMessage) {
|
|
13048
13189
|
let buffer = "";
|
|
13049
13190
|
return (chunk) => {
|
|
@@ -13068,7 +13209,7 @@ function writeJsonLine2(socket, msg) {
|
|
|
13068
13209
|
`);
|
|
13069
13210
|
}
|
|
13070
13211
|
function maybeStartBroker() {
|
|
13071
|
-
const brokerPath = join2(
|
|
13212
|
+
const brokerPath = join2(BASE_DIR2, "broker.cjs");
|
|
13072
13213
|
if (!existsSync(brokerPath))
|
|
13073
13214
|
return;
|
|
13074
13215
|
try {
|
|
@@ -13077,10 +13218,14 @@ function maybeStartBroker() {
|
|
|
13077
13218
|
} catch {}
|
|
13078
13219
|
}
|
|
13079
13220
|
async function connectToBroker() {
|
|
13080
|
-
return await new Promise((
|
|
13221
|
+
return await new Promise((resolve3, reject) => {
|
|
13081
13222
|
const socket = net2.createConnection(SOCKET_PATH);
|
|
13082
|
-
socket.once("connect", () =>
|
|
13083
|
-
socket.once("error", (err) =>
|
|
13223
|
+
socket.once("connect", () => resolve3(socket));
|
|
13224
|
+
socket.once("error", (err) => {
|
|
13225
|
+
lastBrokerError = err instanceof Error ? err : new Error(String(err));
|
|
13226
|
+
logDebug(`broker connect error socket=${SOCKET_PATH} error=${lastBrokerError.message}`);
|
|
13227
|
+
reject(err);
|
|
13228
|
+
});
|
|
13084
13229
|
});
|
|
13085
13230
|
}
|
|
13086
13231
|
async function sleep2(ms) {
|
|
@@ -13089,6 +13234,7 @@ async function sleep2(ms) {
|
|
|
13089
13234
|
var BACKEND_MODE = (process.env.OPENCODE_BROWSER_BACKEND ?? process.env.OPENCODE_BROWSER_MODE ?? "extension").toLowerCase().trim();
|
|
13090
13235
|
var USE_AGENT_BACKEND = ["agent", "agent-browser", "agentbrowser"].includes(BACKEND_MODE);
|
|
13091
13236
|
var socket = null;
|
|
13237
|
+
var lastBrokerError = null;
|
|
13092
13238
|
var sessionId = Math.random().toString(36).slice(2);
|
|
13093
13239
|
var reqId = 0;
|
|
13094
13240
|
var pending = new Map;
|
|
@@ -13109,9 +13255,11 @@ async function ensureBrokerSocket() {
|
|
|
13109
13255
|
}
|
|
13110
13256
|
}
|
|
13111
13257
|
if (!socket || socket.destroyed) {
|
|
13112
|
-
|
|
13258
|
+
const errorMessage = lastBrokerError?.message ? ` (${lastBrokerError.message})` : "";
|
|
13259
|
+
throw new Error(`Could not connect to local broker at ${SOCKET_PATH}${errorMessage}. ` + "Run `npx @different-ai/opencode-browser install` and ensure the extension is loaded.");
|
|
13113
13260
|
}
|
|
13114
13261
|
socket.setNoDelay(true);
|
|
13262
|
+
logDebug(`broker connected socket=${SOCKET_PATH}`);
|
|
13115
13263
|
socket.on("data", createJsonLineParser2((msg) => {
|
|
13116
13264
|
if (msg?.type !== "response" || typeof msg.id !== "number")
|
|
13117
13265
|
return;
|
|
@@ -13137,8 +13285,8 @@ async function ensureBrokerSocket() {
|
|
|
13137
13285
|
async function brokerRequest(op, payload) {
|
|
13138
13286
|
const s = await ensureBrokerSocket();
|
|
13139
13287
|
const id = ++reqId;
|
|
13140
|
-
return await new Promise((
|
|
13141
|
-
pending.set(id, { resolve, reject });
|
|
13288
|
+
return await new Promise((resolve3, reject) => {
|
|
13289
|
+
pending.set(id, { resolve: resolve3, reject });
|
|
13142
13290
|
writeJsonLine2(s, { type: "request", id, op, ...payload });
|
|
13143
13291
|
setTimeout(() => {
|
|
13144
13292
|
if (!pending.has(id))
|
|
@@ -13192,18 +13340,20 @@ var plugin = async (ctx) => {
|
|
|
13192
13340
|
description: "Debug plugin loading and connection status.",
|
|
13193
13341
|
args: {},
|
|
13194
13342
|
async execute(args, ctx2) {
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
|
|
13201
|
-
agentSession: agentBackend?.session ??
|
|
13202
|
-
agentConnection: agentBackend?.connection ?? null
|
|
13203
|
-
agentBrowserVersion: agentBackend?.getVersion?.() ??
|
|
13204
|
-
pluginVersion: getPackageVersion()
|
|
13205
|
-
timestamp: new Date().toISOString()
|
|
13206
|
-
|
|
13343
|
+
const lines = [
|
|
13344
|
+
"loaded: true",
|
|
13345
|
+
`sessionId: ${sessionId}`,
|
|
13346
|
+
`pid: ${process.pid}`,
|
|
13347
|
+
`backend: ${USE_AGENT_BACKEND ? "agent-browser" : "extension"}`,
|
|
13348
|
+
`brokerSocket: ${SOCKET_PATH}`,
|
|
13349
|
+
`agentSession: ${agentBackend?.session ?? ""}`,
|
|
13350
|
+
`agentConnection: ${JSON.stringify(agentBackend?.connection ?? null)}`,
|
|
13351
|
+
`agentBrowserVersion: ${agentBackend?.getVersion?.() ?? ""}`,
|
|
13352
|
+
`pluginVersion: ${getPackageVersion()}`,
|
|
13353
|
+
`timestamp: ${new Date().toISOString()}`
|
|
13354
|
+
];
|
|
13355
|
+
return lines.join(`
|
|
13356
|
+
`);
|
|
13207
13357
|
}
|
|
13208
13358
|
}),
|
|
13209
13359
|
browser_version: tool({
|
|
@@ -13422,6 +13572,127 @@ var plugin = async (ctx) => {
|
|
|
13422
13572
|
});
|
|
13423
13573
|
return toolResultText(data, "Query failed");
|
|
13424
13574
|
}
|
|
13575
|
+
}),
|
|
13576
|
+
browser_download: tool({
|
|
13577
|
+
description: "Download a file via URL or by clicking an element on the page.",
|
|
13578
|
+
args: {
|
|
13579
|
+
url: schema.string().optional(),
|
|
13580
|
+
selector: schema.string().optional(),
|
|
13581
|
+
filename: schema.string().optional(),
|
|
13582
|
+
conflictAction: schema.string().optional(),
|
|
13583
|
+
saveAs: schema.boolean().optional(),
|
|
13584
|
+
wait: schema.boolean().optional(),
|
|
13585
|
+
downloadTimeoutMs: schema.number().optional(),
|
|
13586
|
+
index: schema.number().optional(),
|
|
13587
|
+
tabId: schema.number().optional(),
|
|
13588
|
+
timeoutMs: schema.number().optional(),
|
|
13589
|
+
pollMs: schema.number().optional()
|
|
13590
|
+
},
|
|
13591
|
+
async execute({ url: url2, selector, filename, conflictAction, saveAs, wait, downloadTimeoutMs, index, tabId, timeoutMs, pollMs }, ctx2) {
|
|
13592
|
+
const data = await toolRequest("download", {
|
|
13593
|
+
url: url2,
|
|
13594
|
+
selector,
|
|
13595
|
+
filename,
|
|
13596
|
+
conflictAction,
|
|
13597
|
+
saveAs,
|
|
13598
|
+
wait,
|
|
13599
|
+
downloadTimeoutMs,
|
|
13600
|
+
index,
|
|
13601
|
+
tabId,
|
|
13602
|
+
timeoutMs,
|
|
13603
|
+
pollMs
|
|
13604
|
+
});
|
|
13605
|
+
return toolResultText(data, "Download started");
|
|
13606
|
+
}
|
|
13607
|
+
}),
|
|
13608
|
+
browser_list_downloads: tool({
|
|
13609
|
+
description: "List recent downloads (Chrome backend) or session downloads (agent backend).",
|
|
13610
|
+
args: {
|
|
13611
|
+
limit: schema.number().optional(),
|
|
13612
|
+
state: schema.string().optional()
|
|
13613
|
+
},
|
|
13614
|
+
async execute({ limit, state }, ctx2) {
|
|
13615
|
+
const data = await toolRequest("list_downloads", { limit, state });
|
|
13616
|
+
return toolResultText(data, "[]");
|
|
13617
|
+
}
|
|
13618
|
+
}),
|
|
13619
|
+
browser_set_file_input: tool({
|
|
13620
|
+
description: "Set a file input element's selected file using a local file path.",
|
|
13621
|
+
args: {
|
|
13622
|
+
selector: schema.string(),
|
|
13623
|
+
filePath: schema.string(),
|
|
13624
|
+
fileName: schema.string().optional(),
|
|
13625
|
+
mimeType: schema.string().optional(),
|
|
13626
|
+
index: schema.number().optional(),
|
|
13627
|
+
tabId: schema.number().optional(),
|
|
13628
|
+
timeoutMs: schema.number().optional(),
|
|
13629
|
+
pollMs: schema.number().optional()
|
|
13630
|
+
},
|
|
13631
|
+
async execute({ selector, filePath, fileName, mimeType, index, tabId, timeoutMs, pollMs }, ctx2) {
|
|
13632
|
+
if (USE_AGENT_BACKEND) {
|
|
13633
|
+
const data2 = await toolRequest("set_file_input", { selector, filePath, tabId, index, timeoutMs, pollMs });
|
|
13634
|
+
return toolResultText(data2, "Set file input");
|
|
13635
|
+
}
|
|
13636
|
+
const file2 = buildFileUploadPayload(filePath, fileName, mimeType);
|
|
13637
|
+
const data = await toolRequest("set_file_input", {
|
|
13638
|
+
selector,
|
|
13639
|
+
tabId,
|
|
13640
|
+
index,
|
|
13641
|
+
timeoutMs,
|
|
13642
|
+
pollMs,
|
|
13643
|
+
files: [file2]
|
|
13644
|
+
});
|
|
13645
|
+
return toolResultText(data, "Set file input");
|
|
13646
|
+
}
|
|
13647
|
+
}),
|
|
13648
|
+
browser_highlight: tool({
|
|
13649
|
+
description: "Highlight an element on the page with a colored border for visual debugging.",
|
|
13650
|
+
args: {
|
|
13651
|
+
selector: schema.string(),
|
|
13652
|
+
index: schema.number().optional(),
|
|
13653
|
+
duration: schema.number().optional(),
|
|
13654
|
+
color: schema.string().optional(),
|
|
13655
|
+
showInfo: schema.boolean().optional(),
|
|
13656
|
+
tabId: schema.number().optional(),
|
|
13657
|
+
timeoutMs: schema.number().optional(),
|
|
13658
|
+
pollMs: schema.number().optional()
|
|
13659
|
+
},
|
|
13660
|
+
async execute({ selector, index, duration: duration3, color, showInfo, tabId, timeoutMs, pollMs }, ctx2) {
|
|
13661
|
+
const data = await toolRequest("highlight", {
|
|
13662
|
+
selector,
|
|
13663
|
+
index,
|
|
13664
|
+
duration: duration3,
|
|
13665
|
+
color,
|
|
13666
|
+
showInfo,
|
|
13667
|
+
tabId,
|
|
13668
|
+
timeoutMs,
|
|
13669
|
+
pollMs
|
|
13670
|
+
});
|
|
13671
|
+
return toolResultText(data, "Highlight failed");
|
|
13672
|
+
}
|
|
13673
|
+
}),
|
|
13674
|
+
browser_console: tool({
|
|
13675
|
+
description: "Read console log messages from the page. Uses chrome.debugger API for complete capture. " + "The debugger attaches lazily on first call and may show a banner in the browser.",
|
|
13676
|
+
args: {
|
|
13677
|
+
tabId: schema.number().optional(),
|
|
13678
|
+
clear: schema.boolean().optional(),
|
|
13679
|
+
filter: schema.string().optional()
|
|
13680
|
+
},
|
|
13681
|
+
async execute({ tabId, clear, filter }, ctx2) {
|
|
13682
|
+
const data = await toolRequest("console", { tabId, clear, filter });
|
|
13683
|
+
return toolResultText(data, "[]");
|
|
13684
|
+
}
|
|
13685
|
+
}),
|
|
13686
|
+
browser_errors: tool({
|
|
13687
|
+
description: "Read JavaScript errors from the page. Uses chrome.debugger API for complete capture. " + "The debugger attaches lazily on first call and may show a banner in the browser.",
|
|
13688
|
+
args: {
|
|
13689
|
+
tabId: schema.number().optional(),
|
|
13690
|
+
clear: schema.boolean().optional()
|
|
13691
|
+
},
|
|
13692
|
+
async execute({ tabId, clear }, ctx2) {
|
|
13693
|
+
const data = await toolRequest("errors", { tabId, clear });
|
|
13694
|
+
return toolResultText(data, "[]");
|
|
13695
|
+
}
|
|
13425
13696
|
})
|
|
13426
13697
|
}
|
|
13427
13698
|
};
|