@spec-box/sdd 0.6.4 → 0.7.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/README.md +28 -1
- package/assets/ci/Dockerfile +2 -0
- package/assets/hosts/claude/agent.md +13 -0
- package/assets/project/testing.md +4 -0
- package/assets/roles/challenger.md +4 -0
- package/assets/roles/distiller.md +4 -0
- package/assets/roles/implementer.md +4 -0
- package/assets/roles/planner.md +4 -0
- package/assets/roles/researcher.md +8 -3
- package/assets/roles/reviewer.md +4 -0
- package/assets/roles/tester.md +5 -1
- package/assets/roles/verifier.md +5 -1
- package/assets/skills/sbox-approve.md +11 -0
- package/assets/skills/sbox-browser.md +31 -0
- package/assets/skills/sbox-run.md +24 -0
- package/bin/sbox-browser.js +5 -0
- package/dist/adapters/host/claude/index.js +27 -85
- package/dist/adapters/host/claude/index.js.map +1 -1
- package/dist/adapters/host/index.js +25 -0
- package/dist/adapters/host/index.js.map +1 -0
- package/dist/adapters/host/skills.js +27 -0
- package/dist/adapters/host/skills.js.map +1 -0
- package/dist/browser/cli.js +488 -0
- package/dist/browser/cli.js.map +1 -0
- package/dist/browser/client.js +182 -0
- package/dist/browser/client.js.map +1 -0
- package/dist/browser/commands.js +598 -0
- package/dist/browser/commands.js.map +1 -0
- package/dist/browser/daemon.js +315 -0
- package/dist/browser/daemon.js.map +1 -0
- package/dist/browser/executable.js +138 -0
- package/dist/browser/executable.js.map +1 -0
- package/dist/browser/install.js +49 -0
- package/dist/browser/install.js.map +1 -0
- package/dist/browser/keys.js +44 -0
- package/dist/browser/keys.js.map +1 -0
- package/dist/browser/paths.js +34 -0
- package/dist/browser/paths.js.map +1 -0
- package/dist/browser/protocol.js +34 -0
- package/dist/browser/protocol.js.map +1 -0
- package/dist/browser/selectors.js +53 -0
- package/dist/browser/selectors.js.map +1 -0
- package/dist/browser/session.js +128 -0
- package/dist/browser/session.js.map +1 -0
- package/dist/browser/settings.js +51 -0
- package/dist/browser/settings.js.map +1 -0
- package/dist/browser/snapshot.js +89 -0
- package/dist/browser/snapshot.js.map +1 -0
- package/dist/cli/args.js +9 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/commands/change.js +2 -1
- package/dist/cli/commands/change.js.map +1 -1
- package/dist/cli/commands/doctor.js +16 -0
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/host.js +4 -6
- package/dist/cli/commands/host.js.map +1 -1
- package/dist/cli/commands/init.js +9 -7
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/metrics.js +2 -1
- package/dist/cli/commands/metrics.js.map +1 -1
- package/dist/cli/commands/run.js +5 -4
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/main.js +2 -12
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/output.js +7 -3
- package/dist/cli/output.js.map +1 -1
- package/dist/core/archive.js +4 -0
- package/dist/core/archive.js.map +1 -1
- package/dist/core/async.js +15 -0
- package/dist/core/async.js.map +1 -0
- package/dist/core/change.js +2 -0
- package/dist/core/change.js.map +1 -1
- package/dist/core/config.js +16 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/deliver.js +3 -1
- package/dist/core/deliver.js.map +1 -1
- package/dist/core/lock.js +2 -1
- package/dist/core/lock.js.map +1 -1
- package/dist/core/metrics.js +28 -19
- package/dist/core/metrics.js.map +1 -1
- package/dist/core/packet.js +1 -0
- package/dist/core/packet.js.map +1 -1
- package/dist/core/paths.js +14 -0
- package/dist/core/paths.js.map +1 -1
- package/dist/core/report.js +5 -1
- package/dist/core/report.js.map +1 -1
- package/dist/core/roles.js +16 -5
- package/dist/core/roles.js.map +1 -1
- package/dist/core/run.js +2 -3
- package/dist/core/run.js.map +1 -1
- package/dist/core/skills.js +60 -0
- package/dist/core/skills.js.map +1 -0
- package/docs/design.md +18 -4
- package/package.json +11 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/browser/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** Комбинация клавиш для puppeteer: `ctrl+shift+a`, `Enter`, `cmd+ArrowDown`, `ctrl++`, пробел. Имена модификаторов и служебных клавиш нормализуются. */
|
|
2
|
+
const MODIFIERS = {
|
|
3
|
+
ctrl: 'Control',
|
|
4
|
+
control: 'Control',
|
|
5
|
+
cmd: 'Meta',
|
|
6
|
+
command: 'Meta',
|
|
7
|
+
meta: 'Meta',
|
|
8
|
+
win: 'Meta',
|
|
9
|
+
shift: 'Shift',
|
|
10
|
+
alt: 'Alt',
|
|
11
|
+
option: 'Alt',
|
|
12
|
+
};
|
|
13
|
+
const SPECIAL = ['Enter', 'Tab', 'Escape', 'Backspace', 'Delete', 'Space', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'PageUp', 'PageDown', 'Insert', ...Array.from({ length: 12 }, (_, i) => `F${i + 1}`)];
|
|
14
|
+
const SPECIAL_BY_LOWER = new Map(SPECIAL.map((k) => [k.toLowerCase(), k]));
|
|
15
|
+
const ALIASES = { esc: 'Escape', return: 'Enter', del: 'Delete', up: 'ArrowUp', down: 'ArrowDown', left: 'ArrowLeft', right: 'ArrowRight', pgup: 'PageUp', pgdn: 'PageDown', spacebar: 'Space' };
|
|
16
|
+
export function parseKeyCombo(input) {
|
|
17
|
+
// Одиночный символ, включая пробел и «+», это сама клавиша.
|
|
18
|
+
if (input.length === 1)
|
|
19
|
+
return { modifiers: [], key: input };
|
|
20
|
+
let modifierPart;
|
|
21
|
+
let key;
|
|
22
|
+
if (input.endsWith('+') && input.length > 1) {
|
|
23
|
+
// `ctrl++`: последний плюс это клавиша, а не разделитель.
|
|
24
|
+
key = '+';
|
|
25
|
+
modifierPart = input.slice(0, -1);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
const idx = input.lastIndexOf('+');
|
|
29
|
+
key = idx >= 0 ? input.slice(idx + 1) : input;
|
|
30
|
+
modifierPart = idx >= 0 ? input.slice(0, idx) : '';
|
|
31
|
+
}
|
|
32
|
+
const modifiers = modifierPart
|
|
33
|
+
.split('+')
|
|
34
|
+
.map((m) => m.trim())
|
|
35
|
+
.filter(Boolean)
|
|
36
|
+
.map((m) => MODIFIERS[m.toLowerCase()] ?? m);
|
|
37
|
+
if (key === ' ')
|
|
38
|
+
return { modifiers, key };
|
|
39
|
+
const trimmed = key.trim();
|
|
40
|
+
const lower = trimmed.toLowerCase();
|
|
41
|
+
const canonical = trimmed.length === 1 ? trimmed : (ALIASES[lower] ?? SPECIAL_BY_LOWER.get(lower) ?? trimmed);
|
|
42
|
+
return { modifiers, key: canonical };
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/browser/keys.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { expandHome } from '../core/paths.js';
|
|
5
|
+
/** Домашний каталог инструмента: сессии, профили входа, кэш браузеров, журналы, снимки. Вне репозитория продукта. */
|
|
6
|
+
export function browserHome(env = process.env) {
|
|
7
|
+
const custom = env.SBOX_BROWSER_HOME;
|
|
8
|
+
return custom ? expandHome(custom) : path.join(os.homedir(), '.sbox', 'browser');
|
|
9
|
+
}
|
|
10
|
+
export { expandHome } from '../core/paths.js';
|
|
11
|
+
export const browserDirs = {
|
|
12
|
+
cache: (env) => path.join(browserHome(env), 'cache'),
|
|
13
|
+
profiles: (env) => path.join(browserHome(env), 'profiles'),
|
|
14
|
+
sessions: (env) => path.join(browserHome(env), 'sessions'),
|
|
15
|
+
logs: (env) => path.join(browserHome(env), 'logs'),
|
|
16
|
+
shots: (env) => path.join(browserHome(env), 'shots'),
|
|
17
|
+
};
|
|
18
|
+
/** Кэш самого puppeteer: браузеры, уже скачанные другими проектами, годятся и нам. */
|
|
19
|
+
export function puppeteerDefaultCache(env = process.env) {
|
|
20
|
+
return env.PUPPETEER_CACHE_DIR ? expandHome(env.PUPPETEER_CACHE_DIR) : path.join(os.homedir(), '.cache', 'puppeteer');
|
|
21
|
+
}
|
|
22
|
+
/** Каталоги инструмента содержат профили входа и сокеты: создаются доступными только владельцу. */
|
|
23
|
+
export function ensureDir(dir) {
|
|
24
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
25
|
+
return dir;
|
|
26
|
+
}
|
|
27
|
+
export function profileDir(name, env) {
|
|
28
|
+
return path.join(browserDirs.profiles(env), name);
|
|
29
|
+
}
|
|
30
|
+
export function timestampSlug(d = new Date()) {
|
|
31
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
32
|
+
return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/browser/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,qHAAqH;AACrH,MAAM,UAAU,WAAW,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG;IAC9D,MAAM,MAAM,GAAG,GAAG,CAAC,iBAAiB,CAAC;IACrC,OAAO,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;AACnF,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,KAAK,EAAE,CAAC,GAAuB,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACxE,QAAQ,EAAE,CAAC,GAAuB,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC;IAC9E,QAAQ,EAAE,CAAC,GAAuB,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC;IAC9E,IAAI,EAAE,CAAC,GAAuB,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtE,KAAK,EAAE,CAAC,GAAuB,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACzE,CAAC;AAEF,sFAAsF;AACtF,MAAM,UAAU,qBAAqB,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG;IACxE,OAAO,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AACxH,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACpD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,GAAuB;IAC9D,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE;IAC1C,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACtD,OAAO,GAAG,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC;AAC1I,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { StringDecoder } from 'node:string_decoder';
|
|
2
|
+
/** BigInt из страницы (eval) не сериализуется JSON.stringify: отдаём строкой, а не роняем демон. */
|
|
3
|
+
function replacer(_key, value) {
|
|
4
|
+
return typeof value === 'bigint' ? value.toString() : value;
|
|
5
|
+
}
|
|
6
|
+
export function encodeMessage(msg) {
|
|
7
|
+
return `${JSON.stringify(msg, replacer)}\n`;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Накапливает куски потока и отдаёт разобранные строки; неполная строка ждёт продолжения.
|
|
11
|
+
* Буферы декодируются через StringDecoder: многобайтовый символ UTF-8, разрезанный границей чанка, не портится.
|
|
12
|
+
*/
|
|
13
|
+
export function createLineParser(onMessage, onError) {
|
|
14
|
+
const decoder = new StringDecoder('utf8');
|
|
15
|
+
let buffer = '';
|
|
16
|
+
return (chunk) => {
|
|
17
|
+
buffer += typeof chunk === 'string' ? chunk : decoder.write(chunk);
|
|
18
|
+
let idx = buffer.indexOf('\n');
|
|
19
|
+
while (idx >= 0) {
|
|
20
|
+
const line = buffer.slice(0, idx).trim();
|
|
21
|
+
buffer = buffer.slice(idx + 1);
|
|
22
|
+
if (line) {
|
|
23
|
+
try {
|
|
24
|
+
onMessage(JSON.parse(line));
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
onError?.(e);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
idx = buffer.indexOf('\n');
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/browser/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAsBpD,oGAAoG;AACpG,SAAS,QAAQ,CAAC,IAAY,EAAE,KAAc;IAC5C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAuB;IACnD,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAI,SAA2B,EAAE,OAA8B;IAC7F,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,OAAO,CAAC,KAAK,EAAE,EAAE;QACf,MAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnE,IAAI,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC;YAChB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YACzC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YAC/B,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC;oBACH,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC,CAAC;gBACnC,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,OAAO,EAAE,CAAC,CAAU,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;YACD,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const REF = /^@?(e\d+)$/;
|
|
2
|
+
export function parseTarget(input) {
|
|
3
|
+
const raw = input.trim();
|
|
4
|
+
const ref = raw.match(REF);
|
|
5
|
+
if (ref)
|
|
6
|
+
return { kind: 'ref', ref: ref[1], raw };
|
|
7
|
+
const eq = raw.match(/^(text|aria|xpath|css)=([\s\S]*)$/);
|
|
8
|
+
if (eq) {
|
|
9
|
+
const [, prefix, value] = eq;
|
|
10
|
+
switch (prefix) {
|
|
11
|
+
case 'text':
|
|
12
|
+
return { kind: 'selector', selector: `::-p-text(${value})`, raw };
|
|
13
|
+
case 'aria':
|
|
14
|
+
return { kind: 'selector', selector: `::-p-aria(${value})`, raw };
|
|
15
|
+
case 'xpath':
|
|
16
|
+
return { kind: 'selector', selector: `::-p-xpath(${value})`, raw };
|
|
17
|
+
default:
|
|
18
|
+
return { kind: 'selector', selector: value, raw };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (raw.startsWith('//') || raw.startsWith('(//'))
|
|
22
|
+
return { kind: 'selector', selector: `::-p-xpath(${raw})`, raw };
|
|
23
|
+
return { kind: 'selector', selector: raw, raw };
|
|
24
|
+
}
|
|
25
|
+
/** Совпадение URL с шаблоном: подстрока либо glob со звёздочками. */
|
|
26
|
+
export function urlMatches(url, pattern) {
|
|
27
|
+
if (!pattern.includes('*'))
|
|
28
|
+
return url.includes(pattern);
|
|
29
|
+
const re = new RegExp(`^${pattern.split('*').map((s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('.*')}$`);
|
|
30
|
+
return re.test(url);
|
|
31
|
+
}
|
|
32
|
+
const HOST_WITH_PORT = /^(localhost|\d{1,3}(\.\d{1,3}){3}|\[[0-9a-f:]+\]):\d+(\/|\?|#|$)/i;
|
|
33
|
+
const BARE_DOMAIN = /^(localhost|[a-z0-9-]+(\.[a-z0-9-]+)+)(:\d+)?(\/|\?|#|$)/i;
|
|
34
|
+
/** `index.html` без базового URL это файл, а не домен: последняя метка из известных расширений. */
|
|
35
|
+
const FILE_EXTENSION = /\.(html?|xhtml|php|aspx?|jsp|json|xml|txt|md|pdf|js|mjs|css|svg|png|jpe?g|gif|webp|ico|csv|yaml|yml)(\/|\?|#|$)/i;
|
|
36
|
+
/**
|
|
37
|
+
* Адрес для goto. Полный URL со схемой как есть; `localhost:3000/x` и IP с портом получают http://;
|
|
38
|
+
* при заданном базовом URL всё остальное разрешается от него (`index.html`, `/orders`, `orders/list`);
|
|
39
|
+
* без базового URL доменное имя получает http://, а относительный путь даёт null.
|
|
40
|
+
*/
|
|
41
|
+
export function normalizeUrl(input, baseUrl) {
|
|
42
|
+
const url = input.trim();
|
|
43
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(url) || /^(about|data|blob|file|javascript|mailto):/i.test(url))
|
|
44
|
+
return url;
|
|
45
|
+
if (HOST_WITH_PORT.test(url))
|
|
46
|
+
return `http://${url}`;
|
|
47
|
+
if (baseUrl)
|
|
48
|
+
return new URL(url, baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`).toString();
|
|
49
|
+
if (BARE_DOMAIN.test(url) && !FILE_EXTENSION.test(url.split('/')[0] ?? ''))
|
|
50
|
+
return `http://${url}`;
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=selectors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.js","sourceRoot":"","sources":["../../src/browser/selectors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { SboxError } from '../core/errors.js';
|
|
4
|
+
import { pidAlive } from '../core/lock.js';
|
|
5
|
+
import { browserDirs, ensureDir } from './paths.js';
|
|
6
|
+
const NAME = /^[a-z0-9][a-z0-9-]{0,40}$/;
|
|
7
|
+
export function assertSessionName(name) {
|
|
8
|
+
if (!NAME.test(name))
|
|
9
|
+
throw new SboxError('BROWSER_SESSION_NAME', `Имя сессии «${name}» должно быть из строчных букв, цифр и дефисов.`);
|
|
10
|
+
return name;
|
|
11
|
+
}
|
|
12
|
+
export function sessionFile(name, env) {
|
|
13
|
+
return path.join(browserDirs.sessions(env), `${name}.json`);
|
|
14
|
+
}
|
|
15
|
+
export function lockFile(name, env) {
|
|
16
|
+
return path.join(browserDirs.sessions(env), `${name}.lock`);
|
|
17
|
+
}
|
|
18
|
+
/** Путь сокета: unix-сокет в каталоге сессий, на Windows именованный канал. */
|
|
19
|
+
export function socketPath(name, env, platform = process.platform) {
|
|
20
|
+
if (platform === 'win32')
|
|
21
|
+
return `\\\\.\\pipe\\sbox-browser-${name}`;
|
|
22
|
+
return path.join(browserDirs.sessions(env), `${name}.sock`);
|
|
23
|
+
}
|
|
24
|
+
export function isPipe(sock) {
|
|
25
|
+
return sock.startsWith('\\\\.\\pipe\\');
|
|
26
|
+
}
|
|
27
|
+
export const isPidAlive = pidAlive;
|
|
28
|
+
export function writeSession(info, env) {
|
|
29
|
+
const file = sessionFile(info.name, env);
|
|
30
|
+
ensureDir(path.dirname(file));
|
|
31
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
32
|
+
fs.writeFileSync(tmp, `${JSON.stringify(info, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
|
|
33
|
+
fs.renameSync(tmp, file);
|
|
34
|
+
return file;
|
|
35
|
+
}
|
|
36
|
+
/** Читает сессию; след мёртвого процесса удаляется, чтобы следующая команда подняла демон заново. */
|
|
37
|
+
export function readSession(name, env) {
|
|
38
|
+
const file = sessionFile(name, env);
|
|
39
|
+
if (!fs.existsSync(file))
|
|
40
|
+
return null;
|
|
41
|
+
let info;
|
|
42
|
+
try {
|
|
43
|
+
info = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
removeSession(name, env);
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
if (!info.pid || !pidAlive(info.pid)) {
|
|
50
|
+
removeSession(name, env);
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return info;
|
|
54
|
+
}
|
|
55
|
+
export function removeSession(name, env, platform) {
|
|
56
|
+
fs.rmSync(sessionFile(name, env), { force: true });
|
|
57
|
+
const sock = socketPath(name, env, platform);
|
|
58
|
+
if (!isPipe(sock))
|
|
59
|
+
fs.rmSync(sock, { force: true });
|
|
60
|
+
}
|
|
61
|
+
/** Удаляет след сессии, только если он всё ещё принадлежит процессу pid: чужую живую сессию демон не трогает. */
|
|
62
|
+
export function removeSessionIfOwned(name, pid, env) {
|
|
63
|
+
const file = sessionFile(name, env);
|
|
64
|
+
if (fs.existsSync(file)) {
|
|
65
|
+
try {
|
|
66
|
+
const info = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
67
|
+
if (info.pid !== pid)
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
/* битый файл: убираем */
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
removeSession(name, env);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
export function listSessions(env) {
|
|
78
|
+
const dir = browserDirs.sessions(env);
|
|
79
|
+
if (!fs.existsSync(dir))
|
|
80
|
+
return [];
|
|
81
|
+
return fs
|
|
82
|
+
.readdirSync(dir)
|
|
83
|
+
.filter((f) => f.endsWith('.json'))
|
|
84
|
+
.map((f) => readSession(f.slice(0, -'.json'.length), env))
|
|
85
|
+
.filter((s) => s !== null)
|
|
86
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
87
|
+
}
|
|
88
|
+
export function readLock(name, env) {
|
|
89
|
+
try {
|
|
90
|
+
return JSON.parse(fs.readFileSync(lockFile(name, env), 'utf8'));
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Эксклюзивное право поднимать демон с этим именем: файл создаётся атомарно (O_EXCL) до запуска браузера,
|
|
98
|
+
* поэтому два одновременных автозапуска не могут оба дойти до сокета. Устаревшую блокировку (мёртвый владелец,
|
|
99
|
+
* либо владелец без сессии дольше staleMs) забирает новый демон.
|
|
100
|
+
*/
|
|
101
|
+
export function acquireSessionLock(name, env, opts = {}) {
|
|
102
|
+
const file = lockFile(name, env);
|
|
103
|
+
ensureDir(path.dirname(file));
|
|
104
|
+
const staleMs = opts.staleMs ?? 120_000;
|
|
105
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
106
|
+
try {
|
|
107
|
+
const fd = fs.openSync(file, 'wx', 0o600);
|
|
108
|
+
fs.writeFileSync(fd, JSON.stringify({ pid: process.pid, at: new Date().toISOString() }));
|
|
109
|
+
fs.closeSync(fd);
|
|
110
|
+
return () => {
|
|
111
|
+
const current = readLock(name, env);
|
|
112
|
+
if (current?.pid === process.pid)
|
|
113
|
+
fs.rmSync(file, { force: true });
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
if (e.code !== 'EEXIST')
|
|
118
|
+
throw e;
|
|
119
|
+
const lock = readLock(name, env);
|
|
120
|
+
const alive = lock !== null && pidAlive(lock.pid) && (opts.liveCheck ? opts.liveCheck(lock) : Date.now() - Date.parse(lock.at) < staleMs || fs.existsSync(sessionFile(name, env)));
|
|
121
|
+
if (alive)
|
|
122
|
+
throw new SboxError('BROWSER_SESSION_EXISTS', `Сессия ${name} уже поднимается или работает (pid ${lock?.pid}).`, 'Используйте её или остановите: `sbox-browser stop`.');
|
|
123
|
+
fs.rmSync(file, { force: true });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
throw new SboxError('BROWSER_SESSION_EXISTS', `Не удалось занять блокировку сессии ${name}.`);
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/browser/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { loadConfig } from '../core/config.js';
|
|
2
|
+
import { findProjectRoot } from '../core/paths.js';
|
|
3
|
+
import { SboxError } from '../core/errors.js';
|
|
4
|
+
import { browserDirs } from './paths.js';
|
|
5
|
+
import { expandHome } from '../core/paths.js';
|
|
6
|
+
export function parseViewport(value) {
|
|
7
|
+
const m = value.match(/^(\d+)x(\d+)$/i);
|
|
8
|
+
if (!m)
|
|
9
|
+
throw new SboxError('BROWSER_VIEWPORT', `Размер окна «${value}» должен быть вида 1280x800.`);
|
|
10
|
+
return { width: Number(m[1]), height: Number(m[2]) };
|
|
11
|
+
}
|
|
12
|
+
export function loadBrowserSettings(flags = {}, env = process.env) {
|
|
13
|
+
const projectRoot = findProjectRoot(flags.cwd);
|
|
14
|
+
let cfg = null;
|
|
15
|
+
if (projectRoot) {
|
|
16
|
+
// Невалидный конфиг это ошибка, а не пустая секция browser: иначе профиль и базовый URL молча пропадут.
|
|
17
|
+
try {
|
|
18
|
+
cfg = loadConfig(projectRoot).browser;
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
if (e instanceof SboxError && e.code !== 'NO_CONFIG')
|
|
22
|
+
throw e;
|
|
23
|
+
cfg = null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const executable = flags.executable
|
|
27
|
+
? { path: expandHome(flags.executable), source: 'flag' }
|
|
28
|
+
: env.SBOX_BROWSER_EXECUTABLE
|
|
29
|
+
? { path: expandHome(env.SBOX_BROWSER_EXECUTABLE), source: 'env' }
|
|
30
|
+
: cfg?.executable
|
|
31
|
+
? { path: expandHome(cfg.executable), source: 'config' }
|
|
32
|
+
: null;
|
|
33
|
+
const envHeadless = env.SBOX_BROWSER_HEADLESS;
|
|
34
|
+
const headless = flags.headed ? false : flags.headless ? true : envHeadless !== undefined ? !['0', 'false', 'no'].includes(envHeadless.toLowerCase()) : (cfg?.headless ?? true);
|
|
35
|
+
const profile = flags.profile ?? env.SBOX_BROWSER_PROFILE ?? cfg?.profile ?? null;
|
|
36
|
+
const baseUrl = flags.baseUrl ?? env.SBOX_BROWSER_BASE_URL ?? cfg?.baseUrl ?? null;
|
|
37
|
+
const cacheDir = flags.cacheDir ? expandHome(flags.cacheDir) : env.SBOX_BROWSER_CACHE_DIR ? expandHome(env.SBOX_BROWSER_CACHE_DIR) : cfg?.cacheDir ? expandHome(cfg.cacheDir) : browserDirs.cache(env);
|
|
38
|
+
const viewport = flags.viewport ? parseViewport(flags.viewport) : (cfg?.viewport ?? { width: 1280, height: 800 });
|
|
39
|
+
return {
|
|
40
|
+
executable,
|
|
41
|
+
headless,
|
|
42
|
+
profile: profile || null,
|
|
43
|
+
baseUrl: baseUrl || null,
|
|
44
|
+
cacheDir,
|
|
45
|
+
viewport,
|
|
46
|
+
timeoutMs: flags.timeout ?? cfg?.timeoutMs ?? 15_000,
|
|
47
|
+
idleMinutes: flags.idle ?? cfg?.idleMinutes ?? 30,
|
|
48
|
+
projectRoot,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/browser/settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export const INTERACTIVE_ROLES = new Set([
|
|
2
|
+
'link', 'button', 'textbox', 'searchbox', 'combobox', 'listbox', 'option', 'checkbox', 'radio', 'switch', 'slider',
|
|
3
|
+
'spinbutton', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'tab', 'treeitem', 'menubutton', 'togglebutton',
|
|
4
|
+
]);
|
|
5
|
+
const SKIP_ROLES = new Set(['none', 'presentation', 'generic', 'InlineTextBox', 'LineBreak']);
|
|
6
|
+
const CONTAINER_ROLES = new Set(['RootWebArea', 'WebArea', 'document', 'Iframe', 'iframe']);
|
|
7
|
+
export function renderSnapshot(root, opts = {}) {
|
|
8
|
+
const maxChars = opts.maxChars ?? 40_000;
|
|
9
|
+
const maxName = opts.maxNameLength ?? 80;
|
|
10
|
+
const refs = new Map();
|
|
11
|
+
const lines = [];
|
|
12
|
+
let count = 0;
|
|
13
|
+
const visit = (node, depth) => {
|
|
14
|
+
const interactive = INTERACTIVE_ROLES.has(node.role);
|
|
15
|
+
const skip = SKIP_ROLES.has(node.role) || (CONTAINER_ROLES.has(node.role) && depth > 0);
|
|
16
|
+
const silentText = node.role === 'StaticText' || node.role === 'text';
|
|
17
|
+
let nextDepth = depth;
|
|
18
|
+
if (interactive) {
|
|
19
|
+
count += 1;
|
|
20
|
+
const ref = `e${count}`;
|
|
21
|
+
refs.set(ref, node);
|
|
22
|
+
lines.push(`${' '.repeat(depth)}[${ref}] ${describe(node, maxName)}`);
|
|
23
|
+
nextDepth = depth + 1;
|
|
24
|
+
}
|
|
25
|
+
else if (!skip && !opts.interactiveOnly && !(silentText && !node.name)) {
|
|
26
|
+
if (!(silentText && depth > 0 && isTrivialText(node))) {
|
|
27
|
+
lines.push(`${' '.repeat(depth)}${describe(node, maxName)}`);
|
|
28
|
+
nextDepth = depth + 1;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else if (!skip && depth === 0) {
|
|
32
|
+
nextDepth = depth;
|
|
33
|
+
}
|
|
34
|
+
for (const child of node.children ?? [])
|
|
35
|
+
visit(child, nextDepth);
|
|
36
|
+
};
|
|
37
|
+
if (root)
|
|
38
|
+
visit(root, 0);
|
|
39
|
+
let text = lines.join('\n');
|
|
40
|
+
let truncated = false;
|
|
41
|
+
if (text.length > maxChars) {
|
|
42
|
+
text = `${text.slice(0, maxChars)}\n… (снимок обрезан до ${maxChars} символов: используйте --interactive или --root)`;
|
|
43
|
+
truncated = true;
|
|
44
|
+
}
|
|
45
|
+
return { text, refs, count, truncated };
|
|
46
|
+
}
|
|
47
|
+
function isTrivialText(node) {
|
|
48
|
+
return !node.name || node.name.trim().length === 0;
|
|
49
|
+
}
|
|
50
|
+
function describe(node, maxName) {
|
|
51
|
+
const parts = [node.role === 'StaticText' ? 'text' : node.role];
|
|
52
|
+
if (node.name)
|
|
53
|
+
parts.push(`"${clip(node.name, maxName)}"`);
|
|
54
|
+
if (node.role === 'heading' && node.level)
|
|
55
|
+
parts.push(`(h${node.level})`);
|
|
56
|
+
if (node.value !== undefined && node.value !== '')
|
|
57
|
+
parts.push(`value="${clip(String(node.value), maxName)}"`);
|
|
58
|
+
if (node.url && node.role === 'link')
|
|
59
|
+
parts.push(`→ ${clip(node.url, 120)}`);
|
|
60
|
+
const flags = [];
|
|
61
|
+
if (node.checked === true)
|
|
62
|
+
flags.push('checked');
|
|
63
|
+
if (node.checked === 'mixed')
|
|
64
|
+
flags.push('mixed');
|
|
65
|
+
if (node.pressed === true)
|
|
66
|
+
flags.push('pressed');
|
|
67
|
+
if (node.selected)
|
|
68
|
+
flags.push('selected');
|
|
69
|
+
if (node.disabled)
|
|
70
|
+
flags.push('disabled');
|
|
71
|
+
if (node.focused)
|
|
72
|
+
flags.push('focused');
|
|
73
|
+
if (node.expanded === true)
|
|
74
|
+
flags.push('expanded');
|
|
75
|
+
if (node.expanded === false)
|
|
76
|
+
flags.push('collapsed');
|
|
77
|
+
if (node.required)
|
|
78
|
+
flags.push('required');
|
|
79
|
+
if (flags.length)
|
|
80
|
+
parts.push(`[${flags.join(', ')}]`);
|
|
81
|
+
if (node.description)
|
|
82
|
+
parts.push(`— ${clip(node.description, maxName)}`);
|
|
83
|
+
return parts.join(' ');
|
|
84
|
+
}
|
|
85
|
+
function clip(s, max) {
|
|
86
|
+
const one = s.replace(/\s+/g, ' ').trim();
|
|
87
|
+
return one.length > max ? `${one.slice(0, max - 1)}…` : one;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/browser/snapshot.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/args.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { InvalidArgumentError } from 'commander';
|
|
2
|
+
/** Числовая опция commander: нечисло даёт ошибку разбора с понятным текстом, а не NaN. */
|
|
3
|
+
export function intOption(value) {
|
|
4
|
+
const n = Number(value);
|
|
5
|
+
if (value.trim() === '' || !Number.isFinite(n))
|
|
6
|
+
throw new InvalidArgumentError(`ожидалось число, получено «${value}»`);
|
|
7
|
+
return n;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEjD,0FAA0F;AAC1F,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACxB,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,oBAAoB,CAAC,8BAA8B,KAAK,GAAG,CAAC,CAAC;IACvH,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
+
import { intOption } from '../args.js';
|
|
2
3
|
import { createChange, listChanges, saveChange } from '../../core/change.js';
|
|
3
4
|
import { SboxError } from '../../core/errors.js';
|
|
4
5
|
import { exists, readText, writeText } from '../../core/paths.js';
|
|
@@ -53,7 +54,7 @@ export function registerChange(program) {
|
|
|
53
54
|
change
|
|
54
55
|
.command('resume [id]')
|
|
55
56
|
.description('Продолжить изменение после parked, blocked, stopped, delivery_unknown или waiting_user')
|
|
56
|
-
.option('--returns <n>', 'новый лимит возвратов в фазу (для parked)',
|
|
57
|
+
.option('--returns <n>', 'новый лимит возвратов в фазу (для parked)', intOption)
|
|
57
58
|
.option('--comment <text>', 'ответ человека на блокер; попадёт в фидбэк роли')
|
|
58
59
|
.action((id, opts, cmd) => {
|
|
59
60
|
const g = cmd.optsWithGlobals();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"change.js","sourceRoot":"","sources":["../../../src/cli/commands/change.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"change.js","sourceRoot":"","sources":["../../../src/cli/commands/change.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,7 @@ export function registerDoctor(program) {
|
|
|
24
24
|
}
|
|
25
25
|
diagnostics.push(...doctorWiki(ctx.root, ctx.config));
|
|
26
26
|
diagnostics.push(...runnerReadiness(ctx.config));
|
|
27
|
+
diagnostics.push(await browserReadiness(ctx.root));
|
|
27
28
|
const ok = !hasErrors(diagnostics);
|
|
28
29
|
emit(g, { healthy: ok, diagnostics }, (d) => `${formatDiagnostics(d.diagnostics)}\n\n${d.healthy ? 'Документация пригодна для запуска.' : 'Есть ошибки: исправьте их перед запуском изменений.'}`);
|
|
29
30
|
if (!ok)
|
|
@@ -52,4 +53,19 @@ function runnerReadiness(config) {
|
|
|
52
53
|
out.push({ severity: config.runner.default === 'codex' && !codexOk ? 'error' : 'info', code: 'RUNNER_CODEX', message: codexOk ? `Среда codex: ${codex}` : `Среда codex: исполняемый файл ${codex} не найден`, ...(codexOk ? {} : { fix: 'Укажите runner.codex.executable, например /Applications/ChatGPT.app/Contents/Resources/codex, или установите @openai/codex.' }) });
|
|
53
54
|
return out;
|
|
54
55
|
}
|
|
56
|
+
/** Браузер для проверки интерфейса: найден ли исполняемый файл и откуда. Только info или warning. */
|
|
57
|
+
async function browserReadiness(root) {
|
|
58
|
+
try {
|
|
59
|
+
// Ленивый импорт: загрузчик браузеров нужен только doctor, а не каждой команде sbox.
|
|
60
|
+
const [{ listCandidates }, { loadBrowserSettings }] = await Promise.all([import('../../browser/executable.js'), import('../../browser/settings.js')]);
|
|
61
|
+
const settings = loadBrowserSettings({ cwd: root });
|
|
62
|
+
const found = (await listCandidates({ explicit: settings.executable, cacheDir: settings.cacheDir, headed: !settings.headless }))[0];
|
|
63
|
+
if (found)
|
|
64
|
+
return { severity: 'info', code: 'BROWSER', message: `Браузер для sbox-browser: ${found.path} (${found.source})${settings.profile ? `, профиль ${settings.profile}` : ''}` };
|
|
65
|
+
return { severity: 'warning', code: 'BROWSER', message: 'Браузер для sbox-browser не найден: верификатор не сможет проверить интерфейс', fix: 'Выполните `sbox-browser install` или укажите browser.executable в .sbox/config.yaml.' };
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
return { severity: 'warning', code: 'BROWSER', message: e.message, fix: 'Проверьте browser.executable в .sbox/config.yaml или SBOX_BROWSER_EXECUTABLE.' };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
55
71
|
//# sourceMappingURL=doctor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
|