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.
Files changed (163) hide show
  1. package/README.md +293 -0
  2. package/dist/ActivityPoster.d.ts +15 -0
  3. package/dist/ActivityPoster.d.ts.map +1 -0
  4. package/dist/ActivityPoster.js +194 -0
  5. package/dist/ActivityPoster.js.map +1 -0
  6. package/dist/AgentSessionManager.d.ts +280 -0
  7. package/dist/AgentSessionManager.d.ts.map +1 -0
  8. package/dist/AgentSessionManager.js +1412 -0
  9. package/dist/AgentSessionManager.js.map +1 -0
  10. package/dist/AskUserQuestionHandler.d.ts +97 -0
  11. package/dist/AskUserQuestionHandler.d.ts.map +1 -0
  12. package/dist/AskUserQuestionHandler.js +206 -0
  13. package/dist/AskUserQuestionHandler.js.map +1 -0
  14. package/dist/AttachmentService.d.ts +69 -0
  15. package/dist/AttachmentService.d.ts.map +1 -0
  16. package/dist/AttachmentService.js +369 -0
  17. package/dist/AttachmentService.js.map +1 -0
  18. package/dist/ChatSessionHandler.d.ts +87 -0
  19. package/dist/ChatSessionHandler.d.ts.map +1 -0
  20. package/dist/ChatSessionHandler.js +231 -0
  21. package/dist/ChatSessionHandler.js.map +1 -0
  22. package/dist/ConfigManager.d.ts +91 -0
  23. package/dist/ConfigManager.d.ts.map +1 -0
  24. package/dist/ConfigManager.js +227 -0
  25. package/dist/ConfigManager.js.map +1 -0
  26. package/dist/EdgeWorker.d.ts +670 -0
  27. package/dist/EdgeWorker.d.ts.map +1 -0
  28. package/dist/EdgeWorker.js +3801 -0
  29. package/dist/EdgeWorker.js.map +1 -0
  30. package/dist/GitService.d.ts +39 -0
  31. package/dist/GitService.d.ts.map +1 -0
  32. package/dist/GitService.js +432 -0
  33. package/dist/GitService.js.map +1 -0
  34. package/dist/GlobalSessionRegistry.d.ts +142 -0
  35. package/dist/GlobalSessionRegistry.d.ts.map +1 -0
  36. package/dist/GlobalSessionRegistry.js +254 -0
  37. package/dist/GlobalSessionRegistry.js.map +1 -0
  38. package/dist/PromptBuilder.d.ts +175 -0
  39. package/dist/PromptBuilder.d.ts.map +1 -0
  40. package/dist/PromptBuilder.js +884 -0
  41. package/dist/PromptBuilder.js.map +1 -0
  42. package/dist/RepositoryRouter.d.ts +152 -0
  43. package/dist/RepositoryRouter.d.ts.map +1 -0
  44. package/dist/RepositoryRouter.js +480 -0
  45. package/dist/RepositoryRouter.js.map +1 -0
  46. package/dist/RunnerSelectionService.d.ts +62 -0
  47. package/dist/RunnerSelectionService.d.ts.map +1 -0
  48. package/dist/RunnerSelectionService.js +379 -0
  49. package/dist/RunnerSelectionService.js.map +1 -0
  50. package/dist/SharedApplicationServer.d.ts +107 -0
  51. package/dist/SharedApplicationServer.d.ts.map +1 -0
  52. package/dist/SharedApplicationServer.js +247 -0
  53. package/dist/SharedApplicationServer.js.map +1 -0
  54. package/dist/SharedWebhookServer.d.ts +39 -0
  55. package/dist/SharedWebhookServer.d.ts.map +1 -0
  56. package/dist/SharedWebhookServer.js +150 -0
  57. package/dist/SharedWebhookServer.js.map +1 -0
  58. package/dist/SlackChatAdapter.d.ts +25 -0
  59. package/dist/SlackChatAdapter.d.ts.map +1 -0
  60. package/dist/SlackChatAdapter.js +143 -0
  61. package/dist/SlackChatAdapter.js.map +1 -0
  62. package/dist/UserAccessControl.d.ts +69 -0
  63. package/dist/UserAccessControl.d.ts.map +1 -0
  64. package/dist/UserAccessControl.js +171 -0
  65. package/dist/UserAccessControl.js.map +1 -0
  66. package/dist/WorktreeIncludeService.d.ts +32 -0
  67. package/dist/WorktreeIncludeService.d.ts.map +1 -0
  68. package/dist/WorktreeIncludeService.js +123 -0
  69. package/dist/WorktreeIncludeService.js.map +1 -0
  70. package/dist/index.d.ts +22 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +17 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/label-prompt-template.md +27 -0
  75. package/dist/procedures/ProcedureAnalyzer.d.ts +69 -0
  76. package/dist/procedures/ProcedureAnalyzer.d.ts.map +1 -0
  77. package/dist/procedures/ProcedureAnalyzer.js +271 -0
  78. package/dist/procedures/ProcedureAnalyzer.js.map +1 -0
  79. package/dist/procedures/index.d.ts +7 -0
  80. package/dist/procedures/index.d.ts.map +1 -0
  81. package/dist/procedures/index.js +7 -0
  82. package/dist/procedures/index.js.map +1 -0
  83. package/dist/procedures/registry.d.ts +156 -0
  84. package/dist/procedures/registry.d.ts.map +1 -0
  85. package/dist/procedures/registry.js +240 -0
  86. package/dist/procedures/registry.js.map +1 -0
  87. package/dist/procedures/types.d.ts +103 -0
  88. package/dist/procedures/types.d.ts.map +1 -0
  89. package/dist/procedures/types.js +5 -0
  90. package/dist/procedures/types.js.map +1 -0
  91. package/dist/prompt-assembly/types.d.ts +80 -0
  92. package/dist/prompt-assembly/types.d.ts.map +1 -0
  93. package/dist/prompt-assembly/types.js +8 -0
  94. package/dist/prompt-assembly/types.js.map +1 -0
  95. package/dist/prompts/builder.md +191 -0
  96. package/dist/prompts/debugger.md +128 -0
  97. package/dist/prompts/graphite-orchestrator.md +362 -0
  98. package/dist/prompts/orchestrator.md +290 -0
  99. package/dist/prompts/scoper.md +95 -0
  100. package/dist/prompts/standard-issue-assigned-user-prompt.md +33 -0
  101. package/dist/prompts/subroutines/changelog-update.md +79 -0
  102. package/dist/prompts/subroutines/coding-activity.md +12 -0
  103. package/dist/prompts/subroutines/concise-summary.md +67 -0
  104. package/dist/prompts/subroutines/debugger-fix.md +92 -0
  105. package/dist/prompts/subroutines/debugger-reproduction.md +74 -0
  106. package/dist/prompts/subroutines/full-delegation.md +68 -0
  107. package/dist/prompts/subroutines/get-approval.md +175 -0
  108. package/dist/prompts/subroutines/gh-pr.md +80 -0
  109. package/dist/prompts/subroutines/git-commit.md +37 -0
  110. package/dist/prompts/subroutines/plan-summary.md +21 -0
  111. package/dist/prompts/subroutines/preparation.md +16 -0
  112. package/dist/prompts/subroutines/question-answer.md +8 -0
  113. package/dist/prompts/subroutines/question-investigation.md +8 -0
  114. package/dist/prompts/subroutines/release-execution.md +81 -0
  115. package/dist/prompts/subroutines/release-summary.md +60 -0
  116. package/dist/prompts/subroutines/user-testing-summary.md +87 -0
  117. package/dist/prompts/subroutines/user-testing.md +48 -0
  118. package/dist/prompts/subroutines/validation-fixer.md +56 -0
  119. package/dist/prompts/subroutines/verbose-summary.md +46 -0
  120. package/dist/prompts/subroutines/verifications.md +77 -0
  121. package/dist/prompts/todolist-system-prompt-extension.md +15 -0
  122. package/dist/sinks/IActivitySink.d.ts +60 -0
  123. package/dist/sinks/IActivitySink.d.ts.map +1 -0
  124. package/dist/sinks/IActivitySink.js +2 -0
  125. package/dist/sinks/IActivitySink.js.map +1 -0
  126. package/dist/sinks/LinearActivitySink.d.ts +69 -0
  127. package/dist/sinks/LinearActivitySink.d.ts.map +1 -0
  128. package/dist/sinks/LinearActivitySink.js +111 -0
  129. package/dist/sinks/LinearActivitySink.js.map +1 -0
  130. package/dist/sinks/NoopActivitySink.d.ts +13 -0
  131. package/dist/sinks/NoopActivitySink.d.ts.map +1 -0
  132. package/dist/sinks/NoopActivitySink.js +17 -0
  133. package/dist/sinks/NoopActivitySink.js.map +1 -0
  134. package/dist/sinks/index.d.ts +9 -0
  135. package/dist/sinks/index.d.ts.map +1 -0
  136. package/dist/sinks/index.js +8 -0
  137. package/dist/sinks/index.js.map +1 -0
  138. package/dist/types.d.ts +32 -0
  139. package/dist/types.d.ts.map +1 -0
  140. package/dist/types.js +2 -0
  141. package/dist/types.js.map +1 -0
  142. package/dist/validation/ValidationLoopController.d.ts +54 -0
  143. package/dist/validation/ValidationLoopController.d.ts.map +1 -0
  144. package/dist/validation/ValidationLoopController.js +242 -0
  145. package/dist/validation/ValidationLoopController.js.map +1 -0
  146. package/dist/validation/index.d.ts +7 -0
  147. package/dist/validation/index.d.ts.map +1 -0
  148. package/dist/validation/index.js +7 -0
  149. package/dist/validation/index.js.map +1 -0
  150. package/dist/validation/types.d.ts +82 -0
  151. package/dist/validation/types.d.ts.map +1 -0
  152. package/dist/validation/types.js +29 -0
  153. package/dist/validation/types.js.map +1 -0
  154. package/label-prompt-template.md +27 -0
  155. package/package.json +56 -0
  156. package/prompt-template.md +116 -0
  157. package/prompts/builder.md +191 -0
  158. package/prompts/debugger.md +128 -0
  159. package/prompts/graphite-orchestrator.md +362 -0
  160. package/prompts/orchestrator.md +290 -0
  161. package/prompts/scoper.md +95 -0
  162. package/prompts/standard-issue-assigned-user-prompt.md +33 -0
  163. package/prompts/todolist-system-prompt-extension.md +15 -0
