openads-ai 0.2.2 → 0.2.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/README.md +20 -1
- package/dist/cli.js +37 -1
- package/dist/schedule.js +7 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -188,6 +188,19 @@ openads schedule remove # Remove a schedule
|
|
|
188
188
|
|
|
189
189
|
Uses your OS scheduler (macOS `launchd` / Linux `crontab`) — works even when your terminal is closed.
|
|
190
190
|
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 🛡️ Dual-Mode Safety (Audit vs. Launch)
|
|
194
|
+
|
|
195
|
+
To align with our **Radical Simplicity & Safety by Default** principles, OpenAds operates in two visual modes to give you total control and peace of mind over your ad accounts:
|
|
196
|
+
|
|
197
|
+
* **Audit Mode (Safe / Read-only — Recommended)**: Strict read-only guidelines. The AI can pull live campaign statistics, analyze keywords, find budget waste, and recommend landing page optimizations, but is entirely blocked from making active changes.
|
|
198
|
+
* **Launch Mode (Read-Write)**: Active campaign changes. Authorizes write modifications (e.g. pausing campaigns, scaling bids, altering budgets, or testing ad creative) but strictly mandates a clear visual preview card and an explicit **confirmation prompt (Y/N)** before executing.
|
|
199
|
+
|
|
200
|
+
Configure your default mode anytime by running `openads setup`.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
191
204
|
## 🔒 Security & Privacy
|
|
192
205
|
|
|
193
206
|
- **Runs 100% locally.** OpenAds is not a cloud service. Nothing leaves your machine except the API calls you authorize.
|
|
@@ -242,8 +255,14 @@ Read [CONTRIBUTING.md](CONTRIBUTING.md) to get started.
|
|
|
242
255
|
|
|
243
256
|
---
|
|
244
257
|
|
|
258
|
+
## 👥 Core Team
|
|
259
|
+
|
|
260
|
+
* **Luiz Amorim** — Creator & Maintainer ([lamorim.net](https://lamorim.net) | [LinkedIn](https://www.linkedin.com/in/luizamorim/))
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
245
264
|
## License
|
|
246
265
|
|
|
247
266
|
MIT.
|
|
248
267
|
|
|
249
|
-
*Built on [Pi](https://github.com/earendil-works/pi) (MIT). Includes tools derived from [adloop](https://github.com/kLOsk/adloop) (MIT) by kLOsk. Marketing skills inspired by [marketingskills](https://github.com/coreyhaines31/marketingskills) (MIT) by Corey Haines. Memory and background automation concepts inspired by [Hermes Agent](https://github.com/NousResearch/hermes-agent) by Nous Research.*
|
|
268
|
+
*Built on [Pi](https://github.com/earendil-works/pi) (MIT). Includes tools derived from [adloop](https://github.com/kLOsk/adloop) (MIT) by kLOsk. Marketing skills inspired by [marketingskills](https://github.com/coreyhaines31/marketingskills) (MIT) by Corey Haines. Memory and background automation concepts inspired by [Hermes Agent](https://github.com/NousResearch/hermes-agent) by Nous Research. Token optimization proxy concepts inspired by [RTK](https://github.com/rtk-ai/rtk) by rtk-ai.*
|
package/dist/cli.js
CHANGED
|
@@ -325,7 +325,9 @@ async function main() {
|
|
|
325
325
|
// ─── Build Pi Arguments ─────────────────────────────────────────
|
|
326
326
|
const piArgsRaw = [];
|
|
327
327
|
// Model flag
|
|
328
|
-
|
|
328
|
+
const isLocal = !!config.localBaseUrl;
|
|
329
|
+
const modelIdForPi = isLocal && cleanProvider.includes('/') ? cleanProvider.split('/')[1] : cleanProvider;
|
|
330
|
+
piArgsRaw.push('--model', modelIdForPi);
|
|
329
331
|
// Skills directories
|
|
330
332
|
const skillsDir = path.join(pkgDir, 'skills');
|
|
331
333
|
const templatesDir = path.join(pkgDir, 'templates');
|
|
@@ -350,6 +352,7 @@ async function main() {
|
|
|
350
352
|
}
|
|
351
353
|
if (config.localBaseUrl) {
|
|
352
354
|
env.OPENAI_BASE_URL = config.localBaseUrl;
|
|
355
|
+
env.OPENAI_API_KEY = env.OPENAI_API_KEY || 'sk-local-ai-key-placeholder';
|
|
353
356
|
}
|
|
354
357
|
// ─── White-Label Patch ──────────────────────────────────────────
|
|
355
358
|
const agentDir = path.join(CONFIG_DIR, 'agent');
|
|
@@ -392,6 +395,39 @@ async function main() {
|
|
|
392
395
|
};
|
|
393
396
|
}
|
|
394
397
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
398
|
+
// ─── Write models.json for Local AI ─────────────────────────────
|
|
399
|
+
const modelsPath = path.join(agentDir, 'models.json');
|
|
400
|
+
if (isLocal) {
|
|
401
|
+
const modelsConfig = {
|
|
402
|
+
providers: {
|
|
403
|
+
"local-ai": {
|
|
404
|
+
baseUrl: config.localBaseUrl,
|
|
405
|
+
api: "openai-completions",
|
|
406
|
+
apiKey: "local-key-placeholder",
|
|
407
|
+
compat: {
|
|
408
|
+
supportsDeveloperRole: false,
|
|
409
|
+
supportsReasoningEffort: false
|
|
410
|
+
},
|
|
411
|
+
models: [
|
|
412
|
+
{
|
|
413
|
+
id: modelIdForPi,
|
|
414
|
+
name: `${modelIdForPi} (Local)`
|
|
415
|
+
}
|
|
416
|
+
]
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
fs.writeFileSync(modelsPath, JSON.stringify(modelsConfig, null, 2));
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
// If not local, remove custom models.json to avoid conflicts
|
|
424
|
+
if (fs.existsSync(modelsPath)) {
|
|
425
|
+
try {
|
|
426
|
+
fs.unlinkSync(modelsPath);
|
|
427
|
+
}
|
|
428
|
+
catch (e) { }
|
|
429
|
+
}
|
|
430
|
+
}
|
|
395
431
|
// ─── Launch Agent ───────────────────────────────────────────────
|
|
396
432
|
const piCliPath = path.resolve(pkgDir, 'node_modules', '@earendil-works', 'pi-coding-agent', 'dist', 'cli.js');
|
|
397
433
|
spinner.succeed(chalk.green('Agent ready'));
|
package/dist/schedule.js
CHANGED
|
@@ -243,13 +243,18 @@ export async function runScheduledTask(name) {
|
|
|
243
243
|
else
|
|
244
244
|
env.OPENAI_API_KEY = config.apiKey;
|
|
245
245
|
}
|
|
246
|
-
if (config.localBaseUrl)
|
|
246
|
+
if (config.localBaseUrl) {
|
|
247
247
|
env.OPENAI_BASE_URL = config.localBaseUrl;
|
|
248
|
+
env.OPENAI_API_KEY = env.OPENAI_API_KEY || 'sk-local-ai-key-placeholder';
|
|
249
|
+
}
|
|
248
250
|
const skillsDir = path.resolve(pkgDir, 'skills');
|
|
249
251
|
const contextDir = path.join(CONFIG_DIR, 'context');
|
|
252
|
+
const cleanModel = config.provider;
|
|
253
|
+
const isLocal = !!config.localBaseUrl;
|
|
254
|
+
const modelIdForPi = isLocal && cleanModel.includes('/') ? cleanModel.split('/')[1] : cleanModel;
|
|
250
255
|
const args = [
|
|
251
256
|
piCliPath,
|
|
252
|
-
'--model',
|
|
257
|
+
'--model', modelIdForPi,
|
|
253
258
|
'--skill', skillsDir,
|
|
254
259
|
...(fs.existsSync(contextDir) ? ['--skill', contextDir] : []),
|
|
255
260
|
'--print',
|
package/package.json
CHANGED