@sjawhar/opencode-legion-envoy 9.1.0 → 9.3.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 +211 -35
- package/dist/src/server.js +54 -13
- package/package.json +1 -1
- package/skills/dispatch/SKILL.md +12 -12
- package/skills/envoy/SKILL.md +1 -1
- package/skills/envoy/references/deliveries.md +1 -1
- package/skills/legion-architect/SKILL.md +10 -7
- package/skills/legion-architect/references/acceptance.md +7 -2
- package/skills/legion-architect/references/decomposition.md +3 -2
- package/skills/legion-architect/references/design-gate.md +9 -1
- package/skills/legion-architect/references/wake-routing.md +5 -5
- package/skills/legion-controller/SKILL.md +5 -2
- package/skills/legion-controller/references/admission.md +10 -8
- package/skills/legion-controller/references/wakes.md +22 -8
- package/skills/legion-worker/SKILL.md +2 -2
- package/skills/legion-worker/references/merge-gate.md +12 -11
- package/skills/legion-worker/references/skip-checks-trailer.md +1 -1
- package/skills/legion-worker/references/tools.md +3 -2
package/dist/dispatch.js
CHANGED
|
@@ -13602,6 +13602,15 @@ var ArtifactVersionEventPayloadSchema = exports_external.object({
|
|
|
13602
13602
|
version: exports_external.object({ number: exports_external.number().optional(), summary: exports_external.string().nullish() }).optional(),
|
|
13603
13603
|
diff: exports_external.string().optional()
|
|
13604
13604
|
});
|
|
13605
|
+
var ArtifactHumanEditedEventPayloadSchema = exports_external.object({
|
|
13606
|
+
artifact_id: exports_external.string().optional(),
|
|
13607
|
+
name: exports_external.string().optional(),
|
|
13608
|
+
from_version: exports_external.number().int().optional(),
|
|
13609
|
+
to_version: exports_external.number().int().optional(),
|
|
13610
|
+
editors: exports_external.array(exports_external.string()).optional(),
|
|
13611
|
+
diff: exports_external.string().optional(),
|
|
13612
|
+
diff_truncated: exports_external.boolean().optional()
|
|
13613
|
+
});
|
|
13605
13614
|
var ArtifactReviewEventPayloadSchema = exports_external.object({
|
|
13606
13615
|
artifact_id: exports_external.string().optional(),
|
|
13607
13616
|
name: exports_external.string().optional(),
|
|
@@ -13857,6 +13866,44 @@ function itemFromSearch(search) {
|
|
|
13857
13866
|
}
|
|
13858
13867
|
return ask === null ? { id, kind: "comment" } : { id, kind: "ask" };
|
|
13859
13868
|
}
|
|
13869
|
+
|
|
13870
|
+
// ../contracts/src/dispatch-block-ref.ts
|
|
13871
|
+
var encoder = new TextEncoder;
|
|
13872
|
+
function encodeBlockId(id) {
|
|
13873
|
+
let encoded = "";
|
|
13874
|
+
for (const character of id) {
|
|
13875
|
+
for (const byte of encoder.encode(character)) {
|
|
13876
|
+
const bare = byte >= 48 && byte <= 57 || byte >= 65 && byte <= 90 || byte >= 97 && byte <= 122 || byte === 45;
|
|
13877
|
+
encoded += bare ? String.fromCharCode(byte) : `%${byte.toString(16).toUpperCase().padStart(2, "0")}`;
|
|
13878
|
+
}
|
|
13879
|
+
}
|
|
13880
|
+
return encoded;
|
|
13881
|
+
}
|
|
13882
|
+
function decodeBlockId(encoded) {
|
|
13883
|
+
if (encoded === "" || encoded.includes("@")) {
|
|
13884
|
+
return;
|
|
13885
|
+
}
|
|
13886
|
+
let id;
|
|
13887
|
+
try {
|
|
13888
|
+
id = decodeURIComponent(encoded);
|
|
13889
|
+
} catch {
|
|
13890
|
+
return;
|
|
13891
|
+
}
|
|
13892
|
+
return id === "" || hasControlCharacter(id) ? undefined : id;
|
|
13893
|
+
}
|
|
13894
|
+
var MAX_BLOCK_PIN = 9223372036854775807n;
|
|
13895
|
+
function parseBlockFragment(encoded) {
|
|
13896
|
+
const at = encoded.indexOf("@");
|
|
13897
|
+
const pin = at === -1 ? undefined : encoded.slice(at + 1).match(/^v([1-9][0-9]*)$/)?.[1];
|
|
13898
|
+
if (at !== -1 && (pin === undefined || BigInt(pin) > MAX_BLOCK_PIN)) {
|
|
13899
|
+
return;
|
|
13900
|
+
}
|
|
13901
|
+
const block = decodeBlockId(at === -1 ? encoded : encoded.slice(0, at));
|
|
13902
|
+
if (block === undefined) {
|
|
13903
|
+
return;
|
|
13904
|
+
}
|
|
13905
|
+
return pin === undefined ? { block } : { block, pin };
|
|
13906
|
+
}
|
|
13860
13907
|
// ../contracts/src/dispatch-snippet.ts
|
|
13861
13908
|
var HTML_ENTITIES = [
|
|
13862
13909
|
["<", "<"],
|
|
@@ -14129,7 +14176,7 @@ var dispatchToolSpecs = [
|
|
|
14129
14176
|
issue: z2.string().describe(ISSUE_REFERENCE).optional(),
|
|
14130
14177
|
project: z2.string().describe("Project key owning the document.").optional(),
|
|
14131
14178
|
artifact: z2.string().describe("Project document artifact id, slug, or filename.").optional(),
|
|
14132
|
-
ref: z2.string().describe("Optional dispatch:// reference (issue, document, message, or ask); appended to the question and rendered as a link.").optional(),
|
|
14179
|
+
ref: z2.string().describe("Optional dispatch:// reference (issue, document, block, message, or ask); appended to the question and rendered as a link.").optional(),
|
|
14133
14180
|
question: z2.string({ max: ASK_QUESTION_MAX }).describe(`${ASK_QUESTION_CONTRACT} At most ${ASK_QUESTION_MAX} characters.`),
|
|
14134
14181
|
options: z2.array(z2.object({
|
|
14135
14182
|
label: z2.string().describe("Selectable option label."),
|
|
@@ -14274,7 +14321,7 @@ var dispatchToolSpecs = [
|
|
|
14274
14321
|
ops: [{ op: "delete_column", block: "table-123", index: 1 }],
|
|
14275
14322
|
precondition: { blocks: [{ id: "table-123", token: "sha256:current-table-token" }] }
|
|
14276
14323
|
},
|
|
14277
|
-
description: "Apply deterministic document edits: replace or delete quoted text, insert markdown at an anchor, retype an identified paragraph or typed block into a schema-declared typed block, delete or move a whole block by its id, or delete a table row or column in place. " + "Do not use it for review feedback or for reading; use dispatch comment, dispatch suggest, or dispatch doc-read instead. " + `For replace, delete, and quote anchors, find text as rendered: inline Markdown (**bold**, \`code\`) is tolerated and must be balanced; a leading '# ' matches a heading at any level. replace is inline: with is the new text of the matched span, so a marker of a different kind from the block's own stays literal text ('4. Design' written into a heading). A with that opens with a marker of the same kind as the matched block's own would write it twice and is INVALID_OP - including prose that merely looks like one ('1999. was a year' into an ordered item), which you write as text by escaping it ('1999\\. was a year'). The exception is a heading rename whose find carried a heading marker: replace(find="## Old", with="## New") gives '## New', and a different level applies only when find named the heading's actual level (find "## Old" with "### New" makes it an h3), since '# ' selects a heading without naming its level. A task item (\`- [ ]\` / \`- [x]\`) is ticked the same way: when find matches from the start of the item's text and with opens with '[x] ' or '[ ] ', the opening sets the item's box and the rest is its new text (replace(find="Write it", with="[x] Write it") ticks it); the same opening over a plain list item or a paragraph stays literal text. Any non-empty with that renders to no text - a line indented four spaces or a tab, which markdown reads as a code block, or whitespace alone - is INVALID_OP rather than a silent deletion; pass an empty with to delete the matched text on purpose - a list item, quote, typed block or footnote definition left holding only the emptied paragraph keeps it. ` + "with cannot open a new block: after a hard line break inside with (two trailing spaces, or a backslash, before the newline) a heading, bullet, '1.'/'1)' ordered, or '>' blockquote marker is INVALID_OP too, since that line would stay escaped text inside the matched block - use insert, plus delete for what it replaces, to add the block. A hard break in with is itself INVALID_OP when the matched text is in a heading or a table cell, which are written on one line. " + "A delete whose find is a block's entire text removes the block (a list emptied of its items goes too); delete with block removes any block by id, and move with block relocates one. A delete or retype that would take an ask block out of the document while its ask is open is refused, with nothing sent. delete_row and delete_column take a table block and a zero-based index, preserving the table block id and refusing to remove cells with open asks or unresolved comments. " + `Insert and move anchors also accept "start", "end", "heading:<exact heading text>", and "block:<id>"; dispatch doc-read --blocks lists every block's id, type, opening words and token, and each table's rows and cells with the indexes delete_row and delete_column take (GET /api/v1/artifacts/{artifact UUID}/blocks serves the same list). ` + "Optionally require the state just read: precondition selects exactly one of a document token from dispatch doc-read, or block {id, token} values from dispatch doc-read --blocks. A block guard must include every block the batch changes; Dispatch resolves quote targets and rejects an uncovered batch rather than applying it. Use a document token for insert or move, which depend on document order. Prefer block tokens when the covered content blocks are independent sections. Tokens include inline marks, so a fresh human comment also makes a stale edit fail. PRECONDITION_FAILED means re-read; EDIT_QUEUE_FULL means back off before retrying. " + "The result carries the document token this edit produced, so a chain of guarded edits passes each result's token as the next edit's precondition with no dispatch doc-read between them. " + "A batch that leaves the document exactly as it was mints no version, named or not, and the result says nothing changed and names each operation that did nothing. " + "A change a browser removes while the edit is in flight is never reported as applied: EDIT_LOST_TO_CONCURRENT_CHANGE means the write was refused and nothing was written, so re-read the document and decide again, as with PRECONDITION_FAILED; lost_ops on a successful result names operations whose text the live document no longer has, because the deletion landed after the version was written. " + "One replace per paragraph: more new paragraphs go in one insert after the last one you rewrote, since two inserts at one anchor come out reversed; read the passage back with dispatch doc-read afterwards. " + `The spec holds requirements, design, and decisions - never progress, status, or timestamps; a record of open items or progress is a document of its own. ${OWNER_REFERENCE} ${SPEC_WRITING_POINTER}`,
|
|
14324
|
+
description: "Apply deterministic document edits: replace or delete quoted text, insert markdown at an anchor, retype an identified paragraph or typed block into a schema-declared typed block, delete or move a whole block by its id, or delete a table row or column in place. " + "Do not use it for review feedback or for reading; use dispatch comment, dispatch suggest, or dispatch doc-read instead. " + `For replace, delete, and quote anchors, find text as rendered: inline Markdown (**bold**, \`code\`) is tolerated and must be balanced; a leading '# ' matches a heading at any level. replace is inline: with is the new text of the matched span, so a marker of a different kind from the block's own stays literal text ('4. Design' written into a heading). A with that opens with a marker of the same kind as the matched block's own would write it twice and is INVALID_OP - including prose that merely looks like one ('1999. was a year' into an ordered item), which you write as text by escaping it ('1999\\. was a year'). The exception is a heading rename whose find carried a heading marker: replace(find="## Old", with="## New") gives '## New', and a different level applies only when find named the heading's actual level (find "## Old" with "### New" makes it an h3), since '# ' selects a heading without naming its level. A task item (\`- [ ]\` / \`- [x]\`) is ticked the same way: when find matches from the start of the item's text and with opens with '[x] ' or '[ ] ', the opening sets the item's box and the rest is its new text (replace(find="Write it", with="[x] Write it") ticks it); the same opening over a plain list item or a paragraph stays literal text. Any non-empty with that renders to no text - a line indented four spaces or a tab, which markdown reads as a code block, or whitespace alone - is INVALID_OP rather than a silent deletion; pass an empty with to delete the matched text on purpose - a list item, quote, typed block or footnote definition left holding only the emptied paragraph keeps it. ` + "with cannot open a new block: after a hard line break inside with (two trailing spaces, or a backslash, before the newline) a heading, bullet, '1.'/'1)' ordered, or '>' blockquote marker is INVALID_OP too, since that line would stay escaped text inside the matched block - use insert, plus delete for what it replaces, to add the block. A hard break in with is itself INVALID_OP when the matched text is in a heading or a table cell, which are written on one line. In a table cell, with is the cell's text: write a | in it bare, in code too, since code whose text has an odd run of backslashes right before a | cannot be stored in a cell and is INVALID_OP, naming the cell. " + "A delete whose find is a block's entire text removes the block (a list emptied of its items goes too); delete with block removes any block by id, and move with block relocates one. A delete or retype that would take an ask block out of the document while its ask is open is refused, with nothing sent. delete_row and delete_column take a table block and a zero-based index, preserving the table block id and refusing to remove cells with open asks or unresolved comments. " + `Insert and move anchors also accept "start", "end", "heading:<exact heading text>", and "block:<id>"; dispatch doc-read --blocks lists every block's id, type, opening words and token, and each table's rows and cells with the indexes delete_row and delete_column take (GET /api/v1/artifacts/{artifact UUID}/blocks serves the same list). ` + "Optionally require the state just read: precondition selects exactly one of a document token from dispatch doc-read, or block {id, token} values from dispatch doc-read --blocks. A block guard must include every block the batch changes; Dispatch resolves quote targets and rejects an uncovered batch rather than applying it. Use a document token for insert or move, which depend on document order. Prefer block tokens when the covered content blocks are independent sections. Tokens include inline marks, so a fresh human comment also makes a stale edit fail. PRECONDITION_FAILED means re-read; EDIT_QUEUE_FULL means back off before retrying. " + "The result carries the document token this edit produced, so a chain of guarded edits passes each result's token as the next edit's precondition with no dispatch doc-read between them. " + "A batch that leaves the document exactly as it was mints no version, named or not, and the result says nothing changed and names each operation that did nothing. " + "A change a browser removes while the edit is in flight is never reported as applied: EDIT_LOST_TO_CONCURRENT_CHANGE means the write was refused and nothing was written, so re-read the document and decide again, as with PRECONDITION_FAILED; lost_ops on a successful result names operations whose text the live document no longer has, because the deletion landed after the version was written. " + "One replace per paragraph: more new paragraphs go in one insert after the last one you rewrote, since two inserts at one anchor come out reversed; read the passage back with dispatch doc-read afterwards. " + "A block id written as {#id} longer than 256 bytes is stored, but its block is no graph node, so no reference reaches it. " + `The spec holds requirements, design, and decisions - never progress, status, or timestamps; a record of open items or progress is a document of its own. ${OWNER_REFERENCE} ${SPEC_WRITING_POINTER}`,
|
|
14278
14325
|
arguments: (z2) => ({
|
|
14279
14326
|
issue: z2.string().describe(ISSUE_REFERENCE).optional(),
|
|
14280
14327
|
project: z2.string().describe("Project key owning the document.").optional(),
|
|
@@ -14334,7 +14381,7 @@ var dispatchToolSpecs = [
|
|
|
14334
14381
|
name: "dispatch_artifact",
|
|
14335
14382
|
example: { issue: "DSP-1", name: "design.md", content: `# Design
|
|
14336
14383
|
` },
|
|
14337
|
-
description: "Attach a local file or inline text as an issue artifact or project document. Do not use it to edit a live document; use " + "dispatch doc-edit instead. Never upload a document's own name to change it (spec.md replaces the spec whole); edit it with dispatch doc-edit. Uploading the same name again makes its next version. Exactly one of path or content is required; a markdown document is at most 1 MiB and any other file at most 25 MiB. " + "Markdown is also refused with 413 CAP_EXCEEDED when it makes more than 65,536 elements (a block weighs 3, and an empty list item, quote, footnote definition or typed block 3 more for the empty paragraph it holds; a table cell 4, a hard line break 3, an image 3, a piece of inline HTML 2, an autolink 2, a footnote reference 2; inline syntax, marks, lines of text and backslash escapes or character references 1 each), or when a new version would leave the document's stored markdown (what its text reads back as) longer than 1 MiB or making more than 65,536 elements, and longer or heavier than before; shorten it or split it across documents. " + "Markdown holding an ask block whose body breaks its content rule (one or more question paragraphs, then at most one bullet list of options, last) is refused with 400 INVALID_ASK_BLOCK; a new version of a document is held to it only for the asks it writes or changes. " + `${OWNER_REFERENCE}`,
|
|
14384
|
+
description: "Attach a local file or inline text as an issue artifact or project document. Do not use it to edit a live document; use " + "dispatch doc-edit instead. Never upload a document's own name to change it (spec.md replaces the spec whole); edit it with dispatch doc-edit. Uploading the same name again makes its next version. Exactly one of path or content is required; a markdown document is at most 1 MiB and any other file at most 25 MiB. " + "Markdown is also refused with 413 CAP_EXCEEDED when it makes more than 65,536 elements (a block weighs 3, and an empty list item, quote, footnote definition or typed block 3 more for the empty paragraph it holds; a table cell 4, a hard line break 3, an image 3, a piece of inline HTML 2, an autolink 2, a footnote reference 2; inline syntax, marks, lines of text and backslash escapes or character references 1 each), or when a new version would leave the document's stored markdown (what its text reads back as) longer than 1 MiB or making more than 65,536 elements, and longer or heavier than before; shorten it or split it across documents. " + "In a table row, write every | in a cell as \\|, in code too: a | after two backslashes ends the cell, and a row with more cells than its table is refused. " + "Markdown holding an ask block whose body breaks its content rule (one or more question paragraphs, then at most one bullet list of options, last) is refused with 400 INVALID_ASK_BLOCK; a new version of a document is held to it only for the asks it writes or changes. " + `${OWNER_REFERENCE}`,
|
|
14338
14385
|
arguments: (z2) => ({
|
|
14339
14386
|
issue: z2.string().describe(ISSUE_REFERENCE).optional(),
|
|
14340
14387
|
project: z2.string().describe("Project key for an unlinked document.").optional(),
|
|
@@ -14354,12 +14401,12 @@ var dispatchToolSpecs = [
|
|
|
14354
14401
|
{
|
|
14355
14402
|
name: "dispatch_read",
|
|
14356
14403
|
example: { issue: "DSP-1" },
|
|
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,
|
|
14404
|
+
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. " + "A block read prints `Block:`, `Document:`, `Changed in version:` and `Text:`, then those two sections; a pinned one adds " + "the block's text at that version and whether it is unchanged, changed or removed since, and an absent block, unpinned, " + "reads `No block <id> in <document>.` " + "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,
|
|
14358
14405
|
arguments: (z2) => ({
|
|
14359
14406
|
issue: z2.string().describe(ISSUE_REFERENCE).optional(),
|
|
14360
14407
|
project: z2.string().describe("Project key owning the document.").optional(),
|
|
14361
14408
|
artifact: z2.string().describe("Document artifact id, slug, or filename: one of the issue's, or a project document.").optional(),
|
|
14362
|
-
ref: z2.string().describe("Optional dispatch:// reference: dispatch://KEY, dispatch://KEY/spec, " + "dispatch://KEY/artifact/<slug>[@vN], dispatch://KEY/ask/<id>, dispatch://KEY/comment/<id>, " + "dispatch://KEY/message/<id>, dispatch://PROJECT/artifact/<slug>[@vN], and its " + "/ask/<id> and /comment/<id>; or the dashboard URL of one.").optional(),
|
|
14409
|
+
ref: z2.string().describe("Optional dispatch:// reference: dispatch://KEY, dispatch://KEY/spec, " + "dispatch://KEY/artifact/<slug>[@vN], dispatch://KEY/ask/<id>, dispatch://KEY/comment/<id>, " + "dispatch://KEY/message/<id>, dispatch://PROJECT/artifact/<slug>[@vN], and its " + "/ask/<id> and /comment/<id>; or the dashboard URL of one. A block: " + "dispatch://KEY/spec#b-<block id>[@vN], dispatch://KEY/artifact/<slug>#b-<block id>[@vN] or " + "dispatch://PROJECT/artifact/<slug>#b-<block id>[@vN], the id percent-encoded except ASCII " + "letters, digits and -.").optional(),
|
|
14363
14410
|
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
14411
|
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
14412
|
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()
|
|
@@ -15723,7 +15770,27 @@ function dispatchDocumentRef(owner, slug) {
|
|
|
15723
15770
|
function dispatchChildRef(ownerRef, kind, id) {
|
|
15724
15771
|
return `${ownerRef}/${kind}/${id}`;
|
|
15725
15772
|
}
|
|
15773
|
+
function parseBlockRef(document, fragment) {
|
|
15774
|
+
const target = parseBlockFragment(fragment);
|
|
15775
|
+
const parsed = parseDispatchRef(document);
|
|
15776
|
+
if (target === undefined || parsed === null || parsed.version !== undefined || parsed.kind !== "spec" && parsed.kind !== "artifact") {
|
|
15777
|
+
return null;
|
|
15778
|
+
}
|
|
15779
|
+
return {
|
|
15780
|
+
owner: parsed.owner,
|
|
15781
|
+
kind: "block",
|
|
15782
|
+
id: parsed.id,
|
|
15783
|
+
block: target.block,
|
|
15784
|
+
document,
|
|
15785
|
+
...parsed.owner.kind === "project" ? { artifact: parsed.id } : {},
|
|
15786
|
+
...target.pin === undefined ? {} : { pin: target.pin }
|
|
15787
|
+
};
|
|
15788
|
+
}
|
|
15726
15789
|
function parseDispatchRef(ref) {
|
|
15790
|
+
const hash2 = ref.indexOf("#");
|
|
15791
|
+
if (hash2 !== -1 && ref.startsWith("b-", hash2 + 1)) {
|
|
15792
|
+
return parseBlockRef(ref.slice(0, hash2), ref.slice(hash2 + 3));
|
|
15793
|
+
}
|
|
15727
15794
|
const projectDocument = ref.match(/^dispatch:\/\/([A-Z][A-Z0-9]{1,9})\/artifact\/([^/@]+)(?:@v(\d+))?(?:\/(ask|comment)\/([^/]+))?$/);
|
|
15728
15795
|
if (projectDocument) {
|
|
15729
15796
|
const [, project, artifact2, version3, targetKind, targetID] = projectDocument;
|
|
@@ -16260,6 +16327,13 @@ function subscriptionCovers(topic, owner) {
|
|
|
16260
16327
|
return false;
|
|
16261
16328
|
}
|
|
16262
16329
|
|
|
16330
|
+
// ../envoy-client/src/human-edit.ts
|
|
16331
|
+
function humanEditHead(edit) {
|
|
16332
|
+
const editors = edit.editors ?? [];
|
|
16333
|
+
const by = editors.length === 0 ? "" : `, edited by ${editors.join(", ")}`;
|
|
16334
|
+
return `${edit.name ?? "document"} v${edit.from_version ?? "?"} to v${edit.to_version ?? "?"}${by}`;
|
|
16335
|
+
}
|
|
16336
|
+
|
|
16263
16337
|
// ../envoy-client/src/search-answer.ts
|
|
16264
16338
|
function pageSummaryText(offset, count, total) {
|
|
16265
16339
|
return `showing ${offset + 1}-${offset + count} of ${total}`;
|
|
@@ -16856,9 +16930,13 @@ function dispatchRefFromUrl(value, serverUrl) {
|
|
|
16856
16930
|
const value2 = url2.searchParams.get(name);
|
|
16857
16931
|
return value2 !== null && /^[1-9][0-9]*$/.test(value2) ? `@v${value2}` : "";
|
|
16858
16932
|
};
|
|
16933
|
+
const blockOf = (versionName) => {
|
|
16934
|
+
const id = url2.hash.startsWith("#b-") ? decodeBlockId(url2.hash.slice(3)) : undefined;
|
|
16935
|
+
return id === undefined || url2.searchParams.get(versionName) ? "" : `#b-${encodeBlockId(id)}`;
|
|
16936
|
+
};
|
|
16859
16937
|
const issuePage = url2.pathname.match(/^\/issues\/([A-Z][A-Z0-9]{1,9}-[1-9][0-9]*)(?:\/(spec|log|conversation|activity|children)|\/artifacts\/([^/]+)|\/asks\/([^/]+)|\/comments\/([^/]+)|\/messages\/([^/]+))?\/?$/);
|
|
16860
16938
|
if (issuePage) {
|
|
16861
|
-
const [, key, page, artifact, ask, comment, message] = issuePage;
|
|
16939
|
+
const [, key = "", page, artifact, ask, comment, message] = issuePage;
|
|
16862
16940
|
const version2 = versionOf("v");
|
|
16863
16941
|
if (page === "spec" || artifact !== undefined) {
|
|
16864
16942
|
const item2 = itemFromSearch(url2.search);
|
|
@@ -16869,10 +16947,13 @@ function dispatchRefFromUrl(value, serverUrl) {
|
|
|
16869
16947
|
}
|
|
16870
16948
|
if (page === "spec" && version2 !== "")
|
|
16871
16949
|
return `dispatch://${key}/artifact/spec${version2}`;
|
|
16950
|
+
if (page === "spec")
|
|
16951
|
+
return `dispatch://${key}/spec${blockOf("v")}`;
|
|
16872
16952
|
if (page !== undefined)
|
|
16873
16953
|
return `dispatch://${key}/${page === "conversation" ? "log" : page}`;
|
|
16874
16954
|
if (artifact !== undefined) {
|
|
16875
|
-
|
|
16955
|
+
const slug2 = decodeURIComponent(artifact);
|
|
16956
|
+
return `dispatch://${key}/artifact/${slug2}${version2}${blockOf("v")}`;
|
|
16876
16957
|
}
|
|
16877
16958
|
if (ask !== undefined)
|
|
16878
16959
|
return `dispatch://${key}/ask/${ask}`;
|
|
@@ -16895,25 +16976,26 @@ function dispatchRefFromUrl(value, serverUrl) {
|
|
|
16895
16976
|
if (!documentPage)
|
|
16896
16977
|
return;
|
|
16897
16978
|
const [, project, slug] = documentPage;
|
|
16898
|
-
const
|
|
16979
|
+
const decodedSlug = decodeURIComponent(slug ?? "");
|
|
16980
|
+
const document = `dispatch://${project}/artifact/${decodedSlug}`;
|
|
16899
16981
|
const item = itemFromSearch(url2.search);
|
|
16900
16982
|
if (item === null)
|
|
16901
16983
|
return;
|
|
16902
|
-
return item === undefined ? `${document}${versionOf("version")}` : `${document}/${item.kind}/${item.id}`;
|
|
16984
|
+
return item === undefined ? `${document}${versionOf("version")}${blockOf("version")}` : `${document}/${item.kind}/${item.id}`;
|
|
16903
16985
|
}
|
|
16904
|
-
var refGrammarProblem = "ref must be a valid dispatch:// reference such as dispatch://KEY-1, " + "dispatch://KEY-1/ask/<uuid>, dispatch://KEY-1/comment/<uuid>, " + "dispatch://KEY-1/message/<uuid>, dispatch://KEY-1/artifact/<slug>, " + "dispatch://PROJECT/artifact/<document-ref> (an artifact id, slug, or filename), or " + "dispatch://agent/<session id>/artifact/<slug> (a picture in a conversation on the Agents page, " + "for dispatch doc-read); a dashboard URL on this Dispatch server is accepted too";
|
|
16986
|
+
var refGrammarProblem = "ref must be a valid dispatch:// reference such as dispatch://KEY-1, " + "dispatch://KEY-1/ask/<uuid>, dispatch://KEY-1/comment/<uuid>, " + "dispatch://KEY-1/message/<uuid>, dispatch://KEY-1/artifact/<slug>, " + "dispatch://PROJECT/artifact/<document-ref> (an artifact id, slug, or filename), " + "dispatch://KEY-1/spec#b-<block id>, dispatch://KEY-1/artifact/<slug>#b-<block id> or " + "dispatch://PROJECT/artifact/<slug>#b-<block id> (one block of a document, its id " + "percent-encoded, optionally pinned to a version of the document with @v<N> after it; for " + "dispatch read), or " + "dispatch://agent/<session id>/artifact/<slug> (a picture in a conversation on the Agents page, " + "for dispatch doc-read); a dashboard URL on this Dispatch server is accepted too";
|
|
16905
16987
|
var ownerRequiredProblem = "issue is required; supply issue or set LEGION_ISSUE";
|
|
16906
16988
|
function innerRefProblem(tool, ref, refText) {
|
|
16907
|
-
if (ref.kind !== "ask" && ref.kind !== "comment" && ref.kind !== "message" && ref.kind !== "log" && ref.kind !== "children") {
|
|
16989
|
+
if (ref.kind !== "ask" && ref.kind !== "comment" && ref.kind !== "message" && ref.kind !== "log" && ref.kind !== "children" && ref.kind !== "block") {
|
|
16908
16990
|
return;
|
|
16909
16991
|
}
|
|
16910
16992
|
if (tool === "dispatch_read" || tool === "dispatch_ask")
|
|
16911
16993
|
return;
|
|
16912
16994
|
const owner = refOwnerName(ref);
|
|
16913
|
-
const
|
|
16914
|
-
const ownerArguments = ref.owner.kind === "issue" ? `issue ${ref.owner.issue}${
|
|
16995
|
+
const documentArgument = ref.kind === "block" && tool !== "dispatch_comment" ? ` and artifact ${ref.id}` : tool === "dispatch_suggest" ? " and artifact <the document's slug>" : "";
|
|
16996
|
+
const ownerArguments = ref.owner.kind === "issue" ? `issue ${ref.owner.issue}${documentArgument}` : `project ${ref.owner.project} and artifact ${ref.artifact}`;
|
|
16915
16997
|
const fix = tool === "dispatch_comment" && ref.kind === "ask" ? `reply under it with reply_to_ask ${ref.id} and ${ownerArguments}` : tool === "dispatch_comment" && ref.kind === "comment" ? `reply in its thread with reply_to ${ref.id} and ${ownerArguments}` : `read it with dispatch read, or name ${owner} with ${ownerArguments}`;
|
|
16916
|
-
const item = ref.kind === "ask" ? "an ask" : ref.kind === "log" ? "the event log" : ref.kind === "children" ? "the children" : `a ${ref.kind}`;
|
|
16998
|
+
const item = ref.kind === "ask" ? "an ask" : ref.kind === "log" ? "the event log" : ref.kind === "children" ? "the children" : ref.kind === "block" ? `block ${ref.block}` : `a ${ref.kind}`;
|
|
16917
16999
|
return `ref ${refText} names ${item} on ${owner}; dispatch ${commandName(tool)} would act on ${owner} and drop the ${ref.kind}: ${fix}`;
|
|
16918
17000
|
}
|
|
16919
17001
|
var documentItemPattern = /^dispatch:\/\/([A-Z][A-Z0-9]{1,9}-[1-9][0-9]*)\/artifact\/[^/@]+(?:@v\d+)?\/(ask|comment)\/([^/]+)$/;
|
|
@@ -16940,7 +17022,7 @@ function ownerConflictProblems(tool, args, parsedRef, refText) {
|
|
|
16940
17022
|
const artifact = optionalString(args, "artifact");
|
|
16941
17023
|
const version2 = optionalNumber(args, "version");
|
|
16942
17024
|
const ref = tool === "dispatch_ask" && (issue2 !== undefined || project !== undefined) ? null : parsedRef;
|
|
16943
|
-
const refDocument = ref === null ? undefined : ref.owner.kind === "project" ? ref.artifact ?? ref.id : ref.kind === "spec" || ref.kind === "artifact" ? ref.id : undefined;
|
|
17025
|
+
const refDocument = ref === null ? undefined : ref.owner.kind === "project" ? ref.artifact ?? ref.id : ref.kind === "spec" || ref.kind === "artifact" || ref.kind === "block" ? ref.id : undefined;
|
|
16944
17026
|
if (ref !== null && refText !== undefined) {
|
|
16945
17027
|
const refOwner = refOwnerName(ref);
|
|
16946
17028
|
if (issue2 !== undefined && (ref.owner.kind !== "issue" || nativeIssueKeyPattern.test(issue2) && issue2 !== ref.owner.issue)) {
|
|
@@ -16968,7 +17050,7 @@ function ownerConflictProblems(tool, args, parsedRef, refText) {
|
|
|
16968
17050
|
}
|
|
16969
17051
|
const projectOwned = project !== undefined || ref?.owner.kind === "project";
|
|
16970
17052
|
if (tool === "dispatch_comment" && !projectOwned && optionalString(args, "quote") === undefined) {
|
|
16971
|
-
const document = artifact ?? refDocument;
|
|
17053
|
+
const document = artifact ?? (ref?.kind === "block" ? undefined : refDocument);
|
|
16972
17054
|
if (document !== undefined) {
|
|
16973
17055
|
problems.push(`${command} posts on the issue unless quote anchors it in a document, so document ${document} would be dropped: add --quote to comment on a passage of it, or name only the issue`);
|
|
16974
17056
|
}
|
|
@@ -17341,22 +17423,23 @@ function issueSummary(issue2, events, references, graph, linkBase, titles) {
|
|
|
17341
17423
|
].join(`
|
|
17342
17424
|
`);
|
|
17343
17425
|
}
|
|
17344
|
-
function referenceLines(
|
|
17345
|
-
if (typeof
|
|
17346
|
-
return [`- ${
|
|
17347
|
-
if (edges.length === 0)
|
|
17426
|
+
function referenceLines(read) {
|
|
17427
|
+
if (typeof read === "string")
|
|
17428
|
+
return [`- ${read}`];
|
|
17429
|
+
if (read.edges.length === 0)
|
|
17348
17430
|
return ["- none"];
|
|
17349
|
-
return edges.map((edge) => {
|
|
17431
|
+
return read.edges.map((edge) => {
|
|
17350
17432
|
const excerpt2 = edge.excerpt === undefined ? "" : `${textHead(edge.excerpt.text)} \xB7 `;
|
|
17351
|
-
|
|
17433
|
+
const block = edge.block === undefined ? "" : ` (block ${edge.block.ref ?? edge.block.id})`;
|
|
17434
|
+
return `- ${edge.kind} ${edge.node.kind} ${edge.node.ref ?? edge.node.id} (${excerpt2}${edge.created_at})${block}`;
|
|
17352
17435
|
});
|
|
17353
17436
|
}
|
|
17354
17437
|
function unavailableReason(error48) {
|
|
17355
17438
|
return dispatchAnswered(error48, 404) ? "unavailable" : `unavailable: ${messageFor(error48)}`;
|
|
17356
17439
|
}
|
|
17357
|
-
async function
|
|
17440
|
+
async function graphReferences(client, query) {
|
|
17358
17441
|
try {
|
|
17359
|
-
return
|
|
17442
|
+
return await client.getReferences(query);
|
|
17360
17443
|
} catch (error48) {
|
|
17361
17444
|
return unavailableReason(error48);
|
|
17362
17445
|
}
|
|
@@ -17370,10 +17453,50 @@ async function issueReferencesOrUnavailable(client, key) {
|
|
|
17370
17453
|
}
|
|
17371
17454
|
async function graphSections(client, ref) {
|
|
17372
17455
|
const [incoming, outgoing] = await Promise.all([
|
|
17373
|
-
|
|
17374
|
-
|
|
17456
|
+
graphReferences(client, { to: ref }),
|
|
17457
|
+
graphReferences(client, { from: ref })
|
|
17375
17458
|
]);
|
|
17376
|
-
return
|
|
17459
|
+
return graphSectionLines(incoming, outgoing);
|
|
17460
|
+
}
|
|
17461
|
+
function graphSectionLines(incoming, outgoing) {
|
|
17462
|
+
return [
|
|
17463
|
+
...typeof incoming === "string" ? [] : nodeLine(incoming.node),
|
|
17464
|
+
"Referenced by:",
|
|
17465
|
+
...referenceLines(incoming),
|
|
17466
|
+
"Links:",
|
|
17467
|
+
...referenceLines(outgoing)
|
|
17468
|
+
];
|
|
17469
|
+
}
|
|
17470
|
+
function nodeLine(node) {
|
|
17471
|
+
if (node.made_by === undefined)
|
|
17472
|
+
return [];
|
|
17473
|
+
const fact = (by, time3) => `${by === undefined || by.length === 0 ? "nobody recorded" : by.map(actorText).join(", ")}${time3 == null ? "" : ` at ${time3}`}`;
|
|
17474
|
+
const made = fact(node.made_by, node.made_at);
|
|
17475
|
+
const changed = fact(node.changed_by, node.changed_at);
|
|
17476
|
+
const { parent } = node;
|
|
17477
|
+
const partOf = parent == null ? "" : ` \xB7 part of ${parent.ref ?? `${parent.kind} ${parent.id}`}${node.parent_version == null ? "" : ` (version ${node.parent_version})`}`;
|
|
17478
|
+
return [
|
|
17479
|
+
`Node: ${node.kind} ${node.ref ?? node.id} \xB7 made by ${made} \xB7 changed by ${changed}${partOf}`
|
|
17480
|
+
];
|
|
17481
|
+
}
|
|
17482
|
+
function blockLines(node, ref) {
|
|
17483
|
+
const head = [
|
|
17484
|
+
`Block: ${node.block_id ?? ref.block}`,
|
|
17485
|
+
`Document: ${node.document ?? ref.document}`,
|
|
17486
|
+
...node.changed_version === undefined ? [] : [`Changed in version: ${node.changed_version}`],
|
|
17487
|
+
...node.text === undefined ? [] : ["Text:", node.text]
|
|
17488
|
+
];
|
|
17489
|
+
const { pin } = node;
|
|
17490
|
+
if (pin === undefined)
|
|
17491
|
+
return head;
|
|
17492
|
+
const state = pin.state === "unchanged" ? `Unchanged since version ${pin.version}.` : pin.state === "changed" ? `Changed since version ${pin.version}; last changed in version ${node.changed_version}.` : `Removed in version ${pin.removed_version}.`;
|
|
17493
|
+
return [
|
|
17494
|
+
...head,
|
|
17495
|
+
`Pinned to version: ${pin.version}`,
|
|
17496
|
+
state,
|
|
17497
|
+
`Text at version ${pin.version}:`,
|
|
17498
|
+
pin.text
|
|
17499
|
+
];
|
|
17377
17500
|
}
|
|
17378
17501
|
function logSummary(issue2, events) {
|
|
17379
17502
|
return [
|
|
@@ -17408,6 +17531,8 @@ function eventHead(event) {
|
|
|
17408
17531
|
return textHead(event.payload.body);
|
|
17409
17532
|
case "artifact.version":
|
|
17410
17533
|
return textHead(`${event.payload.name} v${event.payload.version.number}${event.payload.version.summary ? `: ${event.payload.version.summary}` : ""}`);
|
|
17534
|
+
case "artifact.human_edited":
|
|
17535
|
+
return textHead(humanEditHead(event.payload));
|
|
17411
17536
|
case "issue.created":
|
|
17412
17537
|
case "issue.updated":
|
|
17413
17538
|
case "issue.closed":
|
|
@@ -18740,6 +18865,27 @@ ${trailer.join(`
|
|
|
18740
18865
|
...showImages(pictures3)
|
|
18741
18866
|
};
|
|
18742
18867
|
}
|
|
18868
|
+
if (ownerArguments.ref?.kind === "block") {
|
|
18869
|
+
const ref = ownerArguments.ref;
|
|
18870
|
+
const blockRef = stringArg(args, "ref");
|
|
18871
|
+
const [incoming, outgoing] = await Promise.all([
|
|
18872
|
+
client.getReferences({ to: blockRef }).catch((error48) => {
|
|
18873
|
+
if (ref.pin === undefined && dispatchAnswered(error48, 404)) {
|
|
18874
|
+
throw new Error(`No block ${ref.block} in ${ref.document}.`);
|
|
18875
|
+
}
|
|
18876
|
+
throw error48;
|
|
18877
|
+
}),
|
|
18878
|
+
graphReferences(client, { from: blockRef })
|
|
18879
|
+
]);
|
|
18880
|
+
return {
|
|
18881
|
+
text: [...blockLines(incoming.node, ref), ...graphSectionLines(incoming, outgoing)].join(`
|
|
18882
|
+
`),
|
|
18883
|
+
details: {
|
|
18884
|
+
...ref.owner.kind === "project" ? { project: ref.owner.project } : { issue: ref.owner.issue },
|
|
18885
|
+
block: incoming.node.block_id ?? ref.block
|
|
18886
|
+
}
|
|
18887
|
+
};
|
|
18888
|
+
}
|
|
18743
18889
|
const documentReference = optionalString(args, "artifact");
|
|
18744
18890
|
if (documentOwner().kind === "project" || documentReference !== undefined) {
|
|
18745
18891
|
const resolved = await resolveDocument(documentOwner(), documentReference);
|
|
@@ -19680,6 +19826,7 @@ function sessionEnvoySettings(file2, env, options) {
|
|
|
19680
19826
|
// ../envoy-client/src/transport.ts
|
|
19681
19827
|
var DEFAULT_TIMEOUT_MS = 5000;
|
|
19682
19828
|
var RETRY_DELAY_MS = 250;
|
|
19829
|
+
var REPLAY_TIMEOUT_MS = 1e4;
|
|
19683
19830
|
var InterestWireSchema = exports_external.object({
|
|
19684
19831
|
session_id: exports_external.string(),
|
|
19685
19832
|
machine_id: exports_external.string(),
|
|
@@ -19714,12 +19861,33 @@ var RoleHeldWireSchema = exports_external.object({
|
|
|
19714
19861
|
});
|
|
19715
19862
|
var ErrorWireSchema = exports_external.object({
|
|
19716
19863
|
error: exports_external.string(),
|
|
19864
|
+
code: exports_external.string().optional(),
|
|
19717
19865
|
expected: exports_external.array(exports_external.string()).optional()
|
|
19718
19866
|
});
|
|
19719
19867
|
var EnvelopeResponseSchema = EnvelopeSchema.extend({
|
|
19720
19868
|
recipient: exports_external.string().optional(),
|
|
19721
19869
|
holder: exports_external.string().optional()
|
|
19722
19870
|
});
|
|
19871
|
+
var ReplayWireSchema = exports_external.object({
|
|
19872
|
+
stream: exports_external.object({
|
|
19873
|
+
id: exports_external.string().min(1).optional(),
|
|
19874
|
+
created: exports_external.string(),
|
|
19875
|
+
first_seq: exports_external.number().int().nonnegative(),
|
|
19876
|
+
last_seq: exports_external.number().int().nonnegative()
|
|
19877
|
+
}),
|
|
19878
|
+
subjects: exports_external.array(exports_external.object({
|
|
19879
|
+
subject: exports_external.string(),
|
|
19880
|
+
messages: exports_external.array(exports_external.object({
|
|
19881
|
+
seq: exports_external.number().int().positive(),
|
|
19882
|
+
subject: exports_external.string(),
|
|
19883
|
+
time: exports_external.string(),
|
|
19884
|
+
data: exports_external.string()
|
|
19885
|
+
})),
|
|
19886
|
+
next_after: exports_external.number().int().nonnegative(),
|
|
19887
|
+
more: exports_external.boolean(),
|
|
19888
|
+
refused: exports_external.string().optional()
|
|
19889
|
+
}))
|
|
19890
|
+
});
|
|
19723
19891
|
function expandSubscriptionTopics(topics) {
|
|
19724
19892
|
const expanded = new Set;
|
|
19725
19893
|
for (const topic of topics) {
|
|
@@ -19742,6 +19910,7 @@ class EnvoyApiError extends Error {
|
|
|
19742
19910
|
details;
|
|
19743
19911
|
name = "EnvoyApiError";
|
|
19744
19912
|
expected;
|
|
19913
|
+
code;
|
|
19745
19914
|
constructor(details) {
|
|
19746
19915
|
let parsed;
|
|
19747
19916
|
try {
|
|
@@ -19752,16 +19921,18 @@ class EnvoyApiError extends Error {
|
|
|
19752
19921
|
super(parsed === undefined ? `${details.method} ${details.url} failed with ${details.status}: ${details.responseBody}` : `${parsed.error}${parsed.expected === undefined ? "" : ` (expected: ${parsed.expected.join(", ")})`}`);
|
|
19753
19922
|
this.details = details;
|
|
19754
19923
|
this.expected = parsed?.expected;
|
|
19924
|
+
this.code = parsed?.code;
|
|
19755
19925
|
}
|
|
19756
19926
|
}
|
|
19757
19927
|
function createEnvoyClient(config2) {
|
|
19758
19928
|
const baseUrl = normalizeEnvoyUrl(config2.baseUrl);
|
|
19759
19929
|
const timeoutMs = config2.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
19760
19930
|
const apiToken = config2.token;
|
|
19761
|
-
const request = async (path2, init) => {
|
|
19931
|
+
const request = async (path2, init, options = {}) => {
|
|
19762
19932
|
const url2 = `${baseUrl}${path2}`;
|
|
19763
19933
|
const attempts = config2.retry === false ? 1 : 2;
|
|
19764
|
-
|
|
19934
|
+
const tries = options.retry === false ? 1 : attempts;
|
|
19935
|
+
for (let attempt = 0;attempt < tries; attempt += 1) {
|
|
19765
19936
|
let response;
|
|
19766
19937
|
try {
|
|
19767
19938
|
const headers = new Headers(init.headers);
|
|
@@ -19770,10 +19941,10 @@ function createEnvoyClient(config2) {
|
|
|
19770
19941
|
response = await config2.fetch(url2, {
|
|
19771
19942
|
...init,
|
|
19772
19943
|
headers,
|
|
19773
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
19944
|
+
signal: AbortSignal.timeout(options.timeoutMs ?? timeoutMs)
|
|
19774
19945
|
});
|
|
19775
19946
|
} catch (error49) {
|
|
19776
|
-
if (attempt + 1 <
|
|
19947
|
+
if (attempt + 1 < tries) {
|
|
19777
19948
|
await waitForRetry();
|
|
19778
19949
|
continue;
|
|
19779
19950
|
}
|
|
@@ -19788,7 +19959,7 @@ function createEnvoyClient(config2) {
|
|
|
19788
19959
|
status: response.status,
|
|
19789
19960
|
responseBody
|
|
19790
19961
|
});
|
|
19791
|
-
if (response.status >= 500 && attempt + 1 <
|
|
19962
|
+
if (response.status >= 500 && attempt + 1 < tries) {
|
|
19792
19963
|
await waitForRetry();
|
|
19793
19964
|
continue;
|
|
19794
19965
|
}
|
|
@@ -19796,11 +19967,11 @@ function createEnvoyClient(config2) {
|
|
|
19796
19967
|
}
|
|
19797
19968
|
throw new Error("Envoy request exhausted retries");
|
|
19798
19969
|
};
|
|
19799
|
-
const post = (path2, body) => request(path2, {
|
|
19970
|
+
const post = (path2, body, options) => request(path2, {
|
|
19800
19971
|
method: "POST",
|
|
19801
19972
|
headers: { "Content-Type": "application/json" },
|
|
19802
19973
|
body: JSON.stringify(body)
|
|
19803
|
-
});
|
|
19974
|
+
}, options);
|
|
19804
19975
|
return {
|
|
19805
19976
|
subscribe: async (input) => InterestWireSchema.parse(JSON.parse(await post("/v1/interests/subscribe", {
|
|
19806
19977
|
session_id: input.sessionID,
|
|
@@ -19886,7 +20057,12 @@ function createEnvoyClient(config2) {
|
|
|
19886
20057
|
search.set("title", input.title);
|
|
19887
20058
|
const query = search.size === 0 ? "" : `?${search.toString()}`;
|
|
19888
20059
|
return SessionWireSchema.array().parse(JSON.parse(await request(`/v1/sessions${query}`, {})));
|
|
19889
|
-
}
|
|
20060
|
+
},
|
|
20061
|
+
replay: async (input) => ReplayWireSchema.parse(JSON.parse(await post("/v1/replay", {
|
|
20062
|
+
session_id: input.sessionID,
|
|
20063
|
+
subjects: input.subjects.map((cursor) => cursor.after === undefined ? { subject: cursor.subject } : { subject: cursor.subject, after: cursor.after }),
|
|
20064
|
+
...input.maxMessages === undefined ? {} : { max_messages: input.maxMessages }
|
|
20065
|
+
}, { timeoutMs: REPLAY_TIMEOUT_MS, retry: false })))
|
|
19890
20066
|
};
|
|
19891
20067
|
}
|
|
19892
20068
|
function waitForRetry() {
|