@sjawhar/pi-legion 10.25.0 → 10.27.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/dist/legion.js CHANGED
@@ -14132,6 +14132,7 @@ var DispatchServerStartedPayloadSchema = exports_external.strictObject({
14132
14132
  commit: exports_external.string().min(1),
14133
14133
  started_at: exports_external.iso.datetime()
14134
14134
  });
14135
+ var DEFAULT_ISSUE_READ_EVENTS = 10;
14135
14136
  var DispatchEventSchema = exports_external.object({
14136
14137
  issue_key: exports_external.string().nullable(),
14137
14138
  artifact_id: exports_external.string().nullish(),
@@ -14772,13 +14773,15 @@ var dispatchToolSpecs = [
14772
14773
  {
14773
14774
  name: "dispatch_read",
14774
14775
  example: { issue: "DSP-1" },
14775
- description: "Read an issue or document summary, targeted ask, or targeted comment reply chain, or the conversation " + "a message belongs to. Do not use it for document contents; use dispatch doc-read instead. Supply ref, issue, " + "issue plus artifact (one of its documents), or project plus artifact; or message alone, which reads a human's direct message to this session and every " + "reply to it (they belong to no issue). A document summary names its issue, reference, versions and approval. " + "An anchored comment or ask also says where its quote sits, as `Position:`: the block's path from the top, " + "and in a table the row (0 is the header), the cells before the anchored one, and the column's header; " + "`Position: unavailable (<code>)` when Dispatch could not read the document: `DOC_SERVICE_UNAVAILABLE` " + "(try again shortly), `DOC_SCHEMA` (the document needs repair), `DOCUMENT_UNLOADABLE` (the document " + "needs a rebuild) or `INTERNAL`. " + "An issue read carries a `Progress:` line, `tasks 3/7, children 2/5`: its spec's task-list items " + "(`- [ ]` / `- [x]`, nested lists included) and its direct children, each done of total and each only " + "when it has any (`Progress: none` otherwise). " + "Every read ends with `Referenced by:` (what cites or hangs off this node, each with its dispatch:// address, " + "an excerpt, and when) and `Links:` (what it cites), so tracing provenance is one call. " + "The pictures the shown messages, asks and comments embed come back as images you see, newest first, at most 8 " + "and 10 MiB of them per read, each a PNG, JPEG, GIF or WebP of at most 3,750,000 bytes (5 MB of base64); a `Pictures:` section names each " + "one shown, in order, and the rest by reference, for dispatch doc-read. A picture this session was already shown is named, not sent again " + "(every request carries the session's history, and the provider refuses one over 32 MB); dispatch doc-read shows it again. " + OWNER_REFERENCE,
14776
+ description: "Read an issue or document summary, targeted ask, or targeted comment reply chain, or the conversation " + "a message belongs to. Do not use it for document contents; use dispatch doc-read instead. Supply ref, issue, " + "issue plus artifact (one of its documents), or project plus artifact; or message alone, which reads a human's direct message to this session and every " + "reply to it (they belong to no issue). A document summary names its issue, reference, versions and approval. " + "An anchored comment or ask also says where its quote sits, as `Position:`: the block's path from the top, " + "and in a table the row (0 is the header), the cells before the anchored one, and the column's header; " + "`Position: unavailable (<code>)` when Dispatch could not read the document: `DOC_SERVICE_UNAVAILABLE` " + "(try again shortly), `DOC_SCHEMA` (the document needs repair), `DOCUMENT_UNLOADABLE` (the document " + "needs a rebuild) or `INTERNAL`. " + "An issue read carries a `Progress:` line, `tasks 3/7, children 2/5`: its spec's task-list items " + "(`- [ ]` / `- [x]`, nested lists included) and its direct children, each done of total and each only " + "when it has any (`Progress: none` otherwise). " + `An issue read, and its dispatch://KEY/log, lists the issue's last ${DEFAULT_ISSUE_READ_EVENTS} events, oldest first; ` + "--events N lists the last N, and --all-events every one. " + "Every read ends with `Referenced by:` (what cites or hangs off this node, each with its dispatch:// address, " + "an excerpt, and when) and `Links:` (what it cites), so tracing provenance is one call. " + "The pictures the shown messages, asks and comments embed come back as images you see, newest first, at most 8 " + "and 10 MiB of them per read, each a PNG, JPEG, GIF or WebP of at most 3,750,000 bytes (5 MB of base64); a `Pictures:` section names each " + "one shown, in order, and the rest by reference, for dispatch doc-read. A picture this session was already shown is named, not sent again " + "(every request carries the session's history, and the provider refuses one over 32 MB); dispatch doc-read shows it again. " + OWNER_REFERENCE,
14776
14777
  arguments: (z2) => ({
14777
14778
  issue: z2.string().describe(ISSUE_REFERENCE).optional(),
14778
14779
  project: z2.string().describe("Project key owning the document.").optional(),
14779
14780
  artifact: z2.string().describe("Document artifact id, slug, or filename: one of the issue's, or a project document.").optional(),
14780
14781
  ref: z2.string().describe("Optional dispatch:// issue or document reference.").optional(),
14781
- message: z2.string().describe("A message id (uuid): reads the conversation it belongs to, the root message and every " + "reply. Name nothing else with it.").optional()
14782
+ message: z2.string().describe("A message id (uuid): reads the conversation it belongs to, the root message and every " + "reply. Name nothing else with it.").optional(),
14783
+ events: z2.number({ int: true, min: 1 }).describe(`How many of the issue's newest events an issue read or its dispatch://KEY/log lists, oldest first; default ${DEFAULT_ISSUE_READ_EVENTS}. Name no --all-events with it.`).optional(),
14784
+ all_events: z2.boolean().describe(`List every one of the issue's events, oldest first, on an issue read or its dispatch://KEY/log, in place of the last ${DEFAULT_ISSUE_READ_EVENTS}. Name no --events with it.`).optional()
14782
14785
  }),
14783
14786
  validation: readValidation
14784
14787
  },
@@ -15060,6 +15063,7 @@ function asErrorShape(value) {
15060
15063
  function isJson(response) {
15061
15064
  return response.headers.get("content-type")?.includes("application/json") ?? false;
15062
15065
  }
15066
+ var ISSUE_EVENTS_PAGE_MAX = 200;
15063
15067
  var DISPATCH_TOOL_DEADLINE_MS = 60000;
15064
15068
  function requestSignal(signal) {
15065
15069
  const deadline = AbortSignal.timeout(DISPATCH_TOOL_DEADLINE_MS);
@@ -15201,13 +15205,28 @@ class DispatchClient {
15201
15205
  async releaseIssueClaim(issue2, input = {}) {
15202
15206
  return this.#json("DELETE", ["api", "v1", "issues", await this.#resolveIssue(issue2), "claim"], input);
15203
15207
  }
15204
- async getIssueEvents(issue2, after = 0, limit = 200) {
15208
+ async getIssueEvents(issue2, after = 0, limit = ISSUE_EVENTS_PAGE_MAX) {
15205
15209
  return this.#json("GET", ["api", "v1", "issues", await this.#resolveIssue(issue2), "events"], undefined, { after, limit });
15206
15210
  }
15207
- async read(issueReference) {
15211
+ async read(issueReference, options = {}) {
15208
15212
  const issueKey = await this.#resolveIssue(issueReference);
15209
15213
  const issue2 = await this.getIssue(issueKey);
15210
- const events = await this.getIssueEvents(issueKey, Math.max(0, issue2.last_seq - 10), 10);
15214
+ const requested = options.events;
15215
+ const count = requested === undefined ? DEFAULT_ISSUE_READ_EVENTS : requested === "all" ? issue2.last_seq : Math.min(requested, issue2.last_seq);
15216
+ const events = [];
15217
+ let after = Math.max(0, issue2.last_seq - count);
15218
+ while (events.length < count) {
15219
+ const limit = Math.min(ISSUE_EVENTS_PAGE_MAX, count - events.length);
15220
+ const page = await this.getIssueEvents(issueKey, after, limit);
15221
+ events.push(...page);
15222
+ const last = page.at(-1);
15223
+ if (page.length < limit || last === undefined || events.length >= count)
15224
+ break;
15225
+ if (last.seq <= after) {
15226
+ throw new Error(`GET /api/v1/issues/${issueKey}/events?after=${after} answered no event after seq ${after}`);
15227
+ }
15228
+ after = last.seq;
15229
+ }
15211
15230
  return { issue: issue2, events };
15212
15231
  }
15213
15232
  async ask(issue2, input) {
@@ -16937,7 +16956,7 @@ async function bootLegionClaim(host2) {
16937
16956
  // package.json
16938
16957
  var package_default = {
16939
16958
  name: "@sjawhar/pi-legion",
16940
- version: "10.25.0",
16959
+ version: "10.27.0",
16941
16960
  license: "Apache-2.0",
16942
16961
  type: "module",
16943
16962
  omp: {
@@ -254,16 +254,20 @@ reviewing until you finish.
254
254
  - **Nothing waits in the session for a deploy.** A `pending` ends the look: the daemon suspends
255
255
  your claim with its session and the issue's volume kept, the pod goes, and the daemon wakes the
256
256
  check (the pod comes back and your session resumes with a new check task) on Dispatch's
257
- `issue.deployed` event for the pull request, or, for `sjawhar/legion`, on a Legion daemon's boot
258
- on a build containing the merge, on Dispatch's `server.started` naming such a build, or on the
259
- build the daemon read from Dispatch at its boot. The woken look's task names the event
260
- (`Dispatch's issue.deployed: run <id> completed <t>`, `the Legion daemon's boot on build <sha>`,
261
- `Dispatch's start on build <sha>`, `Dispatch's build <sha>`), and its `Production:` line names
262
- it too, so the pull request carries the cause. Never poll for the deploy, never wait on a reply,
263
- and never ask anyone for approval to deploy. Open a `dispatch ask` to a person only when the
264
- instructions name nobody for that deploy; it starts with the production gap and why it matters,
265
- then names the required install or restart step, its risk, and outcome-named options, and the
266
- look still ends `pending`.
257
+ `issue.deployed` event for the pull request; when the project's `legion.yaml` names the
258
+ repository's deploy workflow (`projects.<KEY>.deploys`), at each completed run of that workflow
259
+ on the default branch whose named step (such as `Apply`) succeeded after the merge, once per such
260
+ job; or, for `sjawhar/legion`, on a Legion daemon's boot on a build containing the merge, on
261
+ Dispatch's `server.started` naming such a build, or on the build the daemon read from Dispatch at
262
+ its boot. A wake while a look is open is kept, and a `pending` then starts the next look at once.
263
+ The woken look's task names the event (`Dispatch's issue.deployed: run <id> completed <t>`,
264
+ `the deploy workflow's run: <repo> <workflow> run <id> attempt <n>, job <job name>: <step> succeeded at <t>`,
265
+ `the Legion daemon's boot on build <sha>`, `Dispatch's start on build <sha>`,
266
+ `Dispatch's build <sha>`), and its `Production:` line names it too, so the pull request carries
267
+ the cause. Never poll for the deploy, never wait on a reply, and never ask anyone for approval
268
+ to deploy. Open a `dispatch ask` to a person only when the instructions name nobody for that
269
+ deploy; it starts with the production gap and why it matters, then names the required install or
270
+ restart step, its risk, and outcome-named options, and the look still ends `pending`.
267
271
  - **The bounds.** A look is bounded at 2 hours: one that reports nothing ends as a `pending`
268
272
  would. The whole check is bounded by the project's `production_check_hours` (336, 14 days, by
269
273
  default) from the close, and the wake at that bound is the last look, told so in its task
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/pi-legion",
3
- "version": "10.25.0",
3
+ "version": "10.27.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "omp": {