@bradygaster/squad-sdk 0.8.22 → 0.8.24
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/dist/config/init.d.ts +3 -3
- package/dist/config/init.d.ts.map +1 -1
- package/dist/config/init.js +72 -16
- package/dist/config/init.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/platform/azure-devops.d.ts +68 -0
- package/dist/platform/azure-devops.d.ts.map +1 -0
- package/dist/platform/azure-devops.js +271 -0
- package/dist/platform/azure-devops.js.map +1 -0
- package/dist/platform/comms-ado-discussions.d.ts +31 -0
- package/dist/platform/comms-ado-discussions.d.ts.map +1 -0
- package/dist/platform/comms-ado-discussions.js +82 -0
- package/dist/platform/comms-ado-discussions.js.map +1 -0
- package/dist/platform/comms-file-log.d.ts +31 -0
- package/dist/platform/comms-file-log.d.ts.map +1 -0
- package/dist/platform/comms-file-log.js +71 -0
- package/dist/platform/comms-file-log.js.map +1 -0
- package/dist/platform/comms-github-discussions.d.ts +30 -0
- package/dist/platform/comms-github-discussions.d.ts.map +1 -0
- package/dist/platform/comms-github-discussions.js +68 -0
- package/dist/platform/comms-github-discussions.js.map +1 -0
- package/dist/platform/comms.d.ts +19 -0
- package/dist/platform/comms.d.ts.map +1 -0
- package/dist/platform/comms.js +109 -0
- package/dist/platform/comms.js.map +1 -0
- package/dist/platform/detect.d.ts +56 -0
- package/dist/platform/detect.d.ts.map +1 -0
- package/dist/platform/detect.js +109 -0
- package/dist/platform/detect.js.map +1 -0
- package/dist/platform/github.d.ts +43 -0
- package/dist/platform/github.d.ts.map +1 -0
- package/dist/platform/github.js +192 -0
- package/dist/platform/github.js.map +1 -0
- package/dist/platform/index.d.ts +25 -0
- package/dist/platform/index.d.ts.map +1 -0
- package/dist/platform/index.js +61 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/planner.d.ts +57 -0
- package/dist/platform/planner.d.ts.map +1 -0
- package/dist/platform/planner.js +185 -0
- package/dist/platform/planner.js.map +1 -0
- package/dist/platform/ralph-commands.d.ts +25 -0
- package/dist/platform/ralph-commands.d.ts.map +1 -0
- package/dist/platform/ralph-commands.js +60 -0
- package/dist/platform/ralph-commands.js.map +1 -0
- package/dist/platform/types.d.ts +125 -0
- package/dist/platform/types.d.ts.map +1 -0
- package/dist/platform/types.js +8 -0
- package/dist/platform/types.js.map +1 -0
- package/dist/streams/filter.d.ts +18 -14
- package/dist/streams/filter.d.ts.map +1 -1
- package/dist/streams/filter.js +13 -11
- package/dist/streams/filter.js.map +1 -1
- package/dist/streams/index.d.ts +1 -1
- package/dist/streams/index.js +1 -1
- package/dist/streams/resolver.d.ts +27 -21
- package/dist/streams/resolver.d.ts.map +1 -1
- package/dist/streams/resolver.js +41 -35
- package/dist/streams/resolver.js.map +1 -1
- package/dist/streams/types.d.ts +29 -23
- package/dist/streams/types.d.ts.map +1 -1
- package/dist/streams/types.js +2 -2
- package/dist/types.d.ts +13 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Azure DevOps platform adapter — wraps az CLI for work item/PR/branch operations.
|
|
3
|
+
*
|
|
4
|
+
* @module platform/azure-devops
|
|
5
|
+
*/
|
|
6
|
+
import { execFileSync, execSync } from 'node:child_process';
|
|
7
|
+
const EXEC_OPTS = { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] };
|
|
8
|
+
/** Check whether the az CLI with devops extension is available */
|
|
9
|
+
function assertAzCliAvailable() {
|
|
10
|
+
try {
|
|
11
|
+
execSync('az devops -h', EXEC_OPTS);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
throw new Error('Azure DevOps CLI not found. Install it with:\n' +
|
|
15
|
+
' 1. Install Azure CLI: https://aka.ms/install-az-cli\n' +
|
|
16
|
+
' 2. Add DevOps extension: az extension add --name azure-devops\n' +
|
|
17
|
+
' 3. Login: az login\n' +
|
|
18
|
+
' 4. Set defaults: az devops configure --defaults organization=https://dev.azure.com/YOUR_ORG project=YOUR_PROJECT');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Escape a value for safe interpolation into a WIQL string (double single-quotes). */
|
|
22
|
+
function escapeWiql(value) {
|
|
23
|
+
return value.replace(/'/g, "''");
|
|
24
|
+
}
|
|
25
|
+
/** Safely parse JSON output, including raw text in error messages */
|
|
26
|
+
function parseJson(raw) {
|
|
27
|
+
try {
|
|
28
|
+
return JSON.parse(raw);
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
throw new Error(`Failed to parse JSON from CLI output: ${err.message}\nRaw output: ${raw}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export class AzureDevOpsAdapter {
|
|
35
|
+
org;
|
|
36
|
+
project;
|
|
37
|
+
repo;
|
|
38
|
+
workItemConfig;
|
|
39
|
+
type = 'azure-devops';
|
|
40
|
+
constructor(org, project, repo, workItemConfig) {
|
|
41
|
+
this.org = org;
|
|
42
|
+
this.project = project;
|
|
43
|
+
this.repo = repo;
|
|
44
|
+
this.workItemConfig = workItemConfig;
|
|
45
|
+
assertAzCliAvailable();
|
|
46
|
+
}
|
|
47
|
+
get orgUrl() {
|
|
48
|
+
return `https://dev.azure.com/${this.org}`;
|
|
49
|
+
}
|
|
50
|
+
/** Org URL for work item operations (may differ from repo org). */
|
|
51
|
+
get wiOrgUrl() {
|
|
52
|
+
const wiOrg = this.workItemConfig?.org ?? this.org;
|
|
53
|
+
return `https://dev.azure.com/${wiOrg}`;
|
|
54
|
+
}
|
|
55
|
+
/** Project for work item operations (may differ from repo project). */
|
|
56
|
+
get wiProject() {
|
|
57
|
+
return this.workItemConfig?.project ?? this.project;
|
|
58
|
+
}
|
|
59
|
+
/** Common az CLI default args for repo operations */
|
|
60
|
+
get defaultArgs() {
|
|
61
|
+
return ['--org', this.orgUrl, '--project', this.project];
|
|
62
|
+
}
|
|
63
|
+
/** Common az CLI default args for work item operations */
|
|
64
|
+
get workItemArgs() {
|
|
65
|
+
return ['--org', this.wiOrgUrl, '--project', this.wiProject];
|
|
66
|
+
}
|
|
67
|
+
az(args) {
|
|
68
|
+
return execFileSync('az', args, EXEC_OPTS).trim();
|
|
69
|
+
}
|
|
70
|
+
async listWorkItems(options) {
|
|
71
|
+
const conditions = [];
|
|
72
|
+
if (options.state) {
|
|
73
|
+
conditions.push(`[System.State] = '${escapeWiql(options.state)}'`);
|
|
74
|
+
}
|
|
75
|
+
if (options.tags?.length) {
|
|
76
|
+
for (const tag of options.tags) {
|
|
77
|
+
conditions.push(`[System.Tags] Contains '${escapeWiql(tag)}'`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
conditions.push(`[System.TeamProject] = '${escapeWiql(this.wiProject)}'`);
|
|
81
|
+
const where = conditions.join(' AND ');
|
|
82
|
+
const top = options.limit ?? 50;
|
|
83
|
+
const wiql = `SELECT [System.Id] FROM WorkItems WHERE ${where} ORDER BY [System.CreatedDate] DESC`;
|
|
84
|
+
const output = this.az([
|
|
85
|
+
'boards', 'query', '--wiql', wiql, ...this.workItemArgs, '--output', 'json',
|
|
86
|
+
]);
|
|
87
|
+
const items = parseJson(output);
|
|
88
|
+
// Fetch full details for each work item (limited by top)
|
|
89
|
+
const results = [];
|
|
90
|
+
for (const item of items.slice(0, top)) {
|
|
91
|
+
const wi = await this.getWorkItem(item.id);
|
|
92
|
+
results.push(wi);
|
|
93
|
+
}
|
|
94
|
+
return results;
|
|
95
|
+
}
|
|
96
|
+
async getWorkItem(id) {
|
|
97
|
+
const output = this.az([
|
|
98
|
+
'boards', 'work-item', 'show', '--id', String(id), ...this.workItemArgs, '--output', 'json',
|
|
99
|
+
]);
|
|
100
|
+
const wi = parseJson(output);
|
|
101
|
+
const fields = wi.fields;
|
|
102
|
+
const tags = typeof fields['System.Tags'] === 'string'
|
|
103
|
+
? fields['System.Tags'].split(';').map((t) => t.trim()).filter(Boolean)
|
|
104
|
+
: [];
|
|
105
|
+
const assignedTo = fields['System.AssignedTo'];
|
|
106
|
+
return {
|
|
107
|
+
id: wi.id,
|
|
108
|
+
title: fields['System.Title'] ?? '',
|
|
109
|
+
state: fields['System.State'] ?? '',
|
|
110
|
+
tags,
|
|
111
|
+
assignedTo: assignedTo?.displayName ?? assignedTo?.uniqueName,
|
|
112
|
+
url: wi._links?.html?.href ?? wi.url,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
async createWorkItem(options) {
|
|
116
|
+
const wiType = options.type ?? this.workItemConfig?.defaultWorkItemType ?? 'User Story';
|
|
117
|
+
const fields = [
|
|
118
|
+
`System.Title=${options.title}`,
|
|
119
|
+
];
|
|
120
|
+
if (options.description) {
|
|
121
|
+
fields.push(`System.Description=${options.description}`);
|
|
122
|
+
}
|
|
123
|
+
if (options.tags?.length) {
|
|
124
|
+
fields.push(`System.Tags=${options.tags.join('; ')}`);
|
|
125
|
+
}
|
|
126
|
+
if (options.assignedTo) {
|
|
127
|
+
fields.push(`System.AssignedTo=${options.assignedTo}`);
|
|
128
|
+
}
|
|
129
|
+
// Area path: explicit > config > omit (uses project default)
|
|
130
|
+
const areaPath = options.areaPath ?? this.workItemConfig?.areaPath;
|
|
131
|
+
if (areaPath) {
|
|
132
|
+
fields.push(`System.AreaPath=${areaPath}`);
|
|
133
|
+
}
|
|
134
|
+
// Iteration path: explicit > config > omit (uses project default)
|
|
135
|
+
const iterationPath = options.iterationPath ?? this.workItemConfig?.iterationPath;
|
|
136
|
+
if (iterationPath) {
|
|
137
|
+
fields.push(`System.IterationPath=${iterationPath}`);
|
|
138
|
+
}
|
|
139
|
+
const output = this.az([
|
|
140
|
+
'boards', 'work-item', 'create', '--type', wiType, '--fields', ...fields, ...this.workItemArgs, '--output', 'json',
|
|
141
|
+
]);
|
|
142
|
+
const created = parseJson(output);
|
|
143
|
+
const createdFields = created.fields;
|
|
144
|
+
const tags = typeof createdFields['System.Tags'] === 'string'
|
|
145
|
+
? createdFields['System.Tags'].split(';').map((t) => t.trim()).filter(Boolean)
|
|
146
|
+
: [];
|
|
147
|
+
return {
|
|
148
|
+
id: created.id,
|
|
149
|
+
title: createdFields['System.Title'] ?? '',
|
|
150
|
+
state: createdFields['System.State'] ?? '',
|
|
151
|
+
tags,
|
|
152
|
+
url: created._links?.html?.href ?? created.url,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
async addTag(workItemId, tag) {
|
|
156
|
+
// Get current tags, append the new one
|
|
157
|
+
const wi = await this.getWorkItem(workItemId);
|
|
158
|
+
const currentTags = wi.tags.filter((t) => t !== tag);
|
|
159
|
+
currentTags.push(tag);
|
|
160
|
+
const tagsStr = currentTags.join('; ');
|
|
161
|
+
this.az([
|
|
162
|
+
'boards', 'work-item', 'update', '--id', String(workItemId),
|
|
163
|
+
'--fields', `System.Tags=${tagsStr}`, ...this.workItemArgs, '--output', 'json',
|
|
164
|
+
]);
|
|
165
|
+
}
|
|
166
|
+
async removeTag(workItemId, tag) {
|
|
167
|
+
const wi = await this.getWorkItem(workItemId);
|
|
168
|
+
const updatedTags = wi.tags.filter((t) => t !== tag);
|
|
169
|
+
const tagsStr = updatedTags.join('; ');
|
|
170
|
+
this.az([
|
|
171
|
+
'boards', 'work-item', 'update', '--id', String(workItemId),
|
|
172
|
+
'--fields', `System.Tags=${tagsStr}`, ...this.workItemArgs, '--output', 'json',
|
|
173
|
+
]);
|
|
174
|
+
}
|
|
175
|
+
async addComment(workItemId, comment) {
|
|
176
|
+
this.az([
|
|
177
|
+
'boards', 'work-item', 'update', '--id', String(workItemId),
|
|
178
|
+
'--discussion', comment, ...this.workItemArgs, '--output', 'json',
|
|
179
|
+
]);
|
|
180
|
+
}
|
|
181
|
+
async listPullRequests(options) {
|
|
182
|
+
const args = [
|
|
183
|
+
'repos', 'pr', 'list',
|
|
184
|
+
'--repository', this.repo,
|
|
185
|
+
...this.defaultArgs,
|
|
186
|
+
'--output', 'json',
|
|
187
|
+
];
|
|
188
|
+
if (options.status)
|
|
189
|
+
args.push('--status', options.status);
|
|
190
|
+
if (options.limit)
|
|
191
|
+
args.push('--top', String(options.limit));
|
|
192
|
+
const output = this.az(args);
|
|
193
|
+
const prs = parseJson(output);
|
|
194
|
+
return prs.map((pr) => ({
|
|
195
|
+
id: pr.pullRequestId,
|
|
196
|
+
title: pr.title,
|
|
197
|
+
sourceBranch: stripRefsHeads(pr.sourceRefName),
|
|
198
|
+
targetBranch: stripRefsHeads(pr.targetRefName),
|
|
199
|
+
status: mapAdoPrStatus(pr.status, pr.isDraft),
|
|
200
|
+
reviewStatus: mapAdoReviewStatus(pr.reviewers),
|
|
201
|
+
author: pr.createdBy.displayName ?? pr.createdBy.uniqueName,
|
|
202
|
+
url: pr.repository?.webUrl
|
|
203
|
+
? `${pr.repository.webUrl}/pullrequest/${pr.pullRequestId}`
|
|
204
|
+
: pr.url,
|
|
205
|
+
}));
|
|
206
|
+
}
|
|
207
|
+
async createPullRequest(options) {
|
|
208
|
+
const args = [
|
|
209
|
+
'repos', 'pr', 'create',
|
|
210
|
+
'--repository', this.repo,
|
|
211
|
+
'--source-branch', options.sourceBranch,
|
|
212
|
+
'--target-branch', options.targetBranch,
|
|
213
|
+
'--title', options.title,
|
|
214
|
+
...this.defaultArgs,
|
|
215
|
+
'--output', 'json',
|
|
216
|
+
];
|
|
217
|
+
if (options.description) {
|
|
218
|
+
args.push('--description', options.description);
|
|
219
|
+
}
|
|
220
|
+
const output = this.az(args);
|
|
221
|
+
const pr = parseJson(output);
|
|
222
|
+
return {
|
|
223
|
+
id: pr.pullRequestId,
|
|
224
|
+
title: pr.title,
|
|
225
|
+
sourceBranch: stripRefsHeads(pr.sourceRefName),
|
|
226
|
+
targetBranch: stripRefsHeads(pr.targetRefName),
|
|
227
|
+
status: mapAdoPrStatus(pr.status, pr.isDraft),
|
|
228
|
+
reviewStatus: mapAdoReviewStatus(pr.reviewers),
|
|
229
|
+
author: pr.createdBy.displayName ?? pr.createdBy.uniqueName,
|
|
230
|
+
url: pr.url,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
async mergePullRequest(id) {
|
|
234
|
+
this.az([
|
|
235
|
+
'repos', 'pr', 'update', '--id', String(id),
|
|
236
|
+
'--status', 'completed', ...this.defaultArgs, '--output', 'json',
|
|
237
|
+
]);
|
|
238
|
+
}
|
|
239
|
+
async createBranch(name, fromBranch) {
|
|
240
|
+
const base = fromBranch ?? 'main';
|
|
241
|
+
execFileSync('git', ['checkout', base], EXEC_OPTS);
|
|
242
|
+
execFileSync('git', ['pull'], EXEC_OPTS);
|
|
243
|
+
execFileSync('git', ['checkout', '-b', name], EXEC_OPTS);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function stripRefsHeads(ref) {
|
|
247
|
+
return ref.replace(/^refs\/heads\//, '');
|
|
248
|
+
}
|
|
249
|
+
function mapAdoPrStatus(status, isDraft) {
|
|
250
|
+
if (isDraft)
|
|
251
|
+
return 'draft';
|
|
252
|
+
switch (status.toLowerCase()) {
|
|
253
|
+
case 'active': return 'active';
|
|
254
|
+
case 'completed': return 'completed';
|
|
255
|
+
case 'abandoned': return 'abandoned';
|
|
256
|
+
default: return 'active';
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function mapAdoReviewStatus(reviewers) {
|
|
260
|
+
if (!reviewers?.length)
|
|
261
|
+
return 'pending';
|
|
262
|
+
// ADO vote: 10 = approved, -10 = rejected, 5 = approved with suggestions, -5 = waiting, 0 = no vote
|
|
263
|
+
const hasReject = reviewers.some((r) => r.vote <= -5);
|
|
264
|
+
if (hasReject)
|
|
265
|
+
return 'changes-requested';
|
|
266
|
+
const hasApproval = reviewers.some((r) => r.vote >= 5);
|
|
267
|
+
if (hasApproval)
|
|
268
|
+
return 'approved';
|
|
269
|
+
return 'pending';
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=azure-devops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azure-devops.js","sourceRoot":"","sources":["../../src/platform/azure-devops.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Azure DevOps Work Item Discussion communication adapter.
|
|
3
|
+
*
|
|
4
|
+
* Posts updates as work item comments and reads replies via `az boards`.
|
|
5
|
+
* Phone-capable via ADO mobile app.
|
|
6
|
+
*
|
|
7
|
+
* @module platform/comms-ado-discussions
|
|
8
|
+
*/
|
|
9
|
+
import type { CommunicationAdapter, CommunicationChannel, CommunicationReply } from './types.js';
|
|
10
|
+
export declare class ADODiscussionCommunicationAdapter implements CommunicationAdapter {
|
|
11
|
+
private readonly org;
|
|
12
|
+
private readonly project;
|
|
13
|
+
readonly channel: CommunicationChannel;
|
|
14
|
+
constructor(org: string, project: string);
|
|
15
|
+
private get orgUrl();
|
|
16
|
+
postUpdate(options: {
|
|
17
|
+
title: string;
|
|
18
|
+
body: string;
|
|
19
|
+
category?: string;
|
|
20
|
+
author?: string;
|
|
21
|
+
}): Promise<{
|
|
22
|
+
id: string;
|
|
23
|
+
url?: string;
|
|
24
|
+
}>;
|
|
25
|
+
pollForReplies(options: {
|
|
26
|
+
threadId: string;
|
|
27
|
+
since: Date;
|
|
28
|
+
}): Promise<CommunicationReply[]>;
|
|
29
|
+
getNotificationUrl(threadId: string): string | undefined;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=comms-ado-discussions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comms-ado-discussions.d.ts","sourceRoot":"","sources":["../../src/platform/comms-ado-discussions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAajG,qBAAa,iCAAkC,YAAW,oBAAoB;IAI1E,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAoB;gBAGvC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM;IAGlC,OAAO,KAAK,MAAM,GAEjB;IAEK,UAAU,CAAC,OAAO,EAAE;QACxB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA8BnC,cAAc,CAAC,OAAO,EAAE;QAC5B,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,IAAI,CAAC;KACb,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAqCjC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAGzD"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Azure DevOps Work Item Discussion communication adapter.
|
|
3
|
+
*
|
|
4
|
+
* Posts updates as work item comments and reads replies via `az boards`.
|
|
5
|
+
* Phone-capable via ADO mobile app.
|
|
6
|
+
*
|
|
7
|
+
* @module platform/comms-ado-discussions
|
|
8
|
+
*/
|
|
9
|
+
import { execFileSync } from 'node:child_process';
|
|
10
|
+
const EXEC_OPTS = { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] };
|
|
11
|
+
/** Safely parse JSON output */
|
|
12
|
+
function parseJson(raw) {
|
|
13
|
+
try {
|
|
14
|
+
return JSON.parse(raw);
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
throw new Error(`Failed to parse JSON: ${err.message}\nRaw: ${raw}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class ADODiscussionCommunicationAdapter {
|
|
21
|
+
org;
|
|
22
|
+
project;
|
|
23
|
+
channel = 'ado-work-items';
|
|
24
|
+
constructor(org, project) {
|
|
25
|
+
this.org = org;
|
|
26
|
+
this.project = project;
|
|
27
|
+
}
|
|
28
|
+
get orgUrl() {
|
|
29
|
+
return `https://dev.azure.com/${this.org}`;
|
|
30
|
+
}
|
|
31
|
+
async postUpdate(options) {
|
|
32
|
+
const prefix = options.author ? `**${options.author}:** ` : '';
|
|
33
|
+
const categoryTag = options.category ? ` [${options.category}]` : '';
|
|
34
|
+
const fullTitle = `[Squad${categoryTag}] ${options.title}`;
|
|
35
|
+
const comment = `${prefix}${options.body}`;
|
|
36
|
+
// Create a work item to serve as the discussion thread
|
|
37
|
+
const output = execFileSync('az', [
|
|
38
|
+
'boards', 'work-item', 'create',
|
|
39
|
+
'--type', 'Task',
|
|
40
|
+
'--title', fullTitle,
|
|
41
|
+
'--fields', `System.Tags=squad; squad:comms`,
|
|
42
|
+
'--discussion', comment,
|
|
43
|
+
'--org', this.orgUrl,
|
|
44
|
+
'--project', this.project,
|
|
45
|
+
'--output', 'json',
|
|
46
|
+
], EXEC_OPTS);
|
|
47
|
+
const wi = parseJson(output);
|
|
48
|
+
return {
|
|
49
|
+
id: String(wi.id),
|
|
50
|
+
url: wi._links?.html?.href ?? wi.url,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
async pollForReplies(options) {
|
|
54
|
+
// Read work item comments (discussion history)
|
|
55
|
+
const output = execFileSync('az', [
|
|
56
|
+
'boards', 'work-item', 'show',
|
|
57
|
+
'--id', options.threadId,
|
|
58
|
+
'--org', this.orgUrl,
|
|
59
|
+
'--project', this.project,
|
|
60
|
+
'--expand', 'all',
|
|
61
|
+
'--output', 'json',
|
|
62
|
+
], EXEC_OPTS);
|
|
63
|
+
const wi = parseJson(output);
|
|
64
|
+
// ADO work item show doesn't include comments directly in basic output.
|
|
65
|
+
// The discussion is in the System.History field as HTML.
|
|
66
|
+
// For a production adapter, use the REST API for comments.
|
|
67
|
+
// This is a simplified implementation.
|
|
68
|
+
const history = wi.fields['System.History'];
|
|
69
|
+
if (!history)
|
|
70
|
+
return [];
|
|
71
|
+
return [{
|
|
72
|
+
author: 'ado-user',
|
|
73
|
+
body: history,
|
|
74
|
+
timestamp: new Date(),
|
|
75
|
+
id: `${options.threadId}-history`,
|
|
76
|
+
}];
|
|
77
|
+
}
|
|
78
|
+
getNotificationUrl(threadId) {
|
|
79
|
+
return `${this.orgUrl}/${this.project}/_workitems/edit/${threadId}`;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=comms-ado-discussions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comms-ado-discussions.js","sourceRoot":"","sources":["../../src/platform/comms-ado-discussions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,MAAM,SAAS,GAA2D,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;AAEjI,+BAA+B;AAC/B,SAAS,SAAS,CAAI,GAAW;IAC/B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAM,CAAC;IAC9B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,yBAA0B,GAAa,CAAC,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC;IAClF,CAAC;AACH,CAAC;AAED,MAAM,OAAO,iCAAiC;IAIzB;IACA;IAJV,OAAO,GAAyB,gBAAgB,CAAC;IAE1D,YACmB,GAAW,EACX,OAAe;QADf,QAAG,GAAH,GAAG,CAAQ;QACX,YAAO,GAAP,OAAO,CAAQ;IAC/B,CAAC;IAEJ,IAAY,MAAM;QAChB,OAAO,yBAAyB,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAKhB;QACC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,MAAM,SAAS,GAAG,SAAS,WAAW,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;QAC3D,MAAM,OAAO,GAAG,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAE3C,uDAAuD;QACvD,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE;YAChC,QAAQ,EAAE,WAAW,EAAE,QAAQ;YAC/B,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,SAAS;YACpB,UAAU,EAAE,gCAAgC;YAC5C,cAAc,EAAE,OAAO;YACvB,OAAO,EAAE,IAAI,CAAC,MAAM;YACpB,WAAW,EAAE,IAAI,CAAC,OAAO;YACzB,UAAU,EAAE,MAAM;SACnB,EAAE,SAAS,CAAC,CAAC;QAEd,MAAM,EAAE,GAAG,SAAS,CAIjB,MAAM,CAAC,CAAC;QAEX,OAAO;YACL,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;YACjB,GAAG,EAAE,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,GAAG;SACrC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAGpB;QACC,+CAA+C;QAC/C,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE;YAChC,QAAQ,EAAE,WAAW,EAAE,MAAM;YAC7B,MAAM,EAAE,OAAO,CAAC,QAAQ;YACxB,OAAO,EAAE,IAAI,CAAC,MAAM;YACpB,WAAW,EAAE,IAAI,CAAC,OAAO;YACzB,UAAU,EAAE,KAAK;YACjB,UAAU,EAAE,MAAM;SACnB,EAAE,SAAS,CAAC,CAAC;QAEd,MAAM,EAAE,GAAG,SAAS,CASjB,MAAM,CAAC,CAAC;QAEX,wEAAwE;QACxE,yDAAyD;QACzD,2DAA2D;QAC3D,uCAAuC;QACvC,MAAM,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAuB,CAAC;QAClE,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;QAExB,OAAO,CAAC;gBACN,MAAM,EAAE,UAAU;gBAClB,IAAI,EAAE,OAAO;gBACb,SAAS,EAAE,IAAI,IAAI,EAAE;gBACrB,EAAE,EAAE,GAAG,OAAO,CAAC,QAAQ,UAAU;aAClC,CAAC,CAAC;IACL,CAAC;IAED,kBAAkB,CAAC,QAAgB;QACjC,OAAO,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,oBAAoB,QAAQ,EAAE,CAAC;IACtE,CAAC;CACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-based communication adapter — zero-config fallback.
|
|
3
|
+
*
|
|
4
|
+
* Writes updates to `.squad/comms/` as markdown files.
|
|
5
|
+
* Always available, no external dependencies. Works on every platform.
|
|
6
|
+
* Replies are read from the same directory (humans edit files manually or via git).
|
|
7
|
+
*
|
|
8
|
+
* @module platform/comms-file-log
|
|
9
|
+
*/
|
|
10
|
+
import type { CommunicationAdapter, CommunicationChannel, CommunicationReply } from './types.js';
|
|
11
|
+
export declare class FileLogCommunicationAdapter implements CommunicationAdapter {
|
|
12
|
+
private readonly squadRoot;
|
|
13
|
+
readonly channel: CommunicationChannel;
|
|
14
|
+
private readonly commsDir;
|
|
15
|
+
constructor(squadRoot: string);
|
|
16
|
+
postUpdate(options: {
|
|
17
|
+
title: string;
|
|
18
|
+
body: string;
|
|
19
|
+
category?: string;
|
|
20
|
+
author?: string;
|
|
21
|
+
}): Promise<{
|
|
22
|
+
id: string;
|
|
23
|
+
url?: string;
|
|
24
|
+
}>;
|
|
25
|
+
pollForReplies(options: {
|
|
26
|
+
threadId: string;
|
|
27
|
+
since: Date;
|
|
28
|
+
}): Promise<CommunicationReply[]>;
|
|
29
|
+
getNotificationUrl(_threadId: string): string | undefined;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=comms-file-log.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comms-file-log.d.ts","sourceRoot":"","sources":["../../src/platform/comms-file-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEjG,qBAAa,2BAA4B,YAAW,oBAAoB;IAI1D,OAAO,CAAC,QAAQ,CAAC,SAAS;IAHtC,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAc;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEL,SAAS,EAAE,MAAM;IAOxC,UAAU,CAAC,OAAO,EAAE;QACxB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA4BnC,cAAc,CAAC,OAAO,EAAE;QAC5B,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,IAAI,CAAC;KACb,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAqBjC,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAG1D"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-based communication adapter — zero-config fallback.
|
|
3
|
+
*
|
|
4
|
+
* Writes updates to `.squad/comms/` as markdown files.
|
|
5
|
+
* Always available, no external dependencies. Works on every platform.
|
|
6
|
+
* Replies are read from the same directory (humans edit files manually or via git).
|
|
7
|
+
*
|
|
8
|
+
* @module platform/comms-file-log
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
export class FileLogCommunicationAdapter {
|
|
13
|
+
squadRoot;
|
|
14
|
+
channel = 'file-log';
|
|
15
|
+
commsDir;
|
|
16
|
+
constructor(squadRoot) {
|
|
17
|
+
this.squadRoot = squadRoot;
|
|
18
|
+
this.commsDir = join(squadRoot, '.squad', 'comms');
|
|
19
|
+
if (!existsSync(this.commsDir)) {
|
|
20
|
+
mkdirSync(this.commsDir, { recursive: true });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async postUpdate(options) {
|
|
24
|
+
const timestamp = new Date().toISOString().replace(/:/g, '-').replace(/\.\d+Z$/, 'Z');
|
|
25
|
+
const slug = options.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').slice(0, 40);
|
|
26
|
+
const filename = `${timestamp}-${slug}.md`;
|
|
27
|
+
const filepath = join(this.commsDir, filename);
|
|
28
|
+
const content = [
|
|
29
|
+
`# ${options.title}`,
|
|
30
|
+
'',
|
|
31
|
+
`**Posted by:** ${options.author ?? 'Squad'}`,
|
|
32
|
+
`**Category:** ${options.category ?? 'update'}`,
|
|
33
|
+
`**Timestamp:** ${new Date().toISOString()}`,
|
|
34
|
+
'',
|
|
35
|
+
'---',
|
|
36
|
+
'',
|
|
37
|
+
options.body,
|
|
38
|
+
'',
|
|
39
|
+
'---',
|
|
40
|
+
'',
|
|
41
|
+
'<!-- Replies: add your response below this line -->',
|
|
42
|
+
'',
|
|
43
|
+
].join('\n');
|
|
44
|
+
writeFileSync(filepath, content, 'utf-8');
|
|
45
|
+
return { id: filename.replace(/\.md$/, ''), url: undefined };
|
|
46
|
+
}
|
|
47
|
+
async pollForReplies(options) {
|
|
48
|
+
const filepath = join(this.commsDir, `${options.threadId}.md`);
|
|
49
|
+
if (!existsSync(filepath))
|
|
50
|
+
return [];
|
|
51
|
+
const content = readFileSync(filepath, 'utf-8');
|
|
52
|
+
const replyMarker = '<!-- Replies: add your response below this line -->';
|
|
53
|
+
const markerIdx = content.indexOf(replyMarker);
|
|
54
|
+
if (markerIdx === -1)
|
|
55
|
+
return [];
|
|
56
|
+
const repliesSection = content.slice(markerIdx + replyMarker.length).trim();
|
|
57
|
+
if (!repliesSection)
|
|
58
|
+
return [];
|
|
59
|
+
// Parse simple reply format: lines after the marker are replies
|
|
60
|
+
return [{
|
|
61
|
+
author: 'human',
|
|
62
|
+
body: repliesSection,
|
|
63
|
+
timestamp: new Date(),
|
|
64
|
+
id: `${options.threadId}-reply`,
|
|
65
|
+
}];
|
|
66
|
+
}
|
|
67
|
+
getNotificationUrl(_threadId) {
|
|
68
|
+
return undefined; // File-based has no web UI
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=comms-file-log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comms-file-log.js","sourceRoot":"","sources":["../../src/platform/comms-file-log.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Discussions communication adapter.
|
|
3
|
+
*
|
|
4
|
+
* Posts updates and reads replies via GitHub Discussions using `gh api`.
|
|
5
|
+
* Phone-capable (browser-based), not corp-only.
|
|
6
|
+
*
|
|
7
|
+
* @module platform/comms-github-discussions
|
|
8
|
+
*/
|
|
9
|
+
import type { CommunicationAdapter, CommunicationChannel, CommunicationReply } from './types.js';
|
|
10
|
+
export declare class GitHubDiscussionsCommunicationAdapter implements CommunicationAdapter {
|
|
11
|
+
private readonly owner;
|
|
12
|
+
private readonly repo;
|
|
13
|
+
readonly channel: CommunicationChannel;
|
|
14
|
+
constructor(owner: string, repo: string);
|
|
15
|
+
postUpdate(options: {
|
|
16
|
+
title: string;
|
|
17
|
+
body: string;
|
|
18
|
+
category?: string;
|
|
19
|
+
author?: string;
|
|
20
|
+
}): Promise<{
|
|
21
|
+
id: string;
|
|
22
|
+
url?: string;
|
|
23
|
+
}>;
|
|
24
|
+
pollForReplies(options: {
|
|
25
|
+
threadId: string;
|
|
26
|
+
since: Date;
|
|
27
|
+
}): Promise<CommunicationReply[]>;
|
|
28
|
+
getNotificationUrl(threadId: string): string | undefined;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=comms-github-discussions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comms-github-discussions.d.ts","sourceRoot":"","sources":["../../src/platform/comms-github-discussions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAajG,qBAAa,qCAAsC,YAAW,oBAAoB;IAI9E,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJvB,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAwB;gBAG3C,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM;IAGzB,UAAU,CAAC,OAAO,EAAE;QACxB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAkCnC,cAAc,CAAC,OAAO,EAAE;QAC5B,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,IAAI,CAAC;KACb,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAkBjC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAGzD"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Discussions communication adapter.
|
|
3
|
+
*
|
|
4
|
+
* Posts updates and reads replies via GitHub Discussions using `gh api`.
|
|
5
|
+
* Phone-capable (browser-based), not corp-only.
|
|
6
|
+
*
|
|
7
|
+
* @module platform/comms-github-discussions
|
|
8
|
+
*/
|
|
9
|
+
import { execFileSync } from 'node:child_process';
|
|
10
|
+
const EXEC_OPTS = { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] };
|
|
11
|
+
/** Safely parse JSON output */
|
|
12
|
+
function parseJson(raw) {
|
|
13
|
+
try {
|
|
14
|
+
return JSON.parse(raw);
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
throw new Error(`Failed to parse JSON: ${err.message}\nRaw: ${raw}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class GitHubDiscussionsCommunicationAdapter {
|
|
21
|
+
owner;
|
|
22
|
+
repo;
|
|
23
|
+
channel = 'github-discussions';
|
|
24
|
+
constructor(owner, repo) {
|
|
25
|
+
this.owner = owner;
|
|
26
|
+
this.repo = repo;
|
|
27
|
+
}
|
|
28
|
+
async postUpdate(options) {
|
|
29
|
+
const category = options.category ?? 'General';
|
|
30
|
+
// Get category ID
|
|
31
|
+
const categoryQuery = `query { repository(owner: "${this.owner}", name: "${this.repo}") { discussionCategories(first: 25) { nodes { id name } } } }`;
|
|
32
|
+
const catOutput = execFileSync('gh', ['api', 'graphql', '-f', `query=${categoryQuery}`], EXEC_OPTS);
|
|
33
|
+
const catData = parseJson(catOutput);
|
|
34
|
+
const catNode = catData.data.repository.discussionCategories.nodes.find((n) => n.name.toLowerCase() === category.toLowerCase());
|
|
35
|
+
if (!catNode) {
|
|
36
|
+
throw new Error(`Discussion category "${category}" not found in ${this.owner}/${this.repo}. Available: ${catData.data.repository.discussionCategories.nodes.map((n) => n.name).join(', ')}`);
|
|
37
|
+
}
|
|
38
|
+
// Get repo ID
|
|
39
|
+
const repoQuery = `query { repository(owner: "${this.owner}", name: "${this.repo}") { id } }`;
|
|
40
|
+
const repoOutput = execFileSync('gh', ['api', 'graphql', '-f', `query=${repoQuery}`], EXEC_OPTS);
|
|
41
|
+
const repoData = parseJson(repoOutput);
|
|
42
|
+
// Create discussion
|
|
43
|
+
const prefix = options.author ? `*Posted by ${options.author}*\n\n` : '';
|
|
44
|
+
const mutation = `mutation { createDiscussion(input: { repositoryId: "${repoData.data.repository.id}", categoryId: "${catNode.id}", title: "${options.title.replace(/"/g, '\\"')}", body: "${(prefix + options.body).replace(/"/g, '\\"').replace(/\n/g, '\\n')}" }) { discussion { id number url } } }`;
|
|
45
|
+
const output = execFileSync('gh', ['api', 'graphql', '-f', `query=${mutation}`], EXEC_OPTS);
|
|
46
|
+
const result = parseJson(output);
|
|
47
|
+
const disc = result.data.createDiscussion.discussion;
|
|
48
|
+
return { id: String(disc.number), url: disc.url };
|
|
49
|
+
}
|
|
50
|
+
async pollForReplies(options) {
|
|
51
|
+
const query = `query { repository(owner: "${this.owner}", name: "${this.repo}") { discussion(number: ${options.threadId}) { comments(first: 50) { nodes { id body createdAt author { login } } } } } }`;
|
|
52
|
+
const output = execFileSync('gh', ['api', 'graphql', '-f', `query=${query}`], EXEC_OPTS);
|
|
53
|
+
const data = parseJson(output);
|
|
54
|
+
const comments = data.data.repository.discussion.comments.nodes;
|
|
55
|
+
return comments
|
|
56
|
+
.filter((c) => new Date(c.createdAt) > options.since)
|
|
57
|
+
.map((c) => ({
|
|
58
|
+
author: c.author.login,
|
|
59
|
+
body: c.body,
|
|
60
|
+
timestamp: new Date(c.createdAt),
|
|
61
|
+
id: c.id,
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
getNotificationUrl(threadId) {
|
|
65
|
+
return `https://github.com/${this.owner}/${this.repo}/discussions/${threadId}`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=comms-github-discussions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comms-github-discussions.js","sourceRoot":"","sources":["../../src/platform/comms-github-discussions.ts"],"names":[],"mappings":"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"}
|