| ... | ... | @@ -606,9 +606,24 @@ export const make = Effect.gen(function* () { |
| 606 | 606 | const providerRegistry = yield* ProviderRegistry.ProviderRegistry; |
| 607 | 607 | const projectSetupScriptRunner = yield* ProjectSetupScriptRunner.ProjectSetupScriptRunner; |
| 608 | 608 | const crypto = yield* Crypto.Crypto; |
| 609 | const fileSystem = yield* FileSystem.FileSystem; |
| 610 | const path = yield* Path.Path; |
| 609 | 611 | |
| 610 | 612 | const sourceControlProvider = (cwd: string) => sourceControlProviders.resolve({ cwd }); |
| 611 | 613 | const serverSettingsService = yield* ServerSettings.ServerSettingsService; |
| 614 | const readRepositoryInstructions = (cwd: string, fileName: string) => |
| 615 | Effect.gen(function* () { |
| 616 | const root = yield* fileSystem.realPath(cwd); |
| 617 | const instructionPath = yield* fileSystem.realPath(path.join(root, fileName)); |
| 618 | if (!instructionPath.startsWith(`${root}${path.sep}`)) { |
| 619 | return ""; |
| 620 | } |
| 621 | const info = yield* fileSystem.stat(instructionPath); |
| 622 | if (info.type !== "File" || info.size > FileSystem.Size(20_000)) { |
| 623 | return ""; |
| 624 | } |
| 625 | return (yield* fileSystem.readFileString(instructionPath)).trim(); |
| 626 | }).pipe(Effect.orElseSucceed(() => "")); |
| 612 | 627 | |
| 613 | 628 | const readRecentCommitSubjects = (cwd: string) => |
| 614 | 629 | gitCore |
| ... | ... | @@ -627,26 +642,43 @@ export const make = Effect.gen(function* () { |
| 627 | 642 | Effect.orElseSucceed(() => []), |
| 628 | 643 | ); |
| 629 | 644 | |
| 630 | | const resolveStylePolicy = (cwd: string, style: SourceControlWritingStyleSettings) => |
| 645 | const resolveStylePolicy = (cwd: string, settings: SourceControlTextGenerationSettings) => |
| 631 | 646 | Effect.gen(function* () { |
| 632 | | switch (style.mode) { |
| 647 | switch (settings.style.mode) { |
| 633 | 648 | case "conventional_commits": |
| 634 | 649 | return conventionalCommitsTextGenerationPolicy; |
| 635 | 650 | case "custom": |
| 636 | 651 | return customTextGenerationPolicy( |
| 637 | | style.customInstructions |
| 652 | settings.style.customInstructions |
| 638 | 653 | ? { |
| 639 | | commitInstructions: style.customInstructions, |
| 640 | | changeRequestInstructions: style.customInstructions, |
| 654 | commitInstructions: settings.style.customInstructions, |
| 655 | changeRequestInstructions: settings.style.customInstructions, |
| 641 | 656 | } |
| 642 | 657 | : {}, |
| 643 | 658 | ); |
| 644 | 659 | case "repo_conventions": { |
| 645 | 660 | const subjects = yield* readRecentCommitSubjects(cwd); |
| 646 | | if (subjects.length === 0) { |
| 661 | const agentInstructions = yield* readRepositoryInstructions(cwd, "AGENTS.md"); |
| 662 | const isClaudeWriter = |
| 663 | settings.modelSelection.instanceId === "claudeAgent" || |
| 664 | (yield* providerRegistry.getProviders).some( |
| 665 | (provider) => |
| 666 | provider.instanceId === settings.modelSelection.instanceId && |
| 667 | provider.driver === "claudeAgent", |
| 668 | ); |
| 669 | const claudeInstructions = isClaudeWriter |
| 670 | ? yield* readRepositoryInstructions(cwd, "CLAUDE.md") |
| 671 | : ""; |
| 672 | const examples = [ |
| 673 | ...(subjects.length > 0 |
| 674 | ? [["Recent commit subjects from this repository:", ...subjects].join("\n")] |
| 675 | : []), |
| 676 | ...(agentInstructions ? [`Local AGENTS.md:\n${agentInstructions}`] : []), |
| 677 | ...(claudeInstructions ? [`Local CLAUDE.md:\n${claudeInstructions}`] : []), |
| 678 | ].join("\n\n"); |
| 679 | if (!examples) { |
| 647 | 680 | return repositoryConventionsTextGenerationPolicy; |
| 648 | 681 | } |
| 649 | | const examples = ["Recent commit subjects from this repository:", ...subjects].join("\n"); |
| 650 | 682 | return { |
| 651 | 683 | ...repositoryConventionsTextGenerationPolicy, |
| 652 | 684 | commitInstructions: `${repositoryConventionsTextGenerationPolicy.commitInstructions}\n\n${examples}`, |
| ... | ... | @@ -848,9 +880,6 @@ export const make = Effect.gen(function* () { |
| 848 | 880 | ), |
| 849 | 881 | ), |
| 850 | 882 | ); |
| 851 | | const fileSystem = yield* FileSystem.FileSystem; |
| 852 | | const path = yield* Path.Path; |
| 853 | | |
| 854 | 883 | const tempDir = process.env.TMPDIR ?? process.env.TEMP ?? process.env.TMP ?? "/tmp"; |
| 855 | 884 | const canonicalizeExistingPath = (value: string) => |
| 856 | 885 | fileSystem.realPath(value).pipe(Effect.orElseSucceed(() => value)); |
| ... | ... | @@ -1565,7 +1594,7 @@ export const make = Effect.gen(function* () { |
| 1565 | 1594 | }; |
| 1566 | 1595 | } |
| 1567 | 1596 | |
| 1568 | | const policy = yield* resolveStylePolicy(input.cwd, input.settings.style); |
| 1597 | const policy = yield* resolveStylePolicy(input.cwd, input.settings); |
| 1569 | 1598 | |
| 1570 | 1599 | const generated = yield* textGeneration |
| 1571 | 1600 | .generateCommitMessage({ |
| ... | ... | @@ -1751,7 +1780,7 @@ export const make = Effect.gen(function* () { |
| 1751 | 1780 | }); |
| 1752 | 1781 | const baseRangeRef = yield* resolveBaseRangeRef(cwd, baseBranch); |
| 1753 | 1782 | const rangeContext = yield* gitCore.readRangeContext(cwd, baseRangeRef); |
| 1754 | | const policy = yield* resolveStylePolicy(cwd, settings.style); |
| 1783 | const policy = yield* resolveStylePolicy(cwd, settings); |
| 1755 | 1784 | const changeRequestTemplate = |
| 1756 | 1785 | settings.style.followChangeRequestTemplates && provider.kind === "github" |
| 1757 | 1786 | ? Option.getOrUndefined(yield* detectPrTemplate(cwd, baseRangeRef, gitCore.execute)) |