td-ai-tools 1.0.6 → 1.0.7
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
CHANGED
|
@@ -33,6 +33,9 @@ npx td-ai-tools install
|
|
|
33
33
|
npx td-ai-tools install --all
|
|
34
34
|
npx td-ai-tools install pr-solver
|
|
35
35
|
npx td-ai-tools install pr-solver horizon-component-library
|
|
36
|
+
npx td-ai-tools update
|
|
37
|
+
npx td-ai-tools update --all
|
|
38
|
+
npx td-ai-tools update pr-solver
|
|
36
39
|
```
|
|
37
40
|
|
|
38
41
|
The installer copies requested items into both agent layouts:
|
|
@@ -41,6 +44,8 @@ The installer copies requested items into both agent layouts:
|
|
|
41
44
|
|
|
42
45
|
This keeps the installed assets available to both Claude-style and `.agents`-style project conventions.
|
|
43
46
|
|
|
47
|
+
`install` now errors when the target item already exists. Use `update` to replace an existing installed skill or agent pack.
|
|
48
|
+
|
|
44
49
|
## Local Verification
|
|
45
50
|
Run the local smoke test to package the repo and verify installation into a throwaway project:
|
|
46
51
|
|
package/bin/cli.js
CHANGED
|
@@ -44,7 +44,7 @@ function readFrontmatterField(mdPath, field) {
|
|
|
44
44
|
return match ? match[1].trim() : '';
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
function installSkill(name) {
|
|
47
|
+
function installSkill(name, { replaceExisting = false } = {}) {
|
|
48
48
|
const src = path.join(SKILLS_DIR, name);
|
|
49
49
|
if (!fs.existsSync(src)) {
|
|
50
50
|
console.error(` [error] Skill "${name}" not found.`);
|
|
@@ -52,13 +52,21 @@ function installSkill(name) {
|
|
|
52
52
|
}
|
|
53
53
|
for (const target of INSTALL_TARGETS) {
|
|
54
54
|
const dest = path.join(TARGET_ROOT, target.root, 'skills', name);
|
|
55
|
+
if (fs.existsSync(dest) && !replaceExisting) {
|
|
56
|
+
console.error(` [error] Skill "${name}" already exists at ${target.root}/skills/${name}/ (use "update" to replace).`);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
if (fs.existsSync(dest) && replaceExisting) {
|
|
60
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
61
|
+
}
|
|
55
62
|
copyDir(src, dest);
|
|
56
|
-
|
|
63
|
+
const action = replaceExisting ? 'updated' : 'installed';
|
|
64
|
+
console.log(` [skill] ${name} ${action} -> ${target.root}/skills/${name}/`);
|
|
57
65
|
}
|
|
58
66
|
return true;
|
|
59
67
|
}
|
|
60
68
|
|
|
61
|
-
function installAgent(name) {
|
|
69
|
+
function installAgent(name, { replaceExisting = false } = {}) {
|
|
62
70
|
const src = path.join(AGENTS_DIR, name);
|
|
63
71
|
if (!fs.existsSync(src)) {
|
|
64
72
|
console.error(` [error] Agent pack "${name}" not found.`);
|
|
@@ -66,8 +74,16 @@ function installAgent(name) {
|
|
|
66
74
|
}
|
|
67
75
|
for (const target of INSTALL_TARGETS) {
|
|
68
76
|
const dest = path.join(TARGET_ROOT, target.root, 'agents', name);
|
|
77
|
+
if (fs.existsSync(dest) && !replaceExisting) {
|
|
78
|
+
console.error(` [error] Agent pack "${name}" already exists at ${target.root}/agents/${name}/ (use "update" to replace).`);
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
if (fs.existsSync(dest) && replaceExisting) {
|
|
82
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
83
|
+
}
|
|
69
84
|
copyDir(src, dest);
|
|
70
|
-
|
|
85
|
+
const action = replaceExisting ? 'updated' : 'installed';
|
|
86
|
+
console.log(` [agent] ${name} ${action} -> ${target.root}/agents/${name}/`);
|
|
71
87
|
}
|
|
72
88
|
return true;
|
|
73
89
|
}
|
|
@@ -97,14 +113,14 @@ function buildMenu() {
|
|
|
97
113
|
return [...skills, ...agents];
|
|
98
114
|
}
|
|
99
115
|
|
|
100
|
-
function installItems(items) {
|
|
116
|
+
function installItems(items, options = {}) {
|
|
101
117
|
for (const item of items) {
|
|
102
|
-
if (item.type === 'skill') installSkill(item.name);
|
|
103
|
-
else installAgent(item.name);
|
|
118
|
+
if (item.type === 'skill') installSkill(item.name, options);
|
|
119
|
+
else installAgent(item.name, options);
|
|
104
120
|
}
|
|
105
121
|
}
|
|
106
122
|
|
|
107
|
-
async function interactiveInstall() {
|
|
123
|
+
async function interactiveInstall(mode = 'install') {
|
|
108
124
|
const menu = buildMenu();
|
|
109
125
|
if (menu.length === 0) {
|
|
110
126
|
console.log('No skills or agent packs available.');
|
|
@@ -120,7 +136,7 @@ async function interactiveInstall() {
|
|
|
120
136
|
|
|
121
137
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
122
138
|
return new Promise(resolve => {
|
|
123
|
-
rl.question(
|
|
139
|
+
rl.question(`Select items to ${mode}: `, answer => {
|
|
124
140
|
rl.close();
|
|
125
141
|
const trimmed = answer.trim().toLowerCase();
|
|
126
142
|
let selected;
|
|
@@ -131,7 +147,7 @@ async function interactiveInstall() {
|
|
|
131
147
|
selected = indices.filter(i => i >= 0 && i < menu.length).map(i => menu[i]);
|
|
132
148
|
}
|
|
133
149
|
console.log('');
|
|
134
|
-
installItems(selected);
|
|
150
|
+
installItems(selected, { replaceExisting: mode === 'update' });
|
|
135
151
|
resolve();
|
|
136
152
|
});
|
|
137
153
|
});
|
|
@@ -164,6 +180,9 @@ Usage:
|
|
|
164
180
|
npx td-ai-tools install Interactive install
|
|
165
181
|
npx td-ai-tools install --all Install everything
|
|
166
182
|
npx td-ai-tools install <name...> Install specific skills or agent packs
|
|
183
|
+
npx td-ai-tools update Interactive update (replaces existing items)
|
|
184
|
+
npx td-ai-tools update --all Update everything
|
|
185
|
+
npx td-ai-tools update <name...> Update specific skills or agent packs
|
|
167
186
|
|
|
168
187
|
Skills are installed to: .claude/skills/<name>/
|
|
169
188
|
.agents/skills/<name>/
|
|
@@ -178,7 +197,7 @@ Agent packs installed to: .claude/agents/<name>/
|
|
|
178
197
|
console.log('------------');
|
|
179
198
|
|
|
180
199
|
if (!cmd || cmd === 'install' && args.length === 1) {
|
|
181
|
-
await interactiveInstall();
|
|
200
|
+
await interactiveInstall('install');
|
|
182
201
|
return;
|
|
183
202
|
}
|
|
184
203
|
|
|
@@ -199,6 +218,22 @@ Agent packs installed to: .claude/agents/<name>/
|
|
|
199
218
|
return;
|
|
200
219
|
}
|
|
201
220
|
|
|
221
|
+
if (cmd === 'update') {
|
|
222
|
+
const rest = args.slice(1);
|
|
223
|
+
if (rest.length === 0) {
|
|
224
|
+
await interactiveInstall('update');
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (rest[0] === '--all') {
|
|
228
|
+
console.log('');
|
|
229
|
+
installItems(buildMenu(), { replaceExisting: true });
|
|
230
|
+
} else {
|
|
231
|
+
console.log('');
|
|
232
|
+
installItems(resolveNames(rest), { replaceExisting: true });
|
|
233
|
+
}
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
|
|
202
237
|
console.error(`Unknown command: "${cmd}". Run with --help for usage.`);
|
|
203
238
|
process.exit(1);
|
|
204
239
|
}
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@ machine or one project clone location.
|
|
|
8
8
|
|
|
9
9
|
- `config.toml.template` — the source of truth. Uses two placeholders:
|
|
10
10
|
- `__PROJECT_ROOT__` — replaced with the absolute path to the repo root
|
|
11
|
-
- `
|
|
11
|
+
- `__BROWSER_PATH__` — replaced with the absolute path to the Chromium/Chrome binary
|
|
12
12
|
- `setup-codex.sh` — reads the template, substitutes the placeholders, writes
|
|
13
13
|
`<repo>/.codex/config.toml`.
|
|
14
14
|
|
|
@@ -27,7 +27,7 @@ The script prints the values it resolved, e.g.:
|
|
|
27
27
|
```
|
|
28
28
|
wrote /home/you/code/lio/.codex/config.toml
|
|
29
29
|
PROJECT_ROOT=/home/you/code/lio
|
|
30
|
-
|
|
30
|
+
BROWSER_PATH=/usr/bin/chromium
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
Re-run it any time the template changes or you move the repo.
|
|
@@ -41,17 +41,19 @@ Re-run it any time the template changes or you move the repo.
|
|
|
41
41
|
2. Falls back to walking three directories up from the script
|
|
42
42
|
(`.agents/skills/playwright-cli` → repo root) if the repo isn't a git checkout
|
|
43
43
|
|
|
44
|
-
**`
|
|
44
|
+
**`BROWSER_PATH`** — derived in this order:
|
|
45
45
|
|
|
46
|
-
1. The `
|
|
47
|
-
2.
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
1. The `BROWSER_PATH` environment variable, if set
|
|
47
|
+
2. The legacy `CHROME_PATH` environment variable, if set (kept for backwards compat)
|
|
48
|
+
3. First match from `PATH` of: `chromium`, `chromium-browser`, `google-chrome`,
|
|
49
|
+
`google-chrome-stable` — Chromium is preferred because Chrome is often missing
|
|
50
|
+
on WSL shells
|
|
51
|
+
4. Falls back to `/usr/bin/chromium` with a warning if nothing is found
|
|
50
52
|
|
|
51
|
-
Override the
|
|
53
|
+
Override the browser binary explicitly when needed:
|
|
52
54
|
|
|
53
55
|
```bash
|
|
54
|
-
|
|
56
|
+
BROWSER_PATH=/usr/bin/chromium .agents/skills/playwright-cli/setup-codex.sh
|
|
55
57
|
```
|
|
56
58
|
|
|
57
59
|
## Why a generator instead of variable expansion
|
|
@@ -158,6 +158,7 @@ playwright-cli video-stop video.webm
|
|
|
158
158
|
## Open parameters
|
|
159
159
|
```bash
|
|
160
160
|
# Use specific browser when creating session
|
|
161
|
+
playwright-cli open --browser=chromium
|
|
161
162
|
playwright-cli open --browser=chrome
|
|
162
163
|
playwright-cli open --browser=firefox
|
|
163
164
|
playwright-cli open --browser=webkit
|
|
@@ -19,10 +19,10 @@ inherit = "all"
|
|
|
19
19
|
|
|
20
20
|
[shell_environment_policy.set]
|
|
21
21
|
PLAYWRIGHT_BROWSERS_PATH = "__PROJECT_ROOT__/.artifacts/playwright/ms-playwright"
|
|
22
|
-
PLAYWRIGHT_MCP_BROWSER = "
|
|
23
|
-
PLAYWRIGHT_MCP_EXECUTABLE_PATH = "
|
|
24
|
-
PLAYWRIGHT_DAEMON_SOCKETS_DIR = "__PROJECT_ROOT__/.
|
|
25
|
-
BROWSER = "
|
|
22
|
+
PLAYWRIGHT_MCP_BROWSER = "chromium"
|
|
23
|
+
PLAYWRIGHT_MCP_EXECUTABLE_PATH = "__BROWSER_PATH__"
|
|
24
|
+
PLAYWRIGHT_DAEMON_SOCKETS_DIR = "__PROJECT_ROOT__/.tmp/codex-playwright/sockets"
|
|
25
|
+
BROWSER = "chromium"
|
|
26
26
|
HOME = "__PROJECT_ROOT__/.tmp/codex-playwright/home"
|
|
27
27
|
XDG_CONFIG_HOME = "__PROJECT_ROOT__/.tmp/codex-playwright/config"
|
|
28
28
|
XDG_STATE_HOME = "__PROJECT_ROOT__/.tmp/codex-playwright/state"
|
|
@@ -11,19 +11,19 @@ else
|
|
|
11
11
|
fi
|
|
12
12
|
OUTPUT="$PROJECT_ROOT/.codex/config.toml"
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
if [ -z "$
|
|
16
|
-
echo "warning: no Chrome
|
|
17
|
-
|
|
14
|
+
BROWSER_PATH="${BROWSER_PATH:-${CHROME_PATH:-$(command -v chromium || command -v chromium-browser || command -v google-chrome || command -v google-chrome-stable || true)}}"
|
|
15
|
+
if [ -z "$BROWSER_PATH" ]; then
|
|
16
|
+
echo "warning: no Chromium/Chrome binary found on PATH; set BROWSER_PATH=/path/to/browser and rerun" >&2
|
|
17
|
+
BROWSER_PATH="/usr/bin/chromium"
|
|
18
18
|
fi
|
|
19
19
|
|
|
20
20
|
mkdir -p "$(dirname "$OUTPUT")"
|
|
21
21
|
|
|
22
22
|
sed \
|
|
23
23
|
-e "s|__PROJECT_ROOT__|$PROJECT_ROOT|g" \
|
|
24
|
-
-e "s|
|
|
24
|
+
-e "s|__BROWSER_PATH__|$BROWSER_PATH|g" \
|
|
25
25
|
"$TEMPLATE" > "$OUTPUT"
|
|
26
26
|
|
|
27
27
|
echo "wrote $OUTPUT"
|
|
28
28
|
echo " PROJECT_ROOT=$PROJECT_ROOT"
|
|
29
|
-
echo "
|
|
29
|
+
echo " BROWSER_PATH=$BROWSER_PATH"
|