@@ -0,0 +1,254 @@
1
+ /**
2
+ * GlobalSessionRegistry - Centralized session storage across all repositories
3
+ *
4
+ * This is Phase 1 of the CYPACK-724 architectural refactor.
5
+ * Replaces per-repository session storage in AgentSessionManager with a global registry
6
+ * that enables cross-repository session lookups (e.g., parent orchestrator in Repo A
7
+ * creating child issues in Repo B).
8
+ */
9
+ import { EventEmitter } from "node:events";
10
+ /**
11
+ * GlobalSessionRegistry centralizes all session storage across repositories.
12
+ *
13
+ * Responsibilities:
14
+ * - Store ALL SylasAgentSession objects (all repos)
15
+ * - Store ALL SylasAgentSessionEntry arrays (all repos)
16
+ * - Maintain parent-child session relationships
17
+ * - Emit lifecycle events for session changes
18
+ * - Support serialization/deserialization for persistence
19
+ * - Provide cleanup for old sessions
20
+ */
21
+ export class GlobalSessionRegistry extends EventEmitter {
22
+ /**
23
+ * All sessions keyed by session id
24
+ */
25
+ sessions = new Map();
26
+ /**
27
+ * All entries keyed by session id
28
+ */
29
+ entries = new Map();
30
+ /**
31
+ * Child session ID → parent session ID mapping
32
+ * Enables orchestrator workflows where parent (Repo A) creates child (Repo B)
33
+ */
34
+ childToParentMap = new Map();
35
+ /**
36
+ * Create a new session in the registry
37
+ * @param session The session to create
38
+ * @throws Error if session with same ID already exists
39
+ */
40
+ createSession(session) {
41
+ if (this.sessions.has(session.id)) {
42
+ throw new Error(`Session with ID ${session.id} already exists`);
43
+ }
44
+ this.sessions.set(session.id, session);
45
+ this.entries.set(session.id, []);
46
+ this.emit("sessionCreated", session);
47
+ }
48
+ /**
49
+ * Get a session by ID
50
+ * @param sessionId The session id
51
+ * @returns The session or undefined if not found
52
+ */
53
+ getSession(sessionId) {
54
+ return this.sessions.get(sessionId);
55
+ }
56
+ /**
57
+ * Update a session with partial data
58
+ * @param sessionId The session id
59
+ * @param updates Partial session data to merge
60
+ * @throws Error if session doesn't exist
61
+ */
62
+ updateSession(sessionId, updates) {
63
+ const session = this.sessions.get(sessionId);
64
+ if (!session) {
65
+ throw new Error(`Session with ID ${sessionId} not found`);
66
+ }
67
+ const oldStatus = session.status;
68
+ const updatedSession = { ...session, ...updates, updatedAt: Date.now() };
69
+ this.sessions.set(sessionId, updatedSession);
70
+ this.emit("sessionUpdated", sessionId, updatedSession, updates);
71
+ // Emit completion event if status changed to complete/error
72
+ if (oldStatus !== updatedSession.status &&
73
+ (updatedSession.status === "complete" ||
74
+ updatedSession.status === "error")) {
75
+ this.emit("sessionCompleted", sessionId, updatedSession);
76
+ }
77
+ }
78
+ /**
79
+ * Delete a session and its entries
80
+ * @param sessionId The session id
81
+ */
82
+ deleteSession(sessionId) {
83
+ this.sessions.delete(sessionId);
84
+ this.entries.delete(sessionId);
85
+ // Clean up any parent-child mappings
86
+ this.childToParentMap.delete(sessionId);
87
+ const childMappings = Array.from(this.childToParentMap.entries());
88
+ for (const [childId, parentId] of childMappings) {
89
+ if (parentId === sessionId) {
90
+ this.childToParentMap.delete(childId);
91
+ }
92
+ }
93
+ }
94
+ /**
95
+ * Get all sessions
96
+ * @returns Array of all sessions
97
+ */
98
+ getAllSessions() {
99
+ return Array.from(this.sessions.values());
100
+ }
101
+ /**
102
+ * Add an entry to a session's conversation history
103
+ * @param sessionId The session id
104
+ * @param entry The entry to add
105
+ * @throws Error if session doesn't exist
106
+ */
107
+ addEntry(sessionId, entry) {
108
+ if (!this.sessions.has(sessionId)) {
109
+ throw new Error(`Session with ID ${sessionId} not found`);
110
+ }
111
+ const sessionEntries = this.entries.get(sessionId) || [];
112
+ sessionEntries.push(entry);
113
+ this.entries.set(sessionId, sessionEntries);
114
+ // Update session's updatedAt timestamp
115
+ const session = this.sessions.get(sessionId);
116
+ if (session) {
117
+ session.updatedAt = Date.now();
118
+ }
119
+ }
120
+ /**
121
+ * Get all entries for a session
122
+ * @param sessionId The session id
123
+ * @returns Array of entries (empty if session has no entries or doesn't exist)
124
+ */
125
+ getEntries(sessionId) {
126
+ return this.entries.get(sessionId) || [];
127
+ }
128
+ /**
129
+ * Update an entry in a session's conversation history
130
+ * @param sessionId The session id
131
+ * @param entryIndex The index of the entry to update (0-based)
132
+ * @param updates Partial entry data to merge
133
+ * @throws Error if session doesn't exist or index out of bounds
134
+ */
135
+ updateEntry(sessionId, entryIndex, updates) {
136
+ const sessionEntries = this.entries.get(sessionId);
137
+ if (!sessionEntries) {
138
+ throw new Error(`Session with ID ${sessionId} not found`);
139
+ }
140
+ if (entryIndex < 0 || entryIndex >= sessionEntries.length) {
141
+ throw new Error(`Entry index ${entryIndex} out of bounds for session ${sessionId} (length: ${sessionEntries.length})`);
142
+ }
143
+ const existingEntry = sessionEntries[entryIndex]; // Safe: bounds checked above
144
+ const updatedEntry = {
145
+ ...existingEntry,
146
+ ...updates,
147
+ // Ensure required fields are never undefined
148
+ type: updates.type ?? existingEntry.type,
149
+ content: updates.content ?? existingEntry.content,
150
+ };
151
+ sessionEntries[entryIndex] = updatedEntry;
152
+ // Update session's updatedAt timestamp
153
+ const session = this.sessions.get(sessionId);
154
+ if (session) {
155
+ session.updatedAt = Date.now();
156
+ }
157
+ }
158
+ /**
159
+ * Set parent session for a child session (orchestrator workflow)
160
+ * @param childSessionId The child's session id
161
+ * @param parentSessionId The parent's session id
162
+ */
163
+ setParentSession(childSessionId, parentSessionId) {
164
+ this.childToParentMap.set(childSessionId, parentSessionId);
165
+ }
166
+ /**
167
+ * Get parent session ID for a child session
168
+ * @param childSessionId The child's session id
169
+ * @returns The parent session ID or undefined if not found
170
+ */
171
+ getParentSessionId(childSessionId) {
172
+ return this.childToParentMap.get(childSessionId);
173
+ }
174
+ /**
175
+ * Get all child session IDs for a parent session
176
+ * @param parentSessionId The parent's session id
177
+ * @returns Array of child session IDs
178
+ */
179
+ getChildSessionIds(parentSessionId) {
180
+ const childIds = [];
181
+ const childMappings = Array.from(this.childToParentMap.entries());
182
+ for (const [childId, parentId] of childMappings) {
183
+ if (parentId === parentSessionId) {
184
+ childIds.push(childId);
185
+ }
186
+ }
187
+ return childIds;
188
+ }
189
+ /**
190
+ * Serialize the registry state for persistence
191
+ * Excludes non-serializable data like agentRunner instances
192
+ * @returns Serialized state
193
+ */
194
+ serializeState() {
195
+ const serializedSessions = {};
196
+ const sessionEntries = Array.from(this.sessions.entries());
197
+ for (const [sessionId, session] of sessionEntries) {
198
+ // Exclude non-serializable agentRunner
199
+ const { agentRunner: _agentRunner, ...serializableSession } = session;
200
+ serializedSessions[sessionId] = serializableSession;
201
+ }
202
+ const serializedEntries = Object.fromEntries(Array.from(this.entries.entries()));
203
+ const serializedChildToParent = Object.fromEntries(Array.from(this.childToParentMap.entries()));
204
+ return {
205
+ version: "3.0",
206
+ sessions: serializedSessions,
207
+ entries: serializedEntries,
208
+ childToParentMap: serializedChildToParent,
209
+ };
210
+ }
211
+ /**
212
+ * Restore the registry state from serialized data
213
+ * Clears existing state before restoring
214
+ * @param state Serialized state to restore
215
+ */
216
+ restoreState(state) {
217
+ // Clear existing state
218
+ this.sessions.clear();
219
+ this.entries.clear();
220
+ this.childToParentMap.clear();
221
+ // Restore sessions
222
+ for (const [sessionId, session] of Object.entries(state.sessions)) {
223
+ this.sessions.set(sessionId, session);
224
+ }
225
+ // Restore entries
226
+ for (const [sessionId, entries] of Object.entries(state.entries)) {
227
+ this.entries.set(sessionId, entries);
228
+ }
229
+ // Restore parent-child mapping
230
+ for (const [childId, parentId] of Object.entries(state.childToParentMap)) {
231
+ this.childToParentMap.set(childId, parentId);
232
+ }
233
+ }
234
+ /**
235
+ * Clean up old sessions based on age
236
+ * Removes sessions where updatedAt is older than maxAgeMs
237
+ * @param maxAgeMs Maximum age in milliseconds (sessions older than this are removed)
238
+ * @returns Number of sessions removed
239
+ */
240
+ cleanup(maxAgeMs) {
241
+ const now = Date.now();
242
+ const cutoffTime = now - maxAgeMs;
243
+ let removedCount = 0;
244
+ const sessionEntries = Array.from(this.sessions.entries());
245
+ for (const [sessionId, session] of sessionEntries) {
246
+ if (session.updatedAt < cutoffTime) {
247
+ this.deleteSession(sessionId);
248
+ removedCount++;
249
+ }
250
+ }
251
+ return removedCount;
252
+ }
253
+ }
254
+ //# sourceMappingURL=GlobalSessionRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GlobalSessionRegistry.js","sourceRoot":"","sources":["../src/GlobalSessionRegistry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,175 @@
1
+ import type { Comment, EdgeWorkerConfig, GuidanceRule, IIssueTrackerService, ILogger, Issue, IssueMinimal, RepositoryConfig, WebhookAgentSession, WebhookComment } from "sylas-core";
2
+ import type { GitService } from "./GitService.js";
3
+ import type { SubroutineDefinition } from "./procedures/index.js";
4
+ /**
5
+ * Dependencies required by the PromptBuilder
6
+ */
7
+ export interface PromptBuilderDeps {
8
+ logger: ILogger;
9
+ repositories: Map<string, RepositoryConfig>;
10
+ issueTrackers: Map<string, IIssueTrackerService>;
11
+ gitService: GitService;
12
+ config: EdgeWorkerConfig;
13
+ }
14
+ /**
15
+ * System prompt result from label-based determination
16
+ */
17
+ export interface SystemPromptResult {
18
+ prompt: string;
19
+ version?: string;
20
+ type?: "debugger" | "builder" | "scoper" | "orchestrator" | "graphite-orchestrator";
21
+ }
22
+ /**
23
+ * Result from building a prompt (prompt text + optional version)
24
+ */
25
+ export interface PromptResult {
26
+ prompt: string;
27
+ version?: string;
28
+ }
29
+ /**
30
+ * Responsible for building various prompt types used in the EdgeWorker.
31
+ *
32
+ * Extracted from EdgeWorker to improve separation of concerns.
33
+ * Handles label-based prompts, mention prompts, issue context prompts,
34
+ * issue update prompts, subroutine prompt loading, and related utilities.
35
+ */
36
+ export declare class PromptBuilder {
37
+ private readonly logger;
38
+ private readonly repositories;
39
+ private readonly issueTrackers;
40
+ private readonly gitService;
41
+ private readonly config;
42
+ constructor(deps: PromptBuilderDeps);
43
+ /**
44
+ * Determine system prompt based on issue labels and repository configuration
45
+ */
46
+ determineSystemPromptFromLabels(labels: string[], repository: RepositoryConfig): Promise<SystemPromptResult | undefined>;
47
+ /**
48
+ * Build simplified prompt for label-based workflows
49
+ * @param issue Full Linear issue
50
+ * @param repository Repository configuration
51
+ * @param attachmentManifest Optional attachment manifest
52
+ * @param guidance Optional agent guidance rules from Linear
53
+ * @returns Formatted prompt string
54
+ */
55
+ buildLabelBasedPrompt(issue: Issue, repository: RepositoryConfig, attachmentManifest?: string, guidance?: GuidanceRule[]): Promise<PromptResult>;
56
+ /**
57
+ * Generate routing context for orchestrator mode
58
+ *
59
+ * This provides the orchestrator with information about available repositories
60
+ * and how to route sub-issues to them. The context includes:
61
+ * - List of configured repositories in the workspace
62
+ * - Routing rules for each repository (labels, teams, projects)
63
+ * - Instructions on using description tags for explicit routing
64
+ *
65
+ * @param currentRepository The repository handling the current orchestrator issue
66
+ * @returns XML-formatted routing context string, or empty string if no routing info available
67
+ */
68
+ generateRoutingContext(currentRepository: RepositoryConfig): string;
69
+ /**
70
+ * Build prompt for mention-triggered sessions
71
+ * @param issue Full Linear issue object
72
+ * @param agentSession The agent session containing the mention
73
+ * @param attachmentManifest Optional attachment manifest to append
74
+ * @param guidance Optional agent guidance rules from Linear
75
+ * @returns The constructed prompt and optional version tag
76
+ */
77
+ buildMentionPrompt(issue: Issue, agentSession: WebhookAgentSession, attachmentManifest?: string, guidance?: GuidanceRule[]): Promise<PromptResult>;
78
+ /**
79
+ * Build a prompt for Claude using the improved XML-style template
80
+ * @param issue Full Linear issue
81
+ * @param repository Repository configuration
82
+ * @param newComment Optional new comment to focus on (for handleNewRootComment)
83
+ * @param attachmentManifest Optional attachment manifest
84
+ * @param guidance Optional agent guidance rules from Linear
85
+ * @returns Formatted prompt string
86
+ */
87
+ buildIssueContextPrompt(issue: Issue, repository: RepositoryConfig, newComment?: WebhookComment, attachmentManifest?: string, guidance?: GuidanceRule[]): Promise<PromptResult>;
88
+ /**
89
+ * Build XML-formatted prompt for issue content updates (title/description/attachments)
90
+ *
91
+ * The prompt clearly shows what fields changed by comparing old vs new values,
92
+ * and includes guidance for the agent to evaluate whether these changes affect
93
+ * its current implementation or action plan.
94
+ */
95
+ buildIssueUpdatePrompt(issueIdentifier: string, issueData: {
96
+ title: string;
97
+ description?: string | null;
98
+ attachments?: unknown;
99
+ }, updatedFrom: {
100
+ title?: string;
101
+ description?: string;
102
+ attachments?: unknown;
103
+ }): string;
104
+ /**
105
+ * Format Linear comments into a threaded structure that mirrors the Linear UI
106
+ * @param comments Array of Linear comments
107
+ * @returns Formatted string showing comment threads
108
+ */
109
+ formatCommentThreads(comments: Comment[]): Promise<string>;
110
+ /**
111
+ * Format agent guidance rules as markdown for injection into prompts
112
+ * @param guidance Array of guidance rules from Linear
113
+ * @returns Formatted markdown string with guidance, or empty string if no guidance
114
+ */
115
+ formatAgentGuidance(guidance?: GuidanceRule[]): string;
116
+ /**
117
+ * Extract version tag from template content
118
+ * @param templateContent The template content to parse
119
+ * @returns The version value if found, undefined otherwise
120
+ */
121
+ extractVersionTag(templateContent: string): string | undefined;
122
+ /**
123
+ * Load a subroutine prompt file
124
+ * Extracted helper to make prompt assembly more readable
125
+ */
126
+ loadSubroutinePrompt(subroutine: SubroutineDefinition, workspaceSlug?: string): Promise<string | null>;
127
+ /**
128
+ * Load shared instructions that get appended to all system prompts
129
+ */
130
+ loadSharedInstructions(): Promise<string>;
131
+ /**
132
+ * Determine the base branch for an issue, considering parent issues and blocked-by relationships
133
+ *
134
+ * Priority order:
135
+ * 1. If issue has graphite label AND has a "blocked by" relationship, use the blocking issue's branch
136
+ * (This enables Graphite stacking where each sub-issue branches off the previous)
137
+ * 2. If issue has a parent, use the parent's branch
138
+ * 3. Fall back to repository's default base branch
139
+ */
140
+ determineBaseBranch(issue: Issue, repository: RepositoryConfig): Promise<string>;
141
+ /**
142
+ * Check if an issue has the graphite label
143
+ *
144
+ * @param issue The issue to check
145
+ * @param repository The repository configuration
146
+ * @returns True if the issue has the graphite label
147
+ */
148
+ hasGraphiteLabel(issue: Issue, repository: RepositoryConfig): Promise<boolean>;
149
+ /**
150
+ * Fetch issues that block this issue (i.e., issues this one is "blocked by")
151
+ * Uses the inverseRelations field with type "blocks"
152
+ *
153
+ * Linear relations work like this:
154
+ * - When Issue A "blocks" Issue B, a relation is created with:
155
+ * - issue = A (the blocker)
156
+ * - relatedIssue = B (the blocked one)
157
+ * - type = "blocks"
158
+ *
159
+ * So to find "who blocks Issue B", we need inverseRelations (where B is the relatedIssue)
160
+ * and look for type === "blocks", then get the `issue` field (the blocker).
161
+ *
162
+ * @param issue The issue to fetch blocking issues for
163
+ * @returns Array of issues that block this one, or empty array if none
164
+ */
165
+ fetchBlockingIssues(issue: Issue): Promise<Issue[]>;
166
+ /**
167
+ * Convert full Linear SDK issue to CoreIssue interface for Session creation
168
+ */
169
+ convertLinearIssueToCore(issue: Issue): IssueMinimal;
170
+ /**
171
+ * Fetch issue labels for a given issue
172
+ */
173
+ fetchIssueLabels(issue: Issue): Promise<string[]>;
174
+ }
175
+ //# sourceMappingURL=PromptBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PromptBuilder.d.ts","sourceRoot":"","sources":["../src/PromptBuilder.ts"],"names":[],"mappings":"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"}