faure 0.1.2 → 0.2.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.
- checksums.yaml +4 -4
- data/lib/faure/codeur.rb +30 -4
- data/lib/faure/config.rb +23 -6
- data/lib/faure/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e7329e214012017c8b3e222c24b70410e57f4ae40c24b070b37d22edf56ba699
|
|
4
|
+
data.tar.gz: c141ee9f3e2f7c11e156e7c7091c1a6e7463c07b9d7abd6c0696dccde2bb06b2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 460065142943c13c00c8bd76b9d6fcadc4c68c59e9955ce8b23f4bee4d8bc284d8b51d4e38451b9ec44426556ede92e3b147625c12efe1691f403d3baad45c28
|
|
7
|
+
data.tar.gz: b11f9a311b88924e905c6a658123ceac2cdca7b86cef5931dd056d57927fbc366eb86a855d0dd92ddbac032b0226d56d67a9f7058414f5961e6a34051fd977a7
|
data/lib/faure/codeur.rb
CHANGED
|
@@ -17,6 +17,7 @@ module Faure
|
|
|
17
17
|
@noteable_type = payload.dig('object_attributes', 'noteable_type')
|
|
18
18
|
@author_id = payload.dig('user', 'id').to_i
|
|
19
19
|
@issue_iid = payload.dig('issue', 'iid').to_s
|
|
20
|
+
@agents_md = load_agents_md
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
def run
|
|
@@ -34,7 +35,7 @@ module Faure
|
|
|
34
35
|
.select { |n| n['body'].include?('🤔 **faure demande :**') }
|
|
35
36
|
.last
|
|
36
37
|
|
|
37
|
-
mode = if pending_question && !@note.include?(
|
|
38
|
+
mode = if pending_question && !@note.include?("@#{Config::BOT_USERNAME}")
|
|
38
39
|
:answering_question
|
|
39
40
|
else
|
|
40
41
|
:new_instruction
|
|
@@ -75,15 +76,17 @@ module Faure
|
|
|
75
76
|
abort '[faure] Pas un commentaire sur issue, abandon.' unless @noteable_type == 'Issue'
|
|
76
77
|
abort '[faure] Commentaire du bot, abandon.' if @author_id == Config::BOT_ID
|
|
77
78
|
abort '[faure] Commentaire faure:context, abandon.' if @note.include?('<!-- faure:context -->')
|
|
78
|
-
abort
|
|
79
|
-
unless @note.include?(
|
|
79
|
+
abort "[faure] Pas de mention @#{Config::BOT_USERNAME} ni réponse attendue." \
|
|
80
|
+
unless @note.include?("@#{Config::BOT_USERNAME}") || @note.match?(/^[^@]/)
|
|
80
81
|
end
|
|
81
82
|
|
|
82
83
|
def system_prompt
|
|
83
84
|
lang_instruction = Config::LANG == 'fr' ? 'Réponds en français.' : 'Reply in English.'
|
|
85
|
+
agents_section = @agents_md ? "\n## Project conventions\n\n#{@agents_md}\n" : ''
|
|
84
86
|
<<~SYSTEM
|
|
85
87
|
Tu es un agent codeur expert. Tu reçois une tâche de développement et tu dois produire les modifications de fichiers nécessaires.
|
|
86
88
|
#{lang_instruction}
|
|
89
|
+
#{agents_section}
|
|
87
90
|
Réponds UNIQUEMENT avec des balises XML :
|
|
88
91
|
- <file path="chemin/fichier">contenu complet du fichier</file> pour chaque fichier modifié
|
|
89
92
|
- <question>ta question</question> si tu as besoin de clarifications (peut coexister avec des <file>)
|
|
@@ -91,6 +94,29 @@ module Faure
|
|
|
91
94
|
SYSTEM
|
|
92
95
|
end
|
|
93
96
|
|
|
97
|
+
def load_agents_md
|
|
98
|
+
faure_path = File.join(Config::PROJECT_DIR, '.faure', 'AGENTS.md')
|
|
99
|
+
root_path = File.join(Config::PROJECT_DIR, 'AGENTS.md')
|
|
100
|
+
path = [faure_path, root_path].find { |p| File.exist?(p) }
|
|
101
|
+
unless path
|
|
102
|
+
warn '[faure] No AGENTS.md found (.faure/AGENTS.md or AGENTS.md) — using generic instructions'
|
|
103
|
+
return nil
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
File.read(path).gsub(/^@(\S+)/) do |_|
|
|
107
|
+
ref = File.join(Config::PROJECT_DIR, $1)
|
|
108
|
+
if File.exist?(ref)
|
|
109
|
+
File.read(ref)
|
|
110
|
+
else
|
|
111
|
+
warn "[faure] .faure/AGENTS.md: reference @#{$1} not found, skipping"
|
|
112
|
+
''
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
rescue => e
|
|
116
|
+
warn "[faure] Could not read .faure/AGENTS.md : #{e.message}"
|
|
117
|
+
nil
|
|
118
|
+
end
|
|
119
|
+
|
|
94
120
|
def build_prompt(mode, issue, previous_summary, pending_question)
|
|
95
121
|
case mode
|
|
96
122
|
when :answering_question
|
|
@@ -119,7 +145,7 @@ module Faure
|
|
|
119
145
|
Description :
|
|
120
146
|
#{issue['description']}
|
|
121
147
|
|
|
122
|
-
#{@note.include?(
|
|
148
|
+
#{@note.include?("@#{Config::BOT_USERNAME}") ? "Instruction : #{@note}" : ''}
|
|
123
149
|
PROMPT
|
|
124
150
|
end
|
|
125
151
|
end
|
data/lib/faure/config.rb
CHANGED
|
@@ -1,11 +1,33 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'uri'
|
|
4
|
+
|
|
1
5
|
module Faure
|
|
2
6
|
module Config
|
|
3
7
|
# Obligatoires
|
|
4
8
|
API_TOKEN = ENV.fetch('FAURE_API_TOKEN')
|
|
5
9
|
REVIEWER_ID = ENV.fetch('FAURE_REVIEWER_ID').to_i
|
|
6
|
-
BOT_ID = ENV.fetch('FAURE_BOT_ID', '0').to_i
|
|
7
10
|
OPENAI_URL = ENV.fetch('OPENAI_API_URL', 'http://host.containers.internal:8080')
|
|
8
11
|
|
|
12
|
+
# GitLab CI — injectées automatiquement
|
|
13
|
+
GITLAB_URL = ENV.fetch('CI_SERVER_URL', 'https://gitlab.com')
|
|
14
|
+
PROJECT_ID = ENV.fetch('CI_PROJECT_ID')
|
|
15
|
+
PROJECT_DIR = ENV.fetch('CI_PROJECT_DIR', Dir.pwd)
|
|
16
|
+
|
|
17
|
+
# Résolution dynamique du bot via /api/v4/user (FAURE_BOT_ID déprécié)
|
|
18
|
+
_bot = begin
|
|
19
|
+
uri = URI("#{GITLAB_URL}/api/v4/user")
|
|
20
|
+
req = Net::HTTP::Get.new(uri)
|
|
21
|
+
req['PRIVATE-TOKEN'] = API_TOKEN
|
|
22
|
+
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') { |h| h.request(req) }
|
|
23
|
+
JSON.parse(res.body)
|
|
24
|
+
rescue => e
|
|
25
|
+
warn "[faure] Impossible de résoudre le bot via l'API : #{e.message}"
|
|
26
|
+
{}
|
|
27
|
+
end
|
|
28
|
+
BOT_ID = (_bot['id'] || 0).to_i
|
|
29
|
+
BOT_USERNAME = _bot['username'] || 'faure-bot'
|
|
30
|
+
|
|
9
31
|
# Modèles — configurables par projet
|
|
10
32
|
CODER_MODEL = ENV.fetch('FAURE_CODER_MODEL', 'mlx-community/Qwen3-Coder-30B-A3B-Instruct-4bit')
|
|
11
33
|
AGENT_MODEL = ENV.fetch('FAURE_AGENT_MODEL', 'mlx-community/Qwen3.5-4B-4bit')
|
|
@@ -14,10 +36,5 @@ module Faure
|
|
|
14
36
|
# Options
|
|
15
37
|
TARGET_BRANCH = ENV.fetch('FAURE_TARGET_BRANCH', 'main')
|
|
16
38
|
LANG = ENV.fetch('FAURE_LANG', 'fr')
|
|
17
|
-
|
|
18
|
-
# GitLab CI — injectées automatiquement
|
|
19
|
-
GITLAB_URL = ENV.fetch('CI_SERVER_URL', 'https://gitlab.com')
|
|
20
|
-
PROJECT_ID = ENV.fetch('CI_PROJECT_ID')
|
|
21
|
-
PROJECT_DIR = ENV.fetch('CI_PROJECT_DIR', Dir.pwd)
|
|
22
39
|
end
|
|
23
40
|
end
|
data/lib/faure/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: faure
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Roland Laurès
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-03-
|
|
11
|
+
date: 2026-03-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Faure orchestre un agent codeur et un agent git via GitLab CI/CD et un
|
|
14
14
|
backend OpenAI-compatible (mlx_lm, Ollama, OpenAI...).
|