claude-coder 1.0.4 → 1.0.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-coder",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Claude Coder — Autonomous coding agent harness powered by Claude Code SDK. Scan, plan, code, validate, git-commit in a loop.",
5
5
  "bin": {
6
6
  "claude-coder": "bin/cli.js"
package/src/prompts.js CHANGED
@@ -4,8 +4,14 @@ const fs = require('fs');
4
4
  const { paths, loadConfig, getRequirementsHash } = require('./config');
5
5
  const { loadTasks, findNextTask, getStats } = require('./tasks');
6
6
 
7
- function normalizeJson(text) {
8
- return text.replace(/[\u201c\u201d]/g, '"').replace(/[\u2018\u2019]/g, "'");
7
+ function safeJsonParse(text) {
8
+ try {
9
+ return JSON.parse(text);
10
+ } catch {
11
+ return JSON.parse(
12
+ text.replace(/[\u201c\u201d]/g, '"').replace(/[\u2018\u2019]/g, "'")
13
+ );
14
+ }
9
15
  }
10
16
 
11
17
  /**
@@ -104,7 +110,7 @@ function buildCodingPrompt(sessionNum, opts = {}) {
104
110
  let memoryHint = '';
105
111
  if (fs.existsSync(p.sessionResult)) {
106
112
  try {
107
- const sr = JSON.parse(normalizeJson(fs.readFileSync(p.sessionResult, 'utf8')));
113
+ const sr = safeJsonParse(fs.readFileSync(p.sessionResult, 'utf8'));
108
114
  const last = sr.current || (sr.history?.length ? sr.history[sr.history.length - 1] : null);
109
115
  if (last?.task_id) {
110
116
  memoryHint = `上次会话: ${last.task_id} → ${last.status_after || last.session_result}` +
package/src/runner.js CHANGED
@@ -100,7 +100,10 @@ function appendProgress(entry) {
100
100
  const p = paths();
101
101
  let progress = { sessions: [] };
102
102
  if (fs.existsSync(p.progressFile)) {
103
- try { progress = JSON.parse(fs.readFileSync(p.progressFile, 'utf8').replace(/[\u201c\u201d]/g, '"')); } catch { /* reset */ }
103
+ try {
104
+ const text = fs.readFileSync(p.progressFile, 'utf8');
105
+ try { progress = JSON.parse(text); } catch { progress = JSON.parse(text.replace(/[\u201c\u201d]/g, '"')); }
106
+ } catch { /* reset */ }
104
107
  }
105
108
  if (!Array.isArray(progress.sessions)) progress.sessions = [];
106
109
  progress.sessions.push(entry);
@@ -111,7 +114,10 @@ function updateSessionHistory(sessionData, sessionNum) {
111
114
  const p = paths();
112
115
  let sr = { current: null, history: [] };
113
116
  if (fs.existsSync(p.sessionResult)) {
114
- try { sr = JSON.parse(fs.readFileSync(p.sessionResult, 'utf8').replace(/[\u201c\u201d]/g, '"')); } catch { /* reset */ }
117
+ try {
118
+ const text = fs.readFileSync(p.sessionResult, 'utf8');
119
+ try { sr = JSON.parse(text); } catch { sr = JSON.parse(text.replace(/[\u201c\u201d]/g, '"')); }
120
+ } catch { /* reset */ }
115
121
  if (!sr.history && sr.session_result) {
116
122
  sr = { current: sr, history: [] };
117
123
  }
package/src/tasks.js CHANGED
@@ -13,16 +13,20 @@ const TRANSITIONS = {
13
13
  done: [],
14
14
  };
15
15
 
16
- function normalizeJson(text) {
17
- return text
18
- .replace(/[\u201c\u201d]/g, '"')
19
- .replace(/[\u2018\u2019]/g, "'");
16
+ function safeJsonParse(text) {
17
+ try {
18
+ return JSON.parse(text);
19
+ } catch {
20
+ return JSON.parse(
21
+ text.replace(/[\u201c\u201d]/g, '"').replace(/[\u2018\u2019]/g, "'")
22
+ );
23
+ }
20
24
  }
21
25
 
22
26
  function loadTasks() {
23
27
  const p = paths();
24
28
  if (!fs.existsSync(p.tasksFile)) return null;
25
- return JSON.parse(normalizeJson(fs.readFileSync(p.tasksFile, 'utf8')));
29
+ return safeJsonParse(fs.readFileSync(p.tasksFile, 'utf8'));
26
30
  }
27
31
 
28
32
  function saveTasks(data) {
package/src/validator.js CHANGED
@@ -4,8 +4,14 @@ const fs = require('fs');
4
4
  const { execSync } = require('child_process');
5
5
  const { paths, log, getProjectRoot } = require('./config');
6
6
 
7
- function normalizeJson(text) {
8
- return text.replace(/[\u201c\u201d]/g, '"').replace(/[\u2018\u2019]/g, "'");
7
+ function safeJsonParse(text) {
8
+ try {
9
+ return JSON.parse(text);
10
+ } catch {
11
+ return JSON.parse(
12
+ text.replace(/[\u201c\u201d]/g, '"').replace(/[\u2018\u2019]/g, "'")
13
+ );
14
+ }
9
15
  }
10
16
 
11
17
  function validateSessionResult() {
@@ -18,7 +24,7 @@ function validateSessionResult() {
18
24
 
19
25
  let data;
20
26
  try {
21
- data = JSON.parse(normalizeJson(fs.readFileSync(p.sessionResult, 'utf8')));
27
+ data = safeJsonParse(fs.readFileSync(p.sessionResult, 'utf8'));
22
28
  } catch {
23
29
  log('error', 'session_result.json JSON 格式错误');
24
30
  return { valid: false, fatal: true, reason: 'JSON 格式错误' };
@@ -90,9 +96,9 @@ function checkTestCoverage() {
90
96
  if (!fs.existsSync(p.testsFile) || !fs.existsSync(p.sessionResult)) return;
91
97
 
92
98
  try {
93
- const sr = JSON.parse(normalizeJson(fs.readFileSync(p.sessionResult, 'utf8')));
99
+ const sr = safeJsonParse(fs.readFileSync(p.sessionResult, 'utf8'));
94
100
  const current = sr.current || sr;
95
- const tests = JSON.parse(normalizeJson(fs.readFileSync(p.testsFile, 'utf8')));
101
+ const tests = safeJsonParse(fs.readFileSync(p.testsFile, 'utf8'));
96
102
 
97
103
  const taskId = current.task_id || '';
98
104
  const testCases = tests.test_cases || [];