@sjawhar/opencode-legion-envoy 3.16.0 → 3.16.1
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/src/server.js
CHANGED
|
@@ -13559,6 +13559,8 @@ function serviceSubjectLabel(subject) {
|
|
|
13559
13559
|
}
|
|
13560
13560
|
return subject;
|
|
13561
13561
|
}
|
|
13562
|
+
var MAX_ISSUE_PAGE_LIMIT = 250;
|
|
13563
|
+
var DEFAULT_ISSUE_PAGE_LIMIT = 50;
|
|
13562
13564
|
var ASK_TURNS = ["human", "agent"];
|
|
13563
13565
|
var DELIVERY_CAPABILITIES = ["aside", "btw", "steer"];
|
|
13564
13566
|
var DELIVERY_DUPLICATE_WINDOW_MS = 72 * 60 * 60 * 1000;
|
|
@@ -14284,7 +14286,7 @@ var dispatchToolSpecs = [
|
|
|
14284
14286
|
{
|
|
14285
14287
|
name: "dispatch_issues",
|
|
14286
14288
|
example: { project: "AGENTC", limit: 250, offset: 250 },
|
|
14287
|
-
description: "List a project's issues for a roadmap or backlog pass: every issue in one project, each carrying " + "its status, priority, parent, labels, open-ask count, and route with whether it reaches anyone, " + "so you can see backlog shape without opening every issue. Optionally filter by status, parent, " + "label, priority, route status, or how recently it changed; priority takes one or more of 0-3 " + "(P0-P3) and null for an issue with no priority, so an owner's P0/P1 audit is priority [0, 1]. " + 'route_status "no_holder" lists every open issue whose route names a role nobody holds or a ' + "session that is not running at the moment of the read, whatever its priority. A restarting " + "session is absent for minutes, so an issue is unowned only when a read ten minutes later agrees. " + "Do not use it to search by keyword or phrase; dispatch_search remains the keyword surface. " + "
|
|
14289
|
+
description: "List a project's issues for a roadmap or backlog pass: every issue in one project, each carrying " + "its status, priority, parent, labels, open-ask count, and route with whether it reaches anyone, " + "so you can see backlog shape without opening every issue. Optionally filter by status, parent, " + "label, priority, route status, or how recently it changed; priority takes one or more of 0-3 " + "(P0-P3) and null for an issue with no priority, so an owner's P0/P1 audit is priority [0, 1]. " + 'route_status "no_holder" lists every open issue whose route names a role nobody holds or a ' + "session that is not running at the moment of the read, whatever its priority. A restarting " + "session is absent for minutes, so an issue is unowned only when a read ten minutes later agrees. " + "Do not use it to search by keyword or phrase; dispatch_search remains the keyword surface. " + "Dispatch pages the list: limit sets the page size (default " + `${DEFAULT_ISSUE_PAGE_LIMIT}, max ${MAX_ISSUE_PAGE_LIMIT}) and offset selects where it starts ` + "(default 0), and the answer names how many issues match, so repeat with the next offset to " + "walk every matching issue. A walk is exact only while the list does not change: an issue " + "that enters or leaves what the filters match, or whose status or rank changes, between two " + "pages shifts rows across a page boundary, so one issue can come back twice and another never.",
|
|
14288
14290
|
arguments: (z2) => ({
|
|
14289
14291
|
project: z2.string().describe("Project key to list issues from."),
|
|
14290
14292
|
status: z2.enum(ISSUE_STATUSES).describe("Optional lifecycle status filter.").optional(),
|
|
@@ -14293,7 +14295,7 @@ var dispatchToolSpecs = [
|
|
|
14293
14295
|
priority: z2.array(z2.number({ int: true, min: 0, max: 3 }).nullable(), { min: 1, max: 5 }).describe("Optional priority filter: one or more of 0 (P0, highest) through 3 (P3, lowest), and null " + "for an issue with no priority; an issue matching any listed value is returned.").optional(),
|
|
14294
14296
|
updated_since: z2.string().describe("Optional RFC3339 timestamp; only issues updated at or after it.").optional(),
|
|
14295
14297
|
route_status: z2.enum(ISSUE_ROUTE_STATUSES).describe("Optional: only open issues whose route is in this state. live: a running session holds " + "the role or is the routed session. no_holder: nobody running holds the role, or the " + "session is not running, right now. unknown: the Envoy listener did not answer.").optional(),
|
|
14296
|
-
limit: z2.number({ int: true, min: 1, max:
|
|
14298
|
+
limit: z2.number({ int: true, min: 1, max: MAX_ISSUE_PAGE_LIMIT }).describe(`Maximum rows, 1-${MAX_ISSUE_PAGE_LIMIT}; default ${DEFAULT_ISSUE_PAGE_LIMIT}.`).optional(),
|
|
14297
14299
|
offset: z2.number({ int: true, min: 0 }).describe("Rows to skip before the page; nonnegative integer; default 0.").optional()
|
|
14298
14300
|
})
|
|
14299
14301
|
},
|
|
@@ -15118,8 +15120,26 @@ class DispatchClient {
|
|
|
15118
15120
|
async resolveIssue(issueReference) {
|
|
15119
15121
|
return this.#resolveIssue(issueReference);
|
|
15120
15122
|
}
|
|
15121
|
-
async
|
|
15122
|
-
|
|
15123
|
+
async listIssuePage(options, page) {
|
|
15124
|
+
const answer = await this.#json("GET", ["api", "v1", "issues"], undefined, {
|
|
15125
|
+
...options,
|
|
15126
|
+
limit: page.limit,
|
|
15127
|
+
offset: page.offset
|
|
15128
|
+
});
|
|
15129
|
+
if (Array.isArray(answer)) {
|
|
15130
|
+
const issues = answer;
|
|
15131
|
+
return {
|
|
15132
|
+
issues: issues.slice(page.offset, page.offset + page.limit),
|
|
15133
|
+
total: issues.length,
|
|
15134
|
+
limit: page.limit,
|
|
15135
|
+
offset: page.offset
|
|
15136
|
+
};
|
|
15137
|
+
}
|
|
15138
|
+
const served = answer;
|
|
15139
|
+
if (typeof served !== "object" || served === null || !Array.isArray(served.issues) || typeof served.total !== "number" || typeof served.limit !== "number" || typeof served.offset !== "number") {
|
|
15140
|
+
throw new Error("GET /api/v1/issues answered neither a page ({issues, total, limit, offset}) nor an array of issues");
|
|
15141
|
+
}
|
|
15142
|
+
return served;
|
|
15123
15143
|
}
|
|
15124
15144
|
async listProjectArtifacts(project, unlinked = false) {
|
|
15125
15145
|
return this.#json("GET", ["api", "v1", "projects", project, "artifacts"], undefined, unlinked ? { unlinked: "true" } : undefined);
|
|
@@ -16789,9 +16809,7 @@ async function executeDispatchTool(input) {
|
|
|
16789
16809
|
const priority = optionalPriorityFilter(args, "priority");
|
|
16790
16810
|
const updatedSince = optionalString(args, "updated_since");
|
|
16791
16811
|
const routeStatus = optionalString(args, "route_status");
|
|
16792
|
-
const
|
|
16793
|
-
const offset = Math.max(optionalNumber(args, "offset") ?? 0, 0);
|
|
16794
|
-
const issues = await client.listIssues({
|
|
16812
|
+
const page = await client.listIssuePage({
|
|
16795
16813
|
project,
|
|
16796
16814
|
...status === undefined ? {} : { status },
|
|
16797
16815
|
...parent === undefined ? {} : { parent },
|
|
@@ -16799,9 +16817,12 @@ async function executeDispatchTool(input) {
|
|
|
16799
16817
|
...priority === undefined ? {} : { priority },
|
|
16800
16818
|
...updatedSince === undefined ? {} : { updated_since: updatedSince },
|
|
16801
16819
|
...routeStatus === undefined ? {} : { route_status: routeStatus }
|
|
16820
|
+
}, {
|
|
16821
|
+
limit: optionalNumber(args, "limit") ?? DEFAULT_ISSUE_PAGE_LIMIT,
|
|
16822
|
+
offset: optionalNumber(args, "offset") ?? 0
|
|
16802
16823
|
});
|
|
16803
|
-
const total =
|
|
16804
|
-
const rows = issues.
|
|
16824
|
+
const { total, limit, offset } = page;
|
|
16825
|
+
const rows = page.issues.map((row) => ({
|
|
16805
16826
|
key: row.key,
|
|
16806
16827
|
title: row.title,
|
|
16807
16828
|
status: row.status,
|
package/package.json
CHANGED
|
@@ -26,3 +26,14 @@ A path Dispatch does not serve under `/api` or `/v1` answers
|
|
|
26
26
|
route"}`; when you see that, you typed the path wrong — read the index rather than guessing. Every
|
|
27
27
|
`/api/v1` error body carries a `code`; branch on the code, never on the text.
|
|
28
28
|
|
|
29
|
+
`GET /api/v1/issues` answers every matching issue as an array, or one page when you name `limit`
|
|
30
|
+
(1–250) or `offset` (alone it pages 50): `{issues, total, limit, offset}`, where `total` counts
|
|
31
|
+
every issue your filters match. Walking the pages with the next `offset` is exact only while the
|
|
32
|
+
listing does not change: an issue that enters or leaves what the filters match, or whose status or
|
|
33
|
+
rank changes, between two reads shifts rows across a page boundary, and one issue comes back twice
|
|
34
|
+
and another never, even when you stop at `total`. The unpaged array is the only exact set one read
|
|
35
|
+
gives. `cursor` is `400 INVALID_QUERY`. `dispatch_issues` pages for you.
|
|
36
|
+
The event logs page with `after` or `before` and `limit`, and `GET /api/v1/search` takes a `limit`
|
|
37
|
+
of at most 50 and has no next page. Every other route answers without paging and ignores a paging
|
|
38
|
+
parameter.
|
|
39
|
+
|
|
@@ -144,8 +144,11 @@ when it last changed — a roadmap or backlog pass without opening every issue.
|
|
|
144
144
|
(a lifecycle status), `parent` (one issue's children), `label`, `priority` (a list of `0`–`3`, with
|
|
145
145
|
`null` for an issue with no priority: `[0, 1]` is every P0 and P1), `route_status` (below), or
|
|
146
146
|
`updated_since` (an RFC3339 timestamp, for "what moved this week"). `limit` is the page size, 50 by
|
|
147
|
-
default and 250 at most, and `offset` is where the page starts
|
|
148
|
-
|
|
147
|
+
default and 250 at most, and `offset` is where the page starts; the answer says how many issues
|
|
148
|
+
match. Repeating with the next offset walks every matching issue only while the list does not
|
|
149
|
+
change: an issue that enters or leaves what your filters match, or whose status or rank changes,
|
|
150
|
+
between two pages shifts rows across a page boundary, and the walk then shows one issue twice and
|
|
151
|
+
misses another.
|
|
149
152
|
|
|
150
153
|
This is not search: it matches no text. Use `dispatch_search` for a keyword or phrase, and
|
|
151
154
|
`dispatch_issues` when you want every issue in a project and its current state.
|