@supaku/agentfactory-linear 0.1.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/LICENSE +21 -0
- package/dist/src/agent-client.d.ts +195 -0
- package/dist/src/agent-client.d.ts.map +1 -0
- package/dist/src/agent-client.js +548 -0
- package/dist/src/agent-session.d.ts +284 -0
- package/dist/src/agent-session.d.ts.map +1 -0
- package/dist/src/agent-session.js +875 -0
- package/dist/src/checkbox-utils.d.ts +88 -0
- package/dist/src/checkbox-utils.d.ts.map +1 -0
- package/dist/src/checkbox-utils.js +120 -0
- package/dist/src/constants.d.ts +77 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +87 -0
- package/dist/src/errors.d.ts +79 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +155 -0
- package/dist/src/index.d.ts +15 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +16 -0
- package/dist/src/retry.d.ts +43 -0
- package/dist/src/retry.d.ts.map +1 -0
- package/dist/src/retry.js +73 -0
- package/dist/src/types.d.ts +412 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +121 -0
- package/dist/src/utils.d.ts +52 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +277 -0
- package/package.json +59 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { RetryConfig } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Default retry configuration
|
|
4
|
+
*/
|
|
5
|
+
export declare const DEFAULT_RETRY_CONFIG: Required<RetryConfig>;
|
|
6
|
+
/**
|
|
7
|
+
* Sleep utility for async delays
|
|
8
|
+
*/
|
|
9
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Calculate delay for a given retry attempt with exponential backoff
|
|
12
|
+
*/
|
|
13
|
+
export declare function calculateDelay(attempt: number, config: Required<RetryConfig>): number;
|
|
14
|
+
/**
|
|
15
|
+
* Retry context passed to callbacks
|
|
16
|
+
*/
|
|
17
|
+
export interface RetryContext {
|
|
18
|
+
attempt: number;
|
|
19
|
+
maxRetries: number;
|
|
20
|
+
lastError?: Error;
|
|
21
|
+
delay: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Callback for retry events
|
|
25
|
+
*/
|
|
26
|
+
export type RetryCallback = (context: RetryContext) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Options for withRetry function
|
|
29
|
+
*/
|
|
30
|
+
export interface WithRetryOptions {
|
|
31
|
+
config?: RetryConfig;
|
|
32
|
+
onRetry?: RetryCallback;
|
|
33
|
+
shouldRetry?: (error: unknown) => boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Execute an async function with exponential backoff retry logic
|
|
37
|
+
*/
|
|
38
|
+
export declare function withRetry<T>(fn: () => Promise<T>, options?: WithRetryOptions): Promise<T>;
|
|
39
|
+
/**
|
|
40
|
+
* Create a retry wrapper with pre-configured options
|
|
41
|
+
*/
|
|
42
|
+
export declare function createRetryWrapper(defaultOptions?: WithRetryOptions): <T>(fn: () => Promise<T>, options?: WithRetryOptions) => Promise<T>;
|
|
43
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/retry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAG1C;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,WAAW,CAMtD,CAAA;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,GAC5B,MAAM,CAIR;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAA;AAE3D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAA;CAC1C;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,CAAC,CAAC,CAsCZ;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,cAAc,GAAE,gBAAqB,IACrD,CAAC,EAChB,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,UAAU,gBAAgB,KACzB,OAAO,CAAC,CAAC,CAAC,CAUd"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { isRetryableError } from './errors';
|
|
2
|
+
/**
|
|
3
|
+
* Default retry configuration
|
|
4
|
+
*/
|
|
5
|
+
export const DEFAULT_RETRY_CONFIG = {
|
|
6
|
+
maxRetries: 3,
|
|
7
|
+
initialDelayMs: 1000,
|
|
8
|
+
backoffMultiplier: 2,
|
|
9
|
+
maxDelayMs: 10000,
|
|
10
|
+
retryableStatusCodes: [429, 500, 502, 503, 504],
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Sleep utility for async delays
|
|
14
|
+
*/
|
|
15
|
+
export function sleep(ms) {
|
|
16
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Calculate delay for a given retry attempt with exponential backoff
|
|
20
|
+
*/
|
|
21
|
+
export function calculateDelay(attempt, config) {
|
|
22
|
+
const delay = config.initialDelayMs * Math.pow(config.backoffMultiplier, attempt);
|
|
23
|
+
return Math.min(delay, config.maxDelayMs);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Execute an async function with exponential backoff retry logic
|
|
27
|
+
*/
|
|
28
|
+
export async function withRetry(fn, options = {}) {
|
|
29
|
+
const config = {
|
|
30
|
+
...DEFAULT_RETRY_CONFIG,
|
|
31
|
+
...options.config,
|
|
32
|
+
};
|
|
33
|
+
const shouldRetry = options.shouldRetry ??
|
|
34
|
+
((error) => isRetryableError(error, config.retryableStatusCodes));
|
|
35
|
+
let lastError = new Error('Unknown error');
|
|
36
|
+
for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
|
|
37
|
+
try {
|
|
38
|
+
return await fn();
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
42
|
+
if (attempt === config.maxRetries || !shouldRetry(error)) {
|
|
43
|
+
throw lastError;
|
|
44
|
+
}
|
|
45
|
+
const delay = calculateDelay(attempt, config);
|
|
46
|
+
if (options.onRetry) {
|
|
47
|
+
options.onRetry({
|
|
48
|
+
attempt,
|
|
49
|
+
maxRetries: config.maxRetries,
|
|
50
|
+
lastError,
|
|
51
|
+
delay,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
await sleep(delay);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
throw lastError;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Create a retry wrapper with pre-configured options
|
|
61
|
+
*/
|
|
62
|
+
export function createRetryWrapper(defaultOptions = {}) {
|
|
63
|
+
return function (fn, options) {
|
|
64
|
+
return withRetry(fn, {
|
|
65
|
+
...defaultOptions,
|
|
66
|
+
...options,
|
|
67
|
+
config: {
|
|
68
|
+
...defaultOptions.config,
|
|
69
|
+
...options?.config,
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
}
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
import type { LinearClient } from '@linear/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* AgentSession states as defined by Linear Agent SDK
|
|
4
|
+
*/
|
|
5
|
+
export type AgentSessionState = 'pending' | 'active' | 'error' | 'awaitingInput' | 'complete';
|
|
6
|
+
/**
|
|
7
|
+
* AgentActivity types as defined by Linear Agent API
|
|
8
|
+
*/
|
|
9
|
+
export type AgentActivityType = 'thought' | 'action' | 'response' | 'elicitation' | 'error' | 'prompt';
|
|
10
|
+
/**
|
|
11
|
+
* AgentActivity signals - modifiers that provide additional instructions
|
|
12
|
+
* on how the activity should be interpreted
|
|
13
|
+
*/
|
|
14
|
+
export type AgentActivitySignal = 'auth' | 'continue' | 'select' | 'stop';
|
|
15
|
+
/**
|
|
16
|
+
* Content for a thought activity - reasoning steps
|
|
17
|
+
*/
|
|
18
|
+
export interface ThoughtActivityContent {
|
|
19
|
+
type: 'thought';
|
|
20
|
+
body: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Content for an action activity - tool calls
|
|
24
|
+
*/
|
|
25
|
+
export interface ActionActivityContent {
|
|
26
|
+
type: 'action';
|
|
27
|
+
action: string;
|
|
28
|
+
parameter: string;
|
|
29
|
+
result?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Content for a response activity - final responses
|
|
33
|
+
*/
|
|
34
|
+
export interface ResponseActivityContent {
|
|
35
|
+
type: 'response';
|
|
36
|
+
body: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Content for an elicitation activity - asking for clarification
|
|
40
|
+
*/
|
|
41
|
+
export interface ElicitationActivityContent {
|
|
42
|
+
type: 'elicitation';
|
|
43
|
+
body: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Content for an error activity - error reporting
|
|
47
|
+
*/
|
|
48
|
+
export interface ErrorActivityContent {
|
|
49
|
+
type: 'error';
|
|
50
|
+
body: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Content for a prompt activity - prompts/instructions
|
|
54
|
+
*/
|
|
55
|
+
export interface PromptActivityContent {
|
|
56
|
+
type: 'prompt';
|
|
57
|
+
body: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Union type for all activity content types
|
|
61
|
+
*/
|
|
62
|
+
export type AgentActivityContentPayload = ThoughtActivityContent | ActionActivityContent | ResponseActivityContent | ElicitationActivityContent | ErrorActivityContent | PromptActivityContent;
|
|
63
|
+
/**
|
|
64
|
+
* Input for creating an agent activity via the native Linear API
|
|
65
|
+
*/
|
|
66
|
+
export interface AgentActivityCreateInput {
|
|
67
|
+
agentSessionId: string;
|
|
68
|
+
content: AgentActivityContentPayload;
|
|
69
|
+
ephemeral?: boolean;
|
|
70
|
+
id?: string;
|
|
71
|
+
signal?: AgentActivitySignal;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Result of creating an agent activity
|
|
75
|
+
*/
|
|
76
|
+
export interface AgentActivityResult {
|
|
77
|
+
success: boolean;
|
|
78
|
+
activityId?: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Legacy activity content for backward compatibility
|
|
82
|
+
* @deprecated Use AgentActivityContentPayload instead
|
|
83
|
+
*/
|
|
84
|
+
export interface AgentActivityContent {
|
|
85
|
+
text: string;
|
|
86
|
+
metadata?: Record<string, unknown>;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Configuration for creating an agent activity (internal use)
|
|
90
|
+
*/
|
|
91
|
+
export interface CreateActivityOptions {
|
|
92
|
+
type: AgentActivityType;
|
|
93
|
+
content: AgentActivityContent;
|
|
94
|
+
ephemeral?: boolean;
|
|
95
|
+
signals?: AgentSignals;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* AgentPlan item states
|
|
99
|
+
*/
|
|
100
|
+
export type AgentPlanItemState = 'pending' | 'inProgress' | 'completed' | 'canceled';
|
|
101
|
+
/**
|
|
102
|
+
* Linear's native plan item status values
|
|
103
|
+
* @see https://linear.app/developers/agents
|
|
104
|
+
*/
|
|
105
|
+
export type LinearPlanStatus = 'pending' | 'inProgress' | 'completed' | 'canceled';
|
|
106
|
+
/**
|
|
107
|
+
* Linear's native plan item structure for agentSessionUpdate mutation
|
|
108
|
+
* @see https://linear.app/developers/agents
|
|
109
|
+
*/
|
|
110
|
+
export interface LinearPlanItem {
|
|
111
|
+
/** The task description */
|
|
112
|
+
content: string;
|
|
113
|
+
/** Current status of the task */
|
|
114
|
+
status: LinearPlanStatus;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* A single item in the agent's plan (internal representation)
|
|
118
|
+
* Supports nested children for more detailed task tracking
|
|
119
|
+
*/
|
|
120
|
+
export interface AgentPlanItem {
|
|
121
|
+
id: string;
|
|
122
|
+
title: string;
|
|
123
|
+
state: AgentPlanItemState;
|
|
124
|
+
details?: string;
|
|
125
|
+
children?: AgentPlanItem[];
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Full agent plan structure (internal representation)
|
|
129
|
+
*/
|
|
130
|
+
export interface AgentPlan {
|
|
131
|
+
items: AgentPlanItem[];
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Optional metadata for activity interpretation
|
|
135
|
+
*/
|
|
136
|
+
export interface AgentSignals {
|
|
137
|
+
toolName?: string;
|
|
138
|
+
toolInput?: Record<string, unknown>;
|
|
139
|
+
toolOutput?: unknown;
|
|
140
|
+
error?: {
|
|
141
|
+
message: string;
|
|
142
|
+
code?: string;
|
|
143
|
+
stack?: string;
|
|
144
|
+
};
|
|
145
|
+
progress?: number;
|
|
146
|
+
[key: string]: unknown;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Configuration for the Linear Agent Client
|
|
150
|
+
*/
|
|
151
|
+
export interface LinearAgentClientConfig {
|
|
152
|
+
apiKey: string;
|
|
153
|
+
baseUrl?: string;
|
|
154
|
+
retry?: RetryConfig;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Retry configuration with exponential backoff
|
|
158
|
+
*/
|
|
159
|
+
export interface RetryConfig {
|
|
160
|
+
maxRetries?: number;
|
|
161
|
+
initialDelayMs?: number;
|
|
162
|
+
backoffMultiplier?: number;
|
|
163
|
+
maxDelayMs?: number;
|
|
164
|
+
retryableStatusCodes?: number[];
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Standard Linear workflow states
|
|
168
|
+
*/
|
|
169
|
+
export type LinearWorkflowStatus = 'Backlog' | 'Started' | 'Finished' | 'Delivered' | 'Accepted' | 'Rejected' | 'Canceled';
|
|
170
|
+
/**
|
|
171
|
+
* Type of agent work being performed based on issue status
|
|
172
|
+
*
|
|
173
|
+
* | Issue Status | Work Type | Agent Role |
|
|
174
|
+
* |--------------|------------------------|-----------------------------------------------|
|
|
175
|
+
* | Icebox | research | Research/story-writer |
|
|
176
|
+
* | Icebox | backlog-creation | Create backlog issues from research |
|
|
177
|
+
* | Backlog | development | Developer agents |
|
|
178
|
+
* | Backlog | coordination | Coordinate sub-issue execution |
|
|
179
|
+
* | Started | inflight | Developer (resume/continue) |
|
|
180
|
+
* | Finished | qa | QA agents |
|
|
181
|
+
* | Finished | qa-coordination | Coordinate QA across sub-issues |
|
|
182
|
+
* | Delivered | acceptance | Acceptance testing |
|
|
183
|
+
* | Delivered | acceptance-coordination| Coordinate acceptance across sub-issues |
|
|
184
|
+
* | Rejected | refinement | Refine and return to Backlog |
|
|
185
|
+
*/
|
|
186
|
+
export type AgentWorkType = 'research' | 'backlog-creation' | 'development' | 'inflight' | 'qa' | 'acceptance' | 'refinement' | 'coordination' | 'qa-coordination' | 'acceptance-coordination';
|
|
187
|
+
/**
|
|
188
|
+
* Mapping from Linear issue status to agent work type
|
|
189
|
+
*/
|
|
190
|
+
export declare const STATUS_WORK_TYPE_MAP: Record<string, AgentWorkType>;
|
|
191
|
+
/**
|
|
192
|
+
* Terminal statuses where no agent work is needed
|
|
193
|
+
* Issues in these states are considered complete and should not be processed
|
|
194
|
+
*/
|
|
195
|
+
export declare const TERMINAL_STATUSES: readonly ["Accepted", "Canceled", "Duplicate"];
|
|
196
|
+
export type TerminalStatus = typeof TERMINAL_STATUSES[number];
|
|
197
|
+
/**
|
|
198
|
+
* Status to transition to when agent session STARTS
|
|
199
|
+
* null means no transition on start
|
|
200
|
+
*/
|
|
201
|
+
export declare const WORK_TYPE_START_STATUS: Record<AgentWorkType, LinearWorkflowStatus | null>;
|
|
202
|
+
/**
|
|
203
|
+
* Status to transition to when agent session COMPLETES successfully
|
|
204
|
+
* null means no auto-transition on completion
|
|
205
|
+
*/
|
|
206
|
+
export declare const WORK_TYPE_COMPLETE_STATUS: Record<AgentWorkType, LinearWorkflowStatus | null>;
|
|
207
|
+
/**
|
|
208
|
+
* Status to transition to when agent work FAILS (e.g., QA rejected)
|
|
209
|
+
* null means no auto-transition on failure (stays in current status)
|
|
210
|
+
*/
|
|
211
|
+
export declare const WORK_TYPE_FAIL_STATUS: Record<AgentWorkType, LinearWorkflowStatus | null>;
|
|
212
|
+
/**
|
|
213
|
+
* Allowed statuses for each work type
|
|
214
|
+
* Used to validate that an agent isn't assigned to an issue in the wrong status
|
|
215
|
+
*/
|
|
216
|
+
export declare const WORK_TYPE_ALLOWED_STATUSES: Record<AgentWorkType, string[]>;
|
|
217
|
+
/**
|
|
218
|
+
* Valid work types for each status (reverse of WORK_TYPE_ALLOWED_STATUSES)
|
|
219
|
+
* Used to constrain keyword detection to only valid options for the current status
|
|
220
|
+
*
|
|
221
|
+
* For example:
|
|
222
|
+
* - Icebox issues can use keywords to choose between 'research' and 'backlog-creation'
|
|
223
|
+
* - Backlog issues only have 'development' as valid, so keywords won't change work type
|
|
224
|
+
* but could still provide agent specialization hints
|
|
225
|
+
*/
|
|
226
|
+
export declare const STATUS_VALID_WORK_TYPES: Record<string, AgentWorkType[]>;
|
|
227
|
+
/**
|
|
228
|
+
* Get valid work types for a given status
|
|
229
|
+
* Returns empty array if status is unknown
|
|
230
|
+
*/
|
|
231
|
+
export declare function getValidWorkTypesForStatus(status: string): AgentWorkType[];
|
|
232
|
+
/**
|
|
233
|
+
* Result of work type validation
|
|
234
|
+
*/
|
|
235
|
+
export interface WorkTypeValidationResult {
|
|
236
|
+
valid: boolean;
|
|
237
|
+
error?: string;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Validate that a work type is appropriate for an issue's current status
|
|
241
|
+
*
|
|
242
|
+
* @param workType - The work type being assigned
|
|
243
|
+
* @param issueStatus - The current status of the issue
|
|
244
|
+
* @returns Validation result with error message if invalid
|
|
245
|
+
*/
|
|
246
|
+
export declare function validateWorkTypeForStatus(workType: AgentWorkType, issueStatus: string): WorkTypeValidationResult;
|
|
247
|
+
/**
|
|
248
|
+
* Mapping of status names to their Linear state IDs
|
|
249
|
+
*/
|
|
250
|
+
export interface StatusMapping {
|
|
251
|
+
[statusName: string]: string;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Configuration for creating/managing an agent session
|
|
255
|
+
*/
|
|
256
|
+
export interface AgentSessionConfig {
|
|
257
|
+
client: LinearClient;
|
|
258
|
+
issueId: string;
|
|
259
|
+
sessionId?: string;
|
|
260
|
+
autoTransition?: boolean;
|
|
261
|
+
/**
|
|
262
|
+
* Type of work being performed.
|
|
263
|
+
* - 'development': Normal development work (transitions to Started on start)
|
|
264
|
+
* - 'qa': QA validation work (stays at Finished until QA passes, then Delivered)
|
|
265
|
+
* Defaults to 'development'.
|
|
266
|
+
*/
|
|
267
|
+
workType?: AgentWorkType;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Result of session operations
|
|
271
|
+
*/
|
|
272
|
+
export interface SessionOperationResult {
|
|
273
|
+
success: boolean;
|
|
274
|
+
sessionId?: string;
|
|
275
|
+
error?: Error;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* External URL associated with an agent session
|
|
279
|
+
*/
|
|
280
|
+
export interface AgentSessionExternalUrl {
|
|
281
|
+
/** Label for the URL (e.g., "Dashboard", "Logs") */
|
|
282
|
+
label: string;
|
|
283
|
+
/** The URL of the external resource */
|
|
284
|
+
url: string;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Input for updating an agent session via the Linear API
|
|
288
|
+
*/
|
|
289
|
+
export interface AgentSessionUpdateInput {
|
|
290
|
+
/** The agent session ID to update */
|
|
291
|
+
sessionId: string;
|
|
292
|
+
/** External URLs linking to agent dashboard/logs */
|
|
293
|
+
externalUrls?: AgentSessionExternalUrl[];
|
|
294
|
+
/** External link URL (single, for backward compatibility) */
|
|
295
|
+
externalLink?: string;
|
|
296
|
+
/** Plan array showing agent execution strategy (Linear's native format) */
|
|
297
|
+
plan?: LinearPlanItem[];
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Result of updating an agent session
|
|
301
|
+
*/
|
|
302
|
+
export interface AgentSessionUpdateResult {
|
|
303
|
+
success: boolean;
|
|
304
|
+
sessionId?: string;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Input for creating an agent session on an issue via the Linear API
|
|
308
|
+
* @see https://linear.app/developers/agents
|
|
309
|
+
*/
|
|
310
|
+
export interface AgentSessionCreateOnIssueInput {
|
|
311
|
+
/** The issue ID (UUID) or identifier (e.g., 'SUP-123') to create the session on */
|
|
312
|
+
issueId: string;
|
|
313
|
+
/** External URLs linking to agent dashboard/logs */
|
|
314
|
+
externalUrls?: AgentSessionExternalUrl[];
|
|
315
|
+
/** External link URL (single, for backward compatibility) */
|
|
316
|
+
externalLink?: string;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Result of creating an agent session on an issue
|
|
320
|
+
*/
|
|
321
|
+
export interface AgentSessionCreateResult {
|
|
322
|
+
success: boolean;
|
|
323
|
+
/** The ID of the created agent session */
|
|
324
|
+
sessionId?: string;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Linear issue relationship types
|
|
328
|
+
* @see https://linear.app/developers/sdk
|
|
329
|
+
*/
|
|
330
|
+
export type IssueRelationType = 'related' | 'blocks' | 'duplicate';
|
|
331
|
+
/**
|
|
332
|
+
* Input for creating an issue relation
|
|
333
|
+
*/
|
|
334
|
+
export interface IssueRelationCreateInput {
|
|
335
|
+
issueId: string;
|
|
336
|
+
relatedIssueId: string;
|
|
337
|
+
type: IssueRelationType;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Result of creating/deleting an issue relation
|
|
341
|
+
*/
|
|
342
|
+
export interface IssueRelationResult {
|
|
343
|
+
success: boolean;
|
|
344
|
+
relationId?: string;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Batch result for creating multiple relations
|
|
348
|
+
*/
|
|
349
|
+
export interface IssueRelationBatchResult {
|
|
350
|
+
success: boolean;
|
|
351
|
+
relationIds: string[];
|
|
352
|
+
errors: Array<{
|
|
353
|
+
targetIssueId: string;
|
|
354
|
+
error: string;
|
|
355
|
+
}>;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Sub-issue with its blocking relations for dependency graph building
|
|
359
|
+
*/
|
|
360
|
+
export interface SubIssueGraphNode {
|
|
361
|
+
issue: {
|
|
362
|
+
id: string;
|
|
363
|
+
identifier: string;
|
|
364
|
+
title: string;
|
|
365
|
+
description?: string;
|
|
366
|
+
status?: string;
|
|
367
|
+
priority: number;
|
|
368
|
+
labels: string[];
|
|
369
|
+
url: string;
|
|
370
|
+
};
|
|
371
|
+
/** Identifiers of issues that block this sub-issue */
|
|
372
|
+
blockedBy: string[];
|
|
373
|
+
/** Identifiers of issues that this sub-issue blocks */
|
|
374
|
+
blocks: string[];
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Result of getSubIssueGraph - the complete dependency graph for a parent issue
|
|
378
|
+
*/
|
|
379
|
+
export interface SubIssueGraph {
|
|
380
|
+
parentId: string;
|
|
381
|
+
parentIdentifier: string;
|
|
382
|
+
subIssues: SubIssueGraphNode[];
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Lightweight sub-issue status info (no blocking relations)
|
|
386
|
+
* Used by QA and acceptance agents to validate sub-issue completion
|
|
387
|
+
*/
|
|
388
|
+
export interface SubIssueStatus {
|
|
389
|
+
identifier: string;
|
|
390
|
+
title: string;
|
|
391
|
+
status: string;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Representation of an issue relation
|
|
395
|
+
*/
|
|
396
|
+
export interface IssueRelationInfo {
|
|
397
|
+
id: string;
|
|
398
|
+
type: string;
|
|
399
|
+
issueId: string;
|
|
400
|
+
issueIdentifier?: string;
|
|
401
|
+
relatedIssueId: string;
|
|
402
|
+
relatedIssueIdentifier?: string;
|
|
403
|
+
createdAt: Date;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Result of querying issue relations
|
|
407
|
+
*/
|
|
408
|
+
export interface IssueRelationsResult {
|
|
409
|
+
relations: IssueRelationInfo[];
|
|
410
|
+
inverseRelations: IssueRelationInfo[];
|
|
411
|
+
}
|
|
412
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mapping from Linear issue status to agent work type
|
|
3
|
+
*/
|
|
4
|
+
export const STATUS_WORK_TYPE_MAP = {
|
|
5
|
+
'Icebox': 'research',
|
|
6
|
+
'Backlog': 'development',
|
|
7
|
+
'Started': 'inflight',
|
|
8
|
+
'Finished': 'qa',
|
|
9
|
+
'Delivered': 'acceptance',
|
|
10
|
+
'Rejected': 'refinement',
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Terminal statuses where no agent work is needed
|
|
14
|
+
* Issues in these states are considered complete and should not be processed
|
|
15
|
+
*/
|
|
16
|
+
export const TERMINAL_STATUSES = ['Accepted', 'Canceled', 'Duplicate'];
|
|
17
|
+
/**
|
|
18
|
+
* Status to transition to when agent session STARTS
|
|
19
|
+
* null means no transition on start
|
|
20
|
+
*/
|
|
21
|
+
export const WORK_TYPE_START_STATUS = {
|
|
22
|
+
'research': null, // No transition from Icebox on start
|
|
23
|
+
'backlog-creation': null, // No transition from Icebox on start
|
|
24
|
+
'development': 'Started', // Backlog -> Started when agent begins
|
|
25
|
+
'inflight': null, // Already Started, no change
|
|
26
|
+
'qa': null, // Already Finished
|
|
27
|
+
'acceptance': null, // Already Delivered
|
|
28
|
+
'refinement': null, // Already Rejected
|
|
29
|
+
'coordination': 'Started', // Backlog -> Started when coordinator begins
|
|
30
|
+
'qa-coordination': null, // Already Finished
|
|
31
|
+
'acceptance-coordination': null, // Already Delivered
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Status to transition to when agent session COMPLETES successfully
|
|
35
|
+
* null means no auto-transition on completion
|
|
36
|
+
*/
|
|
37
|
+
export const WORK_TYPE_COMPLETE_STATUS = {
|
|
38
|
+
'research': null, // No auto-transition, user moves to Backlog
|
|
39
|
+
'backlog-creation': null, // Issues created in Backlog, source stays in Icebox
|
|
40
|
+
'development': 'Finished', // Started -> Finished when work done
|
|
41
|
+
'inflight': 'Finished', // Started -> Finished when work done
|
|
42
|
+
'qa': 'Delivered', // Finished -> Delivered on QA pass
|
|
43
|
+
'acceptance': 'Accepted', // Delivered -> Accepted on acceptance pass
|
|
44
|
+
'refinement': 'Backlog', // Rejected -> Backlog after refinement
|
|
45
|
+
'coordination': 'Finished', // Started -> Finished when all sub-issues done
|
|
46
|
+
'qa-coordination': 'Delivered', // Finished -> Delivered when QA coordination passes
|
|
47
|
+
'acceptance-coordination': 'Accepted', // Delivered -> Accepted when acceptance coordination passes
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Status to transition to when agent work FAILS (e.g., QA rejected)
|
|
51
|
+
* null means no auto-transition on failure (stays in current status)
|
|
52
|
+
*/
|
|
53
|
+
export const WORK_TYPE_FAIL_STATUS = {
|
|
54
|
+
'research': null,
|
|
55
|
+
'backlog-creation': null,
|
|
56
|
+
'development': null,
|
|
57
|
+
'inflight': null,
|
|
58
|
+
'qa': 'Rejected', // QA failure -> Rejected (rejection handler diagnoses next steps)
|
|
59
|
+
'acceptance': 'Rejected', // Acceptance failure -> Rejected (rejection handler diagnoses next steps)
|
|
60
|
+
'refinement': null,
|
|
61
|
+
'coordination': null,
|
|
62
|
+
'qa-coordination': 'Rejected', // QA coordination failure -> Rejected
|
|
63
|
+
'acceptance-coordination': 'Rejected', // Acceptance coordination failure -> Rejected
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Allowed statuses for each work type
|
|
67
|
+
* Used to validate that an agent isn't assigned to an issue in the wrong status
|
|
68
|
+
*/
|
|
69
|
+
export const WORK_TYPE_ALLOWED_STATUSES = {
|
|
70
|
+
'research': ['Icebox'],
|
|
71
|
+
'backlog-creation': ['Icebox'],
|
|
72
|
+
'development': ['Backlog'],
|
|
73
|
+
'inflight': ['Started'],
|
|
74
|
+
'qa': ['Finished'],
|
|
75
|
+
'acceptance': ['Delivered'],
|
|
76
|
+
'refinement': ['Rejected'],
|
|
77
|
+
'coordination': ['Backlog', 'Started'],
|
|
78
|
+
'qa-coordination': ['Finished'],
|
|
79
|
+
'acceptance-coordination': ['Delivered'],
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Valid work types for each status (reverse of WORK_TYPE_ALLOWED_STATUSES)
|
|
83
|
+
* Used to constrain keyword detection to only valid options for the current status
|
|
84
|
+
*
|
|
85
|
+
* For example:
|
|
86
|
+
* - Icebox issues can use keywords to choose between 'research' and 'backlog-creation'
|
|
87
|
+
* - Backlog issues only have 'development' as valid, so keywords won't change work type
|
|
88
|
+
* but could still provide agent specialization hints
|
|
89
|
+
*/
|
|
90
|
+
export const STATUS_VALID_WORK_TYPES = {
|
|
91
|
+
'Icebox': ['research', 'backlog-creation'],
|
|
92
|
+
'Backlog': ['development', 'coordination'],
|
|
93
|
+
'Started': ['inflight'],
|
|
94
|
+
'Finished': ['qa', 'qa-coordination'],
|
|
95
|
+
'Delivered': ['acceptance', 'acceptance-coordination'],
|
|
96
|
+
'Rejected': ['refinement'],
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Get valid work types for a given status
|
|
100
|
+
* Returns empty array if status is unknown
|
|
101
|
+
*/
|
|
102
|
+
export function getValidWorkTypesForStatus(status) {
|
|
103
|
+
return STATUS_VALID_WORK_TYPES[status] ?? [];
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Validate that a work type is appropriate for an issue's current status
|
|
107
|
+
*
|
|
108
|
+
* @param workType - The work type being assigned
|
|
109
|
+
* @param issueStatus - The current status of the issue
|
|
110
|
+
* @returns Validation result with error message if invalid
|
|
111
|
+
*/
|
|
112
|
+
export function validateWorkTypeForStatus(workType, issueStatus) {
|
|
113
|
+
const allowedStatuses = WORK_TYPE_ALLOWED_STATUSES[workType];
|
|
114
|
+
if (!allowedStatuses.includes(issueStatus)) {
|
|
115
|
+
return {
|
|
116
|
+
valid: false,
|
|
117
|
+
error: `Cannot assign ${workType} work to issue in ${issueStatus} status. Expected: ${allowedStatuses.join(', ')}`,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return { valid: true };
|
|
121
|
+
}
|