@iservu-inc/adf-cli 0.4.30 → 0.4.32
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/CHANGELOG.md +63 -0
- package/lib/ai/ai-client.js +6 -5
- package/lib/commands/init.js +65 -13
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,69 @@ All notable changes to `@iservu-inc/adf-cli` will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.4.32] - 2025-10-04
|
|
9
|
+
|
|
10
|
+
### ✨ Improved: Smarter .adf Directory Detection
|
|
11
|
+
|
|
12
|
+
**Enhanced: Content-Based Initialization Check**
|
|
13
|
+
- **Problem:** `adf init` prompted to overwrite even when `.adf` only contained `.env` file
|
|
14
|
+
- **Solution:** Now checks for meaningful content before prompting
|
|
15
|
+
|
|
16
|
+
**New Behavior:**
|
|
17
|
+
- `.adf` with only `.env` file → Continues silently ✓
|
|
18
|
+
- `.adf` with session files → Prompts to overwrite ⚠️
|
|
19
|
+
- Empty `.adf` → Creates structure ✓
|
|
20
|
+
|
|
21
|
+
**Implementation:**
|
|
22
|
+
- New `hasMeaningfulContent()` function (init.js:167-204)
|
|
23
|
+
- Checks for sessions/, outputs/, progress files
|
|
24
|
+
- Ignores `.env`, `.gitignore`, hidden files
|
|
25
|
+
- Only prompts when actual work would be lost
|
|
26
|
+
|
|
27
|
+
**User Experience:**
|
|
28
|
+
```
|
|
29
|
+
# Before v0.4.32 (annoying)
|
|
30
|
+
.adf directory already exists. Overwrite? (y/N)
|
|
31
|
+
|
|
32
|
+
# After v0.4.32 (smart)
|
|
33
|
+
✓ Using existing .adf directory
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Confirmed: .gitignore Protection Working**
|
|
37
|
+
- v0.4.30 added automatic root `.gitignore` creation
|
|
38
|
+
- Entry: `.adf/.env` (protects API keys)
|
|
39
|
+
- Created at project root, not in `.adf/`
|
|
40
|
+
- Non-destructive: only adds if missing
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## [0.4.31] - 2025-10-04
|
|
45
|
+
|
|
46
|
+
### 🐛 Fix: OpenAI o-series Model Support (o3, o3-mini, o3-pro)
|
|
47
|
+
|
|
48
|
+
**Fixed: o3 Models Failing with Parameter Error**
|
|
49
|
+
- **Problem:** o3 models failed with `Unsupported parameter: 'max_tokens' is not supported with this model`
|
|
50
|
+
- **Root Cause:** Only checking for `o1` models, not all o-series models (o1, o3, etc.)
|
|
51
|
+
- **Solution:** Updated regex to detect ANY o-series model (`/^o\d/`)
|
|
52
|
+
|
|
53
|
+
**Code Change (ai-client.js:118):**
|
|
54
|
+
```javascript
|
|
55
|
+
// ❌ BEFORE - Only o1 models
|
|
56
|
+
const isO1Model = this.model.startsWith('o1');
|
|
57
|
+
|
|
58
|
+
// ✅ AFTER - All o-series models (o1, o3, o5, etc.)
|
|
59
|
+
const isOSeriesModel = /^o\d/.test(this.model);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Impact:**
|
|
63
|
+
- ✅ o1, o1-mini, o1-preview now work
|
|
64
|
+
- ✅ o3, o3-mini, o3-pro now work
|
|
65
|
+
- ✅ Future o-series models automatically supported
|
|
66
|
+
- Uses `max_completion_tokens` parameter (as required by OpenAI API)
|
|
67
|
+
- Removes `temperature` parameter (not supported by o-series)
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
8
71
|
## [0.4.30] - 2025-10-04
|
|
9
72
|
|
|
10
73
|
### 🔒 Security: Auto .gitignore Protection
|
package/lib/ai/ai-client.js
CHANGED
|
@@ -113,8 +113,9 @@ class AIClient {
|
|
|
113
113
|
* OpenAI GPT request
|
|
114
114
|
*/
|
|
115
115
|
async openaiRequest(prompt, maxTokens, temperature) {
|
|
116
|
-
//
|
|
117
|
-
|
|
116
|
+
// o-series models (o1, o3, etc.) use max_completion_tokens instead of max_tokens
|
|
117
|
+
// Check for any model starting with 'o' followed by a digit
|
|
118
|
+
const isOSeriesModel = /^o\d/.test(this.model);
|
|
118
119
|
|
|
119
120
|
const requestParams = {
|
|
120
121
|
model: this.model,
|
|
@@ -126,10 +127,10 @@ class AIClient {
|
|
|
126
127
|
]
|
|
127
128
|
};
|
|
128
129
|
|
|
129
|
-
//
|
|
130
|
-
if (
|
|
130
|
+
// o-series models use different parameter names
|
|
131
|
+
if (isOSeriesModel) {
|
|
131
132
|
requestParams.max_completion_tokens = maxTokens;
|
|
132
|
-
//
|
|
133
|
+
// o-series models don't support temperature parameter
|
|
133
134
|
} else {
|
|
134
135
|
requestParams.max_tokens = maxTokens;
|
|
135
136
|
requestParams.temperature = temperature;
|
package/lib/commands/init.js
CHANGED
|
@@ -61,23 +61,31 @@ async function init(options) {
|
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
// Check if already initialized
|
|
64
|
+
// Check if already initialized with actual content
|
|
65
65
|
if (await fs.pathExists(adfDir)) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
// Check for meaningful content (not just .env file)
|
|
67
|
+
const hasContent = await hasMeaningfulContent(adfDir);
|
|
68
|
+
|
|
69
|
+
if (hasContent) {
|
|
70
|
+
const { overwrite } = await inquirer.prompt([
|
|
71
|
+
{
|
|
72
|
+
type: 'confirm',
|
|
73
|
+
name: 'overwrite',
|
|
74
|
+
message: chalk.yellow('.adf directory already exists with sessions. Overwrite?'),
|
|
75
|
+
default: false
|
|
76
|
+
}
|
|
77
|
+
]);
|
|
78
|
+
|
|
79
|
+
if (!overwrite) {
|
|
80
|
+
console.log(chalk.yellow('\n✋ Initialization cancelled.\n'));
|
|
81
|
+
return;
|
|
72
82
|
}
|
|
73
|
-
]);
|
|
74
83
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
84
|
+
await fs.remove(adfDir);
|
|
85
|
+
} else {
|
|
86
|
+
// Only .env file exists - safe to continue without prompting
|
|
87
|
+
console.log(chalk.gray('✓ Using existing .adf directory\n'));
|
|
78
88
|
}
|
|
79
|
-
|
|
80
|
-
await fs.remove(adfDir);
|
|
81
89
|
}
|
|
82
90
|
|
|
83
91
|
// Detect project type
|
|
@@ -151,4 +159,48 @@ async function init(options) {
|
|
|
151
159
|
console.log(chalk.green.bold('\n✅ All done! Happy coding! 🚀\n'));
|
|
152
160
|
}
|
|
153
161
|
|
|
162
|
+
/**
|
|
163
|
+
* Check if .adf directory has meaningful content
|
|
164
|
+
* Returns true if there are session files, progress files, or outputs
|
|
165
|
+
* Returns false if only .env or empty
|
|
166
|
+
*/
|
|
167
|
+
async function hasMeaningfulContent(adfDir) {
|
|
168
|
+
try {
|
|
169
|
+
const contents = await fs.readdir(adfDir);
|
|
170
|
+
|
|
171
|
+
// Filter out .env and other config files that don't represent sessions
|
|
172
|
+
const meaningfulFiles = contents.filter(item => {
|
|
173
|
+
return item !== '.env' &&
|
|
174
|
+
item !== '.gitignore' &&
|
|
175
|
+
!item.startsWith('.');
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
if (meaningfulFiles.length === 0) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Check for session directories or files
|
|
183
|
+
for (const item of meaningfulFiles) {
|
|
184
|
+
const itemPath = path.join(adfDir, item);
|
|
185
|
+
const stats = await fs.stat(itemPath);
|
|
186
|
+
|
|
187
|
+
if (stats.isDirectory()) {
|
|
188
|
+
// Check if directory has files (sessions/, outputs/, etc.)
|
|
189
|
+
const dirContents = await fs.readdir(itemPath);
|
|
190
|
+
if (dirContents.length > 0) {
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
} else if (stats.isFile()) {
|
|
194
|
+
// Any non-config file indicates content
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return false;
|
|
200
|
+
} catch (error) {
|
|
201
|
+
// If error reading, assume no content
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
154
206
|
module.exports = init;
|