github-issue-tower-defence-management 1.55.0 → 1.56.1
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/CHANGELOG.md +14 -0
- package/README.md +23 -0
- package/bin/adapter/entry-points/cli/index.js +3 -1
- package/bin/adapter/entry-points/cli/index.js.map +1 -1
- package/bin/adapter/entry-points/cli/projectConfig.js +5 -0
- package/bin/adapter/entry-points/cli/projectConfig.js.map +1 -1
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +3 -1
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
- package/bin/adapter/proxy/RateLimitCache.js +123 -0
- package/bin/adapter/proxy/RateLimitCache.js.map +1 -0
- package/bin/adapter/proxy/TokenListLoader.js +72 -0
- package/bin/adapter/proxy/TokenListLoader.js.map +1 -0
- package/bin/adapter/proxy/ensureProxyRunning.js +73 -0
- package/bin/adapter/proxy/ensureProxyRunning.js.map +1 -0
- package/bin/adapter/proxy/proxyEntry.js +96 -0
- package/bin/adapter/proxy/proxyEntry.js.map +1 -0
- package/bin/adapter/repositories/NodeLocalCommandRunner.js +10 -4
- package/bin/adapter/repositories/NodeLocalCommandRunner.js.map +1 -1
- package/bin/adapter/repositories/OauthProxyClaudeRepository.js +3 -0
- package/bin/adapter/repositories/OauthProxyClaudeRepository.js.map +1 -1
- package/bin/adapter/repositories/ProxyClaudeTokenUsageRepository.js +35 -0
- package/bin/adapter/repositories/ProxyClaudeTokenUsageRepository.js.map +1 -0
- package/bin/domain/entities/ClaudeTokenUsage.js +3 -0
- package/bin/domain/entities/ClaudeTokenUsage.js.map +1 -0
- package/bin/domain/usecases/StartPreparationUseCase.js +26 -2
- package/bin/domain/usecases/StartPreparationUseCase.js.map +1 -1
- package/bin/domain/usecases/adapter-interfaces/ClaudeTokenUsageRepository.js +3 -0
- package/bin/domain/usecases/adapter-interfaces/ClaudeTokenUsageRepository.js.map +1 -0
- package/package.json +1 -1
- package/src/adapter/entry-points/cli/index.ts +5 -0
- package/src/adapter/entry-points/cli/projectConfig.ts +13 -0
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +5 -0
- package/src/adapter/proxy/RateLimitCache.test.ts +131 -0
- package/src/adapter/proxy/RateLimitCache.ts +112 -0
- package/src/adapter/proxy/TokenListLoader.test.ts +82 -0
- package/src/adapter/proxy/TokenListLoader.ts +35 -0
- package/src/adapter/proxy/ensureProxyRunning.test.ts +85 -0
- package/src/adapter/proxy/ensureProxyRunning.ts +41 -0
- package/src/adapter/proxy/proxyEntry.test.ts +48 -0
- package/src/adapter/proxy/proxyEntry.ts +69 -0
- package/src/adapter/repositories/NodeLocalCommandRunner.test.ts +3 -1
- package/src/adapter/repositories/NodeLocalCommandRunner.ts +18 -4
- package/src/adapter/repositories/OauthProxyClaudeRepository.test.ts +29 -0
- package/src/adapter/repositories/OauthProxyClaudeRepository.ts +5 -0
- package/src/adapter/repositories/ProxyClaudeTokenUsageRepository.test.ts +127 -0
- package/src/adapter/repositories/ProxyClaudeTokenUsageRepository.ts +36 -0
- package/src/domain/entities/ClaudeTokenUsage.ts +5 -0
- package/src/domain/usecases/StartPreparationUseCase.test.ts +308 -0
- package/src/domain/usecases/StartPreparationUseCase.ts +37 -1
- package/src/domain/usecases/adapter-interfaces/ClaudeTokenUsageRepository.ts +7 -0
- package/src/domain/usecases/adapter-interfaces/LocalCommandRunner.ts +5 -0
- package/types/adapter/entry-points/cli/index.d.ts.map +1 -1
- package/types/adapter/entry-points/cli/projectConfig.d.ts +1 -0
- package/types/adapter/entry-points/cli/projectConfig.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
- package/types/adapter/proxy/RateLimitCache.d.ts +14 -0
- package/types/adapter/proxy/RateLimitCache.d.ts.map +1 -0
- package/types/adapter/proxy/TokenListLoader.d.ts +2 -0
- package/types/adapter/proxy/TokenListLoader.d.ts.map +1 -0
- package/types/adapter/proxy/ensureProxyRunning.d.ts +2 -0
- package/types/adapter/proxy/ensureProxyRunning.d.ts.map +1 -0
- package/types/adapter/proxy/proxyEntry.d.ts +4 -0
- package/types/adapter/proxy/proxyEntry.d.ts.map +1 -0
- package/types/adapter/repositories/NodeLocalCommandRunner.d.ts +2 -2
- package/types/adapter/repositories/NodeLocalCommandRunner.d.ts.map +1 -1
- package/types/adapter/repositories/OauthProxyClaudeRepository.d.ts.map +1 -1
- package/types/adapter/repositories/ProxyClaudeTokenUsageRepository.d.ts +11 -0
- package/types/adapter/repositories/ProxyClaudeTokenUsageRepository.d.ts.map +1 -0
- package/types/domain/entities/ClaudeTokenUsage.d.ts +6 -0
- package/types/domain/entities/ClaudeTokenUsage.d.ts.map +1 -0
- package/types/domain/usecases/StartPreparationUseCase.d.ts +4 -1
- package/types/domain/usecases/StartPreparationUseCase.d.ts.map +1 -1
- package/types/domain/usecases/adapter-interfaces/ClaudeTokenUsageRepository.d.ts +7 -0
- package/types/domain/usecases/adapter-interfaces/ClaudeTokenUsageRepository.d.ts.map +1 -0
- package/types/domain/usecases/adapter-interfaces/LocalCommandRunner.d.ts +4 -1
- package/types/domain/usecases/adapter-interfaces/LocalCommandRunner.d.ts.map +1 -1
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
import { ProjectRepository } from './adapter-interfaces/ProjectRepository';
|
|
7
7
|
import { LocalCommandRunner } from './adapter-interfaces/LocalCommandRunner';
|
|
8
8
|
import { ClaudeRepository } from './adapter-interfaces/ClaudeRepository';
|
|
9
|
+
import { ClaudeTokenUsageRepository } from './adapter-interfaces/ClaudeTokenUsageRepository';
|
|
9
10
|
import { Issue } from '../entities/Issue';
|
|
10
11
|
import { Project } from '../entities/Project';
|
|
11
12
|
import { StoryObjectMap } from '../entities/StoryObjectMap';
|
|
@@ -92,6 +93,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
92
93
|
>;
|
|
93
94
|
let mockClaudeRepository: Mocked<Pick<ClaudeRepository, 'getUsage'>>;
|
|
94
95
|
let mockLocalCommandRunner: Mocked<LocalCommandRunner>;
|
|
96
|
+
let mockClaudeTokenUsageRepository: Mocked<ClaudeTokenUsageRepository>;
|
|
95
97
|
let mockProject: Project;
|
|
96
98
|
beforeEach(() => {
|
|
97
99
|
jest.resetAllMocks();
|
|
@@ -114,11 +116,17 @@ describe('StartPreparationUseCase', () => {
|
|
|
114
116
|
mockLocalCommandRunner = {
|
|
115
117
|
runCommand: jest.fn(),
|
|
116
118
|
};
|
|
119
|
+
mockClaudeTokenUsageRepository = {
|
|
120
|
+
ensureObservable: jest.fn().mockResolvedValue(undefined),
|
|
121
|
+
getAvailableTokenUsages: jest.fn().mockResolvedValue([]),
|
|
122
|
+
proxyBaseUrl: jest.fn().mockReturnValue('http://127.0.0.1:8787'),
|
|
123
|
+
};
|
|
117
124
|
useCase = new StartPreparationUseCase(
|
|
118
125
|
mockProjectRepository,
|
|
119
126
|
mockIssueRepository,
|
|
120
127
|
mockClaudeRepository,
|
|
121
128
|
mockLocalCommandRunner,
|
|
129
|
+
mockClaudeTokenUsageRepository,
|
|
122
130
|
);
|
|
123
131
|
});
|
|
124
132
|
it('should run aw command for awaiting workspace issues', async () => {
|
|
@@ -2516,4 +2524,304 @@ describe('StartPreparationUseCase', () => {
|
|
|
2516
2524
|
url: 'https://github.com/user/repo/issues/2',
|
|
2517
2525
|
});
|
|
2518
2526
|
});
|
|
2527
|
+
|
|
2528
|
+
it('should pass CLAUDE_CODE_OAUTH_TOKEN and ANTHROPIC_BASE_URL to runCommand when tokens are available', async () => {
|
|
2529
|
+
const awaitingIssue = createMockIssue({
|
|
2530
|
+
url: 'url1',
|
|
2531
|
+
title: 'Issue 1',
|
|
2532
|
+
labels: ['category:impl'],
|
|
2533
|
+
status: 'Awaiting Workspace',
|
|
2534
|
+
number: 1,
|
|
2535
|
+
itemId: 'item-1',
|
|
2536
|
+
});
|
|
2537
|
+
mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
|
|
2538
|
+
mockIssueRepository.getStoryObjectMap.mockResolvedValue(
|
|
2539
|
+
createMockStoryObjectMap([awaitingIssue]),
|
|
2540
|
+
);
|
|
2541
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
2542
|
+
stdout: '',
|
|
2543
|
+
stderr: '',
|
|
2544
|
+
exitCode: 0,
|
|
2545
|
+
});
|
|
2546
|
+
mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue([
|
|
2547
|
+
{ token: 'token-a', fiveHourUtilization: 0, blocked: false },
|
|
2548
|
+
]);
|
|
2549
|
+
|
|
2550
|
+
await useCase.run({
|
|
2551
|
+
projectUrl: 'https://github.com/user/repo',
|
|
2552
|
+
defaultAgentName: 'agent1',
|
|
2553
|
+
defaultLlmModelName: 'claude-opus',
|
|
2554
|
+
defaultLlmAgentName: null,
|
|
2555
|
+
configFilePath: '/path/to/config.yml',
|
|
2556
|
+
maximumPreparingIssuesCount: null,
|
|
2557
|
+
utilizationPercentageThreshold: 90,
|
|
2558
|
+
allowedIssueAuthors: null,
|
|
2559
|
+
codexHomeCandidates: null,
|
|
2560
|
+
allowIssueCacheMinutes: 0,
|
|
2561
|
+
});
|
|
2562
|
+
|
|
2563
|
+
expect(
|
|
2564
|
+
mockClaudeTokenUsageRepository.getAvailableTokenUsages.mock.calls,
|
|
2565
|
+
).toHaveLength(1);
|
|
2566
|
+
expect(
|
|
2567
|
+
mockClaudeTokenUsageRepository.ensureObservable.mock.calls,
|
|
2568
|
+
).toHaveLength(1);
|
|
2569
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(1);
|
|
2570
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls[0][2]).toEqual({
|
|
2571
|
+
env: {
|
|
2572
|
+
CLAUDE_CODE_OAUTH_TOKEN: 'token-a',
|
|
2573
|
+
ANTHROPIC_BASE_URL: 'http://127.0.0.1:8787',
|
|
2574
|
+
},
|
|
2575
|
+
});
|
|
2576
|
+
});
|
|
2577
|
+
|
|
2578
|
+
it('should rotate Claude OAuth tokens round-robin across multiple awaiting issues', async () => {
|
|
2579
|
+
const awaitingIssues: Issue[] = [
|
|
2580
|
+
createMockIssue({
|
|
2581
|
+
url: 'url1',
|
|
2582
|
+
title: 'Issue 1',
|
|
2583
|
+
labels: ['category:impl'],
|
|
2584
|
+
status: 'Awaiting Workspace',
|
|
2585
|
+
number: 1,
|
|
2586
|
+
itemId: 'item-1',
|
|
2587
|
+
}),
|
|
2588
|
+
createMockIssue({
|
|
2589
|
+
url: 'url2',
|
|
2590
|
+
title: 'Issue 2',
|
|
2591
|
+
labels: ['category:impl'],
|
|
2592
|
+
status: 'Awaiting Workspace',
|
|
2593
|
+
number: 2,
|
|
2594
|
+
itemId: 'item-2',
|
|
2595
|
+
}),
|
|
2596
|
+
createMockIssue({
|
|
2597
|
+
url: 'url3',
|
|
2598
|
+
title: 'Issue 3',
|
|
2599
|
+
labels: ['category:impl'],
|
|
2600
|
+
status: 'Awaiting Workspace',
|
|
2601
|
+
number: 3,
|
|
2602
|
+
itemId: 'item-3',
|
|
2603
|
+
}),
|
|
2604
|
+
];
|
|
2605
|
+
mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
|
|
2606
|
+
mockIssueRepository.getStoryObjectMap.mockResolvedValue(
|
|
2607
|
+
createMockStoryObjectMap(awaitingIssues),
|
|
2608
|
+
);
|
|
2609
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
2610
|
+
stdout: '',
|
|
2611
|
+
stderr: '',
|
|
2612
|
+
exitCode: 0,
|
|
2613
|
+
});
|
|
2614
|
+
mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue([
|
|
2615
|
+
{ token: 'token-a', fiveHourUtilization: 0, blocked: false },
|
|
2616
|
+
{ token: 'token-b', fiveHourUtilization: 0, blocked: false },
|
|
2617
|
+
]);
|
|
2618
|
+
|
|
2619
|
+
await useCase.run({
|
|
2620
|
+
projectUrl: 'https://github.com/user/repo',
|
|
2621
|
+
defaultAgentName: 'agent1',
|
|
2622
|
+
defaultLlmModelName: 'claude-opus',
|
|
2623
|
+
defaultLlmAgentName: null,
|
|
2624
|
+
configFilePath: '/path/to/config.yml',
|
|
2625
|
+
maximumPreparingIssuesCount: null,
|
|
2626
|
+
utilizationPercentageThreshold: 90,
|
|
2627
|
+
allowedIssueAuthors: null,
|
|
2628
|
+
codexHomeCandidates: null,
|
|
2629
|
+
allowIssueCacheMinutes: 0,
|
|
2630
|
+
});
|
|
2631
|
+
|
|
2632
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(3);
|
|
2633
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls[0][2]).toMatchObject({
|
|
2634
|
+
env: {
|
|
2635
|
+
CLAUDE_CODE_OAUTH_TOKEN: 'token-a',
|
|
2636
|
+
ANTHROPIC_BASE_URL: 'http://127.0.0.1:8787',
|
|
2637
|
+
},
|
|
2638
|
+
});
|
|
2639
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls[1][2]).toMatchObject({
|
|
2640
|
+
env: {
|
|
2641
|
+
CLAUDE_CODE_OAUTH_TOKEN: 'token-b',
|
|
2642
|
+
ANTHROPIC_BASE_URL: 'http://127.0.0.1:8787',
|
|
2643
|
+
},
|
|
2644
|
+
});
|
|
2645
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls[2][2]).toMatchObject({
|
|
2646
|
+
env: {
|
|
2647
|
+
CLAUDE_CODE_OAUTH_TOKEN: 'token-a',
|
|
2648
|
+
ANTHROPIC_BASE_URL: 'http://127.0.0.1:8787',
|
|
2649
|
+
},
|
|
2650
|
+
});
|
|
2651
|
+
});
|
|
2652
|
+
|
|
2653
|
+
it('should not inject env when no tokens are available', async () => {
|
|
2654
|
+
const awaitingIssue = createMockIssue({
|
|
2655
|
+
url: 'url1',
|
|
2656
|
+
title: 'Issue 1',
|
|
2657
|
+
labels: ['category:impl'],
|
|
2658
|
+
status: 'Awaiting Workspace',
|
|
2659
|
+
number: 1,
|
|
2660
|
+
itemId: 'item-1',
|
|
2661
|
+
});
|
|
2662
|
+
mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
|
|
2663
|
+
mockIssueRepository.getStoryObjectMap.mockResolvedValue(
|
|
2664
|
+
createMockStoryObjectMap([awaitingIssue]),
|
|
2665
|
+
);
|
|
2666
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
2667
|
+
stdout: '',
|
|
2668
|
+
stderr: '',
|
|
2669
|
+
exitCode: 0,
|
|
2670
|
+
});
|
|
2671
|
+
mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue(
|
|
2672
|
+
[],
|
|
2673
|
+
);
|
|
2674
|
+
|
|
2675
|
+
await useCase.run({
|
|
2676
|
+
projectUrl: 'https://github.com/user/repo',
|
|
2677
|
+
defaultAgentName: 'agent1',
|
|
2678
|
+
defaultLlmModelName: 'claude-opus',
|
|
2679
|
+
defaultLlmAgentName: null,
|
|
2680
|
+
configFilePath: '/path/to/config.yml',
|
|
2681
|
+
maximumPreparingIssuesCount: null,
|
|
2682
|
+
utilizationPercentageThreshold: 90,
|
|
2683
|
+
allowedIssueAuthors: null,
|
|
2684
|
+
codexHomeCandidates: null,
|
|
2685
|
+
allowIssueCacheMinutes: 0,
|
|
2686
|
+
});
|
|
2687
|
+
|
|
2688
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(1);
|
|
2689
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls[0][2]).toBeUndefined();
|
|
2690
|
+
expect(
|
|
2691
|
+
mockClaudeTokenUsageRepository.ensureObservable.mock.calls,
|
|
2692
|
+
).toHaveLength(0);
|
|
2693
|
+
});
|
|
2694
|
+
|
|
2695
|
+
it('should pick the least-utilized token first', async () => {
|
|
2696
|
+
const awaitingIssue = createMockIssue({
|
|
2697
|
+
url: 'url1',
|
|
2698
|
+
title: 'Issue 1',
|
|
2699
|
+
labels: ['category:impl'],
|
|
2700
|
+
status: 'Awaiting Workspace',
|
|
2701
|
+
number: 1,
|
|
2702
|
+
itemId: 'item-1',
|
|
2703
|
+
});
|
|
2704
|
+
mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
|
|
2705
|
+
mockIssueRepository.getStoryObjectMap.mockResolvedValue(
|
|
2706
|
+
createMockStoryObjectMap([awaitingIssue]),
|
|
2707
|
+
);
|
|
2708
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
2709
|
+
stdout: '',
|
|
2710
|
+
stderr: '',
|
|
2711
|
+
exitCode: 0,
|
|
2712
|
+
});
|
|
2713
|
+
mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue([
|
|
2714
|
+
{ token: 'token-high', fiveHourUtilization: 80, blocked: false },
|
|
2715
|
+
{ token: 'token-low', fiveHourUtilization: 10, blocked: false },
|
|
2716
|
+
]);
|
|
2717
|
+
|
|
2718
|
+
await useCase.run({
|
|
2719
|
+
projectUrl: 'https://github.com/user/repo',
|
|
2720
|
+
defaultAgentName: 'agent1',
|
|
2721
|
+
defaultLlmModelName: 'claude-opus',
|
|
2722
|
+
defaultLlmAgentName: null,
|
|
2723
|
+
configFilePath: '/path/to/config.yml',
|
|
2724
|
+
maximumPreparingIssuesCount: null,
|
|
2725
|
+
utilizationPercentageThreshold: 90,
|
|
2726
|
+
allowedIssueAuthors: null,
|
|
2727
|
+
codexHomeCandidates: null,
|
|
2728
|
+
allowIssueCacheMinutes: 0,
|
|
2729
|
+
});
|
|
2730
|
+
|
|
2731
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(1);
|
|
2732
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls[0][2]).toEqual({
|
|
2733
|
+
env: {
|
|
2734
|
+
CLAUDE_CODE_OAUTH_TOKEN: 'token-low',
|
|
2735
|
+
ANTHROPIC_BASE_URL: 'http://127.0.0.1:8787',
|
|
2736
|
+
},
|
|
2737
|
+
});
|
|
2738
|
+
});
|
|
2739
|
+
|
|
2740
|
+
it('should exclude blocked tokens from rotation', async () => {
|
|
2741
|
+
const awaitingIssue = createMockIssue({
|
|
2742
|
+
url: 'url1',
|
|
2743
|
+
title: 'Issue 1',
|
|
2744
|
+
labels: ['category:impl'],
|
|
2745
|
+
status: 'Awaiting Workspace',
|
|
2746
|
+
number: 1,
|
|
2747
|
+
itemId: 'item-1',
|
|
2748
|
+
});
|
|
2749
|
+
mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
|
|
2750
|
+
mockIssueRepository.getStoryObjectMap.mockResolvedValue(
|
|
2751
|
+
createMockStoryObjectMap([awaitingIssue]),
|
|
2752
|
+
);
|
|
2753
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
2754
|
+
stdout: '',
|
|
2755
|
+
stderr: '',
|
|
2756
|
+
exitCode: 0,
|
|
2757
|
+
});
|
|
2758
|
+
mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue([
|
|
2759
|
+
{ token: 'token-blocked', fiveHourUtilization: 5, blocked: true },
|
|
2760
|
+
{ token: 'token-ok', fiveHourUtilization: 50, blocked: false },
|
|
2761
|
+
]);
|
|
2762
|
+
|
|
2763
|
+
await useCase.run({
|
|
2764
|
+
projectUrl: 'https://github.com/user/repo',
|
|
2765
|
+
defaultAgentName: 'agent1',
|
|
2766
|
+
defaultLlmModelName: 'claude-opus',
|
|
2767
|
+
defaultLlmAgentName: null,
|
|
2768
|
+
configFilePath: '/path/to/config.yml',
|
|
2769
|
+
maximumPreparingIssuesCount: null,
|
|
2770
|
+
utilizationPercentageThreshold: 90,
|
|
2771
|
+
allowedIssueAuthors: null,
|
|
2772
|
+
codexHomeCandidates: null,
|
|
2773
|
+
allowIssueCacheMinutes: 0,
|
|
2774
|
+
});
|
|
2775
|
+
|
|
2776
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(1);
|
|
2777
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls[0][2]).toEqual({
|
|
2778
|
+
env: {
|
|
2779
|
+
CLAUDE_CODE_OAUTH_TOKEN: 'token-ok',
|
|
2780
|
+
ANTHROPIC_BASE_URL: 'http://127.0.0.1:8787',
|
|
2781
|
+
},
|
|
2782
|
+
});
|
|
2783
|
+
});
|
|
2784
|
+
|
|
2785
|
+
it('should not inject env when every available token is blocked', async () => {
|
|
2786
|
+
const awaitingIssue = createMockIssue({
|
|
2787
|
+
url: 'url1',
|
|
2788
|
+
title: 'Issue 1',
|
|
2789
|
+
labels: ['category:impl'],
|
|
2790
|
+
status: 'Awaiting Workspace',
|
|
2791
|
+
number: 1,
|
|
2792
|
+
itemId: 'item-1',
|
|
2793
|
+
});
|
|
2794
|
+
mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
|
|
2795
|
+
mockIssueRepository.getStoryObjectMap.mockResolvedValue(
|
|
2796
|
+
createMockStoryObjectMap([awaitingIssue]),
|
|
2797
|
+
);
|
|
2798
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
2799
|
+
stdout: '',
|
|
2800
|
+
stderr: '',
|
|
2801
|
+
exitCode: 0,
|
|
2802
|
+
});
|
|
2803
|
+
mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue([
|
|
2804
|
+
{ token: 'token-a', fiveHourUtilization: 5, blocked: true },
|
|
2805
|
+
{ token: 'token-b', fiveHourUtilization: 8, blocked: true },
|
|
2806
|
+
]);
|
|
2807
|
+
|
|
2808
|
+
await useCase.run({
|
|
2809
|
+
projectUrl: 'https://github.com/user/repo',
|
|
2810
|
+
defaultAgentName: 'agent1',
|
|
2811
|
+
defaultLlmModelName: 'claude-opus',
|
|
2812
|
+
defaultLlmAgentName: null,
|
|
2813
|
+
configFilePath: '/path/to/config.yml',
|
|
2814
|
+
maximumPreparingIssuesCount: null,
|
|
2815
|
+
utilizationPercentageThreshold: 90,
|
|
2816
|
+
allowedIssueAuthors: null,
|
|
2817
|
+
codexHomeCandidates: null,
|
|
2818
|
+
allowIssueCacheMinutes: 0,
|
|
2819
|
+
});
|
|
2820
|
+
|
|
2821
|
+
expect(
|
|
2822
|
+
mockClaudeTokenUsageRepository.ensureObservable.mock.calls,
|
|
2823
|
+
).toHaveLength(0);
|
|
2824
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(1);
|
|
2825
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls[0][2]).toBeUndefined();
|
|
2826
|
+
});
|
|
2519
2827
|
});
|
|
@@ -2,6 +2,8 @@ import { IssueRepository } from './adapter-interfaces/IssueRepository';
|
|
|
2
2
|
import { ProjectRepository } from './adapter-interfaces/ProjectRepository';
|
|
3
3
|
import { LocalCommandRunner } from './adapter-interfaces/LocalCommandRunner';
|
|
4
4
|
import { ClaudeRepository } from './adapter-interfaces/ClaudeRepository';
|
|
5
|
+
import { ClaudeTokenUsageRepository } from './adapter-interfaces/ClaudeTokenUsageRepository';
|
|
6
|
+
import { ClaudeTokenUsage } from '../entities/ClaudeTokenUsage';
|
|
5
7
|
import {
|
|
6
8
|
AWAITING_WORKSPACE_STATUS_NAME,
|
|
7
9
|
PREPARATION_STATUS_NAME,
|
|
@@ -22,8 +24,15 @@ export class StartPreparationUseCase {
|
|
|
22
24
|
>,
|
|
23
25
|
private readonly claudeRepository: Pick<ClaudeRepository, 'getUsage'>,
|
|
24
26
|
private readonly localCommandRunner: LocalCommandRunner,
|
|
27
|
+
private readonly claudeTokenUsageRepository: ClaudeTokenUsageRepository,
|
|
25
28
|
) {}
|
|
26
29
|
|
|
30
|
+
private selectRotationTokens = (tokenUsages: ClaudeTokenUsage[]): string[] =>
|
|
31
|
+
tokenUsages
|
|
32
|
+
.filter((usage) => !usage.blocked)
|
|
33
|
+
.sort((a, b) => a.fiveHourUtilization - b.fiveHourUtilization)
|
|
34
|
+
.map((usage) => usage.token);
|
|
35
|
+
|
|
27
36
|
run = async (params: {
|
|
28
37
|
projectUrl: string;
|
|
29
38
|
defaultAgentName: string;
|
|
@@ -84,6 +93,20 @@ export class StartPreparationUseCase {
|
|
|
84
93
|
);
|
|
85
94
|
}
|
|
86
95
|
}
|
|
96
|
+
|
|
97
|
+
const tokenUsages =
|
|
98
|
+
await this.claudeTokenUsageRepository.getAvailableTokenUsages();
|
|
99
|
+
let rotationTokens: string[] | null = null;
|
|
100
|
+
let proxyBaseUrl: string | null = null;
|
|
101
|
+
if (tokenUsages.length > 0) {
|
|
102
|
+
const ranked = this.selectRotationTokens(tokenUsages);
|
|
103
|
+
if (ranked.length > 0) {
|
|
104
|
+
await this.claudeTokenUsageRepository.ensureObservable();
|
|
105
|
+
rotationTokens = ranked;
|
|
106
|
+
proxyBaseUrl = this.claudeTokenUsageRepository.proxyBaseUrl();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
87
110
|
const project = await this.projectRepository.getByUrl(params.projectUrl);
|
|
88
111
|
const storyObjectMap = await this.issueRepository.getStoryObjectMap(
|
|
89
112
|
project,
|
|
@@ -271,7 +294,20 @@ export class StartPreparationUseCase {
|
|
|
271
294
|
];
|
|
272
295
|
awArgs.push('--codexHome', codexHome);
|
|
273
296
|
}
|
|
274
|
-
|
|
297
|
+
let spawnEnv: Record<string, string> | undefined;
|
|
298
|
+
if (rotationTokens !== null && proxyBaseUrl !== null) {
|
|
299
|
+
const selected =
|
|
300
|
+
rotationTokens[startedInThisRunCount % rotationTokens.length];
|
|
301
|
+
spawnEnv = {
|
|
302
|
+
CLAUDE_CODE_OAUTH_TOKEN: selected,
|
|
303
|
+
ANTHROPIC_BASE_URL: proxyBaseUrl,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
await this.localCommandRunner.runCommand(
|
|
307
|
+
'aw',
|
|
308
|
+
awArgs,
|
|
309
|
+
spawnEnv ? { env: spawnEnv } : undefined,
|
|
310
|
+
);
|
|
275
311
|
startedInThisRunCount++;
|
|
276
312
|
updatedCurrentPreparationIssueCount++;
|
|
277
313
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
export interface LocalCommandRunnerOptions {
|
|
2
|
+
env?: Record<string, string>;
|
|
3
|
+
}
|
|
4
|
+
|
|
1
5
|
export interface LocalCommandRunner {
|
|
2
6
|
runCommand(
|
|
3
7
|
program: string,
|
|
4
8
|
args: string[],
|
|
9
|
+
options?: LocalCommandRunnerOptions,
|
|
5
10
|
): Promise<{
|
|
6
11
|
stdout: string;
|
|
7
12
|
stderr: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACL,UAAU,EACV,cAAc,EACd,wBAAwB,EACxB,YAAY,EACZ,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACL,UAAU,EACV,cAAc,EACd,wBAAwB,EACxB,YAAY,EACZ,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AAkEzB,eAAO,MAAM,OAAO,SAAgB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projectConfig.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/projectConfig.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iCAAiC,CAAC,EAAE,MAAM,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC,CAAC;AAoCF,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CACH,CAAC;AAEvE,eAAO,MAAM,cAAc,GAAI,gBAAgB,MAAM,KAAG,
|
|
1
|
+
{"version":3,"file":"projectConfig.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/projectConfig.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iCAAiC,CAAC,EAAE,MAAM,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC,CAAC;AAoCF,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CACH,CAAC;AAEvE,eAAO,MAAM,cAAc,GAAI,gBAAgB,MAAM,KAAG,UAkDvD,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,QAAQ,MAAM,KAAG,UAsDzD,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,YAAY,UAAU,EACtB,cAAc,UAAU,EACxB,iBAAiB,UAAU,KAC1B,UA2DD,CAAC;AAkBH,eAAO,MAAM,kBAAkB,GAC7B,YAAY,MAAM,EAClB,OAAO,MAAM,KACZ,OAAO,CAAC,MAAM,GAAG,IAAI,CAyDvB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAyB3D,qBAAa,kCAAkC;IAC7C,MAAM,GACJ,gBAAgB,MAAM,EACtB,UAAU,OAAO,KAChB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,eAAe,EAAE,IAAI,EAAE,CAAC;KACzB,GAAG,IAAI,CAAC,CA+OP;CACH"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface RateLimitSnapshot {
|
|
2
|
+
fiveHourUtilization: number;
|
|
3
|
+
fiveHourReset: number;
|
|
4
|
+
sevenDayUtilization: number;
|
|
5
|
+
sevenDayReset: number;
|
|
6
|
+
blocked: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare const PROXY_PORT = 8787;
|
|
9
|
+
export declare const cacheDir: () => string;
|
|
10
|
+
export declare const hashToken: (token: string) => string;
|
|
11
|
+
export declare const cachePathForToken: (token: string) => string;
|
|
12
|
+
export declare const writeRateLimit: (token: string, headers: Record<string, string | string[] | undefined>) => void;
|
|
13
|
+
export declare const readRateLimit: (token: string) => RateLimitSnapshot | null;
|
|
14
|
+
//# sourceMappingURL=RateLimitCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RateLimitCache.d.ts","sourceRoot":"","sources":["../../../src/adapter/proxy/RateLimitCache.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,UAAU,OAAO,CAAC;AAI/B,eAAO,MAAM,QAAQ,QAAO,MAG3B,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,KAAG,MACqB,CAAC;AAEhE,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,KAAG,MACC,CAAC;AAEpD,eAAO,MAAM,cAAc,GACzB,OAAO,MAAM,EACb,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,KACrD,IAsCF,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,KAAG,iBAAiB,GAAG,IAwCjE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TokenListLoader.d.ts","sourceRoot":"","sources":["../../../src/adapter/proxy/TokenListLoader.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,UAAU,GAAI,UAAU,MAAM,KAAG,MAAM,EAAE,GAAG,IAiBxD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensureProxyRunning.d.ts","sourceRoot":"","sources":["../../../src/adapter/proxy/ensureProxyRunning.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,kBAAkB,GAC7B,OAAM,MAAmB,KACxB,OAAO,CAAC,IAAI,CAUd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxyEntry.d.ts","sourceRoot":"","sources":["../../../src/adapter/proxy/proxyEntry.ts"],"names":[],"mappings":"AAQA,QAAA,MAAM,YAAY,GAChB,eAAe,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,KAC3C,MAAM,GAAG,IAQX,CAAC;AAEF,QAAA,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,IA0ClC,CAAC;AAMF,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { LocalCommandRunner } from '../../domain/usecases/adapter-interfaces/LocalCommandRunner';
|
|
1
|
+
import { LocalCommandRunner, LocalCommandRunnerOptions } from '../../domain/usecases/adapter-interfaces/LocalCommandRunner';
|
|
2
2
|
export declare class NodeLocalCommandRunner implements LocalCommandRunner {
|
|
3
|
-
runCommand(program: string, args: string[]): Promise<{
|
|
3
|
+
runCommand(program: string, args: string[], options?: LocalCommandRunnerOptions): Promise<{
|
|
4
4
|
stdout: string;
|
|
5
5
|
stderr: string;
|
|
6
6
|
exitCode: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeLocalCommandRunner.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/NodeLocalCommandRunner.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"NodeLocalCommandRunner.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/NodeLocalCommandRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EAC1B,MAAM,6DAA6D,CAAC;AAMrE,qBAAa,sBAAuB,YAAW,kBAAkB;IACzD,UAAU,CACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE,yBAAyB,GAClC,OAAO,CAAC;QACT,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CAmCH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OauthProxyClaudeRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/OauthProxyClaudeRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAC7F,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAuB5E,qBAAa,0BAA2B,YAAW,gBAAgB;IACjE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAGhC,QAAQ,GAAE,MACoB;IAK1B,QAAQ,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"OauthProxyClaudeRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/OauthProxyClaudeRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAC7F,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAuB5E,qBAAa,0BAA2B,YAAW,gBAAgB;IACjE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAGhC,QAAQ,GAAE,MACoB;IAK1B,QAAQ,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAkFxC,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAO7D"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ClaudeTokenUsage } from '../../domain/entities/ClaudeTokenUsage';
|
|
2
|
+
import { ClaudeTokenUsageRepository } from '../../domain/usecases/adapter-interfaces/ClaudeTokenUsageRepository';
|
|
3
|
+
export declare class ProxyClaudeTokenUsageRepository implements ClaudeTokenUsageRepository {
|
|
4
|
+
private readonly tokenListJsonPath;
|
|
5
|
+
private readonly port;
|
|
6
|
+
constructor(tokenListJsonPath: string | null, port?: number);
|
|
7
|
+
ensureObservable: () => Promise<void>;
|
|
8
|
+
getAvailableTokenUsages: () => Promise<ClaudeTokenUsage[]>;
|
|
9
|
+
proxyBaseUrl: () => string;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=ProxyClaudeTokenUsageRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProxyClaudeTokenUsageRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/ProxyClaudeTokenUsageRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,qEAAqE,CAAC;AAKjH,qBAAa,+BAAgC,YAAW,0BAA0B;IAE9E,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI;gBADJ,iBAAiB,EAAE,MAAM,GAAG,IAAI,EAChC,IAAI,GAAE,MAAmB;IAG5C,gBAAgB,QAAa,OAAO,CAAC,IAAI,CAAC,CAExC;IAEF,uBAAuB,QAAa,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAgB7D;IAEF,YAAY,QAAO,MAAM,CAAoC;CAC9D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClaudeTokenUsage.d.ts","sourceRoot":"","sources":["../../../src/domain/entities/ClaudeTokenUsage.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB,EAAE,MAAM,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC"}
|
|
@@ -2,12 +2,15 @@ import { IssueRepository } from './adapter-interfaces/IssueRepository';
|
|
|
2
2
|
import { ProjectRepository } from './adapter-interfaces/ProjectRepository';
|
|
3
3
|
import { LocalCommandRunner } from './adapter-interfaces/LocalCommandRunner';
|
|
4
4
|
import { ClaudeRepository } from './adapter-interfaces/ClaudeRepository';
|
|
5
|
+
import { ClaudeTokenUsageRepository } from './adapter-interfaces/ClaudeTokenUsageRepository';
|
|
5
6
|
export declare class StartPreparationUseCase {
|
|
6
7
|
private readonly projectRepository;
|
|
7
8
|
private readonly issueRepository;
|
|
8
9
|
private readonly claudeRepository;
|
|
9
10
|
private readonly localCommandRunner;
|
|
10
|
-
|
|
11
|
+
private readonly claudeTokenUsageRepository;
|
|
12
|
+
constructor(projectRepository: Pick<ProjectRepository, 'getByUrl'>, issueRepository: Pick<IssueRepository, 'getStoryObjectMap' | 'updateStatus' | 'findRelatedOpenPRs' | 'getOpenPullRequest' | 'closePullRequest' | 'deletePullRequestBranch' | 'createCommentByUrl'>, claudeRepository: Pick<ClaudeRepository, 'getUsage'>, localCommandRunner: LocalCommandRunner, claudeTokenUsageRepository: ClaudeTokenUsageRepository);
|
|
13
|
+
private selectRotationTokens;
|
|
11
14
|
run: (params: {
|
|
12
15
|
projectUrl: string;
|
|
13
16
|
defaultAgentName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StartPreparationUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/StartPreparationUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"StartPreparationUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/StartPreparationUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,iDAAiD,CAAC;AAO7F,qBAAa,uBAAuB;IAEhC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAUhC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,0BAA0B;gBAb1B,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,EACtD,eAAe,EAAE,IAAI,CACpC,eAAe,EACb,mBAAmB,GACnB,cAAc,GACd,oBAAoB,GACpB,oBAAoB,GACpB,kBAAkB,GAClB,yBAAyB,GACzB,oBAAoB,CACvB,EACgB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,EACpD,kBAAkB,EAAE,kBAAkB,EACtC,0BAA0B,EAAE,0BAA0B;IAGzE,OAAO,CAAC,oBAAoB,CAIK;IAEjC,GAAG,GAAU,QAAQ;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,gBAAgB,EAAE,MAAM,CAAC;QACzB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;QACnC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;QACnC,cAAc,EAAE,MAAM,CAAC;QACvB,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3C,8BAA8B,EAAE,MAAM,CAAC;QACvC,mBAAmB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACrC,mBAAmB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QACrC,sBAAsB,EAAE,MAAM,CAAC;KAChC,KAAG,OAAO,CAAC,IAAI,CAAC,CA2Qf;CACH"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ClaudeTokenUsage } from '../../entities/ClaudeTokenUsage';
|
|
2
|
+
export interface ClaudeTokenUsageRepository {
|
|
3
|
+
ensureObservable(): Promise<void>;
|
|
4
|
+
getAvailableTokenUsages(): Promise<ClaudeTokenUsage[]>;
|
|
5
|
+
proxyBaseUrl(): string;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=ClaudeTokenUsageRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClaudeTokenUsageRepository.d.ts","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/ClaudeTokenUsageRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEnE,MAAM,WAAW,0BAA0B;IACzC,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,uBAAuB,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACvD,YAAY,IAAI,MAAM,CAAC;CACxB"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
export interface LocalCommandRunnerOptions {
|
|
2
|
+
env?: Record<string, string>;
|
|
3
|
+
}
|
|
1
4
|
export interface LocalCommandRunner {
|
|
2
|
-
runCommand(program: string, args: string[]): Promise<{
|
|
5
|
+
runCommand(program: string, args: string[], options?: LocalCommandRunnerOptions): Promise<{
|
|
3
6
|
stdout: string;
|
|
4
7
|
stderr: string;
|
|
5
8
|
exitCode: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalCommandRunner.d.ts","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/LocalCommandRunner.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,UAAU,CACR,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"LocalCommandRunner.d.ts","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/LocalCommandRunner.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,yBAAyB;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,CACR,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE,yBAAyB,GAClC,OAAO,CAAC;QACT,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ"}
|