prompt-translator 0.0.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 +206 -0
- package/dist/cefr.d.ts +49 -0
- package/dist/cefr.d.ts.map +1 -0
- package/dist/cefr.js +36 -0
- package/dist/cefr.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +13 -0
- package/dist/cli.js.map +1 -0
- package/dist/generate.d.ts +16 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +45 -0
- package/dist/generate.js.map +1 -0
- package/dist/install.d.ts +9 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +69 -0
- package/dist/install.js.map +1 -0
- package/dist/interactive.d.ts +10 -0
- package/dist/interactive.d.ts.map +1 -0
- package/dist/interactive.js +219 -0
- package/dist/interactive.js.map +1 -0
- package/dist/languages.d.ts +11 -0
- package/dist/languages.d.ts.map +1 -0
- package/dist/languages.js +91 -0
- package/dist/languages.js.map +1 -0
- package/dist/paths.d.ts +9 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +41 -0
- package/dist/paths.js.map +1 -0
- package/dist/validate.d.ts +9 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +26 -0
- package/dist/validate.js.map +1 -0
- package/package.json +63 -0
- package/templates/SKILL.md.hbs +39 -0
- package/templates/languages.json +272 -0
package/README.md
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# prompt-translator
|
|
2
|
+
|
|
3
|
+
CLI tool to generate customized prompt-translator skills for AI agents.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### Global installation
|
|
8
|
+
```bash
|
|
9
|
+
bun install -g prompt-translator
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
### Using bunx (no install)
|
|
13
|
+
```bash
|
|
14
|
+
bunx prompt-translator
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
Run the CLI without any arguments to start the interactive installer:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
prompt-translator
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Interactive Flow
|
|
26
|
+
|
|
27
|
+
1. **Select AI Tool**
|
|
28
|
+
- `OpenCode` — for OpenCode CLI
|
|
29
|
+
- `Claude` — for claude.ai / Claude Code
|
|
30
|
+
- `Other` — for Codex, Gemini, and other agents
|
|
31
|
+
|
|
32
|
+
2. **Select Language** (BCP-47 tag)
|
|
33
|
+
- Choose from supported languages: zh, ja, ko, es, ru, fr, de, pt, it
|
|
34
|
+
|
|
35
|
+
3. **Select Region** (if multiple options)
|
|
36
|
+
- For languages with multiple regions, select the appropriate one
|
|
37
|
+
- Single-region languages (ja, ko, ru, pt) are auto-selected
|
|
38
|
+
|
|
39
|
+
4. **Select CEFR Level**
|
|
40
|
+
- A1–C2 (default: B2)
|
|
41
|
+
|
|
42
|
+
5. **Confirm** — Review and generate
|
|
43
|
+
|
|
44
|
+
### Example Session
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
$ prompt-translator
|
|
48
|
+
|
|
49
|
+
Prompt Translator Skill Generator
|
|
50
|
+
|
|
51
|
+
? Which AI tool are you using? OpenCode
|
|
52
|
+
→ config: ~/.config/opencode/AGENTS.md skills: ~/.config/opencode/skills/prompt-translator
|
|
53
|
+
|
|
54
|
+
? Language tag (type to search): zh
|
|
55
|
+
? Region for zh? TW
|
|
56
|
+
|
|
57
|
+
✓ BCP-47 tag: zh-TW
|
|
58
|
+
|
|
59
|
+
? Target English level (CEFR): B2 — Upper Intermediate (recommended)
|
|
60
|
+
|
|
61
|
+
Tool: OpenCode
|
|
62
|
+
Language: zh-TW
|
|
63
|
+
CEFR: B2
|
|
64
|
+
Skills: ~/.config/opencode/skills/prompt-translator
|
|
65
|
+
|
|
66
|
+
? Generate skill with these settings? Yes
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Installation Paths
|
|
70
|
+
|
|
71
|
+
### OpenCode
|
|
72
|
+
- Skills directory: `~/.config/opencode/skills/prompt-translator/`
|
|
73
|
+
- Config file: `~/.config/opencode/AGENTS.md`
|
|
74
|
+
|
|
75
|
+
### Claude
|
|
76
|
+
- Skills directory: `~/.claude/skills/prompt-translator/`
|
|
77
|
+
- Config file: `~/.claude/CLAUDE.md`
|
|
78
|
+
|
|
79
|
+
### Other (Codex, Gemini, etc.)
|
|
80
|
+
- Skills directory: `~/.agents/skills/prompt-translator/`
|
|
81
|
+
- Config file: `~/.agents/AGENTS.md`
|
|
82
|
+
|
|
83
|
+
## Configuration File Update
|
|
84
|
+
|
|
85
|
+
The CLI will:
|
|
86
|
+
|
|
87
|
+
1. **Scan** for existing `CLAUDE.md` or `AGENTS.md`
|
|
88
|
+
2. **If found**: Ask whether to add the skill to `## Required Skills`
|
|
89
|
+
3. **If not found**: Print a snippet for you to add manually
|
|
90
|
+
|
|
91
|
+
### Manual Snippet
|
|
92
|
+
|
|
93
|
+
If no config file exists, add this to your `AGENTS.md` or `CLAUDE.md`:
|
|
94
|
+
|
|
95
|
+
```markdown
|
|
96
|
+
## Required Skills
|
|
97
|
+
|
|
98
|
+
- **prompt-translator**: Use when the user's prompt contains [Language] text that needs translation to English before processing. Translates [Language] to CEFR [Level] English while preserving existing English, technical terms, and proper nouns.
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## CEFR Levels
|
|
102
|
+
|
|
103
|
+
| Level | Name | Description |
|
|
104
|
+
|-------|------|-------------|
|
|
105
|
+
| A1 | Beginner | Basic phrases and familiar everyday expressions |
|
|
106
|
+
| A2 | Elementary | Simple sentences and frequently used expressions |
|
|
107
|
+
| B1 | Intermediate | Clear standard communication on familiar matters |
|
|
108
|
+
| **B2** | **Upper Intermediate** | **Complex texts and technical discussion** *(default)* |
|
|
109
|
+
| C1 | Advanced | Fluent expression without much searching |
|
|
110
|
+
| C2 | Proficient | Near-native precision and nuance |
|
|
111
|
+
|
|
112
|
+
## Supported Languages
|
|
113
|
+
|
|
114
|
+
The following BCP-47 language tags are supported:
|
|
115
|
+
|
|
116
|
+
### Chinese
|
|
117
|
+
- `zh-TW` — Traditional Chinese (Taiwan)
|
|
118
|
+
- `zh-HK` — Traditional Chinese (Hong Kong)
|
|
119
|
+
- `zh-CN` — Simplified Chinese (China)
|
|
120
|
+
|
|
121
|
+
### Japanese
|
|
122
|
+
- `ja-JP` — Japanese (Japan)
|
|
123
|
+
|
|
124
|
+
### Korean
|
|
125
|
+
- `ko-KR` — Korean (South Korea)
|
|
126
|
+
|
|
127
|
+
### Spanish
|
|
128
|
+
- `es-ES` — Spanish (Spain)
|
|
129
|
+
- `es-MX` — Spanish (Mexico)
|
|
130
|
+
|
|
131
|
+
### Russian
|
|
132
|
+
- `ru-RU` — Russian (Russia)
|
|
133
|
+
|
|
134
|
+
### French
|
|
135
|
+
- `fr-FR` — French (France)
|
|
136
|
+
- `fr-CA` — French (Canada)
|
|
137
|
+
|
|
138
|
+
### German
|
|
139
|
+
- `de-DE` — German (Germany)
|
|
140
|
+
- `de-CH` — German (Switzerland)
|
|
141
|
+
|
|
142
|
+
### Portuguese
|
|
143
|
+
- `pt-BR` — Portuguese (Brazil)
|
|
144
|
+
|
|
145
|
+
### Italian
|
|
146
|
+
- `it-IT` — Italian (Italy)
|
|
147
|
+
- `it-CH` — Italian (Switzerland)
|
|
148
|
+
|
|
149
|
+
## Development
|
|
150
|
+
|
|
151
|
+
### Setup
|
|
152
|
+
```bash
|
|
153
|
+
bun install
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Build
|
|
157
|
+
```bash
|
|
158
|
+
bun run build
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Test
|
|
162
|
+
```bash
|
|
163
|
+
bun run test
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Project Structure
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
prompt-translator/
|
|
170
|
+
├── src/
|
|
171
|
+
│ ├── cli.ts # CLI entry point
|
|
172
|
+
│ ├── interactive.ts # Interactive prompts
|
|
173
|
+
│ ├── generate.ts # Skill generation logic
|
|
174
|
+
│ ├── languages.ts # Language name utilities
|
|
175
|
+
│ ├── cefr.ts # CEFR level definitions
|
|
176
|
+
│ ├── paths.ts # File path resolution
|
|
177
|
+
│ └── install.ts # Config file installation
|
|
178
|
+
├── templates/
|
|
179
|
+
│ ├── SKILL.md.hbs # Skill template (Handlebars)
|
|
180
|
+
│ └── languages.json # Example translations per language
|
|
181
|
+
└── README.md
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Adding/Modifying Examples
|
|
185
|
+
|
|
186
|
+
Edit `templates/languages.json` to add or modify translation examples. Each language key contains an array of `{input, output}` pairs:
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"zh": [
|
|
191
|
+
{ "input": "請幫我寫一個 Python script", "output": "Please help me write a Python script" },
|
|
192
|
+
...
|
|
193
|
+
],
|
|
194
|
+
"ja": [...],
|
|
195
|
+
...
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Template Customization
|
|
200
|
+
|
|
201
|
+
Edit `templates/SKILL.md.hbs` to modify the skill structure:
|
|
202
|
+
- `{{skillName}}` — Name of the skill
|
|
203
|
+
- `{{languageName}}` — Human-readable language name
|
|
204
|
+
- `{{cefrLevel}}` — CEFR level (A1–C2)
|
|
205
|
+
- `{{cefrDescription}}` — Description of the level
|
|
206
|
+
- `{{#each examples}}` — Loop through examples
|
package/dist/cefr.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export declare const CEFR_LEVELS: {
|
|
2
|
+
readonly A1: {
|
|
3
|
+
readonly name: "Beginner";
|
|
4
|
+
readonly description: "basic phrases and familiar everyday expressions";
|
|
5
|
+
};
|
|
6
|
+
readonly A2: {
|
|
7
|
+
readonly name: "Elementary";
|
|
8
|
+
readonly description: "simple sentences and frequently used expressions";
|
|
9
|
+
};
|
|
10
|
+
readonly B1: {
|
|
11
|
+
readonly name: "Intermediate";
|
|
12
|
+
readonly description: "clear standard communication on familiar matters";
|
|
13
|
+
};
|
|
14
|
+
readonly B2: {
|
|
15
|
+
readonly name: "Upper Intermediate";
|
|
16
|
+
readonly description: "complex texts and technical discussion in specialization";
|
|
17
|
+
};
|
|
18
|
+
readonly C1: {
|
|
19
|
+
readonly name: "Advanced";
|
|
20
|
+
readonly description: "fluent expression without much searching for expressions";
|
|
21
|
+
};
|
|
22
|
+
readonly C2: {
|
|
23
|
+
readonly name: "Proficient";
|
|
24
|
+
readonly description: "near-native precision and nuance";
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export type CEFRLevel = keyof typeof CEFR_LEVELS;
|
|
28
|
+
export declare function isValidCEFR(level: string): level is CEFRLevel;
|
|
29
|
+
export declare function getCEFRInfo(level: CEFRLevel): {
|
|
30
|
+
readonly name: "Beginner";
|
|
31
|
+
readonly description: "basic phrases and familiar everyday expressions";
|
|
32
|
+
} | {
|
|
33
|
+
readonly name: "Elementary";
|
|
34
|
+
readonly description: "simple sentences and frequently used expressions";
|
|
35
|
+
} | {
|
|
36
|
+
readonly name: "Intermediate";
|
|
37
|
+
readonly description: "clear standard communication on familiar matters";
|
|
38
|
+
} | {
|
|
39
|
+
readonly name: "Upper Intermediate";
|
|
40
|
+
readonly description: "complex texts and technical discussion in specialization";
|
|
41
|
+
} | {
|
|
42
|
+
readonly name: "Advanced";
|
|
43
|
+
readonly description: "fluent expression without much searching for expressions";
|
|
44
|
+
} | {
|
|
45
|
+
readonly name: "Proficient";
|
|
46
|
+
readonly description: "near-native precision and nuance";
|
|
47
|
+
};
|
|
48
|
+
export declare function getDefaultCEFR(): CEFRLevel;
|
|
49
|
+
//# sourceMappingURL=cefr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cefr.d.ts","sourceRoot":"","sources":["../src/cefr.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;CAyBd,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,WAAW,CAAC;AAEjD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,SAAS,CAE7D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS;;;;;;;;;;;;;;;;;;EAE3C;AAED,wBAAgB,cAAc,IAAI,SAAS,CAE1C"}
|
package/dist/cefr.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const CEFR_LEVELS = {
|
|
2
|
+
A1: {
|
|
3
|
+
name: 'Beginner',
|
|
4
|
+
description: 'basic phrases and familiar everyday expressions',
|
|
5
|
+
},
|
|
6
|
+
A2: {
|
|
7
|
+
name: 'Elementary',
|
|
8
|
+
description: 'simple sentences and frequently used expressions',
|
|
9
|
+
},
|
|
10
|
+
B1: {
|
|
11
|
+
name: 'Intermediate',
|
|
12
|
+
description: 'clear standard communication on familiar matters',
|
|
13
|
+
},
|
|
14
|
+
B2: {
|
|
15
|
+
name: 'Upper Intermediate',
|
|
16
|
+
description: 'complex texts and technical discussion in specialization',
|
|
17
|
+
},
|
|
18
|
+
C1: {
|
|
19
|
+
name: 'Advanced',
|
|
20
|
+
description: 'fluent expression without much searching for expressions',
|
|
21
|
+
},
|
|
22
|
+
C2: {
|
|
23
|
+
name: 'Proficient',
|
|
24
|
+
description: 'near-native precision and nuance',
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
export function isValidCEFR(level) {
|
|
28
|
+
return level.toUpperCase() in CEFR_LEVELS;
|
|
29
|
+
}
|
|
30
|
+
export function getCEFRInfo(level) {
|
|
31
|
+
return CEFR_LEVELS[level];
|
|
32
|
+
}
|
|
33
|
+
export function getDefaultCEFR() {
|
|
34
|
+
return 'B2';
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=cefr.js.map
|
package/dist/cefr.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cefr.js","sourceRoot":"","sources":["../src/cefr.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;IAC1B,EAAE,EAAE;QACH,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,iDAAiD;KAC9D;IACD,EAAE,EAAE;QACH,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,kDAAkD;KAC/D;IACD,EAAE,EAAE;QACH,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,kDAAkD;KAC/D;IACD,EAAE,EAAE;QACH,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,0DAA0D;KACvE;IACD,EAAE,EAAE;QACH,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,0DAA0D;KACvE;IACD,EAAE,EAAE;QACH,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,kCAAkC;KAC/C;CACQ,CAAC;AAIX,MAAM,UAAU,WAAW,CAAC,KAAa;IACxC,OAAO,KAAK,CAAC,WAAW,EAAE,IAAI,WAAW,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAgB;IAC3C,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,cAAc;IAC7B,OAAO,IAAI,CAAC;AACb,CAAC"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { runInteractive } from './interactive.js';
|
|
4
|
+
const program = new Command();
|
|
5
|
+
program
|
|
6
|
+
.name('prompt-translator')
|
|
7
|
+
.description('Generate customized prompt-translator skills for AI agents')
|
|
8
|
+
.version('1.0.0')
|
|
9
|
+
.action(async () => {
|
|
10
|
+
await runInteractive();
|
|
11
|
+
});
|
|
12
|
+
program.parse();
|
|
13
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACL,IAAI,CAAC,mBAAmB,CAAC;KACzB,WAAW,CAAC,4DAA4D,CAAC;KACzE,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,KAAK,IAAI,EAAE;IAClB,MAAM,cAAc,EAAE,CAAC;AACxB,CAAC,CAAC,CAAC;AAEJ,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type CEFRLevel } from './cefr.js';
|
|
2
|
+
import type { ToolTarget } from './paths.js';
|
|
3
|
+
export declare const SKILL_NAME = "prompt-translator";
|
|
4
|
+
export interface GenerateOptions {
|
|
5
|
+
lang: string;
|
|
6
|
+
cefr: CEFRLevel;
|
|
7
|
+
target: ToolTarget;
|
|
8
|
+
cwd: string;
|
|
9
|
+
}
|
|
10
|
+
export interface GenerateResult {
|
|
11
|
+
skillPath: string;
|
|
12
|
+
skillName: string;
|
|
13
|
+
skillDescription: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function generateSkill(options: GenerateOptions): Promise<GenerateResult>;
|
|
16
|
+
//# sourceMappingURL=generate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,WAAW,CAAC;AAExD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,eAAO,MAAM,UAAU,sBAAsB,CAAC;AAE9C,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,cAAc;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;CACzB;AAED,wBAAsB,aAAa,CAClC,OAAO,EAAE,eAAe,GACtB,OAAO,CAAC,cAAc,CAAC,CAuCzB"}
|
package/dist/generate.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import Handlebars from 'handlebars';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { getCEFRInfo } from './cefr.js';
|
|
7
|
+
import { getLanguageName } from './languages.js';
|
|
8
|
+
export const SKILL_NAME = 'prompt-translator';
|
|
9
|
+
export async function generateSkill(options) {
|
|
10
|
+
const { lang, cefr, target } = options;
|
|
11
|
+
const languageName = getLanguageName(lang);
|
|
12
|
+
const cefrInfo = getCEFRInfo(cefr);
|
|
13
|
+
const examplesData = await loadExamples();
|
|
14
|
+
const examples = getExamples(lang, examplesData);
|
|
15
|
+
const templateData = {
|
|
16
|
+
skillName: SKILL_NAME,
|
|
17
|
+
languageName,
|
|
18
|
+
cefrLevel: cefr,
|
|
19
|
+
cefrDescription: cefrInfo.description,
|
|
20
|
+
...examples,
|
|
21
|
+
};
|
|
22
|
+
// skill dir is fixed: target.skillsDir already includes "prompt-translator"
|
|
23
|
+
await mkdir(target.skillsDir, { recursive: true });
|
|
24
|
+
const templatePath = join(dirname(fileURLToPath(import.meta.url)), '..', 'templates', 'SKILL.md.hbs');
|
|
25
|
+
const templateContent = await readFile(templatePath, 'utf-8');
|
|
26
|
+
const skillContent = Handlebars.compile(templateContent)(templateData);
|
|
27
|
+
const skillPath = join(target.skillsDir, 'SKILL.md');
|
|
28
|
+
await writeFile(skillPath, skillContent);
|
|
29
|
+
console.log(chalk.green(` ✓ Skill written to ${skillPath}`));
|
|
30
|
+
const skillDescription = `Use when the user's prompt contains ${languageName} text that needs translation to English before processing. ` +
|
|
31
|
+
`Translates ${languageName} to CEFR ${cefr} English while preserving existing English, technical terms, and proper nouns.`;
|
|
32
|
+
return { skillPath, skillName: SKILL_NAME, skillDescription };
|
|
33
|
+
}
|
|
34
|
+
// ── examples ──────────────────────────────────────────────────────────────────
|
|
35
|
+
async function loadExamples() {
|
|
36
|
+
const filePath = join(dirname(fileURLToPath(import.meta.url)), '..', 'templates', 'languages.json');
|
|
37
|
+
const content = await readFile(filePath, 'utf-8');
|
|
38
|
+
return JSON.parse(content);
|
|
39
|
+
}
|
|
40
|
+
function getExamples(lang, data) {
|
|
41
|
+
const base = lang.split('-')[0].toLowerCase();
|
|
42
|
+
const examples = data[base] ?? data.zh;
|
|
43
|
+
return { examples };
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAkB,WAAW,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGjD,MAAM,CAAC,MAAM,UAAU,GAAG,mBAAmB,CAAC;AAe9C,MAAM,CAAC,KAAK,UAAU,aAAa,CAClC,OAAwB;IAExB,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAEvC,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,YAAY,GAAG,MAAM,YAAY,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAEjD,MAAM,YAAY,GAAG;QACpB,SAAS,EAAE,UAAU;QACrB,YAAY;QACZ,SAAS,EAAE,IAAI;QACf,eAAe,EAAE,QAAQ,CAAC,WAAW;QACrC,GAAG,QAAQ;KACX,CAAC;IAEF,4EAA4E;IAC5E,MAAM,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEnD,MAAM,YAAY,GAAG,IAAI,CACxB,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EACvC,IAAI,EACJ,WAAW,EACX,cAAc,CACd,CAAC;IAEF,MAAM,eAAe,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC9D,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,YAAY,CAAC,CAAC;IAEvE,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACrD,MAAM,SAAS,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAEzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,wBAAwB,SAAS,EAAE,CAAC,CAAC,CAAC;IAE9D,MAAM,gBAAgB,GACrB,uCAAuC,YAAY,6DAA6D;QAChH,cAAc,YAAY,YAAY,IAAI,gFAAgF,CAAC;IAE5H,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC;AAC/D,CAAC;AAED,iFAAiF;AAEjF,KAAK,UAAU,YAAY;IAG1B,MAAM,QAAQ,GAAG,IAAI,CACpB,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EACvC,IAAI,EACJ,WAAW,EACX,gBAAgB,CAChB,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAClD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,WAAW,CACnB,IAAY,EACZ,IAA8D;IAE9D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC;IACvC,OAAO,EAAE,QAAQ,EAAE,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ToolTarget } from './paths.js';
|
|
2
|
+
export interface InstallOptions {
|
|
3
|
+
target: ToolTarget;
|
|
4
|
+
skillName: string;
|
|
5
|
+
skillDescription: string;
|
|
6
|
+
cwd: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function installConfig(options: InstallOptions): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGxC,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;CACZ;AAID,wBAAsB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAuC1E"}
|
package/dist/install.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import prompts from 'prompts';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { SKILL_NAME } from './generate.js';
|
|
6
|
+
const SECTION_HEADER = '## Required Skills';
|
|
7
|
+
export async function installConfig(options) {
|
|
8
|
+
const { target, skillName, skillDescription } = options;
|
|
9
|
+
const { configFile, configFileName } = target;
|
|
10
|
+
const entry = `- **${skillName}**: ${skillDescription}`;
|
|
11
|
+
// Config file does not exist — print suggestion only, do not create
|
|
12
|
+
if (!existsSync(configFile)) {
|
|
13
|
+
console.log('');
|
|
14
|
+
console.log(chalk.yellow(`${configFileName} not found at ${configFile}`));
|
|
15
|
+
console.log(chalk.gray('Add the following snippet to your config file manually:\n'));
|
|
16
|
+
printSuggestion(entry);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
// Config file exists — ask whether to update
|
|
20
|
+
const { shouldUpdate } = await prompts({
|
|
21
|
+
type: 'confirm',
|
|
22
|
+
name: 'shouldUpdate',
|
|
23
|
+
message: `Found ${configFileName}. Add skill to "${SECTION_HEADER}"?`,
|
|
24
|
+
initial: true,
|
|
25
|
+
});
|
|
26
|
+
if (!shouldUpdate) {
|
|
27
|
+
console.log('');
|
|
28
|
+
console.log(chalk.gray('Skipped. Add the following snippet manually:\n'));
|
|
29
|
+
printSuggestion(entry);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const original = await readFile(configFile, 'utf-8');
|
|
33
|
+
// Backup before modifying
|
|
34
|
+
await writeFile(`${configFile}.bak`, original);
|
|
35
|
+
const updated = upsertSkillEntry(original, entry);
|
|
36
|
+
await writeFile(configFile, updated);
|
|
37
|
+
console.log(chalk.green(` ✓ Updated ${configFileName}`));
|
|
38
|
+
}
|
|
39
|
+
// ── helpers ───────────────────────────────────────────────────────────────────
|
|
40
|
+
function printSuggestion(entry) {
|
|
41
|
+
console.log(chalk.cyan(`${SECTION_HEADER}\n\n${entry}`));
|
|
42
|
+
console.log('');
|
|
43
|
+
}
|
|
44
|
+
function upsertSkillEntry(content, entry) {
|
|
45
|
+
const sectionIdx = content.indexOf(SECTION_HEADER);
|
|
46
|
+
if (sectionIdx === -1) {
|
|
47
|
+
// Append section at end
|
|
48
|
+
const suffix = content.endsWith('\n') ? '' : '\n';
|
|
49
|
+
return `${content}${suffix}\n${SECTION_HEADER}\n\n${entry}\n`;
|
|
50
|
+
}
|
|
51
|
+
// Find section boundaries
|
|
52
|
+
const afterHeader = sectionIdx + SECTION_HEADER.length;
|
|
53
|
+
const nextSectionMatch = content.slice(afterHeader).match(/\n## /);
|
|
54
|
+
const sectionEnd = nextSectionMatch
|
|
55
|
+
? afterHeader + nextSectionMatch.index
|
|
56
|
+
: content.length;
|
|
57
|
+
const sectionBody = content.slice(afterHeader, sectionEnd);
|
|
58
|
+
// Already listed — update in place
|
|
59
|
+
if (sectionBody.includes(SKILL_NAME)) {
|
|
60
|
+
const pattern = new RegExp(`^- \\*\\*${SKILL_NAME}\\*\\*:.*$`, 'm');
|
|
61
|
+
const newBody = sectionBody.replace(pattern, entry);
|
|
62
|
+
return content.slice(0, afterHeader) + newBody + content.slice(sectionEnd);
|
|
63
|
+
}
|
|
64
|
+
// Append to section
|
|
65
|
+
const trimmed = sectionBody.trimEnd();
|
|
66
|
+
const newBody = trimmed.length ? `${trimmed}\n${entry}\n` : `\n\n${entry}\n`;
|
|
67
|
+
return content.slice(0, afterHeader) + newBody + content.slice(sectionEnd);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ToolTarget } from './paths.js';
|
|
2
|
+
import type { CEFRLevel } from './cefr.js';
|
|
3
|
+
export interface InteractiveResult {
|
|
4
|
+
tool: 'claude' | 'other';
|
|
5
|
+
lang: string;
|
|
6
|
+
cefr: CEFRLevel;
|
|
7
|
+
target: ToolTarget;
|
|
8
|
+
}
|
|
9
|
+
export declare function runInteractive(): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=interactive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../src/interactive.ts"],"names":[],"mappings":"AAEA,OAAO,EACN,KAAK,UAAU,EAGf,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAI3C,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,UAAU,CAAC;CACnB;AAiHD,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAqIpD"}
|