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
|
@@ -2,30 +2,34 @@
|
|
|
2
2
|
"name": "dev-browser",
|
|
3
3
|
"version": "0.0.1",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
5
|
+
"engines": {
|
|
6
|
+
"node": ">=22"
|
|
7
|
+
},
|
|
8
|
+
"packageManager": "npm@10.9.2",
|
|
9
|
+
"exports": {
|
|
10
|
+
"./client": {
|
|
11
|
+
"types": "./dist/src/client.d.ts",
|
|
12
|
+
"import": "./dist/src/client.js"
|
|
13
|
+
}
|
|
7
14
|
},
|
|
8
15
|
"scripts": {
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
16
|
+
"build": "tsc -p tsconfig.json",
|
|
17
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
18
|
+
"start": "node dist/scripts/start.js standalone",
|
|
19
|
+
"start-server": "node dist/scripts/start.js standalone",
|
|
20
|
+
"start-extension": "node dist/scripts/start.js extension",
|
|
12
21
|
"test": "vitest run",
|
|
13
22
|
"test:watch": "vitest"
|
|
14
23
|
},
|
|
15
24
|
"dependencies": {
|
|
16
|
-
"@hono/node-server": "^1.19.
|
|
17
|
-
"@hono/node-ws": "^1.
|
|
18
|
-
"
|
|
19
|
-
"hono": "^4.11.1",
|
|
25
|
+
"@hono/node-server": "^1.19.13",
|
|
26
|
+
"@hono/node-ws": "^1.3.1",
|
|
27
|
+
"hono": "^4.12.30",
|
|
20
28
|
"playwright": "^1.49.0"
|
|
21
29
|
},
|
|
22
30
|
"devDependencies": {
|
|
23
|
-
"@types/
|
|
24
|
-
"tsx": "^4.21.0",
|
|
31
|
+
"@types/node": "^22.0.0",
|
|
25
32
|
"typescript": "^5.0.0",
|
|
26
33
|
"vitest": "^2.1.0"
|
|
27
|
-
},
|
|
28
|
-
"optionalDependencies": {
|
|
29
|
-
"@rollup/rollup-linux-x64-gnu": "^4.0.0"
|
|
30
34
|
}
|
|
31
35
|
}
|
|
@@ -17,57 +17,106 @@ Scrolling is slow, unreliable, and wastes time. APIs return structured data with
|
|
|
17
17
|
|
|
18
18
|
This prevents wasting time debugging a complex script when the issue is a simple path like `data.user.timeline` vs `data.user.result.timeline`.
|
|
19
19
|
|
|
20
|
-
##
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
import {
|
|
28
|
-
import
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
20
|
+
## External Script Setup
|
|
21
|
+
|
|
22
|
+
Keep the installed skill directory read-only. Put scripts and temporary artifacts in the OS temporary directory or the task workspace, and remove them when the task finishes. External scripts receive the installed skill directory as their first argument and dynamically import the compiled client by file URL.
|
|
23
|
+
|
|
24
|
+
Never persist complete authentication headers. Keep captured headers in memory, and write only redacted metadata or final non-sensitive results.
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
28
|
+
import { tmpdir } from "node:os";
|
|
29
|
+
import { join } from "node:path";
|
|
30
|
+
import { pathToFileURL } from "node:url";
|
|
31
|
+
|
|
32
|
+
const skillDir = process.argv[2];
|
|
33
|
+
if (!skillDir) throw new Error("Pass the installed dev-browser skill directory");
|
|
34
|
+
const { connect, waitForPageLoad } = await import(
|
|
35
|
+
pathToFileURL(join(skillDir, "dist", "src", "client.js")).href
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const workDir = await mkdtemp(join(tmpdir(), "dev-browser-scrape-"));
|
|
39
|
+
let client;
|
|
40
|
+
try {
|
|
41
|
+
client = await connect();
|
|
42
|
+
const page = await client.page("site");
|
|
43
|
+
let capturedRequest;
|
|
44
|
+
|
|
45
|
+
page.on("request", (request) => {
|
|
46
|
+
const url = request.url();
|
|
47
|
+
if (url.includes("/api/") || url.includes("/graphql/")) {
|
|
48
|
+
capturedRequest = {
|
|
49
|
+
url,
|
|
50
|
+
method: request.method(),
|
|
51
|
+
headers: request.headers(),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
await page.goto("https://example.com/profile");
|
|
57
|
+
await waitForPageLoad(page);
|
|
58
|
+
await page.waitForTimeout(3000);
|
|
59
|
+
|
|
60
|
+
if (!capturedRequest) throw new Error("No matching API request captured");
|
|
61
|
+
const capturedUrl = new URL(capturedRequest.url);
|
|
62
|
+
console.log({
|
|
63
|
+
url: `${capturedUrl.origin}${capturedUrl.pathname}`,
|
|
64
|
+
method: capturedRequest.method,
|
|
65
|
+
headerNames: Object.keys(capturedRequest.headers),
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const results = new Map();
|
|
69
|
+
let cursor;
|
|
70
|
+
do {
|
|
71
|
+
const params = { count: 20, ...(cursor ? { cursor } : {}) };
|
|
72
|
+
const url = new URL(capturedRequest.url);
|
|
73
|
+
url.searchParams.set("params", JSON.stringify(params));
|
|
74
|
+
const response = await page.evaluate(
|
|
75
|
+
async ({ url, headers }) => {
|
|
76
|
+
const result = await fetch(url, { headers });
|
|
77
|
+
return result.json();
|
|
78
|
+
},
|
|
79
|
+
{ url: url.href, headers: capturedRequest.headers }
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const entries = response?.data?.entries ?? [];
|
|
83
|
+
cursor = undefined;
|
|
84
|
+
for (const entry of entries) {
|
|
85
|
+
if (entry.type === "cursor-bottom") cursor = entry.value;
|
|
86
|
+
else if (entry.id) results.set(entry.id, entry);
|
|
87
|
+
}
|
|
88
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
89
|
+
} while (cursor);
|
|
90
|
+
|
|
91
|
+
const resultPath = join(workDir, "results.json");
|
|
92
|
+
await writeFile(resultPath, JSON.stringify([...results.values()], null, 2));
|
|
93
|
+
console.log({ count: results.size, resultPath });
|
|
94
|
+
} finally {
|
|
95
|
+
try {
|
|
96
|
+
await client?.disconnect();
|
|
97
|
+
} finally {
|
|
98
|
+
await rm(workDir, { recursive: true, force: true });
|
|
45
99
|
}
|
|
46
|
-
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
47
102
|
|
|
48
|
-
|
|
49
|
-
await waitForPageLoad(page);
|
|
50
|
-
await page.waitForTimeout(3000);
|
|
103
|
+
Run it with quoted paths on Linux, PowerShell, or Command Prompt:
|
|
51
104
|
|
|
52
|
-
|
|
105
|
+
```text
|
|
106
|
+
node "PATH_TO_SCRIPT.mjs" "PATH_TO_INSTALLED_DEV_BROWSER"
|
|
53
107
|
```
|
|
54
108
|
|
|
55
|
-
|
|
109
|
+
If a result must survive the script, write the sanitized deliverable to the task workspace instead of `workDir`, then delete it at task completion unless the user asks to retain it.
|
|
56
110
|
|
|
57
|
-
|
|
111
|
+
## Step-by-Step Workflow
|
|
58
112
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (url.includes("UserTweets") || url.includes("/api/data")) {
|
|
63
|
-
const json = await response.json();
|
|
64
|
-
fs.writeFileSync("tmp/api-response.json", JSON.stringify(json, null, 2));
|
|
65
|
-
console.log("Captured response");
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
```
|
|
113
|
+
### 1. Capture One Request
|
|
114
|
+
|
|
115
|
+
Match a narrow API or GraphQL URL pattern. Keep the request URL and headers in memory. Log only the URL origin/path, method, and header names while confirming the endpoint; query parameters can contain credentials.
|
|
69
116
|
|
|
70
|
-
|
|
117
|
+
### 2. Inspect One Response
|
|
118
|
+
|
|
119
|
+
Inspect the response in memory before building pagination. Find:
|
|
71
120
|
|
|
72
121
|
- Where the data array lives (e.g., `data.user.result.timeline.instructions[].entries`)
|
|
73
122
|
- Where pagination cursors are (e.g., `cursor-bottom` entries)
|
|
@@ -75,67 +124,7 @@ Then analyze the structure to find:
|
|
|
75
124
|
|
|
76
125
|
### 3. Replay API with Pagination
|
|
77
126
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
import { connect } from "@/client.js";
|
|
82
|
-
import * as fs from "node:fs";
|
|
83
|
-
|
|
84
|
-
const client = await connect();
|
|
85
|
-
const page = await client.page("site");
|
|
86
|
-
|
|
87
|
-
const results = new Map(); // Use Map for deduplication
|
|
88
|
-
const headers = JSON.parse(fs.readFileSync("tmp/request-details.json", "utf8")).headers;
|
|
89
|
-
const baseUrl = "https://example.com/api/data";
|
|
90
|
-
|
|
91
|
-
let cursor = null;
|
|
92
|
-
let hasMore = true;
|
|
93
|
-
|
|
94
|
-
while (hasMore) {
|
|
95
|
-
// Build URL with pagination cursor
|
|
96
|
-
const params = { count: 20 };
|
|
97
|
-
if (cursor) params.cursor = cursor;
|
|
98
|
-
const url = `${baseUrl}?params=${encodeURIComponent(JSON.stringify(params))}`;
|
|
99
|
-
|
|
100
|
-
// Execute fetch in browser context (has auth cookies/headers)
|
|
101
|
-
const response = await page.evaluate(
|
|
102
|
-
async ({ url, headers }) => {
|
|
103
|
-
const res = await fetch(url, { headers });
|
|
104
|
-
return res.json();
|
|
105
|
-
},
|
|
106
|
-
{ url, headers }
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
// Extract data and cursor (adjust paths for your API)
|
|
110
|
-
const entries = response?.data?.entries || [];
|
|
111
|
-
for (const entry of entries) {
|
|
112
|
-
if (entry.type === "cursor-bottom") {
|
|
113
|
-
cursor = entry.value;
|
|
114
|
-
} else if (entry.id && !results.has(entry.id)) {
|
|
115
|
-
results.set(entry.id, {
|
|
116
|
-
id: entry.id,
|
|
117
|
-
text: entry.content,
|
|
118
|
-
timestamp: entry.created_at,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
console.log(`Fetched page, total: ${results.size}`);
|
|
124
|
-
|
|
125
|
-
// Check stop conditions
|
|
126
|
-
if (!cursor || entries.length === 0) hasMore = false;
|
|
127
|
-
|
|
128
|
-
// Rate limiting - be respectful
|
|
129
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Export results
|
|
133
|
-
const data = Array.from(results.values());
|
|
134
|
-
fs.writeFileSync("tmp/results.json", JSON.stringify(data, null, 2));
|
|
135
|
-
console.log(`Saved ${data.length} items`);
|
|
136
|
-
|
|
137
|
-
await client.disconnect();
|
|
138
|
-
```
|
|
127
|
+
Replay through `page.evaluate(fetch)` so the browser supplies its session cookies. Pass only the in-memory headers required by the endpoint, deduplicate with a `Map`, stop when the cursor or results end, and rate-limit requests.
|
|
139
128
|
|
|
140
129
|
## Key Patterns
|
|
141
130
|
|
|
@@ -149,7 +138,7 @@ await client.disconnect();
|
|
|
149
138
|
|
|
150
139
|
## Tips
|
|
151
140
|
|
|
152
|
-
- **Extension mode**: `page.context().cookies()` doesn't work -
|
|
141
|
+
- **Extension mode**: `page.context().cookies()` doesn't work - keep intercepted auth headers in memory instead
|
|
153
142
|
- **Rate limiting**: Add 500ms+ delays between requests to avoid blocks
|
|
154
143
|
- **Stop conditions**: Check for empty results, missing cursor, or reaching a date/ID threshold
|
|
155
144
|
- **GraphQL APIs**: URL params often include `variables` and `features` JSON objects - capture and reuse them
|
|
@@ -6,9 +6,9 @@ GROK_API_URL=
|
|
|
6
6
|
# 必填项:你的 API 密钥
|
|
7
7
|
GROK_API_KEY=
|
|
8
8
|
|
|
9
|
-
# 可选项:使用的 Grok 模型(默认:grok-4.20-
|
|
10
|
-
# 常用选项:grok-4.20-auto, grok-4-fast
|
|
11
|
-
GROK_MODEL=grok-4.20-
|
|
9
|
+
# 可选项:使用的 Grok 模型(默认:grok-4.20-non-reasoning)
|
|
10
|
+
# 常用选项:grok-4.20-non-reasoning, grok-4.20-auto, grok-4-fast
|
|
11
|
+
GROK_MODEL=grok-4.20-non-reasoning
|
|
12
12
|
|
|
13
13
|
# 可选项:启用调试模式(true/false)
|
|
14
14
|
GROK_DEBUG=false
|
|
@@ -24,7 +24,7 @@ Use this skill for web search, webpage retrieval, and current-information lookup
|
|
|
24
24
|
```bash
|
|
25
25
|
cp "<SKILL_DIR>/.env.example" "<SKILL_DIR>/.env"
|
|
26
26
|
|
|
27
|
-
python "<SKILL_DIR>/scripts/groksearch_entry.py" web_search --query "search terms" [--platform "GitHub"] [--min-results 3] [--max-results 10] [--model "grok-4.20-
|
|
27
|
+
python "<SKILL_DIR>/scripts/groksearch_entry.py" web_search --query "search terms" [--platform "GitHub"] [--min-results 3] [--max-results 10] [--model "grok-4.20-non-reasoning"] [--extra-sources 3]
|
|
28
28
|
|
|
29
29
|
python "<SKILL_DIR>/scripts/groksearch_entry.py" web_fetch --url "https://..." [--out file.md] [--fallback-grok]
|
|
30
30
|
|
|
@@ -9,6 +9,7 @@ def load_dotenv() -> bool:
|
|
|
9
9
|
if not env_path.exists():
|
|
10
10
|
return False
|
|
11
11
|
try:
|
|
12
|
+
seen_keys = set()
|
|
12
13
|
with open(env_path, "r", encoding="utf-8") as f:
|
|
13
14
|
for line in f:
|
|
14
15
|
line = line.strip()
|
|
@@ -21,7 +22,10 @@ def load_dotenv() -> bool:
|
|
|
21
22
|
value.startswith("'") and value.endswith("'")
|
|
22
23
|
):
|
|
23
24
|
value = value[1:-1]
|
|
24
|
-
if key
|
|
25
|
+
if not key or key in seen_keys:
|
|
26
|
+
continue
|
|
27
|
+
seen_keys.add(key)
|
|
28
|
+
if not os.environ.get(key):
|
|
25
29
|
os.environ[key] = value
|
|
26
30
|
return True
|
|
27
31
|
except IOError:
|
|
@@ -15,6 +15,8 @@ from pathlib import Path
|
|
|
15
15
|
from typing import Optional
|
|
16
16
|
from urllib.parse import urlsplit, urlunsplit
|
|
17
17
|
|
|
18
|
+
from _dotenv import load_dotenv
|
|
19
|
+
|
|
18
20
|
try:
|
|
19
21
|
import httpx
|
|
20
22
|
from tenacity import AsyncRetrying, retry_if_exception, stop_after_attempt, wait_random_exponential
|
|
@@ -24,38 +26,6 @@ except ImportError:
|
|
|
24
26
|
sys.exit(1)
|
|
25
27
|
|
|
26
28
|
|
|
27
|
-
# ============================================================================
|
|
28
|
-
# .env 文件支持
|
|
29
|
-
# ============================================================================
|
|
30
|
-
|
|
31
|
-
def load_dotenv() -> bool:
|
|
32
|
-
"""从项目根目录的 .env 文件加载环境变量。"""
|
|
33
|
-
env_path = Path(__file__).parent.parent / ".env"
|
|
34
|
-
if env_path.exists():
|
|
35
|
-
try:
|
|
36
|
-
with open(env_path, 'r', encoding='utf-8') as f:
|
|
37
|
-
for line in f:
|
|
38
|
-
line = line.strip()
|
|
39
|
-
if not line or line.startswith('#'):
|
|
40
|
-
continue
|
|
41
|
-
if '=' in line:
|
|
42
|
-
key, _, value = line.partition('=')
|
|
43
|
-
key = key.strip()
|
|
44
|
-
value = value.strip()
|
|
45
|
-
# 如果存在引号则移除
|
|
46
|
-
if (value.startswith('"') and value.endswith('"')) or \
|
|
47
|
-
(value.startswith("'") and value.endswith("'")):
|
|
48
|
-
value = value[1:-1]
|
|
49
|
-
# 允许 .env 覆盖空字符串环境变量
|
|
50
|
-
if key and not os.environ.get(key):
|
|
51
|
-
os.environ[key] = value
|
|
52
|
-
return True
|
|
53
|
-
except IOError:
|
|
54
|
-
pass
|
|
55
|
-
return False
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
# 模块导入时加载 .env
|
|
59
29
|
load_dotenv()
|
|
60
30
|
|
|
61
31
|
|
|
@@ -63,9 +33,21 @@ load_dotenv()
|
|
|
63
33
|
# 配置
|
|
64
34
|
# ============================================================================
|
|
65
35
|
|
|
36
|
+
def load_default_model() -> str:
|
|
37
|
+
defaults_path = Path(__file__).resolve().parent.parent / "defaults.json"
|
|
38
|
+
try:
|
|
39
|
+
defaults = json.loads(defaults_path.read_text(encoding="utf-8"))
|
|
40
|
+
model = defaults["model"]
|
|
41
|
+
except (OSError, json.JSONDecodeError, KeyError, TypeError) as error:
|
|
42
|
+
raise RuntimeError(f"无法读取 Grok 默认配置 {defaults_path}: {error}") from error
|
|
43
|
+
if not isinstance(model, str) or not model.strip():
|
|
44
|
+
raise RuntimeError(f"Grok 默认配置缺少有效 model: {defaults_path}")
|
|
45
|
+
return model
|
|
46
|
+
|
|
47
|
+
|
|
66
48
|
class Config:
|
|
67
49
|
_instance = None
|
|
68
|
-
_DEFAULT_MODEL =
|
|
50
|
+
_DEFAULT_MODEL = load_default_model()
|
|
69
51
|
|
|
70
52
|
def __new__(cls):
|
|
71
53
|
if cls._instance is None:
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
name: prompt-enhancer
|
|
3
3
|
description: |
|
|
4
4
|
Rewrite a raw prompt into a clearer prompt for a coding agent. Use only when the user explicitly asks to improve, optimize, rewrite, or structure a prompt for Codex, Claude Code, Gemini CLI, or another AI agent. Triggers: "improve this prompt", "rewrite this prompt", "optimize this prompt for Codex", "make this prompt better for an AI agent".
|
|
5
|
-
allowed-tools: Bash(python:*), Bash(python3:*), Bash(uv:*), Read, Grep
|
|
6
5
|
---
|
|
7
6
|
|
|
8
7
|
# Prompt Enhancer
|
|
@@ -19,31 +18,7 @@ Do not use this for general writing edits like email, docs, or PR copy.
|
|
|
19
18
|
|
|
20
19
|
## Do
|
|
21
20
|
|
|
22
|
-
-
|
|
23
|
-
- Third-party path: use the Python entrypoint only when the user explicitly provides `url`, `apiKey`, and `model`, or when all three are already configured in `<SKILL_DIR>/.env`.
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "user's raw prompt here"
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
- Do not call `scripts/enhance.py` directly.
|
|
30
|
-
- Use the installed skill directory for `<SKILL_DIR>`.
|
|
31
|
-
- If any of `url`, `apiKey`, or `model` is missing, do not invoke the script. Use the current agent directly instead.
|
|
32
|
-
- Optional setup: `cp "<SKILL_DIR>/.env.example" "<SKILL_DIR>/.env"`
|
|
33
|
-
|
|
34
|
-
## Output
|
|
35
|
-
|
|
36
|
-
- Read the enhanced prompt from `stdout`.
|
|
37
|
-
- Keep `stderr` for usage or optional debug output only.
|
|
21
|
+
- Rewrite the prompt directly with the current agent, following the structure from [TEMPLATE.md](TEMPLATE.md).
|
|
38
22
|
- Preserve the user's intent and explicit constraints.
|
|
39
23
|
- Add structure and missing execution context only when it helps the agent act.
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
## Notes
|
|
43
|
-
|
|
44
|
-
- Local config file: `<SKILL_DIR>/.env`
|
|
45
|
-
- The entrypoint auto-loads `<SKILL_DIR>/.env` before bootstrap and dependency install.
|
|
46
|
-
- Optional debug flag: `PE_DEBUG=1`
|
|
47
|
-
- Bootstrap controls: `PROMPT_ENHANCER_VENV_DIR`, `PROMPT_ENHANCER_PYTHON`, `AGENTS_SKILLS_PYTHON`
|
|
48
|
-
- Setup and troubleshooting: [ADVANCED.md](ADVANCED.md)
|
|
49
|
-
- Prompt template reference: [TEMPLATE.md](TEMPLATE.md)
|
|
24
|
+
- Use placeholders for unknown context instead of inventing new requirements.
|
|
@@ -84,8 +84,4 @@ Identify and fix the sorting bug in the codebase.
|
|
|
84
84
|
5. Add or update tests to cover the bug scenario
|
|
85
85
|
|
|
86
86
|
# Constraints
|
|
87
|
-
- Maintain backward compatibility
|
|
88
|
-
- Do not change the function signature unless necessary
|
|
89
|
-
- Add inline comments explaining the fix
|
|
90
87
|
```
|
|
91
|
-
|
package/.skill-lock.json
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"skills": {
|
|
4
|
-
"git-commit": {
|
|
5
|
-
"source": "github/awesome-copilot",
|
|
6
|
-
"sourceType": "github",
|
|
7
|
-
"sourceUrl": "https://github.com/github/awesome-copilot.git",
|
|
8
|
-
"skillPath": "skills/git-commit/SKILL.md",
|
|
9
|
-
"skillFolderHash": "883a6a7466f55a9cd9f22cf1cce2d9333fc9b998",
|
|
10
|
-
"installedAt": "2026-03-12T08:25:08.313Z",
|
|
11
|
-
"updatedAt": "2026-03-12T08:25:08.313Z"
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
"dismissed": {
|
|
15
|
-
"findSkillsPrompt": true
|
|
16
|
-
},
|
|
17
|
-
"lastSelectedAgents": [
|
|
18
|
-
"amp",
|
|
19
|
-
"cline",
|
|
20
|
-
"codex",
|
|
21
|
-
"cursor",
|
|
22
|
-
"gemini-cli",
|
|
23
|
-
"github-copilot",
|
|
24
|
-
"kimi-cli",
|
|
25
|
-
"opencode",
|
|
26
|
-
"claude-code",
|
|
27
|
-
"crush"
|
|
28
|
-
]
|
|
29
|
-
}
|
package/AGENTS.md
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# Configuration
|
|
2
|
-
|
|
3
|
-
## Language
|
|
4
|
-
|
|
5
|
-
- Tool/model interactions: **English**
|
|
6
|
-
- User-facing output: **Chinese**
|
|
7
|
-
|
|
8
|
-
## Code Style
|
|
9
|
-
|
|
10
|
-
- Concise, efficient, no redundancy
|
|
11
|
-
- Minimal comments/docs (only when necessary)
|
|
12
|
-
- Targeted changes only; never touch unrelated functionality
|
|
13
|
-
|
|
14
|
-
## Context Rules
|
|
15
|
-
|
|
16
|
-
- {{CODEBASE_RETRIEVAL_POLICY}}
|
|
17
|
-
- Rely only on project code plus `grok/context7` results
|
|
18
|
-
- If information is insufficient or uncertain, state it explicitly
|
|
19
|
-
|
|
20
|
-
## Workflow
|
|
21
|
-
|
|
22
|
-
```
|
|
23
|
-
/abel-init → /abel-research → /abel-plan → /abel-implement(TDD)
|
|
24
|
-
↘ /abel-diagnose (bug fix)
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Universal Constraints
|
|
28
|
-
|
|
29
|
-
1. Use `unified diff patch` format for proposed/applied changes
|
|
30
|
-
2. Require confidence ≥90% before applying changes
|
|
31
|
-
|
|
32
|
-
## Stage Skill Matrix
|
|
33
|
-
|
|
34
|
-
| Skill | Research | Plan | Implement | Diagnose | Capability & Triggers |
|
|
35
|
-
| --- | :---: | :---: | :---: | :---: | --- |
|
|
36
|
-
| /sequential-think | ✅ | ✅ | ❌ | ✅ | Multi-step reasoning, hypothesis testing. Trigger: 3+ interconnected components |
|
|
37
|
-
| /grok-search | ✅ | ○ | ❌ | ✅ | Deep research, concept understanding. Trigger: architectural patterns, best practices |
|
|
38
|
-
| /context7-auto-research | ✅ | ✅ | ✅ | ✅ | Official docs retrieval. Trigger: framework/library usage, APIs |
|
|
39
|
-
| /dev-browser | ○ | ○ | ✅ | ✅ | Browser automation. Trigger: E2E testing, UI verification |
|
|
40
|
-
| /confidence-check | ❌ | ✅ | ✅ | ✅ | Readiness verification. Trigger: before implementation/fix (≥90%) |
|
|
41
|
-
| /time | ○ | ✅ | ✅ | ○ | Time/timezone operations. Trigger: scheduling logic |
|
|
42
|
-
|
|
43
|
-
Legend: ✅ Primary, ○ Optional, ❌ Forbidden
|
|
44
|
-
|
|
45
|
-
OpenSpec commands: `/opsx:new` `/opsx:ff` `/opsx:archive` `openspec view` `openspec status`
|