@sjawhar/opencode-legion-envoy 9.7.0 → 9.8.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/dispatch.js
CHANGED
|
@@ -14663,7 +14663,7 @@ var dispatchToolSpecs = [
|
|
|
14663
14663
|
{
|
|
14664
14664
|
name: "dispatch_doc_read",
|
|
14665
14665
|
example: { issue: "DSP-1" },
|
|
14666
|
-
description: "Read a live document or a named document version, or the text of an uploaded file at its latest or named version. " + "Do not use it for issue status, asks, or events; " + "use dispatch read instead. Supply ref, issue, or project plus artifact; issue plus an omitted artifact reads the primary document. " + "A live read returns its document token for an optional dispatch doc-edit precondition. With blocks it lists the live document's blocks instead of its markdown, in document order: each block's id, type, token, anchored comments and asks, and opening words, and under a table each row by the index delete_row takes and each cell by its row and the column delete_column takes; block ids, block tokens and those indexes are what dispatch doc-edit takes. " + "A picture (an uploaded PNG, JPEG, GIF or WebP of at most 3,750,000 bytes, 5 MB once base64-encoded) comes back as an image you see, with its name, type, size and version, every time you ask, including one a read already showed this session; " + "any other file that is not UTF-8 text is described, with the route that serves its bytes. " + OWNER_REFERENCE,
|
|
14666
|
+
description: "Read a live document or a named document version, or the text of an uploaded file at its latest or named version. " + "Do not use it for issue status, asks, or events; " + "use dispatch read instead. Supply ref, issue, or project plus artifact; issue plus an omitted artifact reads the primary document. " + "A live read returns its document token for an optional dispatch doc-edit precondition. With blocks it lists the live document's blocks instead of its markdown, in document order: each block's id, type, token, anchored comments and asks, and opening words, and under a table each row by the index delete_row takes and each cell by its row and the column delete_column takes; block ids, block tokens and those indexes are what dispatch doc-edit takes. " + "After the markdown it prints every open thread anchored on the document in full: an open ask with its id and question and each reply's author, time and text, and a comment thread with its root's id, author, quote and text and each reply's author, time and text, in order; a resolved thread, and an ask that is answered or resolved, is not printed. " + "A picture (an uploaded PNG, JPEG, GIF or WebP of at most 3,750,000 bytes, 5 MB once base64-encoded) comes back as an image you see, with its name, type, size and version, every time you ask, including one a read already showed this session; " + "any other file that is not UTF-8 text is described, with the route that serves its bytes. " + OWNER_REFERENCE,
|
|
14667
14667
|
arguments: (z) => ({
|
|
14668
14668
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
14669
14669
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
@@ -15933,8 +15933,8 @@ class DispatchClient {
|
|
|
15933
15933
|
async resolveComment(id, actor) {
|
|
15934
15934
|
return this.#json("POST", ["api", "v1", "comments", id, "resolve"], { actor });
|
|
15935
15935
|
}
|
|
15936
|
-
async getComments(issue
|
|
15937
|
-
return this.#json("GET", ["api", "v1", "issues", await this.#resolveIssue(issue), "comments"]
|
|
15936
|
+
async getComments(issue) {
|
|
15937
|
+
return this.#json("GET", ["api", "v1", "issues", await this.#resolveIssue(issue), "comments"]);
|
|
15938
15938
|
}
|
|
15939
15939
|
async getIssueReferences(issue) {
|
|
15940
15940
|
return this.#json("GET", [
|
|
@@ -18040,22 +18040,64 @@ function messageSummary({ message, replies }, graph) {
|
|
|
18040
18040
|
].join(`
|
|
18041
18041
|
`);
|
|
18042
18042
|
}
|
|
18043
|
-
async function
|
|
18043
|
+
async function openAnchoredThreads(client, resolved) {
|
|
18044
18044
|
const asksPromise = resolved.owner.kind === "project" ? client.getArtifactAsks(resolved.artifact.id) : Promise.resolve(resolved.issue?.open_asks ?? []);
|
|
18045
|
-
const commentsPromise = resolved.owner.kind === "project" ? client.getArtifactComments(resolved.artifact.id) : client.getComments(resolved.issue?.key ?? ""
|
|
18045
|
+
const commentsPromise = resolved.owner.kind === "project" ? client.getArtifactComments(resolved.artifact.id) : client.getComments(resolved.issue?.key ?? "");
|
|
18046
18046
|
const commentsResultPromise = commentsPromise.then((value) => ({ status: "fulfilled", value }), (reason) => ({ status: "rejected", reason }));
|
|
18047
|
-
const asks = await asksPromise;
|
|
18048
|
-
const marks = asks.filter((ask) => ask.state === "open" && ask.anchor?.artifact_id === resolved.artifact.id).map((ask) => `ask ${ask.id}`);
|
|
18047
|
+
const asks = (await asksPromise).filter((ask) => ask.state === "open" && ask.anchor?.artifact_id === resolved.artifact.id);
|
|
18049
18048
|
const commentsResult = await commentsResultPromise;
|
|
18050
|
-
if (commentsResult.status === "rejected") {
|
|
18051
|
-
if (dispatchAnswered(commentsResult.reason, 404))
|
|
18052
|
-
return marks;
|
|
18049
|
+
if (commentsResult.status === "rejected" && !dispatchAnswered(commentsResult.reason, 404)) {
|
|
18053
18050
|
throw commentsResult.reason;
|
|
18054
18051
|
}
|
|
18055
|
-
|
|
18056
|
-
|
|
18057
|
-
|
|
18058
|
-
|
|
18052
|
+
const comments = commentsResult.status === "fulfilled" ? commentsResult.value : [];
|
|
18053
|
+
const askReplies = new Map(asks.map((ask) => [ask.id, []]));
|
|
18054
|
+
for (const comment of comments) {
|
|
18055
|
+
if (comment.ask_id)
|
|
18056
|
+
askReplies.get(comment.ask_id)?.push(comment);
|
|
18057
|
+
}
|
|
18058
|
+
const askThreads = asks.map((ask) => [
|
|
18059
|
+
`ask ${ask.id} \xB7 ${actorText(ask.author)} \xB7 ${ask.created_at}`,
|
|
18060
|
+
...anchorLines(ask),
|
|
18061
|
+
`Question: ${ask.question}`,
|
|
18062
|
+
...threadReplyLines(askReplies.get(ask.id) ?? [])
|
|
18063
|
+
].join(`
|
|
18064
|
+
`));
|
|
18065
|
+
const byId = new Map(comments.map((comment) => [comment.id, comment]));
|
|
18066
|
+
const roots = comments.filter((comment) => comment.reply_to === null && !comment.ask_id && !comment.resolved && comment.anchor?.artifact_id === resolved.artifact.id);
|
|
18067
|
+
const replies = new Map(roots.map((root) => [root.id, []]));
|
|
18068
|
+
for (const comment of comments) {
|
|
18069
|
+
const root = comment.reply_to === null ? undefined : threadRootId(comment, byId);
|
|
18070
|
+
if (root !== undefined)
|
|
18071
|
+
replies.get(root)?.push(comment);
|
|
18072
|
+
}
|
|
18073
|
+
const commentThreads = roots.map((root) => [
|
|
18074
|
+
`comment ${root.id} \xB7 ${actorText(root.author)} \xB7 ${root.created_at}`,
|
|
18075
|
+
...anchorLines(root),
|
|
18076
|
+
`Body: ${root.body}`,
|
|
18077
|
+
...threadReplyLines(replies.get(root.id) ?? [])
|
|
18078
|
+
].join(`
|
|
18079
|
+
`));
|
|
18080
|
+
return [...askThreads, ...commentThreads];
|
|
18081
|
+
}
|
|
18082
|
+
function threadReplyLines(replies) {
|
|
18083
|
+
return replies.flatMap((reply) => [
|
|
18084
|
+
`reply ${reply.id} \xB7 ${actorText(reply.author)} \xB7 ${reply.created_at}`,
|
|
18085
|
+
`Body: ${reply.body}`
|
|
18086
|
+
]);
|
|
18087
|
+
}
|
|
18088
|
+
function threadRootId(comment, byId) {
|
|
18089
|
+
const seen = new Set;
|
|
18090
|
+
let current = comment;
|
|
18091
|
+
while (current.reply_to !== null) {
|
|
18092
|
+
if (seen.has(current.id))
|
|
18093
|
+
return;
|
|
18094
|
+
seen.add(current.id);
|
|
18095
|
+
const parent = byId.get(current.reply_to);
|
|
18096
|
+
if (parent === undefined)
|
|
18097
|
+
return;
|
|
18098
|
+
current = parent;
|
|
18099
|
+
}
|
|
18100
|
+
return current.id;
|
|
18059
18101
|
}
|
|
18060
18102
|
async function blockAsks(client, resolved, state) {
|
|
18061
18103
|
const asks = await (resolved.issue === undefined ? client.getArtifactAsks(resolved.artifact.id, state) : client.listIssueAsks(resolved.issue.key, state));
|
|
@@ -19020,24 +19062,27 @@ Document token: ${listed.token}`,
|
|
|
19020
19062
|
} : { issue: resolved.issue?.key }, version, resolved.owner.kind === "project" ? resolved.owner.project : resolved.owner.issue, shown);
|
|
19021
19063
|
}
|
|
19022
19064
|
const documentPromise = client.docRead(resolved.artifact.id, version);
|
|
19023
|
-
const
|
|
19024
|
-
const
|
|
19065
|
+
const threadsPromise = openAnchoredThreads(client, resolved);
|
|
19066
|
+
const threadsResultPromise = threadsPromise.then((value) => ({ status: "fulfilled", value }), (reason) => ({ status: "rejected", reason }));
|
|
19025
19067
|
const document = await documentPromise;
|
|
19026
|
-
const
|
|
19027
|
-
if (
|
|
19028
|
-
throw
|
|
19029
|
-
const
|
|
19068
|
+
const threadsResult = await threadsResultPromise;
|
|
19069
|
+
if (threadsResult.status === "rejected")
|
|
19070
|
+
throw threadsResult.reason;
|
|
19071
|
+
const threads = threadsResult.value;
|
|
19030
19072
|
const approval = approvalLine(resolved.artifact);
|
|
19031
19073
|
const trailer = [
|
|
19032
19074
|
..."token" in document && document.token !== undefined ? [`Document token: ${document.token}`] : [],
|
|
19033
|
-
...marks.length === 0 ? [] : [`Open anchored asks/comments: ${marks.join(", ")}`],
|
|
19034
19075
|
...approval === undefined ? [] : [approval]
|
|
19035
19076
|
];
|
|
19036
19077
|
return {
|
|
19037
|
-
text:
|
|
19078
|
+
text: [
|
|
19079
|
+
document.markdown,
|
|
19080
|
+
...trailer.length === 0 ? [] : [trailer.join(`
|
|
19081
|
+
`)],
|
|
19082
|
+
...threads.length === 0 ? [] : ["Open anchored threads:", ...threads]
|
|
19083
|
+
].join(`
|
|
19038
19084
|
|
|
19039
|
-
|
|
19040
|
-
`)}`,
|
|
19085
|
+
`),
|
|
19041
19086
|
details: resolved.owner.kind === "project" ? {
|
|
19042
19087
|
project: resolved.artifact.project,
|
|
19043
19088
|
document: `${resolved.artifact.project}/${resolved.artifact.slug}`
|
|
@@ -20191,7 +20236,9 @@ var SessionWireSchema = object({
|
|
|
20191
20236
|
roles: array(string2()).optional(),
|
|
20192
20237
|
capabilities: array(string2()).optional(),
|
|
20193
20238
|
self_subscribed: boolean2(),
|
|
20194
|
-
last_seen: number2().int().optional()
|
|
20239
|
+
last_seen: number2().int().optional(),
|
|
20240
|
+
plugin: string2().optional(),
|
|
20241
|
+
plugin_version: string2().optional()
|
|
20195
20242
|
});
|
|
20196
20243
|
var RoleWireSchema = object({
|
|
20197
20244
|
role: string2(),
|
|
@@ -20327,7 +20374,9 @@ function createEnvoyClient(config) {
|
|
|
20327
20374
|
...input.capabilities === undefined ? {} : { capabilities: input.capabilities },
|
|
20328
20375
|
driving: input.driving,
|
|
20329
20376
|
...input.selfSubscribed === undefined ? {} : { self_subscribed: input.selfSubscribed },
|
|
20330
|
-
host: machineID()
|
|
20377
|
+
host: machineID(),
|
|
20378
|
+
plugin: input.plugin.name,
|
|
20379
|
+
plugin_version: input.plugin.version
|
|
20331
20380
|
}))),
|
|
20332
20381
|
unsubscribe: async (input) => {
|
|
20333
20382
|
await post("/v1/interests/unsubscribe", {
|
package/dist/src/server.js
CHANGED
|
@@ -14192,7 +14192,7 @@ var dispatchToolSpecs = [
|
|
|
14192
14192
|
{
|
|
14193
14193
|
name: "dispatch_doc_read",
|
|
14194
14194
|
example: { issue: "DSP-1" },
|
|
14195
|
-
description: "Read a live document or a named document version, or the text of an uploaded file at its latest or named version. " + "Do not use it for issue status, asks, or events; " + "use dispatch read instead. Supply ref, issue, or project plus artifact; issue plus an omitted artifact reads the primary document. " + "A live read returns its document token for an optional dispatch doc-edit precondition. With blocks it lists the live document's blocks instead of its markdown, in document order: each block's id, type, token, anchored comments and asks, and opening words, and under a table each row by the index delete_row takes and each cell by its row and the column delete_column takes; block ids, block tokens and those indexes are what dispatch doc-edit takes. " + "A picture (an uploaded PNG, JPEG, GIF or WebP of at most 3,750,000 bytes, 5 MB once base64-encoded) comes back as an image you see, with its name, type, size and version, every time you ask, including one a read already showed this session; " + "any other file that is not UTF-8 text is described, with the route that serves its bytes. " + OWNER_REFERENCE,
|
|
14195
|
+
description: "Read a live document or a named document version, or the text of an uploaded file at its latest or named version. " + "Do not use it for issue status, asks, or events; " + "use dispatch read instead. Supply ref, issue, or project plus artifact; issue plus an omitted artifact reads the primary document. " + "A live read returns its document token for an optional dispatch doc-edit precondition. With blocks it lists the live document's blocks instead of its markdown, in document order: each block's id, type, token, anchored comments and asks, and opening words, and under a table each row by the index delete_row takes and each cell by its row and the column delete_column takes; block ids, block tokens and those indexes are what dispatch doc-edit takes. " + "After the markdown it prints every open thread anchored on the document in full: an open ask with its id and question and each reply's author, time and text, and a comment thread with its root's id, author, quote and text and each reply's author, time and text, in order; a resolved thread, and an ask that is answered or resolved, is not printed. " + "A picture (an uploaded PNG, JPEG, GIF or WebP of at most 3,750,000 bytes, 5 MB once base64-encoded) comes back as an image you see, with its name, type, size and version, every time you ask, including one a read already showed this session; " + "any other file that is not UTF-8 text is described, with the route that serves its bytes. " + OWNER_REFERENCE,
|
|
14196
14196
|
arguments: (z) => ({
|
|
14197
14197
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
14198
14198
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
@@ -15342,7 +15342,9 @@ var SessionWireSchema = object({
|
|
|
15342
15342
|
roles: array(string2()).optional(),
|
|
15343
15343
|
capabilities: array(string2()).optional(),
|
|
15344
15344
|
self_subscribed: boolean2(),
|
|
15345
|
-
last_seen: number2().int().optional()
|
|
15345
|
+
last_seen: number2().int().optional(),
|
|
15346
|
+
plugin: string2().optional(),
|
|
15347
|
+
plugin_version: string2().optional()
|
|
15346
15348
|
});
|
|
15347
15349
|
var RoleWireSchema = object({
|
|
15348
15350
|
role: string2(),
|
|
@@ -15478,7 +15480,9 @@ function createEnvoyClient(config) {
|
|
|
15478
15480
|
...input.capabilities === undefined ? {} : { capabilities: input.capabilities },
|
|
15479
15481
|
driving: input.driving,
|
|
15480
15482
|
...input.selfSubscribed === undefined ? {} : { self_subscribed: input.selfSubscribed },
|
|
15481
|
-
host: machineID()
|
|
15483
|
+
host: machineID(),
|
|
15484
|
+
plugin: input.plugin.name,
|
|
15485
|
+
plugin_version: input.plugin.version
|
|
15482
15486
|
}))),
|
|
15483
15487
|
unsubscribe: async (input) => {
|
|
15484
15488
|
await post("/v1/interests/unsubscribe", {
|
|
@@ -15581,6 +15585,8 @@ function sourceSession(sessionID) {
|
|
|
15581
15585
|
|
|
15582
15586
|
// src/server.ts
|
|
15583
15587
|
import { tool } from "@opencode-ai/plugin/tool";
|
|
15588
|
+
// package.json
|
|
15589
|
+
var version2 = "9.8.1";
|
|
15584
15590
|
|
|
15585
15591
|
// src/log.ts
|
|
15586
15592
|
import { appendFile, mkdir } from "fs/promises";
|
|
@@ -15671,6 +15677,7 @@ var skillsDirectory = [
|
|
|
15671
15677
|
path3.resolve(moduleDirectory, "../../../skills")
|
|
15672
15678
|
].find((dir) => existsSync2(dir));
|
|
15673
15679
|
var PACKAGE_NAME = "@sjawhar/opencode-legion-envoy";
|
|
15680
|
+
var PLUGIN = { name: PACKAGE_NAME, version: version2 };
|
|
15674
15681
|
function packageRoot(from) {
|
|
15675
15682
|
for (let directory = from;; directory = path3.dirname(directory)) {
|
|
15676
15683
|
if (manifestName(path3.join(directory, "package.json")) === PACKAGE_NAME)
|
|
@@ -15716,7 +15723,8 @@ function envoyTools(client, port, title) {
|
|
|
15716
15723
|
topics: args.topics,
|
|
15717
15724
|
port: port() ?? 0,
|
|
15718
15725
|
title: title() ?? "",
|
|
15719
|
-
driving: true
|
|
15726
|
+
driving: true,
|
|
15727
|
+
plugin: PLUGIN
|
|
15720
15728
|
}));
|
|
15721
15729
|
}
|
|
15722
15730
|
}),
|
|
@@ -15879,7 +15887,8 @@ var server_default = async (input) => {
|
|
|
15879
15887
|
topics: [agentSubject(sessionID)],
|
|
15880
15888
|
port,
|
|
15881
15889
|
title: title ?? "",
|
|
15882
|
-
driving
|
|
15890
|
+
driving,
|
|
15891
|
+
plugin: PLUGIN
|
|
15883
15892
|
}).catch(() => {});
|
|
15884
15893
|
let stopEnvoy = () => {};
|
|
15885
15894
|
if (envoyOn !== undefined) {
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@ except a clear defect a role reports ([Issues handed to Legion](#issues-handed-t
|
|
|
12
12
|
|
|
13
13
|
## Rules
|
|
14
14
|
|
|
15
|
-
- Handle no wake until the extension's startup
|
|
15
|
+
- Handle no wake until the extension has registered this session with the daemon as the project's controller, at session startup or, in a controller an operator started, from its first command once Oh My Pi has started, because without that registration the daemon does not know you as its controller.
|
|
16
16
|
- Answer a person's direct message first, in the conversation. A plain user turn that is neither the start message nor a task sent with `legion claims deliver` is a person writing from Dispatch's Agents page.
|
|
17
17
|
- A direct Dispatch message that decides scope, priority or an owner is a ruling: after you answer it, run the weekly-plan reconciliation (`skill://legion-controller/references/backlog-stewardship.md`), because the plan must record the rule.
|
|
18
18
|
- Handle one wake per turn, then end the turn. Never poll or wait for an event, because the daemon wakes you again (`tick` at least every `controller_wake_interval_seconds`).
|
|
@@ -83,8 +83,8 @@ environment, then run:
|
|
|
83
83
|
It checks `LEGION_PROJECT` against the daemon, registers the session, claims the Envoy role, and
|
|
84
84
|
moves the daemon's recorded controller session id to this session; the `legion` tool's controller
|
|
85
85
|
operations then work there. Never pass the secret as a command argument or copy it into a
|
|
86
|
-
transcript, because others read transcripts. Do not set `LEGION_CONTROLLER=1
|
|
87
|
-
|
|
86
|
+
transcript, because others read transcripts. Do not set `LEGION_CONTROLLER=1`: that marker makes
|
|
87
|
+
the session the launched controller, which needs a start message. Run `/legion-claim-controller`
|
|
88
88
|
once per session; do not run it again after an Envoy listener restart, because the heartbeat
|
|
89
89
|
re-claims the role.
|
|
90
90
|
|
|
@@ -53,10 +53,20 @@ it, and any other change to the head voids it.
|
|
|
53
53
|
push's runs and read the CI head again). GitHub's compare lists at most 300 files for the whole
|
|
54
54
|
comparison, so `files` at 300 is a comparison GitHub cut at its cap and `handoffsOnly` decides
|
|
55
55
|
nothing: tell the architect and do not approve. A required check
|
|
56
|
-
`queued` or `in_progress`: wait. One `completed` as
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
`queued` or `in_progress`: wait. One `completed` as `cancelled`, or absent: re-run that run's
|
|
57
|
+
failed and cancelled jobs, once, then wait — never the whole run, which runs again every job that
|
|
58
|
+
succeeded too. Find the run and job at the CI head: the head's runs
|
|
59
|
+
(`gh api 'repos/<o>/<r>/actions/runs?head_sha=<ci head>&per_page=100' --jq '.workflow_runs[] | [.id, .name, .event, .status, .conclusion] | @tsv'`),
|
|
60
|
+
then each candidate run's jobs
|
|
61
|
+
(`gh api repos/<o>/<r>/actions/runs/<run-id>/jobs --jq '.jobs[] | [.id, .name, .status, .conclusion] | @tsv'`).
|
|
62
|
+
A cancelled job: `gh run rerun <run-id> --failed`, which GitHub applies to the run's failed and
|
|
63
|
+
cancelled jobs and the jobs that depend on them, and to nothing that succeeded. Never
|
|
64
|
+
`--job <job-id>` alone: under a routing workflow, re-running only the final job reads the
|
|
65
|
+
cancelled results again and stays red. GitHub refuses a re-run while an attempt of that run is
|
|
66
|
+
still in progress: wait for it. When no
|
|
67
|
+
run at the CI head holds the job, or nothing will run it (a check only a commit status reports, a
|
|
68
|
+
workflow another repository defines), tell the architect and do not approve. `gh pr checks <n>`
|
|
69
|
+
is not the read: it reads only the current head, which
|
|
60
70
|
at a handoff head shows only the `pr-title` runs the review events start (measured on
|
|
61
71
|
sjawhar/legion#1944 at 0220b94fc2 on 2026-10-14).
|
|
62
72
|
Approval is refused while either `E2E (implementer)` or `E2E (tester)` is missing: `REQUEST_CHANGES` naming the missing line.
|
package/src/server.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from "@legion/envoy-client/tool-contract";
|
|
13
13
|
import { createEnvoyClient, type EnvoyClient } from "@legion/envoy-client/transport";
|
|
14
14
|
import { type ToolDefinition, tool } from "@opencode-ai/plugin/tool";
|
|
15
|
+
import { version } from "../package.json" with { type: "json" };
|
|
15
16
|
import { logger } from "./log";
|
|
16
17
|
import { resolvePort } from "./port";
|
|
17
18
|
|
|
@@ -29,6 +30,9 @@ const skillsDirectory = [
|
|
|
29
30
|
|
|
30
31
|
const PACKAGE_NAME = "@sjawhar/opencode-legion-envoy";
|
|
31
32
|
|
|
33
|
+
/** The plugin every registration names: this package and the version its manifest carries. */
|
|
34
|
+
const PLUGIN = { name: PACKAGE_NAME, version };
|
|
35
|
+
|
|
32
36
|
/** The package root: the nearest directory above `from` whose package.json names this package.
|
|
33
37
|
* The packed server.js sits in dist/src/, the repo's server.ts in src/. A manifest on the way up
|
|
34
38
|
* that is missing, unreadable or not JSON is passed over. */
|
|
@@ -93,6 +97,7 @@ function envoyTools(
|
|
|
93
97
|
port: port() ?? 0,
|
|
94
98
|
title: title() ?? "",
|
|
95
99
|
driving: true,
|
|
100
|
+
plugin: PLUGIN,
|
|
96
101
|
})
|
|
97
102
|
);
|
|
98
103
|
},
|
|
@@ -307,6 +312,7 @@ export default async (input: { serverUrl: URL }) => {
|
|
|
307
312
|
port,
|
|
308
313
|
title: title ?? "",
|
|
309
314
|
driving,
|
|
315
|
+
plugin: PLUGIN,
|
|
310
316
|
})
|
|
311
317
|
.catch(() => {});
|
|
312
318
|
|