Compare commits

...

26 Commits

Author SHA1 Message Date
admin aea3e93d36 Merge pull request 'fix(llm): 強化 OpenCode JSON 回應解析' (#17) from develop into master
CD / 計算版本號 (push) Successful in 1s
CD / 發布專案 (push) Successful in 4s
Reviewed-on: #17
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
2026-06-17 07:15:15 +00:00
jiantw83 c66a9aa025 fix(llm): 強化 OpenCode JSON 回應解析 2026-06-17 07:08:11 +00:00
admin 79e4042003 Merge pull request 'feat(opencode): 新增 OpenCode server provider 串接' (#16) from develop into master
CD / 計算版本號 (push) Successful in 2s
CD / 發布專案 (push) Successful in 3s
Reviewed-on: #16
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
2026-06-17 07:00:27 +00:00
jiantw83 92f10c7970 Merge pull request '優化 Step2:改用 skill RPG 攻防腳色系統(新增 Mage 邏輯角色、Step3/4 套 Paladin 裁決人設)' (#15) from develop into master
CD / 計算版本號 (push) Successful in 2s
CD / 發布專案 (push) Successful in 5s
Reviewed-on: #15
2026-06-16 09:05:54 +00:00
jiantw83 07e38f9d45 Merge pull request 'feat: 前置驗證納入 git push 認證檢查' (#11) from develop into master
CD / 計算版本號 (push) Successful in 2s
CD / 發布專案 (push) Successful in 7s
Reviewed-on: #11
2026-06-16 06:23:51 +00:00
jiantw83 49f190e944 Merge pull request 'feat: implement Git integration for automated repository instruction syncing and commit management' (#131) from develop into master
Reviewed-on: #131
2026-05-21 04:00:28 +00:00
jiantw83 72701dee0a Merge pull request 'feat: add SKILL.md for triage-findings documentation' (#128) from develop into master
Reviewed-on: #128
2026-05-20 09:11:03 +00:00
jiantw83 503e50a2d0 Merge pull request 'feat: 將 ANTIGRAVITY 加入程式與技能' (#126) from develop into master
Reviewed-on: #126
2026-05-20 02:56:21 +00:00
jiantw83 dddcc9031b Merge pull request 'develop' (#124) from develop into master
Reviewed-on: #124
2026-05-18 03:32:00 +00:00
jiantw83 ace50037ba Merge pull request 'feat: 優化AI排除問題與過濾' (#122) from develop into master
Reviewed-on: #122
2026-05-18 02:59:46 +00:00
jiantw83 76eaff7788 Merge pull request '版本 0.1.6' (#120) from develop into master
Reviewed-on: #120
2026-05-15 15:57:20 +00:00
jiantw83 6ac8512dbc Merge pull request 'fix: remove GITEA_TOKEN from AI Code Review step and ensure master branch is ignored in pull requestsfix: remove GITEA_TOKEN from AI Code Review step and ensure master branch is ignored in pull requests' (#116) from develop into master
Reviewed-on: #116
2026-05-15 09:56:51 +00:00
jiantw83 3b8e942e7f Merge pull request 'feat: enhance findings and exclusions handling with repo state logging' (#114) from develop into master
Reviewed-on: #114
2026-05-15 09:52:26 +00:00
jiantw83 051457b11b Merge pull request 'fix: clarify stage seven push failures' (#112) from develop into master
Reviewed-on: #112
2026-05-15 06:55:50 +00:00
jiantw83 92f1c6fe82 Merge pull request 'fix: support wrapped exclusions schema' (#111) from develop into master
Reviewed-on: #111
2026-05-15 06:46:28 +00:00
jiantw83 27df6894a4 Merge pull request 'fix: write findings to review dir' (#110) from develop into master
Reviewed-on: #110
2026-05-15 06:25:29 +00:00
jiantw83 1afd978059 Merge pull request 'fix: stage generated review files' (#109) from develop into master
Reviewed-on: #109
2026-05-15 05:53:55 +00:00
jiantw83 146faca7cb Merge pull request 'docs: preserve original text in exclusions' (#108) from develop into master
Reviewed-on: #108
2026-05-15 04:51:23 +00:00
jiantw83 4c99247566 Merge pull request 'fix: sync codex skill assets' (#107) from develop into master
Reviewed-on: #107
2026-05-15 04:24:32 +00:00
jiantw83 81cbb83340 Merge pull request 'fix: package triage skills into the action image' (#106) from develop into master
Reviewed-on: #106
2026-05-15 04:00:55 +00:00
jiantw83 3f65b72cf0 Merge pull request 'fix: restore triage skill files and keep sync non-destructive' (#104) from develop into master
Reviewed-on: #104
2026-05-15 03:34:26 +00:00
jiantw83 2eb94c8f74 Merge pull request 'feat: 解決階段七commit失敗的問題' (#102) from develop into master
Reviewed-on: #102
2026-05-15 03:18:55 +00:00
jiantw83 6354c0987c Merge pull request 'chore: refine stage 7 json validation' (#98) from develop into master
Reviewed-on: #98
2026-05-14 02:42:13 +00:00
jiantw83 7df34eb1d0 Merge pull request '版本 0.0.4' (#97) from develop into master
Reviewed-on: #97
2026-05-13 06:31:30 +00:00
jiantw83 ca5d54882f Merge pull request '版本 0.0.2' (#94) from develop into master
Reviewed-on: #94
2026-05-13 02:43:10 +00:00
jiantw83 ca4664e0cc Merge pull request '發布 0.0.1' (#86) from develop into master
Reviewed-on: #86
2026-05-12 10:09:32 +00:00
4 changed files with 88 additions and 1 deletions
+4
View File
@@ -203,6 +203,10 @@ export async function mergeInstructionText(existingText, sourceText, relPath, ai
try {
const aiMerged = await aiMergeAssistant({ relPath, existingText, sourceText, deterministicText: deterministic, requiredBlocks });
if (aiMerged == null) {
warn(`[merge] ${relPath} AI result unavailable; using deterministic merge`);
return deterministic;
}
if (typeof aiMerged === 'string' && validateMergedInstructionText(aiMerged, requiredBlocks)) {
return normalizeText(aiMerged) === normalizeText(existingText) ? existingText : aiMerged;
}
+9
View File
@@ -211,6 +211,15 @@ describe('commitAndPush', () => {
assert.ok(result.includes('extra block'));
});
it('uses deterministic instruction merge when AI returns no usable result', async () => {
const aiMergeAssistant = async () => null;
const result = await mergeInstructionText('repo block', 'source block', 'AGENTS.md', aiMergeAssistant);
assert.ok(result.includes('repo block'));
assert.ok(result.includes('source block'));
});
it('exits when AI output drops a block', async () => {
const originalExit = process.exit;
let exitCode = null;
+61 -1
View File
@@ -111,9 +111,69 @@ export async function chat(systemPrompt, userContent) {
export async function chatJSON(systemPrompt, userContent) {
const text = await chat(systemPrompt, userContent);
try {
return JSON.parse(text.trim().replace(/^```[^\n]*\n?/, '').replace(/```$/, '').trim());
return JSON.parse(extractJSONText(text));
} catch (e) {
line(`[LLM] JSON 解析失敗: ${e.message}`);
return [];
}
}
function stripOuterFence(text) {
return String(text)
.trim()
.replace(/^```[a-zA-Z0-9_-]*\n?/, '')
.replace(/```$/, '')
.trim();
}
function extractBalancedJSON(text, startIndex) {
const source = String(text);
const open = source[startIndex];
const close = open === '{' ? '}' : ']';
let depth = 0;
let inString = false;
let escaped = false;
for (let i = startIndex; i < source.length; i++) {
const ch = source[i];
if (inString) {
if (escaped) {
escaped = false;
} else if (ch === '\\') {
escaped = true;
} else if (ch === '"') {
inString = false;
}
continue;
}
if (ch === '"') {
inString = true;
continue;
}
if (ch === open) depth += 1;
else if (ch === close) {
depth -= 1;
if (depth === 0) return source.slice(startIndex, i + 1);
}
}
return null;
}
function extractJSONText(text) {
const stripped = stripOuterFence(text);
try {
JSON.parse(stripped);
return stripped;
} catch {}
for (let i = 0; i < stripped.length; i++) {
if (stripped[i] !== '[' && stripped[i] !== '{') continue;
const candidate = extractBalancedJSON(stripped, i);
if (!candidate) continue;
try {
JSON.parse(candidate);
return candidate;
} catch {}
}
return stripped;
}
+14
View File
@@ -208,6 +208,20 @@ describe('chatJSON', async () => {
assert.deepEqual(result, [{ level: 'info' }]);
});
it('extracts JSON array from surrounding prose', async () => {
process.env.OPENAI_API_KEY = 'sk-test';
mockAxiosPost([makeOkResponse('**Reviewing findings**\n\n[{"level":"warning","suggestion":"x"}]\n\nDone.')]);
const result = await chatJSON('sys', 'user');
assert.deepEqual(result, [{ level: 'warning', suggestion: 'x' }]);
});
it('extracts JSON object from surrounding prose', async () => {
process.env.OPENAI_API_KEY = 'sk-test';
mockAxiosPost([makeOkResponse('**Begin Combine**\n{"merged_text":"repo block\\n\\nsource block"}')]);
const result = await chatJSON('sys', 'user');
assert.deepEqual(result, { merged_text: 'repo block\n\nsource block' });
});
it('returns [] when JSON is invalid', async () => {
process.env.OPENAI_API_KEY = 'sk-test';
mockAxiosPost([makeOkResponse('not json')]);