abelworkflow 0.9.2 → 1.0.0-rc.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 +55 -182
- package/bin/abelworkflow.mjs +5 -3
- package/lib/cli/args.mjs +76 -0
- package/lib/cli/main.mjs +387 -0
- package/lib/cli/prompts.mjs +119 -0
- package/lib/config/dotenv.mjs +102 -0
- package/lib/config/jsonc.mjs +80 -0
- package/lib/config/store.mjs +310 -0
- package/lib/config/toml.mjs +638 -0
- package/lib/installer/assets.mjs +326 -0
- package/lib/installer/install.mjs +167 -0
- package/lib/installer/links.mjs +427 -0
- package/lib/installer/render.mjs +46 -0
- package/lib/installer/state.mjs +182 -0
- package/lib/paths.mjs +99 -0
- package/lib/providers/claude.mjs +388 -0
- package/lib/providers/codex.mjs +433 -0
- package/lib/providers/pi.mjs +362 -0
- package/lib/providers/skills.mjs +164 -0
- package/lib/templates/codex/agents/default.toml +7 -0
- package/lib/templates/codex/agents/explorer.toml +7 -0
- package/lib/templates/codex/agents/planner.toml +7 -0
- package/lib/templates/codex/agents/reviewer.toml +7 -0
- package/lib/templates/codex/agents/worker.toml +7 -0
- package/lib/templates/codex/config-base.toml +11 -3
- package/{AGENTS.md → lib/templates/workflow/AGENTS.md} +8 -3
- package/{commands → lib/templates/workflow/commands}/abel-diagnose.md +5 -5
- package/{commands → lib/templates/workflow/commands}/abel-implement.md +3 -8
- package/{commands → lib/templates/workflow/commands}/abel-init.md +1 -1
- package/{commands → lib/templates/workflow/commands}/abel-plan.md +1 -7
- package/{commands → lib/templates/workflow/commands}/abel-research.md +1 -1
- package/{.gitignore → lib/templates/workflow/gitignore.template} +0 -2
- package/lib/tools/cli-installer.mjs +277 -0
- package/package.json +43 -10
- package/skills/context7-auto-research/SKILL.md +5 -5
- package/skills/context7-auto-research/{context7-api.js → context7-api.cjs} +5 -8
- package/skills/dev-browser/SKILL.md +53 -33
- package/skills/dev-browser/dist/scripts/start.d.ts +2 -0
- package/skills/dev-browser/dist/scripts/start.d.ts.map +1 -0
- package/skills/dev-browser/dist/scripts/start.js +118 -0
- package/skills/dev-browser/dist/scripts/start.js.map +1 -0
- package/skills/dev-browser/dist/src/client.d.ts +93 -0
- package/skills/dev-browser/dist/src/client.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/client.js +310 -0
- package/skills/dev-browser/dist/src/client.js.map +1 -0
- package/skills/dev-browser/dist/src/entrypoint.d.ts +29 -0
- package/skills/dev-browser/dist/src/entrypoint.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/entrypoint.js +106 -0
- package/skills/dev-browser/dist/src/entrypoint.js.map +1 -0
- package/skills/dev-browser/dist/src/index.d.ts +4 -0
- package/skills/dev-browser/dist/src/index.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/index.js +2 -0
- package/skills/dev-browser/dist/src/index.js.map +1 -0
- package/skills/dev-browser/dist/src/page-api.d.ts +25 -0
- package/skills/dev-browser/dist/src/page-api.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/page-api.js +104 -0
- package/skills/dev-browser/dist/src/page-api.js.map +1 -0
- package/skills/dev-browser/dist/src/relay.d.ts +27 -0
- package/skills/dev-browser/dist/src/relay.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/relay.js +521 -0
- package/skills/dev-browser/dist/src/relay.js.map +1 -0
- package/skills/dev-browser/dist/src/runtime.d.ts +45 -0
- package/skills/dev-browser/dist/src/runtime.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/runtime.js +54 -0
- package/skills/dev-browser/dist/src/runtime.js.map +1 -0
- package/skills/dev-browser/dist/src/snapshot/browser-script.d.ts +23 -0
- package/skills/dev-browser/dist/src/snapshot/browser-script.d.ts.map +1 -0
- package/skills/dev-browser/{src/snapshot/browser-script.ts → dist/src/snapshot/browser-script.js} +21 -30
- package/skills/dev-browser/dist/src/snapshot/browser-script.js.map +1 -0
- package/skills/dev-browser/dist/src/snapshot/index.d.ts +14 -0
- package/skills/dev-browser/dist/src/snapshot/index.d.ts.map +1 -0
- package/skills/dev-browser/{src/snapshot/index.ts → dist/src/snapshot/index.js} +2 -2
- package/skills/dev-browser/dist/src/snapshot/index.js.map +1 -0
- package/skills/dev-browser/dist/src/snapshot/inject.d.ts +13 -0
- package/skills/dev-browser/dist/src/snapshot/inject.d.ts.map +1 -0
- package/skills/dev-browser/{src/snapshot/inject.ts → dist/src/snapshot/inject.js} +2 -2
- package/skills/dev-browser/dist/src/snapshot/inject.js.map +1 -0
- package/skills/dev-browser/dist/src/standalone.d.ts +32 -0
- package/skills/dev-browser/dist/src/standalone.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/standalone.js +174 -0
- package/skills/dev-browser/dist/src/standalone.js.map +1 -0
- package/skills/dev-browser/dist/src/startup.d.ts +55 -0
- package/skills/dev-browser/dist/src/startup.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/startup.js +81 -0
- package/skills/dev-browser/dist/src/startup.js.map +1 -0
- package/skills/dev-browser/dist/src/target-registry.d.ts +29 -0
- package/skills/dev-browser/dist/src/target-registry.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/target-registry.js +135 -0
- package/skills/dev-browser/dist/src/target-registry.js.map +1 -0
- package/skills/dev-browser/dist/src/types.d.ts +27 -0
- package/skills/dev-browser/dist/src/types.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/types.js +2 -0
- package/skills/dev-browser/dist/src/types.js.map +1 -0
- package/skills/dev-browser/package-lock.json +67 -1510
- package/skills/dev-browser/package.json +18 -14
- package/skills/dev-browser/references/scraping.md +94 -105
- package/skills/grok-search/defaults.json +3 -0
- package/skills/grok-search/gitignore.template +4 -0
- package/skills/grok-search/scripts/_dotenv.py +5 -1
- package/skills/grok-search/scripts/groksearch_cli.py +15 -33
- package/skills/prompt-enhancer/TEMPLATE.md +0 -4
- package/skills/prompt-enhancer/requirements.txt +0 -1
- package/skills/prompt-enhancer/scripts/_dotenv.py +5 -1
- package/skills/prompt-enhancer/scripts/enhance.py +4 -51
- package/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py +1 -16
- package/.skill-lock.json +0 -29
- package/lib/cli/logic.mjs +0 -213
- package/lib/cli.mjs +0 -3016
- package/skills/confidence-check/SKILL.md +0 -34
- package/skills/confidence-check/confidence.ts +0 -276
- package/skills/dev-browser/bun.lock +0 -460
- package/skills/dev-browser/scripts/start.ts +0 -280
- package/skills/dev-browser/src/client.ts +0 -474
- package/skills/dev-browser/src/entrypoint.ts +0 -157
- package/skills/dev-browser/src/index.ts +0 -289
- package/skills/dev-browser/src/relay.ts +0 -731
- package/skills/dev-browser/src/runtime.test.ts +0 -60
- package/skills/dev-browser/src/runtime.ts +0 -171
- package/skills/dev-browser/src/startup.test.ts +0 -95
- package/skills/dev-browser/src/startup.ts +0 -153
- package/skills/dev-browser/src/types.ts +0 -35
- package/skills/dev-browser/tsconfig.json +0 -36
- package/skills/dev-browser/vitest.config.ts +0 -12
- package/skills/sequential-think/SKILL.md +0 -198
- package/skills/sequential-think/scripts/.env.example +0 -5
- package/skills/sequential-think/scripts/sequential_think_cli.py +0 -253
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { join } from "node:path";
|
|
2
|
-
|
|
3
|
-
import { describe, expect, it } from "vitest";
|
|
4
|
-
|
|
5
|
-
import { getPlaywrightBrowserRoots, isPlaywrightChromiumInstalled } from "./runtime.js";
|
|
6
|
-
|
|
7
|
-
describe("getPlaywrightBrowserRoots", () => {
|
|
8
|
-
const skillDir = "/tmp/dev-browser";
|
|
9
|
-
|
|
10
|
-
it("uses the hermetic local browser directory when PLAYWRIGHT_BROWSERS_PATH is 0", () => {
|
|
11
|
-
expect(
|
|
12
|
-
getPlaywrightBrowserRoots({
|
|
13
|
-
skillDir,
|
|
14
|
-
platform: "win32",
|
|
15
|
-
env: { PLAYWRIGHT_BROWSERS_PATH: "0" },
|
|
16
|
-
})
|
|
17
|
-
).toEqual([join(skillDir, "node_modules", "playwright-core", ".local-browsers")]);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it("prefers LOCALAPPDATA on Windows before USERPROFILE fallback", () => {
|
|
21
|
-
expect(
|
|
22
|
-
getPlaywrightBrowserRoots({
|
|
23
|
-
skillDir,
|
|
24
|
-
platform: "win32",
|
|
25
|
-
env: {
|
|
26
|
-
LOCALAPPDATA: "C:\\Users\\Alice\\AppData\\Local",
|
|
27
|
-
USERPROFILE: "C:\\Users\\Alice",
|
|
28
|
-
},
|
|
29
|
-
})
|
|
30
|
-
).toEqual([join("C:\\Users\\Alice\\AppData\\Local", "ms-playwright")]);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("falls back to USERPROFILE when LOCALAPPDATA is unavailable", () => {
|
|
34
|
-
expect(
|
|
35
|
-
getPlaywrightBrowserRoots({
|
|
36
|
-
skillDir,
|
|
37
|
-
platform: "win32",
|
|
38
|
-
env: { USERPROFILE: "C:\\Users\\Alice" },
|
|
39
|
-
})
|
|
40
|
-
).toEqual([join("C:\\Users\\Alice", "AppData", "Local", "ms-playwright")]);
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
describe("isPlaywrightChromiumInstalled", () => {
|
|
45
|
-
const skillDir = "/tmp/dev-browser";
|
|
46
|
-
|
|
47
|
-
it("detects chromium in the hermetic local browser directory", () => {
|
|
48
|
-
const hermeticRoot = join(skillDir, "node_modules", "playwright-core", ".local-browsers");
|
|
49
|
-
|
|
50
|
-
expect(
|
|
51
|
-
isPlaywrightChromiumInstalled({
|
|
52
|
-
skillDir,
|
|
53
|
-
platform: "win32",
|
|
54
|
-
env: { PLAYWRIGHT_BROWSERS_PATH: "0" },
|
|
55
|
-
exists: (path) => path === hermeticRoot,
|
|
56
|
-
readDir: () => ["chromium-1162"],
|
|
57
|
-
})
|
|
58
|
-
).toBe(true);
|
|
59
|
-
});
|
|
60
|
-
});
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import { dirname, join } from "node:path";
|
|
2
|
-
import { fileURLToPath } from "node:url";
|
|
3
|
-
|
|
4
|
-
export interface CommandStatusResult {
|
|
5
|
-
status: number | null;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export interface PackageManager {
|
|
9
|
-
name: "bun" | "pnpm" | "npm";
|
|
10
|
-
command: string;
|
|
11
|
-
args: string[];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface ChromiumInstallCheckOptions {
|
|
15
|
-
skillDir: string;
|
|
16
|
-
platform: NodeJS.Platform;
|
|
17
|
-
env: NodeJS.ProcessEnv;
|
|
18
|
-
exists: (path: string) => boolean;
|
|
19
|
-
readDir: (path: string) => string[];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface MissingPackageDependenciesOptions {
|
|
23
|
-
skillDir: string;
|
|
24
|
-
dependencies: string[];
|
|
25
|
-
exists: (path: string) => boolean;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function commandExists(
|
|
29
|
-
command: string,
|
|
30
|
-
runCheck: (command: string) => CommandStatusResult
|
|
31
|
-
): boolean {
|
|
32
|
-
return runCheck(command).status === 0;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function findAvailablePackageManager(
|
|
36
|
-
hasCommand: (command: string) => boolean
|
|
37
|
-
): PackageManager | null {
|
|
38
|
-
const candidates: PackageManager[] = [
|
|
39
|
-
{
|
|
40
|
-
name: "bun",
|
|
41
|
-
command: "bunx",
|
|
42
|
-
args: ["playwright", "install", "chromium"],
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
name: "pnpm",
|
|
46
|
-
command: "pnpm",
|
|
47
|
-
args: ["exec", "playwright", "install", "chromium"],
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
name: "npm",
|
|
51
|
-
command: "npx",
|
|
52
|
-
args: ["playwright", "install", "chromium"],
|
|
53
|
-
},
|
|
54
|
-
];
|
|
55
|
-
|
|
56
|
-
for (const candidate of candidates) {
|
|
57
|
-
const probe = candidate.name === "npm" ? "npm" : candidate.name;
|
|
58
|
-
if (hasCommand(probe)) {
|
|
59
|
-
return candidate;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function getPlaywrightInstallCommand(manager: PackageManager): string {
|
|
67
|
-
return [manager.command, ...manager.args].join(" ");
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function normalizePathForComparison(path: string): string {
|
|
71
|
-
return path.replaceAll("\\", "/").replace(/\/+/g, "/").toLowerCase();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function getPlaywrightBrowserRoots({
|
|
75
|
-
skillDir,
|
|
76
|
-
platform,
|
|
77
|
-
env,
|
|
78
|
-
}: {
|
|
79
|
-
skillDir: string;
|
|
80
|
-
platform: NodeJS.Platform;
|
|
81
|
-
env: NodeJS.ProcessEnv;
|
|
82
|
-
}): string[] {
|
|
83
|
-
const explicitPath = env.PLAYWRIGHT_BROWSERS_PATH?.trim();
|
|
84
|
-
if (explicitPath) {
|
|
85
|
-
if (explicitPath === "0") {
|
|
86
|
-
return [join(skillDir, "node_modules", "playwright-core", ".local-browsers")];
|
|
87
|
-
}
|
|
88
|
-
return [explicitPath];
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (platform === "win32") {
|
|
92
|
-
const roots: string[] = [];
|
|
93
|
-
const localAppData = env.LOCALAPPDATA?.trim();
|
|
94
|
-
if (localAppData) {
|
|
95
|
-
roots.push(join(localAppData, "ms-playwright"));
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const userProfile = env.USERPROFILE?.trim() ?? env.HOME?.trim();
|
|
99
|
-
if (userProfile) {
|
|
100
|
-
const fallbackRoot = join(userProfile, "AppData", "Local", "ms-playwright");
|
|
101
|
-
if (!roots.some((root) => normalizePathForComparison(root) === normalizePathForComparison(fallbackRoot))) {
|
|
102
|
-
roots.push(fallbackRoot);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return roots;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const home = env.HOME ?? env.USERPROFILE;
|
|
110
|
-
return home ? [join(home, ".cache", "ms-playwright")] : [];
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function isPlaywrightChromiumInstalled({
|
|
114
|
-
skillDir,
|
|
115
|
-
platform,
|
|
116
|
-
env,
|
|
117
|
-
exists,
|
|
118
|
-
readDir,
|
|
119
|
-
}: ChromiumInstallCheckOptions): boolean {
|
|
120
|
-
for (const root of getPlaywrightBrowserRoots({ skillDir, platform, env })) {
|
|
121
|
-
if (!exists(root)) {
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
try {
|
|
126
|
-
const entries = readDir(root);
|
|
127
|
-
if (entries.some((entry) => entry.startsWith("chromium"))) {
|
|
128
|
-
return true;
|
|
129
|
-
}
|
|
130
|
-
} catch {
|
|
131
|
-
// Ignore unreadable directories and continue probing.
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export function getMissingPackageDependencies({
|
|
139
|
-
skillDir,
|
|
140
|
-
dependencies,
|
|
141
|
-
exists,
|
|
142
|
-
}: MissingPackageDependenciesOptions): string[] {
|
|
143
|
-
return dependencies.filter(
|
|
144
|
-
(dependency) =>
|
|
145
|
-
!exists(join(skillDir, "node_modules", ...dependency.split("/"), "package.json"))
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export function resolveRuntimePaths(skillDir: string) {
|
|
150
|
-
const tmpDir = join(skillDir, "tmp");
|
|
151
|
-
const profileDir = join(skillDir, "profiles");
|
|
152
|
-
|
|
153
|
-
return {
|
|
154
|
-
skillDir,
|
|
155
|
-
tmpDir,
|
|
156
|
-
profileDir,
|
|
157
|
-
browserDataDir: join(profileDir, "browser-data"),
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
export function resolveImportMetaDir(moduleUrl: string): string {
|
|
162
|
-
return dirname(fileURLToPath(moduleUrl));
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export function resolveSkillDirFromEntrypoint(moduleUrl: string): string {
|
|
166
|
-
return dirname(resolveImportMetaDir(moduleUrl));
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export function shouldUseShellForPackageCommands(platform: NodeJS.Platform): boolean {
|
|
170
|
-
return platform === "win32";
|
|
171
|
-
}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from "vitest";
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
DEFAULT_HOST,
|
|
5
|
-
formatHttpUrl,
|
|
6
|
-
formatReadinessLines,
|
|
7
|
-
parseEntrypointArgs,
|
|
8
|
-
resolveHostForProbe,
|
|
9
|
-
} from "./entrypoint.js";
|
|
10
|
-
import { preflightStandaloneStartup } from "./startup.js";
|
|
11
|
-
|
|
12
|
-
describe("entrypoint host handling", () => {
|
|
13
|
-
it("defaults standalone host to localhost", () => {
|
|
14
|
-
const args = parseEntrypointArgs([], {});
|
|
15
|
-
|
|
16
|
-
expect(args.host).toBe(DEFAULT_HOST);
|
|
17
|
-
expect(args.host).toBe("localhost");
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it("formats IPv6 hosts in readiness output", () => {
|
|
21
|
-
expect(formatHttpUrl("::1", 9222)).toBe("http://[::1]:9222");
|
|
22
|
-
|
|
23
|
-
expect(
|
|
24
|
-
formatReadinessLines({
|
|
25
|
-
mode: "standalone",
|
|
26
|
-
host: "::1",
|
|
27
|
-
port: 9222,
|
|
28
|
-
wsEndpoint: "ws://127.0.0.1:9223/devtools/browser/test",
|
|
29
|
-
tmpDir: "/tmp/dev-browser",
|
|
30
|
-
profileDir: "/tmp/dev-browser/profile",
|
|
31
|
-
})
|
|
32
|
-
).toContain(" HTTP: http://[::1]:9222");
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("normalizes wildcard hosts to a reachable probe target", () => {
|
|
36
|
-
expect(resolveHostForProbe("0.0.0.0")).toBe("127.0.0.1");
|
|
37
|
-
expect(resolveHostForProbe("::")).toBe("::1");
|
|
38
|
-
expect(resolveHostForProbe("[::1]")).toBe("::1");
|
|
39
|
-
expect(resolveHostForProbe("localhost")).toBe("localhost");
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
describe("preflightStandaloneStartup", () => {
|
|
44
|
-
it("checks the configured host before starting", async () => {
|
|
45
|
-
const checkServer = vi.fn().mockResolvedValue({ ok: false });
|
|
46
|
-
const isPortInUse = vi.fn().mockResolvedValue(false);
|
|
47
|
-
const log = vi.fn();
|
|
48
|
-
|
|
49
|
-
await expect(
|
|
50
|
-
preflightStandaloneStartup(
|
|
51
|
-
{
|
|
52
|
-
mode: "standalone",
|
|
53
|
-
host: "::1",
|
|
54
|
-
port: 9222,
|
|
55
|
-
cdpPort: 9223,
|
|
56
|
-
headless: false,
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
checkServer,
|
|
60
|
-
isPortInUse,
|
|
61
|
-
log,
|
|
62
|
-
}
|
|
63
|
-
)
|
|
64
|
-
).resolves.toBe(true);
|
|
65
|
-
|
|
66
|
-
expect(checkServer).toHaveBeenCalledWith("::1", 9222);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it("short-circuits when the configured host already has a server", async () => {
|
|
70
|
-
const checkServer = vi.fn().mockResolvedValue({ ok: true, info: { wsEndpoint: "ws://test" } });
|
|
71
|
-
const isPortInUse = vi.fn();
|
|
72
|
-
const log = vi.fn();
|
|
73
|
-
|
|
74
|
-
await expect(
|
|
75
|
-
preflightStandaloneStartup(
|
|
76
|
-
{
|
|
77
|
-
mode: "standalone",
|
|
78
|
-
host: "localhost",
|
|
79
|
-
port: 9222,
|
|
80
|
-
cdpPort: 9223,
|
|
81
|
-
headless: false,
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
checkServer,
|
|
85
|
-
isPortInUse,
|
|
86
|
-
log,
|
|
87
|
-
}
|
|
88
|
-
)
|
|
89
|
-
).resolves.toBe(false);
|
|
90
|
-
|
|
91
|
-
expect(checkServer).toHaveBeenCalledWith("localhost", 9222);
|
|
92
|
-
expect(isPortInUse).not.toHaveBeenCalled();
|
|
93
|
-
expect(log).toHaveBeenCalledWith("Server already running on port 9222");
|
|
94
|
-
});
|
|
95
|
-
});
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import { formatReadinessLines, type EntrypointArgs } from "./entrypoint.js";
|
|
2
|
-
import type { PackageManager } from "./runtime.js";
|
|
3
|
-
|
|
4
|
-
export interface RuntimePaths {
|
|
5
|
-
skillDir: string;
|
|
6
|
-
tmpDir: string;
|
|
7
|
-
profileDir: string;
|
|
8
|
-
browserDataDir: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
interface StandaloneServer {
|
|
12
|
-
port: number;
|
|
13
|
-
wsEndpoint: string;
|
|
14
|
-
stop: () => Promise<void>;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface ExtensionServer {
|
|
18
|
-
port: number;
|
|
19
|
-
wsEndpoint: string;
|
|
20
|
-
stop: () => Promise<void>;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface RunEntrypointDeps {
|
|
24
|
-
runtimePaths: RuntimePaths;
|
|
25
|
-
mkdir: (path: string, options: { recursive: true }) => void;
|
|
26
|
-
serveStandalone: (options: {
|
|
27
|
-
port: number;
|
|
28
|
-
host: string;
|
|
29
|
-
headless: boolean;
|
|
30
|
-
cdpPort: number;
|
|
31
|
-
profileDir: string;
|
|
32
|
-
}) => Promise<StandaloneServer>;
|
|
33
|
-
serveExtension: (options: { port: number; host: string }) => Promise<ExtensionServer>;
|
|
34
|
-
registerShutdown: (stop: () => Promise<void>) => void;
|
|
35
|
-
keepAlive: () => Promise<void>;
|
|
36
|
-
log: (line: string) => void;
|
|
37
|
-
ensureBrowser?: () => Promise<void>;
|
|
38
|
-
preflightStandalone?: () => Promise<boolean>;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface EnsurePlaywrightChromiumDeps {
|
|
42
|
-
isInstalled: () => boolean;
|
|
43
|
-
findPackageManager: () => PackageManager | null;
|
|
44
|
-
runCommand: (command: string, args: string[]) => Promise<void>;
|
|
45
|
-
log: (line: string) => void;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export interface PreflightStandaloneStartupDeps {
|
|
49
|
-
checkServer: (host: string, port: number) => Promise<{ ok: boolean; info?: { wsEndpoint?: string } }>;
|
|
50
|
-
isPortInUse: (port: number) => Promise<boolean>;
|
|
51
|
-
browserDataDir?: string;
|
|
52
|
-
recoverStaleBrowser?: (options: { cdpPort: number; browserDataDir: string }) => Promise<boolean>;
|
|
53
|
-
log: (line: string) => void;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export async function preflightStandaloneStartup(
|
|
57
|
-
args: EntrypointArgs,
|
|
58
|
-
deps: PreflightStandaloneStartupDeps
|
|
59
|
-
): Promise<boolean> {
|
|
60
|
-
const serverCheck = await deps.checkServer(args.host, args.port);
|
|
61
|
-
if (serverCheck.ok) {
|
|
62
|
-
deps.log(`Server already running on port ${args.port}`);
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (await deps.isPortInUse(args.cdpPort)) {
|
|
67
|
-
const recovered =
|
|
68
|
-
deps.browserDataDir && deps.recoverStaleBrowser
|
|
69
|
-
? await deps.recoverStaleBrowser({
|
|
70
|
-
cdpPort: args.cdpPort,
|
|
71
|
-
browserDataDir: deps.browserDataDir,
|
|
72
|
-
})
|
|
73
|
-
: false;
|
|
74
|
-
|
|
75
|
-
if (!recovered && (await deps.isPortInUse(args.cdpPort))) {
|
|
76
|
-
throw new Error(`CDP port ${args.cdpPort} is already in use by another process`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return true;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export async function ensurePlaywrightChromium(deps: EnsurePlaywrightChromiumDeps) {
|
|
84
|
-
if (deps.isInstalled()) {
|
|
85
|
-
deps.log("Playwright Chromium already installed.");
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
deps.log("Playwright Chromium not found. Installing (this may take a minute)...");
|
|
90
|
-
const manager = deps.findPackageManager();
|
|
91
|
-
if (!manager) {
|
|
92
|
-
throw new Error("No package manager found (tried bun, pnpm, npm)");
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
deps.log(`Using ${manager.name} to install Playwright...`);
|
|
96
|
-
await deps.runCommand(manager.command, manager.args);
|
|
97
|
-
deps.log("Chromium installed successfully.");
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export async function runEntrypoint(args: EntrypointArgs, deps: RunEntrypointDeps) {
|
|
101
|
-
deps.mkdir(deps.runtimePaths.tmpDir, { recursive: true });
|
|
102
|
-
|
|
103
|
-
if (args.mode === "extension") {
|
|
104
|
-
const server = await deps.serveExtension({
|
|
105
|
-
port: args.port,
|
|
106
|
-
host: args.host,
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
for (const line of formatReadinessLines({
|
|
110
|
-
mode: "extension",
|
|
111
|
-
host: args.host,
|
|
112
|
-
port: args.port,
|
|
113
|
-
wsEndpoint: server.wsEndpoint,
|
|
114
|
-
})) {
|
|
115
|
-
deps.log(line);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
deps.registerShutdown(() => server.stop());
|
|
119
|
-
await deps.keepAlive();
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
deps.mkdir(deps.runtimePaths.profileDir, { recursive: true });
|
|
124
|
-
|
|
125
|
-
const shouldStart = await deps.preflightStandalone?.();
|
|
126
|
-
if (shouldStart === false) {
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
await deps.ensureBrowser?.();
|
|
131
|
-
|
|
132
|
-
const server = await deps.serveStandalone({
|
|
133
|
-
port: args.port,
|
|
134
|
-
host: args.host,
|
|
135
|
-
headless: args.headless,
|
|
136
|
-
cdpPort: args.cdpPort,
|
|
137
|
-
profileDir: deps.runtimePaths.profileDir,
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
for (const line of formatReadinessLines({
|
|
141
|
-
mode: "standalone",
|
|
142
|
-
host: args.host,
|
|
143
|
-
port: args.port,
|
|
144
|
-
wsEndpoint: server.wsEndpoint,
|
|
145
|
-
tmpDir: deps.runtimePaths.tmpDir,
|
|
146
|
-
profileDir: deps.runtimePaths.profileDir,
|
|
147
|
-
})) {
|
|
148
|
-
deps.log(line);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
deps.registerShutdown(() => server.stop());
|
|
152
|
-
await deps.keepAlive();
|
|
153
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// API request/response types - shared between client and server
|
|
2
|
-
|
|
3
|
-
export interface ServeOptions {
|
|
4
|
-
port?: number;
|
|
5
|
-
host?: string;
|
|
6
|
-
headless?: boolean;
|
|
7
|
-
cdpPort?: number;
|
|
8
|
-
/** Directory to store persistent browser profiles (cookies, localStorage, etc.) */
|
|
9
|
-
profileDir?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface ViewportSize {
|
|
13
|
-
width: number;
|
|
14
|
-
height: number;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface GetPageRequest {
|
|
18
|
-
name: string;
|
|
19
|
-
/** Optional viewport size for new pages */
|
|
20
|
-
viewport?: ViewportSize;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface GetPageResponse {
|
|
24
|
-
wsEndpoint: string;
|
|
25
|
-
name: string;
|
|
26
|
-
targetId: string; // CDP target ID for reliable page matching
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface ListPagesResponse {
|
|
30
|
-
pages: string[];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface ServerInfoResponse {
|
|
34
|
-
wsEndpoint: string;
|
|
35
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
// Environment setup & latest features
|
|
4
|
-
"lib": ["ESNext"],
|
|
5
|
-
"target": "ESNext",
|
|
6
|
-
"module": "Preserve",
|
|
7
|
-
"moduleDetection": "force",
|
|
8
|
-
"jsx": "react-jsx",
|
|
9
|
-
"allowJs": true,
|
|
10
|
-
|
|
11
|
-
// Bundler mode
|
|
12
|
-
"moduleResolution": "bundler",
|
|
13
|
-
"allowImportingTsExtensions": true,
|
|
14
|
-
"verbatimModuleSyntax": true,
|
|
15
|
-
"noEmit": true,
|
|
16
|
-
|
|
17
|
-
// Path aliases
|
|
18
|
-
"baseUrl": ".",
|
|
19
|
-
"paths": {
|
|
20
|
-
"@/*": ["./src/*"]
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
// Best practices
|
|
24
|
-
"strict": true,
|
|
25
|
-
"skipLibCheck": true,
|
|
26
|
-
"noFallthroughCasesInSwitch": true,
|
|
27
|
-
"noUncheckedIndexedAccess": true,
|
|
28
|
-
"noImplicitOverride": true,
|
|
29
|
-
|
|
30
|
-
// Some stricter flags (disabled by default)
|
|
31
|
-
"noUnusedLocals": false,
|
|
32
|
-
"noUnusedParameters": false,
|
|
33
|
-
"noPropertyAccessFromIndexSignature": false
|
|
34
|
-
},
|
|
35
|
-
"include": ["src/**/*", "scripts/**/*"]
|
|
36
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "vitest/config";
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
globals: true,
|
|
6
|
-
environment: "node",
|
|
7
|
-
include: ["src/**/*.test.ts"],
|
|
8
|
-
testTimeout: 60000, // Playwright tests can be slow
|
|
9
|
-
hookTimeout: 60000,
|
|
10
|
-
teardownTimeout: 60000,
|
|
11
|
-
},
|
|
12
|
-
});
|