@justin_666/square-couplets-master-skills 1.0.4 → 1.0.6
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/bin/doufang-image.js +20 -0
- package/bin/doufang-init.js +50 -9
- package/bin/doufang-optimize.js +20 -0
- package/bin/doufang-prompt.js +20 -0
- package/bin/doufang-skills.js +20 -0
- package/package.json +4 -3
- package/skills/generate-doufang-image/SKILL.md +6 -0
- package/skills/generate-doufang-image/index.js +65 -4
- package/skills/generate-doufang-prompt/SKILL.md +8 -0
- package/skills/generate-doufang-prompt/index.js +90 -16
- package/skills/optimize-doufang-prompt/SKILL.md +8 -0
package/bin/doufang-image.js
CHANGED
|
@@ -7,18 +7,38 @@
|
|
|
7
7
|
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
9
|
import { dirname, join, resolve } from 'path';
|
|
10
|
+
import { readFileSync } from 'fs';
|
|
10
11
|
import { spawn } from 'child_process';
|
|
11
12
|
|
|
12
13
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
14
|
const __dirname = dirname(__filename);
|
|
14
15
|
const packageRoot = resolve(__dirname, '..');
|
|
15
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Get package version
|
|
19
|
+
*/
|
|
20
|
+
function getVersion() {
|
|
21
|
+
try {
|
|
22
|
+
const packageJsonPath = join(packageRoot, 'package.json');
|
|
23
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
24
|
+
return packageJson.version || 'unknown';
|
|
25
|
+
} catch (e) {
|
|
26
|
+
return 'unknown';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
16
30
|
// Path to the skill script
|
|
17
31
|
const skillScript = join(packageRoot, 'skills', 'generate-doufang-image', 'index.js');
|
|
18
32
|
|
|
19
33
|
// Forward all arguments to the skill script
|
|
20
34
|
const args = process.argv.slice(2);
|
|
21
35
|
|
|
36
|
+
// Handle version flag
|
|
37
|
+
if (args[0] === '--version' || args[0] === '-v' || args[0] === 'version') {
|
|
38
|
+
console.log(getVersion());
|
|
39
|
+
process.exit(0);
|
|
40
|
+
}
|
|
41
|
+
|
|
22
42
|
const child = spawn('node', [skillScript, ...args], {
|
|
23
43
|
stdio: 'inherit',
|
|
24
44
|
cwd: process.cwd()
|
package/bin/doufang-init.js
CHANGED
|
@@ -15,6 +15,19 @@ const __dirname = dirname(__filename);
|
|
|
15
15
|
// Get package root directory
|
|
16
16
|
const packageRoot = resolve(__dirname, '..');
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Get package version
|
|
20
|
+
*/
|
|
21
|
+
function getVersion() {
|
|
22
|
+
try {
|
|
23
|
+
const packageJsonPath = join(packageRoot, 'package.json');
|
|
24
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
25
|
+
return packageJson.version || 'unknown';
|
|
26
|
+
} catch (e) {
|
|
27
|
+
return 'unknown';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
18
31
|
/**
|
|
19
32
|
* Get the path to skills directory
|
|
20
33
|
*/
|
|
@@ -142,8 +155,18 @@ You are a Doufang assistant. When the user uses the \`/doufang\` command or asks
|
|
|
142
155
|
|
|
143
156
|
## Execution Guidelines
|
|
144
157
|
|
|
145
|
-
- **Direct CLI Execution**:
|
|
146
|
-
-
|
|
158
|
+
- **CRITICAL: Direct CLI Execution Only**:
|
|
159
|
+
- When user requests Doufang functionality, you MUST directly execute the CLI command in the terminal
|
|
160
|
+
- **NEVER create temporary .js, .ts, or any script files**
|
|
161
|
+
- **NEVER write code to files** - just execute the command directly
|
|
162
|
+
- Use the terminal/command execution tool to run: \`doufang-prompt\`, \`doufang-image\`, or \`doufang-optimize\`
|
|
163
|
+
|
|
164
|
+
- **Command Execution Examples**:
|
|
165
|
+
- User: "生成財富主題的 prompt" → Execute: \`doufang-prompt "財富"\`
|
|
166
|
+
- User: "用上述 prompt 生成 2K 圖片" → Execute: \`doufang-image "<prompt>" gemini-3-pro-image-preview 2K\`
|
|
167
|
+
- User: "優化這個 prompt" → Execute: \`doufang-optimize "<prompt>"\`
|
|
168
|
+
|
|
169
|
+
- **Read API Key**: Automatically read GEMINI_API_KEY from .env or .env.local file (CLI commands handle this automatically)
|
|
147
170
|
- **Ask for Details**: If user doesn't provide required parameters (like keyword or prompt), ask for clarification
|
|
148
171
|
- **Error Handling**: If API key is missing, guide user to set GEMINI_API_KEY in .env file
|
|
149
172
|
- **Output Format**: For prompt generation, output JSON format. For image generation, save to output/ directory and provide file path
|
|
@@ -151,19 +174,27 @@ You are a Doufang assistant. When the user uses the \`/doufang\` command or asks
|
|
|
151
174
|
## Common Workflows
|
|
152
175
|
|
|
153
176
|
### Generate Image from Keyword
|
|
154
|
-
1.
|
|
177
|
+
1. Execute: \`doufang-prompt "財富"\` (directly in terminal, no script creation)
|
|
155
178
|
2. Extract imagePrompt from JSON output
|
|
156
|
-
3.
|
|
179
|
+
3. Execute: \`doufang-image "<imagePrompt>" gemini-3-pro-image-preview 2K\` (directly in terminal, no script creation)
|
|
157
180
|
|
|
158
181
|
### Generate Image with Reference
|
|
159
|
-
1.
|
|
182
|
+
1. Execute: \`doufang-prompt "健康" images/reference.png\` (directly in terminal)
|
|
160
183
|
2. Extract imagePrompt from JSON output
|
|
161
|
-
3.
|
|
184
|
+
3. Execute: \`doufang-image "<imagePrompt>" gemini-3-pro-image-preview 2K images/reference.png\` (directly in terminal)
|
|
162
185
|
|
|
163
186
|
### Optimize and Generate
|
|
164
|
-
1.
|
|
165
|
-
2.
|
|
166
|
-
3.
|
|
187
|
+
1. Execute: \`doufang-prompt "財富"\` (directly in terminal)
|
|
188
|
+
2. Execute: \`doufang-optimize "<imagePrompt>"\` (directly in terminal)
|
|
189
|
+
3. Execute: \`doufang-image "<optimizedPrompt>" gemini-3-pro-image-preview 2K\` (directly in terminal)
|
|
190
|
+
|
|
191
|
+
## IMPORTANT REMINDERS
|
|
192
|
+
|
|
193
|
+
- **DO NOT** create any .js, .ts, .mjs, or script files
|
|
194
|
+
- **DO NOT** write code to files
|
|
195
|
+
- **DO** execute CLI commands directly using terminal/command execution
|
|
196
|
+
- The CLI commands (\`doufang-prompt\`, \`doufang-image\`, \`doufang-optimize\`) are already installed and ready to use
|
|
197
|
+
- Just run the commands - they handle everything automatically
|
|
167
198
|
|
|
168
199
|
## Skills Location
|
|
169
200
|
|
|
@@ -308,6 +339,12 @@ function main() {
|
|
|
308
339
|
const args = process.argv.slice(2);
|
|
309
340
|
const command = args[0];
|
|
310
341
|
|
|
342
|
+
// Handle version flag (check before parsing other options)
|
|
343
|
+
if (command === '--version' || command === '-v' || command === 'version') {
|
|
344
|
+
console.log(getVersion());
|
|
345
|
+
process.exit(0);
|
|
346
|
+
}
|
|
347
|
+
|
|
311
348
|
// Parse --ai option
|
|
312
349
|
let aiOption = null;
|
|
313
350
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -317,6 +354,9 @@ function main() {
|
|
|
317
354
|
} else if (args[i]?.startsWith('--ai=')) {
|
|
318
355
|
aiOption = args[i].replace('--ai=', '');
|
|
319
356
|
break;
|
|
357
|
+
} else if (args[i] === '--version' || args[i] === '-v' || args[i] === 'version') {
|
|
358
|
+
console.log(getVersion());
|
|
359
|
+
process.exit(0);
|
|
320
360
|
}
|
|
321
361
|
}
|
|
322
362
|
|
|
@@ -329,6 +369,7 @@ Usage:
|
|
|
329
369
|
|
|
330
370
|
Options:
|
|
331
371
|
--ai <assistant> AI assistant to configure (cursor, windsurf, antigravity, or claude)
|
|
372
|
+
--version, -v Show version number
|
|
332
373
|
|
|
333
374
|
Examples:
|
|
334
375
|
doufang init --ai cursor
|
package/bin/doufang-optimize.js
CHANGED
|
@@ -7,18 +7,38 @@
|
|
|
7
7
|
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
9
|
import { dirname, join, resolve } from 'path';
|
|
10
|
+
import { readFileSync } from 'fs';
|
|
10
11
|
import { spawn } from 'child_process';
|
|
11
12
|
|
|
12
13
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
14
|
const __dirname = dirname(__filename);
|
|
14
15
|
const packageRoot = resolve(__dirname, '..');
|
|
15
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Get package version
|
|
19
|
+
*/
|
|
20
|
+
function getVersion() {
|
|
21
|
+
try {
|
|
22
|
+
const packageJsonPath = join(packageRoot, 'package.json');
|
|
23
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
24
|
+
return packageJson.version || 'unknown';
|
|
25
|
+
} catch (e) {
|
|
26
|
+
return 'unknown';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
16
30
|
// Path to the skill script
|
|
17
31
|
const skillScript = join(packageRoot, 'skills', 'optimize-doufang-prompt', 'index.js');
|
|
18
32
|
|
|
19
33
|
// Forward all arguments to the skill script
|
|
20
34
|
const args = process.argv.slice(2);
|
|
21
35
|
|
|
36
|
+
// Handle version flag
|
|
37
|
+
if (args[0] === '--version' || args[0] === '-v' || args[0] === 'version') {
|
|
38
|
+
console.log(getVersion());
|
|
39
|
+
process.exit(0);
|
|
40
|
+
}
|
|
41
|
+
|
|
22
42
|
const child = spawn('node', [skillScript, ...args], {
|
|
23
43
|
stdio: 'inherit',
|
|
24
44
|
cwd: process.cwd()
|
package/bin/doufang-prompt.js
CHANGED
|
@@ -7,18 +7,38 @@
|
|
|
7
7
|
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
9
|
import { dirname, join, resolve } from 'path';
|
|
10
|
+
import { readFileSync } from 'fs';
|
|
10
11
|
import { spawn } from 'child_process';
|
|
11
12
|
|
|
12
13
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
14
|
const __dirname = dirname(__filename);
|
|
14
15
|
const packageRoot = resolve(__dirname, '..');
|
|
15
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Get package version
|
|
19
|
+
*/
|
|
20
|
+
function getVersion() {
|
|
21
|
+
try {
|
|
22
|
+
const packageJsonPath = join(packageRoot, 'package.json');
|
|
23
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
24
|
+
return packageJson.version || 'unknown';
|
|
25
|
+
} catch (e) {
|
|
26
|
+
return 'unknown';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
16
30
|
// Path to the skill script
|
|
17
31
|
const skillScript = join(packageRoot, 'skills', 'generate-doufang-prompt', 'index.js');
|
|
18
32
|
|
|
19
33
|
// Forward all arguments to the skill script
|
|
20
34
|
const args = process.argv.slice(2);
|
|
21
35
|
|
|
36
|
+
// Handle version flag
|
|
37
|
+
if (args[0] === '--version' || args[0] === '-v' || args[0] === 'version') {
|
|
38
|
+
console.log(getVersion());
|
|
39
|
+
process.exit(0);
|
|
40
|
+
}
|
|
41
|
+
|
|
22
42
|
const child = spawn('node', [skillScript, ...args], {
|
|
23
43
|
stdio: 'inherit',
|
|
24
44
|
cwd: process.cwd()
|
package/bin/doufang-skills.js
CHANGED
|
@@ -15,6 +15,19 @@ const __dirname = dirname(__filename);
|
|
|
15
15
|
// Get package root directory (parent of bin/)
|
|
16
16
|
const packageRoot = resolve(__dirname, '..');
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Get package version
|
|
20
|
+
*/
|
|
21
|
+
function getVersion() {
|
|
22
|
+
try {
|
|
23
|
+
const packageJsonPath = join(packageRoot, 'package.json');
|
|
24
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
25
|
+
return packageJson.version || 'unknown';
|
|
26
|
+
} catch (e) {
|
|
27
|
+
return 'unknown';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
18
31
|
/**
|
|
19
32
|
* Get the path to skills directory
|
|
20
33
|
*/
|
|
@@ -120,6 +133,12 @@ function main() {
|
|
|
120
133
|
const args = process.argv.slice(2);
|
|
121
134
|
const command = args[0];
|
|
122
135
|
|
|
136
|
+
// Handle version flag
|
|
137
|
+
if (command === '--version' || command === '-v' || command === 'version') {
|
|
138
|
+
console.log(getVersion());
|
|
139
|
+
process.exit(0);
|
|
140
|
+
}
|
|
141
|
+
|
|
123
142
|
if (!command || command === 'list' || command === 'ls') {
|
|
124
143
|
listSkills();
|
|
125
144
|
} else if (command === 'show' || command === 'view') {
|
|
@@ -150,6 +169,7 @@ Commands:
|
|
|
150
169
|
list, ls List all available skills
|
|
151
170
|
show <skill-name> Show a specific skill's content
|
|
152
171
|
path <skill-name> Get the file path to a skill
|
|
172
|
+
version, --version Show version number
|
|
153
173
|
help Show this help message
|
|
154
174
|
|
|
155
175
|
Examples:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@justin_666/square-couplets-master-skills",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Claude Agent Skills for generating Chinese New Year Doufang (diamond-shaped couplet) artwork using Google Gemini AI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bin/doufang-skills.js",
|
|
@@ -59,12 +59,13 @@
|
|
|
59
59
|
"engines": {
|
|
60
60
|
"node": ">=18.0.0"
|
|
61
61
|
},
|
|
62
|
-
"dependencies": {
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"dotenv": "^17.2.3"
|
|
64
|
+
},
|
|
63
65
|
"devDependencies": {
|
|
64
66
|
"@google/genai": "^1.37.0",
|
|
65
67
|
"@types/node": "^22.14.0",
|
|
66
68
|
"@vitejs/plugin-react": "^5.0.0",
|
|
67
|
-
"dotenv": "^17.2.3",
|
|
68
69
|
"react": "^19.2.3",
|
|
69
70
|
"react-dom": "^19.2.3",
|
|
70
71
|
"tsx": "^4.21.0",
|
|
@@ -151,6 +151,12 @@ Error: Network connection error. Please check your internet connection and try a
|
|
|
151
151
|
|
|
152
152
|
## Implementation Notes
|
|
153
153
|
|
|
154
|
+
- **CRITICAL: Use CLI Command Directly**
|
|
155
|
+
- Execute: `doufang-image <prompt> [model] [size] [reference-image] [output-path]`
|
|
156
|
+
- **DO NOT create temporary .js, .ts, or any script files**
|
|
157
|
+
- **DO NOT write code** - just execute the CLI command directly
|
|
158
|
+
- The CLI command handles all API calls, error handling, and file operations automatically
|
|
159
|
+
|
|
154
160
|
- Use retry mechanism for transient errors (500, 503, network errors)
|
|
155
161
|
- Compress reference images if they exceed 500KB
|
|
156
162
|
- Validate image formats (JPEG, PNG supported)
|
|
@@ -8,7 +8,33 @@
|
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
9
|
import { dirname, join, resolve } from 'path';
|
|
10
10
|
import { readFileSync, writeFileSync, existsSync, statSync, mkdirSync } from 'fs';
|
|
11
|
-
import {
|
|
11
|
+
import { execSync } from 'child_process';
|
|
12
|
+
import { createRequire } from 'module';
|
|
13
|
+
|
|
14
|
+
// Load environment variables helper
|
|
15
|
+
async function loadEnvironmentVariables() {
|
|
16
|
+
try {
|
|
17
|
+
const dotenv = await import('dotenv');
|
|
18
|
+
const envLocalPath = join(projectRoot, '.env.local');
|
|
19
|
+
const envPath = join(projectRoot, '.env');
|
|
20
|
+
const cwdEnvLocalPath = join(process.cwd(), '.env.local');
|
|
21
|
+
const cwdEnvPath = join(process.cwd(), '.env');
|
|
22
|
+
|
|
23
|
+
if (existsSync(envLocalPath)) {
|
|
24
|
+
dotenv.config({ path: envLocalPath });
|
|
25
|
+
} else if (existsSync(envPath)) {
|
|
26
|
+
dotenv.config({ path: envPath });
|
|
27
|
+
} else if (existsSync(cwdEnvLocalPath)) {
|
|
28
|
+
dotenv.config({ path: cwdEnvLocalPath });
|
|
29
|
+
} else if (existsSync(cwdEnvPath)) {
|
|
30
|
+
dotenv.config({ path: cwdEnvPath });
|
|
31
|
+
} else {
|
|
32
|
+
dotenv.config();
|
|
33
|
+
}
|
|
34
|
+
} catch (e) {
|
|
35
|
+
// dotenv not available, continue without it (will use environment variables)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
12
38
|
|
|
13
39
|
// Resolve project root and service path
|
|
14
40
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -18,10 +44,39 @@ const projectRoot = resolve(skillDir, '../..');
|
|
|
18
44
|
|
|
19
45
|
// Try to find services directory
|
|
20
46
|
function findServicesPath() {
|
|
47
|
+
// Get npm global prefix to find globally installed packages
|
|
48
|
+
let globalPrefix = null;
|
|
49
|
+
try {
|
|
50
|
+
globalPrefix = execSync('npm config get prefix', { encoding: 'utf-8' }).trim();
|
|
51
|
+
} catch (e) {
|
|
52
|
+
// Ignore error, try other methods
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Try to resolve package location using createRequire (works in ES modules)
|
|
56
|
+
let packageRoot = null;
|
|
57
|
+
try {
|
|
58
|
+
const require = createRequire(import.meta.url);
|
|
59
|
+
const packageJsonPath = require.resolve('@justin_666/square-couplets-master-skills/package.json');
|
|
60
|
+
packageRoot = dirname(packageJsonPath);
|
|
61
|
+
} catch (e) {
|
|
62
|
+
// Package not found via require.resolve, will try other paths
|
|
63
|
+
}
|
|
64
|
+
|
|
21
65
|
const possiblePaths = [
|
|
66
|
+
// Global npm package (highest priority - most reliable for installed packages)
|
|
67
|
+
...(globalPrefix ? [
|
|
68
|
+
join(globalPrefix, 'lib', 'node_modules', '@justin_666', 'square-couplets-master-skills', 'services'),
|
|
69
|
+
join(globalPrefix, 'node_modules', '@justin_666', 'square-couplets-master-skills', 'services'),
|
|
70
|
+
] : []),
|
|
71
|
+
// From resolved package root (if it has services)
|
|
72
|
+
...(packageRoot ? [join(packageRoot, 'services')] : []),
|
|
73
|
+
// Local project root
|
|
22
74
|
join(projectRoot, 'services'),
|
|
75
|
+
// Local node_modules
|
|
23
76
|
join(projectRoot, 'node_modules', '@justin_666', 'square-couplets-master-skills', 'services'),
|
|
77
|
+
// Current working directory
|
|
24
78
|
join(process.cwd(), 'services'),
|
|
79
|
+
// Current working directory node_modules
|
|
25
80
|
join(process.cwd(), 'node_modules', '@justin_666', 'square-couplets-master-skills', 'services'),
|
|
26
81
|
];
|
|
27
82
|
|
|
@@ -40,13 +95,19 @@ function findServicesPath() {
|
|
|
40
95
|
// Load environment variables
|
|
41
96
|
const envLocalPath = join(projectRoot, '.env.local');
|
|
42
97
|
const envPath = join(projectRoot, '.env');
|
|
98
|
+
const cwdEnvLocalPath = join(process.cwd(), '.env.local');
|
|
99
|
+
const cwdEnvPath = join(process.cwd(), '.env');
|
|
43
100
|
|
|
44
101
|
if (existsSync(envLocalPath)) {
|
|
45
|
-
|
|
102
|
+
dotenvConfig({ path: envLocalPath });
|
|
46
103
|
} else if (existsSync(envPath)) {
|
|
47
|
-
|
|
104
|
+
dotenvConfig({ path: envPath });
|
|
105
|
+
} else if (existsSync(cwdEnvLocalPath)) {
|
|
106
|
+
dotenvConfig({ path: cwdEnvLocalPath });
|
|
107
|
+
} else if (existsSync(cwdEnvPath)) {
|
|
108
|
+
dotenvConfig({ path: cwdEnvPath });
|
|
48
109
|
} else {
|
|
49
|
-
|
|
110
|
+
dotenvConfig();
|
|
50
111
|
}
|
|
51
112
|
|
|
52
113
|
async function main() {
|
|
@@ -106,3 +106,11 @@ When user provides a keyword or wish phrase, generate a professional Doufang art
|
|
|
106
106
|
- User already has a complete prompt
|
|
107
107
|
- User wants to modify an existing prompt (use `optimize-doufang-prompt` instead)
|
|
108
108
|
- User wants to generate the actual image (use `generate-doufang-image` instead)
|
|
109
|
+
|
|
110
|
+
## Implementation Notes
|
|
111
|
+
|
|
112
|
+
- **CRITICAL: Use CLI Command Directly**
|
|
113
|
+
- Execute: `doufang-prompt <keyword> [reference-image]`
|
|
114
|
+
- **DO NOT create temporary .js, .ts, or any script files**
|
|
115
|
+
- **DO NOT write code** - just execute the CLI command directly
|
|
116
|
+
- The CLI command handles all API calls and returns JSON output automatically
|
|
@@ -8,7 +8,33 @@
|
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
9
|
import { dirname, join, resolve } from 'path';
|
|
10
10
|
import { readFileSync, existsSync, statSync } from 'fs';
|
|
11
|
-
import {
|
|
11
|
+
import { execSync } from 'child_process';
|
|
12
|
+
import { createRequire } from 'module';
|
|
13
|
+
|
|
14
|
+
// Load environment variables helper
|
|
15
|
+
async function loadEnvironmentVariables() {
|
|
16
|
+
try {
|
|
17
|
+
const dotenv = await import('dotenv');
|
|
18
|
+
const envLocalPath = join(projectRoot, '.env.local');
|
|
19
|
+
const envPath = join(projectRoot, '.env');
|
|
20
|
+
const cwdEnvLocalPath = join(process.cwd(), '.env.local');
|
|
21
|
+
const cwdEnvPath = join(process.cwd(), '.env');
|
|
22
|
+
|
|
23
|
+
if (existsSync(envLocalPath)) {
|
|
24
|
+
dotenv.config({ path: envLocalPath });
|
|
25
|
+
} else if (existsSync(envPath)) {
|
|
26
|
+
dotenv.config({ path: envPath });
|
|
27
|
+
} else if (existsSync(cwdEnvLocalPath)) {
|
|
28
|
+
dotenv.config({ path: cwdEnvLocalPath });
|
|
29
|
+
} else if (existsSync(cwdEnvPath)) {
|
|
30
|
+
dotenv.config({ path: cwdEnvPath });
|
|
31
|
+
} else {
|
|
32
|
+
dotenv.config();
|
|
33
|
+
}
|
|
34
|
+
} catch (e) {
|
|
35
|
+
// dotenv not available, continue without it (will use environment variables)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
12
38
|
|
|
13
39
|
// Resolve project root and service path
|
|
14
40
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -18,40 +44,76 @@ const projectRoot = resolve(skillDir, '../..');
|
|
|
18
44
|
|
|
19
45
|
// Try to find services directory
|
|
20
46
|
function findServicesPath() {
|
|
47
|
+
// Get npm global prefix to find globally installed packages
|
|
48
|
+
let globalPrefix = null;
|
|
49
|
+
try {
|
|
50
|
+
globalPrefix = execSync('npm config get prefix', { encoding: 'utf-8' }).trim();
|
|
51
|
+
} catch (e) {
|
|
52
|
+
// Ignore error, try other methods
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Try to resolve package location using createRequire (works in ES modules)
|
|
56
|
+
let packageRoot = null;
|
|
57
|
+
try {
|
|
58
|
+
const require = createRequire(import.meta.url);
|
|
59
|
+
const packageJsonPath = require.resolve('@justin_666/square-couplets-master-skills/package.json');
|
|
60
|
+
packageRoot = dirname(packageJsonPath);
|
|
61
|
+
} catch (e) {
|
|
62
|
+
// Package not found via require.resolve, will try other paths
|
|
63
|
+
}
|
|
64
|
+
|
|
21
65
|
const possiblePaths = [
|
|
66
|
+
// Global npm package (highest priority - most reliable for installed packages)
|
|
67
|
+
...(globalPrefix ? [
|
|
68
|
+
join(globalPrefix, 'lib', 'node_modules', '@justin_666', 'square-couplets-master-skills', 'services'),
|
|
69
|
+
join(globalPrefix, 'node_modules', '@justin_666', 'square-couplets-master-skills', 'services'),
|
|
70
|
+
] : []),
|
|
71
|
+
// From resolved package root (if it has services)
|
|
72
|
+
...(packageRoot ? [join(packageRoot, 'services')] : []),
|
|
73
|
+
// Local project root
|
|
22
74
|
join(projectRoot, 'services'),
|
|
75
|
+
// Local node_modules
|
|
23
76
|
join(projectRoot, 'node_modules', '@justin_666', 'square-couplets-master-skills', 'services'),
|
|
77
|
+
// Current working directory
|
|
24
78
|
join(process.cwd(), 'services'),
|
|
79
|
+
// Current working directory node_modules
|
|
25
80
|
join(process.cwd(), 'node_modules', '@justin_666', 'square-couplets-master-skills', 'services'),
|
|
26
81
|
];
|
|
27
82
|
|
|
83
|
+
// Debug: log all paths being checked (only in development)
|
|
84
|
+
if (process.env.DEBUG_DOUFANG) {
|
|
85
|
+
console.log('🔍 Checking paths for services directory:');
|
|
86
|
+
for (const path of possiblePaths) {
|
|
87
|
+
console.log(` - ${path} ${existsSync(path) ? '✅' : '❌'}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
28
91
|
for (const path of possiblePaths) {
|
|
29
92
|
try {
|
|
30
93
|
if (statSync(path).isDirectory()) {
|
|
94
|
+
if (process.env.DEBUG_DOUFANG) {
|
|
95
|
+
console.log(`✅ Found services at: ${path}`);
|
|
96
|
+
}
|
|
31
97
|
return path;
|
|
32
98
|
}
|
|
33
99
|
} catch (e) {
|
|
34
100
|
// Path doesn't exist, try next
|
|
35
101
|
}
|
|
36
102
|
}
|
|
103
|
+
|
|
104
|
+
// If not found, provide helpful error message
|
|
105
|
+
if (process.env.DEBUG_DOUFANG) {
|
|
106
|
+
console.log('❌ Services directory not found in any of the checked paths');
|
|
107
|
+
}
|
|
37
108
|
return null;
|
|
38
109
|
}
|
|
39
110
|
|
|
40
|
-
// Load environment variables
|
|
41
|
-
const envLocalPath = join(projectRoot, '.env.local');
|
|
42
|
-
const envPath = join(projectRoot, '.env');
|
|
43
|
-
|
|
44
|
-
if (existsSync(envLocalPath)) {
|
|
45
|
-
config({ path: envLocalPath });
|
|
46
|
-
} else if (existsSync(envPath)) {
|
|
47
|
-
config({ path: envPath });
|
|
48
|
-
} else {
|
|
49
|
-
// Try current working directory
|
|
50
|
-
config();
|
|
51
|
-
}
|
|
52
111
|
|
|
53
112
|
async function main() {
|
|
54
113
|
try {
|
|
114
|
+
// Load environment variables first
|
|
115
|
+
await loadEnvironmentVariables();
|
|
116
|
+
|
|
55
117
|
// Parse command line arguments
|
|
56
118
|
const args = process.argv.slice(2);
|
|
57
119
|
const keyword = args[0];
|
|
@@ -87,16 +149,28 @@ async function main() {
|
|
|
87
149
|
// Dynamic import of service (support both .ts and .js)
|
|
88
150
|
let serviceModule;
|
|
89
151
|
try {
|
|
90
|
-
// Try .js first (for npm package)
|
|
152
|
+
// Try .js first (for compiled npm package)
|
|
91
153
|
serviceModule = await import(`file://${join(servicesPath, 'geminiService.js')}`);
|
|
92
154
|
} catch (e) {
|
|
93
155
|
try {
|
|
94
|
-
// Try .ts (for development)
|
|
95
|
-
|
|
156
|
+
// Try .ts (for development or source packages)
|
|
157
|
+
// Node.js cannot directly import .ts files
|
|
158
|
+
console.error('❌ Error: Cannot import TypeScript service module');
|
|
159
|
+
console.error(' The package contains TypeScript source files (.ts) which cannot be directly executed');
|
|
160
|
+
console.error('');
|
|
161
|
+
console.error('💡 Solution: Use the CLI command instead (recommended):');
|
|
162
|
+
console.error(` doufang-prompt "${keyword}"${referenceImagePath ? ` ${referenceImagePath}` : ''}`);
|
|
163
|
+
console.error('');
|
|
164
|
+
console.error(' Or if you need to use the script directly:');
|
|
165
|
+
console.error(' 1. Install tsx: npm install -g tsx');
|
|
166
|
+
console.error(` 2. Run: tsx skills/generate-doufang-prompt/index.js "${keyword}"${referenceImagePath ? ` ${referenceImagePath}` : ''}`);
|
|
167
|
+
process.exit(1);
|
|
96
168
|
} catch (e2) {
|
|
97
169
|
console.error('❌ Error: Cannot import service module');
|
|
98
170
|
console.error(' Tried:', join(servicesPath, 'geminiService.js'));
|
|
99
171
|
console.error(' Tried:', join(servicesPath, 'geminiService.ts'));
|
|
172
|
+
console.error(' 💡 Solution: Use the CLI command instead:');
|
|
173
|
+
console.error(` doufang-prompt "${keyword}"${referenceImagePath ? ` ${referenceImagePath}` : ''}`);
|
|
100
174
|
process.exit(1);
|
|
101
175
|
}
|
|
102
176
|
}
|
|
@@ -152,3 +152,11 @@ This skill works best when:
|
|
|
152
152
|
## Output Format
|
|
153
153
|
|
|
154
154
|
Return the optimized prompt as a string, maintaining all other aspects of the original prompt while only modifying the composition and margin-related instructions.
|
|
155
|
+
|
|
156
|
+
## Implementation Notes
|
|
157
|
+
|
|
158
|
+
- **CRITICAL: Use CLI Command Directly**
|
|
159
|
+
- Execute: `doufang-optimize <prompt>`
|
|
160
|
+
- **DO NOT create temporary .js, .ts, or any script files**
|
|
161
|
+
- **DO NOT write code** - just execute the CLI command directly
|
|
162
|
+
- The CLI command handles prompt optimization and returns the optimized prompt automatically
|