loreli 1.0.0 → 2.0.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/README.md +66 -26
- package/package.json +17 -14
- package/packages/action/prompts/action.md +172 -0
- package/packages/action/src/index.js +33 -5
- package/packages/agent/README.md +107 -18
- package/packages/agent/src/backends/claude.js +111 -11
- package/packages/agent/src/backends/codex.js +78 -5
- package/packages/agent/src/backends/cursor.js +104 -27
- package/packages/agent/src/backends/index.js +162 -5
- package/packages/agent/src/cli.js +80 -3
- package/packages/agent/src/discover.js +396 -0
- package/packages/agent/src/factory.js +39 -34
- package/packages/agent/src/models.js +24 -6
- package/packages/classify/README.md +136 -0
- package/packages/classify/prompts/blocker.md +12 -0
- package/packages/classify/prompts/feedback.md +14 -0
- package/packages/classify/prompts/pane-state.md +20 -0
- package/packages/classify/src/index.js +81 -0
- package/packages/config/README.md +156 -91
- package/packages/config/src/defaults.js +32 -21
- package/packages/config/src/index.js +33 -2
- package/packages/config/src/schema.js +57 -39
- package/packages/hub/src/github.js +59 -20
- package/packages/identity/README.md +1 -1
- package/packages/identity/src/index.js +2 -2
- package/packages/knowledge/README.md +86 -106
- package/packages/knowledge/src/index.js +56 -225
- package/packages/mcp/README.md +51 -7
- package/packages/mcp/instructions.md +6 -1
- package/packages/mcp/scaffolding/loreli.yml +115 -77
- package/packages/mcp/scaffolding/mcp-configs/.codex/config.toml +1 -0
- package/packages/mcp/scaffolding/mcp-configs/.cursor/mcp.json +4 -1
- package/packages/mcp/scaffolding/mcp-configs/.mcp.json +4 -1
- package/packages/mcp/src/index.js +45 -16
- package/packages/mcp/src/tools/agent-context.js +44 -0
- package/packages/mcp/src/tools/agents.js +34 -13
- package/packages/mcp/src/tools/context.js +3 -2
- package/packages/mcp/src/tools/github.js +11 -47
- package/packages/mcp/src/tools/hitl.js +19 -6
- package/packages/mcp/src/tools/index.js +2 -1
- package/packages/mcp/src/tools/refactor.js +227 -0
- package/packages/mcp/src/tools/repo.js +44 -0
- package/packages/mcp/src/tools/start.js +159 -90
- package/packages/mcp/src/tools/status.js +5 -2
- package/packages/mcp/src/tools/work.js +18 -8
- package/packages/orchestrator/src/index.js +345 -79
- package/packages/planner/README.md +84 -1
- package/packages/planner/prompts/plan-reviewer.md +109 -0
- package/packages/planner/prompts/planner.md +191 -0
- package/packages/planner/prompts/tiebreaker-reviewer.md +71 -0
- package/packages/planner/src/index.js +326 -111
- package/packages/review/README.md +2 -2
- package/packages/review/prompts/reviewer.md +158 -0
- package/packages/review/src/index.js +196 -76
- package/packages/risk/README.md +81 -22
- package/packages/risk/prompts/risk.md +272 -0
- package/packages/risk/src/index.js +44 -33
- package/packages/tmux/src/index.js +61 -12
- package/packages/workflow/README.md +18 -14
- package/packages/workflow/prompts/preamble.md +14 -0
- package/packages/workflow/src/index.js +191 -12
- package/packages/workspace/README.md +2 -2
- package/packages/workspace/src/index.js +69 -18
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import ms from 'ms';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Valid merge methods supported by GitHub.
|
|
5
|
+
* @type {Set<string>}
|
|
6
|
+
*/
|
|
7
|
+
const MERGE_METHODS = new Set(['merge', 'squash', 'rebase']);
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Pattern for valid "owner/name" repository format.
|
|
11
|
+
* @type {RegExp}
|
|
12
|
+
*/
|
|
13
|
+
const REPO_RE = /^[^/]+\/[^/]+$/;
|
|
14
|
+
|
|
3
15
|
/**
|
|
4
16
|
* Validates and normalizes a raw config object parsed from loreli.yml.
|
|
5
17
|
* Ensures types are correct and unknown keys are stripped.
|
|
@@ -15,6 +27,8 @@ export function validate(raw) {
|
|
|
15
27
|
|
|
16
28
|
const out = {};
|
|
17
29
|
|
|
30
|
+
if (typeof raw.repo === 'string' && REPO_RE.test(raw.repo)) out.repo = raw.repo;
|
|
31
|
+
|
|
18
32
|
if (typeof raw.theme === 'string') {
|
|
19
33
|
out.theme = raw.theme;
|
|
20
34
|
} else if (Array.isArray(raw.theme)) {
|
|
@@ -32,7 +46,7 @@ export function validate(raw) {
|
|
|
32
46
|
|
|
33
47
|
if (raw.merge && typeof raw.merge === 'object') {
|
|
34
48
|
out.merge = {};
|
|
35
|
-
if (typeof raw.merge.method === 'string') out.merge.method = raw.merge.method;
|
|
49
|
+
if (typeof raw.merge.method === 'string' && MERGE_METHODS.has(raw.merge.method)) out.merge.method = raw.merge.method;
|
|
36
50
|
if (typeof raw.merge.base === 'string') out.merge.base = raw.merge.base;
|
|
37
51
|
|
|
38
52
|
if (typeof raw.merge.hitl === 'boolean') {
|
|
@@ -78,7 +92,7 @@ export function validate(raw) {
|
|
|
78
92
|
|
|
79
93
|
if (raw.timeouts && typeof raw.timeouts === 'object') {
|
|
80
94
|
out.timeouts = {};
|
|
81
|
-
for (const key of ['stall', 'shutdown', 'poll', 'rapidDeath']) {
|
|
95
|
+
for (const key of ['stall', 'shutdown', 'poll', 'rapidDeath', 'proxyDiscovery']) {
|
|
82
96
|
const v = raw.timeouts[key];
|
|
83
97
|
if (v == null) continue;
|
|
84
98
|
try { out.timeouts[key] = typeof v === 'number' ? v : ms(v); } catch { /* invalid — falls to default */ }
|
|
@@ -113,13 +127,6 @@ export function validate(raw) {
|
|
|
113
127
|
if (typeof raw.watch.maxClaims === 'number' && raw.watch.maxClaims > 0) out.watch.maxClaims = raw.watch.maxClaims;
|
|
114
128
|
}
|
|
115
129
|
|
|
116
|
-
if (raw.review && typeof raw.review === 'object') {
|
|
117
|
-
out.review = {};
|
|
118
|
-
if (typeof raw.review.skipRiskAssessment === 'boolean') {
|
|
119
|
-
out.review.skipRiskAssessment = raw.review.skipRiskAssessment;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
130
|
if (raw.scaling && typeof raw.scaling === 'object') {
|
|
124
131
|
out.scaling = {};
|
|
125
132
|
if (typeof raw.scaling.maxAgents === 'number') out.scaling.maxAgents = raw.scaling.maxAgents;
|
|
@@ -130,16 +137,6 @@ export function validate(raw) {
|
|
|
130
137
|
try { out.scaling.cooldown = typeof cd === 'number' ? cd : ms(cd); } catch { /* invalid — falls to default */ }
|
|
131
138
|
}
|
|
132
139
|
|
|
133
|
-
if (raw.scaling.maxPerRole && typeof raw.scaling.maxPerRole === 'object') {
|
|
134
|
-
const mpr = {};
|
|
135
|
-
for (const role of ['action', 'reviewer', 'risk', 'planner']) {
|
|
136
|
-
if (typeof raw.scaling.maxPerRole[role] === 'number') {
|
|
137
|
-
mpr[role] = raw.scaling.maxPerRole[role];
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
if (Object.keys(mpr).length) out.scaling.maxPerRole = mpr;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
140
|
if (!Object.keys(out.scaling).length) delete out.scaling;
|
|
144
141
|
}
|
|
145
142
|
|
|
@@ -190,25 +187,23 @@ export function validate(raw) {
|
|
|
190
187
|
if (!Object.keys(out.backends).length) delete out.backends;
|
|
191
188
|
}
|
|
192
189
|
|
|
190
|
+
if (raw.classify && typeof raw.classify === 'object') {
|
|
191
|
+
out.classify = {};
|
|
192
|
+
if (typeof raw.classify.model === 'string') out.classify.model = raw.classify.model;
|
|
193
|
+
if (typeof raw.classify.maxLines === 'number' && raw.classify.maxLines > 0) out.classify.maxLines = raw.classify.maxLines;
|
|
194
|
+
if (typeof raw.classify.maxRetries === 'number' && raw.classify.maxRetries > 0) out.classify.maxRetries = raw.classify.maxRetries;
|
|
195
|
+
const t = raw.classify.timeout;
|
|
196
|
+
if (t != null) {
|
|
197
|
+
try { out.classify.timeout = typeof t === 'number' ? t : ms(t); } catch { /* invalid — falls to default */ }
|
|
198
|
+
}
|
|
199
|
+
if (!Object.keys(out.classify).length) delete out.classify;
|
|
200
|
+
}
|
|
201
|
+
|
|
193
202
|
if (raw.trace && typeof raw.trace === 'object') {
|
|
194
203
|
out.trace = {};
|
|
195
204
|
if (typeof raw.trace.enabled === 'boolean') out.trace.enabled = raw.trace.enabled;
|
|
196
205
|
if (typeof raw.trace.includeOutput === 'boolean') out.trace.includeOutput = raw.trace.includeOutput;
|
|
197
206
|
if (typeof raw.trace.maxOutputChars === 'number') out.trace.maxOutputChars = raw.trace.maxOutputChars;
|
|
198
|
-
|
|
199
|
-
if (raw.trace.workflows && typeof raw.trace.workflows === 'object') {
|
|
200
|
-
const workflows = {};
|
|
201
|
-
for (const role of ['planner', 'reviewer', 'risk']) {
|
|
202
|
-
const wf = raw.trace.workflows[role];
|
|
203
|
-
if (wf && typeof wf === 'object') {
|
|
204
|
-
const entry = {};
|
|
205
|
-
if (typeof wf.enabled === 'boolean') entry.enabled = wf.enabled;
|
|
206
|
-
if (typeof wf.maxOutputChars === 'number') entry.maxOutputChars = wf.maxOutputChars;
|
|
207
|
-
if (Object.keys(entry).length) workflows[role] = entry;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
if (Object.keys(workflows).length) out.trace.workflows = workflows;
|
|
211
|
-
}
|
|
212
207
|
}
|
|
213
208
|
|
|
214
209
|
if (raw.agents && typeof raw.agents === 'object') {
|
|
@@ -240,6 +235,13 @@ export function validate(raw) {
|
|
|
240
235
|
function isString(c) { return typeof c === 'string'; }
|
|
241
236
|
);
|
|
242
237
|
}
|
|
238
|
+
if (typeof raw.feedback.hitl === 'boolean') {
|
|
239
|
+
out.feedback.hitl = raw.feedback.hitl;
|
|
240
|
+
} else if (Array.isArray(raw.feedback.hitl)) {
|
|
241
|
+
out.feedback.hitl = raw.feedback.hitl.filter(
|
|
242
|
+
function isString(c) { return typeof c === 'string'; }
|
|
243
|
+
);
|
|
244
|
+
}
|
|
243
245
|
}
|
|
244
246
|
|
|
245
247
|
if (raw.workspace && typeof raw.workspace === 'object') {
|
|
@@ -256,17 +258,33 @@ export function validate(raw) {
|
|
|
256
258
|
if (typeof raw.cleanup.autoprune === 'boolean') out.cleanup.autoprune = raw.cleanup.autoprune;
|
|
257
259
|
}
|
|
258
260
|
|
|
259
|
-
if (raw.
|
|
260
|
-
const
|
|
261
|
-
for (const role of ['action', 'reviewer', '
|
|
262
|
-
|
|
261
|
+
if (raw.workflows && typeof raw.workflows === 'object') {
|
|
262
|
+
const workflows = {};
|
|
263
|
+
for (const role of ['action', 'reviewer', 'risk', 'planner']) {
|
|
264
|
+
const wf = raw.workflows[role];
|
|
265
|
+
if (!wf || typeof wf !== 'object') continue;
|
|
266
|
+
|
|
267
|
+
const entry = {};
|
|
268
|
+
if (typeof wf.model === 'string') entry.model = wf.model;
|
|
269
|
+
if (typeof wf.maxAgents === 'number') entry.maxAgents = wf.maxAgents;
|
|
270
|
+
if (typeof wf.prompt === 'string') entry.prompt = wf.prompt;
|
|
271
|
+
if (typeof wf.skip === 'boolean') entry.skip = wf.skip;
|
|
272
|
+
|
|
273
|
+
if (wf.trace && typeof wf.trace === 'object') {
|
|
274
|
+
const trace = {};
|
|
275
|
+
if (typeof wf.trace.enabled === 'boolean') trace.enabled = wf.trace.enabled;
|
|
276
|
+
if (typeof wf.trace.maxOutputChars === 'number') trace.maxOutputChars = wf.trace.maxOutputChars;
|
|
277
|
+
if (Object.keys(trace).length) entry.trace = trace;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (Object.keys(entry).length) workflows[role] = entry;
|
|
263
281
|
}
|
|
264
|
-
if (Object.keys(
|
|
282
|
+
if (Object.keys(workflows).length) out.workflows = workflows;
|
|
265
283
|
}
|
|
266
284
|
|
|
267
285
|
if (raw.github && typeof raw.github === 'object') {
|
|
268
286
|
out.github = {};
|
|
269
|
-
if (typeof raw.github.token === 'string') out.github.token = raw.github.token;
|
|
287
|
+
if (typeof raw.github.token === 'string' && raw.github.token.length > 0) out.github.token = raw.github.token;
|
|
270
288
|
}
|
|
271
289
|
|
|
272
290
|
return out;
|
|
@@ -12,11 +12,19 @@ const log = logger('hub');
|
|
|
12
12
|
const RATE_WARN_THRESHOLD = 0.2;
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* Maximum retry attempts for
|
|
15
|
+
* Maximum retry attempts for transient failures.
|
|
16
16
|
* @type {number}
|
|
17
17
|
*/
|
|
18
18
|
const MAX_RETRIES = 3;
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* HTTP status codes eligible for automatic retry with backoff.
|
|
22
|
+
* 429 = secondary rate limit, 500/502/503 = transient server errors.
|
|
23
|
+
*
|
|
24
|
+
* @type {Set<number>}
|
|
25
|
+
*/
|
|
26
|
+
const RETRYABLE = new Set([429, 500, 502, 503]);
|
|
27
|
+
|
|
20
28
|
/**
|
|
21
29
|
* Calculate exponential backoff with jitter.
|
|
22
30
|
*
|
|
@@ -125,7 +133,7 @@ const normalize = {
|
|
|
125
133
|
* Normalize a GitHub pull request object.
|
|
126
134
|
*
|
|
127
135
|
* @param {object} raw - Raw GitHub PR API response.
|
|
128
|
-
* @returns {{number: number, title: string, body: string, state: string, head: string, headSha: string, base: string, author: string, url: string, labels: string[], merged: boolean, created: string, updated: string}}
|
|
136
|
+
* @returns {{number: number, title: string, body: string, state: string, head: string, headSha: string, base: string, author: string, url: string, labels: string[], merged: boolean, mergeable: boolean|null, mergeableState: string|null, created: string, updated: string}}
|
|
129
137
|
*/
|
|
130
138
|
pull(raw) {
|
|
131
139
|
return {
|
|
@@ -142,6 +150,8 @@ const normalize = {
|
|
|
142
150
|
return typeof l === 'string' ? l : l.name;
|
|
143
151
|
}),
|
|
144
152
|
merged: raw.merged ?? false,
|
|
153
|
+
mergeable: raw.mergeable ?? null,
|
|
154
|
+
mergeableState: raw.mergeable_state ?? null,
|
|
145
155
|
created: raw.created_at,
|
|
146
156
|
updated: raw.updated_at
|
|
147
157
|
};
|
|
@@ -226,9 +236,9 @@ export class GitHubHub extends BaseHub {
|
|
|
226
236
|
try {
|
|
227
237
|
response = await request(options);
|
|
228
238
|
} catch (err) {
|
|
229
|
-
|
|
230
|
-
if (err.status === 429 && attempt < MAX_RETRIES) {
|
|
239
|
+
if (RETRYABLE.has(err.status) && attempt < MAX_RETRIES) {
|
|
231
240
|
const wait = parseRetryAfter(err.response?.headers) ?? backoff(attempt);
|
|
241
|
+
log.warn(`retrying ${options.method} ${options.url} (${err.status}, attempt ${attempt + 1}/${MAX_RETRIES})`);
|
|
232
242
|
await new Promise(function delay(r) { setTimeout(r, wait); });
|
|
233
243
|
continue;
|
|
234
244
|
}
|
|
@@ -249,6 +259,29 @@ export class GitHubHub extends BaseHub {
|
|
|
249
259
|
});
|
|
250
260
|
}
|
|
251
261
|
|
|
262
|
+
/**
|
|
263
|
+
* Execute a GraphQL query/mutation with error checking and rate limit tracking.
|
|
264
|
+
*
|
|
265
|
+
* GraphQL responses can return partial data alongside an `errors` array.
|
|
266
|
+
* This method throws on errors instead of silently using partial data.
|
|
267
|
+
* Also extracts `x-ratelimit-*` headers that the REST hook misses.
|
|
268
|
+
*
|
|
269
|
+
* @param {string} query - GraphQL query or mutation string.
|
|
270
|
+
* @param {object} [variables] - Query variables.
|
|
271
|
+
* @returns {Promise<object>} The response data.
|
|
272
|
+
* @throws {Error} When the response contains GraphQL errors.
|
|
273
|
+
*/
|
|
274
|
+
async _graphql(query, variables) {
|
|
275
|
+
const result = await this.client.graphql(query, variables);
|
|
276
|
+
|
|
277
|
+
if (result.errors?.length) {
|
|
278
|
+
const messages = result.errors.map(function msg(e) { return e.message; }).join('; ');
|
|
279
|
+
throw new Error(`GraphQL errors: ${messages}`);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return result;
|
|
283
|
+
}
|
|
284
|
+
|
|
252
285
|
/**
|
|
253
286
|
* Parse rate limit headers from a GitHub API response and update internal state.
|
|
254
287
|
* Emits a warning when remaining requests drop below the configured threshold.
|
|
@@ -357,8 +390,10 @@ export class GitHubHub extends BaseHub {
|
|
|
357
390
|
* @returns {[string, string]} Tuple of [owner, repo].
|
|
358
391
|
*/
|
|
359
392
|
parse(repo) {
|
|
360
|
-
const
|
|
361
|
-
|
|
393
|
+
const slash = repo.indexOf('/');
|
|
394
|
+
if (slash <= 0 || slash === repo.length - 1)
|
|
395
|
+
throw new Error(`Invalid repo format "${repo}": expected "owner/name"`);
|
|
396
|
+
return [repo.slice(0, slash), repo.slice(slash + 1)];
|
|
362
397
|
}
|
|
363
398
|
|
|
364
399
|
/**
|
|
@@ -438,6 +473,8 @@ export class GitHubHub extends BaseHub {
|
|
|
438
473
|
owner, repo: name,
|
|
439
474
|
state: opts.state ?? 'open',
|
|
440
475
|
labels: opts.labels?.join(','),
|
|
476
|
+
sort: 'created',
|
|
477
|
+
direction: 'asc',
|
|
441
478
|
per_page: 100
|
|
442
479
|
});
|
|
443
480
|
return data.filter(function notPR(i) { return !i.pull_request; }).map(normalize.issue);
|
|
@@ -575,6 +612,8 @@ export class GitHubHub extends BaseHub {
|
|
|
575
612
|
const data = await this.client.paginate(this.client.pulls.list, {
|
|
576
613
|
owner, repo: name,
|
|
577
614
|
state: opts.state ?? 'open',
|
|
615
|
+
sort: 'created',
|
|
616
|
+
direction: 'asc',
|
|
578
617
|
per_page: 100
|
|
579
618
|
});
|
|
580
619
|
return data.map(normalize.pull);
|
|
@@ -585,7 +624,7 @@ export class GitHubHub extends BaseHub {
|
|
|
585
624
|
*
|
|
586
625
|
* @param {string} repo - "owner/name" repository.
|
|
587
626
|
* @param {number} number - Pull request number.
|
|
588
|
-
* @returns {Promise<{number: number, title: string, body: string, state: string, head: string, base: string, author: string, url: string, labels: string[], merged: boolean, created: string, updated: string}>}
|
|
627
|
+
* @returns {Promise<{number: number, title: string, body: string, state: string, head: string, base: string, author: string, url: string, labels: string[], merged: boolean, mergeable: boolean|null, mergeableState: string|null, created: string, updated: string}>}
|
|
589
628
|
*/
|
|
590
629
|
async pull(repo, number) {
|
|
591
630
|
const [owner, name] = this.parse(repo);
|
|
@@ -1077,7 +1116,7 @@ export class GitHubHub extends BaseHub {
|
|
|
1077
1116
|
}
|
|
1078
1117
|
}`;
|
|
1079
1118
|
|
|
1080
|
-
const result = await this.
|
|
1119
|
+
const result = await this._graphql(query, { owner, name: repoName });
|
|
1081
1120
|
const cats = result.repository?.discussionCategories?.nodes ?? [];
|
|
1082
1121
|
const match = cats.find(function byName(c) { return c.name === name; });
|
|
1083
1122
|
if (!match) {
|
|
@@ -1113,7 +1152,7 @@ export class GitHubHub extends BaseHub {
|
|
|
1113
1152
|
}
|
|
1114
1153
|
}`;
|
|
1115
1154
|
|
|
1116
|
-
const result = await this.
|
|
1155
|
+
const result = await this._graphql(mutation, {
|
|
1117
1156
|
repositoryId: opts.repositoryId,
|
|
1118
1157
|
categoryId: opts.categoryId,
|
|
1119
1158
|
title: opts.title,
|
|
@@ -1152,7 +1191,7 @@ export class GitHubHub extends BaseHub {
|
|
|
1152
1191
|
const [owner, repoName] = this.parse(repo);
|
|
1153
1192
|
const query = `query($owner: String!, $name: String!, $categoryId: ID!) {
|
|
1154
1193
|
repository(owner: $owner, name: $name) {
|
|
1155
|
-
discussions(first: 100, categoryId: $categoryId) {
|
|
1194
|
+
discussions(first: 100, categoryId: $categoryId, orderBy: { field: CREATED_AT, direction: ASC }) {
|
|
1156
1195
|
nodes {
|
|
1157
1196
|
id number title body url closed
|
|
1158
1197
|
author { login }
|
|
@@ -1162,7 +1201,7 @@ export class GitHubHub extends BaseHub {
|
|
|
1162
1201
|
}
|
|
1163
1202
|
}`;
|
|
1164
1203
|
|
|
1165
|
-
const result = await this.
|
|
1204
|
+
const result = await this._graphql(query, { owner, name: repoName, categoryId });
|
|
1166
1205
|
const nodes = result.repository?.discussions?.nodes ?? [];
|
|
1167
1206
|
return nodes.map(function norm(d) {
|
|
1168
1207
|
return {
|
|
@@ -1203,7 +1242,7 @@ export class GitHubHub extends BaseHub {
|
|
|
1203
1242
|
}
|
|
1204
1243
|
}`;
|
|
1205
1244
|
|
|
1206
|
-
const result = await this.
|
|
1245
|
+
const result = await this._graphql(query, { owner, name: repoName, number });
|
|
1207
1246
|
const d = result.repository?.discussion;
|
|
1208
1247
|
if (!d) throw new Error(`Discussion #${number} not found in ${repo}`);
|
|
1209
1248
|
return {
|
|
@@ -1241,7 +1280,7 @@ export class GitHubHub extends BaseHub {
|
|
|
1241
1280
|
}
|
|
1242
1281
|
}`;
|
|
1243
1282
|
|
|
1244
|
-
const result = await this.
|
|
1283
|
+
const result = await this._graphql(query, { id: discussionId });
|
|
1245
1284
|
const nodes = result.node?.comments?.nodes ?? [];
|
|
1246
1285
|
return nodes.map(function norm(c) {
|
|
1247
1286
|
return { id: c.id, body: c.body ?? '', author: c.author?.login ?? '', created: c.createdAt };
|
|
@@ -1265,7 +1304,7 @@ export class GitHubHub extends BaseHub {
|
|
|
1265
1304
|
}
|
|
1266
1305
|
}`;
|
|
1267
1306
|
|
|
1268
|
-
const result = await this.
|
|
1307
|
+
const result = await this._graphql(mutation, {
|
|
1269
1308
|
discussionId,
|
|
1270
1309
|
body: this._stamp(body)
|
|
1271
1310
|
});
|
|
@@ -1300,7 +1339,7 @@ export class GitHubHub extends BaseHub {
|
|
|
1300
1339
|
}
|
|
1301
1340
|
}`;
|
|
1302
1341
|
|
|
1303
|
-
const result = await this.
|
|
1342
|
+
const result = await this._graphql(mutation, input);
|
|
1304
1343
|
return {
|
|
1305
1344
|
id: result.updateDiscussion.discussion.id,
|
|
1306
1345
|
title: result.updateDiscussion.discussion.title
|
|
@@ -1319,14 +1358,14 @@ export class GitHubHub extends BaseHub {
|
|
|
1319
1358
|
discussion { id }
|
|
1320
1359
|
}
|
|
1321
1360
|
}`;
|
|
1322
|
-
await this.
|
|
1361
|
+
await this._graphql(closeMutation, { id: discussionId });
|
|
1323
1362
|
|
|
1324
1363
|
const lockMutation = `mutation($id: ID!) {
|
|
1325
1364
|
lockLockable(input: { lockableId: $id }) {
|
|
1326
1365
|
lockedRecord { locked }
|
|
1327
1366
|
}
|
|
1328
1367
|
}`;
|
|
1329
|
-
await this.
|
|
1368
|
+
await this._graphql(lockMutation, { id: discussionId });
|
|
1330
1369
|
}
|
|
1331
1370
|
|
|
1332
1371
|
/**
|
|
@@ -1341,7 +1380,7 @@ export class GitHubHub extends BaseHub {
|
|
|
1341
1380
|
discussion { id }
|
|
1342
1381
|
}
|
|
1343
1382
|
}`;
|
|
1344
|
-
const result = await this.
|
|
1383
|
+
const result = await this._graphql(mutation, { id: discussionId });
|
|
1345
1384
|
const deletedId = result.deleteDiscussion?.discussion?.id;
|
|
1346
1385
|
|
|
1347
1386
|
// Verify the discussion is no longer fetchable by node ID
|
|
@@ -1398,7 +1437,7 @@ export class GitHubHub extends BaseHub {
|
|
|
1398
1437
|
labelable { ... on Discussion { id } }
|
|
1399
1438
|
}
|
|
1400
1439
|
}`;
|
|
1401
|
-
await this.
|
|
1440
|
+
await this._graphql(mutation, { labelableId: discussionId, labelIds });
|
|
1402
1441
|
}
|
|
1403
1442
|
|
|
1404
1443
|
/**
|
|
@@ -1431,7 +1470,7 @@ export class GitHubHub extends BaseHub {
|
|
|
1431
1470
|
labelable { ... on Discussion { id } }
|
|
1432
1471
|
}
|
|
1433
1472
|
}`;
|
|
1434
|
-
await this.
|
|
1473
|
+
await this._graphql(mutation, { labelableId: discussionId, labelIds });
|
|
1435
1474
|
}
|
|
1436
1475
|
|
|
1437
1476
|
// --- Search & Commits ---
|
|
@@ -151,7 +151,7 @@ Autobots, roll out! — **optimus-0**
|
|
|
151
151
|
|
|
152
152
|
| Agent | Model | Provider | Faction | Role | Version |
|
|
153
153
|
|-------|-------|----------|---------|------|---------|
|
|
154
|
-
| optimus-0 | gpt-4o | openai | autobots | action | loreli@0.0.0 |
|
|
154
|
+
| optimus-0 | gpt-4o | openai | autobots | action | `loreli@0.0.0` |
|
|
155
155
|
```
|
|
156
156
|
|
|
157
157
|
This is automatically appended by claim, signoff, and relay comments in the orchestration workflow.
|
|
@@ -439,7 +439,7 @@ export class Identity {
|
|
|
439
439
|
*
|
|
440
440
|
* | Agent | Model | Provider | Faction | Role | Version |
|
|
441
441
|
* |-------|-------|----------|---------|------|---------|
|
|
442
|
-
* | {name} | {displayModel} | {provider} | {faction} | {role} | loreli@{version} |
|
|
442
|
+
* | {name} | {displayModel} | {provider} | {faction} | {role} | `loreli@{version}` |
|
|
443
443
|
* ```
|
|
444
444
|
*
|
|
445
445
|
* @param {string} role - The agent's current role.
|
|
@@ -460,7 +460,7 @@ export class Identity {
|
|
|
460
460
|
'',
|
|
461
461
|
'| Agent | Model | Provider | Faction | Role | Version |',
|
|
462
462
|
'|-------|-------|----------|---------|------|---------|',
|
|
463
|
-
`| ${this.name} | ${model} | ${this.provider} | ${this.faction} | ${role} | loreli@${ver} |`
|
|
463
|
+
`| ${this.name} | ${model} | ${this.provider} | ${this.faction} | ${role} | \`loreli@${ver}\` |`
|
|
464
464
|
].join('\n');
|
|
465
465
|
}
|
|
466
466
|
}
|