specweave 0.30.18 → 0.32.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/CLAUDE.md +22 -0
- package/dist/src/adapters/README.md +275 -0
- package/dist/src/adapters/adapter-base.d.ts +1 -1
- package/dist/src/adapters/adapter-base.js +3 -3
- package/dist/src/adapters/adapter-base.js.map +1 -1
- package/dist/src/adapters/adapter-loader.d.ts +11 -10
- package/dist/src/adapters/adapter-loader.d.ts.map +1 -1
- package/dist/src/adapters/adapter-loader.js +31 -21
- package/dist/src/adapters/adapter-loader.js.map +1 -1
- package/dist/src/adapters/claude/README.md +233 -0
- package/dist/src/adapters/codex/README.md +105 -0
- package/dist/src/adapters/cursor/.cursor/context/docs-context.md +62 -0
- package/dist/src/adapters/cursor/.cursor/context/increments-context.md +71 -0
- package/dist/src/adapters/cursor/.cursor/context/strategy-context.md +73 -0
- package/dist/src/adapters/cursor/.cursor/context/tests-context.md +89 -0
- package/dist/src/adapters/cursor/README.md +283 -0
- package/dist/src/adapters/cursor/adapter.d.ts +5 -1
- package/dist/src/adapters/cursor/adapter.d.ts.map +1 -1
- package/dist/src/adapters/cursor/adapter.js +18 -115
- package/dist/src/adapters/cursor/adapter.js.map +1 -1
- package/dist/src/adapters/gemini/README.md +97 -0
- package/dist/src/adapters/generic/README.md +277 -0
- package/dist/src/adapters/registry.yaml +197 -0
- package/dist/src/cli/helpers/init/living-docs-preflight.js +12 -12
- package/dist/src/cli/helpers/init/living-docs-preflight.js.map +1 -1
- package/dist/src/config/types.d.ts +1208 -203
- package/dist/src/config/types.d.ts.map +1 -1
- package/dist/src/core/external-tools/external-items-counter.d.ts +62 -0
- package/dist/src/core/external-tools/external-items-counter.d.ts.map +1 -0
- package/dist/src/core/external-tools/external-items-counter.js +206 -0
- package/dist/src/core/external-tools/external-items-counter.js.map +1 -0
- package/dist/src/core/external-tools/external-items-display.d.ts +39 -0
- package/dist/src/core/external-tools/external-items-display.d.ts.map +1 -0
- package/dist/src/core/external-tools/external-items-display.js +185 -0
- package/dist/src/core/external-tools/external-items-display.js.map +1 -0
- package/dist/src/core/external-tools/index.d.ts +8 -0
- package/dist/src/core/external-tools/index.d.ts.map +1 -0
- package/dist/src/core/external-tools/index.js +8 -0
- package/dist/src/core/external-tools/index.js.map +1 -0
- package/dist/src/core/external-tools/providers/ado-items-adapter.d.ts +39 -0
- package/dist/src/core/external-tools/providers/ado-items-adapter.d.ts.map +1 -0
- package/dist/src/core/external-tools/providers/ado-items-adapter.js +188 -0
- package/dist/src/core/external-tools/providers/ado-items-adapter.js.map +1 -0
- package/dist/src/core/external-tools/providers/github-items-adapter.d.ts +38 -0
- package/dist/src/core/external-tools/providers/github-items-adapter.d.ts.map +1 -0
- package/dist/src/core/external-tools/providers/github-items-adapter.js +136 -0
- package/dist/src/core/external-tools/providers/github-items-adapter.js.map +1 -0
- package/dist/src/core/external-tools/providers/index.d.ts +7 -0
- package/dist/src/core/external-tools/providers/index.d.ts.map +1 -0
- package/dist/src/core/external-tools/providers/index.js +7 -0
- package/dist/src/core/external-tools/providers/index.js.map +1 -0
- package/dist/src/core/external-tools/providers/jira-items-adapter.d.ts +42 -0
- package/dist/src/core/external-tools/providers/jira-items-adapter.d.ts.map +1 -0
- package/dist/src/core/external-tools/providers/jira-items-adapter.js +153 -0
- package/dist/src/core/external-tools/providers/jira-items-adapter.js.map +1 -0
- package/dist/src/core/external-tools/types.d.ts +78 -0
- package/dist/src/core/external-tools/types.d.ts.map +1 -0
- package/dist/src/core/external-tools/types.js +19 -0
- package/dist/src/core/external-tools/types.js.map +1 -0
- package/dist/src/core/increment/increment-utils.d.ts +13 -37
- package/dist/src/core/increment/increment-utils.d.ts.map +1 -1
- package/dist/src/core/increment/increment-utils.js +17 -64
- package/dist/src/core/increment/increment-utils.js.map +1 -1
- package/dist/src/core/increment/status-change-sync-trigger.d.ts.map +1 -1
- package/dist/src/core/increment/status-change-sync-trigger.js +4 -0
- package/dist/src/core/increment/status-change-sync-trigger.js.map +1 -1
- package/dist/src/core/llm/providers/azure-openai-provider.d.ts.map +1 -1
- package/dist/src/core/llm/providers/azure-openai-provider.js +1 -0
- package/dist/src/core/llm/providers/azure-openai-provider.js.map +1 -1
- package/dist/src/core/llm/providers/bedrock-provider.d.ts.map +1 -1
- package/dist/src/core/llm/providers/bedrock-provider.js +4 -3
- package/dist/src/core/llm/providers/bedrock-provider.js.map +1 -1
- package/dist/src/core/llm/providers/openai-provider.d.ts.map +1 -1
- package/dist/src/core/llm/providers/openai-provider.js +1 -0
- package/dist/src/core/llm/providers/openai-provider.js.map +1 -1
- package/dist/src/core/llm/providers/vertex-ai-provider.d.ts.map +1 -1
- package/dist/src/core/llm/providers/vertex-ai-provider.js +1 -0
- package/dist/src/core/llm/providers/vertex-ai-provider.js.map +1 -1
- package/dist/src/importers/ado-importer.d.ts.map +1 -1
- package/dist/src/importers/ado-importer.js +2 -1
- package/dist/src/importers/ado-importer.js.map +1 -1
- package/dist/src/importers/github-importer.d.ts.map +1 -1
- package/dist/src/importers/github-importer.js +2 -1
- package/dist/src/importers/github-importer.js.map +1 -1
- package/dist/src/importers/jira-importer.d.ts.map +1 -1
- package/dist/src/importers/jira-importer.js +2 -1
- package/dist/src/importers/jira-importer.js.map +1 -1
- package/dist/src/init/architecture/types.d.ts +140 -33
- package/dist/src/init/architecture/types.d.ts.map +1 -1
- package/dist/src/init/compliance/types.d.ts +27 -30
- package/dist/src/init/compliance/types.d.ts.map +1 -1
- package/dist/src/init/repo/types.d.ts +34 -11
- package/dist/src/init/repo/types.d.ts.map +1 -1
- package/dist/src/init/research/src/config/types.d.ts +82 -15
- package/dist/src/init/research/src/config/types.d.ts.map +1 -1
- package/dist/src/init/research/types.d.ts +93 -38
- package/dist/src/init/research/types.d.ts.map +1 -1
- package/dist/src/init/team/types.d.ts +42 -4
- package/dist/src/init/team/types.d.ts.map +1 -1
- package/dist/src/utils/fs-native.d.ts +2 -1
- package/dist/src/utils/fs-native.d.ts.map +1 -1
- package/dist/src/utils/fs-native.js +6 -1
- package/dist/src/utils/fs-native.js.map +1 -1
- package/dist/src/utils/html-to-mdx.d.ts +37 -0
- package/dist/src/utils/html-to-mdx.d.ts.map +1 -0
- package/dist/src/utils/html-to-mdx.js +98 -0
- package/dist/src/utils/html-to-mdx.js.map +1 -0
- package/package.json +3 -3
- package/plugins/specweave/commands/specweave-external.md +150 -0
- package/plugins/specweave/commands/specweave-judge.md +11 -0
- package/plugins/specweave/hooks/lib/update-status-line.sh +16 -4
- package/plugins/specweave/hooks/universal/hook-wrapper.cmd +26 -26
- package/plugins/specweave/hooks/universal/session-start.cmd +16 -16
- package/plugins/specweave/hooks/universal/session-start.ps1 +16 -16
- package/plugins/specweave/lib/vendor/utils/fs-native.d.ts +2 -1
- package/plugins/specweave/lib/vendor/utils/fs-native.js +6 -1
- package/plugins/specweave/lib/vendor/utils/fs-native.js.map +1 -1
- package/plugins/specweave-docs/commands/build.md +47 -73
- package/plugins/specweave-docs/commands/preview.md +181 -87
- package/plugins/specweave-docs/skills/preview/SKILL.md +45 -56
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +0 -296
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +0 -444
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Azure DevOps Items Adapter - OPTIMIZED FOR SCALE
|
|
3
|
+
*
|
|
4
|
+
* Three-tier fetching:
|
|
5
|
+
* 1. getOpenCount() - Single WIQL query, returns count (for status)
|
|
6
|
+
* 2. getOpenItems(filter) - Paginated, filtered (for details)
|
|
7
|
+
*
|
|
8
|
+
* Requires ADO_ORG_URL, ADO_PROJECT, ADO_PAT in environment
|
|
9
|
+
*/
|
|
10
|
+
import { STALE_THRESHOLD_DAYS, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE, } from '../types.js';
|
|
11
|
+
import { consoleLogger } from '../../../utils/logger.js';
|
|
12
|
+
export class AdoItemsAdapter {
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.orgUrl = options.orgUrl.replace(/\/$/, '');
|
|
15
|
+
this.project = options.project;
|
|
16
|
+
this.pat = options.pat;
|
|
17
|
+
this.logger = options.logger ?? consoleLogger;
|
|
18
|
+
}
|
|
19
|
+
static fromEnv(options) {
|
|
20
|
+
const orgUrl = process.env.ADO_ORG_URL || process.env.AZURE_DEVOPS_ORG_URL;
|
|
21
|
+
const project = process.env.ADO_PROJECT || process.env.AZURE_DEVOPS_PROJECT;
|
|
22
|
+
const pat = process.env.ADO_PAT || process.env.AZURE_DEVOPS_PAT;
|
|
23
|
+
if (!orgUrl || !project || !pat) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
return new AdoItemsAdapter({
|
|
27
|
+
orgUrl,
|
|
28
|
+
project,
|
|
29
|
+
pat,
|
|
30
|
+
logger: options?.logger,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
getProviderName() {
|
|
34
|
+
return 'ado';
|
|
35
|
+
}
|
|
36
|
+
async isConfigured() {
|
|
37
|
+
return !!(this.orgUrl && this.project && this.pat);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* TIER 1: Fast count - single WIQL query, just count IDs
|
|
41
|
+
* WIQL returns workItem IDs, we just count them without fetching details
|
|
42
|
+
*/
|
|
43
|
+
async getOpenCount() {
|
|
44
|
+
if (!await this.isConfigured()) {
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const wiql = {
|
|
49
|
+
query: `SELECT [System.Id]
|
|
50
|
+
FROM WorkItems
|
|
51
|
+
WHERE [System.TeamProject] = '${this.project}'
|
|
52
|
+
AND [System.State] NOT IN ('Done', 'Closed', 'Removed', 'Completed')`,
|
|
53
|
+
};
|
|
54
|
+
const queryUrl = `${this.orgUrl}/${this.project}/_apis/wit/wiql?api-version=7.0`;
|
|
55
|
+
const authString = Buffer.from(`:${this.pat}`).toString('base64');
|
|
56
|
+
const response = await fetch(queryUrl, {
|
|
57
|
+
method: 'POST',
|
|
58
|
+
headers: {
|
|
59
|
+
'Authorization': `Basic ${authString}`,
|
|
60
|
+
'Content-Type': 'application/json',
|
|
61
|
+
},
|
|
62
|
+
body: JSON.stringify(wiql),
|
|
63
|
+
});
|
|
64
|
+
if (!response.ok) {
|
|
65
|
+
this.logger.error(`ADO count error: ${response.status} ${response.statusText}`);
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
const data = await response.json();
|
|
69
|
+
return data.workItems?.length || 0;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
this.logger.error(`ADO count failed: ${error}`);
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* TIER 3: Paginated items - on-demand with filters
|
|
78
|
+
*/
|
|
79
|
+
async getOpenItems(filter) {
|
|
80
|
+
if (!await this.isConfigured()) {
|
|
81
|
+
return this.emptyResult(1, DEFAULT_PAGE_SIZE);
|
|
82
|
+
}
|
|
83
|
+
const limit = Math.min(filter?.limit || DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE);
|
|
84
|
+
const offset = filter?.offset || 0;
|
|
85
|
+
const page = Math.floor(offset / limit) + 1;
|
|
86
|
+
try {
|
|
87
|
+
// First get all IDs (for total count and pagination)
|
|
88
|
+
const wiql = {
|
|
89
|
+
query: `SELECT [System.Id]
|
|
90
|
+
FROM WorkItems
|
|
91
|
+
WHERE [System.TeamProject] = '${this.project}'
|
|
92
|
+
AND [System.State] NOT IN ('Done', 'Closed', 'Removed', 'Completed')
|
|
93
|
+
ORDER BY [System.CreatedDate] DESC`,
|
|
94
|
+
};
|
|
95
|
+
const queryUrl = `${this.orgUrl}/${this.project}/_apis/wit/wiql?api-version=7.0`;
|
|
96
|
+
const authString = Buffer.from(`:${this.pat}`).toString('base64');
|
|
97
|
+
const queryResponse = await fetch(queryUrl, {
|
|
98
|
+
method: 'POST',
|
|
99
|
+
headers: {
|
|
100
|
+
'Authorization': `Basic ${authString}`,
|
|
101
|
+
'Content-Type': 'application/json',
|
|
102
|
+
},
|
|
103
|
+
body: JSON.stringify(wiql),
|
|
104
|
+
});
|
|
105
|
+
if (!queryResponse.ok) {
|
|
106
|
+
this.logger.error(`ADO WIQL error: ${queryResponse.status} ${queryResponse.statusText}`);
|
|
107
|
+
return this.emptyResult(page, limit);
|
|
108
|
+
}
|
|
109
|
+
const queryData = await queryResponse.json();
|
|
110
|
+
const allIds = queryData.workItems || [];
|
|
111
|
+
const total = allIds.length;
|
|
112
|
+
const totalPages = Math.ceil(total / limit);
|
|
113
|
+
if (total === 0) {
|
|
114
|
+
return this.emptyResult(page, limit);
|
|
115
|
+
}
|
|
116
|
+
// Get IDs for current page
|
|
117
|
+
const pageIds = allIds.slice(offset, offset + limit).map(wi => wi.id);
|
|
118
|
+
if (pageIds.length === 0) {
|
|
119
|
+
return {
|
|
120
|
+
items: [],
|
|
121
|
+
total,
|
|
122
|
+
page,
|
|
123
|
+
pageSize: limit,
|
|
124
|
+
totalPages,
|
|
125
|
+
hasMore: false,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// Fetch details for page
|
|
129
|
+
const detailsUrl = `${this.orgUrl}/${this.project}/_apis/wit/workitems?ids=${pageIds.join(',')}&fields=System.Id,System.Title,System.CreatedDate,System.State,System.Tags&api-version=7.0`;
|
|
130
|
+
const detailsResponse = await fetch(detailsUrl, {
|
|
131
|
+
headers: {
|
|
132
|
+
'Authorization': `Basic ${authString}`,
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
if (!detailsResponse.ok) {
|
|
136
|
+
this.logger.error(`ADO details error: ${detailsResponse.status}`);
|
|
137
|
+
return this.emptyResult(page, limit);
|
|
138
|
+
}
|
|
139
|
+
const detailsData = await detailsResponse.json();
|
|
140
|
+
const now = Date.now();
|
|
141
|
+
const items = detailsData.value.map(item => {
|
|
142
|
+
const createdDate = new Date(item.fields['System.CreatedDate']).getTime();
|
|
143
|
+
const ageMs = now - createdDate;
|
|
144
|
+
const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24));
|
|
145
|
+
const tags = item.fields['System.Tags']?.split(';').map(t => t.trim()) || [];
|
|
146
|
+
return {
|
|
147
|
+
id: `#${item.id}`,
|
|
148
|
+
title: item.fields['System.Title'],
|
|
149
|
+
url: item._links.html.href,
|
|
150
|
+
createdAt: item.fields['System.CreatedDate'],
|
|
151
|
+
age: ageDays,
|
|
152
|
+
labels: tags,
|
|
153
|
+
provider: 'ado',
|
|
154
|
+
project: this.project,
|
|
155
|
+
state: item.fields['System.State'],
|
|
156
|
+
isStale: ageDays >= STALE_THRESHOLD_DAYS,
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
// Filter stale if requested
|
|
160
|
+
const filteredItems = filter?.staleOnly
|
|
161
|
+
? items.filter(i => i.isStale)
|
|
162
|
+
: items;
|
|
163
|
+
return {
|
|
164
|
+
items: filteredItems,
|
|
165
|
+
total,
|
|
166
|
+
page,
|
|
167
|
+
pageSize: limit,
|
|
168
|
+
totalPages,
|
|
169
|
+
hasMore: page < totalPages,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
this.logger.error(`Failed to fetch ADO work items: ${error}`);
|
|
174
|
+
return this.emptyResult(page, limit);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
emptyResult(page, pageSize) {
|
|
178
|
+
return {
|
|
179
|
+
items: [],
|
|
180
|
+
total: 0,
|
|
181
|
+
page,
|
|
182
|
+
pageSize,
|
|
183
|
+
totalPages: 0,
|
|
184
|
+
hasMore: false,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=ado-items-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ado-items-adapter.js","sourceRoot":"","sources":["../../../../../src/core/external-tools/providers/ado-items-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Items Adapter - OPTIMIZED FOR SCALE
|
|
3
|
+
*
|
|
4
|
+
* Three-tier fetching:
|
|
5
|
+
* 1. getOpenCount() - Single API call, returns total (for status)
|
|
6
|
+
* 2. getOpenItems(filter) - Paginated, filtered (for details)
|
|
7
|
+
*/
|
|
8
|
+
import { ExternalItemsProvider, ExternalProvider, ItemsFilter, PaginatedItemsResult } from '../types.js';
|
|
9
|
+
import { Logger } from '../../../utils/logger.js';
|
|
10
|
+
export declare class GitHubItemsAdapter implements ExternalItemsProvider {
|
|
11
|
+
private owner;
|
|
12
|
+
private repo;
|
|
13
|
+
private logger;
|
|
14
|
+
constructor(options: {
|
|
15
|
+
owner: string;
|
|
16
|
+
repo: string;
|
|
17
|
+
logger?: Logger;
|
|
18
|
+
});
|
|
19
|
+
/**
|
|
20
|
+
* Create adapter from auto-detected git remote
|
|
21
|
+
*/
|
|
22
|
+
static fromGitRemote(options?: {
|
|
23
|
+
logger?: Logger;
|
|
24
|
+
}): Promise<GitHubItemsAdapter | null>;
|
|
25
|
+
getProviderName(): ExternalProvider;
|
|
26
|
+
isConfigured(): Promise<boolean>;
|
|
27
|
+
/**
|
|
28
|
+
* TIER 1: Fast count - single API call
|
|
29
|
+
* Uses GitHub search API to get total_count without fetching items
|
|
30
|
+
*/
|
|
31
|
+
getOpenCount(): Promise<number>;
|
|
32
|
+
/**
|
|
33
|
+
* TIER 3: Paginated items - on-demand with filters
|
|
34
|
+
*/
|
|
35
|
+
getOpenItems(filter?: ItemsFilter): Promise<PaginatedItemsResult>;
|
|
36
|
+
private emptyResult;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=github-items-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-items-adapter.d.ts","sourceRoot":"","sources":["../../../../../src/core/external-tools/providers/github-items-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAEL,qBAAqB,EACrB,gBAAgB,EAChB,WAAW,EACX,oBAAoB,EAIrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,MAAM,EAAiB,MAAM,0BAA0B,CAAC;AAgBjE,qBAAa,kBAAmB,YAAW,qBAAqB;IAC9D,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;IAMD;;OAEG;WACU,aAAa,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAqB7F,eAAe,IAAI,gBAAgB;IAI7B,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;IAKtC;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAoBrC;;OAEG;IACG,YAAY,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAmEvE,OAAO,CAAC,WAAW;CAUpB"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Items Adapter - OPTIMIZED FOR SCALE
|
|
3
|
+
*
|
|
4
|
+
* Three-tier fetching:
|
|
5
|
+
* 1. getOpenCount() - Single API call, returns total (for status)
|
|
6
|
+
* 2. getOpenItems(filter) - Paginated, filtered (for details)
|
|
7
|
+
*/
|
|
8
|
+
import { execFileNoThrow } from '../../../utils/execFileNoThrow.js';
|
|
9
|
+
import { STALE_THRESHOLD_DAYS, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE, } from '../types.js';
|
|
10
|
+
import { consoleLogger } from '../../../utils/logger.js';
|
|
11
|
+
export class GitHubItemsAdapter {
|
|
12
|
+
constructor(options) {
|
|
13
|
+
this.owner = options.owner;
|
|
14
|
+
this.repo = options.repo;
|
|
15
|
+
this.logger = options.logger ?? consoleLogger;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Create adapter from auto-detected git remote
|
|
19
|
+
*/
|
|
20
|
+
static async fromGitRemote(options) {
|
|
21
|
+
const result = await execFileNoThrow('git', ['remote', 'get-url', 'origin']);
|
|
22
|
+
if (result.exitCode !== 0) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const remote = result.stdout.trim();
|
|
26
|
+
const match = remote.match(/github\.com[:/](.+)\/(.+?)(?:\.git)?$/);
|
|
27
|
+
if (!match) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return new GitHubItemsAdapter({
|
|
31
|
+
owner: match[1],
|
|
32
|
+
repo: match[2],
|
|
33
|
+
logger: options?.logger,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
getProviderName() {
|
|
37
|
+
return 'github';
|
|
38
|
+
}
|
|
39
|
+
async isConfigured() {
|
|
40
|
+
const result = await execFileNoThrow('gh', ['auth', 'status']);
|
|
41
|
+
return result.exitCode === 0;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* TIER 1: Fast count - single API call
|
|
45
|
+
* Uses GitHub search API to get total_count without fetching items
|
|
46
|
+
*/
|
|
47
|
+
async getOpenCount() {
|
|
48
|
+
// Use search API with per_page=1 to get total_count efficiently
|
|
49
|
+
const query = `repo:${this.owner}/${this.repo} is:issue is:open`;
|
|
50
|
+
const result = await execFileNoThrow('gh', [
|
|
51
|
+
'api',
|
|
52
|
+
'search/issues',
|
|
53
|
+
'-X', 'GET',
|
|
54
|
+
'-f', `q=${query}`,
|
|
55
|
+
'-f', 'per_page=1',
|
|
56
|
+
'--jq', '.total_count',
|
|
57
|
+
]);
|
|
58
|
+
if (result.exitCode !== 0) {
|
|
59
|
+
this.logger.error(`GitHub count failed: ${result.stderr}`);
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
return parseInt(result.stdout.trim(), 10) || 0;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* TIER 3: Paginated items - on-demand with filters
|
|
66
|
+
*/
|
|
67
|
+
async getOpenItems(filter) {
|
|
68
|
+
const limit = Math.min(filter?.limit || DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE);
|
|
69
|
+
const offset = filter?.offset || 0;
|
|
70
|
+
const page = Math.floor(offset / limit) + 1;
|
|
71
|
+
// First get total count
|
|
72
|
+
const total = await this.getOpenCount();
|
|
73
|
+
// Then fetch page of items
|
|
74
|
+
const result = await execFileNoThrow('gh', [
|
|
75
|
+
'issue',
|
|
76
|
+
'list',
|
|
77
|
+
'--repo', `${this.owner}/${this.repo}`,
|
|
78
|
+
'--state', 'open',
|
|
79
|
+
'--limit', String(limit),
|
|
80
|
+
'--json', 'number,title,url,createdAt,labels,state',
|
|
81
|
+
]);
|
|
82
|
+
if (result.exitCode !== 0) {
|
|
83
|
+
this.logger.error(`GitHub items failed: ${result.stderr}`);
|
|
84
|
+
return this.emptyResult(page, limit);
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const issues = JSON.parse(result.stdout);
|
|
88
|
+
const now = Date.now();
|
|
89
|
+
const items = issues.map(issue => {
|
|
90
|
+
const createdDate = new Date(issue.createdAt).getTime();
|
|
91
|
+
const ageMs = now - createdDate;
|
|
92
|
+
const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24));
|
|
93
|
+
return {
|
|
94
|
+
id: `#${issue.number}`,
|
|
95
|
+
title: issue.title,
|
|
96
|
+
url: issue.url,
|
|
97
|
+
createdAt: issue.createdAt,
|
|
98
|
+
age: ageDays,
|
|
99
|
+
labels: issue.labels.map(l => l.name),
|
|
100
|
+
provider: 'github',
|
|
101
|
+
project: `${this.owner}/${this.repo}`,
|
|
102
|
+
state: issue.state,
|
|
103
|
+
isStale: ageDays >= STALE_THRESHOLD_DAYS,
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
// Filter stale if requested
|
|
107
|
+
const filteredItems = filter?.staleOnly
|
|
108
|
+
? items.filter(i => i.isStale)
|
|
109
|
+
: items;
|
|
110
|
+
const totalPages = Math.ceil(total / limit);
|
|
111
|
+
return {
|
|
112
|
+
items: filteredItems,
|
|
113
|
+
total,
|
|
114
|
+
page,
|
|
115
|
+
pageSize: limit,
|
|
116
|
+
totalPages,
|
|
117
|
+
hasMore: page < totalPages,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
this.logger.error(`GitHub parse failed: ${error}`);
|
|
122
|
+
return this.emptyResult(page, limit);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
emptyResult(page, pageSize) {
|
|
126
|
+
return {
|
|
127
|
+
items: [],
|
|
128
|
+
total: 0,
|
|
129
|
+
page,
|
|
130
|
+
pageSize,
|
|
131
|
+
totalPages: 0,
|
|
132
|
+
hasMore: false,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=github-items-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-items-adapter.js","sourceRoot":"","sources":["../../../../../src/core/external-tools/providers/github-items-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External Items Providers - Re-exports
|
|
3
|
+
*/
|
|
4
|
+
export { GitHubItemsAdapter } from './github-items-adapter.js';
|
|
5
|
+
export { JiraItemsAdapter } from './jira-items-adapter.js';
|
|
6
|
+
export { AdoItemsAdapter } from './ado-items-adapter.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/external-tools/providers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External Items Providers - Re-exports
|
|
3
|
+
*/
|
|
4
|
+
export { GitHubItemsAdapter } from './github-items-adapter.js';
|
|
5
|
+
export { JiraItemsAdapter } from './jira-items-adapter.js';
|
|
6
|
+
export { AdoItemsAdapter } from './ado-items-adapter.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/external-tools/providers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JIRA Items Adapter - OPTIMIZED FOR SCALE
|
|
3
|
+
*
|
|
4
|
+
* Three-tier fetching:
|
|
5
|
+
* 1. getOpenCount() - Single API call, returns total (for status)
|
|
6
|
+
* 2. getOpenItems(filter) - Paginated, filtered (for details)
|
|
7
|
+
*
|
|
8
|
+
* Requires JIRA_BASE_URL, JIRA_EMAIL, JIRA_API_TOKEN in environment
|
|
9
|
+
*/
|
|
10
|
+
import { ExternalItemsProvider, ExternalProvider, ItemsFilter, PaginatedItemsResult } from '../types.js';
|
|
11
|
+
import { Logger } from '../../../utils/logger.js';
|
|
12
|
+
export declare class JiraItemsAdapter implements ExternalItemsProvider {
|
|
13
|
+
private baseUrl;
|
|
14
|
+
private email;
|
|
15
|
+
private apiToken;
|
|
16
|
+
private projectKey;
|
|
17
|
+
private logger;
|
|
18
|
+
constructor(options: {
|
|
19
|
+
baseUrl: string;
|
|
20
|
+
email: string;
|
|
21
|
+
apiToken: string;
|
|
22
|
+
projectKey: string;
|
|
23
|
+
logger?: Logger;
|
|
24
|
+
});
|
|
25
|
+
static fromEnv(options?: {
|
|
26
|
+
projectKey?: string;
|
|
27
|
+
logger?: Logger;
|
|
28
|
+
}): JiraItemsAdapter | null;
|
|
29
|
+
getProviderName(): ExternalProvider;
|
|
30
|
+
isConfigured(): Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* TIER 1: Fast count - single API call with maxResults=0
|
|
33
|
+
* JIRA returns total even when maxResults=0, so we get count without fetching items
|
|
34
|
+
*/
|
|
35
|
+
getOpenCount(): Promise<number>;
|
|
36
|
+
/**
|
|
37
|
+
* TIER 3: Paginated items - on-demand with filters
|
|
38
|
+
*/
|
|
39
|
+
getOpenItems(filter?: ItemsFilter): Promise<PaginatedItemsResult>;
|
|
40
|
+
private emptyResult;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=jira-items-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jira-items-adapter.d.ts","sourceRoot":"","sources":["../../../../../src/core/external-tools/providers/jira-items-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAEL,qBAAqB,EACrB,gBAAgB,EAChB,WAAW,EACX,oBAAoB,EAIrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,MAAM,EAAiB,MAAM,0BAA0B,CAAC;AAEjE,qBAAa,gBAAiB,YAAW,qBAAqB;IAC5D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;IAQD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,gBAAgB,GAAG,IAAI;IAmB3F,eAAe,IAAI,gBAAgB;IAI7B,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;IAItC;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAmCrC;;OAEG;IACG,YAAY,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAqFvE,OAAO,CAAC,WAAW;CAUpB"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JIRA Items Adapter - OPTIMIZED FOR SCALE
|
|
3
|
+
*
|
|
4
|
+
* Three-tier fetching:
|
|
5
|
+
* 1. getOpenCount() - Single API call, returns total (for status)
|
|
6
|
+
* 2. getOpenItems(filter) - Paginated, filtered (for details)
|
|
7
|
+
*
|
|
8
|
+
* Requires JIRA_BASE_URL, JIRA_EMAIL, JIRA_API_TOKEN in environment
|
|
9
|
+
*/
|
|
10
|
+
import { STALE_THRESHOLD_DAYS, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE, } from '../types.js';
|
|
11
|
+
import { consoleLogger } from '../../../utils/logger.js';
|
|
12
|
+
export class JiraItemsAdapter {
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
15
|
+
this.email = options.email;
|
|
16
|
+
this.apiToken = options.apiToken;
|
|
17
|
+
this.projectKey = options.projectKey;
|
|
18
|
+
this.logger = options.logger ?? consoleLogger;
|
|
19
|
+
}
|
|
20
|
+
static fromEnv(options) {
|
|
21
|
+
const baseUrl = process.env.JIRA_BASE_URL;
|
|
22
|
+
const email = process.env.JIRA_EMAIL;
|
|
23
|
+
const apiToken = process.env.JIRA_API_TOKEN;
|
|
24
|
+
const projectKey = options?.projectKey || process.env.JIRA_PROJECT_KEY;
|
|
25
|
+
if (!baseUrl || !email || !apiToken) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return new JiraItemsAdapter({
|
|
29
|
+
baseUrl,
|
|
30
|
+
email,
|
|
31
|
+
apiToken,
|
|
32
|
+
projectKey: projectKey || '',
|
|
33
|
+
logger: options?.logger,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
getProviderName() {
|
|
37
|
+
return 'jira';
|
|
38
|
+
}
|
|
39
|
+
async isConfigured() {
|
|
40
|
+
return !!(this.baseUrl && this.email && this.apiToken);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* TIER 1: Fast count - single API call with maxResults=0
|
|
44
|
+
* JIRA returns total even when maxResults=0, so we get count without fetching items
|
|
45
|
+
*/
|
|
46
|
+
async getOpenCount() {
|
|
47
|
+
if (!await this.isConfigured()) {
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const jql = this.projectKey
|
|
52
|
+
? `project = "${this.projectKey}" AND status NOT IN (Done, Closed)`
|
|
53
|
+
: 'status NOT IN (Done, Closed)';
|
|
54
|
+
const encodedJql = encodeURIComponent(jql);
|
|
55
|
+
// maxResults=0 returns just the total count without fetching items
|
|
56
|
+
const url = `${this.baseUrl}/rest/api/3/search?jql=${encodedJql}&maxResults=0`;
|
|
57
|
+
const authString = Buffer.from(`${this.email}:${this.apiToken}`).toString('base64');
|
|
58
|
+
const response = await fetch(url, {
|
|
59
|
+
headers: {
|
|
60
|
+
'Authorization': `Basic ${authString}`,
|
|
61
|
+
'Accept': 'application/json',
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
if (!response.ok) {
|
|
65
|
+
this.logger.error(`JIRA count error: ${response.status} ${response.statusText}`);
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
const data = await response.json();
|
|
69
|
+
return data.total || 0;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
this.logger.error(`JIRA count failed: ${error}`);
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* TIER 3: Paginated items - on-demand with filters
|
|
78
|
+
*/
|
|
79
|
+
async getOpenItems(filter) {
|
|
80
|
+
if (!await this.isConfigured()) {
|
|
81
|
+
return this.emptyResult(1, DEFAULT_PAGE_SIZE);
|
|
82
|
+
}
|
|
83
|
+
const limit = Math.min(filter?.limit || DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE);
|
|
84
|
+
const offset = filter?.offset || 0;
|
|
85
|
+
const page = Math.floor(offset / limit) + 1;
|
|
86
|
+
try {
|
|
87
|
+
const jql = this.projectKey
|
|
88
|
+
? `project = "${this.projectKey}" AND status NOT IN (Done, Closed) ORDER BY created DESC`
|
|
89
|
+
: 'status NOT IN (Done, Closed) ORDER BY created DESC';
|
|
90
|
+
const encodedJql = encodeURIComponent(jql);
|
|
91
|
+
const url = `${this.baseUrl}/rest/api/3/search?jql=${encodedJql}&startAt=${offset}&maxResults=${limit}&fields=key,summary,created,labels,status`;
|
|
92
|
+
const authString = Buffer.from(`${this.email}:${this.apiToken}`).toString('base64');
|
|
93
|
+
const response = await fetch(url, {
|
|
94
|
+
headers: {
|
|
95
|
+
'Authorization': `Basic ${authString}`,
|
|
96
|
+
'Accept': 'application/json',
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
this.logger.error(`JIRA API error: ${response.status} ${response.statusText}`);
|
|
101
|
+
return this.emptyResult(page, limit);
|
|
102
|
+
}
|
|
103
|
+
const data = await response.json();
|
|
104
|
+
const now = Date.now();
|
|
105
|
+
const total = data.total;
|
|
106
|
+
const totalPages = Math.ceil(total / limit);
|
|
107
|
+
const items = data.issues.map(issue => {
|
|
108
|
+
const createdDate = new Date(issue.fields.created).getTime();
|
|
109
|
+
const ageMs = now - createdDate;
|
|
110
|
+
const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24));
|
|
111
|
+
return {
|
|
112
|
+
id: issue.key,
|
|
113
|
+
title: issue.fields.summary,
|
|
114
|
+
url: `${this.baseUrl}/browse/${issue.key}`,
|
|
115
|
+
createdAt: issue.fields.created,
|
|
116
|
+
age: ageDays,
|
|
117
|
+
labels: issue.fields.labels || [],
|
|
118
|
+
provider: 'jira',
|
|
119
|
+
project: this.projectKey || 'default',
|
|
120
|
+
state: issue.fields.status.name,
|
|
121
|
+
isStale: ageDays >= STALE_THRESHOLD_DAYS,
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
// Filter stale if requested
|
|
125
|
+
const filteredItems = filter?.staleOnly
|
|
126
|
+
? items.filter(i => i.isStale)
|
|
127
|
+
: items;
|
|
128
|
+
return {
|
|
129
|
+
items: filteredItems,
|
|
130
|
+
total,
|
|
131
|
+
page,
|
|
132
|
+
pageSize: limit,
|
|
133
|
+
totalPages,
|
|
134
|
+
hasMore: page < totalPages,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
this.logger.error(`Failed to fetch JIRA issues: ${error}`);
|
|
139
|
+
return this.emptyResult(page, limit);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
emptyResult(page, pageSize) {
|
|
143
|
+
return {
|
|
144
|
+
items: [],
|
|
145
|
+
total: 0,
|
|
146
|
+
page,
|
|
147
|
+
pageSize,
|
|
148
|
+
totalPages: 0,
|
|
149
|
+
hasMore: false,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=jira-items-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jira-items-adapter.js","sourceRoot":"","sources":["../../../../../src/core/external-tools/providers/jira-items-adapter.ts"],"names":[],"mappings":"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"}
|