@sjawhar/pi-envoy 10.22.0 → 10.23.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/dispatch.js CHANGED
@@ -13576,6 +13576,7 @@ var DispatchServerStartedPayloadSchema = exports_external.strictObject({
13576
13576
  commit: exports_external.string().min(1),
13577
13577
  started_at: exports_external.iso.datetime()
13578
13578
  });
13579
+ var DEFAULT_ISSUE_READ_EVENTS = 10;
13579
13580
  var DispatchEventSchema = exports_external.object({
13580
13581
  issue_key: exports_external.string().nullable(),
13581
13582
  artifact_id: exports_external.string().nullish(),
@@ -14353,13 +14354,15 @@ var dispatchToolSpecs = [
14353
14354
  {
14354
14355
  name: "dispatch_read",
14355
14356
  example: { issue: "DSP-1" },
14356
- 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,
14357
+ 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,
14357
14358
  arguments: (z2) => ({
14358
14359
  issue: z2.string().describe(ISSUE_REFERENCE).optional(),
14359
14360
  project: z2.string().describe("Project key owning the document.").optional(),
14360
14361
  artifact: z2.string().describe("Document artifact id, slug, or filename: one of the issue's, or a project document.").optional(),
14361
14362
  ref: z2.string().describe("Optional dispatch:// issue or document reference.").optional(),
14362
- 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()
14363
+ 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(),
14364
+ 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(),
14365
+ 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()
14363
14366
  }),
14364
14367
  validation: readValidation
14365
14368
  },
@@ -15161,6 +15164,7 @@ function asErrorShape(value) {
15161
15164
  function isJson(response) {
15162
15165
  return response.headers.get("content-type")?.includes("application/json") ?? false;
15163
15166
  }
15167
+ var ISSUE_EVENTS_PAGE_MAX = 200;
15164
15168
  var DISPATCH_TOOL_DEADLINE_MS = 60000;
15165
15169
  function requestSignal(signal) {
15166
15170
  const deadline = AbortSignal.timeout(DISPATCH_TOOL_DEADLINE_MS);
@@ -15302,13 +15306,28 @@ class DispatchClient {
15302
15306
  async releaseIssueClaim(issue2, input = {}) {
15303
15307
  return this.#json("DELETE", ["api", "v1", "issues", await this.#resolveIssue(issue2), "claim"], input);
15304
15308
  }
15305
- async getIssueEvents(issue2, after = 0, limit = 200) {
15309
+ async getIssueEvents(issue2, after = 0, limit = ISSUE_EVENTS_PAGE_MAX) {
15306
15310
  return this.#json("GET", ["api", "v1", "issues", await this.#resolveIssue(issue2), "events"], undefined, { after, limit });
15307
15311
  }
15308
- async read(issueReference) {
15312
+ async read(issueReference, options = {}) {
15309
15313
  const issueKey = await this.#resolveIssue(issueReference);
15310
15314
  const issue2 = await this.getIssue(issueKey);
15311
- const events = await this.getIssueEvents(issueKey, Math.max(0, issue2.last_seq - 10), 10);
15315
+ const requested = options.events;
15316
+ const count = requested === undefined ? DEFAULT_ISSUE_READ_EVENTS : requested === "all" ? issue2.last_seq : Math.min(requested, issue2.last_seq);
15317
+ const events = [];
15318
+ let after = Math.max(0, issue2.last_seq - count);
15319
+ while (events.length < count) {
15320
+ const limit = Math.min(ISSUE_EVENTS_PAGE_MAX, count - events.length);
15321
+ const page = await this.getIssueEvents(issueKey, after, limit);
15322
+ events.push(...page);
15323
+ const last = page.at(-1);
15324
+ if (page.length < limit || last === undefined || events.length >= count)
15325
+ break;
15326
+ if (last.seq <= after) {
15327
+ throw new Error(`GET /api/v1/issues/${issueKey}/events?after=${after} answered no event after seq ${after}`);
15328
+ }
15329
+ after = last.seq;
15330
+ }
15312
15331
  return { issue: issue2, events };
15313
15332
  }
15314
15333
  async ask(issue2, input) {
@@ -16659,6 +16678,16 @@ function argumentProblems(tool, args) {
16659
16678
  if (message !== undefined && messageIdOf(message) === undefined) {
16660
16679
  problems.push("message must be a full message id (uuid) or a dispatch://KEY/message/<id> reference");
16661
16680
  }
16681
+ const events = optionalNumber(args, "events");
16682
+ const allEvents = optionalBoolean(args, "all_events") === true;
16683
+ if (events !== undefined && allEvents) {
16684
+ problems.push("--events and --all-events both say how many events the read lists: name one, --events N for the last N or --all-events for every one");
16685
+ }
16686
+ const count = events !== undefined ? "--events" : allEvents ? "--all-events" : undefined;
16687
+ const eventless = count === undefined ? undefined : readWithoutEvents(args);
16688
+ if (eventless !== undefined) {
16689
+ problems.push(`${count} lists an issue's events, which dispatch read prints only for an issue or its dispatch://KEY/log, not for ${eventless}: drop ${count}`);
16690
+ }
16662
16691
  break;
16663
16692
  }
16664
16693
  case "dispatch_doc_read": {
@@ -16670,6 +16699,27 @@ function argumentProblems(tool, args) {
16670
16699
  }
16671
16700
  return problems;
16672
16701
  }
16702
+ function readWithoutEvents(args) {
16703
+ if (optionalString(args, "message") !== undefined)
16704
+ return "a message's conversation";
16705
+ const ref = optionalString(args, "ref");
16706
+ switch (ref === undefined ? undefined : parseDispatchRef(ref)?.kind) {
16707
+ case "ask":
16708
+ return "an ask";
16709
+ case "comment":
16710
+ return "a comment";
16711
+ case "message":
16712
+ return "a message's conversation";
16713
+ case "children":
16714
+ return "the issue's children";
16715
+ case "log":
16716
+ return;
16717
+ }
16718
+ if (optionalString(args, "artifact") !== undefined || optionalString(args, "project") !== undefined) {
16719
+ return "a document summary";
16720
+ }
16721
+ return;
16722
+ }
16673
16723
  function dispatchRefFromUrl(value, serverUrl) {
16674
16724
  let url2;
16675
16725
  let origin;
@@ -18581,8 +18631,11 @@ ${trailer.join(`
18581
18631
  };
18582
18632
  }
18583
18633
  const issueKey = issue2();
18634
+ const readEvents = {
18635
+ events: optionalBoolean(args, "all_events") === true ? "all" : optionalNumber(args, "events")
18636
+ };
18584
18637
  if (ownerArguments.ref?.kind === "log") {
18585
- const read2 = await client.read(issueKey);
18638
+ const read2 = await client.read(issueKey, readEvents);
18586
18639
  const pictures3 = await picturesOf(read2.events.flatMap(eventTexts));
18587
18640
  return {
18588
18641
  text: [logSummary(read2.issue, read2.events), ...pictures3.lines].join(`
@@ -18592,13 +18645,13 @@ ${trailer.join(`
18592
18645
  };
18593
18646
  }
18594
18647
  if (ownerArguments.ref?.kind === "children") {
18595
- const read2 = await client.read(issueKey);
18648
+ const parent = await client.getIssue(issueKey);
18596
18649
  return {
18597
- text: childrenSummary(read2.issue),
18598
- details: { issue: read2.issue.key }
18650
+ text: childrenSummary(parent),
18651
+ details: { issue: parent.key }
18599
18652
  };
18600
18653
  }
18601
- const readPromise = client.read(issueKey);
18654
+ const readPromise = client.read(issueKey, readEvents);
18602
18655
  const referencesPromise = issueReferencesOrUnavailable(client, issueKey);
18603
18656
  const read = await readPromise;
18604
18657
  const [references, graph, titles, pictures2] = await Promise.all([
package/dist/envoy.js CHANGED
@@ -29665,6 +29665,7 @@ var DispatchServerStartedPayloadSchema = exports_external.strictObject({
29665
29665
  commit: exports_external.string().min(1),
29666
29666
  started_at: exports_external.iso.datetime()
29667
29667
  });
29668
+ var DEFAULT_ISSUE_READ_EVENTS = 10;
29668
29669
  var DispatchEventSchema = exports_external.object({
29669
29670
  issue_key: exports_external.string().nullable(),
29670
29671
  artifact_id: exports_external.string().nullish(),
@@ -30340,13 +30341,15 @@ var dispatchToolSpecs = [
30340
30341
  {
30341
30342
  name: "dispatch_read",
30342
30343
  example: { issue: "DSP-1" },
30343
- 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,
30344
+ 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,
30344
30345
  arguments: (z2) => ({
30345
30346
  issue: z2.string().describe(ISSUE_REFERENCE).optional(),
30346
30347
  project: z2.string().describe("Project key owning the document.").optional(),
30347
30348
  artifact: z2.string().describe("Document artifact id, slug, or filename: one of the issue's, or a project document.").optional(),
30348
30349
  ref: z2.string().describe("Optional dispatch:// issue or document reference.").optional(),
30349
- 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()
30350
+ 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(),
30351
+ 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(),
30352
+ 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()
30350
30353
  }),
30351
30354
  validation: readValidation
30352
30355
  },
@@ -32705,6 +32708,7 @@ function asErrorShape(value) {
32705
32708
  function isJson(response) {
32706
32709
  return response.headers.get("content-type")?.includes("application/json") ?? false;
32707
32710
  }
32711
+ var ISSUE_EVENTS_PAGE_MAX = 200;
32708
32712
  var DISPATCH_TOOL_DEADLINE_MS = 60000;
32709
32713
  function requestSignal(signal) {
32710
32714
  const deadline = AbortSignal.timeout(DISPATCH_TOOL_DEADLINE_MS);
@@ -32846,13 +32850,28 @@ class DispatchClient {
32846
32850
  async releaseIssueClaim(issue2, input = {}) {
32847
32851
  return this.#json("DELETE", ["api", "v1", "issues", await this.#resolveIssue(issue2), "claim"], input);
32848
32852
  }
32849
- async getIssueEvents(issue2, after = 0, limit = 200) {
32853
+ async getIssueEvents(issue2, after = 0, limit = ISSUE_EVENTS_PAGE_MAX) {
32850
32854
  return this.#json("GET", ["api", "v1", "issues", await this.#resolveIssue(issue2), "events"], undefined, { after, limit });
32851
32855
  }
32852
- async read(issueReference) {
32856
+ async read(issueReference, options = {}) {
32853
32857
  const issueKey = await this.#resolveIssue(issueReference);
32854
32858
  const issue2 = await this.getIssue(issueKey);
32855
- const events = await this.getIssueEvents(issueKey, Math.max(0, issue2.last_seq - 10), 10);
32859
+ const requested = options.events;
32860
+ const count = requested === undefined ? DEFAULT_ISSUE_READ_EVENTS : requested === "all" ? issue2.last_seq : Math.min(requested, issue2.last_seq);
32861
+ const events = [];
32862
+ let after = Math.max(0, issue2.last_seq - count);
32863
+ while (events.length < count) {
32864
+ const limit = Math.min(ISSUE_EVENTS_PAGE_MAX, count - events.length);
32865
+ const page = await this.getIssueEvents(issueKey, after, limit);
32866
+ events.push(...page);
32867
+ const last = page.at(-1);
32868
+ if (page.length < limit || last === undefined || events.length >= count)
32869
+ break;
32870
+ if (last.seq <= after) {
32871
+ throw new Error(`GET /api/v1/issues/${issueKey}/events?after=${after} answered no event after seq ${after}`);
32872
+ }
32873
+ after = last.seq;
32874
+ }
32856
32875
  return { issue: issue2, events };
32857
32876
  }
32858
32877
  async ask(issue2, input) {
@@ -4,7 +4,8 @@ Read this to catch up after a restart, read a node, trace what cites it, or writ
4
4
 
5
5
  ## What comes back
6
6
 
7
- - After a restart, catch up with `dispatch read --issue <KEY>` (or `--artifact` with `--issue` or `--project`, or `--ref`). It prints the issue's summary, open asks, references and recent events, a document's summary (its issue, reference, versions and approval), or an ask's, comment's or message's thread. Reads do not subscribe. Use `dispatch doc-read` for document text.
7
+ - After a restart, catch up with `dispatch read --issue <KEY>` (or `--artifact` with `--issue` or `--project`, or `--ref`). It prints the issue's summary, open asks, references and last 10 events, a document's summary (its issue, reference, versions and approval), or an ask's, comment's or message's thread. Reads do not subscribe. Use `dispatch doc-read` for document text.
8
+ - To audit an issue's history (who asked what, which ask was answered), add `--events N` for the last N events or `--all-events` for every one. Both work on `--ref dispatch://KEY/log` too.
8
9
  - An anchored comment or ask prints `Position:`, where its quote's block stands. `unavailable (DOC_SERVICE_UNAVAILABLE)` means try again shortly. `unavailable (DOC_SCHEMA)` means the document needs repair.
9
10
  - The API gives the same facts as `anchor_block` (or `anchor_block_error`) on `GET /api/v1/comments/{id}` and `GET /api/v1/asks/{id}`. `GET /api/v1/artifacts/{id}/blocks/{block_id}` gives them for any block.
10
11
  - Each read ends with `Referenced by:` (what cites the node) and `Links:` (what it cites), across projects. "What led to this decision" is one read on the ask.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/pi-envoy",
3
- "version": "10.22.0",
3
+ "version": "10.23.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "omp": {