sylas-edge-worker 0.2.21
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/README.md +293 -0
- package/dist/ActivityPoster.d.ts +15 -0
- package/dist/ActivityPoster.d.ts.map +1 -0
- package/dist/ActivityPoster.js +194 -0
- package/dist/ActivityPoster.js.map +1 -0
- package/dist/AgentSessionManager.d.ts +280 -0
- package/dist/AgentSessionManager.d.ts.map +1 -0
- package/dist/AgentSessionManager.js +1412 -0
- package/dist/AgentSessionManager.js.map +1 -0
- package/dist/AskUserQuestionHandler.d.ts +97 -0
- package/dist/AskUserQuestionHandler.d.ts.map +1 -0
- package/dist/AskUserQuestionHandler.js +206 -0
- package/dist/AskUserQuestionHandler.js.map +1 -0
- package/dist/AttachmentService.d.ts +69 -0
- package/dist/AttachmentService.d.ts.map +1 -0
- package/dist/AttachmentService.js +369 -0
- package/dist/AttachmentService.js.map +1 -0
- package/dist/ChatSessionHandler.d.ts +87 -0
- package/dist/ChatSessionHandler.d.ts.map +1 -0
- package/dist/ChatSessionHandler.js +231 -0
- package/dist/ChatSessionHandler.js.map +1 -0
- package/dist/ConfigManager.d.ts +91 -0
- package/dist/ConfigManager.d.ts.map +1 -0
- package/dist/ConfigManager.js +227 -0
- package/dist/ConfigManager.js.map +1 -0
- package/dist/EdgeWorker.d.ts +670 -0
- package/dist/EdgeWorker.d.ts.map +1 -0
- package/dist/EdgeWorker.js +3801 -0
- package/dist/EdgeWorker.js.map +1 -0
- package/dist/GitService.d.ts +39 -0
- package/dist/GitService.d.ts.map +1 -0
- package/dist/GitService.js +432 -0
- package/dist/GitService.js.map +1 -0
- package/dist/GlobalSessionRegistry.d.ts +142 -0
- package/dist/GlobalSessionRegistry.d.ts.map +1 -0
- package/dist/GlobalSessionRegistry.js +254 -0
- package/dist/GlobalSessionRegistry.js.map +1 -0
- package/dist/PromptBuilder.d.ts +175 -0
- package/dist/PromptBuilder.d.ts.map +1 -0
- package/dist/PromptBuilder.js +884 -0
- package/dist/PromptBuilder.js.map +1 -0
- package/dist/RepositoryRouter.d.ts +152 -0
- package/dist/RepositoryRouter.d.ts.map +1 -0
- package/dist/RepositoryRouter.js +480 -0
- package/dist/RepositoryRouter.js.map +1 -0
- package/dist/RunnerSelectionService.d.ts +62 -0
- package/dist/RunnerSelectionService.d.ts.map +1 -0
- package/dist/RunnerSelectionService.js +379 -0
- package/dist/RunnerSelectionService.js.map +1 -0
- package/dist/SharedApplicationServer.d.ts +107 -0
- package/dist/SharedApplicationServer.d.ts.map +1 -0
- package/dist/SharedApplicationServer.js +247 -0
- package/dist/SharedApplicationServer.js.map +1 -0
- package/dist/SharedWebhookServer.d.ts +39 -0
- package/dist/SharedWebhookServer.d.ts.map +1 -0
- package/dist/SharedWebhookServer.js +150 -0
- package/dist/SharedWebhookServer.js.map +1 -0
- package/dist/SlackChatAdapter.d.ts +25 -0
- package/dist/SlackChatAdapter.d.ts.map +1 -0
- package/dist/SlackChatAdapter.js +143 -0
- package/dist/SlackChatAdapter.js.map +1 -0
- package/dist/UserAccessControl.d.ts +69 -0
- package/dist/UserAccessControl.d.ts.map +1 -0
- package/dist/UserAccessControl.js +171 -0
- package/dist/UserAccessControl.js.map +1 -0
- package/dist/WorktreeIncludeService.d.ts +32 -0
- package/dist/WorktreeIncludeService.d.ts.map +1 -0
- package/dist/WorktreeIncludeService.js +123 -0
- package/dist/WorktreeIncludeService.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/label-prompt-template.md +27 -0
- package/dist/procedures/ProcedureAnalyzer.d.ts +69 -0
- package/dist/procedures/ProcedureAnalyzer.d.ts.map +1 -0
- package/dist/procedures/ProcedureAnalyzer.js +271 -0
- package/dist/procedures/ProcedureAnalyzer.js.map +1 -0
- package/dist/procedures/index.d.ts +7 -0
- package/dist/procedures/index.d.ts.map +1 -0
- package/dist/procedures/index.js +7 -0
- package/dist/procedures/index.js.map +1 -0
- package/dist/procedures/registry.d.ts +156 -0
- package/dist/procedures/registry.d.ts.map +1 -0
- package/dist/procedures/registry.js +240 -0
- package/dist/procedures/registry.js.map +1 -0
- package/dist/procedures/types.d.ts +103 -0
- package/dist/procedures/types.d.ts.map +1 -0
- package/dist/procedures/types.js +5 -0
- package/dist/procedures/types.js.map +1 -0
- package/dist/prompt-assembly/types.d.ts +80 -0
- package/dist/prompt-assembly/types.d.ts.map +1 -0
- package/dist/prompt-assembly/types.js +8 -0
- package/dist/prompt-assembly/types.js.map +1 -0
- package/dist/prompts/builder.md +191 -0
- package/dist/prompts/debugger.md +128 -0
- package/dist/prompts/graphite-orchestrator.md +362 -0
- package/dist/prompts/orchestrator.md +290 -0
- package/dist/prompts/scoper.md +95 -0
- package/dist/prompts/standard-issue-assigned-user-prompt.md +33 -0
- package/dist/prompts/subroutines/changelog-update.md +79 -0
- package/dist/prompts/subroutines/coding-activity.md +12 -0
- package/dist/prompts/subroutines/concise-summary.md +67 -0
- package/dist/prompts/subroutines/debugger-fix.md +92 -0
- package/dist/prompts/subroutines/debugger-reproduction.md +74 -0
- package/dist/prompts/subroutines/full-delegation.md +68 -0
- package/dist/prompts/subroutines/get-approval.md +175 -0
- package/dist/prompts/subroutines/gh-pr.md +80 -0
- package/dist/prompts/subroutines/git-commit.md +37 -0
- package/dist/prompts/subroutines/plan-summary.md +21 -0
- package/dist/prompts/subroutines/preparation.md +16 -0
- package/dist/prompts/subroutines/question-answer.md +8 -0
- package/dist/prompts/subroutines/question-investigation.md +8 -0
- package/dist/prompts/subroutines/release-execution.md +81 -0
- package/dist/prompts/subroutines/release-summary.md +60 -0
- package/dist/prompts/subroutines/user-testing-summary.md +87 -0
- package/dist/prompts/subroutines/user-testing.md +48 -0
- package/dist/prompts/subroutines/validation-fixer.md +56 -0
- package/dist/prompts/subroutines/verbose-summary.md +46 -0
- package/dist/prompts/subroutines/verifications.md +77 -0
- package/dist/prompts/todolist-system-prompt-extension.md +15 -0
- package/dist/sinks/IActivitySink.d.ts +60 -0
- package/dist/sinks/IActivitySink.d.ts.map +1 -0
- package/dist/sinks/IActivitySink.js +2 -0
- package/dist/sinks/IActivitySink.js.map +1 -0
- package/dist/sinks/LinearActivitySink.d.ts +69 -0
- package/dist/sinks/LinearActivitySink.d.ts.map +1 -0
- package/dist/sinks/LinearActivitySink.js +111 -0
- package/dist/sinks/LinearActivitySink.js.map +1 -0
- package/dist/sinks/NoopActivitySink.d.ts +13 -0
- package/dist/sinks/NoopActivitySink.d.ts.map +1 -0
- package/dist/sinks/NoopActivitySink.js +17 -0
- package/dist/sinks/NoopActivitySink.js.map +1 -0
- package/dist/sinks/index.d.ts +9 -0
- package/dist/sinks/index.d.ts.map +1 -0
- package/dist/sinks/index.js +8 -0
- package/dist/sinks/index.js.map +1 -0
- package/dist/types.d.ts +32 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/validation/ValidationLoopController.d.ts +54 -0
- package/dist/validation/ValidationLoopController.d.ts.map +1 -0
- package/dist/validation/ValidationLoopController.js +242 -0
- package/dist/validation/ValidationLoopController.js.map +1 -0
- package/dist/validation/index.d.ts +7 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +7 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/types.d.ts +82 -0
- package/dist/validation/types.d.ts.map +1 -0
- package/dist/validation/types.js +29 -0
- package/dist/validation/types.js.map +1 -0
- package/label-prompt-template.md +27 -0
- package/package.json +56 -0
- package/prompt-template.md +116 -0
- package/prompts/builder.md +191 -0
- package/prompts/debugger.md +128 -0
- package/prompts/graphite-orchestrator.md +362 -0
- package/prompts/orchestrator.md +290 -0
- package/prompts/scoper.md +95 -0
- package/prompts/standard-issue-assigned-user-prompt.md +33 -0
- package/prompts/todolist-system-prompt-extension.md +15 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { mkdir } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { ClaudeRunner, getAllTools } from "sylas-claude-runner";
|
|
4
|
+
import { createLogger } from "sylas-core";
|
|
5
|
+
import { AgentSessionManager } from "./AgentSessionManager.js";
|
|
6
|
+
import { NoopActivitySink } from "./sinks/NoopActivitySink.js";
|
|
7
|
+
/**
|
|
8
|
+
* Generic session lifecycle engine for chat platform integrations.
|
|
9
|
+
*
|
|
10
|
+
* Manages the create/resume/inject/reply session lifecycle independent of any
|
|
11
|
+
* specific chat platform. Platform-specific behavior is provided via a
|
|
12
|
+
* ChatPlatformAdapter.
|
|
13
|
+
*/
|
|
14
|
+
export class ChatSessionHandler {
|
|
15
|
+
adapter;
|
|
16
|
+
sessionManager;
|
|
17
|
+
threadSessions = new Map();
|
|
18
|
+
deps;
|
|
19
|
+
logger;
|
|
20
|
+
constructor(adapter, deps, logger) {
|
|
21
|
+
this.adapter = adapter;
|
|
22
|
+
this.deps = deps;
|
|
23
|
+
this.logger = logger ?? createLogger({ component: "ChatSessionHandler" });
|
|
24
|
+
// Initialize a dedicated AgentSessionManager (not tied to any repository)
|
|
25
|
+
const activitySink = new NoopActivitySink(adapter.platformName);
|
|
26
|
+
this.sessionManager = new AgentSessionManager(activitySink, undefined, // No parent session lookup
|
|
27
|
+
undefined, // No resume parent session
|
|
28
|
+
undefined, // No procedure analyzer
|
|
29
|
+
undefined);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Main entry point â handles a single chat platform event.
|
|
33
|
+
*
|
|
34
|
+
* Replaces the per-platform handleXxxWebhook method in EdgeWorker.
|
|
35
|
+
*/
|
|
36
|
+
async handleEvent(event) {
|
|
37
|
+
this.deps.onWebhookStart();
|
|
38
|
+
try {
|
|
39
|
+
this.logger.info(`Processing ${this.adapter.platformName} webhook: ${this.adapter.getEventId(event)}`);
|
|
40
|
+
// Fire-and-forget acknowledgement (e.g., emoji reaction)
|
|
41
|
+
this.adapter.acknowledgeReceipt(event).catch((err) => {
|
|
42
|
+
this.logger.warn(`Failed to acknowledge ${this.adapter.platformName} event: ${err instanceof Error ? err.message : err}`);
|
|
43
|
+
});
|
|
44
|
+
const taskInstructions = this.adapter.extractTaskInstructions(event);
|
|
45
|
+
const threadKey = this.adapter.getThreadKey(event);
|
|
46
|
+
// Check if there's already an active session for this thread
|
|
47
|
+
const existingSessionId = this.threadSessions.get(threadKey);
|
|
48
|
+
if (existingSessionId) {
|
|
49
|
+
const existingSession = this.sessionManager.getSession(existingSessionId);
|
|
50
|
+
const existingRunner = this.sessionManager.getAgentRunner(existingSessionId);
|
|
51
|
+
if (existingSession && existingRunner?.isRunning()) {
|
|
52
|
+
// Session is actively running â inject the follow-up via streaming input
|
|
53
|
+
if (existingRunner.addStreamMessage &&
|
|
54
|
+
existingRunner.isStreaming?.()) {
|
|
55
|
+
this.logger.info(`Injecting follow-up prompt into running session ${existingSessionId} (thread ${threadKey})`);
|
|
56
|
+
existingRunner.addStreamMessage(taskInstructions);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// Runner doesn't support streaming input or isn't in streaming mode â notify user
|
|
60
|
+
this.logger.info(`Session ${existingSessionId} is still running, notifying user (thread ${threadKey})`);
|
|
61
|
+
await this.adapter.notifyBusy(event, threadKey);
|
|
62
|
+
}
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (existingSession && existingRunner) {
|
|
66
|
+
// Session exists but is not running â resume with --continue
|
|
67
|
+
this.logger.info(`Resuming completed ${this.adapter.platformName} session ${existingSessionId} (thread ${threadKey})`);
|
|
68
|
+
const resumeSessionId = existingSession.claudeSessionId ||
|
|
69
|
+
existingSession.geminiSessionId ||
|
|
70
|
+
existingSession.codexSessionId ||
|
|
71
|
+
existingSession.cursorSessionId ||
|
|
72
|
+
existingSession.openCodeSessionId;
|
|
73
|
+
if (resumeSessionId) {
|
|
74
|
+
try {
|
|
75
|
+
await this.resumeSession(event, existingSession, existingSessionId, resumeSessionId, taskInstructions);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
this.logger.error(`Failed to resume ${this.adapter.platformName} session ${existingSessionId}`, error instanceof Error ? error : new Error(String(error)));
|
|
79
|
+
}
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Session exists but runner was lost â fall through to create a new session
|
|
84
|
+
this.logger.info(`Previous session ${existingSessionId} for thread ${threadKey} has no runner, creating new session`);
|
|
85
|
+
}
|
|
86
|
+
// Create an empty workspace directory for this thread
|
|
87
|
+
const workspace = await this.createWorkspace(threadKey);
|
|
88
|
+
if (!workspace) {
|
|
89
|
+
this.logger.error(`Failed to create workspace for ${this.adapter.platformName} thread ${threadKey}`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
this.logger.info(`${this.adapter.platformName} workspace created at: ${workspace.path}`);
|
|
93
|
+
// Create a chat session (not tied to any issue or repository)
|
|
94
|
+
const eventId = this.adapter.getEventId(event);
|
|
95
|
+
const sessionId = `${this.adapter.platformName}-${eventId}`;
|
|
96
|
+
this.sessionManager.createChatSession(sessionId, workspace, this.adapter.platformName);
|
|
97
|
+
const session = this.sessionManager.getSession(sessionId);
|
|
98
|
+
if (!session) {
|
|
99
|
+
this.logger.error(`Failed to create session for ${this.adapter.platformName} webhook ${eventId}`);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// Track this thread â session mapping for follow-up messages
|
|
103
|
+
this.threadSessions.set(threadKey, sessionId);
|
|
104
|
+
// Initialize procedure metadata
|
|
105
|
+
if (!session.metadata) {
|
|
106
|
+
session.metadata = {};
|
|
107
|
+
}
|
|
108
|
+
// Build the system prompt
|
|
109
|
+
const systemPrompt = this.adapter.buildSystemPrompt(event);
|
|
110
|
+
// Build runner config
|
|
111
|
+
const runnerConfig = this.buildRunnerConfig(session.workspace.path, sessionId, systemPrompt, sessionId);
|
|
112
|
+
const runner = new ClaudeRunner(runnerConfig);
|
|
113
|
+
// Store the runner in the session manager
|
|
114
|
+
this.sessionManager.addAgentRunner(sessionId, runner);
|
|
115
|
+
// Save persisted state
|
|
116
|
+
await this.deps.onStateChange();
|
|
117
|
+
// Fetch thread context for threaded mentions
|
|
118
|
+
const threadContext = await this.adapter.fetchThreadContext(event);
|
|
119
|
+
const userPrompt = threadContext
|
|
120
|
+
? `${threadContext}\n\n${taskInstructions}`
|
|
121
|
+
: taskInstructions;
|
|
122
|
+
this.logger.info(`Starting Claude runner for ${this.adapter.platformName} event ${eventId}`);
|
|
123
|
+
// Start in streaming mode so follow-up messages in the same thread
|
|
124
|
+
// can be injected via addStreamMessage() while the session is running
|
|
125
|
+
try {
|
|
126
|
+
const sessionInfo = await runner.startStreaming(userPrompt);
|
|
127
|
+
this.logger.info(`${this.adapter.platformName} session started: ${sessionInfo.sessionId}`);
|
|
128
|
+
// When session completes, post the reply back
|
|
129
|
+
await this.adapter.postReply(event, runner);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
this.logger.error(`${this.adapter.platformName} session error for event ${eventId}`, error instanceof Error ? error : new Error(String(error)));
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
await this.deps.onStateChange();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
this.logger.error(`Failed to process ${this.adapter.platformName} webhook`, error instanceof Error ? error : new Error(String(error)));
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
this.deps.onWebhookEnd();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/** Returns true if any runner managed by this handler is currently busy */
|
|
146
|
+
isAnyRunnerBusy() {
|
|
147
|
+
for (const runner of this.sessionManager.getAllAgentRunners()) {
|
|
148
|
+
if (runner.isRunning()) {
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
/** Returns all runners managed by this handler (for shutdown) */
|
|
155
|
+
getAllRunners() {
|
|
156
|
+
return this.sessionManager.getAllAgentRunners();
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Resume an existing session with a new prompt (--continue behavior).
|
|
160
|
+
*/
|
|
161
|
+
async resumeSession(event, existingSession, sessionId, resumeSessionId, taskInstructions) {
|
|
162
|
+
const systemPrompt = this.adapter.buildSystemPrompt(event);
|
|
163
|
+
const runnerConfig = this.buildRunnerConfig(existingSession.workspace.path, sessionId, systemPrompt, sessionId, resumeSessionId);
|
|
164
|
+
const runner = new ClaudeRunner(runnerConfig);
|
|
165
|
+
this.sessionManager.addAgentRunner(sessionId, runner);
|
|
166
|
+
try {
|
|
167
|
+
const sessionInfo = await runner.startStreaming(taskInstructions);
|
|
168
|
+
this.logger.info(`${this.adapter.platformName} session resumed: ${sessionInfo.sessionId} (was ${resumeSessionId})`);
|
|
169
|
+
await this.adapter.postReply(event, runner);
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
this.logger.error(`${this.adapter.platformName} resume session error for ${sessionId}`, error instanceof Error ? error : new Error(String(error)));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Handle Claude messages for chat sessions.
|
|
177
|
+
* Routes to the dedicated AgentSessionManager.
|
|
178
|
+
*/
|
|
179
|
+
async handleClaudeMessage(sessionId, message) {
|
|
180
|
+
await this.sessionManager.handleClaudeMessage(sessionId, message);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Create an empty workspace directory for a chat thread.
|
|
184
|
+
* Unlike repository-associated sessions, chat sessions use plain directories (not git worktrees).
|
|
185
|
+
*/
|
|
186
|
+
async createWorkspace(threadKey) {
|
|
187
|
+
try {
|
|
188
|
+
const sanitizedKey = threadKey.replace(/[^a-zA-Z0-9.-]/g, "_");
|
|
189
|
+
const workspacePath = join(this.deps.sylasHome, `${this.adapter.platformName}-workspaces`, sanitizedKey);
|
|
190
|
+
await mkdir(workspacePath, { recursive: true });
|
|
191
|
+
return { path: workspacePath, isGitWorktree: false };
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
this.logger.error(`Failed to create ${this.adapter.platformName} workspace for thread ${threadKey}`, error instanceof Error ? error : new Error(String(error)));
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Build a ClaudeRunner config for a chat session.
|
|
200
|
+
* Used by both handleEvent (new session) and resumeSession to eliminate duplication.
|
|
201
|
+
*/
|
|
202
|
+
buildRunnerConfig(workspacePath, workspaceName, systemPrompt, sessionId, resumeSessionId) {
|
|
203
|
+
// When MCP servers are configured, include their tool permissions
|
|
204
|
+
const mcpToolPermissions = this.deps.mcpConfig
|
|
205
|
+
? Object.keys(this.deps.mcpConfig).map((server) => `mcp__${server}`)
|
|
206
|
+
: [];
|
|
207
|
+
return {
|
|
208
|
+
workingDirectory: workspacePath,
|
|
209
|
+
allowedTools: [...getAllTools(), ...mcpToolPermissions],
|
|
210
|
+
disallowedTools: [],
|
|
211
|
+
allowedDirectories: [workspacePath],
|
|
212
|
+
workspaceName,
|
|
213
|
+
sylasHome: this.deps.sylasHome,
|
|
214
|
+
appendSystemPrompt: systemPrompt,
|
|
215
|
+
model: this.deps.defaultModel,
|
|
216
|
+
fallbackModel: this.deps.defaultFallbackModel,
|
|
217
|
+
...(this.deps.mcpConfig ? { mcpConfig: this.deps.mcpConfig } : {}),
|
|
218
|
+
...(resumeSessionId ? { resumeSessionId } : {}),
|
|
219
|
+
logger: this.logger.withContext({
|
|
220
|
+
sessionId,
|
|
221
|
+
platform: this.adapter.platformName,
|
|
222
|
+
}),
|
|
223
|
+
maxTurns: 200,
|
|
224
|
+
onMessage: (message) => {
|
|
225
|
+
this.handleClaudeMessage(sessionId, message);
|
|
226
|
+
},
|
|
227
|
+
onError: (error) => this.deps.onClaudeError(error),
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=ChatSessionHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatSessionHandler.js","sourceRoot":"","sources":["../src/ChatSessionHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import type { EdgeWorkerConfig, ILogger, RepositoryConfig } from "sylas-core";
|
|
3
|
+
/**
|
|
4
|
+
* Describes the set of repository-level changes detected after a config
|
|
5
|
+
* file reload. Emitted as the payload of the `configChanged` event.
|
|
6
|
+
*/
|
|
7
|
+
export interface RepositoryChanges {
|
|
8
|
+
added: RepositoryConfig[];
|
|
9
|
+
modified: RepositoryConfig[];
|
|
10
|
+
removed: RepositoryConfig[];
|
|
11
|
+
/** The fully-merged new config (caller should replace its reference). */
|
|
12
|
+
newConfig: EdgeWorkerConfig;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Events emitted by ConfigManager.
|
|
16
|
+
*/
|
|
17
|
+
export interface ConfigManagerEvents {
|
|
18
|
+
configChanged: (changes: RepositoryChanges) => void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* ConfigManager is responsible for watching, loading, validating, and
|
|
22
|
+
* diffing the EdgeWorker configuration file. It does **not** perform any
|
|
23
|
+
* repository lifecycle operations (adding / updating / removing session
|
|
24
|
+
* managers, issue trackers, etc.) -- instead it emits a `configChanged`
|
|
25
|
+
* event that the EdgeWorker listens to and acts upon.
|
|
26
|
+
*
|
|
27
|
+
* Usage:
|
|
28
|
+
* ```ts
|
|
29
|
+
* const configManager = new ConfigManager(config, logger, configPath, repositories);
|
|
30
|
+
* configManager.on("configChanged", async (changes) => {
|
|
31
|
+
* await removeDeletedRepositories(changes.removed);
|
|
32
|
+
* await updateModifiedRepositories(changes.modified);
|
|
33
|
+
* await addNewRepositories(changes.added);
|
|
34
|
+
* this.config = changes.newConfig;
|
|
35
|
+
* });
|
|
36
|
+
* configManager.startConfigWatcher();
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare class ConfigManager extends EventEmitter {
|
|
40
|
+
private config;
|
|
41
|
+
private readonly logger;
|
|
42
|
+
private configPath?;
|
|
43
|
+
/** Live reference to EdgeWorker's repository map -- used for diffing. */
|
|
44
|
+
private readonly repositories;
|
|
45
|
+
private configWatcher?;
|
|
46
|
+
constructor(config: EdgeWorkerConfig, logger: ILogger, configPath: string | undefined, repositories: Map<string, RepositoryConfig>);
|
|
47
|
+
/**
|
|
48
|
+
* Start watching the config file for changes. Each detected change
|
|
49
|
+
* triggers a reload-and-diff cycle; if repository-level changes are
|
|
50
|
+
* found a `configChanged` event is emitted.
|
|
51
|
+
*/
|
|
52
|
+
startConfigWatcher(): void;
|
|
53
|
+
/**
|
|
54
|
+
* Stop the config file watcher and release resources.
|
|
55
|
+
*/
|
|
56
|
+
stop(): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Return the current (possibly reloaded) config snapshot.
|
|
59
|
+
*/
|
|
60
|
+
getConfig(): EdgeWorkerConfig;
|
|
61
|
+
/**
|
|
62
|
+
* Update the internal config reference. This is useful when the
|
|
63
|
+
* EdgeWorker needs to push an externally-modified config back into
|
|
64
|
+
* the ConfigManager (e.g. after applying the changes from a
|
|
65
|
+
* `configChanged` event).
|
|
66
|
+
*/
|
|
67
|
+
setConfig(config: EdgeWorkerConfig): void;
|
|
68
|
+
/**
|
|
69
|
+
* Update the config file path (e.g. when set after construction).
|
|
70
|
+
*/
|
|
71
|
+
setConfigPath(configPath: string): void;
|
|
72
|
+
/**
|
|
73
|
+
* Handle a config file change event: load, validate, diff, and emit.
|
|
74
|
+
*/
|
|
75
|
+
private handleConfigChange;
|
|
76
|
+
/**
|
|
77
|
+
* Safely load configuration from the file, merging with the current
|
|
78
|
+
* in-memory config for fields that are not present in the file.
|
|
79
|
+
*/
|
|
80
|
+
private loadConfigSafely;
|
|
81
|
+
/**
|
|
82
|
+
* Detect changes between the current in-memory repository map and
|
|
83
|
+
* the repositories declared in `newConfig`.
|
|
84
|
+
*/
|
|
85
|
+
private detectRepositoryChanges;
|
|
86
|
+
/**
|
|
87
|
+
* Deep equality check for repository configs.
|
|
88
|
+
*/
|
|
89
|
+
private deepEqual;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=ConfigManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfigManager.d.ts","sourceRoot":"","sources":["../src/ConfigManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9E;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,yEAAyE;IACzE,SAAS,EAAE,gBAAgB,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,aAAa,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACpD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,aAAc,SAAQ,YAAY;IAC9C,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,yEAAyE;IACzE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgC;IAC7D,OAAO,CAAC,aAAa,CAAC,CAAY;gBAGjC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,OAAO,EACf,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAa5C;;;;OAIG;IACH,kBAAkB,IAAI,IAAI;IA2B1B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B;;OAEG;IACH,SAAS,IAAI,gBAAgB;IAI7B;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI;IAIzC;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAQvC;;OAEG;YACW,kBAAkB;IAkChC;;;OAGG;YACW,gBAAgB;IA6E9B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAoC/B;;OAEG;IACH,OAAO,CAAC,SAAS;CAGjB"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { watch as chokidarWatch } from "chokidar";
|
|
4
|
+
/**
|
|
5
|
+
* ConfigManager is responsible for watching, loading, validating, and
|
|
6
|
+
* diffing the EdgeWorker configuration file. It does **not** perform any
|
|
7
|
+
* repository lifecycle operations (adding / updating / removing session
|
|
8
|
+
* managers, issue trackers, etc.) -- instead it emits a `configChanged`
|
|
9
|
+
* event that the EdgeWorker listens to and acts upon.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* ```ts
|
|
13
|
+
* const configManager = new ConfigManager(config, logger, configPath, repositories);
|
|
14
|
+
* configManager.on("configChanged", async (changes) => {
|
|
15
|
+
* await removeDeletedRepositories(changes.removed);
|
|
16
|
+
* await updateModifiedRepositories(changes.modified);
|
|
17
|
+
* await addNewRepositories(changes.added);
|
|
18
|
+
* this.config = changes.newConfig;
|
|
19
|
+
* });
|
|
20
|
+
* configManager.startConfigWatcher();
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export class ConfigManager extends EventEmitter {
|
|
24
|
+
config;
|
|
25
|
+
logger;
|
|
26
|
+
configPath;
|
|
27
|
+
/** Live reference to EdgeWorker's repository map -- used for diffing. */
|
|
28
|
+
repositories;
|
|
29
|
+
configWatcher;
|
|
30
|
+
constructor(config, logger, configPath, repositories) {
|
|
31
|
+
super();
|
|
32
|
+
this.config = config;
|
|
33
|
+
this.logger = logger;
|
|
34
|
+
this.configPath = configPath;
|
|
35
|
+
this.repositories = repositories;
|
|
36
|
+
}
|
|
37
|
+
// ------------------------------------------------------------------
|
|
38
|
+
// Public API
|
|
39
|
+
// ------------------------------------------------------------------
|
|
40
|
+
/**
|
|
41
|
+
* Start watching the config file for changes. Each detected change
|
|
42
|
+
* triggers a reload-and-diff cycle; if repository-level changes are
|
|
43
|
+
* found a `configChanged` event is emitted.
|
|
44
|
+
*/
|
|
45
|
+
startConfigWatcher() {
|
|
46
|
+
if (!this.configPath) {
|
|
47
|
+
this.logger.warn("â ī¸ No config path set, skipping config file watcher");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
this.logger.info(`đ Watching config file for changes: ${this.configPath}`);
|
|
51
|
+
this.configWatcher = chokidarWatch(this.configPath, {
|
|
52
|
+
persistent: true,
|
|
53
|
+
ignoreInitial: true,
|
|
54
|
+
awaitWriteFinish: {
|
|
55
|
+
stabilityThreshold: 500,
|
|
56
|
+
pollInterval: 100,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
this.configWatcher.on("change", async () => {
|
|
60
|
+
this.logger.info("đ Config file changed, reloading...");
|
|
61
|
+
await this.handleConfigChange();
|
|
62
|
+
});
|
|
63
|
+
this.configWatcher.on("error", (error) => {
|
|
64
|
+
this.logger.error("â Config watcher error:", error);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Stop the config file watcher and release resources.
|
|
69
|
+
*/
|
|
70
|
+
async stop() {
|
|
71
|
+
if (this.configWatcher) {
|
|
72
|
+
await this.configWatcher.close();
|
|
73
|
+
this.configWatcher = undefined;
|
|
74
|
+
this.logger.info("â
Config file watcher stopped");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Return the current (possibly reloaded) config snapshot.
|
|
79
|
+
*/
|
|
80
|
+
getConfig() {
|
|
81
|
+
return this.config;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Update the internal config reference. This is useful when the
|
|
85
|
+
* EdgeWorker needs to push an externally-modified config back into
|
|
86
|
+
* the ConfigManager (e.g. after applying the changes from a
|
|
87
|
+
* `configChanged` event).
|
|
88
|
+
*/
|
|
89
|
+
setConfig(config) {
|
|
90
|
+
this.config = config;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Update the config file path (e.g. when set after construction).
|
|
94
|
+
*/
|
|
95
|
+
setConfigPath(configPath) {
|
|
96
|
+
this.configPath = configPath;
|
|
97
|
+
}
|
|
98
|
+
// ------------------------------------------------------------------
|
|
99
|
+
// Internal helpers
|
|
100
|
+
// ------------------------------------------------------------------
|
|
101
|
+
/**
|
|
102
|
+
* Handle a config file change event: load, validate, diff, and emit.
|
|
103
|
+
*/
|
|
104
|
+
async handleConfigChange() {
|
|
105
|
+
try {
|
|
106
|
+
const newConfig = await this.loadConfigSafely();
|
|
107
|
+
if (!newConfig) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const changes = this.detectRepositoryChanges(newConfig);
|
|
111
|
+
if (changes.added.length === 0 &&
|
|
112
|
+
changes.modified.length === 0 &&
|
|
113
|
+
changes.removed.length === 0) {
|
|
114
|
+
this.logger.info("âšī¸ No repository changes detected");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
this.logger.info(`đ Repository changes detected: ${changes.added.length} added, ${changes.modified.length} modified, ${changes.removed.length} removed`);
|
|
118
|
+
// Emit the diff so EdgeWorker can orchestrate the mutations.
|
|
119
|
+
this.emit("configChanged", {
|
|
120
|
+
added: changes.added,
|
|
121
|
+
modified: changes.modified,
|
|
122
|
+
removed: changes.removed,
|
|
123
|
+
newConfig,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
this.logger.error("â Failed to reload configuration:", error);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Safely load configuration from the file, merging with the current
|
|
132
|
+
* in-memory config for fields that are not present in the file.
|
|
133
|
+
*/
|
|
134
|
+
async loadConfigSafely() {
|
|
135
|
+
try {
|
|
136
|
+
if (!this.configPath) {
|
|
137
|
+
this.logger.error("â No config path set");
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
const configContent = await readFile(this.configPath, "utf-8");
|
|
141
|
+
const parsedConfig = JSON.parse(configContent);
|
|
142
|
+
// Merge with current EdgeWorker config structure
|
|
143
|
+
const newConfig = {
|
|
144
|
+
...this.config,
|
|
145
|
+
repositories: parsedConfig.repositories || [],
|
|
146
|
+
ngrokAuthToken: parsedConfig.ngrokAuthToken || this.config.ngrokAuthToken,
|
|
147
|
+
linearWorkspaceSlug: parsedConfig.linearWorkspaceSlug || this.config.linearWorkspaceSlug,
|
|
148
|
+
claudeDefaultModel: parsedConfig.claudeDefaultModel ||
|
|
149
|
+
parsedConfig.defaultModel ||
|
|
150
|
+
this.config.claudeDefaultModel ||
|
|
151
|
+
this.config.defaultModel,
|
|
152
|
+
claudeDefaultFallbackModel: parsedConfig.claudeDefaultFallbackModel ||
|
|
153
|
+
parsedConfig.defaultFallbackModel ||
|
|
154
|
+
this.config.claudeDefaultFallbackModel ||
|
|
155
|
+
this.config.defaultFallbackModel,
|
|
156
|
+
geminiDefaultModel: parsedConfig.geminiDefaultModel || this.config.geminiDefaultModel,
|
|
157
|
+
codexDefaultModel: parsedConfig.codexDefaultModel || this.config.codexDefaultModel,
|
|
158
|
+
openCodeDefaultModel: parsedConfig.openCodeDefaultModel || this.config.openCodeDefaultModel,
|
|
159
|
+
defaultModel: parsedConfig.defaultModel || this.config.defaultModel,
|
|
160
|
+
defaultFallbackModel: parsedConfig.defaultFallbackModel || this.config.defaultFallbackModel,
|
|
161
|
+
defaultAllowedTools: parsedConfig.defaultAllowedTools || this.config.defaultAllowedTools,
|
|
162
|
+
defaultDisallowedTools: parsedConfig.defaultDisallowedTools ||
|
|
163
|
+
this.config.defaultDisallowedTools,
|
|
164
|
+
// Issue update trigger: use parsed value if explicitly set,
|
|
165
|
+
// otherwise keep current or default to true
|
|
166
|
+
issueUpdateTrigger: parsedConfig.issueUpdateTrigger ?? this.config.issueUpdateTrigger,
|
|
167
|
+
};
|
|
168
|
+
// Basic validation
|
|
169
|
+
if (!Array.isArray(newConfig.repositories)) {
|
|
170
|
+
this.logger.error("â Invalid config: repositories must be an array");
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
// Validate each repository has required fields
|
|
174
|
+
for (const repo of newConfig.repositories) {
|
|
175
|
+
if (!repo.id ||
|
|
176
|
+
!repo.name ||
|
|
177
|
+
!repo.repositoryPath ||
|
|
178
|
+
!repo.baseBranch) {
|
|
179
|
+
this.logger.error(`â Invalid repository config: missing required fields (id, name, repositoryPath, baseBranch)`, repo);
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return newConfig;
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
this.logger.error("â Failed to load config file:", error);
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Detect changes between the current in-memory repository map and
|
|
192
|
+
* the repositories declared in `newConfig`.
|
|
193
|
+
*/
|
|
194
|
+
detectRepositoryChanges(newConfig) {
|
|
195
|
+
const currentRepos = new Map(this.repositories);
|
|
196
|
+
const newRepos = new Map(newConfig.repositories.map((r) => [r.id, r]));
|
|
197
|
+
const added = [];
|
|
198
|
+
const modified = [];
|
|
199
|
+
const removed = [];
|
|
200
|
+
// Find added and modified repositories
|
|
201
|
+
for (const [id, repo] of newRepos) {
|
|
202
|
+
if (!currentRepos.has(id)) {
|
|
203
|
+
added.push(repo);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
const currentRepo = currentRepos.get(id);
|
|
207
|
+
if (currentRepo && !this.deepEqual(currentRepo, repo)) {
|
|
208
|
+
modified.push(repo);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// Find removed repositories
|
|
213
|
+
for (const [id, repo] of currentRepos) {
|
|
214
|
+
if (!newRepos.has(id)) {
|
|
215
|
+
removed.push(repo);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return { added, modified, removed };
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Deep equality check for repository configs.
|
|
222
|
+
*/
|
|
223
|
+
deepEqual(obj1, obj2) {
|
|
224
|
+
return JSON.stringify(obj1) === JSON.stringify(obj2);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=ConfigManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfigManager.js","sourceRoot":"","sources":["../src/ConfigManager.ts"],"names":[],"mappings":"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"}
|