ronds_ai 0.1.13 → 0.1.17
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/README.md +41 -21
- package/bin/ronds_ai.js +60 -8
- package/lib/code_record.js +177 -317
- package/lib/doctor.js +4 -2
- package/lib/hooks_deploy.js +604 -396
- package/package.json +1 -1
package/lib/code_record.js
CHANGED
|
@@ -1,25 +1,30 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
1
|
+
const fs = require('fs');
|
|
2
2
|
const os = require('os');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const http = require('http');
|
|
5
5
|
const https = require('https');
|
|
6
|
-
const { execFileSync } = require('child_process');
|
|
7
6
|
const { runGit } = require('./git');
|
|
8
|
-
const {
|
|
7
|
+
const { randomUUID } = require('crypto');
|
|
9
8
|
|
|
10
9
|
const DEFAULT_TIMEOUT_MS = 10000;
|
|
11
10
|
const MAX_ADDED_CONTENT_CHARS = 20000;
|
|
12
11
|
const DEFAULT_HOOK_REPORT_URL = 'https://aihub.ronds.com/api/api/v1/ai-code-events';
|
|
13
12
|
const CLAUDE_SUPPORTED_HOOK_EVENT = 'PostToolUse';
|
|
14
13
|
const CLAUDE_SUPPORTED_TOOLS = new Set(['Write', 'Edit', 'MultiEdit']);
|
|
15
|
-
const CURSOR_SUPPORTED_HOOK_EVENT = 'afterFileEdit';
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
const CURSOR_SUPPORTED_HOOK_EVENT = 'afterFileEdit';
|
|
15
|
+
const CODEX_SUPPORTED_HOOK_EVENT = 'PostToolUse';
|
|
16
|
+
const CODEX_SUPPORTED_TOOL = 'apply_patch';
|
|
17
|
+
|
|
18
|
+
// 构造 Codex PostToolUse hook 要求的标准输出,避免 stdout 出现 schema 之外的字段。
|
|
19
|
+
function buildCodexPostToolUseOutput() {
|
|
20
|
+
return {
|
|
21
|
+
continue: true,
|
|
22
|
+
suppressOutput: true,
|
|
23
|
+
hookSpecificOutput: {
|
|
24
|
+
hookEventName: CODEX_SUPPORTED_HOOK_EVENT,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
23
28
|
|
|
24
29
|
function readStdin() {
|
|
25
30
|
return new Promise((resolve, reject) => {
|
|
@@ -38,7 +43,9 @@ function parseJson(raw, label) {
|
|
|
38
43
|
return JSON.parse(raw);
|
|
39
44
|
} catch (error) {
|
|
40
45
|
const detail = error instanceof Error ? error.message : String(error);
|
|
41
|
-
|
|
46
|
+
const wrappedError = new Error(`${label} is not valid JSON: ${detail}`);
|
|
47
|
+
wrappedError.rawPayload = raw;
|
|
48
|
+
throw wrappedError;
|
|
42
49
|
}
|
|
43
50
|
}
|
|
44
51
|
|
|
@@ -426,303 +433,134 @@ function buildCursorEvent(payload, source) {
|
|
|
426
433
|
};
|
|
427
434
|
}
|
|
428
435
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
return
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
if (
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
const output = runGit(repoRoot, ['diff', '--name-only', `${normalizedFromRef}..${normalizedToRef}`], false);
|
|
543
|
-
return output.split('\n')
|
|
544
|
-
.map((line) => line.trim().replace(/\\/g, '/'))
|
|
545
|
-
.filter(Boolean);
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
function statesEqual(beforeState, afterState) {
|
|
549
|
-
return beforeState.exists === afterState.exists
|
|
550
|
-
&& beforeState.isBinary === afterState.isBinary
|
|
551
|
-
&& beforeState.content === afterState.content;
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
function buildCodexChange(beforeState, afterState) {
|
|
555
|
-
if (afterState.isBinary || beforeState.isBinary) {
|
|
556
|
-
const operation = beforeState.exists ? 'edit' : 'write';
|
|
557
|
-
return {
|
|
558
|
-
operation,
|
|
559
|
-
changes: {
|
|
560
|
-
added_content: '',
|
|
561
|
-
added: 0,
|
|
562
|
-
removed: 0,
|
|
563
|
-
},
|
|
564
|
-
};
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
const diff = diffLineStats(beforeState.content, afterState.content);
|
|
568
|
-
return {
|
|
569
|
-
operation: beforeState.exists ? 'edit' : 'write',
|
|
570
|
-
changes: {
|
|
571
|
-
added_content: diff.addedContent,
|
|
572
|
-
added: diff.added,
|
|
573
|
-
removed: diff.removed,
|
|
574
|
-
},
|
|
575
|
-
};
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
function cleanupStaleSnapshots() {
|
|
579
|
-
let entries;
|
|
580
|
-
try {
|
|
581
|
-
if (!fs.existsSync(CODEX_SNAPSHOT_DIR)) {
|
|
582
|
-
return;
|
|
583
|
-
}
|
|
584
|
-
entries = fs.readdirSync(CODEX_SNAPSHOT_DIR);
|
|
585
|
-
} catch {
|
|
586
|
-
return;
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
const nowSec = Date.now() / 1000;
|
|
590
|
-
for (const entry of entries) {
|
|
591
|
-
if (!entry.endsWith('.json')) {
|
|
592
|
-
continue;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
const filePath = path.join(CODEX_SNAPSHOT_DIR, entry);
|
|
596
|
-
try {
|
|
597
|
-
const raw = fs.readFileSync(filePath, 'utf8');
|
|
598
|
-
const snapshot = JSON.parse(raw);
|
|
599
|
-
const createdAt = String(snapshot.created_at || '');
|
|
600
|
-
const createdSec = new Date(createdAt).getTime() / 1000;
|
|
601
|
-
if (isNaN(createdSec)) {
|
|
602
|
-
continue;
|
|
603
|
-
}
|
|
604
|
-
if (nowSec - createdSec > CODEX_SNAPSHOT_TTL_SEC) {
|
|
605
|
-
fs.rmSync(filePath, { force: true });
|
|
606
|
-
}
|
|
607
|
-
} catch {
|
|
608
|
-
continue;
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
function handleCodexUserPromptSubmit(payload) {
|
|
614
|
-
const cwd = payload.cwd || process.cwd();
|
|
615
|
-
const repoRoot = findGitRepoRoot(cwd);
|
|
616
|
-
const snapshotPath = getCodexSnapshotFilePath(payload, repoRoot);
|
|
617
|
-
if (!repoRoot || !snapshotPath) {
|
|
618
|
-
return [];
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
const head = readCurrentHead(repoRoot);
|
|
622
|
-
const baseline = {};
|
|
623
|
-
for (const entry of parseGitStatus(repoRoot)) {
|
|
624
|
-
const absolutePath = path.join(repoRoot, entry.path);
|
|
625
|
-
baseline[entry.path] = entry.state === 'deleted'
|
|
626
|
-
? readHeadFileState(repoRoot, entry.path)
|
|
627
|
-
: readFileState(absolutePath);
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
cleanupStaleSnapshots();
|
|
631
|
-
fs.mkdirSync(CODEX_SNAPSHOT_DIR, { recursive: true });
|
|
632
|
-
fs.writeFileSync(snapshotPath, JSON.stringify({
|
|
633
|
-
version: 1,
|
|
634
|
-
session_id: payload.session_id || payload.sessionId || '',
|
|
635
|
-
turn_id: payload.turn_id || payload.turnId || '',
|
|
636
|
-
repo_root: repoRoot,
|
|
637
|
-
head,
|
|
638
|
-
created_at: new Date().toISOString(),
|
|
639
|
-
baseline,
|
|
640
|
-
}), 'utf8');
|
|
641
|
-
|
|
642
|
-
return [];
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
function buildCodexStopEvents(payload, source) {
|
|
646
|
-
const cwd = payload.cwd || process.cwd();
|
|
647
|
-
const repoRoot = findGitRepoRoot(cwd);
|
|
648
|
-
const snapshotPath = getCodexSnapshotFilePath(payload, repoRoot);
|
|
649
|
-
if (!repoRoot || !snapshotPath) {
|
|
650
|
-
return [];
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
let snapshot = null;
|
|
654
|
-
if (fs.existsSync(snapshotPath)) {
|
|
655
|
-
try {
|
|
656
|
-
snapshot = parseJson(fs.readFileSync(snapshotPath, 'utf8'), 'Codex snapshot');
|
|
657
|
-
} catch {
|
|
658
|
-
snapshot = null;
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
const baseline = snapshot && snapshot.baseline && typeof snapshot.baseline === 'object'
|
|
663
|
-
? snapshot.baseline
|
|
664
|
-
: {};
|
|
665
|
-
const currentEntries = parseGitStatus(repoRoot);
|
|
666
|
-
const currentPaths = new Set(currentEntries.map((entry) => entry.path));
|
|
667
|
-
const baseRef = snapshot && typeof snapshot.head === 'string' && snapshot.head.trim()
|
|
668
|
-
? snapshot.head.trim()
|
|
669
|
-
: 'HEAD';
|
|
670
|
-
const currentHead = readCurrentHead(repoRoot) || 'HEAD';
|
|
671
|
-
const committedPaths = new Set(parseGitDiffNameOnly(repoRoot, baseRef, currentHead));
|
|
672
|
-
const allPaths = new Set([
|
|
673
|
-
...Object.keys(baseline),
|
|
674
|
-
...currentPaths,
|
|
675
|
-
...committedPaths,
|
|
676
|
-
]);
|
|
677
|
-
const workerId = resolveWorkerId(repoRoot);
|
|
678
|
-
const git = resolveGitMetadata(repoRoot);
|
|
679
|
-
const events = [];
|
|
680
|
-
|
|
681
|
-
for (const repoRelativePath of allPaths) {
|
|
682
|
-
const absolutePath = path.join(repoRoot, repoRelativePath);
|
|
683
|
-
const beforeState = baseline[repoRelativePath] || readGitRefFileState(repoRoot, baseRef, repoRelativePath);
|
|
684
|
-
let afterState = readFileState(absolutePath);
|
|
685
|
-
if (!afterState.exists && committedPaths.has(repoRelativePath)) {
|
|
686
|
-
afterState = readGitRefFileState(repoRoot, currentHead, repoRelativePath);
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
if (statesEqual(beforeState, afterState)) {
|
|
690
|
-
continue;
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
const changeInfo = buildCodexChange(beforeState, afterState);
|
|
694
|
-
events.push({
|
|
695
|
-
event_id: randomUUID(),
|
|
696
|
-
timestamp: new Date().toISOString(),
|
|
697
|
-
source,
|
|
698
|
-
worker_id: workerId,
|
|
699
|
-
git,
|
|
700
|
-
file: {
|
|
701
|
-
path: repoRelativePath,
|
|
702
|
-
operation: changeInfo.operation,
|
|
703
|
-
},
|
|
704
|
-
changes: changeInfo.changes,
|
|
705
|
-
});
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
if (fs.existsSync(snapshotPath)) {
|
|
709
|
-
fs.rmSync(snapshotPath, { force: true });
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
return events;
|
|
713
|
-
}
|
|
436
|
+
// 从 Codex PostToolUse 的 apply_patch 命令中提取补丁正文。
|
|
437
|
+
function extractApplyPatchText(command) {
|
|
438
|
+
const rawCommand = String(command || '').replace(/\r\n/g, '\n');
|
|
439
|
+
const beginIndex = rawCommand.indexOf('*** Begin Patch');
|
|
440
|
+
const endIndex = rawCommand.indexOf('*** End Patch', beginIndex);
|
|
441
|
+
if (beginIndex === -1 || endIndex === -1) {
|
|
442
|
+
return '';
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return rawCommand.slice(beginIndex, endIndex + '*** End Patch'.length);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// 解析 apply_patch 文件头,返回变更类型和目标路径。
|
|
449
|
+
function parseApplyPatchHeader(line) {
|
|
450
|
+
const match = /^\*\*\* (Add|Update|Delete) File: (.+)$/.exec(line);
|
|
451
|
+
if (!match) {
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return {
|
|
456
|
+
action: match[1],
|
|
457
|
+
path: match[2].trim(),
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// 按文件聚合 apply_patch 中的新增/删除行,生成后续上报需要的变更摘要。
|
|
462
|
+
function parseApplyPatchFiles(patchText) {
|
|
463
|
+
const lines = String(patchText || '').replace(/\r\n/g, '\n').split('\n');
|
|
464
|
+
const files = [];
|
|
465
|
+
let current = null;
|
|
466
|
+
|
|
467
|
+
for (const line of lines) {
|
|
468
|
+
const header = parseApplyPatchHeader(line);
|
|
469
|
+
if (header) {
|
|
470
|
+
current = {
|
|
471
|
+
path: header.path,
|
|
472
|
+
action: header.action,
|
|
473
|
+
movedTo: '',
|
|
474
|
+
addedLines: [],
|
|
475
|
+
added: 0,
|
|
476
|
+
removed: 0,
|
|
477
|
+
};
|
|
478
|
+
files.push(current);
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (!current) {
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (line.startsWith('*** Move to: ')) {
|
|
487
|
+
current.movedTo = line.slice('*** Move to: '.length).trim();
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
if (line.startsWith('+++') || line.startsWith('---')) {
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (line.startsWith('+')) {
|
|
496
|
+
const addedLine = line.slice(1);
|
|
497
|
+
if (addedLine !== '') {
|
|
498
|
+
current.addedLines.push(addedLine);
|
|
499
|
+
current.added += 1;
|
|
500
|
+
}
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (line.startsWith('-')) {
|
|
505
|
+
if (line.slice(1) !== '') {
|
|
506
|
+
current.removed += 1;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
return files;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// 将 Codex apply_patch 的文件级变更转换为统一代码事件。
|
|
515
|
+
function buildCodexApplyPatchEvents(payload, source, patchFiles) {
|
|
516
|
+
const cwd = payload.cwd || process.cwd();
|
|
517
|
+
const events = [];
|
|
518
|
+
|
|
519
|
+
for (const fileChange of patchFiles) {
|
|
520
|
+
const eventPath = fileChange.movedTo || fileChange.path;
|
|
521
|
+
const absoluteFilePath = path.resolve(cwd, eventPath);
|
|
522
|
+
const { repoRoot, git, repoRelativePath } = getGitInfo(absoluteFilePath);
|
|
523
|
+
const workerId = resolveWorkerId(repoRoot);
|
|
524
|
+
let addedContent = fileChange.addedLines.join('\n');
|
|
525
|
+
if (addedContent.length > MAX_ADDED_CONTENT_CHARS) {
|
|
526
|
+
addedContent = `${addedContent.slice(0, MAX_ADDED_CONTENT_CHARS)}\n... (truncated)`;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
events.push({
|
|
530
|
+
event_id: randomUUID(),
|
|
531
|
+
timestamp: new Date().toISOString(),
|
|
532
|
+
source,
|
|
533
|
+
worker_id: workerId,
|
|
534
|
+
git,
|
|
535
|
+
file: {
|
|
536
|
+
path: repoRelativePath || eventPath.replace(/\\/g, '/'),
|
|
537
|
+
operation: fileChange.action === 'Add' ? 'write' : 'edit',
|
|
538
|
+
},
|
|
539
|
+
changes: {
|
|
540
|
+
added_content: addedContent,
|
|
541
|
+
added: fileChange.added,
|
|
542
|
+
removed: fileChange.removed,
|
|
543
|
+
},
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
return events;
|
|
548
|
+
}
|
|
714
549
|
|
|
715
550
|
function buildCodexEvents(payload, source) {
|
|
716
551
|
const hookEvent = payload.hook_event_name || payload.hookEvent;
|
|
717
|
-
|
|
552
|
+
const toolName = payload.tool_name || payload.toolName;
|
|
553
|
+
if (hookEvent !== CODEX_SUPPORTED_HOOK_EVENT || toolName !== CODEX_SUPPORTED_TOOL) {
|
|
718
554
|
return [];
|
|
719
555
|
}
|
|
720
556
|
|
|
721
|
-
|
|
722
|
-
|
|
557
|
+
const toolInput = payload.tool_input || payload.toolInput || {};
|
|
558
|
+
const patchText = extractApplyPatchText(toolInput.command);
|
|
559
|
+
if (!patchText) {
|
|
560
|
+
return [];
|
|
723
561
|
}
|
|
724
562
|
|
|
725
|
-
return
|
|
563
|
+
return buildCodexApplyPatchEvents(payload, source, parseApplyPatchFiles(patchText));
|
|
726
564
|
}
|
|
727
565
|
|
|
728
566
|
function loadRequestConfig() {
|
|
@@ -790,14 +628,23 @@ function saveCliError(error, context = {}) {
|
|
|
790
628
|
error: errorMessage,
|
|
791
629
|
context,
|
|
792
630
|
};
|
|
631
|
+
|
|
632
|
+
if (error && typeof error.rawPayload === 'string') {
|
|
633
|
+
record.raw_payload = error.rawPayload;
|
|
634
|
+
}
|
|
635
|
+
|
|
793
636
|
return appendFailedRecord('cli', record, timestamp);
|
|
794
637
|
}
|
|
795
638
|
|
|
796
|
-
function sendJsonRequest(event, config) {
|
|
797
|
-
if (process.env.HOOK_REQUEST_DRY_RUN === '1') {
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
639
|
+
function sendJsonRequest(event, config) {
|
|
640
|
+
if (process.env.HOOK_REQUEST_DRY_RUN === '1') {
|
|
641
|
+
return Promise.resolve({
|
|
642
|
+
statusCode: 0,
|
|
643
|
+
body: 'dry-run',
|
|
644
|
+
dryRun: true,
|
|
645
|
+
event,
|
|
646
|
+
});
|
|
647
|
+
}
|
|
801
648
|
|
|
802
649
|
if (!config.url) {
|
|
803
650
|
return Promise.reject(new Error('Missing request URL'));
|
|
@@ -878,9 +725,19 @@ async function runCodeRecord(source) {
|
|
|
878
725
|
return;
|
|
879
726
|
}
|
|
880
727
|
|
|
881
|
-
|
|
728
|
+
let payload;
|
|
729
|
+
try {
|
|
730
|
+
payload = JSON.parse(raw);
|
|
731
|
+
} catch (parseError) {
|
|
732
|
+
const message = parseError instanceof Error ? parseError.message : String(parseError || '');
|
|
733
|
+
const dumpPath = path.join(os.homedir(), '.ronds_ai', `hook-payload-${Date.now()}.txt`);
|
|
734
|
+
try {
|
|
735
|
+
fs.mkdirSync(path.dirname(dumpPath), { recursive: true });
|
|
736
|
+
fs.writeFileSync(dumpPath, raw, 'utf8');
|
|
737
|
+
} catch { /* best effort */ }
|
|
738
|
+
throw new Error(`Hook payload is not valid JSON: ${message}\nRaw payload dumped to ${dumpPath}`);
|
|
739
|
+
}
|
|
882
740
|
const events = buildEvents(payload, source);
|
|
883
|
-
const hookEvent = payload.hook_event_name || payload.hookEvent;
|
|
884
741
|
const config = loadRequestConfig();
|
|
885
742
|
|
|
886
743
|
const results = [];
|
|
@@ -902,15 +759,18 @@ async function runCodeRecord(source) {
|
|
|
902
759
|
}
|
|
903
760
|
}
|
|
904
761
|
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
762
|
+
for (const result of results) {
|
|
763
|
+
if (source === 'codex') {
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
if (source === 'codex') {
|
|
771
|
+
process.stdout.write(`${JSON.stringify(buildCodexPostToolUseOutput())}\n`);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
914
774
|
|
|
915
775
|
module.exports = {
|
|
916
776
|
runCodeRecord,
|
package/lib/doctor.js
CHANGED
|
@@ -36,8 +36,10 @@ function getConfigChecks(tool, baseDir) {
|
|
|
36
36
|
if (tool === 'codex') {
|
|
37
37
|
return [
|
|
38
38
|
{
|
|
39
|
-
label: '.
|
|
40
|
-
path:
|
|
39
|
+
label: 'Codex requirements.toml',
|
|
40
|
+
path: process.platform === 'win32'
|
|
41
|
+
? 'C:\\ProgramData\\OpenAI\\Codex\\requirements.toml'
|
|
42
|
+
: '/etc/codex/requirements.toml',
|
|
41
43
|
},
|
|
42
44
|
];
|
|
43
45
|
}
|