@dcyfr/ai 3.0.1 → 3.0.2

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 (64) hide show
  1. package/LICENSE +11 -30
  2. package/README.md +211 -138
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/ai/core/provider-registry.d.ts +8 -0
  5. package/dist/ai/core/provider-registry.d.ts.map +1 -1
  6. package/dist/ai/core/provider-registry.js +17 -2
  7. package/dist/ai/core/provider-registry.js.map +1 -1
  8. package/dist/ai/metacognition/config.d.ts +41 -0
  9. package/dist/ai/metacognition/config.d.ts.map +1 -0
  10. package/dist/ai/metacognition/config.js +51 -0
  11. package/dist/ai/metacognition/config.js.map +1 -0
  12. package/dist/ai/metacognition/governance.d.ts +68 -0
  13. package/dist/ai/metacognition/governance.d.ts.map +1 -0
  14. package/dist/ai/metacognition/governance.js +118 -0
  15. package/dist/ai/metacognition/governance.js.map +1 -0
  16. package/dist/ai/metacognition/index.d.ts +24 -0
  17. package/dist/ai/metacognition/index.d.ts.map +1 -0
  18. package/dist/ai/metacognition/index.js +18 -0
  19. package/dist/ai/metacognition/index.js.map +1 -0
  20. package/dist/ai/metacognition/ledger.d.ts +121 -0
  21. package/dist/ai/metacognition/ledger.d.ts.map +1 -0
  22. package/dist/ai/metacognition/ledger.js +268 -0
  23. package/dist/ai/metacognition/ledger.js.map +1 -0
  24. package/dist/ai/metacognition/runtime.d.ts +205 -0
  25. package/dist/ai/metacognition/runtime.d.ts.map +1 -0
  26. package/dist/ai/metacognition/runtime.js +391 -0
  27. package/dist/ai/metacognition/runtime.js.map +1 -0
  28. package/dist/ai/metacognition/telemetry.d.ts +144 -0
  29. package/dist/ai/metacognition/telemetry.d.ts.map +1 -0
  30. package/dist/ai/metacognition/telemetry.js +149 -0
  31. package/dist/ai/metacognition/telemetry.js.map +1 -0
  32. package/dist/ai/metacognition/transfer.d.ts +153 -0
  33. package/dist/ai/metacognition/transfer.d.ts.map +1 -0
  34. package/dist/ai/metacognition/transfer.js +182 -0
  35. package/dist/ai/metacognition/transfer.js.map +1 -0
  36. package/dist/ai/metacognition/types.d.ts +302 -0
  37. package/dist/ai/metacognition/types.d.ts.map +1 -0
  38. package/dist/ai/metacognition/types.js +79 -0
  39. package/dist/ai/metacognition/types.js.map +1 -0
  40. package/dist/ai/runtime/agent-runtime.d.ts.map +1 -1
  41. package/dist/ai/runtime/agent-runtime.js.map +1 -1
  42. package/dist/ai/src/integrations/linear/index.d.ts +19 -0
  43. package/dist/ai/src/integrations/linear/index.d.ts.map +1 -0
  44. package/dist/ai/src/integrations/linear/index.js +20 -0
  45. package/dist/ai/src/integrations/linear/index.js.map +1 -0
  46. package/dist/ai/src/integrations/linear/issue-mapper.d.ts +93 -0
  47. package/dist/ai/src/integrations/linear/issue-mapper.d.ts.map +1 -0
  48. package/dist/ai/src/integrations/linear/issue-mapper.js +186 -0
  49. package/dist/ai/src/integrations/linear/issue-mapper.js.map +1 -0
  50. package/dist/ai/src/integrations/linear/linear-client.d.ts +199 -0
  51. package/dist/ai/src/integrations/linear/linear-client.d.ts.map +1 -0
  52. package/dist/ai/src/integrations/linear/linear-client.js +300 -0
  53. package/dist/ai/src/integrations/linear/linear-client.js.map +1 -0
  54. package/dist/ai/src/runtime/agent-runtime.js +1 -1
  55. package/dist/ai/src/runtime/agent-runtime.js.map +1 -1
  56. package/dist/ai/src/security/prompt-scan-worker.d.ts +63 -0
  57. package/dist/ai/src/security/prompt-scan-worker.d.ts.map +1 -0
  58. package/dist/ai/src/security/prompt-scan-worker.js +174 -0
  59. package/dist/ai/src/security/prompt-scan-worker.js.map +1 -0
  60. package/dist/ai/src/telemetry/delegation-telemetry.d.ts +10 -0
  61. package/dist/ai/src/telemetry/delegation-telemetry.d.ts.map +1 -1
  62. package/dist/ai/src/telemetry/delegation-telemetry.js +23 -0
  63. package/dist/ai/src/telemetry/delegation-telemetry.js.map +1 -1
  64. package/package.json +25 -15
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Issue Key Correlation and Mapping
3
+ *
4
+ * Extracts issue keys from GitHub PR titles, branch names, and commit messages
5
+ * to automatically correlate them with Linear issues. Implements a priority-based
6
+ * matching strategy and stores mappings for future reference.
7
+ *
8
+ * Correlation Strategy (in order of confidence):
9
+ * 1. Branch name: `feature/DCYFR-123-description` [confidence: 0.95]
10
+ * 2. PR title: `[DCYFR-123] Feature description` [confidence: 0.85]
11
+ * 3. Commit message: Usually at end: `... Fixes DCYFR-123` [confidence: 0.75]
12
+ * 4. Manual mapping: User explicitly linked (stored in DB) [confidence: 1.0]
13
+ *
14
+ * Usage:
15
+ * const mapper = new IssueMapper({ store: myMappingStore });
16
+ * const match = await mapper.correlate({
17
+ * branch: 'feature/DCYFR-123-auth',
18
+ * prTitle: '[DCYFR-123] Add OAuth',
19
+ * commits: ['Add auth module (#123)', 'Fixes DCYFR-123']
20
+ * });
21
+ * // => { linearIssueId: 'uuid-xxx', identifier: 'DCYFR-123', confidence: 0.95 }
22
+ *
23
+ * Part of: Phase 2 (MVP Linear Sync) + Phase 3 (Bidirectional Sync)
24
+ * Test: __tests__/integrations/linear/issue-mapper.test.ts
25
+ */
26
+ export interface CorrelationInput {
27
+ /** Git branch name (e.g., "feature/DCYFR-123-auth") */
28
+ branch?: string;
29
+ /** Pull request title (e.g., "[DCYFR-123] Add OAuth") */
30
+ prTitle?: string;
31
+ /** List of commit messages to search */
32
+ commits?: string[];
33
+ /** Raw PR body/description to search */
34
+ prBody?: string;
35
+ }
36
+ export interface CorrelationResult {
37
+ /** Linear issue identifier if found (e.g., "DCYFR-123") */
38
+ identifier: string | null;
39
+ /** Source of the match (branch|pr_title|commit_message|pr_body) */
40
+ source: 'branch' | 'pr_title' | 'commit_message' | 'pr_body' | null;
41
+ /** Confidence score (0-1, where 1.0 = certain) */
42
+ confidence: number;
43
+ /** All potential matches found (for debugging/validation) */
44
+ alternates: Array<{
45
+ identifier: string;
46
+ source: string;
47
+ confidence: number;
48
+ }>;
49
+ }
50
+ export declare class IssueMapper {
51
+ /**
52
+ * Extract issue key from a string, returning up to `limit` matches.
53
+ */
54
+ static extractIssueKeys(text: string, limit?: number): string[];
55
+ /**
56
+ * Extract issue key from branch name (highest confidence).
57
+ * Pattern: feature/DCYFR-123-description
58
+ */
59
+ static extractFromBranch(branch: string): string | null;
60
+ /**
61
+ * Extract issue key from PR title (high confidence).
62
+ * Patterns: "[DCYFR-123] Title", "[DCYFR-123]: Title"
63
+ */
64
+ static extractFromPrTitle(title: string): string | null;
65
+ /**
66
+ * Extract issue key from commit messages (moderate confidence).
67
+ * Patterns: "Fixes DCYFR-123", "Closes DCYFR-123", "Resolves DCYFR-123"
68
+ */
69
+ static extractFromCommits(commits: string[]): string | null;
70
+ /**
71
+ * Extract issue keys from PR body/description (low confidence).
72
+ * Uses generic issue key pattern matching.
73
+ */
74
+ static extractFromPrBody(body: string): string[];
75
+ /**
76
+ * Correlate a pull request to a Linear issue by examining branch, title, commits, and body.
77
+ *
78
+ * Returns the best match with highest confidence, plus alternates for manual review.
79
+ * Implements priority-based matching:
80
+ * 1. Branch name (0.95) — most specific
81
+ * 2. PR title (0.85)
82
+ * 3. Commit messages (0.75)
83
+ * 4. PR body (0.60) — lowest confidence
84
+ */
85
+ static correlate(input: CorrelationInput): CorrelationResult;
86
+ /**
87
+ * Validate that a correlation result meets minimum confidence threshold.
88
+ * Default threshold: 0.8 (requires high confidence)
89
+ */
90
+ static isConfident(result: CorrelationResult, threshold?: number): boolean;
91
+ }
92
+ export default IssueMapper;
93
+ //# sourceMappingURL=issue-mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-mapper.d.ts","sourceRoot":"","sources":["../../../../../packages/ai/src/integrations/linear/issue-mapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,WAAW,gBAAgB;IAC7B,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAC9B,2DAA2D;IAC3D,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,mEAAmE;IACnE,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,gBAAgB,GAAG,SAAS,GAAG,IAAI,CAAC;IACpE,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,UAAU,EAAE,KAAK,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;CACN;AAoCD,qBAAa,WAAW;IACpB;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,MAAM,EAAE;IAQlE;;;OAGG;IACH,MAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKvD;;;OAGG;IACH,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKvD;;;OAGG;IACH,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI;IAU3D;;;OAGG;IACH,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAIhD;;;;;;;;;OASG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB;IA+E5D;;;OAGG;IACH,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,iBAAiB,EAAE,SAAS,SAAM,GAAG,OAAO;CAG1E;AAED,eAAe,WAAW,CAAC"}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Issue Key Correlation and Mapping
3
+ *
4
+ * Extracts issue keys from GitHub PR titles, branch names, and commit messages
5
+ * to automatically correlate them with Linear issues. Implements a priority-based
6
+ * matching strategy and stores mappings for future reference.
7
+ *
8
+ * Correlation Strategy (in order of confidence):
9
+ * 1. Branch name: `feature/DCYFR-123-description` [confidence: 0.95]
10
+ * 2. PR title: `[DCYFR-123] Feature description` [confidence: 0.85]
11
+ * 3. Commit message: Usually at end: `... Fixes DCYFR-123` [confidence: 0.75]
12
+ * 4. Manual mapping: User explicitly linked (stored in DB) [confidence: 1.0]
13
+ *
14
+ * Usage:
15
+ * const mapper = new IssueMapper({ store: myMappingStore });
16
+ * const match = await mapper.correlate({
17
+ * branch: 'feature/DCYFR-123-auth',
18
+ * prTitle: '[DCYFR-123] Add OAuth',
19
+ * commits: ['Add auth module (#123)', 'Fixes DCYFR-123']
20
+ * });
21
+ * // => { linearIssueId: 'uuid-xxx', identifier: 'DCYFR-123', confidence: 0.95 }
22
+ *
23
+ * Part of: Phase 2 (MVP Linear Sync) + Phase 3 (Bidirectional Sync)
24
+ * Test: __tests__/integrations/linear/issue-mapper.test.ts
25
+ */
26
+ // ============================================================================
27
+ // Issue Key Regex Patterns
28
+ // ============================================================================
29
+ /**
30
+ * Matches Jira-style issue keys: TEAM-NUMBER
31
+ * Examples: DCYFR-123, FOO-999
32
+ *
33
+ * Pattern explanation:
34
+ * [A-Z]+ = one or more uppercase letters (team key)
35
+ * - = hyphen
36
+ * \d+ = one or more digits (issue number)
37
+ */
38
+ const ISSUE_KEY_PATTERN = /([A-Z][A-Z0-9]*-\d+)/g;
39
+ /**
40
+ * Branch name format: feature/TEAM-NUMBER-description
41
+ */
42
+ const BRANCH_PATTERN = /^[a-z]+\/([A-Z][A-Z0-9]*-\d+)/;
43
+ /**
44
+ * PR title format: "[TEAM-NUMBER] Description" or "[TEAM-NUMBER] Description (Fixes)"
45
+ */
46
+ const PR_TITLE_PATTERN = /^\[([A-Z][A-Z0-9]*-\d+)\]/;
47
+ /**
48
+ * Commit pattern: "Description (Fixes|Closes|Resolves) TEAM-NUMBER"
49
+ */
50
+ const COMMIT_PATTERN = /(Fixes|Closes|Resolves|Fixed|Closed|Resolved)\s+([A-Z][A-Z0-9]*-\d+)/i;
51
+ // ============================================================================
52
+ // IssueMapper
53
+ // ============================================================================
54
+ export class IssueMapper {
55
+ /**
56
+ * Extract issue key from a string, returning up to `limit` matches.
57
+ */
58
+ static extractIssueKeys(text, limit = 5) {
59
+ const matches = text.matchAll(ISSUE_KEY_PATTERN);
60
+ return Array.from(matches)
61
+ .map(m => m[1])
62
+ .slice(0, limit)
63
+ .filter((v, i, a) => a.indexOf(v) === i); // Deduplicate
64
+ }
65
+ /**
66
+ * Extract issue key from branch name (highest confidence).
67
+ * Pattern: feature/DCYFR-123-description
68
+ */
69
+ static extractFromBranch(branch) {
70
+ const match = branch.match(BRANCH_PATTERN);
71
+ return match ? match[1] : null;
72
+ }
73
+ /**
74
+ * Extract issue key from PR title (high confidence).
75
+ * Patterns: "[DCYFR-123] Title", "[DCYFR-123]: Title"
76
+ */
77
+ static extractFromPrTitle(title) {
78
+ const match = title.match(PR_TITLE_PATTERN);
79
+ return match ? match[1] : null;
80
+ }
81
+ /**
82
+ * Extract issue key from commit messages (moderate confidence).
83
+ * Patterns: "Fixes DCYFR-123", "Closes DCYFR-123", "Resolves DCYFR-123"
84
+ */
85
+ static extractFromCommits(commits) {
86
+ for (const commit of commits) {
87
+ const match = commit.match(COMMIT_PATTERN);
88
+ if (match) {
89
+ return match[2]; // Return the issue key
90
+ }
91
+ }
92
+ return null;
93
+ }
94
+ /**
95
+ * Extract issue keys from PR body/description (low confidence).
96
+ * Uses generic issue key pattern matching.
97
+ */
98
+ static extractFromPrBody(body) {
99
+ return this.extractIssueKeys(body, 1);
100
+ }
101
+ /**
102
+ * Correlate a pull request to a Linear issue by examining branch, title, commits, and body.
103
+ *
104
+ * Returns the best match with highest confidence, plus alternates for manual review.
105
+ * Implements priority-based matching:
106
+ * 1. Branch name (0.95) — most specific
107
+ * 2. PR title (0.85)
108
+ * 3. Commit messages (0.75)
109
+ * 4. PR body (0.60) — lowest confidence
110
+ */
111
+ static correlate(input) {
112
+ const candidates = [];
113
+ // 1. Branch (highest priority)
114
+ if (input.branch) {
115
+ const key = this.extractFromBranch(input.branch);
116
+ if (key) {
117
+ candidates.push({
118
+ identifier: key,
119
+ source: 'branch',
120
+ confidence: 0.95,
121
+ });
122
+ }
123
+ }
124
+ // 2. PR title
125
+ if (input.prTitle) {
126
+ const key = this.extractFromPrTitle(input.prTitle);
127
+ if (key) {
128
+ candidates.push({
129
+ identifier: key,
130
+ source: 'pr_title',
131
+ confidence: 0.85,
132
+ });
133
+ }
134
+ }
135
+ // 3. Commit messages
136
+ if (input.commits && input.commits.length > 0) {
137
+ const key = this.extractFromCommits(input.commits);
138
+ if (key) {
139
+ candidates.push({
140
+ identifier: key,
141
+ source: 'commit_message',
142
+ confidence: 0.75,
143
+ });
144
+ }
145
+ }
146
+ // 4. PR body
147
+ if (input.prBody) {
148
+ const keys = this.extractFromPrBody(input.prBody);
149
+ for (const key of keys) {
150
+ candidates.push({
151
+ identifier: key,
152
+ source: 'pr_body',
153
+ confidence: 0.60,
154
+ });
155
+ }
156
+ }
157
+ // Return best match (by confidence, then by source priority)
158
+ if (candidates.length === 0) {
159
+ return {
160
+ identifier: null,
161
+ source: null,
162
+ confidence: 0,
163
+ alternates: [],
164
+ };
165
+ }
166
+ // Sort by confidence descending
167
+ candidates.sort((a, b) => b.confidence - a.confidence);
168
+ const best = candidates[0];
169
+ const alternates = candidates.slice(1);
170
+ return {
171
+ identifier: best.identifier,
172
+ source: best.source,
173
+ confidence: best.confidence,
174
+ alternates,
175
+ };
176
+ }
177
+ /**
178
+ * Validate that a correlation result meets minimum confidence threshold.
179
+ * Default threshold: 0.8 (requires high confidence)
180
+ */
181
+ static isConfident(result, threshold = 0.8) {
182
+ return result.confidence >= threshold && result.identifier !== null;
183
+ }
184
+ }
185
+ export default IssueMapper;
186
+ //# sourceMappingURL=issue-mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-mapper.js","sourceRoot":"","sources":["../../../../../packages/ai/src/integrations/linear/issue-mapper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,199 @@
1
+ /**
2
+ * Linear API Client
3
+ *
4
+ * Provides a typed, authenticated wrapper around the Linear GraphQL API for
5
+ * reading/writing issues, creating comments, adding labels, and managing
6
+ * issue state transitions.
7
+ *
8
+ * Usage:
9
+ * const client = new LinearClient({ apiKey: process.env.LINEAR_API_KEY });
10
+ * const issue = await client.getIssue('DCYFR-123');
11
+ * await client.addComment(issue.id, 'Review started');
12
+ * await client.updateIssueState(issue.id, 'In Review');
13
+ *
14
+ * Authentication:
15
+ * - Requires LINEAR_API_KEY environment variable (org API key)
16
+ * - API documentation: https://developers.linear.app/docs
17
+ * - GraphQL endpoint: https://api.linear.app/graphql
18
+ *
19
+ * Rate Limiting:
20
+ * - Linear API: 1000 requests/hour per token
21
+ * - Implements sliding-window rate limiter with exponential backoff
22
+ *
23
+ * Idempotency:
24
+ * - All write operations include deduplication keys
25
+ * - Prevents duplicate comments/updates on identical requests
26
+ *
27
+ * Error Handling:
28
+ * - GraphQL errors returned as structured `LinearError`
29
+ * - Network failures trigger exponential backoff retry
30
+ * - Rate limits surface as `RateLimitError`
31
+ *
32
+ * Part of: dcyfr-ai integration layer
33
+ * Roadmap: Phase 2 (MVP Linear Sync) + Phase 3 (Bidirectional Sync)
34
+ * Test: __tests__/integrations/linear/linear-client.test.ts
35
+ */
36
+ type GraphQLError = {
37
+ message: string;
38
+ extensions?: Record<string, unknown>;
39
+ };
40
+ /**
41
+ * Linear API credentials and configuration.
42
+ */
43
+ export interface LinearClientConfig {
44
+ /** Linear API key (org-scoped, from workspace settings) */
45
+ apiKey: string;
46
+ /** Optional: Override GraphQL endpoint (default: https://api.linear.app/graphql) */
47
+ graphqlEndpoint?: string;
48
+ /** Optional: Maximum retry attempts for transient failures (default: 3) */
49
+ maxRetries?: number;
50
+ /** Optional: Timeout in ms for API requests (default: 30000) */
51
+ requestTimeout?: number;
52
+ }
53
+ /**
54
+ * Mapping between Linear issue and GitHub PR/issue.
55
+ * Stored in persistent mapping store for correlation.
56
+ */
57
+ export interface IssueMapping {
58
+ /** Linear issue ID (UUID) */
59
+ linearIssueId: string;
60
+ /** GitHub repository owner */
61
+ owner: string;
62
+ /** GitHub repository name */
63
+ repo: string;
64
+ /** GitHub PR number (if PR) or issue number (if issue) */
65
+ prOrIssueNumber: number;
66
+ /** How the correlation was established */
67
+ correlationSource: 'branch' | 'pr_title' | 'commit_message' | 'manual';
68
+ /** Confidence score (0-1); 1.0 = certain, < 0.8 = needs review */
69
+ confidence: number;
70
+ /** When the mapping was created */
71
+ createdAt: Date;
72
+ /** When the mapping was last verified */
73
+ lastVerifiedAt?: Date;
74
+ }
75
+ /**
76
+ * Linear issue with relevant fields for review/PR sync.
77
+ */
78
+ export interface LinearIssue {
79
+ id: string;
80
+ identifier: string;
81
+ title: string;
82
+ description?: string;
83
+ state: {
84
+ id: string;
85
+ name: string;
86
+ };
87
+ assignee?: {
88
+ id: string;
89
+ name: string;
90
+ email: string;
91
+ };
92
+ team: {
93
+ id: string;
94
+ key: string;
95
+ };
96
+ labels: Array<{
97
+ id: string;
98
+ name: string;
99
+ }>;
100
+ createdAt: string;
101
+ updatedAt: string;
102
+ /** Custom field for linking to GitHub PR */
103
+ _githubPrUrl?: string;
104
+ /** Custom field for PR review status */
105
+ _prReviewStatus?: 'pending' | 'in_progress' | 'approved' | 'changes_requested';
106
+ }
107
+ /**
108
+ * Linear issue state for workflow transitions.
109
+ */
110
+ export interface LinearIssueState {
111
+ id: string;
112
+ name: string;
113
+ type: 'backlog' | 'unstarted' | 'started' | 'completed' | 'cancelled';
114
+ position: number;
115
+ }
116
+ /**
117
+ * Comment created on a Linear issue.
118
+ */
119
+ export interface LinearComment {
120
+ id: string;
121
+ body: string;
122
+ author: {
123
+ id: string;
124
+ name: string;
125
+ };
126
+ createdAt: string;
127
+ updatedAt: string;
128
+ }
129
+ /**
130
+ * Linear API error with detailed context.
131
+ */
132
+ export declare class LinearError extends Error {
133
+ readonly statusCode?: number | undefined;
134
+ readonly graphqlErrors?: GraphQLError[] | undefined;
135
+ constructor(message: string, statusCode?: number | undefined, graphqlErrors?: GraphQLError[] | undefined);
136
+ }
137
+ /**
138
+ * Rate limit error when API quota is exceeded.
139
+ */
140
+ export declare class LinearRateLimitError extends LinearError {
141
+ readonly resetAt: Date;
142
+ constructor(message: string, resetAt: Date);
143
+ }
144
+ export declare class LinearClient {
145
+ private apiKey;
146
+ private graphqlEndpoint;
147
+ private maxRetries;
148
+ private requestTimeout;
149
+ private requestCount;
150
+ private requestResetAt;
151
+ constructor(config: LinearClientConfig);
152
+ /**
153
+ * Retrieve a Linear issue by identifier (e.g., "DCYFR-123").
154
+ */
155
+ getIssue(identifier: string): Promise<LinearIssue>;
156
+ /**
157
+ * Get all available workflow states for a team.
158
+ * Used for determining valid state transitions.
159
+ */
160
+ getWorkflowStates(teamId: string): Promise<LinearIssueState[]>;
161
+ /**
162
+ * Update an issue's state (e.g., "In Review" → "Changes Requested").
163
+ * Returns the updated issue.
164
+ */
165
+ updateIssueState(issueId: string, newState: string): Promise<LinearIssue>;
166
+ /**
167
+ * Add a comment to a Linear issue.
168
+ * Includes deduplication key to prevent duplicate comments.
169
+ */
170
+ addComment(issueId: string, body: string, deduplicationKey?: string): Promise<LinearComment>;
171
+ /**
172
+ * Add a label to a Linear issue.
173
+ */
174
+ addLabel(issueId: string, labelId: string): Promise<void>;
175
+ /**
176
+ * Assign a Linear issue to a team member.
177
+ */
178
+ assignIssue(issueId: string, userId: string): Promise<void>;
179
+ /**
180
+ * Search for issues by query (e.g., team or label filters).
181
+ * Used for finding issues linked to GitHub PRs.
182
+ */
183
+ searchIssues(query: string, limit?: number): Promise<LinearIssue[]>;
184
+ /**
185
+ * Internal: Execute a GraphQL query/mutation with rate-limit and retry handling.
186
+ */
187
+ private graphql;
188
+ /**
189
+ * Check if request is within rate limit quota.
190
+ * Resets hourly.
191
+ */
192
+ private checkRateLimit;
193
+ /**
194
+ * Determine if an error is transient (can be retried).
195
+ */
196
+ private isTransient;
197
+ }
198
+ export default LinearClient;
199
+ //# sourceMappingURL=linear-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-client.d.ts","sourceRoot":"","sources":["../../../../../packages/ai/src/integrations/linear/linear-client.ts"],"names":[],"mappings":"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"}