opalacoder 0.2.0__tar.gz → 0.2.3__tar.gz

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 (163) hide show
  1. opalacoder-0.2.3/AppIcons/icon.png +0 -0
  2. opalacoder-0.2.3/AppIcons/opalaicon.png +0 -0
  3. {opalacoder-0.2.0 → opalacoder-0.2.3}/PKG-INFO +1 -1
  4. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/specs/07-configuracao.md +217 -1
  5. {opalacoder-0.2.0 → opalacoder-0.2.3}/gui_src/src/App.jsx +111 -3
  6. {opalacoder-0.2.0 → opalacoder-0.2.3}/gui_src/src/index.css +5 -0
  7. opalacoder-0.2.3/icon.png +0 -0
  8. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/agent_stdin.py +16 -2
  9. opalacoder-0.2.3/opalacoder/assetstore/modelconfigs/gpt_oss__latest.metadata +4 -0
  10. opalacoder-0.2.3/opalacoder/assetstore/modelconfigs/gpt_oss__latest.zip +0 -0
  11. opalacoder-0.2.3/opalacoder/assetstore/skills/skill_html_css_js.metadata +4 -0
  12. opalacoder-0.2.3/opalacoder/assetstore/skills/skill_html_css_js.zip +0 -0
  13. opalacoder-0.2.3/opalacoder/assetstore/skills/skill_implement_feature.metadata +4 -0
  14. opalacoder-0.2.3/opalacoder/assetstore/skills/skill_implement_feature.zip +0 -0
  15. opalacoder-0.2.3/opalacoder/assetstore.py +179 -0
  16. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/cli_commands.py +78 -0
  17. opalacoder-0.2.3/opalacoder/gui/assets/index-CD7_Sjss.css +32 -0
  18. opalacoder-0.2.3/opalacoder/gui/assets/index-DYKstQJF.js +159 -0
  19. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/gui/index.html +2 -2
  20. opalacoder-0.2.3/opalacoder/icon.png +0 -0
  21. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/ide_server.py +58 -1
  22. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/memgpt_runtime.py +2 -1
  23. {opalacoder-0.2.0 → opalacoder-0.2.3}/pyproject.toml +1 -1
  24. opalacoder-0.2.0/opalacoder/gui/assets/index-BqTKFzta.js +0 -159
  25. opalacoder-0.2.0/opalacoder/gui/assets/index-_ON06SYj.css +0 -32
  26. opalacoder-0.2.0/opalacoder/icon.png +0 -0
  27. {opalacoder-0.2.0 → opalacoder-0.2.3}/.claude/rules/RULES.md +0 -0
  28. {opalacoder-0.2.0 → opalacoder-0.2.3}/.claude/settings.json +0 -0
  29. {opalacoder-0.2.0 → opalacoder-0.2.3}/.github/workflows/publish.yml +0 -0
  30. {opalacoder-0.2.0 → opalacoder-0.2.3}/.gitignore +0 -0
  31. {opalacoder-0.2.0 → opalacoder-0.2.3}/AGENTS.md +0 -0
  32. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/100.png +0 -0
  33. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/102.png +0 -0
  34. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/1024.png +0 -0
  35. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/108.png +0 -0
  36. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/114.png +0 -0
  37. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/120.png +0 -0
  38. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/128.png +0 -0
  39. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/144.png +0 -0
  40. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/152.png +0 -0
  41. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/16.png +0 -0
  42. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/167.png +0 -0
  43. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/172.png +0 -0
  44. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/180.png +0 -0
  45. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/196.png +0 -0
  46. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/20.png +0 -0
  47. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/216.png +0 -0
  48. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/234.png +0 -0
  49. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/256.png +0 -0
  50. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/258.png +0 -0
  51. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/29.png +0 -0
  52. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/32.png +0 -0
  53. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/40.png +0 -0
  54. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/48.png +0 -0
  55. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/50.png +0 -0
  56. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/512.png +0 -0
  57. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/55.png +0 -0
  58. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/57.png +0 -0
  59. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/58.png +0 -0
  60. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/60.png +0 -0
  61. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/64.png +0 -0
  62. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/66.png +0 -0
  63. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/72.png +0 -0
  64. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/76.png +0 -0
  65. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/80.png +0 -0
  66. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/87.png +0 -0
  67. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/88.png +0 -0
  68. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/92.png +0 -0
  69. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
  70. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/android/mipmap-hdpi/ic_launcher.png +0 -0
  71. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/android/mipmap-mdpi/ic_launcher.png +0 -0
  72. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/android/mipmap-xhdpi/ic_launcher.png +0 -0
  73. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/android/mipmap-xxhdpi/ic_launcher.png +0 -0
  74. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/android/mipmap-xxxhdpi/ic_launcher.png +0 -0
  75. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/appstore.png +0 -0
  76. {opalacoder-0.2.0 → opalacoder-0.2.3}/AppIcons/playstore.png +0 -0
  77. {opalacoder-0.2.0 → opalacoder-0.2.3}/CLAUDE.md +0 -0
  78. {opalacoder-0.2.0 → opalacoder-0.2.3}/GEMINI.md +0 -0
  79. {opalacoder-0.2.0 → opalacoder-0.2.3}/README.md +0 -0
  80. {opalacoder-0.2.0 → opalacoder-0.2.3}/agents.yaml +0 -0
  81. {opalacoder-0.2.0 → opalacoder-0.2.3}/config.yaml +0 -0
  82. {opalacoder-0.2.0 → opalacoder-0.2.3/debug}/debug_litellm_callbacks.py +0 -0
  83. {opalacoder-0.2.0 → opalacoder-0.2.3}/debug/scratch_tail.py +0 -0
  84. {opalacoder-0.2.0 → opalacoder-0.2.3/debug}/test_thought_stream.py +0 -0
  85. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/guide/analysis_results.md +0 -0
  86. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/guide/figs/logotipo.png +0 -0
  87. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/guide/paper_memplan.md +0 -0
  88. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/guide/skills-plugin-system.md +0 -0
  89. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/specs/01-arquitetura.md +0 -0
  90. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/specs/02-memgpt-orquestrador.md +0 -0
  91. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/specs/03-skill-implement-feature.md +0 -0
  92. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/specs/04-memoria.md +0 -0
  93. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/specs/05-vcs-sombra.md +0 -0
  94. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/specs/06-skills-e-plugins.md +0 -0
  95. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/specs/08-ide.md +0 -0
  96. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/specs/09-ide-projectcreationinterface.md +0 -0
  97. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/specs/README.md +0 -0
  98. {opalacoder-0.2.0 → opalacoder-0.2.3}/docs/specs/backlog_register.md +0 -0
  99. {opalacoder-0.2.0 → opalacoder-0.2.3}/gui_src/index.html +0 -0
  100. {opalacoder-0.2.0 → opalacoder-0.2.3}/gui_src/package-lock.json +0 -0
  101. {opalacoder-0.2.0 → opalacoder-0.2.3}/gui_src/package.json +0 -0
  102. {opalacoder-0.2.0 → opalacoder-0.2.3}/gui_src/src/main.jsx +0 -0
  103. {opalacoder-0.2.0 → opalacoder-0.2.3}/gui_src/vite.config.js +0 -0
  104. {opalacoder-0.2.0 → opalacoder-0.2.3}/main.py +0 -0
  105. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/__init__.py +0 -0
  106. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/agents.py +0 -0
  107. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/api_keys.py +0 -0
  108. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/archival.py +0 -0
  109. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/cli.py +0 -0
  110. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/code_index.py +0 -0
  111. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/config.py +0 -0
  112. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/embeddings.py +0 -0
  113. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/gui/assets/vendor-monaco-BkbU5OES.js +0 -0
  114. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/gui/assets/vendor-react-B2vUwPEE.js +0 -0
  115. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/gui/assets/vendor-xterm-3VOAfa_q.js +0 -0
  116. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/i18n.py +0 -0
  117. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/orchestrator.py +0 -0
  118. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/planner.py +0 -0
  119. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/plugins/__init__.py +0 -0
  120. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/plugins/html_css_js_tools.py +0 -0
  121. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/project.py +0 -0
  122. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/session.py +0 -0
  123. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/skills.py +0 -0
  124. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/structured.py +0 -0
  125. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/terminal.py +0 -0
  126. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/terminal_manager.py +0 -0
  127. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/tools.py +0 -0
  128. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/vcs.py +0 -0
  129. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/vector_index.py +0 -0
  130. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/workflow_orchestrator.py +0 -0
  131. {opalacoder-0.2.0 → opalacoder-0.2.3}/opalacoder/workflow_tools.py +0 -0
  132. {opalacoder-0.2.0 → opalacoder-0.2.3}/pytest.ini +0 -0
  133. {opalacoder-0.2.0 → opalacoder-0.2.3}/requirements.txt +0 -0
  134. {opalacoder-0.2.0 → opalacoder-0.2.3}/skills/chat-orchestrator/SKILL.md +0 -0
  135. {opalacoder-0.2.0 → opalacoder-0.2.3}/skills/command-line/SKILL.md +0 -0
  136. {opalacoder-0.2.0 → opalacoder-0.2.3}/skills/command-line/scripts/command_executor.py +0 -0
  137. {opalacoder-0.2.0 → opalacoder-0.2.3}/skills/skills_store/html-css-js/SKILL.md +0 -0
  138. {opalacoder-0.2.0 → opalacoder-0.2.3}/skills/skills_store/html-css-js/scripts/check_contracts.py +0 -0
  139. {opalacoder-0.2.0 → opalacoder-0.2.3}/skills/skills_store/implement-feature/SKILL.md +0 -0
  140. {opalacoder-0.2.0 → opalacoder-0.2.3}/skills/skills_store/implement-feature/scripts/run_workflow.py +0 -0
  141. {opalacoder-0.2.0 → opalacoder-0.2.3}/skills/view-editor/SKILL.md +0 -0
  142. {opalacoder-0.2.0 → opalacoder-0.2.3}/skills/view-editor/scripts/run_view_editor.py +0 -0
  143. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_agent_config.py +0 -0
  144. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_agent_stdin.py +0 -0
  145. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_code_index_integration.py +0 -0
  146. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_command_line_skill.py +0 -0
  147. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_complexity_evaluator.py +0 -0
  148. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_context_guard.py +0 -0
  149. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_file_delete.py +0 -0
  150. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_i18n_coverage.py +0 -0
  151. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_implement_feature_script.py +0 -0
  152. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_memgpt_runtime.py +0 -0
  153. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_model_commands.py +0 -0
  154. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_planner_oracle_live.py +0 -0
  155. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_planner_output.py +0 -0
  156. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_project_store.py +0 -0
  157. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_refinement_loop.py +0 -0
  158. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_search_bugs.py +0 -0
  159. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_skills_directory_loader.py +0 -0
  160. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_unhashable_dict_bug.py +0 -0
  161. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_verification_strategies.py +0 -0
  162. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_view_editor_skill.py +0 -0
  163. {opalacoder-0.2.0 → opalacoder-0.2.3}/tests/test_workflow_pipeline.py +0 -0
