natureco-cli 5.18.3 → 5.20.0

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.
Files changed (346) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/package.json +1 -1
  3. package/skills/a-b-testing/SKILL.md +34 -0
  4. package/skills/accessibility-audit/SKILL.md +34 -0
  5. package/skills/agent-memory/SKILL.md +34 -0
  6. package/skills/agent-orchestration/SKILL.md +34 -0
  7. package/skills/airunway-aks-setup/SKILL.md +73 -0
  8. package/skills/algorithmic-art/SKILL.md +405 -0
  9. package/skills/analytics-setup/SKILL.md +34 -0
  10. package/skills/api-design/SKILL.md +34 -0
  11. package/skills/api-versioning/SKILL.md +34 -0
  12. package/skills/appinsights-instrumentation/SKILL.md +76 -0
  13. package/skills/audio-transcription/SKILL.md +34 -0
  14. package/skills/authentication-patterns/SKILL.md +34 -0
  15. package/skills/authorization-rbac/SKILL.md +34 -0
  16. package/skills/azure-ai/SKILL.md +71 -0
  17. package/skills/azure-aigateway/SKILL.md +129 -0
  18. package/skills/azure-cloud-migrate/SKILL.md +52 -0
  19. package/skills/azure-compliance/SKILL.md +108 -0
  20. package/skills/azure-compute/SKILL.md +46 -0
  21. package/skills/azure-cost/SKILL.md +45 -0
  22. package/skills/azure-deploy/SKILL.md +97 -0
  23. package/skills/azure-diagnostics/SKILL.md +151 -0
  24. package/skills/azure-enterprise-infra-planner/SKILL.md +54 -0
  25. package/skills/azure-hosted-copilot-sdk/SKILL.md +89 -0
  26. package/skills/azure-kubernetes/SKILL.md +153 -0
  27. package/skills/azure-kusto/SKILL.md +231 -0
  28. package/skills/azure-messaging/SKILL.md +57 -0
  29. package/skills/azure-prepare/SKILL.md +165 -0
  30. package/skills/azure-quotas/SKILL.md +276 -0
  31. package/skills/azure-rbac/SKILL.md +17 -0
  32. package/skills/azure-reliability/SKILL.md +387 -0
  33. package/skills/azure-resource-lookup/SKILL.md +108 -0
  34. package/skills/azure-resource-visualizer/SKILL.md +183 -0
  35. package/skills/azure-storage/SKILL.md +100 -0
  36. package/skills/azure-upgrade/SKILL.md +91 -0
  37. package/skills/azure-validate/SKILL.md +72 -0
  38. package/skills/backup-strategy/SKILL.md +34 -0
  39. package/skills/bash-scripting/SKILL.md +34 -0
  40. package/skills/batch-api-calls/SKILL.md +34 -0
  41. package/skills/batch-processing/SKILL.md +34 -0
  42. package/skills/brainstorming/SKILL.md +159 -0
  43. package/skills/brand-guidelines/SKILL.md +73 -0
  44. package/skills/brandkit/SKILL.md +798 -0
  45. package/skills/brutalist-skill/SKILL.md +92 -0
  46. package/skills/bulk-file-operations/SKILL.md +34 -0
  47. package/skills/cache-responses/SKILL.md +34 -0
  48. package/skills/caching-strategy/SKILL.md +34 -0
  49. package/skills/calendar-optimization/SKILL.md +34 -0
  50. package/skills/canvas-design/SKILL.md +130 -0
  51. package/skills/cavecrew/SKILL.md +82 -0
  52. package/skills/caveman-commit/SKILL.md +65 -0
  53. package/skills/caveman-help/SKILL.md +63 -0
  54. package/skills/caveman-review/SKILL.md +55 -0
  55. package/skills/caveman-stats/SKILL.md +10 -0
  56. package/skills/changelog-generation/SKILL.md +34 -0
  57. package/skills/chat-bot-design/SKILL.md +34 -0
  58. package/skills/chunking-strategy/SKILL.md +34 -0
  59. package/skills/ci-cd-pipeline/SKILL.md +34 -0
  60. package/skills/classification-pipeline/SKILL.md +34 -0
  61. package/skills/claude-api/SKILL.md +356 -0
  62. package/skills/clipboard-master/SKILL.md +34 -0
  63. package/skills/code-explanation/SKILL.md +34 -0
  64. package/skills/code-generation/SKILL.md +34 -0
  65. package/skills/code-migration/SKILL.md +34 -0
  66. package/skills/code-review-checklist/SKILL.md +34 -0
  67. package/skills/composition-patterns/SKILL.md +89 -0
  68. package/skills/contact-management/SKILL.md +34 -0
  69. package/skills/content-generation/SKILL.md +34 -0
  70. package/skills/context-pruning/SKILL.md +34 -0
  71. package/skills/context-window-management/SKILL.md +34 -0
  72. package/skills/continuous-improvement/SKILL.md +34 -0
  73. package/skills/cron-scheduling/SKILL.md +34 -0
  74. package/skills/cross-platform-compat/SKILL.md +34 -0
  75. package/skills/csv-processing/SKILL.md +34 -0
  76. package/skills/daily-journal/SKILL.md +34 -0
  77. package/skills/data-analysis/SKILL.md +34 -0
  78. package/skills/data-backup/SKILL.md +34 -0
  79. package/skills/data-cleaning/SKILL.md +34 -0
  80. package/skills/data-extraction/SKILL.md +34 -0
  81. package/skills/data-validation/SKILL.md +34 -0
  82. package/skills/database-migrations/SKILL.md +34 -0
  83. package/skills/database-schema-design/SKILL.md +34 -0
  84. package/skills/decision-mapping/SKILL.md +84 -0
  85. package/skills/decision-matrix/SKILL.md +34 -0
  86. package/skills/dependency-management/SKILL.md +34 -0
  87. package/skills/deploy-to-vercel/SKILL.md +296 -0
  88. package/skills/design-an-interface/SKILL.md +94 -0
  89. package/skills/design-doc-mermaid/SKILL.md +498 -0
  90. package/skills/dev-environment-setup/SKILL.md +34 -0
  91. package/skills/develop-userscripts/SKILL.md +84 -0
  92. package/skills/distraction-blocker/SKILL.md +34 -0
  93. package/skills/doc-coauthoring/SKILL.md +375 -0
  94. package/skills/docker-optimization/SKILL.md +34 -0
  95. package/skills/document-template/SKILL.md +34 -0
  96. package/skills/documentation/SKILL.md +109 -0
  97. package/skills/documentation-gen/SKILL.md +34 -0
  98. package/skills/docx/SKILL.md +590 -0
  99. package/skills/edit-article/SKILL.md +15 -0
  100. package/skills/efficient-formatting/SKILL.md +34 -0
  101. package/skills/email-management/SKILL.md +34 -0
  102. package/skills/email-service/SKILL.md +34 -0
  103. package/skills/embedding-generation/SKILL.md +34 -0
  104. package/skills/entity-extraction/SKILL.md +34 -0
  105. package/skills/entra-agent-id/SKILL.md +356 -0
  106. package/skills/entra-app-registration/SKILL.md +191 -0
  107. package/skills/environment-config/SKILL.md +34 -0
  108. package/skills/error-handling/SKILL.md +34 -0
  109. package/skills/estimation-techniques/SKILL.md +34 -0
  110. package/skills/event-driven-architecture/SKILL.md +34 -0
  111. package/skills/excel-automation/SKILL.md +34 -0
  112. package/skills/execution-monitoring/SKILL.md +34 -0
  113. package/skills/expense-tracking/SKILL.md +34 -0
  114. package/skills/faceless-explainer/SKILL.md +202 -0
  115. package/skills/fastify/SKILL.md +75 -0
  116. package/skills/feature-engineering/SKILL.md +34 -0
  117. package/skills/feature-flags/SKILL.md +34 -0
  118. package/skills/file-conversion/SKILL.md +34 -0
  119. package/skills/file-upload-handling/SKILL.md +34 -0
  120. package/skills/fine-tuning-prep/SKILL.md +34 -0
  121. package/skills/focus-mode/SKILL.md +34 -0
  122. package/skills/form-validation/SKILL.md +34 -0
  123. package/skills/function-calling/SKILL.md +34 -0
  124. package/skills/general-video/SKILL.md +143 -0
  125. package/skills/git-guardrails-claude-code/SKILL.md +95 -0
  126. package/skills/git-workflow/SKILL.md +34 -0
  127. package/skills/github-actions-docs/SKILL.md +98 -0
  128. package/skills/goal-setting/SKILL.md +34 -0
  129. package/skills/gpt-tasteskill/SKILL.md +74 -0
  130. package/skills/graphql-design/SKILL.md +34 -0
  131. package/skills/grill-me/SKILL.md +7 -0
  132. package/skills/grilling/SKILL.md +10 -0
  133. package/skills/habit-tracker/SKILL.md +34 -0
  134. package/skills/hallucination-detection/SKILL.md +34 -0
  135. package/skills/handoff/SKILL.md +16 -0
  136. package/skills/hyperframes/SKILL.md +152 -0
  137. package/skills/hyperframes-animation/SKILL.md +82 -0
  138. package/skills/hyperframes-cli/SKILL.md +109 -0
  139. package/skills/hyperframes-core/SKILL.md +78 -0
  140. package/skills/hyperframes-creative/SKILL.md +68 -0
  141. package/skills/hyperframes-media/SKILL.md +97 -0
  142. package/skills/image-processing/SKILL.md +34 -0
  143. package/skills/image-to-code-skill/SKILL.md +1228 -0
  144. package/skills/imagegen-frontend-mobile/SKILL.md +1465 -0
  145. package/skills/imagegen-frontend-web/SKILL.md +987 -0
  146. package/skills/implement/SKILL.md +15 -0
  147. package/skills/init/SKILL.md +91 -0
  148. package/skills/internal-comms/SKILL.md +32 -0
  149. package/skills/json-transformation/SKILL.md +34 -0
  150. package/skills/keyboard-shortcuts/SKILL.md +34 -0
  151. package/skills/knowledge-base/SKILL.md +34 -0
  152. package/skills/knowledge-graph/SKILL.md +34 -0
  153. package/skills/kubernetes-deployment/SKILL.md +34 -0
  154. package/skills/language-translation/SKILL.md +34 -0
  155. package/skills/lark-approval/SKILL.md +56 -0
  156. package/skills/lark-base/SKILL.md +157 -0
  157. package/skills/lark-doc/SKILL.md +81 -0
  158. package/skills/lark-shared/SKILL.md +168 -0
  159. package/skills/lark-workflow-meeting-summary/SKILL.md +122 -0
  160. package/skills/linting-neostandard-eslint9/SKILL.md +64 -0
  161. package/skills/llm-chaining/SKILL.md +34 -0
  162. package/skills/localization-i18n/SKILL.md +34 -0
  163. package/skills/logging-best-practices/SKILL.md +34 -0
  164. package/skills/loop-me/SKILL.md +32 -0
  165. package/skills/machine-learning-pipeline/SKILL.md +34 -0
  166. package/skills/meeting-notes/SKILL.md +34 -0
  167. package/skills/meeting-scheduler/SKILL.md +34 -0
  168. package/skills/message-queues/SKILL.md +34 -0
  169. package/skills/message-summarization/SKILL.md +34 -0
  170. package/skills/microservices-architecture/SKILL.md +34 -0
  171. package/skills/microsoft-foundry/SKILL.md +262 -0
  172. package/skills/migrate-to-shoehorn/SKILL.md +118 -0
  173. package/skills/milestone-tracking/SKILL.md +34 -0
  174. package/skills/minimalist-skill/SKILL.md +85 -0
  175. package/skills/model-deployment/SKILL.md +34 -0
  176. package/skills/model-evaluation/SKILL.md +34 -0
  177. package/skills/monitoring-setup/SKILL.md +34 -0
  178. package/skills/monorepo-setup/SKILL.md +34 -0
  179. package/skills/motion-graphics/SKILL.md +170 -0
  180. package/skills/multi-agent-systems/SKILL.md +34 -0
  181. package/skills/music-to-video/SKILL.md +197 -0
  182. package/skills/network-troubleshooting/SKILL.md +34 -0
  183. package/skills/node/SKILL.md +94 -0
  184. package/skills/nodejs-core/SKILL.md +156 -0
  185. package/skills/note-organization/SKILL.md +34 -0
  186. package/skills/oauth/SKILL.md +186 -0
  187. package/skills/obsidian-vault/SKILL.md +59 -0
  188. package/skills/octocat/SKILL.md +93 -0
  189. package/skills/openclaw-secure-linux-cloud/SKILL.md +157 -0
  190. package/skills/opensource-guide-coach/SKILL.md +218 -0
  191. package/skills/output-skill/SKILL.md +49 -0
  192. package/skills/package-publishing/SKILL.md +34 -0
  193. package/skills/password-generator/SKILL.md +34 -0
  194. package/skills/pdf/SKILL.md +314 -0
  195. package/skills/pdf-processing/SKILL.md +34 -0
  196. package/skills/performance-optimization/SKILL.md +34 -0
  197. package/skills/pomodoro-timer/SKILL.md +34 -0
  198. package/skills/powershell-automation/SKILL.md +34 -0
  199. package/skills/pptx/SKILL.md +232 -0
  200. package/skills/pr-to-video/SKILL.md +235 -0
  201. package/skills/priority-filtering/SKILL.md +34 -0
  202. package/skills/product-launch-video/SKILL.md +205 -0
  203. package/skills/project-tracking/SKILL.md +34 -0
  204. package/skills/prompt-compression/SKILL.md +34 -0
  205. package/skills/prompt-engineering/SKILL.md +34 -0
  206. package/skills/push-notifications/SKILL.md +34 -0
  207. package/skills/python-appservice-deploy/SKILL.md +36 -0
  208. package/skills/qa/SKILL.md +130 -0
  209. package/skills/rag-implementation/SKILL.md +34 -0
  210. package/skills/rate-limiting/SKILL.md +34 -0
  211. package/skills/react-best-practices/SKILL.md +149 -0
  212. package/skills/react-native-skills/SKILL.md +121 -0
  213. package/skills/react-view-transitions/SKILL.md +320 -0
  214. package/skills/readme-i18n/SKILL.md +176 -0
  215. package/skills/real-time-communication/SKILL.md +34 -0
  216. package/skills/redesign-skill/SKILL.md +178 -0
  217. package/skills/refactoring-strategy/SKILL.md +34 -0
  218. package/skills/regex-mastery/SKILL.md +34 -0
  219. package/skills/remotion/SKILL.md +364 -0
  220. package/skills/report-generation/SKILL.md +34 -0
  221. package/skills/request-refactor-plan/SKILL.md +68 -0
  222. package/skills/research-compiler/SKILL.md +34 -0
  223. package/skills/resolving-merge-conflicts/SKILL.md +14 -0
  224. package/skills/responsive-design/SKILL.md +34 -0
  225. package/skills/rest-api-patterns/SKILL.md +34 -0
  226. package/skills/retrospectives/SKILL.md +34 -0
  227. package/skills/risk-assessment/SKILL.md +34 -0
  228. package/skills/roadmap-creation/SKILL.md +34 -0
  229. package/skills/running-claude-code-via-litellm-copilot/SKILL.md +263 -0
  230. package/skills/scaffold-exercises/SKILL.md +106 -0
  231. package/skills/search-implementation/SKILL.md +34 -0
  232. package/skills/secrets-management/SKILL.md +34 -0
  233. package/skills/secure-linux-web-hosting/SKILL.md +162 -0
  234. package/skills/security-audit/SKILL.md +34 -0
  235. package/skills/selective-memory/SKILL.md +34 -0
  236. package/skills/semantic-search/SKILL.md +34 -0
  237. package/skills/semantic-versioning/SKILL.md +34 -0
  238. package/skills/sentiment-analysis/SKILL.md +34 -0
  239. package/skills/seo-optimization/SKILL.md +34 -0
  240. package/skills/setup-pre-commit/SKILL.md +91 -0
  241. package/skills/shadcn/SKILL.md +267 -0
  242. package/skills/simple/SKILL.md +52 -0
  243. package/skills/skill-creator/SKILL.md +485 -0
  244. package/skills/skill-optimizer/SKILL.md +47 -0
  245. package/skills/skills-cli/SKILL.md +281 -0
  246. package/skills/slack-gif-creator/SKILL.md +254 -0
  247. package/skills/snipgrapher/SKILL.md +58 -0
  248. package/skills/snippet-manager/SKILL.md +34 -0
  249. package/skills/soft-skill/SKILL.md +98 -0
  250. package/skills/sprint-planning/SKILL.md +34 -0
  251. package/skills/sql-query-optimization/SKILL.md +34 -0
  252. package/skills/stakeholder-communication/SKILL.md +34 -0
  253. package/skills/state-management/SKILL.md +34 -0
  254. package/skills/statistical-analysis/SKILL.md +34 -0
  255. package/skills/stitch-skill/SKILL.md +184 -0
  256. package/skills/streaming-responses/SKILL.md +34 -0
  257. package/skills/structured-output/SKILL.md +34 -0
  258. package/skills/summarization-techniques/SKILL.md +34 -0
  259. package/skills/supabase/SKILL.md +135 -0
  260. package/skills/supabase-postgres-best-practices/SKILL.md +64 -0
  261. package/skills/system-diagnostics/SKILL.md +34 -0
  262. package/skills/systematic-debugging/SKILL.md +296 -0
  263. package/skills/talking-head-recut/SKILL.md +1191 -0
  264. package/skills/task-decomposition/SKILL.md +34 -0
  265. package/skills/task-prioritization/SKILL.md +34 -0
  266. package/skills/taste-skill/SKILL.md +1206 -0
  267. package/skills/taste-skill-v1/SKILL.md +226 -0
  268. package/skills/tdd/SKILL.md +108 -0
  269. package/skills/teach/SKILL.md +140 -0
  270. package/skills/template-library/SKILL.md +34 -0
  271. package/skills/test-driven-development/SKILL.md +371 -0
  272. package/skills/test-generation/SKILL.md +34 -0
  273. package/skills/testing-strategy/SKILL.md +34 -0
  274. package/skills/text-expansion/SKILL.md +34 -0
  275. package/skills/theme-factory/SKILL.md +59 -0
  276. package/skills/time-blocking/SKILL.md +34 -0
  277. package/skills/to-prd/SKILL.md +75 -0
  278. package/skills/token-budgeting/SKILL.md +34 -0
  279. package/skills/token-optimization/SKILL.md +34 -0
  280. package/skills/tool-calling-patterns/SKILL.md +34 -0
  281. package/skills/typescript-magician/SKILL.md +117 -0
  282. package/skills/tzst/SKILL.md +68 -0
  283. package/skills/ubiquitous-language/SKILL.md +93 -0
  284. package/skills/use-my-browser/SKILL.md +110 -0
  285. package/skills/using-superpowers/SKILL.md +121 -0
  286. package/skills/vector-database-setup/SKILL.md +34 -0
  287. package/skills/vercel-cli-with-tokens/SKILL.md +353 -0
  288. package/skills/vercel-optimize/SKILL.md +322 -0
  289. package/skills/video-editing/SKILL.md +34 -0
  290. package/skills/viral-instagram-reels/SKILL.md +180 -0
  291. package/skills/viral-short-form/SKILL.md +147 -0
  292. package/skills/viral-short-form-ideas/SKILL.md +184 -0
  293. package/skills/viral-tiktok-content/SKILL.md +180 -0
  294. package/skills/visualization-creation/SKILL.md +34 -0
  295. package/skills/web-artifacts-builder/SKILL.md +74 -0
  296. package/skills/web-design-guidelines/SKILL.md +39 -0
  297. package/skills/web-scraping/SKILL.md +34 -0
  298. package/skills/webapp-testing/SKILL.md +96 -0
  299. package/skills/webhook-handling/SKILL.md +34 -0
  300. package/skills/website-to-video/SKILL.md +145 -0
  301. package/skills/weekly-review/SKILL.md +34 -0
  302. package/skills/workflow-automation/SKILL.md +34 -0
  303. package/skills/writing-beats/SKILL.md +67 -0
  304. package/skills/writing-fragments/SKILL.md +79 -0
  305. package/skills/writing-great-skills/SKILL.md +82 -0
  306. package/skills/writing-guidelines/SKILL.md +39 -0
  307. package/skills/writing-plans/SKILL.md +174 -0
  308. package/skills/writing-shape/SKILL.md +79 -0
  309. package/skills/xdrop/SKILL.md +78 -0
  310. package/skills/xget/SKILL.md +87 -0
  311. package/skills/xlsx/SKILL.md +292 -0
  312. package/src/commands/code_v5.js +377 -73
  313. package/src/commands/repl.js +505 -86
  314. package/src/providers/model/anthropic.js +84 -0
  315. package/src/providers/model/gemini.js +49 -0
  316. package/src/providers/model/minimax.js +48 -0
  317. package/src/providers/model/ollama.js +42 -0
  318. package/src/providers/model/openai.js +49 -0
  319. package/src/providers/search/duckduckgo.js +45 -0
  320. package/src/providers/search/exa.js +52 -0
  321. package/src/providers/search/searxng.js +51 -0
  322. package/src/providers/search/tavily.js +47 -0
  323. package/src/tools/model_provider.js +71 -0
  324. package/src/tools/parallel_search.js +40 -49
  325. package/src/tools/search_provider.js +79 -0
  326. package/src/tools/skills_download.js +217 -0
  327. package/src/tools/web_search.js +42 -62
  328. package/src/tools/workflow.js +21 -9
  329. package/src/utils/cron.js +82 -126
  330. package/src/utils/effort-levels.js +42 -0
  331. package/src/utils/fallback-chain.js +72 -0
  332. package/src/utils/file-history.js +78 -0
  333. package/src/utils/model-provider.js +113 -0
  334. package/src/utils/permissions.js +147 -0
  335. package/src/utils/plan-mode.js +164 -0
  336. package/src/utils/provider-detect.js +7 -32
  337. package/src/utils/sandbox.js +60 -0
  338. package/src/utils/search-provider.js +62 -0
  339. package/src/utils/session-search.js +66 -0
  340. package/src/utils/structured-output.js +20 -0
  341. package/src/utils/system-prompt.js +28 -2
  342. package/src/utils/tasks.js +132 -0
  343. package/src/utils/tool-hooks.js +154 -0
  344. package/src/utils/tools.js +18 -2
  345. package/src/utils/ultra-review.js +59 -0
  346. package/src/utils/worktree.js +192 -0
