hungry-ghost-hive 0.55.0 → 0.57.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/dist/cli/commands/manager/fast-message-forwarding.test.d.ts +2 -0
- package/dist/cli/commands/manager/fast-message-forwarding.test.d.ts.map +1 -0
- package/dist/cli/commands/manager/fast-message-forwarding.test.js +243 -0
- package/dist/cli/commands/manager/fast-message-forwarding.test.js.map +1 -0
- package/dist/cli/commands/manager/index.d.ts +7 -1
- package/dist/cli/commands/manager/index.d.ts.map +1 -1
- package/dist/cli/commands/manager/index.js +61 -49
- package/dist/cli/commands/manager/index.js.map +1 -1
- package/dist/cli/commands/manager/index.test.js +0 -92
- package/dist/cli/commands/manager/index.test.js.map +1 -1
- package/dist/cli/commands/nuke.d.ts.map +1 -1
- package/dist/cli/commands/nuke.js +13 -0
- package/dist/cli/commands/nuke.js.map +1 -1
- package/dist/cli/commands/req-list-show.test.d.ts +2 -0
- package/dist/cli/commands/req-list-show.test.d.ts.map +1 -0
- package/dist/cli/commands/req-list-show.test.js +219 -0
- package/dist/cli/commands/req-list-show.test.js.map +1 -0
- package/dist/cli/commands/req.d.ts.map +1 -1
- package/dist/cli/commands/req.js +76 -2
- package/dist/cli/commands/req.js.map +1 -1
- package/dist/config/schema.d.ts +16 -8
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +7 -4
- package/dist/config/schema.js.map +1 -1
- package/dist/context-files/index.test.js +2 -1
- package/dist/context-files/index.test.js.map +1 -1
- package/dist/git/worktree.d.ts.map +1 -1
- package/dist/git/worktree.js +18 -2
- package/dist/git/worktree.js.map +1 -1
- package/dist/orchestrator/scheduler.d.ts.map +1 -1
- package/dist/orchestrator/scheduler.js +15 -1
- package/dist/orchestrator/scheduler.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/manager/fast-message-forwarding.test.ts +292 -0
- package/src/cli/commands/manager/index.test.ts +1 -113
- package/src/cli/commands/manager/index.ts +68 -57
- package/src/cli/commands/nuke.ts +12 -0
- package/src/cli/commands/req-list-show.test.ts +276 -0
- package/src/cli/commands/req.ts +106 -2
- package/src/config/schema.ts +7 -4
- package/src/context-files/index.test.ts +2 -1
- package/src/git/worktree.ts +17 -2
- package/src/orchestrator/scheduler.ts +21 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fast-message-forwarding.test.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/manager/fast-message-forwarding.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
// Licensed under the Hungry Ghost Hive License. See LICENSE.
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
// Mock all external dependencies before importing the module under test
|
|
4
|
+
vi.mock('../../../utils/with-hive-context.js', () => ({
|
|
5
|
+
withHiveContext: vi.fn(),
|
|
6
|
+
}));
|
|
7
|
+
vi.mock('../../../db/queries/messages.js', () => ({
|
|
8
|
+
getAllPendingMessages: vi.fn(),
|
|
9
|
+
markMessagesRead: vi.fn(),
|
|
10
|
+
}));
|
|
11
|
+
vi.mock('../../../db/queries/agents.js', () => ({
|
|
12
|
+
getAllAgents: vi.fn(),
|
|
13
|
+
getAgentById: vi.fn(),
|
|
14
|
+
}));
|
|
15
|
+
vi.mock('../../../tmux/manager.js', () => ({
|
|
16
|
+
getHiveSessions: vi.fn(),
|
|
17
|
+
getManagerSession: vi.fn(),
|
|
18
|
+
captureTmuxPane: vi.fn(),
|
|
19
|
+
isManagerRunning: vi.fn(),
|
|
20
|
+
stopManager: vi.fn(),
|
|
21
|
+
killTmuxSession: vi.fn(),
|
|
22
|
+
isTmuxSessionRunning: vi.fn(),
|
|
23
|
+
}));
|
|
24
|
+
vi.mock('./agent-monitoring.js', () => ({
|
|
25
|
+
forwardMessages: vi.fn(),
|
|
26
|
+
agentStates: new Map(),
|
|
27
|
+
detectAgentState: vi.fn(),
|
|
28
|
+
enforceBypassMode: vi.fn(),
|
|
29
|
+
getAgentSafetyMode: vi.fn(),
|
|
30
|
+
handlePermissionPrompt: vi.fn(),
|
|
31
|
+
handlePlanApproval: vi.fn(),
|
|
32
|
+
nudgeAgent: vi.fn(),
|
|
33
|
+
updateAgentStateTracking: vi.fn(),
|
|
34
|
+
}));
|
|
35
|
+
// Mock many other transitive imports to keep tests focused
|
|
36
|
+
vi.mock('../../../config/loader.js', () => ({ loadConfig: vi.fn() }));
|
|
37
|
+
vi.mock('../../../db/lock.js', () => ({ acquireLock: vi.fn() }));
|
|
38
|
+
vi.mock('../../../db/queries/escalations.js', () => ({
|
|
39
|
+
getPendingEscalations: vi.fn(),
|
|
40
|
+
updateEscalation: vi.fn(),
|
|
41
|
+
}));
|
|
42
|
+
vi.mock('../../../db/queries/logs.js', () => ({ createLog: vi.fn() }));
|
|
43
|
+
vi.mock('../../../db/queries/pull-requests.js', () => ({
|
|
44
|
+
getApprovedPullRequests: vi.fn(),
|
|
45
|
+
updatePullRequest: vi.fn(),
|
|
46
|
+
backfillGithubPrNumbers: vi.fn(),
|
|
47
|
+
}));
|
|
48
|
+
vi.mock('../../../db/queries/stories.js', () => ({ getStoryById: vi.fn() }));
|
|
49
|
+
vi.mock('../../../orchestrator/scheduler.js', () => ({ Scheduler: vi.fn() }));
|
|
50
|
+
vi.mock('../../../cluster/runtime.js', () => ({
|
|
51
|
+
ClusterRuntime: vi.fn(),
|
|
52
|
+
fetchLocalClusterStatus: vi.fn(),
|
|
53
|
+
}));
|
|
54
|
+
vi.mock('../../../connectors/project-management/operations.js', () => ({
|
|
55
|
+
syncFromProvider: vi.fn(),
|
|
56
|
+
}));
|
|
57
|
+
vi.mock('../../../utils/auto-merge.js', () => ({ autoMergeApprovedPRs: vi.fn() }));
|
|
58
|
+
vi.mock('../../../utils/instance.js', () => ({
|
|
59
|
+
getManagerLockPath: vi.fn(),
|
|
60
|
+
getTechLeadSessionName: vi.fn(),
|
|
61
|
+
}));
|
|
62
|
+
vi.mock('./auditor-lifecycle.js', () => ({ spawnAuditorIfNeeded: vi.fn() }));
|
|
63
|
+
vi.mock('./auto-assignment.js', () => ({ autoAssignPlannedStories: vi.fn() }));
|
|
64
|
+
vi.mock('./done-intelligence.js', () => ({ assessCompletionFromOutput: vi.fn() }));
|
|
65
|
+
vi.mock('./escalation-handler.js', () => ({ handleEscalationAndNudge: vi.fn() }));
|
|
66
|
+
vi.mock('./feature-sign-off.js', () => ({ checkFeatureSignOff: vi.fn() }));
|
|
67
|
+
vi.mock('./feature-test-result.js', () => ({ checkFeatureTestResult: vi.fn() }));
|
|
68
|
+
vi.mock('./handoff-recovery.js', () => ({ handleStalledPlanningHandoff: vi.fn() }));
|
|
69
|
+
vi.mock('./manager-utils.js', () => ({
|
|
70
|
+
formatDuration: vi.fn(),
|
|
71
|
+
getMaxStuckNudgesPerStory: vi.fn(),
|
|
72
|
+
getScreenStaticInactivityThresholdMs: vi.fn(),
|
|
73
|
+
sendManagerNudge: vi.fn(),
|
|
74
|
+
verboseLog: vi.fn(),
|
|
75
|
+
verboseLogCtx: vi.fn(),
|
|
76
|
+
}));
|
|
77
|
+
vi.mock('./orphaned-escalations.js', () => ({
|
|
78
|
+
shouldAutoResolveOrphanedManagerEscalation: vi.fn(),
|
|
79
|
+
}));
|
|
80
|
+
vi.mock('./qa-review-handler.js', () => ({
|
|
81
|
+
notifyQAOfQueuedPRs: vi.fn(),
|
|
82
|
+
autoRejectCommentOnlyReviews: vi.fn(),
|
|
83
|
+
handleRejectedPRs: vi.fn(),
|
|
84
|
+
}));
|
|
85
|
+
vi.mock('./pr-sync-orchestrator.js', () => ({
|
|
86
|
+
closeStalePRs: vi.fn(),
|
|
87
|
+
reconcileAgentsOnMergedStories: vi.fn(),
|
|
88
|
+
recoverStaleReviewingPRs: vi.fn(),
|
|
89
|
+
syncMergedPRs: vi.fn(),
|
|
90
|
+
syncOpenPRs: vi.fn(),
|
|
91
|
+
}));
|
|
92
|
+
vi.mock('./spin-down.js', () => ({
|
|
93
|
+
spinDownIdleAgents: vi.fn(),
|
|
94
|
+
spinDownMergedAgents: vi.fn(),
|
|
95
|
+
}));
|
|
96
|
+
vi.mock('./stale-escalations.js', () => ({ findStaleSessionEscalations: vi.fn() }));
|
|
97
|
+
vi.mock('./stuck-story-helpers.js', () => ({
|
|
98
|
+
applyHumanInterventionStateOverride: vi.fn(),
|
|
99
|
+
clearHumanIntervention: vi.fn(),
|
|
100
|
+
isClassifierTimeoutReason: vi.fn(),
|
|
101
|
+
markClassifierTimeoutForHumanIntervention: vi.fn(),
|
|
102
|
+
markDoneFalseForHumanIntervention: vi.fn(),
|
|
103
|
+
screenStaticBySession: new Map(),
|
|
104
|
+
}));
|
|
105
|
+
vi.mock('./stuck-story-processor.js', () => ({
|
|
106
|
+
nudgeQAFailedStories: vi.fn(),
|
|
107
|
+
recoverUnassignedQAFailedStories: vi.fn(),
|
|
108
|
+
nudgeStuckStories: vi.fn(),
|
|
109
|
+
autoProgressDoneStory: vi.fn(),
|
|
110
|
+
}));
|
|
111
|
+
vi.mock('./tech-lead-lifecycle.js', () => ({ restartStaleTechLead: vi.fn() }));
|
|
112
|
+
vi.mock('./token-capture.js', () => ({
|
|
113
|
+
parseAndPersistTokenUsage: vi.fn(),
|
|
114
|
+
parseAndPersistTokenUsageIfChanged: vi.fn(),
|
|
115
|
+
}));
|
|
116
|
+
function makeMessage(overrides = {}) {
|
|
117
|
+
return {
|
|
118
|
+
id: 'msg-1',
|
|
119
|
+
from_session: 'hive-agent-a',
|
|
120
|
+
to_session: 'hive-agent-b',
|
|
121
|
+
subject: 'hello',
|
|
122
|
+
body: 'world',
|
|
123
|
+
status: 'pending',
|
|
124
|
+
created_at: new Date().toISOString(),
|
|
125
|
+
...overrides,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function makeAgent(overrides = {}) {
|
|
129
|
+
return {
|
|
130
|
+
id: 'agent-b',
|
|
131
|
+
tmux_session: 'hive-agent-b',
|
|
132
|
+
cli_tool: 'claude',
|
|
133
|
+
current_story_id: null,
|
|
134
|
+
...overrides,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
describe('forwardPendingMessages', () => {
|
|
138
|
+
beforeEach(() => {
|
|
139
|
+
vi.clearAllMocks();
|
|
140
|
+
});
|
|
141
|
+
it('exits early when there are no pending messages', async () => {
|
|
142
|
+
const { withHiveContext } = await import('../../../utils/with-hive-context.js');
|
|
143
|
+
const { getAllPendingMessages } = await import('../../../db/queries/messages.js');
|
|
144
|
+
const { forwardMessages } = await import('./agent-monitoring.js');
|
|
145
|
+
const mockDb = { provider: {}, save: vi.fn() };
|
|
146
|
+
const mockPaths = { hiveDir: '/hive' };
|
|
147
|
+
vi.mocked(withHiveContext).mockImplementation(async (fn) => fn({ db: mockDb, paths: mockPaths }));
|
|
148
|
+
vi.mocked(getAllPendingMessages).mockResolvedValue([]);
|
|
149
|
+
const { forwardPendingMessages } = await import('./index.js');
|
|
150
|
+
await forwardPendingMessages(false);
|
|
151
|
+
expect(forwardMessages).not.toHaveBeenCalled();
|
|
152
|
+
});
|
|
153
|
+
it('forwards messages to active sessions and marks them as read', async () => {
|
|
154
|
+
const { withHiveContext } = await import('../../../utils/with-hive-context.js');
|
|
155
|
+
const { getAllPendingMessages, markMessagesRead } = await import('../../../db/queries/messages.js');
|
|
156
|
+
const { getAllAgents } = await import('../../../db/queries/agents.js');
|
|
157
|
+
const { getHiveSessions, getManagerSession } = await import('../../../tmux/manager.js');
|
|
158
|
+
const { forwardMessages } = await import('./agent-monitoring.js');
|
|
159
|
+
const mockDb = { provider: {}, save: vi.fn() };
|
|
160
|
+
const mockPaths = { hiveDir: '/hive' };
|
|
161
|
+
const msg = makeMessage();
|
|
162
|
+
const agent = makeAgent();
|
|
163
|
+
vi.mocked(withHiveContext).mockImplementation(async (fn) => fn({ db: mockDb, paths: mockPaths }));
|
|
164
|
+
vi.mocked(getAllPendingMessages).mockResolvedValue([msg]);
|
|
165
|
+
vi.mocked(getAllAgents).mockResolvedValue([agent]);
|
|
166
|
+
vi.mocked(getHiveSessions).mockResolvedValue([{ name: 'hive-agent-b' }]);
|
|
167
|
+
vi.mocked(getManagerSession).mockReturnValue('hive-manager');
|
|
168
|
+
vi.mocked(forwardMessages).mockResolvedValue(undefined);
|
|
169
|
+
const { forwardPendingMessages } = await import('./index.js');
|
|
170
|
+
await forwardPendingMessages(false);
|
|
171
|
+
expect(forwardMessages).toHaveBeenCalledWith('hive-agent-b', [msg], 'claude');
|
|
172
|
+
expect(markMessagesRead).toHaveBeenCalledWith(mockDb.provider, ['msg-1']);
|
|
173
|
+
expect(mockDb.save).toHaveBeenCalled();
|
|
174
|
+
});
|
|
175
|
+
it('skips the manager session', async () => {
|
|
176
|
+
const { withHiveContext } = await import('../../../utils/with-hive-context.js');
|
|
177
|
+
const { getAllPendingMessages, markMessagesRead } = await import('../../../db/queries/messages.js');
|
|
178
|
+
const { getAllAgents } = await import('../../../db/queries/agents.js');
|
|
179
|
+
const { getHiveSessions, getManagerSession } = await import('../../../tmux/manager.js');
|
|
180
|
+
const { forwardMessages } = await import('./agent-monitoring.js');
|
|
181
|
+
const mockDb = { provider: {}, save: vi.fn() };
|
|
182
|
+
const mockPaths = { hiveDir: '/hive' };
|
|
183
|
+
const msg = makeMessage({ to_session: 'hive-manager' });
|
|
184
|
+
vi.mocked(withHiveContext).mockImplementation(async (fn) => fn({ db: mockDb, paths: mockPaths }));
|
|
185
|
+
vi.mocked(getAllPendingMessages).mockResolvedValue([msg]);
|
|
186
|
+
vi.mocked(getAllAgents).mockResolvedValue([]);
|
|
187
|
+
vi.mocked(getHiveSessions).mockResolvedValue([{ name: 'hive-manager' }]);
|
|
188
|
+
vi.mocked(getManagerSession).mockReturnValue('hive-manager');
|
|
189
|
+
const { forwardPendingMessages } = await import('./index.js');
|
|
190
|
+
await forwardPendingMessages(false);
|
|
191
|
+
expect(forwardMessages).not.toHaveBeenCalled();
|
|
192
|
+
expect(markMessagesRead).not.toHaveBeenCalled();
|
|
193
|
+
});
|
|
194
|
+
it('skips sessions not registered in the DB', async () => {
|
|
195
|
+
const { withHiveContext } = await import('../../../utils/with-hive-context.js');
|
|
196
|
+
const { getAllPendingMessages, markMessagesRead } = await import('../../../db/queries/messages.js');
|
|
197
|
+
const { getAllAgents } = await import('../../../db/queries/agents.js');
|
|
198
|
+
const { getHiveSessions, getManagerSession } = await import('../../../tmux/manager.js');
|
|
199
|
+
const { forwardMessages } = await import('./agent-monitoring.js');
|
|
200
|
+
const mockDb = { provider: {}, save: vi.fn() };
|
|
201
|
+
const mockPaths = { hiveDir: '/hive' };
|
|
202
|
+
const msg = makeMessage({ to_session: 'hive-unknown' });
|
|
203
|
+
vi.mocked(withHiveContext).mockImplementation(async (fn) => fn({ db: mockDb, paths: mockPaths }));
|
|
204
|
+
vi.mocked(getAllPendingMessages).mockResolvedValue([msg]);
|
|
205
|
+
vi.mocked(getAllAgents).mockResolvedValue([]); // no agents registered
|
|
206
|
+
vi.mocked(getHiveSessions).mockResolvedValue([{ name: 'hive-unknown' }]);
|
|
207
|
+
vi.mocked(getManagerSession).mockReturnValue('hive-manager');
|
|
208
|
+
const { forwardPendingMessages } = await import('./index.js');
|
|
209
|
+
await forwardPendingMessages(false);
|
|
210
|
+
expect(forwardMessages).not.toHaveBeenCalled();
|
|
211
|
+
expect(markMessagesRead).not.toHaveBeenCalled();
|
|
212
|
+
});
|
|
213
|
+
it('handles errors without throwing', async () => {
|
|
214
|
+
const { withHiveContext } = await import('../../../utils/with-hive-context.js');
|
|
215
|
+
vi.mocked(withHiveContext).mockRejectedValue(new Error('DB unavailable'));
|
|
216
|
+
const { forwardPendingMessages } = await import('./index.js');
|
|
217
|
+
// Should not throw
|
|
218
|
+
await expect(forwardPendingMessages(false)).resolves.toBeUndefined();
|
|
219
|
+
});
|
|
220
|
+
it('uses hive-<id> session name pattern to resolve agents', async () => {
|
|
221
|
+
const { withHiveContext } = await import('../../../utils/with-hive-context.js');
|
|
222
|
+
const { getAllPendingMessages, markMessagesRead } = await import('../../../db/queries/messages.js');
|
|
223
|
+
const { getAllAgents } = await import('../../../db/queries/agents.js');
|
|
224
|
+
const { getHiveSessions, getManagerSession } = await import('../../../tmux/manager.js');
|
|
225
|
+
const { forwardMessages } = await import('./agent-monitoring.js');
|
|
226
|
+
const mockDb = { provider: {}, save: vi.fn() };
|
|
227
|
+
const mockPaths = { hiveDir: '/hive' };
|
|
228
|
+
// Agent with no tmux_session set — should still be found via hive-<id> pattern
|
|
229
|
+
const agent = makeAgent({ id: 'xyz', tmux_session: null });
|
|
230
|
+
const msg = makeMessage({ to_session: 'hive-xyz' });
|
|
231
|
+
vi.mocked(withHiveContext).mockImplementation(async (fn) => fn({ db: mockDb, paths: mockPaths }));
|
|
232
|
+
vi.mocked(getAllPendingMessages).mockResolvedValue([msg]);
|
|
233
|
+
vi.mocked(getAllAgents).mockResolvedValue([agent]);
|
|
234
|
+
vi.mocked(getHiveSessions).mockResolvedValue([{ name: 'hive-xyz' }]);
|
|
235
|
+
vi.mocked(getManagerSession).mockReturnValue('hive-manager');
|
|
236
|
+
vi.mocked(forwardMessages).mockResolvedValue(undefined);
|
|
237
|
+
const { forwardPendingMessages } = await import('./index.js');
|
|
238
|
+
await forwardPendingMessages(false);
|
|
239
|
+
expect(forwardMessages).toHaveBeenCalledWith('hive-xyz', [msg], 'claude');
|
|
240
|
+
expect(markMessagesRead).toHaveBeenCalledWith(mockDb.provider, ['msg-1']);
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
//# sourceMappingURL=fast-message-forwarding.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fast-message-forwarding.test.js","sourceRoot":"","sources":["../../../../src/cli/commands/manager/fast-message-forwarding.test.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAE7D,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAI9D,wEAAwE;AACxE,EAAE,CAAC,IAAI,CAAC,qCAAqC,EAAE,GAAG,EAAE,CAAC,CAAC;IACpD,eAAe,EAAE,EAAE,CAAC,EAAE,EAAE;CACzB,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,iCAAiC,EAAE,GAAG,EAAE,CAAC,CAAC;IAChD,qBAAqB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC9B,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE;CAC1B,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,+BAA+B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC9C,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE;IACrB,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE;CACtB,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,CAAC;IACzC,eAAe,EAAE,EAAE,CAAC,EAAE,EAAE;IACxB,iBAAiB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC1B,eAAe,EAAE,EAAE,CAAC,EAAE,EAAE;IACxB,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE;IACzB,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE;IACpB,eAAe,EAAE,EAAE,CAAC,EAAE,EAAE;IACxB,oBAAoB,EAAE,EAAE,CAAC,EAAE,EAAE;CAC9B,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,uBAAuB,EAAE,GAAG,EAAE,CAAC,CAAC;IACtC,eAAe,EAAE,EAAE,CAAC,EAAE,EAAE;IACxB,WAAW,EAAE,IAAI,GAAG,EAAE;IACtB,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE;IACzB,iBAAiB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC1B,kBAAkB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC3B,sBAAsB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC/B,kBAAkB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC3B,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;IACnB,wBAAwB,EAAE,EAAE,CAAC,EAAE,EAAE;CAClC,CAAC,CAAC,CAAC;AAEJ,2DAA2D;AAC3D,EAAE,CAAC,IAAI,CAAC,2BAA2B,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACtE,EAAE,CAAC,IAAI,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACjE,EAAE,CAAC,IAAI,CAAC,oCAAoC,EAAE,GAAG,EAAE,CAAC,CAAC;IACnD,qBAAqB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC9B,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE;CAC1B,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,6BAA6B,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACvE,EAAE,CAAC,IAAI,CAAC,sCAAsC,EAAE,GAAG,EAAE,CAAC,CAAC;IACrD,uBAAuB,EAAE,EAAE,CAAC,EAAE,EAAE;IAChC,iBAAiB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC1B,uBAAuB,EAAE,EAAE,CAAC,EAAE,EAAE;CACjC,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,gCAAgC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAC7E,EAAE,CAAC,IAAI,CAAC,oCAAoC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAC9E,EAAE,CAAC,IAAI,CAAC,6BAA6B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5C,cAAc,EAAE,EAAE,CAAC,EAAE,EAAE;IACvB,uBAAuB,EAAE,EAAE,CAAC,EAAE,EAAE;CACjC,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,sDAAsD,EAAE,GAAG,EAAE,CAAC,CAAC;IACrE,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE;CAC1B,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,8BAA8B,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,oBAAoB,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACnF,EAAE,CAAC,IAAI,CAAC,4BAA4B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3C,kBAAkB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC3B,sBAAsB,EAAE,EAAE,CAAC,EAAE,EAAE;CAChC,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,oBAAoB,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAC7E,EAAE,CAAC,IAAI,CAAC,sBAAsB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,wBAAwB,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAC/E,EAAE,CAAC,IAAI,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,0BAA0B,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACnF,EAAE,CAAC,IAAI,CAAC,yBAAyB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,wBAAwB,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAClF,EAAE,CAAC,IAAI,CAAC,uBAAuB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,mBAAmB,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3E,EAAE,CAAC,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,sBAAsB,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACjF,EAAE,CAAC,IAAI,CAAC,uBAAuB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,4BAA4B,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACpF,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAAC,CAAC;IACnC,cAAc,EAAE,EAAE,CAAC,EAAE,EAAE;IACvB,yBAAyB,EAAE,EAAE,CAAC,EAAE,EAAE;IAClC,oCAAoC,EAAE,EAAE,CAAC,EAAE,EAAE;IAC7C,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE;IACzB,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;IACnB,aAAa,EAAE,EAAE,CAAC,EAAE,EAAE;CACvB,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,2BAA2B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1C,0CAA0C,EAAE,EAAE,CAAC,EAAE,EAAE;CACpD,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC;IACvC,mBAAmB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC5B,4BAA4B,EAAE,EAAE,CAAC,EAAE,EAAE;IACrC,iBAAiB,EAAE,EAAE,CAAC,EAAE,EAAE;CAC3B,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,2BAA2B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1C,aAAa,EAAE,EAAE,CAAC,EAAE,EAAE;IACtB,8BAA8B,EAAE,EAAE,CAAC,EAAE,EAAE;IACvC,wBAAwB,EAAE,EAAE,CAAC,EAAE,EAAE;IACjC,aAAa,EAAE,EAAE,CAAC,EAAE,EAAE;IACtB,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE;CACrB,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/B,kBAAkB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC3B,oBAAoB,EAAE,EAAE,CAAC,EAAE,EAAE;CAC9B,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,2BAA2B,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACpF,EAAE,CAAC,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,CAAC;IACzC,mCAAmC,EAAE,EAAE,CAAC,EAAE,EAAE;IAC5C,sBAAsB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC/B,yBAAyB,EAAE,EAAE,CAAC,EAAE,EAAE;IAClC,yCAAyC,EAAE,EAAE,CAAC,EAAE,EAAE;IAClD,iCAAiC,EAAE,EAAE,CAAC,EAAE,EAAE;IAC1C,qBAAqB,EAAE,IAAI,GAAG,EAAE;CACjC,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,4BAA4B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3C,oBAAoB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC7B,gCAAgC,EAAE,EAAE,CAAC,EAAE,EAAE;IACzC,iBAAiB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC1B,qBAAqB,EAAE,EAAE,CAAC,EAAE,EAAE;CAC/B,CAAC,CAAC,CAAC;AACJ,EAAE,CAAC,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,oBAAoB,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAC/E,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAAC,CAAC;IACnC,yBAAyB,EAAE,EAAE,CAAC,EAAE,EAAE;IAClC,kCAAkC,EAAE,EAAE,CAAC,EAAE,EAAE;CAC5C,CAAC,CAAC,CAAC;AAEJ,SAAS,WAAW,CAAC,YAAiC,EAAE;IACtD,OAAO;QACL,EAAE,EAAE,OAAO;QACX,YAAY,EAAE,cAAc;QAC5B,UAAU,EAAE,cAAc;QAC1B,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,SAAS;QACjB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,GAAG,SAAS;KACC,CAAC;AAClB,CAAC;AAED,SAAS,SAAS,CAAC,YAA+B,EAAE;IAClD,OAAO;QACL,EAAE,EAAE,SAAS;QACb,YAAY,EAAE,cAAc;QAC5B,QAAQ,EAAE,QAAQ;QAClB,gBAAgB,EAAE,IAAI;QACtB,GAAG,SAAS;KACD,CAAC;AAChB,CAAC;AAED,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,qCAAqC,CAAC,CAAC;QAChF,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,iCAAiC,CAAC,CAAC;QAClF,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAElE,MAAM,MAAM,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;QAEvC,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,kBAAkB,CAAC,KAAK,EAAC,EAAE,EAAC,EAAE,CACvD,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAW,CAAC,CAC9C,CAAC;QACF,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QAEvD,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAC9D,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAEpC,MAAM,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,qCAAqC,CAAC,CAAC;QAChF,MAAM,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,GAC/C,MAAM,MAAM,CAAC,iCAAiC,CAAC,CAAC;QAClD,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,+BAA+B,CAAC,CAAC;QACvE,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;QACxF,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAElE,MAAM,MAAM,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;QAE1B,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,kBAAkB,CAAC,KAAK,EAAC,EAAE,EAAC,EAAE,CACvD,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAW,CAAC,CAC9C,CAAC;QACF,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,iBAAiB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACnD,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAU,CAAC,CAAC;QAClF,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;QAC7D,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAExD,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAC9D,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAEpC,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAAC,cAAc,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC9E,MAAM,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAC1E,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;QACzC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,qCAAqC,CAAC,CAAC;QAChF,MAAM,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,GAC/C,MAAM,MAAM,CAAC,iCAAiC,CAAC,CAAC;QAClD,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,+BAA+B,CAAC,CAAC;QACvE,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;QACxF,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAElE,MAAM,MAAM,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,WAAW,CAAC,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC,CAAC;QAExD,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,kBAAkB,CAAC,KAAK,EAAC,EAAE,EAAC,EAAE,CACvD,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAW,CAAC,CAC9C,CAAC;QACF,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QAC9C,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAU,CAAC,CAAC;QAClF,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;QAE7D,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAC9D,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAEpC,MAAM,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAC/C,MAAM,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,qCAAqC,CAAC,CAAC;QAChF,MAAM,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,GAC/C,MAAM,MAAM,CAAC,iCAAiC,CAAC,CAAC;QAClD,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,+BAA+B,CAAC,CAAC;QACvE,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;QACxF,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAElE,MAAM,MAAM,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,WAAW,CAAC,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC,CAAC;QAExD,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,kBAAkB,CAAC,KAAK,EAAC,EAAE,EAAC,EAAE,CACvD,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAW,CAAC,CAC9C,CAAC;QACF,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,uBAAuB;QACtE,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAU,CAAC,CAAC;QAClF,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;QAE7D,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAC9D,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAEpC,MAAM,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAC/C,MAAM,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,qCAAqC,CAAC,CAAC;QAEhF,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAE1E,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAC9D,mBAAmB;QACnB,MAAM,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,qCAAqC,CAAC,CAAC;QAChF,MAAM,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,GAC/C,MAAM,MAAM,CAAC,iCAAiC,CAAC,CAAC;QAClD,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,+BAA+B,CAAC,CAAC;QACvE,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;QACxF,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAElE,MAAM,MAAM,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;QACvC,+EAA+E;QAC/E,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,GAAG,GAAG,WAAW,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;QAEpD,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,kBAAkB,CAAC,KAAK,EAAC,EAAE,EAAC,EAAE,CACvD,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAW,CAAC,CAC9C,CAAC;QACF,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,iBAAiB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACnD,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAU,CAAC,CAAC;QAC9E,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;QAC7D,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAExD,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAC9D,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAEpC,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC1E,MAAM,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -14,5 +14,11 @@ interface SummaryLine {
|
|
|
14
14
|
}
|
|
15
15
|
export declare function classifyNoActionSummary(snapshot: NoActionSummarySnapshot): SummaryLine;
|
|
16
16
|
export declare const managerCommand: Command;
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Lightweight fast-path that only forwards pending messages to agents.
|
|
19
|
+
* Called on the message_poll_interval (default 5s) independently of the full
|
|
20
|
+
* manager check cycle. Does NOT perform state detection, escalation handling,
|
|
21
|
+
* PR checks, or any other heavy operations.
|
|
22
|
+
*/
|
|
23
|
+
export declare function forwardPendingMessages(verbose: boolean): Promise<void>;
|
|
18
24
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/manager/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuGpC,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EACL,yCAAyC,EACzC,gCAAgC,GACjC,MAAM,0BAA0B,CAAC;AAYlC,UAAU,uBAAuB;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,wBAAwB,EAAE,MAAM,CAAC;IACjC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,UAAU,WAAW;IACnB,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,uBAAuB,GAAG,WAAW,CA0BtF;AA2FD,eAAO,MAAM,cAAc,SAE1B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/manager/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuGpC,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EACL,yCAAyC,EACzC,gCAAgC,GACjC,MAAM,0BAA0B,CAAC;AAYlC,UAAU,uBAAuB;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,wBAAwB,EAAE,MAAM,CAAC;IACjC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,UAAU,WAAW;IACnB,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,uBAAuB,GAAG,WAAW,CA0BtF;AA2FD,eAAO,MAAM,cAAc,SAE1B,CAAC;AA2sBF;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAmD5E"}
|
|
@@ -213,18 +213,18 @@ managerCommand
|
|
|
213
213
|
const slowInterval = config.cluster.enabled
|
|
214
214
|
? Math.min(config.manager.slow_poll_interval, config.cluster.sync_interval_ms)
|
|
215
215
|
: config.manager.slow_poll_interval;
|
|
216
|
-
|
|
216
|
+
const messagePollInterval = config.manager.message_poll_interval;
|
|
217
|
+
console.log(chalk.cyan(`Manager started (polling every ${slowInterval / 1000}s, messages every ${messagePollInterval / 1000}s)`));
|
|
217
218
|
console.log(chalk.gray('Press Ctrl+C to stop\n'));
|
|
218
219
|
await runCheck();
|
|
219
220
|
if (!options.once) {
|
|
220
221
|
setInterval(() => {
|
|
221
222
|
void runCheck();
|
|
222
223
|
}, slowInterval);
|
|
223
|
-
// Fast message-
|
|
224
|
-
|
|
225
|
-
console.log(chalk.gray(` Fast message polling every ${messagePollInterval / 1000}s`));
|
|
224
|
+
// Fast message-forwarding loop — only queries the messages table and
|
|
225
|
+
// forwards pending messages via tmux. Does not run the full manager cycle.
|
|
226
226
|
setInterval(() => {
|
|
227
|
-
void
|
|
227
|
+
void forwardPendingMessages(verbose);
|
|
228
228
|
}, messagePollInterval);
|
|
229
229
|
}
|
|
230
230
|
else if (releaseLock) {
|
|
@@ -368,50 +368,6 @@ managerCommand
|
|
|
368
368
|
console.log(chalk.green(`Nudged ${session}`));
|
|
369
369
|
});
|
|
370
370
|
});
|
|
371
|
-
export async function runFastMessageCheck(verbose = false) {
|
|
372
|
-
verboseLog(verbose, 'fastMessageCheck: start');
|
|
373
|
-
try {
|
|
374
|
-
await withHiveContext(async ({ db }) => {
|
|
375
|
-
const allPendingMessages = await getAllPendingMessages(db.provider);
|
|
376
|
-
if (allPendingMessages.length === 0) {
|
|
377
|
-
verboseLog(verbose, 'fastMessageCheck: no pending messages');
|
|
378
|
-
return;
|
|
379
|
-
}
|
|
380
|
-
verboseLog(verbose, `fastMessageCheck: ${allPendingMessages.length} pending message(s)`);
|
|
381
|
-
const messagesBySession = new Map();
|
|
382
|
-
for (const msg of allPendingMessages) {
|
|
383
|
-
if (!messagesBySession.has(msg.to_session)) {
|
|
384
|
-
messagesBySession.set(msg.to_session, []);
|
|
385
|
-
}
|
|
386
|
-
messagesBySession.get(msg.to_session).push(msg);
|
|
387
|
-
}
|
|
388
|
-
const allAgents = await getAllAgents(db.provider);
|
|
389
|
-
const agentBySession = new Map();
|
|
390
|
-
for (const agent of allAgents) {
|
|
391
|
-
agentBySession.set(`hive-${agent.id}`, agent);
|
|
392
|
-
if (agent.tmux_session) {
|
|
393
|
-
agentBySession.set(agent.tmux_session, agent);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
const forwardedIds = [];
|
|
397
|
-
for (const [sessionName, messages] of messagesBySession) {
|
|
398
|
-
const agent = agentBySession.get(sessionName);
|
|
399
|
-
const cliTool = agent?.cli_tool || 'claude';
|
|
400
|
-
verboseLog(verbose, `fastMessageCheck: forwarding ${messages.length} message(s) to ${sessionName}`);
|
|
401
|
-
await forwardMessages(sessionName, messages, cliTool);
|
|
402
|
-
forwardedIds.push(...messages.map(m => m.id));
|
|
403
|
-
}
|
|
404
|
-
if (forwardedIds.length > 0) {
|
|
405
|
-
markMessagesRead(db.provider, forwardedIds);
|
|
406
|
-
db.save();
|
|
407
|
-
verboseLog(verbose, `fastMessageCheck: marked ${forwardedIds.length} message(s) as read`);
|
|
408
|
-
}
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
|
-
catch (err) {
|
|
412
|
-
verboseLog(verbose, `fastMessageCheck: error ${String(err)}`);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
371
|
async function managerCheck(root, config, clusterRuntime, verbose = false) {
|
|
416
372
|
const timestamp = new Date().toLocaleTimeString();
|
|
417
373
|
console.log(chalk.gray(`[${timestamp}] Manager checking...`));
|
|
@@ -757,6 +713,62 @@ async function resolveOrphanedSessionEscalations(ctx) {
|
|
|
757
713
|
}
|
|
758
714
|
verboseLogCtx(ctx, `resolveOrphanedSessionEscalations: resolved=${resolvedCount}`);
|
|
759
715
|
}
|
|
716
|
+
/**
|
|
717
|
+
* Lightweight fast-path that only forwards pending messages to agents.
|
|
718
|
+
* Called on the message_poll_interval (default 5s) independently of the full
|
|
719
|
+
* manager check cycle. Does NOT perform state detection, escalation handling,
|
|
720
|
+
* PR checks, or any other heavy operations.
|
|
721
|
+
*/
|
|
722
|
+
export async function forwardPendingMessages(verbose) {
|
|
723
|
+
try {
|
|
724
|
+
await withHiveContext(async (ctx) => {
|
|
725
|
+
const { db, paths } = ctx;
|
|
726
|
+
const allPendingMessages = await getAllPendingMessages(db.provider);
|
|
727
|
+
if (allPendingMessages.length === 0)
|
|
728
|
+
return;
|
|
729
|
+
const sessions = await getHiveSessions(paths.hiveDir);
|
|
730
|
+
const managerSession = getManagerSession(paths.hiveDir);
|
|
731
|
+
const allAgents = await getAllAgents(db.provider);
|
|
732
|
+
const agentsBySessionName = new Map();
|
|
733
|
+
for (const agent of allAgents) {
|
|
734
|
+
agentsBySessionName.set(`hive-${agent.id}`, agent);
|
|
735
|
+
if (agent.tmux_session) {
|
|
736
|
+
agentsBySessionName.set(agent.tmux_session, agent);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
const messagesBySession = new Map();
|
|
740
|
+
for (const msg of allPendingMessages) {
|
|
741
|
+
if (!messagesBySession.has(msg.to_session)) {
|
|
742
|
+
messagesBySession.set(msg.to_session, []);
|
|
743
|
+
}
|
|
744
|
+
messagesBySession.get(msg.to_session).push(msg);
|
|
745
|
+
}
|
|
746
|
+
const toMarkRead = [];
|
|
747
|
+
for (const session of sessions) {
|
|
748
|
+
if (session.name === managerSession)
|
|
749
|
+
continue;
|
|
750
|
+
const agent = agentsBySessionName.get(session.name);
|
|
751
|
+
if (!agent)
|
|
752
|
+
continue;
|
|
753
|
+
const unread = messagesBySession.get(session.name) ?? [];
|
|
754
|
+
if (unread.length === 0)
|
|
755
|
+
continue;
|
|
756
|
+
const agentCliTool = (agent.cli_tool ?? 'claude');
|
|
757
|
+
verboseLog(verbose, `fast-forward: ${session.name} forwarding ${unread.length} message(s)`);
|
|
758
|
+
await forwardMessages(session.name, unread, agentCliTool);
|
|
759
|
+
toMarkRead.push(...unread.map(msg => msg.id));
|
|
760
|
+
}
|
|
761
|
+
if (toMarkRead.length > 0) {
|
|
762
|
+
await markMessagesRead(db.provider, toMarkRead);
|
|
763
|
+
db.save();
|
|
764
|
+
verboseLog(verbose, `fast-forward: marked ${toMarkRead.length} message(s) as read`);
|
|
765
|
+
}
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
catch (err) {
|
|
769
|
+
console.error(chalk.red('Message forwarding error:'), err);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
760
772
|
async function scanAgentSessions(ctx) {
|
|
761
773
|
// Phase 1: Batch fetch pending messages (brief lock)
|
|
762
774
|
const [allPendingMessages, allPendingBtwMessages] = await ctx.withDb(async (db) => Promise.all([getAllPendingMessages(db.provider), getAllPendingBtwMessages(db.provider)]));
|