Binary file
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opalacoder
3
- Version: 0.2.0
3
+ Version: 0.2.3
4
4
  Summary: Autonomous coding agent with interactive planning and modular execution
5
5
  Project-URL: Homepage, https://github.com/gilzamir/OpalaCoder
6
6
  Project-URL: Bug Tracker, https://github.com/gilzamir/OpalaCoder/issues
@@ -141,7 +141,223 @@ De `build_parser` ([cli.py:419](../../opalacoder/cli.py#L419)):
141
141
 
142
142
  ---
143
143
 
144
- ## 5. Comandos do REPL
144
+ ## 5. AssetStore Repositório de Assets Reutilizáveis
145
+
146
+ > **Estado: IMPLEMENTADO**
147
+
148
+ ### Conceito
149
+
150
+ A AssetStore é um **repositório local de assets reutilizáveis** empacotados com o OpalaCoder. Ela serve como banco de dados de casos bem-sucedidos de configuração para modelos locais e como biblioteca de skills extras que podem ser instaladas sob demanda em qualquer projeto.
151
+
152
+ ```
153
+ opalacoder/assetstore/ ← instalado junto com o pacote pip
154
+ skills/
155
+ <ID>.zip ← árvore completa da skill
156
+ <ID>.metadata ← metadados YAML
157
+ modelconfigs/
158
+ <ID>.zip ← único arquivo .yaml de configuração
159
+ <ID>.metadata ← metadados YAML
160
+ ```
161
+
162
+ O caminho base é sempre `Path(__file__).parent / "assetstore"`, portanto funciona corretamente quando instalado via `pip install opalacoder` em qualquer máquina.
163
+
164
+ ### Formato dos metadados (`.metadata`)
165
+
166
+ Arquivo YAML com os campos:
167
+
168
+ | Campo | Obrigatório | Descrição |
169
+ |---|---|---|
170
+ | `id` | ✓ | Identificador único do asset (ex: `skill_implement_feature`) |
171
+ | `type` | ✓ | `skill` ou `modelconfig` |
172
+ | `desc` | ✓ | Descrição legível usada como critério de busca |
173
+ | `name` | skill | Nome da skill (igual ao diretório dentro do zip) |
174
+ | `model` | modelconfig | Identificador do modelo (ex: `ollama/gpt-oss:latest`) |
175
+
176
+ **Exemplo — skill:**
177
+ ```yaml
178
+ id: skill_implement_feature
179
+ type: skill
180
+ name: implement-feature
181
+ desc: Plan-Execute-Verify loop for implementing features and fixing bugs in project files
182
+ ```
183
+
184
+ **Exemplo — modelconfig:**
185
+ ```yaml
186
+ id: model_ollama_gpt_oss__latest
187
+ type: modelconfig
188
+ desc: gpt-oss:latest via Ollama — think=false, tool calling stable
189
+ model: ollama/gpt-oss:latest
190
+ ```
191
+
192
+ ### Destino de instalação
193
+
194
+ | Tipo | Destino no projeto |
195
+ |---|---|
196
+ | `skill` | `<projeto>/.opalacoder/skills/<name>/` |
197
+ | `modelconfig` | `<projeto>/.opalacoder/modelsconfig/<provider>/<modelo>.yaml` |
198
+
199
+ Para modelconfigs, o provider é normalizado: `ollama_chat/` e `ollama/` → diretório `ollama/`. Os dois pontos no nome do modelo viram `__`.
200
+
201
+ ### Comandos REPL
202
+
203
+ ```
204
+ /list_assets [tipo] — lista todos os assets (ou só do tipo especificado)
205
+ /load_asset <tipo> <desc|id|*> — instala asset(s) no projeto ativo
206
+ ```
207
+
208
+ `<desc>` pode ser o `id` exato ou o valor do campo `desc`. Usar `*` instala todos os assets do tipo.
209
+
210
+ **Exemplos:**
211
+ ```
212
+ /list_assets
213
+ /list_assets modelconfig
214
+ /load_asset skill skill_implement_feature
215
+ /load_asset modelconfig model_ollama_gpt_oss__latest
216
+ /load_asset skill *
217
+ ```
218
+
219
+ Após instalar uma skill, ativá-la no projeto com `/addskill <name>`.
220
+
221
+ ---
222
+
223
+ ## 5.1. Banco de Configurações Refinadas de Modelos
224
+
225
+ > **Estado: IMPLEMENTADO**
226
+
227
+ ### Conceito
228
+
229
+ O diretório `.opalacoder/modelsconfig/` dentro de cada projeto funciona como um
230
+ **banco de dados de casos bem-sucedidos de configuração para modelos locais**. Cada
231
+ arquivo YAML registra os parâmetros que produziram comportamento correto e estável
232
+ para um modelo específico naquele projeto — resultado de testes empíricos, não de
233
+ valores genéricos.
234
+
235
+ A motivação é que modelos locais (Ollama, LM Studio, etc.) exigem combinações
236
+ precisas de parâmetros para funcionar bem: `think` e `stream` podem quebrar
237
+ tool calling em certos modelos; `num_ctx` muito baixo degrada o raciocínio;
238
+ `temperature` alta pode destabilizar modelos de instrução. Esses parâmetros
239
+ **não são portáveis** — o que funciona para `deepseek-r1:14b` não funciona para
240
+ `ministral-3:14b`. O banco de configurações resolve isso por projeto.
241
+
242
+ ### Estrutura de diretórios
243
+
244
+ ```
245
+ <projeto>/
246
+ └── .opalacoder/
247
+ └── modelsconfig/
248
+ └── <provider>/
249
+ └── <nome_do_modelo>.yaml
250
+ ```
251
+
252
+ - **`<provider>`**: prefixo do modelo, com normalização — `ollama_chat/` e `ollama/`
253
+ mapeiam ambos para o diretório `ollama/`.
254
+ - **`<nome_do_modelo>.yaml`**: nome do modelo com `:` substituído por `__`
255
+ (hífens mantidos).
256
+
257
+ **Exemplos de mapeamento:**
258
+
259
+ | Modelo digitado | Diretório | Arquivo |
260
+ |---|---|---|
261
+ | `ollama/deepseek-r1:14b` | `ollama/` | `deepseek-r1__14b.yaml` |
262
+ | `ollama_chat/deepseek-r1:14b` | `ollama/` | `deepseek-r1__14b.yaml` |
263
+ | `ollama/ministral-3:14b` | `ollama/` | `ministral-3__14b.yaml` |
264
+ | `ollama/qwen3:14b` | `ollama/` | `qwen3__14b.yaml` |
265
+
266
+ ### Formato do arquivo YAML
267
+
268
+ O arquivo pode conter qualquer chave de `model_params` aceita pelo sistema, mais
269
+ uma chave especial `provider`:
270
+
271
+ ```yaml
272
+ # .opalacoder/modelsconfig/ollama/deepseek-r1__14b.yaml
273
+ # Configuração refinada para DeepSeek-R1 14B via Ollama
274
+ # Obtida empiricamente — funciona com tool calling e thinking em tempo real
275
+
276
+ provider: ollama_chat # opcional: substitui o prefixo do modelo na sessão
277
+ # aqui muda de ollama/ para ollama_chat/ para habilitar
278
+ # o endpoint nativo do Ollama com thinking por chunk
279
+
280
+ # LiteLLM / model_kwargs
281
+ think: true
282
+ stream: true
283
+ temperature: 0.6
284
+ num_ctx: 32768
285
+ max_tokens: 8192
286
+
287
+ # Parâmetros do agente
288
+ max_heartbeats: 15
289
+ ```
290
+
291
+ ```yaml
292
+ # .opalacoder/modelsconfig/ollama/ministral-3__14b.yaml
293
+ # Ministral 3 14B — sem thinking (não suportado), tool calling estável
294
+
295
+ think: false
296
+ stream: false
297
+ temperature: 0.7
298
+ num_ctx: 16384
299
+ max_tokens: 8128
300
+ max_heartbeats: 20
301
+ ```
302
+
303
+ **Chave `provider`** (opcional): quando presente, substitui o prefixo do modelo
304
+ na interface. Útil para forçar `ollama_chat/` em modelos com suporte a thinking
305
+ nativo, sem o usuário precisar digitar o prefixo correto.
306
+
307
+ ### Como usar
308
+
309
+ Na janela de **criação** ou **configuração** de projeto, após definir o modelo,
310
+ clique em **Load Refined Config**:
311
+
312
+ - Se existir um arquivo para o modelo: carrega e substitui completamente o
313
+ `model_params` do projeto. Se o YAML tiver `provider:`, atualiza o campo
314
+ modelo com o novo prefixo.
315
+ - Se não existir: exibe `--- ainda não temos parâmetros refinados para este modelo`.
316
+
317
+ O backend resolve o arquivo via `GET/POST /api/opalacoder/model-config`
318
+ ([ide_server.py](../../opalacoder/ide_server.py)).
319
+
320
+ ### Critério para adicionar uma entrada
321
+
322
+ Uma entrada deve ser adicionada ao banco quando:
323
+
324
+ 1. O modelo foi testado com a configuração e **tool calling funciona** sem erros.
325
+ 2. O comportamento de **thinking/reflection** (se aplicável) está correto.
326
+ 3. Os valores de **contexto e tokens** são adequados ao hardware disponível.
327
+
328
+ O arquivo é mantido manualmente pelo usuário/equipe e versionado junto com o
329
+ projeto. Não é gerado automaticamente.
330
+
331
+ ### Exemplo completo — `gpt-oss:latest` (Ollama)
332
+
333
+ ```yaml
334
+ # .opalacoder/modelsconfig/ollama/gpt-oss__latest.yaml
335
+ #
336
+ # Configuração refinada para gpt-oss:latest via Ollama
337
+ # Testado em: 2026-06-02 | Hardware: RTX 4090 24GB
338
+ # Status: tool calling OK, thinking OK, stream OK
339
+ #
340
+ provider: ollama_chat # endpoint nativo: thinking por chunk em tempo real
341
+
342
+ # LiteLLM / model_kwargs
343
+ think: false # desativar thinking evita bug de tool_calls vazio (ollama #15288)
344
+ stream: false # stream false: mais estável com tool calling
345
+ temperature: 0.1 # baixo para respostas determinísticas em tarefas de código
346
+ num_ctx: 32768 # contexto amplo para projetos grandes
347
+ max_tokens: 8192
348
+
349
+ # Parâmetros do agente MemGPT (chat-orquestrador)
350
+ max_heartbeats: 20
351
+ max_context_tokens: 32768
352
+
353
+ # Parâmetros do agente LLMAgentBlock (workers)
354
+ max_tool_calls: 10
355
+ debug: false
356
+ ```
357
+
358
+ ---
359
+
360
+ ## 6. Comandos do REPL
145
361
 
146
362
  Registrados em [cli_commands.py](../../opalacoder/cli_commands.py):
147
363
 
@@ -75,6 +75,7 @@ export default function App() {
75
75
  const [thinkingLogs, setThinkingLogs] = useState([]);
76
76
  const [showAdvancedParams, setShowAdvancedParams] = useState(false);
77
77
  const [newProjError, setNewProjError] = useState('');
78
+ const [modelConfigMsg, setModelConfigMsg] = useState('');
78
79
 
79
80
  // Directory picker state: { target: 'new'|'edit', current: '/path', dirs: [{name,path}] } | null
80
81
  const [dirPicker, setDirPicker] = useState(null);
@@ -182,6 +183,7 @@ export default function App() {
182
183
  const [newProjDesc, setNewProjDesc] = useState('');
183
184
  const [newProjModel, setNewProjModel] = useState('gemini/gemini-2.5-flash');
184
185
  const [newProjMode, setNewProjMode] = useState('auto');
186
+ const [newProjModelParams, setNewProjModelParams] = useState({});
185
187
  const [newProjApiKey, setNewProjApiKey] = useState('');
186
188
  const [newProjApiBase, setNewProjApiBase] = useState('http://localhost:11434/v1');
187
189
 
@@ -440,6 +442,18 @@ export default function App() {
440
442
  }
441
443
  }, [activeProject]);
442
444
 
445
+ // Polling for workspace file changes and git status (every 10 seconds)
446
+ useEffect(() => {
447
+ if (!activeProject) return;
448
+
449
+ const interval = setInterval(() => {
450
+ fetchFiles();
451
+ fetchGitStatus();
452
+ }, 10000);
453
+
454
+ return () => clearInterval(interval);
455
+ }, [activeProject]);
456
+
443
457
  useEffect(() => {
444
458
  if (activeSidebarTab === 'git' && activeProject) {
445
459
  fetchGitStatus();
@@ -980,7 +994,8 @@ export default function App() {
980
994
  model: newProjModel,
981
995
  mode: newProjMode,
982
996
  api_key: newProjApiKey,
983
- api_base: newProjApiBase
997
+ api_base: newProjApiBase,
998
+ model_params: Object.keys(newProjModelParams).length ? newProjModelParams : undefined
984
999
  })
985
1000
  });
986
1001
  if (res.ok) {
@@ -1035,6 +1050,7 @@ export default function App() {
1035
1050
  if (found) fresh = found;
1036
1051
  }
1037
1052
  } catch (_) { }
1053
+ setModelConfigMsg('');
1038
1054
  setEditingProject({
1039
1055
  name: fresh.name,
1040
1056
  project_name: fresh.project_name || fresh.name,
@@ -1087,6 +1103,30 @@ export default function App() {
1087
1103
  }
1088
1104
  };
1089
1105
 
1106
+ const loadModelConfig = async (projectPath, model, applyFn) => {
1107
+ setModelConfigMsg('');
1108
+ if (!projectPath || !model) {
1109
+ setModelConfigMsg('⚠️ Defina o caminho do projeto e o modelo antes de carregar.');
1110
+ return;
1111
+ }
1112
+ try {
1113
+ const res = await fetch('/api/opalacoder/model-config', {
1114
+ method: 'POST',
1115
+ headers: { 'Content-Type': 'application/json' },
1116
+ body: JSON.stringify({ projectPath, model }),
1117
+ });
1118
+ const data = await res.json();
1119
+ if (!data.found) {
1120
+ setModelConfigMsg(data.message);
1121
+ return;
1122
+ }
1123
+ applyFn(data);
1124
+ setModelConfigMsg('✅ Configuração refinada carregada.');
1125
+ } catch (e) {
1126
+ setModelConfigMsg(`⚠️ Erro ao carregar: ${e.message}`);
1127
+ }
1128
+ };
1129
+
1090
1130
  const openDirPicker = async (target, startPath) => {
1091
1131
  const path = startPath || '~';
1092
1132
  try {
@@ -1194,6 +1234,7 @@ export default function App() {
1194
1234
  setChatMessages(prev => [...prev, { role: 'assistant', content: `🔴 Falha: ${err.message}` }]);
1195
1235
  } finally {
1196
1236
  setIsAgentRunning(false);
1237
+ fetchFiles();
1197
1238
  }
1198
1239
  return;
1199
1240
  }
@@ -1474,7 +1515,7 @@ export default function App() {
1474
1515
  <div className="vscode-sidebar-header">
1475
1516
  <span className="vscode-sidebar-title">EXPLORER: PROJECTS</span>
1476
1517
  <button
1477
- onClick={() => setShowNewProjectModal(true)}
1518
+ onClick={() => { setShowNewProjectModal(true); setModelConfigMsg(''); setNewProjModelParams({}); }}
1478
1519
  style={{ background: 'transparent', border: 'none', cursor: 'pointer', color: '#c5c5c5' }}
1479
1520
  title="Novo Projeto..."
1480
1521
  >
@@ -1545,7 +1586,39 @@ export default function App() {
1545
1586
  }}
1546
1587
  style={dragOverPath === '__root__' ? { border: '2px dashed #007acc', backgroundColor: 'rgba(0, 122, 204, 0.05)' } : {}}
1547
1588
  >
1548
- <div className="vscode-sidebar-section-title">Workspace Files</div>
1589
+ <div className="vscode-sidebar-section-title" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
1590
+ <span>Workspace Files</span>
1591
+ {activeProject && (
1592
+ <button
1593
+ onClick={(e) => {
1594
+ e.stopPropagation();
1595
+ fetchFiles();
1596
+ }}
1597
+ title="Atualizar arquivos"
1598
+ style={{
1599
+ background: 'transparent',
1600
+ border: 'none',
1601
+ color: '#808080',
1602
+ cursor: 'pointer',
1603
+ display: 'flex',
1604
+ alignItems: 'center',
1605
+ padding: '2px',
1606
+ borderRadius: '3px',
1607
+ transition: 'color 0.2s, background-color 0.2s',
1608
+ }}
1609
+ onMouseOver={(e) => {
1610
+ e.currentTarget.style.color = '#ffffff';
1611
+ e.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
1612
+ }}
1613
+ onMouseOut={(e) => {
1614
+ e.currentTarget.style.color = '#808080';
1615
+ e.currentTarget.style.backgroundColor = 'transparent';
1616
+ }}
1617
+ >
1618
+ <RefreshCw size={12} />
1619
+ </button>
1620
+ )}
1621
+ </div>
1549
1622
  {files.length === 0 ? (
1550
1623
  <div style={{ fontSize: '12px', color: '#808080', padding: '0 4px', fontStyle: 'italic' }}>
1551
1624
  Selecione um projeto para explorar.
@@ -2194,6 +2267,22 @@ export default function App() {
2194
2267
  </div>
2195
2268
  </div>
2196
2269
 
2270
+ {/* Load refined model config */}
2271
+ <div style={{ display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'wrap' }}>
2272
+ <button type="button" className="vscode-button" style={{ background: '#3c3c3c', fontSize: '12px' }}
2273
+ onClick={() => loadModelConfig(newProjPath, newProjModel, (cfg) => {
2274
+ if (cfg.model_params) setNewProjModelParams(cfg.model_params);
2275
+ if (cfg.model) setNewProjModel(cfg.model);
2276
+ })}>
2277
+ Load Refined Config
2278
+ </button>
2279
+ {modelConfigMsg && (
2280
+ <span style={{ fontSize: '11px', color: modelConfigMsg.startsWith('✅') ? '#4ec9b0' : '#f48771' }}>
2281
+ {modelConfigMsg}
2282
+ </span>
2283
+ )}
2284
+ </div>
2285
+
2197
2286
  {newProjError && (
2198
2287
  <div style={{ color: '#f48771', fontSize: '11px', marginTop: '4px', whiteSpace: 'pre-wrap' }}>
2199
2288
  ⚠️ {newProjError}
@@ -2359,6 +2448,25 @@ export default function App() {
2359
2448
  </div>
2360
2449
  </div>
2361
2450
 
2451
+ {/* Load refined model config */}
2452
+ <div style={{ display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'wrap' }}>
2453
+ <button type="button" className="vscode-button" style={{ background: '#3c3c3c', fontSize: '12px' }}
2454
+ onClick={() => loadModelConfig(editingProject.project_path, editingProject.model, (cfg) => {
2455
+ setEditingProject(p => ({
2456
+ ...p,
2457
+ model_params: cfg.model_params || p.model_params,
2458
+ model: cfg.model || p.model,
2459
+ }));
2460
+ })}>
2461
+ Load Refined Config
2462
+ </button>
2463
+ {modelConfigMsg && (
2464
+ <span style={{ fontSize: '11px', color: modelConfigMsg.startsWith('✅') ? '#4ec9b0' : '#f48771' }}>
2465
+ {modelConfigMsg}
2466
+ </span>
2467
+ )}
2468
+ </div>
2469
+
2362
2470
  {/* Alternative model */}
2363
2471
  <div className="flex flex-col" style={{ gap: '4px' }}>
2364
2472
  <label className="vscode-sidebar-section-title" style={{ padding: 0 }}>Modelo Alternativo</label>
@@ -92,6 +92,11 @@ input, select, textarea {
92
92
  outline: none;
93
93
  }
94
94
 
95
+ select option {
96
+ background-color: var(--vscode-input-bg);
97
+ color: var(--vscode-text-fg);
98
+ }
99
+
95
100
  input:focus, select:focus, textarea:focus {
96
101
  border-color: var(--vscode-active-border);
97
102
  }
Binary file
@@ -286,11 +286,22 @@ async def handle_slash_command(data: dict) -> dict:
286
286
  T.confirm = lambda p, default=True: default # sync fallback never used in GUI
287
287
  T.ask = lambda p: ""
288
288
 
289
+ def _render_rich(obj) -> str:
290
+ from rich.console import Console as _Console
291
+ from rich.table import Table as _Table
292
+ from io import StringIO
293
+ if isinstance(obj, _Table):
294
+ buf = StringIO()
295
+ c = _Console(file=buf, highlight=False, no_color=True)
296
+ c.print(obj)
297
+ return buf.getvalue()
298
+ return str(obj)
299
+
289
300
  def _console_print(*args_c, **kwargs_c):
290
301
  if not args_c:
291
302
  messages.append("")
292
303
  return
293
- raw = " ".join(str(x) for x in args_c)
304
+ raw = " ".join(_render_rich(x) for x in args_c)
294
305
  for line in raw.split("\n"):
295
306
  stripped = line.strip()
296
307
  if not stripped:
@@ -302,6 +313,9 @@ async def handle_slash_command(data: dict) -> dict:
302
313
  messages.append("### 🧠 Active skills for this project\n"); continue
303
314
  if "Available skills" in stripped:
304
315
  messages.append("### 📚 Available skills\n"); continue
316
+ clean = re.sub(r'\[/?[\w\s]+\]', '', stripped)
317
+ if clean and clean == clean.upper() and clean.replace(" ", "").isalpha():
318
+ messages.append(f"### {clean}\n"); continue
305
319
  m = re.match(r'\s*(?:\*\s*)?\[(green|cyan)\]\s*(.*?)\s*\[/\1\]\s*(.*)', line)
306
320
  if m:
307
321
  name = m.group(2).strip()
@@ -316,7 +330,7 @@ async def handle_slash_command(data: dict) -> dict:
316
330
  if sm:
317
331
  star = "⭐ " if has_star else "🔹 "
318
332
  messages.append(f"{star}**`{sm.group(1).strip()}`** — {sm.group(2).strip()}"); continue
319
- messages.append(re.sub(r'\[/?\w+\]', '', line))
333
+ messages.append(re.sub(r'\[/?[\w\s]+\]', '', line))
320
334
 
321
335
  T.console.print = _console_print
322
336
 
@@ -0,0 +1,4 @@
1
+ id: gpt_oss__latest
2
+ type: modelconfig
3
+ desc: "GPT OSS latest model via Ollama"
4
+ model: ollama/gpt-oss:latest
@@ -0,0 +1,4 @@
1
+ id: skill_html_css_js
2
+ type: skill
3
+ name: html-css-js
4
+ desc: Best practice rules and contract detector for vanilla HTML/CSS/JavaScript projects
@@ -0,0 +1,4 @@
1
+ id: skill_implement_feature
2
+ type: skill
3
+ name: implement-feature
4
+ desc: Plan-Execute-Verify loop for implementing features and fixing bugs in project files