package/src/utils/cron.js CHANGED
@@ -1,126 +1,82 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const os = require('os');
4
- const cron = require('node-cron');
5
-
6
- const CRON_FILE = path.join(os.homedir(), '.natureco', 'cron.json');
7
- const CRON_LOGS_DIR = path.join(os.homedir(), '.natureco', 'cron-logs');
8
-
9
- function ensureCronDirs() {
10
- const dir = path.dirname(CRON_FILE);
11
- if (!fs.existsSync(dir)) {
12
- fs.mkdirSync(dir, { recursive: true });
13
- }
14
- if (!fs.existsSync(CRON_LOGS_DIR)) {
15
- fs.mkdirSync(CRON_LOGS_DIR, { recursive: true });
16
- }
17
- }
18
-
19
- function loadCronJobs() {
20
- ensureCronDirs();
21
- if (!fs.existsSync(CRON_FILE)) {
22
- return [];
23
- }
24
- try {
25
- const data = fs.readFileSync(CRON_FILE, 'utf-8');
26
- return JSON.parse(data);
27
- } catch {
28
- return [];
29
- }
30
- }
31
-
32
- function saveCronJobs(jobs) {
33
- ensureCronDirs();
34
- fs.writeFileSync(CRON_FILE, JSON.stringify(jobs, null, 2), 'utf-8');
35
- }
36
-
37
- function addCronJob(job) {
38
- const jobs = loadCronJobs();
39
- const id = Date.now().toString(36) + Math.random().toString(36).slice(2);
40
- const newJob = {
41
- id,
42
- ...job,
43
- enabled: true,
44
- createdAt: new Date().toISOString(),
45
- };
46
- jobs.push(newJob);
47
- saveCronJobs(jobs);
48
- return newJob;
49
- }
50
-
51
- function removeCronJob(id) {
52
- const jobs = loadCronJobs();
53
- const filtered = jobs.filter(j => j.id !== id);
54
- saveCronJobs(filtered);
55
- return filtered.length < jobs.length;
56
- }
57
-
58
- function updateCronJob(id, updates) {
59
- const jobs = loadCronJobs();
60
- const index = jobs.findIndex(j => j.id === id);
61
- if (index === -1) return false;
62
- jobs[index] = { ...jobs[index], ...updates };
63
- saveCronJobs(jobs);
64
- return true;
65
- }
66
-
67
- function getCronJob(id) {
68
- const jobs = loadCronJobs();
69
- return jobs.find(j => j.id === id);
70
- }
71
-
72
- function parseCronSchedule(schedule) {
73
- // Basit zamanlama formatlarını cron expression'a çevir
74
- if (schedule.startsWith('every ')) {
75
- const parts = schedule.split(' ');
76
- if (parts[2] === 'hours') {
77
- const hours = parseInt(parts[1]);
78
- return `0 */${hours} * * *`;
79
- }
80
- if (parts[2] === 'minutes') {
81
- const minutes = parseInt(parts[1]);
82
- return `*/${minutes} * * * *`;
83
- }
84
- }
85
-
86
- if (schedule.startsWith('daily at ')) {
87
- const time = schedule.replace('daily at ', '');
88
- const [hour, minute = '0'] = time.split(':');
89
- return `${minute} ${hour} * * *`;
90
- }
91
-
92
- // Zaten cron expression ise olduğu gibi döndür
93
- return schedule;
94
- }
95
-
96
- function validateCronExpression(expression) {
97
- return cron.validate(expression);
98
- }
99
-
100
- function logCronOutput(jobId, output) {
101
- const logFile = path.join(CRON_LOGS_DIR, `${jobId}.log`);
102
- const timestamp = new Date().toISOString();
103
- const logEntry = `[${timestamp}]\n${output}\n\n`;
104
- fs.appendFileSync(logFile, logEntry, 'utf-8');
105
- }
106
-
107
- function getCronLog(jobId) {
108
- const logFile = path.join(CRON_LOGS_DIR, `${jobId}.log`);
109
- if (!fs.existsSync(logFile)) {
110
- return null;
111
- }
112
- return fs.readFileSync(logFile, 'utf-8');
113
- }
114
-
115
- module.exports = {
116
- loadCronJobs,
117
- saveCronJobs,
118
- addCronJob,
119
- removeCronJob,
120
- updateCronJob,
121
- getCronJob,
122
- parseCronSchedule,
123
- validateCronExpression,
124
- logCronOutput,
125
- getCronLog,
126
- };
1
+ /**
2
+ * cron — Scheduled task monitoring (cron-like expressions)
3
+ *
4
+ * Format (standard cron): min hour dom mon dow
5
+ * e.g., "every 5 min" -> minute field = "star/5"
6
+ * Checks if a task should run based on its schedule.
7
+ */
8
+
9
+ const path = require('path');
10
+ const os = require('os');
11
+ const fs = require('fs');
12
+
13
+ const CRON_FILE = path.join(os.homedir(), '.natureco', 'cron-jobs.json');
14
+
15
+ function parseCron(expr) {
16
+ const parts = expr.trim().split(/\s+/);
17
+ if (parts.length !== 5) return null;
18
+ const [min, hour, dom, mon, dow] = parts;
19
+ return { min, hour, dom, mon, dow };
20
+ }
21
+
22
+ function matchesField(value, pattern) {
23
+ if (pattern === '*') return true;
24
+ if (pattern.startsWith('*/')) {
25
+ const step = parseInt(pattern.slice(2), 10);
26
+ return value % step === 0;
27
+ }
28
+ if (pattern.includes(',')) return pattern.split(',').some(p => matchesField(value, p));
29
+ if (pattern.includes('-')) {
30
+ const [lo, hi] = pattern.split('-').map(Number);
31
+ return value >= lo && value <= hi;
32
+ }
33
+ return parseInt(pattern, 10) === value;
34
+ }
35
+
36
+ function shouldRun(expr) {
37
+ const parsed = parseCron(expr);
38
+ if (!parsed) return false;
39
+ const now = new Date();
40
+ return (
41
+ matchesField(now.getMinutes(), parsed.min) &&
42
+ matchesField(now.getHours(), parsed.hour) &&
43
+ matchesField(now.getDate(), parsed.dom) &&
44
+ matchesField(now.getMonth() + 1, parsed.mon) &&
45
+ matchesField(now.getDay(), parsed.dow)
46
+ );
47
+ }
48
+
49
+ function loadJobs() {
50
+ try {
51
+ if (fs.existsSync(CRON_FILE)) return JSON.parse(fs.readFileSync(CRON_FILE, 'utf8'));
52
+ } catch {}
53
+ return [];
54
+ }
55
+
56
+ function addJob(job) {
57
+ const jobs = loadJobs();
58
+ const entry = {
59
+ id: `cron_${Date.now()}`,
60
+ schedule: job.schedule,
61
+ command: job.command,
62
+ description: job.description || '',
63
+ createdAt: Date.now(),
64
+ lastRun: null,
65
+ enabled: true,
66
+ };
67
+ jobs.push(entry);
68
+ const dir = path.dirname(CRON_FILE);
69
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
70
+ fs.writeFileSync(CRON_FILE, JSON.stringify(jobs, null, 2));
71
+ return entry;
72
+ }
73
+
74
+ function removeJob(id) {
75
+ const jobs = loadJobs().filter(j => j.id !== id);
76
+ const dir = path.dirname(CRON_FILE);
77
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
78
+ fs.writeFileSync(CRON_FILE, JSON.stringify(jobs, null, 2));
79
+ return true;
80
+ }
81
+
82
+ module.exports = { parseCron, shouldRun, loadJobs, addJob, removeJob };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * effort-levels — Effort level control (Claude Code: low/medium/high)
3
+ *
4
+ * Controls token budget, iteration limits, and tool breadth:
5
+ * low: quick answers, 2 tool iterations, 1024 max_tokens, minimal tools
6
+ * medium: balanced, 5 iterations, 2048 max_tokens, standard tools (default)
7
+ * high: thorough, 12 iterations, 4096 max_tokens, all tools
8
+ */
9
+
10
+ const LEVELS = { low: 'low', medium: 'medium', high: 'high' };
11
+
12
+ const CONFIG = {
13
+ low: {
14
+ maxTokens: 1024,
15
+ maxToolIterations: 2,
16
+ temperature: 0.1,
17
+ toolBreadth: 'minimal',
18
+ },
19
+ medium: {
20
+ maxTokens: 2048,
21
+ maxToolIterations: 5,
22
+ temperature: 0.3,
23
+ toolBreadth: 'standard',
24
+ },
25
+ high: {
26
+ maxTokens: 4096,
27
+ maxToolIterations: 12,
28
+ temperature: 0.5,
29
+ toolBreadth: 'all',
30
+ },
31
+ };
32
+
33
+ function getLevel(cfg = {}) {
34
+ const level = (cfg.effort || cfg.effortLevel || 'medium').toLowerCase();
35
+ return LEVELS[level] || 'medium';
36
+ }
37
+
38
+ function getConfig(level) {
39
+ return CONFIG[level] || CONFIG.medium;
40
+ }
41
+
42
+ module.exports = { LEVELS, CONFIG, getLevel, getConfig };
@@ -0,0 +1,72 @@
1
+ /**
2
+ * fallback-chain — Multi-model fallback chain (3 models max)
3
+ *
4
+ * Config:
5
+ * "models": ["gpt-4", "claude-3", "gemini-pro"]
6
+ * "fallback": {
7
+ * "enabled": true,
8
+ * "onError": true,
9
+ * "onRateLimit": true,
10
+ * "onTimeout": true
11
+ * }
12
+ *
13
+ * Returns which model to use for each turn, rotating through the chain
14
+ * when errors occur.
15
+ */
16
+
17
+ class FallbackChain {
18
+ constructor() {
19
+ this.models = [];
20
+ this.currentIndex = 0;
21
+ this.config = { onError: true, onRateLimit: true, onTimeout: true };
22
+ this.fallbacksUsed = 0;
23
+ this.history = [];
24
+ }
25
+
26
+ configure(models, config = {}) {
27
+ this.models = Array.isArray(models) ? models.filter(Boolean) : [];
28
+ this.currentIndex = 0;
29
+ this.fallbacksUsed = 0;
30
+ this.config = { ...this.config, ...config };
31
+ this.history = [];
32
+ }
33
+
34
+ get current() {
35
+ return this.models[this.currentIndex] || null;
36
+ }
37
+
38
+ get hasFallback() {
39
+ return this.currentIndex < this.models.length - 1;
40
+ }
41
+
42
+ get remaining() {
43
+ return Math.max(0, this.models.length - this.currentIndex - 1);
44
+ }
45
+
46
+ get list() {
47
+ return [...this.models];
48
+ }
49
+
50
+ recordError(model, error) {
51
+ this.history.push({ model, error: error.message || String(error), at: Date.now() });
52
+ if (this.hasFallback) {
53
+ this.currentIndex++;
54
+ this.fallbacksUsed++;
55
+ return { fallback: true, nextModel: this.current, from: model };
56
+ }
57
+ return { fallback: false, nextModel: null, from: model };
58
+ }
59
+
60
+ reset() {
61
+ this.currentIndex = 0;
62
+ this.fallbacksUsed = 0;
63
+ }
64
+ }
65
+
66
+ let _instance = null;
67
+ function getFallbackChain() {
68
+ if (!_instance) _instance = new FallbackChain();
69
+ return _instance;
70
+ }
71
+
72
+ module.exports = { FallbackChain, getFallbackChain };
@@ -0,0 +1,78 @@
1
+ /**
2
+ * file-history — File change history with undo support
3
+ *
4
+ * Snapshots files before edits and stores them in .natureco/history/
5
+ * Supports undo via `file-restore` CLI command.
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const os = require('os');
11
+
12
+ const HISTORY_DIR = path.join(process.cwd(), '.natureco', 'history');
13
+ const MAX_SNAPSHOTS_PER_FILE = 20;
14
+
15
+ function ensureDir() {
16
+ fs.mkdirSync(HISTORY_DIR, { recursive: true });
17
+ }
18
+
19
+ function snapshotKey(filePath) {
20
+ const rel = path.relative(process.cwd(), path.resolve(filePath));
21
+ return rel.replace(/\//g, '__');
22
+ }
23
+
24
+ function getHistory(filePath) {
25
+ const key = snapshotKey(filePath);
26
+ const dir = path.join(HISTORY_DIR, key);
27
+ if (!fs.existsSync(dir)) return [];
28
+ return fs.readdirSync(dir)
29
+ .filter(f => f.endsWith('.snap'))
30
+ .map(f => {
31
+ const ts = parseInt(f.replace('.snap', ''), 10);
32
+ const snapPath = path.join(dir, f);
33
+ return { timestamp: ts, size: fs.statSync(snapPath).size, file: f };
34
+ })
35
+ .sort((a, b) => b.timestamp - a.timestamp);
36
+ }
37
+
38
+ function snapshot(filePath, content) {
39
+ ensureDir();
40
+ const key = snapshotKey(filePath);
41
+ const dir = path.join(HISTORY_DIR, key);
42
+ fs.mkdirSync(dir, { recursive: true });
43
+ fs.writeFileSync(path.join(dir, `${Date.now()}.snap`), content || '');
44
+
45
+ // Prune old snapshots
46
+ const snaps = fs.readdirSync(dir).filter(f => f.endsWith('.snap')).sort();
47
+ while (snaps.length > MAX_SNAPSHOTS_PER_FILE) {
48
+ const old = snaps.shift();
49
+ try { fs.unlinkSync(path.join(dir, old)); } catch {}
50
+ }
51
+ }
52
+
53
+ function restore(filePath, timestamp) {
54
+ const key = snapshotKey(filePath);
55
+ const snapPath = path.join(HISTORY_DIR, key, `${timestamp}.snap`);
56
+ if (!fs.existsSync(snapPath)) return { error: 'Snapshot not found' };
57
+ const content = fs.readFileSync(snapPath, 'utf8');
58
+ fs.writeFileSync(path.resolve(filePath), content);
59
+ return { restored: true, filePath, timestamp, size: content.length };
60
+ }
61
+
62
+ function listAll() {
63
+ if (!fs.existsSync(HISTORY_DIR)) return [];
64
+ const results = [];
65
+ for (const entry of fs.readdirSync(HISTORY_DIR)) {
66
+ const dir = path.join(HISTORY_DIR, entry);
67
+ if (fs.statSync(dir).isDirectory()) {
68
+ const snaps = fs.readdirSync(dir).filter(f => f.endsWith('.snap'));
69
+ if (snaps.length > 0) {
70
+ const filePath = entry.replace(/__/g, '/');
71
+ results.push({ file: filePath, snapshots: snaps.length, latest: Math.max(...snaps.map(s => parseInt(s, 10))) });
72
+ }
73
+ }
74
+ }
75
+ return results;
76
+ }
77
+
78
+ module.exports = { snapshot, restore, getHistory, listAll };
@@ -0,0 +1,113 @@
1
+ const _registry = new Map();
2
+ const _instances = new Map();
3
+
4
+ const PROVIDER_CONFIG_KEY = 'modelProvider';
5
+ const DEFAULT_PROVIDER = 'auto';
6
+
7
+ function registerProvider(name, providerClass) {
8
+ _registry.set(name, providerClass);
9
+ }
10
+
11
+ function getProviderNames() {
12
+ return Array.from(_registry.keys());
13
+ }
14
+
15
+ function getProvider(name) {
16
+ return _registry.get(name) || null;
17
+ }
18
+
19
+ function detectFamily(providerUrl, model) {
20
+ const url = (providerUrl || '').toLowerCase();
21
+ const m = (model || '').toLowerCase();
22
+ if (url.includes('anthropic.com') || m.includes('claude')) return 'anthropic';
23
+ if (url.includes('groq.com') || m.includes('groq') || m.includes('llama-3') || m.includes('mixtral')) return 'groq';
24
+ if (url.includes('openrouter.ai')) return 'openrouter';
25
+ if (url.includes('api.deepseek.com') || m.includes('deepseek')) return 'deepseek';
26
+ if (url.includes('mistral.ai') || m.includes('mistral') || m.includes('codestral')) return 'mistral';
27
+ if (url.includes('together.xyz') || m.includes('together')) return 'together';
28
+ if (url.includes('fireworks.ai') || m.includes('fireworks')) return 'fireworks';
29
+ if (url.includes('perplexity.ai') || m.includes('pplx') || m.includes('sonar')) return 'perplexity';
30
+ if (url.includes('localhost') || url.includes('127.0.0.1') || url.includes('ollama')) return 'ollama';
31
+ if (url.includes('minimax.io') || url.includes('minimax')) return 'minimax';
32
+ if (url.includes('generativelanguage.googleapis.com') || url.includes('gemini')) return 'gemini';
33
+ return 'openai';
34
+ }
35
+
36
+ function getProviderFamily(name) {
37
+ const openaiCompat = ['openai', 'groq', 'openrouter', 'deepseek', 'mistral', 'together', 'fireworks', 'perplexity'];
38
+ if (openaiCompat.includes(name)) return 'openai';
39
+ return name;
40
+ }
41
+
42
+ function resolveProviderConfig(cfg) {
43
+ const env = process.env.NATURECO_MODEL_PROVIDER || '';
44
+ if (env && _registry.has(env)) return env;
45
+ if (cfg && cfg[PROVIDER_CONFIG_KEY] && _registry.has(cfg[PROVIDER_CONFIG_KEY])) {
46
+ return cfg[PROVIDER_CONFIG_KEY];
47
+ }
48
+ const family = detectFamily(cfg?.providerUrl, cfg?.providerModel);
49
+ const resolved = getProviderFamily(family);
50
+ if (_registry.has(resolved)) return resolved;
51
+ return DEFAULT_PROVIDER;
52
+ }
53
+
54
+ function getActiveProvider(cfg) {
55
+ const name = resolveProviderConfig(cfg);
56
+ if (name === 'auto') {
57
+ const family = detectFamily(cfg?.providerUrl, cfg?.providerModel);
58
+ const familyGroup = getProviderFamily(family);
59
+ const Cls = _registry.get(familyGroup);
60
+ if (Cls) return Cls;
61
+ }
62
+ const Cls = _registry.get(name);
63
+ if (!Cls) return getProvider('openai') || null;
64
+ return Cls;
65
+ }
66
+
67
+ const DEFAULT_ANTHROPIC_SYSTEM = 'You are a helpful AI assistant running inside the natureco CLI.';
68
+
69
+ class ModelProvider {
70
+ constructor(config = {}) {
71
+ this.config = config;
72
+ this.name = 'base';
73
+ }
74
+
75
+ getEndpoint() {
76
+ throw new Error('Not implemented: getEndpoint');
77
+ }
78
+
79
+ buildRequest(messages, options = {}) {
80
+ throw new Error('Not implemented: buildRequest');
81
+ }
82
+
83
+ parseResponse(data) {
84
+ throw new Error('Not implemented: parseResponse');
85
+ }
86
+
87
+ normalizeTools(tools) {
88
+ return tools || [];
89
+ }
90
+
91
+ parseToolCalls(message) {
92
+ return message?.tool_calls || [];
93
+ }
94
+
95
+ extractSystem(messages) {
96
+ const systemMsg = messages.find(m => m.role === 'system');
97
+ return systemMsg?.content || '';
98
+ }
99
+ }
100
+
101
+ module.exports = {
102
+ ModelProvider,
103
+ registerProvider,
104
+ getProviderNames,
105
+ getProvider,
106
+ detectFamily,
107
+ getProviderFamily,
108
+ resolveProviderConfig,
109
+ getActiveProvider,
110
+ PROVIDER_CONFIG_KEY,
111
+ DEFAULT_PROVIDER,
112
+ DEFAULT_ANTHROPIC_SYSTEM,
113
+ };
@@ -0,0 +1,147 @@
1
+ /**
2
+ * permissions — Granular tool-level allow/deny rules (Claude Code style)
3
+ *
4
+ * Config format (~/.natureco/config.json or .natureco/config.json):
5
+ * "permissions": {
6
+ * "Read(~/.ssh/**)": { "action": "deny", "reason": "SSH keys are sensitive" },
7
+ * "Read(~/.aws/**)": "deny",
8
+ * "Edit(.env*)": { "action": "ask", "reason": "Review env changes" },
9
+ * "Bash(npm *)": "ask",
10
+ * "Bash(rm *rf *)": "deny"
11
+ * }
12
+ *
13
+ * Resolution order (first match wins):
14
+ * 1. Config permissions (deny > ask > allow)
15
+ * 2. Built-in high-risk patterns (assessRisk in code_v5)
16
+ * 3. Default: allow
17
+ */
18
+
19
+ const fs = require('fs');
20
+ const path = require('path');
21
+ const os = require('os');
22
+
23
+ const { matchGlob, flattenArgs } = require('./tool-hooks');
24
+
25
+ function loadPermissionRules() {
26
+ const rules = [];
27
+ const sources = [
28
+ path.join(os.homedir(), '.natureco', 'config.json'),
29
+ path.join(process.cwd(), '.natureco', 'config.json'),
30
+ ];
31
+ for (const cfgPath of sources) {
32
+ try {
33
+ if (fs.existsSync(cfgPath)) {
34
+ const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));
35
+ if (cfg.permissions) {
36
+ for (const [pattern, value] of Object.entries(cfg.permissions)) {
37
+ const parsed = parsePermissionRule(pattern, value);
38
+ if (parsed) rules.push(parsed);
39
+ }
40
+ }
41
+ }
42
+ } catch {}
43
+ }
44
+ return rules;
45
+ }
46
+
47
+ function parsePermissionRule(pattern, value) {
48
+ const match = pattern.match(/^(\*|[a-zA-Z_]+)\((.+)\)$/);
49
+ if (!match && pattern !== '*') return null;
50
+ const toolName = match ? match[1] : '*';
51
+ const glob = match ? match[2] : '*';
52
+
53
+ let action, reason;
54
+ if (typeof value === 'string') {
55
+ action = value;
56
+ } else if (value && typeof value === 'object') {
57
+ action = value.action || 'ask';
58
+ reason = value.reason;
59
+ }
60
+ if (!['allow', 'deny', 'ask'].includes(action)) action = 'ask';
61
+
62
+ return { toolName, glob, action, reason, raw: pattern };
63
+ }
64
+
65
+ /**
66
+ * Check permissions for a tool call.
67
+ * Returns { action: 'allow'|'deny'|'ask', reason, rule }
68
+ */
69
+ function checkPermission(toolName, args) {
70
+ const rules = loadPermissionRules();
71
+ const flat = flattenArgs(args);
72
+
73
+ for (const rule of rules) {
74
+ if (rule.toolName !== '*' && rule.toolName !== toolName) continue;
75
+ const matchesGlob = rule.glob === '*' || matchGlob(flat, rule.glob) || matchGlob(toolName, rule.glob);
76
+ if (!matchesGlob) continue;
77
+ if (rule.action === 'deny') {
78
+ return { action: 'deny', reason: rule.reason || `Engellendi: ${rule.raw}`, rule };
79
+ }
80
+ if (rule.action === 'ask') {
81
+ return { action: 'ask', reason: rule.reason || `Onay gerekli: ${rule.raw}`, rule };
82
+ }
83
+ if (rule.action === 'allow') {
84
+ return { action: 'allow', reason: '', rule };
85
+ }
86
+ }
87
+
88
+ return { action: 'allow', reason: '', rule: null };
89
+ }
90
+
91
+ /**
92
+ * Persistent permission approvals (session + disk cache).
93
+ */
94
+ const _permSessionCache = new Map();
95
+
96
+ function loadPersistentApprovals() {
97
+ try {
98
+ const f = path.join(os.homedir(), '.natureco', 'perm-approvals.json');
99
+ if (fs.existsSync(f)) return JSON.parse(fs.readFileSync(f, 'utf8'));
100
+ } catch {}
101
+ return {};
102
+ }
103
+
104
+ function savePersistentApproval(key) {
105
+ try {
106
+ const f = path.join(os.homedir(), '.natureco', 'perm-approvals.json');
107
+ const data = loadPersistentApprovals();
108
+ data[key] = { approved: true, at: Date.now() };
109
+ const dir = path.dirname(f);
110
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
111
+ fs.writeFileSync(f, JSON.stringify(data, null, 2), { mode: 0o600 });
112
+ } catch {}
113
+ }
114
+
115
+ function isApproved(key) {
116
+ if (_permSessionCache.get(key) === true) return true;
117
+ const persistent = loadPersistentApprovals();
118
+ if (persistent[key]?.approved) {
119
+ _permSessionCache.set(key, true);
120
+ return true;
121
+ }
122
+ return false;
123
+ }
124
+
125
+ function markApproved(key, persistent = false) {
126
+ _permSessionCache.set(key, true);
127
+ if (persistent) savePersistentApproval(key);
128
+ }
129
+
130
+ /**
131
+ * Format a tool call for permission display.
132
+ */
133
+ function formatPermissionPrompt(toolName, args, reason) {
134
+ const parts = Object.entries(args || {}).map(([k, v]) => {
135
+ const s = typeof v === 'string' ? v : JSON.stringify(v);
136
+ return s.length > 80 ? s.slice(0, 77) + '...' : s;
137
+ });
138
+ return `${toolName}(${parts.join(', ')})`;
139
+ }
140
+
141
+ module.exports = {
142
+ checkPermission,
143
+ loadPermissionRules,
144
+ isApproved,
145
+ markApproved,
146
+ formatPermissionPrompt,
147
+ };