abelworkflow 0.9.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -182
- package/bin/abelworkflow.mjs +5 -3
- package/extensions/pi-gpt-responses-compat/index.ts +1 -1
- package/lib/cli/args.mjs +76 -0
- package/lib/cli/main.mjs +385 -0
- package/lib/cli/prompts.mjs +106 -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 +324 -0
- package/lib/installer/install.mjs +153 -0
- package/lib/installer/links.mjs +427 -0
- package/lib/installer/state.mjs +163 -0
- package/lib/paths.mjs +99 -0
- package/lib/providers/claude.mjs +197 -0
- package/lib/providers/codex.mjs +433 -0
- package/lib/providers/pi.mjs +577 -0
- package/lib/providers/skills.mjs +105 -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/lib/templates/workflow/AGENTS.md +50 -0
- package/lib/templates/workflow/commands/abel-design.md +175 -0
- package/{commands → lib/templates/workflow/commands}/abel-diagnose.md +5 -5
- package/lib/templates/workflow/commands/abel-implement.md +170 -0
- package/{commands → lib/templates/workflow/commands}/abel-init.md +3 -5
- package/{.gitignore → lib/templates/workflow/gitignore.template} +0 -2
- package/lib/tools/cli-installer.mjs +277 -0
- package/package.json +37 -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/.env.example +3 -3
- package/skills/grok-search/SKILL.md +1 -1
- 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/SKILL.md +2 -27
- package/skills/prompt-enhancer/TEMPLATE.md +0 -4
- package/.skill-lock.json +0 -29
- package/AGENTS.md +0 -45
- package/commands/abel-implement.md +0 -157
- package/commands/abel-plan.md +0 -88
- package/commands/abel-research.md +0 -126
- 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/prompt-enhancer/.env.example +0 -12
- package/skills/prompt-enhancer/ADVANCED.md +0 -103
- package/skills/prompt-enhancer/requirements.txt +0 -2
- package/skills/prompt-enhancer/scripts/_dotenv.py +0 -28
- package/skills/prompt-enhancer/scripts/enhance.py +0 -191
- package/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py +0 -253
- 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
|
-
});
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# Prompt Enhancer CLI configuration
|
|
2
|
-
# Copy this file to .env and fill in the values you want to use.
|
|
3
|
-
|
|
4
|
-
# Optional: third-party OpenAI-compatible base URL
|
|
5
|
-
PE_API_URL=
|
|
6
|
-
|
|
7
|
-
# Optional: third-party OpenAI-compatible API key
|
|
8
|
-
PE_API_KEY=
|
|
9
|
-
|
|
10
|
-
# Optional: model name for the third-party endpoint
|
|
11
|
-
# Leave all three fields blank to use the current agent directly.
|
|
12
|
-
PE_MODEL=
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
# Advanced Usage
|
|
2
|
-
|
|
3
|
-
## Using the Python Script Directly
|
|
4
|
-
|
|
5
|
-
Use the bootstrap entrypoint from the installed skill directory:
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
# Assuming third-party config is already set in <SKILL_DIR>/.env or the environment
|
|
9
|
-
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "your prompt here"
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
`prompt_enhancer_entry.py` is the canonical entrypoint. It creates or reuses a skill-local virtual environment and then runs `scripts/enhance.py`.
|
|
13
|
-
If `PE_API_URL`, `PE_API_KEY`, and `PE_MODEL` are not all present, do not call the script; rewrite the prompt directly with the current agent instead.
|
|
14
|
-
|
|
15
|
-
## Environment Variables
|
|
16
|
-
|
|
17
|
-
| Variable | Description | Default |
|
|
18
|
-
|----------|-------------|---------|
|
|
19
|
-
| `PE_API_URL` | Third-party OpenAI-compatible base URL | - |
|
|
20
|
-
| `PE_API_KEY` | Third-party OpenAI-compatible API key | - |
|
|
21
|
-
| `PE_MODEL` | Model to use on the third-party endpoint | - |
|
|
22
|
-
| `PE_DEBUG` | Print bootstrap and fallback diagnostics to `stderr` | `0` |
|
|
23
|
-
| `PROMPT_ENHANCER_VENV_DIR` | Override the skill-local venv path | `skills/prompt-enhancer/.venv` |
|
|
24
|
-
| `PROMPT_ENHANCER_PYTHON` | Python version/spec for `uv venv --python` | - |
|
|
25
|
-
| `AGENTS_SKILLS_PYTHON` | Absolute path to fallback/bootstrap Python | - |
|
|
26
|
-
|
|
27
|
-
## Local `.env`
|
|
28
|
-
|
|
29
|
-
The CLI loads `<SKILL_DIR>/.env` automatically if present:
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
cp "<SKILL_DIR>/.env.example" "<SKILL_DIR>/.env"
|
|
33
|
-
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "your prompt here"
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Integration with Other Tools
|
|
37
|
-
|
|
38
|
-
The enhanced prompt is written to `stdout`. Usage or debug diagnostics stay on `stderr`, and bootstrap/fallback diagnostics are only emitted when `PE_DEBUG=1`.
|
|
39
|
-
|
|
40
|
-
### Piping Output
|
|
41
|
-
|
|
42
|
-
Assuming `PE_API_URL`, `PE_API_KEY`, and `PE_MODEL` are already configured:
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
# Pipe to clipboard (macOS)
|
|
46
|
-
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "my prompt" | pbcopy
|
|
47
|
-
|
|
48
|
-
# Pipe to file
|
|
49
|
-
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "my prompt" > enhanced.md
|
|
50
|
-
|
|
51
|
-
# Chain with other commands
|
|
52
|
-
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "my prompt" | claude -p
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### In Shell Scripts
|
|
56
|
-
|
|
57
|
-
Assuming the environment is already configured:
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
#!/bin/bash
|
|
61
|
-
ENHANCED=$(python "$HOME/.agents/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py" "$1")
|
|
62
|
-
echo "$ENHANCED"
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Manual Enhancement (Current Agent)
|
|
66
|
-
|
|
67
|
-
If the user does not provide `url`, `apiKey`, and `model`, use the current agent directly and apply the enhancement principles:
|
|
68
|
-
|
|
69
|
-
1. Read the user's prompt
|
|
70
|
-
2. Apply the template from [TEMPLATE.md](TEMPLATE.md)
|
|
71
|
-
3. Preserve every explicit user constraint
|
|
72
|
-
4. Use placeholders for unknown context instead of inventing requirements
|
|
73
|
-
5. Structure the output with:
|
|
74
|
-
- Context section
|
|
75
|
-
- Objective section
|
|
76
|
-
- Step-by-step instructions
|
|
77
|
-
- Constraints
|
|
78
|
-
|
|
79
|
-
## Troubleshooting
|
|
80
|
-
|
|
81
|
-
### Script Not Found
|
|
82
|
-
Verify the canonical entrypoint exists:
|
|
83
|
-
```bash
|
|
84
|
-
ls "$HOME/.agents/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py"
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Permission Denied
|
|
88
|
-
Run it through Python instead of executing the file directly:
|
|
89
|
-
```bash
|
|
90
|
-
python "$HOME/.agents/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py" "your prompt here"
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
### Show Usage
|
|
94
|
-
Run the entrypoint without a prompt to print usage information:
|
|
95
|
-
```bash
|
|
96
|
-
python "$HOME/.agents/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py"
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### Missing Third-Party Config
|
|
100
|
-
The script requires `PE_API_URL`, `PE_API_KEY`, and `PE_MODEL`. If any field is missing, skip the script and use the current agent directly.
|
|
101
|
-
|
|
102
|
-
### Debug Fallbacks
|
|
103
|
-
Set `PE_DEBUG=1` to show dependency-install or configuration diagnostics on `stderr`.
|