| ... | @@ -606,9 +606,24 @@ export const make = Effect.gen(function* () { | ... | @@ -606,9 +606,24 @@ export const make = Effect.gen(function* () { |
| 606 | const providerRegistry = yield* ProviderRegistry.ProviderRegistry; | 606 | const providerRegistry = yield* ProviderRegistry.ProviderRegistry; |
| 607 | const projectSetupScriptRunner = yield* ProjectSetupScriptRunner.ProjectSetupScriptRunner; | 607 | const projectSetupScriptRunner = yield* ProjectSetupScriptRunner.ProjectSetupScriptRunner; |
| 608 | const crypto = yield* Crypto.Crypto; | 608 | const crypto = yield* Crypto.Crypto; |
| | 609 | const fileSystem = yield* FileSystem.FileSystem; |
| | 610 | const path = yield* Path.Path; |
| 609 | | 611 | |
| 610 | const sourceControlProvider = (cwd: string) => sourceControlProviders.resolve({ cwd }); | 612 | const sourceControlProvider = (cwd: string) => sourceControlProviders.resolve({ cwd }); |
| 611 | const serverSettingsService = yield* ServerSettings.ServerSettingsService; | 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 | const readRecentCommitSubjects = (cwd: string) => | 628 | const readRecentCommitSubjects = (cwd: string) => |
| 614 | gitCore | 629 | gitCore |
| ... | @@ -627,26 +642,43 @@ export const make = Effect.gen(function* () { | ... | @@ -627,26 +642,43 @@ export const make = Effect.gen(function* () { |
| 627 | Effect.orElseSucceed(() => []), | 642 | Effect.orElseSucceed(() => []), |
| 628 | ); | 643 | ); |
| 629 | | 644 | |
| 630 | const resolveStylePolicy = (cwd: string, style: SourceControlWritingStyleSettings) => | 645 | const resolveStylePolicy = (cwd: string, settings: SourceControlTextGenerationSettings) => |
| 631 | Effect.gen(function* () { | 646 | Effect.gen(function* () { |
| 632 | switch (style.mode) { | 647 | switch (settings.style.mode) { |
| 633 | case "conventional_commits": | 648 | case "conventional_commits": |
| 634 | return conventionalCommitsTextGenerationPolicy; | 649 | return conventionalCommitsTextGenerationPolicy; |
| 635 | case "custom": | 650 | case "custom": |
| 636 | return customTextGenerationPolicy( | 651 | return customTextGenerationPolicy( |
| 637 | style.customInstructions | 652 | settings.style.customInstructions |
| 638 | ? { | 653 | ? { |
| 639 | commitInstructions: style.customInstructions, | 654 | commitInstructions: settings.style.customInstructions, |
| 640 | changeRequestInstructions: style.customInstructions, | 655 | changeRequestInstructions: settings.style.customInstructions, |
| 641 | } | 656 | } |
| 642 | : {}, | 657 | : {}, |
| 643 | ); | 658 | ); |
| 644 | case "repo_conventions": { | 659 | case "repo_conventions": { |
| 645 | const subjects = yield* readRecentCommitSubjects(cwd); | 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 | return repositoryConventionsTextGenerationPolicy; | 680 | return repositoryConventionsTextGenerationPolicy; |
| 648 | } | 681 | } |
| 649 | const examples = ["Recent commit subjects from this repository:", ...subjects].join("\n"); | | |
| 650 | return { | 682 | return { |
| 651 | ...repositoryConventionsTextGenerationPolicy, | 683 | ...repositoryConventionsTextGenerationPolicy, |
| 652 | commitInstructions: `${repositoryConventionsTextGenerationPolicy.commitInstructions}\n\n${examples}`, | 684 | commitInstructions: `${repositoryConventionsTextGenerationPolicy.commitInstructions}\n\n${examples}`, |
| ... | @@ -848,9 +880,6 @@ export const make = Effect.gen(function* () { | ... | @@ -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 | const tempDir = process.env.TMPDIR ?? process.env.TEMP ?? process.env.TMP ?? "/tmp"; | 883 | const tempDir = process.env.TMPDIR ?? process.env.TEMP ?? process.env.TMP ?? "/tmp"; |
| 855 | const canonicalizeExistingPath = (value: string) => | 884 | const canonicalizeExistingPath = (value: string) => |
| 856 | fileSystem.realPath(value).pipe(Effect.orElseSucceed(() => value)); | 885 | fileSystem.realPath(value).pipe(Effect.orElseSucceed(() => value)); |
| ... | @@ -1565,7 +1594,7 @@ export const make = Effect.gen(function* () { | ... | @@ -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 | const generated = yield* textGeneration | 1599 | const generated = yield* textGeneration |
| 1571 | .generateCommitMessage({ | 1600 | .generateCommitMessage({ |
| ... | @@ -1751,7 +1780,7 @@ export const make = Effect.gen(function* () { | ... | @@ -1751,7 +1780,7 @@ export const make = Effect.gen(function* () { |
| 1751 | }); | 1780 | }); |
| 1752 | const baseRangeRef = yield* resolveBaseRangeRef(cwd, baseBranch); | 1781 | const baseRangeRef = yield* resolveBaseRangeRef(cwd, baseBranch); |
| 1753 | const rangeContext = yield* gitCore.readRangeContext(cwd, baseRangeRef); | 1782 | const rangeContext = yield* gitCore.readRangeContext(cwd, baseRangeRef); |
| 1754 | const policy = yield* resolveStylePolicy(cwd, settings.style); | 1783 | const policy = yield* resolveStylePolicy(cwd, settings); |
| 1755 | const changeRequestTemplate = | 1784 | const changeRequestTemplate = |
| 1756 | settings.style.followChangeRequestTemplates && provider.kind === "github" | 1785 | settings.style.followChangeRequestTemplates && provider.kind === "github" |
| 1757 | ? Option.getOrUndefined(yield* detectPrTemplate(cwd, baseRangeRef, gitCore.execute)) | 1786 | ? Option.getOrUndefined(yield* detectPrTemplate(cwd, baseRangeRef, gitCore.execute)) |