@sjawhar/opencode-legion-envoy 1.44.0 → 1.45.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/src/server.js +107 -17
- package/package.json +1 -1
- package/skills/dispatch/SKILL.md +3 -1
package/dist/src/server.js
CHANGED
|
@@ -15436,6 +15436,36 @@ function notSubscribed(owner) {
|
|
|
15436
15436
|
function followsAsk(owner) {
|
|
15437
15437
|
return `You follow this ask: its answer and replies reach you directly. For every event on ${owner.label}: envoy_subscribe ${owner.topic}`;
|
|
15438
15438
|
}
|
|
15439
|
+
var triageAdviceShown = new Set;
|
|
15440
|
+
function renderAdvice(tool, key, advice, opts) {
|
|
15441
|
+
if (advice === undefined)
|
|
15442
|
+
return [];
|
|
15443
|
+
const hasIssueAdvice = advice.issue_status !== undefined;
|
|
15444
|
+
const openAsks = advice.your_open_asks;
|
|
15445
|
+
const writesSinceHuman = advice.session_writes_since_human;
|
|
15446
|
+
const lines = [];
|
|
15447
|
+
if (advice.decision_blocks === 0 && opts.isPrimarySpec === true && (tool === "dispatch_issue" || tool === "dispatch_artifact")) {
|
|
15448
|
+
lines.push('No decision blocks in this spec \u2014 nothing here reaches a human\'s inbox. Want human feedback? See the `dispatch` skill, "Decision blocks".');
|
|
15449
|
+
}
|
|
15450
|
+
if (hasIssueAdvice && writesSinceHuman !== undefined && writesSinceHuman >= 3 && (tool === "dispatch_message" || tool === "dispatch_ask" || tool === "dispatch_comment" && opts.isAskReply !== true)) {
|
|
15451
|
+
const middle = writesSinceHuman >= 6 ? "Stop posting here until a human replies." : "Progress ledger or scratchpad? If so, stop.";
|
|
15452
|
+
lines.push(`You've sent ${writesSinceHuman} messages on ${key} with no human response. ${middle} See the \`dispatch\` skill, "Structure over stream".`);
|
|
15453
|
+
}
|
|
15454
|
+
if (advice.issue_status === "triage" && tool !== "dispatch_issue" && !(tool === "dispatch_issue_update" && opts.setsStatus === true) && !triageAdviceShown.has(key)) {
|
|
15455
|
+
triageAdviceShown.add(key);
|
|
15456
|
+
lines.push(`${key} is still in triage \u2014 nobody can see its development status. See the \`dispatch\` skill, "Issue status is yours to move".`);
|
|
15457
|
+
}
|
|
15458
|
+
if (hasIssueAdvice && openAsks !== undefined && openAsks.length > 0 && (tool === "dispatch_message" || tool === "dispatch_doc_edit" || tool === "dispatch_issue_update" || tool === "dispatch_comment" && opts.replyToOwnAsk !== true)) {
|
|
15459
|
+
const askCount = Math.min(openAsks.length, 2);
|
|
15460
|
+
for (let index = 0;index < askCount; index += 1) {
|
|
15461
|
+
const ask = openAsks[index];
|
|
15462
|
+
if (ask === undefined)
|
|
15463
|
+
break;
|
|
15464
|
+
lines.push(`You still have an open ask on ${key}: "${ask.question.slice(0, 80)}" (${ask.id}). Still needed? See the \`dispatch\` skill, "Close what you opened".`);
|
|
15465
|
+
}
|
|
15466
|
+
}
|
|
15467
|
+
return lines;
|
|
15468
|
+
}
|
|
15439
15469
|
function documentResultDetails(artifact) {
|
|
15440
15470
|
return {
|
|
15441
15471
|
project: artifact.project,
|
|
@@ -16324,9 +16354,19 @@ async function executeDispatchTool(input) {
|
|
|
16324
16354
|
...Array.isArray(labels) ? { labels } : {},
|
|
16325
16355
|
actor
|
|
16326
16356
|
});
|
|
16357
|
+
const adviceLines = renderAdvice(input.tool, created.key, created.advice, {
|
|
16358
|
+
isPrimarySpec: spec !== undefined
|
|
16359
|
+
});
|
|
16327
16360
|
return {
|
|
16328
|
-
text:
|
|
16329
|
-
|
|
16361
|
+
text: [
|
|
16362
|
+
`Created ${created.key}: ${created.title} ${notSubscribed(issueTopic(created.key))}`,
|
|
16363
|
+
...adviceLines
|
|
16364
|
+
].join(`
|
|
16365
|
+
`),
|
|
16366
|
+
details: {
|
|
16367
|
+
issue: created.key,
|
|
16368
|
+
...created.advice === undefined ? {} : { advice: created.advice }
|
|
16369
|
+
}
|
|
16330
16370
|
};
|
|
16331
16371
|
} catch (error) {
|
|
16332
16372
|
if (!(error instanceof DispatchServiceError) || error.code !== "POSSIBLE_DUPLICATE") {
|
|
@@ -16383,12 +16423,20 @@ async function executeDispatchTool(input) {
|
|
|
16383
16423
|
...parent === undefined ? [] : [after.parent === null ? "parent cleared" : `parent -> ${after.parent}`],
|
|
16384
16424
|
...components === undefined ? [] : [componentsChange(components, after.components)]
|
|
16385
16425
|
];
|
|
16426
|
+
const adviceLines = renderAdvice(input.tool, after.key, after.advice, {
|
|
16427
|
+
setsStatus: status !== undefined
|
|
16428
|
+
});
|
|
16386
16429
|
return {
|
|
16387
|
-
text:
|
|
16430
|
+
text: [
|
|
16431
|
+
`${after.key}: ${changes.join("; ")} ${notSubscribed(issueTopic(after.key))}`,
|
|
16432
|
+
...adviceLines
|
|
16433
|
+
].join(`
|
|
16434
|
+
`),
|
|
16388
16435
|
details: {
|
|
16389
16436
|
issue: after.key,
|
|
16390
16437
|
status: after.status,
|
|
16391
|
-
external_links: after.external_links.map((link) => link.url)
|
|
16438
|
+
external_links: after.external_links.map((link) => link.url),
|
|
16439
|
+
...after.advice === undefined ? {} : { advice: after.advice }
|
|
16392
16440
|
}
|
|
16393
16441
|
};
|
|
16394
16442
|
} catch (error) {
|
|
@@ -16519,10 +16567,18 @@ async function executeDispatchTool(input) {
|
|
|
16519
16567
|
};
|
|
16520
16568
|
const ask = resolved?.owner.kind === "project" ? await client.artifactAsk(resolved.artifact.id, askInput) : await client.ask(issue(), askInput);
|
|
16521
16569
|
const askOwner = ask.issue_key !== null ? issueTopic(ask.issue_key) : resolved === undefined ? issueTopic(issue()) : documentTopic(resolved.artifact);
|
|
16570
|
+
const adviceLines = renderAdvice(input.tool, askOwner.label, ask.advice, {});
|
|
16522
16571
|
return {
|
|
16523
|
-
text:
|
|
16572
|
+
text: [
|
|
16573
|
+
`Asked ${ask.id} on ${askOwner.label} (urgency ${ask.urgency}): ${ask.question}
|
|
16524
16574
|
${followsAsk(askOwner)}`,
|
|
16525
|
-
|
|
16575
|
+
...adviceLines
|
|
16576
|
+
].join(`
|
|
16577
|
+
`),
|
|
16578
|
+
details: {
|
|
16579
|
+
...await followedAskDetails(client, ask, resolved?.artifact),
|
|
16580
|
+
...ask.advice === undefined ? {} : { advice: ask.advice }
|
|
16581
|
+
}
|
|
16526
16582
|
};
|
|
16527
16583
|
}
|
|
16528
16584
|
case "dispatch_edit_ask": {
|
|
@@ -16567,21 +16623,34 @@ ${followsAsk(askOwner)}`,
|
|
|
16567
16623
|
const comment = resolved?.owner.kind === "project" ? await client.artifactComment(resolved.artifact.id, commentInput) : await client.comment(issue(), commentInput);
|
|
16568
16624
|
const commentOwner = resolved === undefined ? issueTopic(issue()) : resolvedTopic(resolved);
|
|
16569
16625
|
const commentDetails = resolved === undefined ? { issue: comment.issue_key, comment: comment.id } : writeResultDetails(resolved, { comment: comment.id });
|
|
16626
|
+
const adviceLines = renderAdvice(input.tool, commentOwner.label, comment.advice, {
|
|
16627
|
+
isAskReply: replyToAsk !== undefined,
|
|
16628
|
+
replyToOwnAsk: replyToAsk !== undefined && (comment.advice?.your_open_asks?.some((ask) => ask.id === replyToAsk) ?? false)
|
|
16629
|
+
});
|
|
16570
16630
|
if (replyToAsk !== undefined) {
|
|
16571
16631
|
const askState = comment.turn === null ? "" : `; ask now waiting on ${comment.turn}`;
|
|
16572
16632
|
return {
|
|
16573
|
-
text:
|
|
16633
|
+
text: [
|
|
16634
|
+
`Replied on ask ${replyToAsk} (comment ${comment.id}${askState}). ${followsAsk(commentOwner)}`,
|
|
16635
|
+
...adviceLines
|
|
16636
|
+
].join(`
|
|
16637
|
+
`),
|
|
16574
16638
|
details: {
|
|
16575
16639
|
...commentDetails,
|
|
16576
16640
|
ask: replyToAsk,
|
|
16577
16641
|
follows: { ask: replyToAsk },
|
|
16578
|
-
...comment.turn === null ? {} : { ask_waiting_on: comment.turn }
|
|
16642
|
+
...comment.turn === null ? {} : { ask_waiting_on: comment.turn },
|
|
16643
|
+
...comment.advice === undefined ? {} : { advice: comment.advice }
|
|
16579
16644
|
}
|
|
16580
16645
|
};
|
|
16581
16646
|
}
|
|
16582
16647
|
return {
|
|
16583
|
-
text: `Posted comment ${comment.id} ${notSubscribed(commentOwner)}`,
|
|
16584
|
-
|
|
16648
|
+
text: [`Posted comment ${comment.id} ${notSubscribed(commentOwner)}`, ...adviceLines].join(`
|
|
16649
|
+
`),
|
|
16650
|
+
details: {
|
|
16651
|
+
...commentDetails,
|
|
16652
|
+
...comment.advice === undefined ? {} : { advice: comment.advice }
|
|
16653
|
+
}
|
|
16585
16654
|
};
|
|
16586
16655
|
}
|
|
16587
16656
|
case "dispatch_suggest": {
|
|
@@ -16611,9 +16680,18 @@ ${followsAsk(askOwner)}`,
|
|
|
16611
16680
|
actor
|
|
16612
16681
|
});
|
|
16613
16682
|
const messageRef = dispatchChildRef(dispatchIssueRef(issueKey), "message", message.id);
|
|
16683
|
+
const adviceLines = renderAdvice(input.tool, issueKey, message.advice, {});
|
|
16614
16684
|
return {
|
|
16615
|
-
text:
|
|
16616
|
-
|
|
16685
|
+
text: [
|
|
16686
|
+
`Posted message ${message.id} (${messageRef}) ${notSubscribed(issueTopic(issueKey))}`,
|
|
16687
|
+
...adviceLines
|
|
16688
|
+
].join(`
|
|
16689
|
+
`),
|
|
16690
|
+
details: {
|
|
16691
|
+
issue: issueKey,
|
|
16692
|
+
message: message.id,
|
|
16693
|
+
...message.advice === undefined ? {} : { advice: message.advice }
|
|
16694
|
+
}
|
|
16617
16695
|
};
|
|
16618
16696
|
}
|
|
16619
16697
|
case "dispatch_doc_edit": {
|
|
@@ -16631,11 +16709,14 @@ ${followsAsk(askOwner)}`,
|
|
|
16631
16709
|
const retyped = ops.filter((operation) => operation.op === "retype").length;
|
|
16632
16710
|
const versionText = edited.version === null ? "no new version" : `version ${edited.version.number}`;
|
|
16633
16711
|
const applied = retyped === 0 ? `Applied ${edited.applied} ops (${versionText})` : `Applied ${edited.applied} ops; retyped ${retyped} block${retyped === 1 ? "" : "s"} (${versionText})`;
|
|
16712
|
+
const adviceLines = renderAdvice(input.tool, resolvedTopic(resolved).label, edited.advice, {});
|
|
16634
16713
|
return {
|
|
16635
|
-
text: `${applied} ${notSubscribed(resolvedTopic(resolved))}`,
|
|
16714
|
+
text: [`${applied} ${notSubscribed(resolvedTopic(resolved))}`, ...adviceLines].join(`
|
|
16715
|
+
`),
|
|
16636
16716
|
details: writeResultDetails(resolved, {
|
|
16637
16717
|
applied: edited.applied,
|
|
16638
|
-
...edited.version === null ? {} : { version: edited.version.number }
|
|
16718
|
+
...edited.version === null ? {} : { version: edited.version.number },
|
|
16719
|
+
...edited.advice === undefined ? {} : { advice: edited.advice }
|
|
16639
16720
|
})
|
|
16640
16721
|
};
|
|
16641
16722
|
}
|
|
@@ -16707,15 +16788,24 @@ ${trailer.join(`
|
|
|
16707
16788
|
const result = artifactOwner.kind === "project" ? await client.projectArtifact(artifactOwner.project, artifactInput) : await client.artifact(issue(), artifactInput);
|
|
16708
16789
|
const artifactRef = dispatchDocumentRef(artifactOwner.kind === "project" ? artifactOwner.project : issue(), result.artifact.slug);
|
|
16709
16790
|
const uploadOwner = artifactOwner.kind === "project" ? documentTopic(result.artifact) : issueTopic(issue());
|
|
16791
|
+
const adviceLines = renderAdvice(input.tool, uploadOwner.label, result.advice, {
|
|
16792
|
+
isPrimarySpec: result.artifact.primary || result.artifact.name === "spec.md"
|
|
16793
|
+
});
|
|
16710
16794
|
return {
|
|
16711
|
-
text:
|
|
16795
|
+
text: [
|
|
16796
|
+
`Uploaded ${result.artifact.name} as version ${result.version.number} (artifact slug ${result.artifact.slug}; ${artifactRef}) ${notSubscribed(uploadOwner)}`,
|
|
16797
|
+
...adviceLines
|
|
16798
|
+
].join(`
|
|
16799
|
+
`),
|
|
16712
16800
|
details: artifactOwner.kind === "project" ? {
|
|
16713
16801
|
...documentResultDetails(result.artifact),
|
|
16714
|
-
version: result.version.number
|
|
16802
|
+
version: result.version.number,
|
|
16803
|
+
...result.advice === undefined ? {} : { advice: result.advice }
|
|
16715
16804
|
} : {
|
|
16716
16805
|
issue: issue(),
|
|
16717
16806
|
artifact: result.artifact.id,
|
|
16718
|
-
version: result.version.number
|
|
16807
|
+
version: result.version.number,
|
|
16808
|
+
...result.advice === undefined ? {} : { advice: result.advice }
|
|
16719
16809
|
}
|
|
16720
16810
|
};
|
|
16721
16811
|
}
|
package/package.json
CHANGED
package/skills/dispatch/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dispatch
|
|
3
|
-
description: "Use when asking Sami a question, updating the spec, commenting on a document, attaching an artifact, or calling a dispatch_* tool."
|
|
3
|
+
description: "Use before posting a message, a status update, or a periodic status update; before asking a question that references another message, artifact, or eval; and when asking Sami a question, updating the spec, commenting on a document, attaching an artifact, or calling a dispatch_* tool."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Dispatch
|
|
@@ -678,6 +678,8 @@ title is invisible to the graph.
|
|
|
678
678
|
|
|
679
679
|
## References
|
|
680
680
|
|
|
681
|
+
**Every reference is a link, never an unlinked mention.** If you name a thing that has an address, link it: another issue, ask, comment, spec, or message (the `dispatch://` forms below), an artifact (`dispatch://KEY/artifact/<slug>`), an eval (its viewer URL), a Slack message (its permalink), a Drive file (its share link). Bare phrases like "see this eval", "his 09-04 run", "the comment above", or "per the spec" with no link are banned: they make the reader hunt for what you already had in hand, and nothing can be traversed from them. Linking every reference is what makes a body both consumable and navigable. If a thing genuinely has no linkable address, say so; otherwise the link is not optional.
|
|
682
|
+
|
|
681
683
|
Use these in document, ask, comment, and message bodies. In the dashboard, a reference renders
|
|
682
684
|
as an inline link whose text is the target's title (an issue's title, an ask's question, a
|
|
683
685
|
comment's first line, a document's name) once it resolves; a body that is only a bare reference
|