github-issue-tower-defence-management 1.104.3 → 1.105.0
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 +20 -0
- package/README.md +8 -7
- package/bin/adapter/entry-points/cli/index.js +21 -13
- package/bin/adapter/entry-points/cli/index.js.map +1 -1
- package/bin/adapter/entry-points/console/{consoleServer.js → webServer.js} +11 -11
- package/bin/adapter/entry-points/console/webServer.js.map +1 -0
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +41 -2
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
- package/bin/adapter/entry-points/handlers/dashboardRowWriter.js +34 -0
- package/bin/adapter/entry-points/handlers/dashboardRowWriter.js.map +1 -0
- package/bin/adapter/entry-points/handlers/machineStatusWriter.js +60 -0
- package/bin/adapter/entry-points/handlers/machineStatusWriter.js.map +1 -0
- package/bin/adapter/entry-points/handlers/tokenStatusWriter.js +98 -0
- package/bin/adapter/entry-points/handlers/tokenStatusWriter.js.map +1 -0
- package/bin/adapter/proxy/RateLimitCache.js +3 -0
- package/bin/adapter/proxy/RateLimitCache.js.map +1 -1
- package/bin/adapter/repositories/ProcHostMetricsRepository.js +136 -0
- package/bin/adapter/repositories/ProcHostMetricsRepository.js.map +1 -0
- package/bin/adapter/repositories/ProcTakeOwnershipSpawnRepository.js +131 -0
- package/bin/adapter/repositories/ProcTakeOwnershipSpawnRepository.js.map +1 -0
- package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js +93 -8
- package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js.map +1 -1
- package/bin/domain/usecases/adapter-interfaces/TakeOwnershipSpawnRepository.js +3 -0
- package/bin/domain/usecases/adapter-interfaces/TakeOwnershipSpawnRepository.js.map +1 -0
- package/bin/domain/usecases/dashboard/GenerateDashboardRowUseCase.js +38 -0
- package/bin/domain/usecases/dashboard/GenerateDashboardRowUseCase.js.map +1 -0
- package/bin/domain/usecases/dashboard/GenerateTokenStatusUseCase.js +115 -0
- package/bin/domain/usecases/dashboard/GenerateTokenStatusUseCase.js.map +1 -0
- package/package.json +1 -1
- package/src/adapter/entry-points/cli/index.test.ts +74 -21
- package/src/adapter/entry-points/cli/index.ts +146 -136
- package/src/adapter/entry-points/console/ui/e2e/consoleTestHarness.ts +2 -2
- package/src/adapter/entry-points/console/{consoleServer.test.ts → webServer.test.ts} +32 -32
- package/src/adapter/entry-points/console/{consoleServer.ts → webServer.ts} +15 -17
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +52 -0
- package/src/adapter/entry-points/handlers/dashboardRowWriter.test.ts +111 -0
- package/src/adapter/entry-points/handlers/dashboardRowWriter.ts +51 -0
- package/src/adapter/entry-points/handlers/machineStatusWriter.test.ts +100 -0
- package/src/adapter/entry-points/handlers/machineStatusWriter.ts +79 -0
- package/src/adapter/entry-points/handlers/tokenStatusWriter.test.ts +176 -0
- package/src/adapter/entry-points/handlers/tokenStatusWriter.ts +139 -0
- package/src/adapter/proxy/RateLimitCache.test.ts +32 -0
- package/src/adapter/proxy/RateLimitCache.ts +6 -0
- package/src/adapter/repositories/ProcHostMetricsRepository.test.ts +135 -0
- package/src/adapter/repositories/ProcHostMetricsRepository.ts +136 -0
- package/src/adapter/repositories/ProcTakeOwnershipSpawnRepository.test.ts +130 -0
- package/src/adapter/repositories/ProcTakeOwnershipSpawnRepository.ts +118 -0
- package/src/adapter/repositories/issue/GraphqlProjectItemRepository.test.ts +267 -13
- package/src/adapter/repositories/issue/GraphqlProjectItemRepository.ts +140 -47
- package/src/domain/usecases/adapter-interfaces/TakeOwnershipSpawnRepository.ts +8 -0
- package/src/domain/usecases/dashboard/GenerateDashboardRowUseCase.test.ts +159 -0
- package/src/domain/usecases/dashboard/GenerateDashboardRowUseCase.ts +72 -0
- package/src/domain/usecases/dashboard/GenerateTokenStatusUseCase.test.ts +209 -0
- package/src/domain/usecases/dashboard/GenerateTokenStatusUseCase.ts +195 -0
- package/types/adapter/entry-points/cli/index.d.ts.map +1 -1
- package/types/adapter/entry-points/console/{consoleServer.d.ts → webServer.d.ts} +7 -7
- package/types/adapter/entry-points/console/webServer.d.ts.map +1 -0
- package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/dashboardRowWriter.d.ts +15 -0
- package/types/adapter/entry-points/handlers/dashboardRowWriter.d.ts.map +1 -0
- package/types/adapter/entry-points/handlers/machineStatusWriter.d.ts +16 -0
- package/types/adapter/entry-points/handlers/machineStatusWriter.d.ts.map +1 -0
- package/types/adapter/entry-points/handlers/tokenStatusWriter.d.ts +21 -0
- package/types/adapter/entry-points/handlers/tokenStatusWriter.d.ts.map +1 -0
- package/types/adapter/proxy/RateLimitCache.d.ts +2 -0
- package/types/adapter/proxy/RateLimitCache.d.ts.map +1 -1
- package/types/adapter/repositories/ProcHostMetricsRepository.d.ts +23 -0
- package/types/adapter/repositories/ProcHostMetricsRepository.d.ts.map +1 -0
- package/types/adapter/repositories/ProcTakeOwnershipSpawnRepository.d.ts +11 -0
- package/types/adapter/repositories/ProcTakeOwnershipSpawnRepository.d.ts.map +1 -0
- package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts +6 -1
- package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts.map +1 -1
- package/types/domain/usecases/adapter-interfaces/TakeOwnershipSpawnRepository.d.ts +8 -0
- package/types/domain/usecases/adapter-interfaces/TakeOwnershipSpawnRepository.d.ts.map +1 -0
- package/types/domain/usecases/dashboard/GenerateDashboardRowUseCase.d.ts +19 -0
- package/types/domain/usecases/dashboard/GenerateDashboardRowUseCase.d.ts.map +1 -0
- package/types/domain/usecases/dashboard/GenerateTokenStatusUseCase.d.ts +53 -0
- package/types/domain/usecases/dashboard/GenerateTokenStatusUseCase.d.ts.map +1 -0
- package/bin/adapter/entry-points/console/consoleServer.js.map +0 -1
- package/types/adapter/entry-points/console/consoleServer.d.ts.map +0 -1
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { Issue } from '../../entities/Issue';
|
|
2
|
+
import { GenerateDashboardRowUseCase } from './GenerateDashboardRowUseCase';
|
|
3
|
+
|
|
4
|
+
const ASSIGNEE = 'HiromiShikata';
|
|
5
|
+
|
|
6
|
+
let issueCounter = 0;
|
|
7
|
+
const makeIssue = (overrides: Partial<Issue>): Issue => {
|
|
8
|
+
issueCounter += 1;
|
|
9
|
+
return {
|
|
10
|
+
nameWithOwner: 'demo/repo',
|
|
11
|
+
number: issueCounter,
|
|
12
|
+
title: `Issue ${issueCounter}`,
|
|
13
|
+
state: 'OPEN',
|
|
14
|
+
status: null,
|
|
15
|
+
story: null,
|
|
16
|
+
nextActionDate: null,
|
|
17
|
+
nextActionHour: null,
|
|
18
|
+
estimationMinutes: null,
|
|
19
|
+
dependedIssueUrls: [],
|
|
20
|
+
completionDate50PercentConfidence: null,
|
|
21
|
+
url: `https://github.com/demo/repo/issues/${issueCounter}`,
|
|
22
|
+
assignees: [ASSIGNEE],
|
|
23
|
+
labels: [],
|
|
24
|
+
org: 'demo',
|
|
25
|
+
repo: 'repo',
|
|
26
|
+
body: '',
|
|
27
|
+
itemId: `item-${issueCounter}`,
|
|
28
|
+
isPr: false,
|
|
29
|
+
isInProgress: false,
|
|
30
|
+
isClosed: false,
|
|
31
|
+
createdAt: new Date('2026-06-13T08:18:45.000Z'),
|
|
32
|
+
author: 'someone',
|
|
33
|
+
closingIssueReferenceUrls: [],
|
|
34
|
+
...overrides,
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
describe('GenerateDashboardRowUseCase', () => {
|
|
39
|
+
const usecase = new GenerateDashboardRowUseCase();
|
|
40
|
+
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
issueCounter = 0;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('returns all-zero counts for an empty issue list', () => {
|
|
46
|
+
expect(usecase.run({ issues: [], assigneeLogin: ASSIGNEE })).toEqual({
|
|
47
|
+
unread: 0,
|
|
48
|
+
todo: 0,
|
|
49
|
+
qc: 0,
|
|
50
|
+
fail: 0,
|
|
51
|
+
pr: 0,
|
|
52
|
+
ws: 0,
|
|
53
|
+
dep: 0,
|
|
54
|
+
blocker: 0,
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('counts actionable Unread, Todo, Awaiting Quality Check and Awaiting Workspace issues', () => {
|
|
59
|
+
const issues = [
|
|
60
|
+
makeIssue({ status: 'Unread' }),
|
|
61
|
+
makeIssue({ status: 'Todo by human' }),
|
|
62
|
+
makeIssue({ status: 'Awaiting Quality Check' }),
|
|
63
|
+
makeIssue({ status: 'Awaiting Workspace' }),
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
expect(usecase.run({ issues, assigneeLogin: ASSIGNEE })).toEqual({
|
|
67
|
+
unread: 1,
|
|
68
|
+
todo: 1,
|
|
69
|
+
qc: 1,
|
|
70
|
+
fail: 0,
|
|
71
|
+
pr: 0,
|
|
72
|
+
ws: 1,
|
|
73
|
+
dep: 0,
|
|
74
|
+
blocker: 0,
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('excludes non-actionable issues from actionable status columns', () => {
|
|
79
|
+
const issues = [
|
|
80
|
+
makeIssue({ status: 'Unread', nextActionDate: new Date() }),
|
|
81
|
+
makeIssue({ status: 'Unread', nextActionHour: 9 }),
|
|
82
|
+
makeIssue({
|
|
83
|
+
status: 'Awaiting Quality Check',
|
|
84
|
+
dependedIssueUrls: ['https://github.com/demo/repo/issues/999'],
|
|
85
|
+
}),
|
|
86
|
+
makeIssue({ status: 'Todo by human', assignees: ['someone-else'] }),
|
|
87
|
+
makeIssue({ status: 'Awaiting Workspace', isClosed: true }),
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
expect(usecase.run({ issues, assigneeLogin: ASSIGNEE })).toEqual({
|
|
91
|
+
unread: 0,
|
|
92
|
+
todo: 0,
|
|
93
|
+
qc: 0,
|
|
94
|
+
fail: 0,
|
|
95
|
+
pr: 0,
|
|
96
|
+
ws: 0,
|
|
97
|
+
dep: 0,
|
|
98
|
+
blocker: 0,
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('counts Preparation and Failed Preparation by whole status without the actionable predicate', () => {
|
|
103
|
+
const issues = [
|
|
104
|
+
makeIssue({ status: 'Preparation', nextActionHour: 9 }),
|
|
105
|
+
makeIssue({
|
|
106
|
+
status: 'Failed Preparation',
|
|
107
|
+
dependedIssueUrls: ['https://github.com/demo/repo/issues/999'],
|
|
108
|
+
}),
|
|
109
|
+
makeIssue({ status: 'Preparation', isClosed: true }),
|
|
110
|
+
makeIssue({ status: 'Failed Preparation', assignees: ['someone-else'] }),
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
expect(usecase.run({ issues, assigneeLogin: ASSIGNEE })).toEqual({
|
|
114
|
+
unread: 0,
|
|
115
|
+
todo: 0,
|
|
116
|
+
qc: 0,
|
|
117
|
+
fail: 1,
|
|
118
|
+
pr: 1,
|
|
119
|
+
ws: 0,
|
|
120
|
+
dep: 0,
|
|
121
|
+
blocker: 0,
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('counts dep as Awaiting Workspace issues blocked by a dependency, and never as ws', () => {
|
|
126
|
+
const issues = [
|
|
127
|
+
makeIssue({ status: 'Awaiting Workspace' }),
|
|
128
|
+
makeIssue({
|
|
129
|
+
status: 'Awaiting Workspace',
|
|
130
|
+
dependedIssueUrls: ['https://github.com/demo/repo/issues/999'],
|
|
131
|
+
}),
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
expect(usecase.run({ issues, assigneeLogin: ASSIGNEE })).toMatchObject({
|
|
135
|
+
ws: 1,
|
|
136
|
+
dep: 1,
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('counts blocker by case-insensitive workflow blocker story membership for non-closed mine issues', () => {
|
|
141
|
+
const issues = [
|
|
142
|
+
makeIssue({ status: 'Unread', story: 'Workflow Blocker / urgent' }),
|
|
143
|
+
makeIssue({ status: 'Awaiting Workspace', story: 'workflow blocker' }),
|
|
144
|
+
makeIssue({ status: 'Unread', story: 'regular / maintenance' }),
|
|
145
|
+
makeIssue({
|
|
146
|
+
status: 'Unread',
|
|
147
|
+
story: 'workflow blocker',
|
|
148
|
+
isClosed: true,
|
|
149
|
+
}),
|
|
150
|
+
makeIssue({
|
|
151
|
+
status: 'Unread',
|
|
152
|
+
story: 'workflow blocker',
|
|
153
|
+
assignees: ['someone-else'],
|
|
154
|
+
}),
|
|
155
|
+
];
|
|
156
|
+
|
|
157
|
+
expect(usecase.run({ issues, assigneeLogin: ASSIGNEE }).blocker).toBe(2);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Issue } from '../../entities/Issue';
|
|
2
|
+
import {
|
|
3
|
+
AWAITING_QUALITY_CHECK_STATUS_NAME,
|
|
4
|
+
AWAITING_WORKSPACE_STATUS_NAME,
|
|
5
|
+
DEFAULT_STATUS_NAME,
|
|
6
|
+
FAILED_PREPARATION_STATUS_NAME,
|
|
7
|
+
PREPARATION_STATUS_NAME,
|
|
8
|
+
TODO_STATUS_NAME,
|
|
9
|
+
} from '../../entities/WorkflowStatus';
|
|
10
|
+
|
|
11
|
+
export type DashboardRow = {
|
|
12
|
+
unread: number;
|
|
13
|
+
todo: number;
|
|
14
|
+
qc: number;
|
|
15
|
+
fail: number;
|
|
16
|
+
pr: number;
|
|
17
|
+
ws: number;
|
|
18
|
+
dep: number;
|
|
19
|
+
blocker: number;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type GenerateDashboardRowInput = {
|
|
23
|
+
issues: Issue[];
|
|
24
|
+
assigneeLogin: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const WORKFLOW_BLOCKER_STORY_MARKER = 'workflow blocker';
|
|
28
|
+
|
|
29
|
+
export class GenerateDashboardRowUseCase {
|
|
30
|
+
run = (input: GenerateDashboardRowInput): DashboardRow => {
|
|
31
|
+
const { issues, assigneeLogin } = input;
|
|
32
|
+
|
|
33
|
+
const mine = (issue: Issue): boolean =>
|
|
34
|
+
issue.isClosed === false && issue.assignees.includes(assigneeLogin);
|
|
35
|
+
|
|
36
|
+
const actionable = (issue: Issue): boolean =>
|
|
37
|
+
mine(issue) &&
|
|
38
|
+
issue.dependedIssueUrls.length === 0 &&
|
|
39
|
+
issue.nextActionDate === null &&
|
|
40
|
+
issue.nextActionHour === null;
|
|
41
|
+
|
|
42
|
+
const countActionableWithStatus = (statusName: string): number =>
|
|
43
|
+
issues.filter((issue) => issue.status === statusName && actionable(issue))
|
|
44
|
+
.length;
|
|
45
|
+
|
|
46
|
+
const countMineWithStatus = (statusName: string): number =>
|
|
47
|
+
issues.filter((issue) => mine(issue) && issue.status === statusName)
|
|
48
|
+
.length;
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
unread: countActionableWithStatus(DEFAULT_STATUS_NAME),
|
|
52
|
+
todo: countActionableWithStatus(TODO_STATUS_NAME),
|
|
53
|
+
qc: countActionableWithStatus(AWAITING_QUALITY_CHECK_STATUS_NAME),
|
|
54
|
+
fail: countMineWithStatus(FAILED_PREPARATION_STATUS_NAME),
|
|
55
|
+
pr: countMineWithStatus(PREPARATION_STATUS_NAME),
|
|
56
|
+
ws: countActionableWithStatus(AWAITING_WORKSPACE_STATUS_NAME),
|
|
57
|
+
dep: issues.filter(
|
|
58
|
+
(issue) =>
|
|
59
|
+
mine(issue) &&
|
|
60
|
+
issue.status === AWAITING_WORKSPACE_STATUS_NAME &&
|
|
61
|
+
issue.dependedIssueUrls.length > 0,
|
|
62
|
+
).length,
|
|
63
|
+
blocker: issues.filter(
|
|
64
|
+
(issue) =>
|
|
65
|
+
mine(issue) &&
|
|
66
|
+
(issue.story ?? '')
|
|
67
|
+
.toLowerCase()
|
|
68
|
+
.includes(WORKFLOW_BLOCKER_STORY_MARKER),
|
|
69
|
+
).length,
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GenerateTokenStatusUseCase,
|
|
3
|
+
TokenRateLimitDecision,
|
|
4
|
+
TokenRateLimitSnapshot,
|
|
5
|
+
judgeTokenColor,
|
|
6
|
+
} from './GenerateTokenStatusUseCase';
|
|
7
|
+
|
|
8
|
+
const usableDecision = (
|
|
9
|
+
overrides: Partial<TokenRateLimitDecision> = {},
|
|
10
|
+
): TokenRateLimitDecision => ({
|
|
11
|
+
fiveHourUtilization: 0.1,
|
|
12
|
+
sevenDayUtilization: 0.1,
|
|
13
|
+
fiveHourRejected: false,
|
|
14
|
+
sevenDayRejected: false,
|
|
15
|
+
blocked: false,
|
|
16
|
+
unifiedStatus: 'allowed',
|
|
17
|
+
sevenDaySonnetRejected: false,
|
|
18
|
+
sevenDayOpusRejected: false,
|
|
19
|
+
partial: false,
|
|
20
|
+
...overrides,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('judgeTokenColor', () => {
|
|
24
|
+
it('returns Y when there is no snapshot or the snapshot is partial', () => {
|
|
25
|
+
expect(judgeTokenColor(null)).toBe('Y');
|
|
26
|
+
expect(judgeTokenColor(usableDecision({ partial: true }))).toBe('Y');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('returns G for a normal allowed low-utilization token', () => {
|
|
30
|
+
expect(judgeTokenColor(usableDecision())).toBe('G');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('returns Y for high utilization while allowed', () => {
|
|
34
|
+
expect(judgeTokenColor(usableDecision({ fiveHourUtilization: 0.8 }))).toBe(
|
|
35
|
+
'Y',
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('keeps a token usable (G) when only Sonnet 7d is rejected but Opus is usable', () => {
|
|
40
|
+
expect(
|
|
41
|
+
judgeTokenColor(
|
|
42
|
+
usableDecision({
|
|
43
|
+
sevenDaySonnetRejected: true,
|
|
44
|
+
sevenDayOpusRejected: false,
|
|
45
|
+
}),
|
|
46
|
+
),
|
|
47
|
+
).toBe('G');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('returns Y when Sonnet is rejected, Opus usable, and 7d utilization is high', () => {
|
|
51
|
+
expect(
|
|
52
|
+
judgeTokenColor(
|
|
53
|
+
usableDecision({
|
|
54
|
+
sevenDaySonnetRejected: true,
|
|
55
|
+
sevenDayOpusRejected: false,
|
|
56
|
+
sevenDayUtilization: 0.8,
|
|
57
|
+
}),
|
|
58
|
+
),
|
|
59
|
+
).toBe('Y');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('returns K when both Sonnet and Opus 7d are rejected', () => {
|
|
63
|
+
expect(
|
|
64
|
+
judgeTokenColor(
|
|
65
|
+
usableDecision({
|
|
66
|
+
sevenDaySonnetRejected: true,
|
|
67
|
+
sevenDayOpusRejected: true,
|
|
68
|
+
}),
|
|
69
|
+
),
|
|
70
|
+
).toBe('K');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('returns K when the general 7d window is rejected', () => {
|
|
74
|
+
expect(judgeTokenColor(usableDecision({ sevenDayRejected: true }))).toBe(
|
|
75
|
+
'K',
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('returns K when the 5h window is rejected', () => {
|
|
80
|
+
expect(judgeTokenColor(usableDecision({ fiveHourRejected: true }))).toBe(
|
|
81
|
+
'K',
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('returns K when 5h utilization is exhausted', () => {
|
|
86
|
+
expect(judgeTokenColor(usableDecision({ fiveHourUtilization: 1.0 }))).toBe(
|
|
87
|
+
'K',
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('returns Y for the allowed_warning unified status', () => {
|
|
92
|
+
expect(
|
|
93
|
+
judgeTokenColor(usableDecision({ unifiedStatus: 'allowed_warning' })),
|
|
94
|
+
).toBe('Y');
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const snapshot = (
|
|
99
|
+
overrides: Partial<TokenRateLimitSnapshot> = {},
|
|
100
|
+
): TokenRateLimitSnapshot => ({
|
|
101
|
+
fiveHourUtilization: 0.1,
|
|
102
|
+
fiveHourReset: 0,
|
|
103
|
+
sevenDayUtilization: 0.1,
|
|
104
|
+
sevenDayReset: 0,
|
|
105
|
+
blocked: false,
|
|
106
|
+
fiveHourRejected: false,
|
|
107
|
+
sevenDayRejected: false,
|
|
108
|
+
unifiedStatus: 'allowed',
|
|
109
|
+
sevenDaySonnetRejected: false,
|
|
110
|
+
sevenDayOpusRejected: false,
|
|
111
|
+
hasWindowData: true,
|
|
112
|
+
...overrides,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('GenerateTokenStatusUseCase', () => {
|
|
116
|
+
const usecase = new GenerateTokenStatusUseCase();
|
|
117
|
+
const now = 1_000_000;
|
|
118
|
+
|
|
119
|
+
it('renders per-token utilization percents, color, prep and hum counts', () => {
|
|
120
|
+
const result = usecase.run({
|
|
121
|
+
tokens: [
|
|
122
|
+
{
|
|
123
|
+
name: 'alice',
|
|
124
|
+
token: 'token-a',
|
|
125
|
+
snapshot: snapshot({
|
|
126
|
+
fiveHourUtilization: 0.42,
|
|
127
|
+
fiveHourReset: now + 3600,
|
|
128
|
+
sevenDayUtilization: 0.8,
|
|
129
|
+
sevenDayReset: now + 86400,
|
|
130
|
+
}),
|
|
131
|
+
},
|
|
132
|
+
{ name: 'bob', token: 'token-b', snapshot: null },
|
|
133
|
+
],
|
|
134
|
+
prepCountByToken: new Map([['token-a', 2]]),
|
|
135
|
+
humCountByToken: new Map([['token-a', 1]]),
|
|
136
|
+
nowEpochSeconds: now,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
expect(result).toEqual([
|
|
140
|
+
{
|
|
141
|
+
name: 'alice',
|
|
142
|
+
fiveHourUtilizationPercent: 42,
|
|
143
|
+
fiveHourResetSeconds: 3600,
|
|
144
|
+
sevenDayUtilizationPercent: 80,
|
|
145
|
+
sevenDayResetSeconds: 86400,
|
|
146
|
+
color: 'Y',
|
|
147
|
+
prep: 2,
|
|
148
|
+
hum: 1,
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: 'bob',
|
|
152
|
+
fiveHourUtilizationPercent: null,
|
|
153
|
+
fiveHourResetSeconds: null,
|
|
154
|
+
sevenDayUtilizationPercent: null,
|
|
155
|
+
sevenDayResetSeconds: null,
|
|
156
|
+
color: 'Y',
|
|
157
|
+
prep: 0,
|
|
158
|
+
hum: 0,
|
|
159
|
+
},
|
|
160
|
+
]);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('reports G for an allowed token with headroom on both windows', () => {
|
|
164
|
+
const result = usecase.run({
|
|
165
|
+
tokens: [
|
|
166
|
+
{
|
|
167
|
+
name: 'alice',
|
|
168
|
+
token: 'token-a',
|
|
169
|
+
snapshot: snapshot({
|
|
170
|
+
fiveHourUtilization: 0.1,
|
|
171
|
+
fiveHourReset: now + 3600,
|
|
172
|
+
sevenDayUtilization: 0.1,
|
|
173
|
+
sevenDayReset: now + 86400,
|
|
174
|
+
}),
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
prepCountByToken: new Map(),
|
|
178
|
+
humCountByToken: new Map(),
|
|
179
|
+
nowEpochSeconds: now,
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
expect(result[0].color).toBe('G');
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('zeroes a window whose reset is already in the past and clears its rejection', () => {
|
|
186
|
+
const result = usecase.run({
|
|
187
|
+
tokens: [
|
|
188
|
+
{
|
|
189
|
+
name: 'alice',
|
|
190
|
+
token: 'token-a',
|
|
191
|
+
snapshot: snapshot({
|
|
192
|
+
fiveHourUtilization: 1.0,
|
|
193
|
+
fiveHourReset: now - 10,
|
|
194
|
+
fiveHourRejected: true,
|
|
195
|
+
sevenDayUtilization: 0.2,
|
|
196
|
+
sevenDayReset: now + 86400,
|
|
197
|
+
}),
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
prepCountByToken: new Map(),
|
|
201
|
+
humCountByToken: new Map(),
|
|
202
|
+
nowEpochSeconds: now,
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
expect(result[0].fiveHourUtilizationPercent).toBe(0);
|
|
206
|
+
expect(result[0].fiveHourResetSeconds).toBe(0);
|
|
207
|
+
expect(result[0].color).toBe('G');
|
|
208
|
+
});
|
|
209
|
+
});
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
export type TokenStatusColor = 'G' | 'Y' | 'K';
|
|
2
|
+
|
|
3
|
+
export type TokenRateLimitSnapshot = {
|
|
4
|
+
fiveHourUtilization: number;
|
|
5
|
+
fiveHourReset: number;
|
|
6
|
+
sevenDayUtilization: number;
|
|
7
|
+
sevenDayReset: number;
|
|
8
|
+
blocked: boolean;
|
|
9
|
+
fiveHourRejected: boolean;
|
|
10
|
+
sevenDayRejected: boolean;
|
|
11
|
+
unifiedStatus: string | null;
|
|
12
|
+
sevenDaySonnetRejected: boolean;
|
|
13
|
+
sevenDayOpusRejected: boolean;
|
|
14
|
+
hasWindowData: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type TokenRateLimitDecision = {
|
|
18
|
+
fiveHourUtilization: number | null;
|
|
19
|
+
sevenDayUtilization: number | null;
|
|
20
|
+
fiveHourRejected: boolean;
|
|
21
|
+
sevenDayRejected: boolean;
|
|
22
|
+
blocked: boolean;
|
|
23
|
+
unifiedStatus: string | null;
|
|
24
|
+
sevenDaySonnetRejected: boolean;
|
|
25
|
+
sevenDayOpusRejected: boolean;
|
|
26
|
+
partial: boolean;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type TokenStatus = {
|
|
30
|
+
name: string;
|
|
31
|
+
fiveHourUtilizationPercent: number | null;
|
|
32
|
+
fiveHourResetSeconds: number | null;
|
|
33
|
+
sevenDayUtilizationPercent: number | null;
|
|
34
|
+
sevenDayResetSeconds: number | null;
|
|
35
|
+
color: TokenStatusColor;
|
|
36
|
+
prep: number;
|
|
37
|
+
hum: number;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type TokenStatusInput = {
|
|
41
|
+
name: string;
|
|
42
|
+
token: string;
|
|
43
|
+
snapshot: TokenRateLimitSnapshot | null;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type GenerateTokenStatusInput = {
|
|
47
|
+
tokens: TokenStatusInput[];
|
|
48
|
+
prepCountByToken: Map<string, number>;
|
|
49
|
+
humCountByToken: Map<string, number>;
|
|
50
|
+
nowEpochSeconds: number;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const HIGH_UTILIZATION_THRESHOLD = 0.7;
|
|
54
|
+
const ALLOWED_WARNING_STATUS = 'allowed_warning';
|
|
55
|
+
|
|
56
|
+
export const judgeTokenColor = (
|
|
57
|
+
decision: TokenRateLimitDecision | null,
|
|
58
|
+
): TokenStatusColor => {
|
|
59
|
+
if (decision === null || decision.partial) {
|
|
60
|
+
return 'Y';
|
|
61
|
+
}
|
|
62
|
+
const fiveHourUtilization = decision.fiveHourUtilization ?? 0;
|
|
63
|
+
const sevenDayUtilization = decision.sevenDayUtilization ?? 0;
|
|
64
|
+
const fiveHourExhausted =
|
|
65
|
+
fiveHourUtilization >= 1.0 || decision.fiveHourRejected;
|
|
66
|
+
const generalSevenDayRejected = decision.sevenDayRejected;
|
|
67
|
+
const bothModelsSevenDayRejected =
|
|
68
|
+
decision.sevenDaySonnetRejected && decision.sevenDayOpusRejected;
|
|
69
|
+
const noModelUsable =
|
|
70
|
+
decision.blocked ||
|
|
71
|
+
fiveHourExhausted ||
|
|
72
|
+
generalSevenDayRejected ||
|
|
73
|
+
bothModelsSevenDayRejected;
|
|
74
|
+
if (noModelUsable) {
|
|
75
|
+
return 'K';
|
|
76
|
+
}
|
|
77
|
+
if (decision.unifiedStatus === ALLOWED_WARNING_STATUS) {
|
|
78
|
+
return 'Y';
|
|
79
|
+
}
|
|
80
|
+
if (
|
|
81
|
+
fiveHourUtilization >= HIGH_UTILIZATION_THRESHOLD ||
|
|
82
|
+
sevenDayUtilization >= HIGH_UTILIZATION_THRESHOLD
|
|
83
|
+
) {
|
|
84
|
+
return 'Y';
|
|
85
|
+
}
|
|
86
|
+
return 'G';
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export class GenerateTokenStatusUseCase {
|
|
90
|
+
run = (input: GenerateTokenStatusInput): TokenStatus[] => {
|
|
91
|
+
const { tokens, prepCountByToken, humCountByToken, nowEpochSeconds } =
|
|
92
|
+
input;
|
|
93
|
+
return tokens.map((tokenInput) => {
|
|
94
|
+
const decision = this.toDecision(tokenInput.snapshot, nowEpochSeconds);
|
|
95
|
+
const normalized = this.normalizeWindows(
|
|
96
|
+
tokenInput.snapshot,
|
|
97
|
+
nowEpochSeconds,
|
|
98
|
+
);
|
|
99
|
+
return {
|
|
100
|
+
name: tokenInput.name,
|
|
101
|
+
fiveHourUtilizationPercent: normalized.fiveHourUtilizationPercent,
|
|
102
|
+
fiveHourResetSeconds: normalized.fiveHourResetSeconds,
|
|
103
|
+
sevenDayUtilizationPercent: normalized.sevenDayUtilizationPercent,
|
|
104
|
+
sevenDayResetSeconds: normalized.sevenDayResetSeconds,
|
|
105
|
+
color: judgeTokenColor(decision),
|
|
106
|
+
prep: prepCountByToken.get(tokenInput.token) ?? 0,
|
|
107
|
+
hum: humCountByToken.get(tokenInput.token) ?? 0,
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
private normalizeWindows = (
|
|
113
|
+
snapshot: TokenRateLimitSnapshot | null,
|
|
114
|
+
nowEpochSeconds: number,
|
|
115
|
+
): {
|
|
116
|
+
fiveHourUtilizationPercent: number | null;
|
|
117
|
+
fiveHourResetSeconds: number | null;
|
|
118
|
+
sevenDayUtilizationPercent: number | null;
|
|
119
|
+
sevenDayResetSeconds: number | null;
|
|
120
|
+
} => {
|
|
121
|
+
if (snapshot === null || !snapshot.hasWindowData) {
|
|
122
|
+
return {
|
|
123
|
+
fiveHourUtilizationPercent: null,
|
|
124
|
+
fiveHourResetSeconds: null,
|
|
125
|
+
sevenDayUtilizationPercent: null,
|
|
126
|
+
sevenDayResetSeconds: null,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
const fiveHourReset =
|
|
130
|
+
snapshot.fiveHourReset > 0 ? snapshot.fiveHourReset : null;
|
|
131
|
+
const sevenDayReset =
|
|
132
|
+
snapshot.sevenDayReset > 0 ? snapshot.sevenDayReset : null;
|
|
133
|
+
const fiveHourExpired =
|
|
134
|
+
fiveHourReset !== null && fiveHourReset < nowEpochSeconds;
|
|
135
|
+
const sevenDayExpired =
|
|
136
|
+
sevenDayReset !== null && sevenDayReset < nowEpochSeconds;
|
|
137
|
+
return {
|
|
138
|
+
fiveHourUtilizationPercent: fiveHourExpired
|
|
139
|
+
? 0
|
|
140
|
+
: Math.trunc(snapshot.fiveHourUtilization * 100),
|
|
141
|
+
fiveHourResetSeconds:
|
|
142
|
+
fiveHourReset === null
|
|
143
|
+
? null
|
|
144
|
+
: Math.max(0, fiveHourReset - nowEpochSeconds),
|
|
145
|
+
sevenDayUtilizationPercent: sevenDayExpired
|
|
146
|
+
? 0
|
|
147
|
+
: Math.trunc(snapshot.sevenDayUtilization * 100),
|
|
148
|
+
sevenDayResetSeconds:
|
|
149
|
+
sevenDayReset === null
|
|
150
|
+
? null
|
|
151
|
+
: Math.max(0, sevenDayReset - nowEpochSeconds),
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
private toDecision = (
|
|
156
|
+
snapshot: TokenRateLimitSnapshot | null,
|
|
157
|
+
nowEpochSeconds: number,
|
|
158
|
+
): TokenRateLimitDecision | null => {
|
|
159
|
+
if (snapshot === null) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
if (!snapshot.hasWindowData) {
|
|
163
|
+
return {
|
|
164
|
+
fiveHourUtilization: null,
|
|
165
|
+
sevenDayUtilization: null,
|
|
166
|
+
fiveHourRejected: snapshot.fiveHourRejected,
|
|
167
|
+
sevenDayRejected: snapshot.sevenDayRejected,
|
|
168
|
+
blocked: snapshot.blocked,
|
|
169
|
+
unifiedStatus: snapshot.unifiedStatus,
|
|
170
|
+
sevenDaySonnetRejected: snapshot.sevenDaySonnetRejected,
|
|
171
|
+
sevenDayOpusRejected: snapshot.sevenDayOpusRejected,
|
|
172
|
+
partial: true,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
const fiveHourExpired =
|
|
176
|
+
snapshot.fiveHourReset > 0 && snapshot.fiveHourReset < nowEpochSeconds;
|
|
177
|
+
const sevenDayExpired =
|
|
178
|
+
snapshot.sevenDayReset > 0 && snapshot.sevenDayReset < nowEpochSeconds;
|
|
179
|
+
return {
|
|
180
|
+
fiveHourUtilization: fiveHourExpired ? 0 : snapshot.fiveHourUtilization,
|
|
181
|
+
sevenDayUtilization: sevenDayExpired ? 0 : snapshot.sevenDayUtilization,
|
|
182
|
+
fiveHourRejected: fiveHourExpired ? false : snapshot.fiveHourRejected,
|
|
183
|
+
sevenDayRejected: sevenDayExpired ? false : snapshot.sevenDayRejected,
|
|
184
|
+
blocked: snapshot.blocked,
|
|
185
|
+
unifiedStatus: snapshot.unifiedStatus,
|
|
186
|
+
sevenDaySonnetRejected:
|
|
187
|
+
snapshot.sevenDaySonnetRejected ||
|
|
188
|
+
(sevenDayExpired ? false : snapshot.sevenDayRejected),
|
|
189
|
+
sevenDayOpusRejected:
|
|
190
|
+
snapshot.sevenDayOpusRejected ||
|
|
191
|
+
(sevenDayExpired ? false : snapshot.sevenDayRejected),
|
|
192
|
+
partial: false,
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
}
|
|
@@ -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;AACpC,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;AACpC,OAAO,EACL,UAAU,EACV,cAAc,EACd,wBAAwB,EACxB,YAAY,EACZ,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AA4GzB,eAAO,MAAM,OAAO,SAAgB,CAAC"}
|
|
@@ -3,14 +3,14 @@ import { IssueRepository } from '../../../domain/usecases/adapter-interfaces/Iss
|
|
|
3
3
|
import { IssueTitleStateCache } from './consoleReadApi';
|
|
4
4
|
import { ConsoleProjectResolver } from './consoleOperationApi';
|
|
5
5
|
import { ImageFetcher } from './consoleImageProxy';
|
|
6
|
-
export declare const
|
|
6
|
+
export declare const DEFAULT_WEB_PORT = 9981;
|
|
7
7
|
export declare const CONSOLE_TOKEN_HEADER = "x-pv-token";
|
|
8
8
|
export declare const hasDotSegment: (requestPath: string) => boolean;
|
|
9
9
|
export declare const requiresToken: (requestPath: string) => boolean;
|
|
10
10
|
export declare const isConsoleAppRoute: (requestPath: string) => boolean;
|
|
11
11
|
export declare const isTokenValid: (expectedToken: string, providedToken: string | null) => boolean;
|
|
12
12
|
export declare const extractProvidedToken: (queryToken: string | string[] | null, headerToken: string | string[] | undefined) => string | null;
|
|
13
|
-
export type
|
|
13
|
+
export type WebServerOptions = {
|
|
14
14
|
accessToken: string;
|
|
15
15
|
uiDistDir: string;
|
|
16
16
|
consoleDataOutputDir: string | null;
|
|
@@ -26,10 +26,10 @@ export declare const DASHBOARD_REQUEST_PATH = "/tdpm.txt";
|
|
|
26
26
|
export declare const IMAGE_PROXY_REQUEST_PATH = "/api/img";
|
|
27
27
|
export declare const resolveDashboardFilePath: (dashboardDir: string, requestPath: string) => string | null;
|
|
28
28
|
export declare const resolveFlatInTmuxFilePath: (inTmuxDataDir: string, requestPath: string) => string | null;
|
|
29
|
-
export declare const
|
|
30
|
-
export declare const
|
|
31
|
-
export type
|
|
29
|
+
export declare const handleWebRequest: (options: WebServerOptions, request: http.IncomingMessage, response: http.ServerResponse) => Promise<void>;
|
|
30
|
+
export declare const createWebServer: (options: WebServerOptions) => http.Server;
|
|
31
|
+
export type StartWebServerOptions = WebServerOptions & {
|
|
32
32
|
port: number;
|
|
33
33
|
};
|
|
34
|
-
export declare const
|
|
35
|
-
//# sourceMappingURL=
|
|
34
|
+
export declare const startWebServer: (options: StartWebServerOptions) => Promise<http.Server>;
|
|
35
|
+
//# sourceMappingURL=webServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webServer.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/console/webServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,OAAO,EAAE,eAAe,EAAE,MAAM,6DAA6D,CAAC;AAM9F,OAAO,EACL,oBAAoB,EAOrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAEL,sBAAsB,EAMvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAqB,MAAM,qBAAqB,CAAC;AAEtE,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAmCjD,eAAO,MAAM,aAAa,GAAI,aAAa,MAAM,KAAG,OAGiB,CAAC;AAEtE,eAAO,MAAM,aAAa,GAAI,aAAa,MAAM,KAAG,OAGrB,CAAC;AAIhC,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,KAAG,OAmBvD,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,eAAe,MAAM,EACrB,eAAe,MAAM,GAAG,IAAI,KAC3B,OAAoE,CAAC;AAExE,eAAO,MAAM,oBAAoB,GAC/B,YAAY,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EACpC,aAAa,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,KACzC,MAAM,GAAG,IAQX,CAAC;AAuCF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,cAAc,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC/C,oBAAoB,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;CACpD,CAAC;AAMF,eAAO,MAAM,sBAAsB,cAAc,CAAC;AAElD,eAAO,MAAM,wBAAwB,aAAa,CAAC;AAInD,eAAO,MAAM,wBAAwB,GACnC,cAAc,MAAM,EACpB,aAAa,MAAM,KAClB,MAAM,GAAG,IAWX,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,eAAe,MAAM,EACrB,aAAa,MAAM,KAClB,MAAM,GAAG,IAeX,CAAC;AA4TF,eAAO,MAAM,gBAAgB,GAC3B,SAAS,gBAAgB,EACzB,SAAS,IAAI,CAAC,eAAe,EAC7B,UAAU,IAAI,CAAC,cAAc,KAC5B,OAAO,CAAC,IAAI,CAiFd,CAAC;AAcF,eAAO,MAAM,eAAe,GAAI,SAAS,gBAAgB,KAAG,IAAI,CAAC,MAM7D,CAAC;AAEL,MAAM,MAAM,qBAAqB,GAAG,gBAAgB,GAAG;IACrD,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,eAAO,MAAM,cAAc,GACzB,SAAS,qBAAqB,KAC7B,OAAO,CAAC,IAAI,CAAC,MAAM,CAQlB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAgC3D,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,CAwbP;CACH"}
|